YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/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