/Users/deen/code/yugabyte-db/src/yb/gutil/mathlimits.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2005 Google Inc. |
2 | | // |
3 | | // Licensed to the Apache Software Foundation (ASF) under one |
4 | | // or more contributor license agreements. See the NOTICE file |
5 | | // distributed with this work for additional information |
6 | | // regarding copyright ownership. The ASF licenses this file |
7 | | // to you under the Apache License, Version 2.0 (the |
8 | | // "License"); you may not use this file except in compliance |
9 | | // with the License. You may obtain a copy of the License at |
10 | | // |
11 | | // http://www.apache.org/licenses/LICENSE-2.0 |
12 | | // |
13 | | // Unless required by applicable law or agreed to in writing, |
14 | | // software distributed under the License is distributed on an |
15 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
16 | | // KIND, either express or implied. See the License for the |
17 | | // specific language governing permissions and limitations |
18 | | // under the License. |
19 | | // |
20 | | // The following only applies to changes made to this file as part of YugaByte development. |
21 | | // |
22 | | // Portions Copyright (c) YugaByte, Inc. |
23 | | // |
24 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
25 | | // in compliance with the License. You may obtain a copy of the License at |
26 | | // |
27 | | // http://www.apache.org/licenses/LICENSE-2.0 |
28 | | // |
29 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
30 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
31 | | // or implied. See the License for the specific language governing permissions and limitations |
32 | | // under the License. |
33 | | // |
34 | | // --- |
35 | | // |
36 | | // |
37 | | // Useful integer and floating point limits and type traits. |
38 | | // |
39 | | // This partially replaces/duplictes numeric_limits<> from <limits>. |
40 | | // We get a Google-style class that we have a greater control over |
41 | | // and thus can add new features to it or fix whatever happens to be broken in |
42 | | // numeric_limits for the compilers we use. |
43 | | // |
44 | | |
45 | | #ifndef YB_GUTIL_MATHLIMITS_H |
46 | | #define YB_GUTIL_MATHLIMITS_H |
47 | | |
48 | | #include <cfloat> |
49 | | #include <cmath> |
50 | | |
51 | | // ========================================================================= // |
52 | | |
53 | | // Useful integer and floating point limits and type traits. |
54 | | // This is just for the documentation; |
55 | | // real members are defined in our specializations below. |
56 | | template<typename T> struct MathLimits { |
57 | | // Type name. |
58 | | typedef T Type; |
59 | | // Unsigned version of the Type with the same byte size. |
60 | | // Same as Type for floating point and unsigned types. |
61 | | typedef T UnsignedType; |
62 | | // If the type supports negative values. |
63 | | static const bool kIsSigned; |
64 | | // If the type supports only integer values. |
65 | | static const bool kIsInteger; |
66 | | // Magnitude-wise smallest representable positive value. |
67 | | static const Type kPosMin; |
68 | | // Magnitude-wise largest representable positive value. |
69 | | static const Type kPosMax; |
70 | | // Smallest representable value. |
71 | | static const Type kMin; |
72 | | // Largest representable value. |
73 | | static const Type kMax; |
74 | | // Magnitude-wise smallest representable negative value. |
75 | | // Present only if kIsSigned. |
76 | | static const Type kNegMin; |
77 | | // Magnitude-wise largest representable negative value. |
78 | | // Present only if kIsSigned. |
79 | | static const Type kNegMax; |
80 | | // Smallest integer x such that 10^x is representable. |
81 | | static const int kMin10Exp; |
82 | | // Largest integer x such that 10^x is representable. |
83 | | static const int kMax10Exp; |
84 | | // Smallest positive value such that Type(1) + kEpsilon != Type(1) |
85 | | static const Type kEpsilon; |
86 | | // Typical rounding error that is enough to cover |
87 | | // a few simple floating-point operations. |
88 | | // Slightly larger than kEpsilon to account for a few rounding errors. |
89 | | // Is zero if kIsInteger. |
90 | | static const Type kStdError; |
91 | | // Number of decimal digits of mantissa precision. |
92 | | // Present only if !kIsInteger. |
93 | | static const int kPrecisionDigits; |
94 | | // Not a number, i.e. result of 0/0. |
95 | | // Present only if !kIsInteger. |
96 | | static const Type kNaN; |
97 | | // Positive infinity, i.e. result of 1/0. |
98 | | // Present only if !kIsInteger. |
99 | | static const Type kPosInf; |
100 | | // Negative infinity, i.e. result of -1/0. |
101 | | // Present only if !kIsInteger. |
102 | | static const Type kNegInf; |
103 | | |
104 | | // NOTE: Special floating point values behave |
105 | | // in a special (but mathematically-logical) way |
106 | | // in terms of (in)equalty comparison and mathematical operations |
107 | | // -- see out unittest for examples. |
108 | | |
109 | | // Special floating point value testers. |
110 | | // Present in integer types for convenience. |
111 | | static bool IsFinite(const Type x); |
112 | | static bool IsNaN(const Type x); |
113 | | static bool IsInf(const Type x); |
114 | | static bool IsPosInf(const Type x); |
115 | | static bool IsNegInf(const Type x); |
116 | | }; |
117 | | |
118 | | // ========================================================================= // |
119 | | |
120 | | // All #define-s below are simply to refactor the declarations of |
121 | | // MathLimits template specializations. |
122 | | // They are all #undef-ined below. |
123 | | |
124 | | // The hoop-jumping in *_INT_(MAX|MIN) below is so that the compiler does not |
125 | | // get an overflow while computing the constants. |
126 | | |
127 | | #define SIGNED_INT_MAX(Type) \ |
128 | | (((Type(1) << (sizeof(Type)*8 - 2)) - 1) + (Type(1) << (sizeof(Type)*8 - 2))) |
129 | | |
130 | | #define SIGNED_INT_MIN(Type) \ |
131 | | (-(Type(1) << (sizeof(Type)*8 - 2)) - (Type(1) << (sizeof(Type)*8 - 2))) |
132 | | |
133 | | #define UNSIGNED_INT_MAX(Type) \ |
134 | | (((Type(1) << (sizeof(Type)*8 - 1)) - 1) + (Type(1) << (sizeof(Type)*8 - 1))) |
135 | | |
136 | | // Compile-time selected log10-related constants for integer types. |
137 | | #define SIGNED_MAX_10_EXP(Type) \ |
138 | | (sizeof(Type) == 1 ? 2 : ( \ |
139 | | sizeof(Type) == 2 ? 4 : ( \ |
140 | | sizeof(Type) == 4 ? 9 : ( \ |
141 | | sizeof(Type) == 8 ? 18 : -1)))) |
142 | | |
143 | | #define UNSIGNED_MAX_10_EXP(Type) \ |
144 | | (sizeof(Type) == 1 ? 2 : ( \ |
145 | | sizeof(Type) == 2 ? 4 : ( \ |
146 | | sizeof(Type) == 4 ? 9 : ( \ |
147 | | sizeof(Type) == 8 ? 19 : -1)))) |
148 | | |
149 | | #define DECL_INT_LIMIT_FUNCS \ |
150 | 0 | static bool IsFinite(const Type x) { return true; } \ Unexecuted instantiation: MathLimits<signed char>::IsFinite(signed char) Unexecuted instantiation: MathLimits<short>::IsFinite(short) Unexecuted instantiation: MathLimits<int>::IsFinite(int) Unexecuted instantiation: MathLimits<long>::IsFinite(long) Unexecuted instantiation: MathLimits<long long>::IsFinite(long long) Unexecuted instantiation: MathLimits<unsigned char>::IsFinite(unsigned char) Unexecuted instantiation: MathLimits<unsigned short>::IsFinite(unsigned short) Unexecuted instantiation: MathLimits<unsigned int>::IsFinite(unsigned int) Unexecuted instantiation: MathLimits<unsigned long>::IsFinite(unsigned long) Unexecuted instantiation: MathLimits<unsigned long long>::IsFinite(unsigned long long) |
151 | 0 | static bool IsNaN(const Type x) { return false; } \ Unexecuted instantiation: MathLimits<signed char>::IsNaN(signed char) Unexecuted instantiation: MathLimits<short>::IsNaN(short) Unexecuted instantiation: MathLimits<int>::IsNaN(int) Unexecuted instantiation: MathLimits<long>::IsNaN(long) Unexecuted instantiation: MathLimits<long long>::IsNaN(long long) Unexecuted instantiation: MathLimits<unsigned char>::IsNaN(unsigned char) Unexecuted instantiation: MathLimits<unsigned short>::IsNaN(unsigned short) Unexecuted instantiation: MathLimits<unsigned int>::IsNaN(unsigned int) Unexecuted instantiation: MathLimits<unsigned long>::IsNaN(unsigned long) Unexecuted instantiation: MathLimits<unsigned long long>::IsNaN(unsigned long long) |
152 | 0 | static bool IsInf(const Type x) { return false; } \ Unexecuted instantiation: MathLimits<signed char>::IsInf(signed char) Unexecuted instantiation: MathLimits<short>::IsInf(short) Unexecuted instantiation: MathLimits<int>::IsInf(int) Unexecuted instantiation: MathLimits<long>::IsInf(long) Unexecuted instantiation: MathLimits<long long>::IsInf(long long) Unexecuted instantiation: MathLimits<unsigned char>::IsInf(unsigned char) Unexecuted instantiation: MathLimits<unsigned short>::IsInf(unsigned short) Unexecuted instantiation: MathLimits<unsigned int>::IsInf(unsigned int) Unexecuted instantiation: MathLimits<unsigned long>::IsInf(unsigned long) Unexecuted instantiation: MathLimits<unsigned long long>::IsInf(unsigned long long) |
153 | 0 | static bool IsPosInf(const Type x) { return false; } \ Unexecuted instantiation: MathLimits<signed char>::IsPosInf(signed char) Unexecuted instantiation: MathLimits<short>::IsPosInf(short) Unexecuted instantiation: MathLimits<int>::IsPosInf(int) Unexecuted instantiation: MathLimits<long>::IsPosInf(long) Unexecuted instantiation: MathLimits<long long>::IsPosInf(long long) Unexecuted instantiation: MathLimits<unsigned char>::IsPosInf(unsigned char) Unexecuted instantiation: MathLimits<unsigned short>::IsPosInf(unsigned short) Unexecuted instantiation: MathLimits<unsigned int>::IsPosInf(unsigned int) Unexecuted instantiation: MathLimits<unsigned long>::IsPosInf(unsigned long) Unexecuted instantiation: MathLimits<unsigned long long>::IsPosInf(unsigned long long) |
154 | 0 | static bool IsNegInf(const Type x) { return false; } Unexecuted instantiation: MathLimits<signed char>::IsNegInf(signed char) Unexecuted instantiation: MathLimits<short>::IsNegInf(short) Unexecuted instantiation: MathLimits<int>::IsNegInf(int) Unexecuted instantiation: MathLimits<long>::IsNegInf(long) Unexecuted instantiation: MathLimits<long long>::IsNegInf(long long) Unexecuted instantiation: MathLimits<unsigned char>::IsNegInf(unsigned char) Unexecuted instantiation: MathLimits<unsigned short>::IsNegInf(unsigned short) Unexecuted instantiation: MathLimits<unsigned int>::IsNegInf(unsigned int) Unexecuted instantiation: MathLimits<unsigned long>::IsNegInf(unsigned long) Unexecuted instantiation: MathLimits<unsigned long long>::IsNegInf(unsigned long long) |
155 | | |
156 | | #define DECL_SIGNED_INT_LIMITS(IntType, UnsignedIntType) \ |
157 | | template<> \ |
158 | | struct MathLimits<IntType> { \ |
159 | | typedef IntType Type; \ |
160 | | typedef UnsignedIntType UnsignedType; \ |
161 | | static const bool kIsSigned = true; \ |
162 | | static const bool kIsInteger = true; \ |
163 | | static const Type kPosMin = 1; \ |
164 | | static const Type kPosMax = SIGNED_INT_MAX(Type); \ |
165 | | static const Type kMin = SIGNED_INT_MIN(Type); \ |
166 | | static const Type kMax = kPosMax; \ |
167 | | static const Type kNegMin = -1; \ |
168 | | static const Type kNegMax = kMin; \ |
169 | | static const int kMin10Exp = 0; \ |
170 | | static const int kMax10Exp = SIGNED_MAX_10_EXP(Type); \ |
171 | | static const Type kEpsilon = 1; \ |
172 | | static const Type kStdError = 0; \ |
173 | | DECL_INT_LIMIT_FUNCS \ |
174 | | }; |
175 | | |
176 | | #define DECL_UNSIGNED_INT_LIMITS(IntType) \ |
177 | | template<> \ |
178 | | struct MathLimits<IntType> { \ |
179 | | typedef IntType Type; \ |
180 | | typedef IntType UnsignedType; \ |
181 | | static const bool kIsSigned = false; \ |
182 | | static const bool kIsInteger = true; \ |
183 | | static const Type kPosMin = 1; \ |
184 | | static const Type kPosMax = UNSIGNED_INT_MAX(Type); \ |
185 | | static const Type kMin = 0; \ |
186 | | static const Type kMax = kPosMax; \ |
187 | | static const int kMin10Exp = 0; \ |
188 | | static const int kMax10Exp = UNSIGNED_MAX_10_EXP(Type); \ |
189 | | static const Type kEpsilon = 1; \ |
190 | | static const Type kStdError = 0; \ |
191 | | DECL_INT_LIMIT_FUNCS \ |
192 | | }; |
193 | | |
194 | | DECL_SIGNED_INT_LIMITS(signed char, unsigned char) |
195 | | DECL_SIGNED_INT_LIMITS(signed short int, unsigned short int) // NOLINT |
196 | | DECL_SIGNED_INT_LIMITS(signed int, unsigned int) |
197 | | DECL_SIGNED_INT_LIMITS(signed long int, unsigned long int) // NOLINT |
198 | | DECL_SIGNED_INT_LIMITS(signed long long int, unsigned long long int) // NOLINT |
199 | | DECL_UNSIGNED_INT_LIMITS(unsigned char) |
200 | | DECL_UNSIGNED_INT_LIMITS(unsigned short int) // NOLINT |
201 | | DECL_UNSIGNED_INT_LIMITS(unsigned int) |
202 | | DECL_UNSIGNED_INT_LIMITS(unsigned long int) // NOLINT |
203 | | DECL_UNSIGNED_INT_LIMITS(unsigned long long int) // NOLINT |
204 | | |
205 | | #undef DECL_SIGNED_INT_LIMITS |
206 | | #undef DECL_UNSIGNED_INT_LIMITS |
207 | | #undef SIGNED_INT_MAX |
208 | | #undef SIGNED_INT_MIN |
209 | | #undef UNSIGNED_INT_MAX |
210 | | #undef SIGNED_MAX_10_EXP |
211 | | #undef UNSIGNED_MAX_10_EXP |
212 | | #undef DECL_INT_LIMIT_FUNCS |
213 | | |
214 | | // ========================================================================= // |
215 | | #ifdef WIN32 // Lacks built-in isnan() and isinf() |
216 | | #define DECL_FP_LIMIT_FUNCS \ |
217 | | static bool IsFinite(const Type x) { return _finite(x); } \ |
218 | | static bool IsNaN(const Type x) { return _isnan(x); } \ |
219 | | static bool IsInf(const Type x) { return (_fpclass(x) & (_FPCLASS_NINF | _FPCLASS_PINF)) != 0; } \ |
220 | | static bool IsPosInf(const Type x) { return _fpclass(x) == _FPCLASS_PINF; } \ |
221 | | static bool IsNegInf(const Type x) { return _fpclass(x) == _FPCLASS_NINF; } |
222 | | #else |
223 | | #define DECL_FP_LIMIT_FUNCS \ |
224 | 0 | static bool IsFinite(const Type x) { return !std::isinf(x) && !std::isnan(x); } \ Unexecuted instantiation: MathLimits<float>::IsFinite(float) Unexecuted instantiation: MathLimits<double>::IsFinite(double) Unexecuted instantiation: MathLimits<long double>::IsFinite(long double) |
225 | 0 | static bool IsNaN(const Type x) { return std::isnan(x); } \ Unexecuted instantiation: MathLimits<float>::IsNaN(float) Unexecuted instantiation: MathLimits<double>::IsNaN(double) Unexecuted instantiation: MathLimits<long double>::IsNaN(long double) |
226 | 0 | static bool IsInf(const Type x) { return std::isinf(x); } \ Unexecuted instantiation: MathLimits<float>::IsInf(float) Unexecuted instantiation: MathLimits<double>::IsInf(double) Unexecuted instantiation: MathLimits<long double>::IsInf(long double) |
227 | 0 | static bool IsPosInf(const Type x) { return std::isinf(x) && x > 0; } \ Unexecuted instantiation: MathLimits<float>::IsPosInf(float) Unexecuted instantiation: MathLimits<double>::IsPosInf(double) Unexecuted instantiation: MathLimits<long double>::IsPosInf(long double) |
228 | 0 | static bool IsNegInf(const Type x) { return std::isinf(x) && x < 0; } Unexecuted instantiation: MathLimits<float>::IsNegInf(float) Unexecuted instantiation: MathLimits<double>::IsNegInf(double) Unexecuted instantiation: MathLimits<long double>::IsNegInf(long double) |
229 | | #endif |
230 | | |
231 | | // We can't put floating-point constant values in the header here because |
232 | | // such constants are not considered to be primitive-type constants by gcc. |
233 | | // CAVEAT: Hence, they are going to be initialized only during |
234 | | // the global objects construction time. |
235 | | #define DECL_FP_LIMITS(FP_Type, PREFIX) \ |
236 | | template<> \ |
237 | | struct MathLimits<FP_Type> { \ |
238 | | typedef FP_Type Type; \ |
239 | | typedef FP_Type UnsignedType; \ |
240 | | static const bool kIsSigned = true; \ |
241 | | static const bool kIsInteger = false; \ |
242 | | static const Type kPosMin; \ |
243 | | static const Type kPosMax; \ |
244 | | static const Type kMin; \ |
245 | | static const Type kMax; \ |
246 | | static const Type kNegMin; \ |
247 | | static const Type kNegMax; \ |
248 | | static const int kMin10Exp = PREFIX##_MIN_10_EXP; \ |
249 | | static const int kMax10Exp = PREFIX##_MAX_10_EXP; \ |
250 | | static const Type kEpsilon; \ |
251 | | static const Type kStdError; \ |
252 | | static const int kPrecisionDigits = PREFIX##_DIG; \ |
253 | | static const Type kNaN; \ |
254 | | static const Type kPosInf; \ |
255 | | static const Type kNegInf; \ |
256 | | DECL_FP_LIMIT_FUNCS \ |
257 | | }; |
258 | | |
259 | | DECL_FP_LIMITS(float, FLT) |
260 | | DECL_FP_LIMITS(double, DBL) |
261 | | DECL_FP_LIMITS(long double, LDBL) |
262 | | |
263 | | #undef DECL_FP_LIMITS |
264 | | #undef DECL_FP_LIMIT_FUNCS |
265 | | |
266 | | // ========================================================================= // |
267 | | |
268 | | #endif // YB_GUTIL_MATHLIMITS_H |