Home | History | Annotate | Download | only in stubs
      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