OpenZGY/C++ API and Internals (ALPHA)
Access seismic data stored in ZGY format.
roundandclip.h
Go to the documentation of this file.
1 // Copyright 2017-2020, Schlumberger
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //Adapted from: Zgy/PlatformLib/RoundAndClip.h and others.
16 #pragma once
17 
18 #include <cstdint>
19 #include <cmath>
20 #include <limits>
21 
38 namespace InternalZGY {
39 #if 0
40 }
41 #endif
42 
48 static inline bool IsFiniteD(double val)
49 {
50  return std::isfinite(val);
51 }
52 
56 template <typename T> inline bool IsFiniteT(T /*value*/)
57 {
58  return true;
59 }
60 
61 template <> inline bool IsFiniteT<float>(float value)
62 {
63  return std::isfinite(value);
64 }
65 
66 template <> inline bool IsFiniteT<double>(double value)
67 {
68  return std::isfinite(value);
69 }
70 
71 template <> inline bool IsFiniteT<long double>(long double value)
72 {
73  return std::isfinite(static_cast<double>(value));
74 }
75 
79 template <typename T> inline bool IsNanT(T /*value*/)
80 {
81  return false;
82 }
83 
84 template <> inline bool IsNanT<float>(float value)
85 {
86  return std::isnan(value);
87 }
88 
89 template <> inline bool IsNanT<double>(double value)
90 {
91  return std::isnan(value);
92 }
93 
94 template <> inline bool IsNanT<long double>(long double value)
95 {
96  return std::isnan(static_cast<double>(value));
97 }
98 
103 static inline std::int32_t RoundD2I(double d)
104 {
105  return d>0 ? (int)(d+0.5) : (int)(d-0.5);
106 }
107 
120 template <typename T>
121 T RoundAndClip(double value)
122 {
123  // Can skip this (and avoid an annoying warning on windows)
124  // if we are sure that all floating types are explicitly
125  // specialized below. Or replace it with an assert.
126  // But an assert could be even worse due to the performance hit.
127  if (!std::numeric_limits<T>::is_integer)
128  return static_cast<T>(value);
129 
130  // Be careful changing this code, it is more subtle than it looks.
131  // If T is a 64-bit integer, this has greater precision than a double.
132  // E.g. for T == unsigned long long and an input value of, say,
133  // 2^64+1 this is clearly outside the valid range (max 2^64-1).
134  // But both those values end up being rounded to 2^64 when assigned
135  // to a double. So if the test used the more intuitive > instead of
136  // >= it would fail. And the assignment at the end would overflow,
137  // resulting in a hardware dependant result. 0x8000000000000000 on
138  // Pentium. NaNs are supposed to fail both tests; in this case I want
139  // the 0x8xx result as a fallback in case the caller didn't remove NaNs.
140 
141  if (value <= (double)std::numeric_limits<T>::min())
142  return std::numeric_limits<T>::min();
143  if (value >= (double)std::numeric_limits<T>::max())
144  return std::numeric_limits<T>::max();
145 
146  // Since C++ by default rounds toward zero, we need special handling.
147  // In the general case we cannot use RoundD2I(), and round() is slow.
148  if (value < 0)
149  return static_cast<T>(value - 0.5);
150  return static_cast<T>(value + 0.5);
151 }
152 
157 template <typename T>
158 T RoundAndClip(double value, T nan)
159 {
160  if (!std::numeric_limits<T>::is_integer)
161  return static_cast<T>(value);
162  else if (IsNanT(value))
163  return nan;
164  else
165  return RoundAndClip<T>(value);
166 }
167 
168 } // namespace
InternalZGY::IsNanT
bool IsNanT(T)
Definition: roundandclip.h:79
InternalZGY::IsFiniteT
bool IsFiniteT(T)
Definition: roundandclip.h:56
InternalZGY
Implementation not visible to clients.
InternalZGY::RoundAndClip
T RoundAndClip(double value, T nan)
Definition: roundandclip.h:158