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. 63namespace google { 64namespace protobuf { 65template<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) \ 166template<> \ 167struct 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) \ 186template<> \ 187struct 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 203DECL_SIGNED_INT_LIMITS(signed char, unsigned char) 204DECL_SIGNED_INT_LIMITS(signed short int, unsigned short int) 205DECL_SIGNED_INT_LIMITS(signed int, unsigned int) 206DECL_SIGNED_INT_LIMITS(signed long int, unsigned long int) 207DECL_SIGNED_INT_LIMITS(signed long long int, unsigned long long int) 208DECL_UNSIGNED_INT_LIMITS(unsigned char) 209DECL_UNSIGNED_INT_LIMITS(unsigned short int) 210DECL_UNSIGNED_INT_LIMITS(unsigned int) 211DECL_UNSIGNED_INT_LIMITS(unsigned long int) 212DECL_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) \ 245template<> \ 246struct 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 268DECL_FP_LIMITS(float, FLT) 269DECL_FP_LIMITS(double, DBL) 270DECL_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