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 // <math.h> lacks a lot of prototypes. However, this file needs <math.h> to 47 // access old-fashioned isinf et al. Even worse more: this file must not 48 // include <cmath> because that breaks the definition of isinf with gcc 4.9. 49 // 50 // TODO(mec): after C++11 everywhere, use <cmath> and std::isinf in this file. 51 #include <math.h> 52 #include <string.h> 53 54 #include <cfloat> 55 56 #include <google/protobuf/stubs/common.h> 57 58 // ========================================================================= // 59 60 // Useful integer and floating point limits and type traits. 61 // This is just for the documentation; 62 // real members are defined in our specializations below. 63 namespace google { 64 namespace protobuf { 65 template<typename T> struct MathLimits { 66 // Type name. 67 typedef T Type; 68 // Unsigned version of the Type with the same byte size. 69 // Same as Type for floating point and unsigned types. 70 typedef T UnsignedType; 71 // If the type supports negative values. 72 static const bool kIsSigned; 73 // If the type supports only integer values. 74 static const bool kIsInteger; 75 // Magnitude-wise smallest representable positive value. 76 static const Type kPosMin; 77 // Magnitude-wise largest representable positive value. 78 static const Type kPosMax; 79 // Smallest representable value. 80 static const Type kMin; 81 // Largest representable value. 82 static const Type kMax; 83 // Magnitude-wise smallest representable negative value. 84 // Present only if kIsSigned. 85 static const Type kNegMin; 86 // Magnitude-wise largest representable negative value. 87 // Present only if kIsSigned. 88 static const Type kNegMax; 89 // Smallest integer x such that 10^x is representable. 90 static const int kMin10Exp; 91 // Largest integer x such that 10^x is representable. 92 static const int kMax10Exp; 93 // Smallest positive value such that Type(1) + kEpsilon != Type(1) 94 static const Type kEpsilon; 95 // Typical rounding error that is enough to cover 96 // a few simple floating-point operations. 97 // Slightly larger than kEpsilon to account for a few rounding errors. 98 // Is zero if kIsInteger. 99 static const Type kStdError; 100 // Number of decimal digits of mantissa precision. 101 // Present only if !kIsInteger. 102 static const int kPrecisionDigits; 103 // Not a number, i.e. result of 0/0. 104 // Present only if !kIsInteger. 105 static const Type kNaN; 106 // Positive infinity, i.e. result of 1/0. 107 // Present only if !kIsInteger. 108 static const Type kPosInf; 109 // Negative infinity, i.e. result of -1/0. 110 // Present only if !kIsInteger. 111 static const Type kNegInf; 112 113 // NOTE: Special floating point values behave 114 // in a special (but mathematically-logical) way 115 // in terms of (in)equalty comparison and mathematical operations 116 // -- see out unittest for examples. 117 118 // Special floating point value testers. 119 // Present in integer types for convenience. 120 static bool IsFinite(const Type x); 121 static bool IsNaN(const Type x); 122 static bool IsInf(const Type x); 123 static bool IsPosInf(const Type x); 124 static bool IsNegInf(const Type x); 125 }; 126 127 // ========================================================================= // 128 129 // All #define-s below are simply to refactor the declarations of 130 // MathLimits template specializations. 131 // They are all #undef-ined below. 132 133 // The hoop-jumping in *_INT_(MAX|MIN) below is so that the compiler does not 134 // get an overflow while computing the constants. 135 136 #define SIGNED_INT_MAX(Type) \ 137 (((Type(1) << (sizeof(Type)*8 - 2)) - 1) + (Type(1) << (sizeof(Type)*8 - 2))) 138 139 #define SIGNED_INT_MIN(Type) \ 140 (-(Type(1) << (sizeof(Type)*8 - 2)) - (Type(1) << (sizeof(Type)*8 - 2))) 141 142 #define UNSIGNED_INT_MAX(Type) \ 143 (((Type(1) << (sizeof(Type)*8 - 1)) - 1) + (Type(1) << (sizeof(Type)*8 - 1))) 144 145 // Compile-time selected log10-related constants for integer types. 146 #define SIGNED_MAX_10_EXP(Type) \ 147 (sizeof(Type) == 1 ? 2 : ( \ 148 sizeof(Type) == 2 ? 4 : ( \ 149 sizeof(Type) == 4 ? 9 : ( \ 150 sizeof(Type) == 8 ? 18 : -1)))) 151 152 #define UNSIGNED_MAX_10_EXP(Type) \ 153 (sizeof(Type) == 1 ? 2 : ( \ 154 sizeof(Type) == 2 ? 4 : ( \ 155 sizeof(Type) == 4 ? 9 : ( \ 156 sizeof(Type) == 8 ? 19 : -1)))) 157 158 #define DECL_INT_LIMIT_FUNCS \ 159 static bool IsFinite(const Type /*x*/) { return true; } \ 160 static bool IsNaN(const Type /*x*/) { return false; } \ 161 static bool IsInf(const Type /*x*/) { return false; } \ 162 static bool IsPosInf(const Type /*x*/) { return false; } \ 163 static bool IsNegInf(const Type /*x*/) { return false; } 164 165 #define DECL_SIGNED_INT_LIMITS(IntType, UnsignedIntType) \ 166 template<> \ 167 struct LIBPROTOBUF_EXPORT MathLimits<IntType> { \ 168 typedef IntType Type; \ 169 typedef UnsignedIntType UnsignedType; \ 170 static const bool kIsSigned = true; \ 171 static const bool kIsInteger = true; \ 172 static const Type kPosMin = 1; \ 173 static const Type kPosMax = SIGNED_INT_MAX(Type); \ 174 static const Type kMin = SIGNED_INT_MIN(Type); \ 175 static const Type kMax = kPosMax; \ 176 static const Type kNegMin = -1; \ 177 static const Type kNegMax = kMin; \ 178 static const int kMin10Exp = 0; \ 179 static const int kMax10Exp = SIGNED_MAX_10_EXP(Type); \ 180 static const Type kEpsilon = 1; \ 181 static const Type kStdError = 0; \ 182 DECL_INT_LIMIT_FUNCS \ 183 }; 184 185 #define DECL_UNSIGNED_INT_LIMITS(IntType) \ 186 template<> \ 187 struct LIBPROTOBUF_EXPORT MathLimits<IntType> { \ 188 typedef IntType Type; \ 189 typedef IntType UnsignedType; \ 190 static const bool kIsSigned = false; \ 191 static const bool kIsInteger = true; \ 192 static const Type kPosMin = 1; \ 193 static const Type kPosMax = UNSIGNED_INT_MAX(Type); \ 194 static const Type kMin = 0; \ 195 static const Type kMax = kPosMax; \ 196 static const int kMin10Exp = 0; \ 197 static const int kMax10Exp = UNSIGNED_MAX_10_EXP(Type); \ 198 static const Type kEpsilon = 1; \ 199 static const Type kStdError = 0; \ 200 DECL_INT_LIMIT_FUNCS \ 201 }; 202 203 DECL_SIGNED_INT_LIMITS(signed char, unsigned char) 204 DECL_SIGNED_INT_LIMITS(signed short int, unsigned short int) 205 DECL_SIGNED_INT_LIMITS(signed int, unsigned int) 206 DECL_SIGNED_INT_LIMITS(signed long int, unsigned long int) 207 DECL_SIGNED_INT_LIMITS(signed long long int, unsigned long long int) 208 DECL_UNSIGNED_INT_LIMITS(unsigned char) 209 DECL_UNSIGNED_INT_LIMITS(unsigned short int) 210 DECL_UNSIGNED_INT_LIMITS(unsigned int) 211 DECL_UNSIGNED_INT_LIMITS(unsigned long int) 212 DECL_UNSIGNED_INT_LIMITS(unsigned long long int) 213 214 #undef DECL_SIGNED_INT_LIMITS 215 #undef DECL_UNSIGNED_INT_LIMITS 216 #undef SIGNED_INT_MAX 217 #undef SIGNED_INT_MIN 218 #undef UNSIGNED_INT_MAX 219 #undef SIGNED_MAX_10_EXP 220 #undef UNSIGNED_MAX_10_EXP 221 #undef DECL_INT_LIMIT_FUNCS 222 223 // ========================================================================= // 224 #ifdef WIN32 // Lacks built-in isnan() and isinf() 225 #define DECL_FP_LIMIT_FUNCS \ 226 static bool IsFinite(const Type x) { return _finite(x); } \ 227 static bool IsNaN(const Type x) { return _isnan(x); } \ 228 static bool IsInf(const Type x) { return (_fpclass(x) & (_FPCLASS_NINF | _FPCLASS_PINF)) != 0; } \ 229 static bool IsPosInf(const Type x) { return _fpclass(x) == _FPCLASS_PINF; } \ 230 static bool IsNegInf(const Type x) { return _fpclass(x) == _FPCLASS_NINF; } 231 #else 232 #define DECL_FP_LIMIT_FUNCS \ 233 static bool IsFinite(const Type x) { return !isinf(x) && !isnan(x); } \ 234 static bool IsNaN(const Type x) { return isnan(x); } \ 235 static bool IsInf(const Type x) { return isinf(x); } \ 236 static bool IsPosInf(const Type x) { return isinf(x) && x > 0; } \ 237 static bool IsNegInf(const Type x) { return isinf(x) && x < 0; } 238 #endif 239 240 // We can't put floating-point constant values in the header here because 241 // such constants are not considered to be primitive-type constants by gcc. 242 // CAVEAT: Hence, they are going to be initialized only during 243 // the global objects construction time. 244 #define DECL_FP_LIMITS(FP_Type, PREFIX) \ 245 template<> \ 246 struct LIBPROTOBUF_EXPORT MathLimits<FP_Type> { \ 247 typedef FP_Type Type; \ 248 typedef FP_Type UnsignedType; \ 249 static const bool kIsSigned = true; \ 250 static const bool kIsInteger = false; \ 251 static const Type kPosMin; \ 252 static const Type kPosMax; \ 253 static const Type kMin; \ 254 static const Type kMax; \ 255 static const Type kNegMin; \ 256 static const Type kNegMax; \ 257 static const int kMin10Exp = PREFIX##_MIN_10_EXP; \ 258 static const int kMax10Exp = PREFIX##_MAX_10_EXP; \ 259 static const Type kEpsilon; \ 260 static const Type kStdError; \ 261 static const int kPrecisionDigits = PREFIX##_DIG; \ 262 static const Type kNaN; \ 263 static const Type kPosInf; \ 264 static const Type kNegInf; \ 265 DECL_FP_LIMIT_FUNCS \ 266 }; 267 268 DECL_FP_LIMITS(float, FLT) 269 DECL_FP_LIMITS(double, DBL) 270 DECL_FP_LIMITS(long double, LDBL) 271 272 #undef DECL_FP_LIMITS 273 #undef DECL_FP_LIMIT_FUNCS 274 275 // ========================================================================= // 276 } // namespace protobuf 277 } // namespace google 278 279 #endif // UTIL_MATH_MATHLIMITS_H__ 280