1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 // All Rights Reserved. 32 // 33 // Author: Maxim Lifantsev 34 // 35 // Useful integer and floating point limits and type traits. 36 // 37 // This partially replaces/duplictes numeric_limits<> from <limits>. 38 // We get a Google-style class that we have a greater control over 39 // and thus can add new features to it or fix whatever happens to be broken in 40 // numeric_limits for the compilers we use. 41 // 42 43 #ifndef UTIL_MATH_MATHLIMITS_H__ 44 #define UTIL_MATH_MATHLIMITS_H__ 45 46 // Note that for Windows we do something different because it does not support 47 // the plain isinf and isnan. 48 #if __cplusplus >= 201103L 49 // GCC 4.9 has a bug that makes isinf and isnan ambigious when both <math.h> 50 // and <cmath> get pulled into the same translation unit. We use the ones in 51 // std:: namespace explicitly for C++11 52 #include <cmath> 53 #define GOOGLE_PROTOBUF_USE_STD_CMATH 54 #elif _GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC 55 // libstdc++ <cmath> header undefines the global macros and put functions in 56 // std:: namespace even before C++11. Use the ones in std:: instead too. 57 #include <cmath> 58 #define GOOGLE_PROTOBUF_USE_STD_CMATH 59 #else 60 #include <math.h> 61 #endif 62 63 #include <string.h> 64 65 #include <cfloat> 66 67 #include <google/protobuf/stubs/common.h> 68 69 #include <google/protobuf/port_def.inc> 70 71 // ========================================================================= // 72 73 // Useful integer and floating point limits and type traits. 74 // This is just for the documentation; 75 // real members are defined in our specializations below. 76 namespace google { 77 namespace protobuf { 78 template<typename T> struct MathLimits { 79 // Type name. 80 typedef T Type; 81 // Unsigned version of the Type with the same byte size. 82 // Same as Type for floating point and unsigned types. 83 typedef T UnsignedType; 84 // If the type supports negative values. 85 static const bool kIsSigned; 86 // If the type supports only integer values. 87 static const bool kIsInteger; 88 // Magnitude-wise smallest representable positive value. 89 static const Type kPosMin; 90 // Magnitude-wise largest representable positive value. 91 static const Type kPosMax; 92 // Smallest representable value. 93 static const Type kMin; 94 // Largest representable value. 95 static const Type kMax; 96 // Magnitude-wise smallest representable negative value. 97 // Present only if kIsSigned. 98 static const Type kNegMin; 99 // Magnitude-wise largest representable negative value. 100 // Present only if kIsSigned. 101 static const Type kNegMax; 102 // Smallest integer x such that 10^x is representable. 103 static const int kMin10Exp; 104 // Largest integer x such that 10^x is representable. 105 static const int kMax10Exp; 106 // Smallest positive value such that Type(1) + kEpsilon != Type(1) 107 static const Type kEpsilon; 108 // Typical rounding error that is enough to cover 109 // a few simple floating-point operations. 110 // Slightly larger than kEpsilon to account for a few rounding errors. 111 // Is zero if kIsInteger. 112 static const Type kStdError; 113 // Number of decimal digits of mantissa precision. 114 // Present only if !kIsInteger. 115 static const int kPrecisionDigits; 116 // Not a number, i.e. result of 0/0. 117 // Present only if !kIsInteger. 118 static const Type kNaN; 119 // Positive infinity, i.e. result of 1/0. 120 // Present only if !kIsInteger. 121 static const Type kPosInf; 122 // Negative infinity, i.e. result of -1/0. 123 // Present only if !kIsInteger. 124 static const Type kNegInf; 125 126 // NOTE: Special floating point values behave 127 // in a special (but mathematically-logical) way 128 // in terms of (in)equalty comparison and mathematical operations 129 // -- see out unittest for examples. 130 131 // Special floating point value testers. 132 // Present in integer types for convenience. 133 static bool IsFinite(const Type x); 134 static bool IsNaN(const Type x); 135 static bool IsInf(const Type x); 136 static bool IsPosInf(const Type x); 137 static bool IsNegInf(const Type x); 138 }; 139 140 // ========================================================================= // 141 142 // All #define-s below are simply to refactor the declarations of 143 // MathLimits template specializations. 144 // They are all #undef-ined below. 145 146 // The hoop-jumping in *_INT_(MAX|MIN) below is so that the compiler does not 147 // get an overflow while computing the constants. 148 149 #define SIGNED_INT_MAX(Type) \ 150 (((Type(1) << (sizeof(Type)*8 - 2)) - 1) + (Type(1) << (sizeof(Type)*8 - 2))) 151 152 #define SIGNED_INT_MIN(Type) \ 153 (-(Type(1) << (sizeof(Type)*8 - 2)) - (Type(1) << (sizeof(Type)*8 - 2))) 154 155 #define UNSIGNED_INT_MAX(Type) \ 156 (((Type(1) << (sizeof(Type)*8 - 1)) - 1) + (Type(1) << (sizeof(Type)*8 - 1))) 157 158 // Compile-time selected log10-related constants for integer types. 159 #define SIGNED_MAX_10_EXP(Type) \ 160 (sizeof(Type) == 1 ? 2 : ( \ 161 sizeof(Type) == 2 ? 4 : ( \ 162 sizeof(Type) == 4 ? 9 : ( \ 163 sizeof(Type) == 8 ? 18 : -1)))) 164 165 #define UNSIGNED_MAX_10_EXP(Type) \ 166 (sizeof(Type) == 1 ? 2 : ( \ 167 sizeof(Type) == 2 ? 4 : ( \ 168 sizeof(Type) == 4 ? 9 : ( \ 169 sizeof(Type) == 8 ? 19 : -1)))) 170 171 #define DECL_INT_LIMIT_FUNCS \ 172 static bool IsFinite(const Type /*x*/) { return true; } \ 173 static bool IsNaN(const Type /*x*/) { return false; } \ 174 static bool IsInf(const Type /*x*/) { return false; } \ 175 static bool IsPosInf(const Type /*x*/) { return false; } \ 176 static bool IsNegInf(const Type /*x*/) { return false; } 177 178 #define DECL_SIGNED_INT_LIMITS(IntType, UnsignedIntType) \ 179 template <> \ 180 struct PROTOBUF_EXPORT MathLimits<IntType> { \ 181 typedef IntType Type; \ 182 typedef UnsignedIntType UnsignedType; \ 183 static const bool kIsSigned = true; \ 184 static const bool kIsInteger = true; \ 185 static const Type kPosMin = 1; \ 186 static const Type kPosMax = SIGNED_INT_MAX(Type); \ 187 static const Type kMin = SIGNED_INT_MIN(Type); \ 188 static const Type kMax = kPosMax; \ 189 static const Type kNegMin = -1; \ 190 static const Type kNegMax = kMin; \ 191 static const int kMin10Exp = 0; \ 192 static const int kMax10Exp = SIGNED_MAX_10_EXP(Type); \ 193 static const Type kEpsilon = 1; \ 194 static const Type kStdError = 0; \ 195 DECL_INT_LIMIT_FUNCS \ 196 }; 197 198 #define DECL_UNSIGNED_INT_LIMITS(IntType) \ 199 template <> \ 200 struct PROTOBUF_EXPORT MathLimits<IntType> { \ 201 typedef IntType Type; \ 202 typedef IntType UnsignedType; \ 203 static const bool kIsSigned = false; \ 204 static const bool kIsInteger = true; \ 205 static const Type kPosMin = 1; \ 206 static const Type kPosMax = UNSIGNED_INT_MAX(Type); \ 207 static const Type kMin = 0; \ 208 static const Type kMax = kPosMax; \ 209 static const int kMin10Exp = 0; \ 210 static const int kMax10Exp = UNSIGNED_MAX_10_EXP(Type); \ 211 static const Type kEpsilon = 1; \ 212 static const Type kStdError = 0; \ 213 DECL_INT_LIMIT_FUNCS \ 214 }; 215 216 DECL_SIGNED_INT_LIMITS(signed char, unsigned char) 217 DECL_SIGNED_INT_LIMITS(signed short int, unsigned short int) 218 DECL_SIGNED_INT_LIMITS(signed int, unsigned int) 219 DECL_SIGNED_INT_LIMITS(signed long int, unsigned long int) 220 DECL_SIGNED_INT_LIMITS(signed long long int, unsigned long long int) 221 DECL_UNSIGNED_INT_LIMITS(unsigned char) 222 DECL_UNSIGNED_INT_LIMITS(unsigned short int) 223 DECL_UNSIGNED_INT_LIMITS(unsigned int) 224 DECL_UNSIGNED_INT_LIMITS(unsigned long int) 225 DECL_UNSIGNED_INT_LIMITS(unsigned long long int) 226 227 #undef DECL_SIGNED_INT_LIMITS 228 #undef DECL_UNSIGNED_INT_LIMITS 229 #undef SIGNED_INT_MAX 230 #undef SIGNED_INT_MIN 231 #undef UNSIGNED_INT_MAX 232 #undef SIGNED_MAX_10_EXP 233 #undef UNSIGNED_MAX_10_EXP 234 #undef DECL_INT_LIMIT_FUNCS 235 236 // For non-Windows builds we use the std:: versions of isinf and isnan if they 237 // are available; see the comment about <cmath> at the top of this file for the 238 // details on why we need to do this. 239 #ifdef GOOGLE_PROTOBUF_USE_STD_CMATH 240 #define ISINF std::isinf 241 #define ISNAN std::isnan 242 #else 243 #define ISINF isinf 244 #define ISNAN isnan 245 #endif 246 247 // ========================================================================= // 248 #if defined(_WIN32) && !defined(__MINGW32__) // Lacks built-in isnan() and isinf() 249 #define DECL_FP_LIMIT_FUNCS \ 250 static bool IsFinite(const Type x) { return _finite(x); } \ 251 static bool IsNaN(const Type x) { return _isnan(x); } \ 252 static bool IsInf(const Type x) { return (_fpclass(x) & (_FPCLASS_NINF | _FPCLASS_PINF)) != 0; } \ 253 static bool IsPosInf(const Type x) { return _fpclass(x) == _FPCLASS_PINF; } \ 254 static bool IsNegInf(const Type x) { return _fpclass(x) == _FPCLASS_NINF; } 255 #else 256 #define DECL_FP_LIMIT_FUNCS \ 257 static bool IsFinite(const Type x) { return !ISINF(x) && !ISNAN(x); } \ 258 static bool IsNaN(const Type x) { return ISNAN(x); } \ 259 static bool IsInf(const Type x) { return ISINF(x); } \ 260 static bool IsPosInf(const Type x) { return ISINF(x) && x > 0; } \ 261 static bool IsNegInf(const Type x) { return ISINF(x) && x < 0; } 262 #endif 263 264 // We can't put floating-point constant values in the header here because 265 // such constants are not considered to be primitive-type constants by gcc. 266 // CAVEAT: Hence, they are going to be initialized only during 267 // the global objects construction time. 268 #define DECL_FP_LIMITS(FP_Type, PREFIX) \ 269 template <> \ 270 struct PROTOBUF_EXPORT MathLimits<FP_Type> { \ 271 typedef FP_Type Type; \ 272 typedef FP_Type UnsignedType; \ 273 static const bool kIsSigned = true; \ 274 static const bool kIsInteger = false; \ 275 static const Type kPosMin; \ 276 static const Type kPosMax; \ 277 static const Type kMin; \ 278 static const Type kMax; \ 279 static const Type kNegMin; \ 280 static const Type kNegMax; \ 281 static const int kMin10Exp = PREFIX##_MIN_10_EXP; \ 282 static const int kMax10Exp = PREFIX##_MAX_10_EXP; \ 283 static const Type kEpsilon; \ 284 static const Type kStdError; \ 285 static const int kPrecisionDigits = PREFIX##_DIG; \ 286 static const Type kNaN; \ 287 static const Type kPosInf; \ 288 static const Type kNegInf; \ 289 DECL_FP_LIMIT_FUNCS \ 290 }; 291 292 DECL_FP_LIMITS(float, FLT) 293 DECL_FP_LIMITS(double, DBL) 294 DECL_FP_LIMITS(long double, LDBL) 295 296 #undef ISINF 297 #undef ISNAN 298 #undef DECL_FP_LIMITS 299 #undef DECL_FP_LIMIT_FUNCS 300 301 // ========================================================================= // 302 } // namespace protobuf 303 } // namespace google 304 305 #include <google/protobuf/port_undef.inc> 306 307 #endif // UTIL_MATH_MATHLIMITS_H__ 308