Home | History | Annotate | Download | only in wtf
      1 /*
      2  * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef WTF_MathExtras_h
     27 #define WTF_MathExtras_h
     28 
     29 #include "wtf/CPU.h"
     30 #include <cmath>
     31 #include <limits>
     32 
     33 #if COMPILER(MSVC)
     34 #include "wtf/Assertions.h"
     35 #include <stdint.h>
     36 #endif
     37 
     38 #if OS(OPENBSD)
     39 #include <sys/types.h>
     40 #include <machine/ieee.h>
     41 #endif
     42 
     43 const double piDouble = M_PI;
     44 const float piFloat = static_cast<float>(M_PI);
     45 
     46 const double piOverTwoDouble = M_PI_2;
     47 const float piOverTwoFloat = static_cast<float>(M_PI_2);
     48 
     49 const double piOverFourDouble = M_PI_4;
     50 const float piOverFourFloat = static_cast<float>(M_PI_4);
     51 
     52 const double twoPiDouble = piDouble * 2.0;
     53 const float twoPiFloat = piFloat * 2.0f;
     54 
     55 #if OS(MACOSX)
     56 
     57 // Work around a bug in the Mac OS X libc where ceil(-0.1) return +0.
     58 inline double wtf_ceil(double x) { return copysign(ceil(x), x); }
     59 
     60 #define ceil(x) wtf_ceil(x)
     61 
     62 #endif
     63 
     64 #if OS(OPENBSD)
     65 
     66 namespace std {
     67 
     68 #ifndef isfinite
     69 inline bool isfinite(double x) { return finite(x); }
     70 #endif
     71 #ifndef signbit
     72 inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x; return p->dbl_sign; }
     73 #endif
     74 
     75 } // namespace std
     76 
     77 #endif
     78 
     79 #if COMPILER(MSVC) && (_MSC_VER < 1800)
     80 
     81 // We must not do 'num + 0.5' or 'num - 0.5' because they can cause precision loss.
     82 static double round(double num)
     83 {
     84     double integer = ceil(num);
     85     if (num > 0)
     86         return integer - num > 0.5 ? integer - 1.0 : integer;
     87     return integer - num >= 0.5 ? integer - 1.0 : integer;
     88 }
     89 static float roundf(float num)
     90 {
     91     float integer = ceilf(num);
     92     if (num > 0)
     93         return integer - num > 0.5f ? integer - 1.0f : integer;
     94     return integer - num >= 0.5f ? integer - 1.0f : integer;
     95 }
     96 inline long long llround(double num) { return static_cast<long long>(round(num)); }
     97 inline long long llroundf(float num) { return static_cast<long long>(roundf(num)); }
     98 inline long lround(double num) { return static_cast<long>(round(num)); }
     99 inline long lroundf(float num) { return static_cast<long>(roundf(num)); }
    100 inline double trunc(double num) { return num > 0 ? floor(num) : ceil(num); }
    101 
    102 #endif
    103 
    104 #if OS(ANDROID) || COMPILER(MSVC)
    105 // ANDROID and MSVC's math.h does not currently supply log2 or log2f.
    106 inline double log2(double num)
    107 {
    108     // This constant is roughly M_LN2, which is not provided by default on Windows and Android.
    109     return log(num) / 0.693147180559945309417232121458176568;
    110 }
    111 
    112 inline float log2f(float num)
    113 {
    114     // This constant is roughly M_LN2, which is not provided by default on Windows and Android.
    115     return logf(num) / 0.693147180559945309417232121458176568f;
    116 }
    117 #endif
    118 
    119 #if COMPILER(MSVC)
    120 
    121 // VS2013 has most of the math functions now, but we still need to work
    122 // around various differences in behavior of Inf.
    123 
    124 #if _MSC_VER < 1800
    125 
    126 namespace std {
    127 
    128 inline bool isinf(double num) { return !_finite(num) && !_isnan(num); }
    129 inline bool isnan(double num) { return !!_isnan(num); }
    130 inline bool isfinite(double x) { return _finite(x); }
    131 inline bool signbit(double num) { return _copysign(1.0, num) < 0; }
    132 
    133 } // namespace std
    134 
    135 inline double nextafter(double x, double y) { return _nextafter(x, y); }
    136 inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x + FLT_EPSILON; }
    137 
    138 inline double copysign(double x, double y) { return _copysign(x, y); }
    139 
    140 #endif // _MSC_VER
    141 
    142 // Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN instead of specific values.
    143 inline double wtf_atan2(double x, double y)
    144 {
    145     double posInf = std::numeric_limits<double>::infinity();
    146     double negInf = -std::numeric_limits<double>::infinity();
    147     double nan = std::numeric_limits<double>::quiet_NaN();
    148 
    149     double result = nan;
    150 
    151     if (x == posInf && y == posInf)
    152         result = piOverFourDouble;
    153     else if (x == posInf && y == negInf)
    154         result = 3 * piOverFourDouble;
    155     else if (x == negInf && y == posInf)
    156         result = -piOverFourDouble;
    157     else if (x == negInf && y == negInf)
    158         result = -3 * piOverFourDouble;
    159     else
    160         result = ::atan2(x, y);
    161 
    162     return result;
    163 }
    164 
    165 // Work around a bug in the Microsoft CRT, where fmod(x, +-infinity) yields NaN instead of x.
    166 inline double wtf_fmod(double x, double y) { return (!std::isinf(x) && std::isinf(y)) ? x : fmod(x, y); }
    167 
    168 // Work around a bug in the Microsoft CRT, where pow(NaN, 0) yields NaN instead of 1.
    169 inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); }
    170 
    171 #define atan2(x, y) wtf_atan2(x, y)
    172 #define fmod(x, y) wtf_fmod(x, y)
    173 #define pow(x, y) wtf_pow(x, y)
    174 
    175 #if _MSC_VER < 1800
    176 
    177 // MSVC's math functions do not bring lrint.
    178 inline long int lrint(double flt)
    179 {
    180     int64_t intgr;
    181 #if CPU(X86)
    182     __asm {
    183         fld flt
    184         fistp intgr
    185     };
    186 #else
    187     ASSERT(std::isfinite(flt));
    188     double rounded = round(flt);
    189     intgr = static_cast<int64_t>(rounded);
    190     // If the fractional part is exactly 0.5, we need to check whether
    191     // the rounded result is even. If it is not we need to add 1 to
    192     // negative values and subtract one from positive values.
    193     if ((fabs(intgr - flt) == 0.5) & intgr)
    194         intgr -= ((intgr >> 62) | 1); // 1 with the sign of result, i.e. -1 or 1.
    195 #endif
    196     return static_cast<long int>(intgr);
    197 }
    198 
    199 #endif // _MSC_VER
    200 
    201 #endif // COMPILER(MSVC)
    202 
    203 inline double deg2rad(double d)  { return d * piDouble / 180.0; }
    204 inline double rad2deg(double r)  { return r * 180.0 / piDouble; }
    205 inline double deg2grad(double d) { return d * 400.0 / 360.0; }
    206 inline double grad2deg(double g) { return g * 360.0 / 400.0; }
    207 inline double turn2deg(double t) { return t * 360.0; }
    208 inline double deg2turn(double d) { return d / 360.0; }
    209 inline double rad2grad(double r) { return r * 200.0 / piDouble; }
    210 inline double grad2rad(double g) { return g * piDouble / 200.0; }
    211 inline double turn2grad(double t) { return t * 400; }
    212 inline double grad2turn(double g) { return g / 400; }
    213 
    214 inline float deg2rad(float d)  { return d * piFloat / 180.0f; }
    215 inline float rad2deg(float r)  { return r * 180.0f / piFloat; }
    216 inline float deg2grad(float d) { return d * 400.0f / 360.0f; }
    217 inline float grad2deg(float g) { return g * 360.0f / 400.0f; }
    218 inline float turn2deg(float t) { return t * 360.0f; }
    219 inline float deg2turn(float d) { return d / 360.0f; }
    220 inline float rad2grad(float r) { return r * 200.0f / piFloat; }
    221 inline float grad2rad(float g) { return g * piFloat / 200.0f; }
    222 inline float turn2grad(float t) { return t * 400; }
    223 inline float grad2turn(float g) { return g / 400; }
    224 
    225 // std::numeric_limits<T>::min() returns the smallest positive value for floating point types
    226 template<typename T> inline T defaultMinimumForClamp() { return std::numeric_limits<T>::min(); }
    227 template<> inline float defaultMinimumForClamp() { return -std::numeric_limits<float>::max(); }
    228 template<> inline double defaultMinimumForClamp() { return -std::numeric_limits<double>::max(); }
    229 template<typename T> inline T defaultMaximumForClamp() { return std::numeric_limits<T>::max(); }
    230 
    231 template<typename T> inline T clampTo(double value, T min = defaultMinimumForClamp<T>(), T max = defaultMaximumForClamp<T>())
    232 {
    233     if (value >= static_cast<double>(max))
    234         return max;
    235     if (value <= static_cast<double>(min))
    236         return min;
    237     return static_cast<T>(value);
    238 }
    239 template<> inline long long int clampTo(double, long long int, long long int); // clampTo does not support long long ints.
    240 
    241 inline int clampToInteger(double value)
    242 {
    243     return clampTo<int>(value);
    244 }
    245 
    246 inline unsigned clampToUnsigned(double value)
    247 {
    248     return clampTo<unsigned>(value);
    249 }
    250 
    251 inline float clampToFloat(double value)
    252 {
    253     return clampTo<float>(value);
    254 }
    255 
    256 inline int clampToPositiveInteger(double value)
    257 {
    258     return clampTo<int>(value, 0);
    259 }
    260 
    261 inline int clampToInteger(float value)
    262 {
    263     return clampTo<int>(value);
    264 }
    265 
    266 inline int clampToInteger(unsigned x)
    267 {
    268     const unsigned intMax = static_cast<unsigned>(std::numeric_limits<int>::max());
    269 
    270     if (x >= intMax)
    271         return std::numeric_limits<int>::max();
    272     return static_cast<int>(x);
    273 }
    274 
    275 inline bool isWithinIntRange(float x)
    276 {
    277     return x > static_cast<float>(std::numeric_limits<int>::min()) && x < static_cast<float>(std::numeric_limits<int>::max());
    278 }
    279 
    280 static size_t greatestCommonDivisor(size_t a, size_t b)
    281 {
    282     return b ? greatestCommonDivisor(b, a % b) : a;
    283 }
    284 
    285 inline size_t lowestCommonMultiple(size_t a, size_t b)
    286 {
    287     return a && b ? a / greatestCommonDivisor(a, b) * b : 0;
    288 }
    289 
    290 #ifndef UINT64_C
    291 #if COMPILER(MSVC)
    292 #define UINT64_C(c) c ## ui64
    293 #else
    294 #define UINT64_C(c) c ## ull
    295 #endif
    296 #endif
    297 
    298 // Calculate d % 2^{64}.
    299 inline void doubleToInteger(double d, unsigned long long& value)
    300 {
    301     if (std::isnan(d) || std::isinf(d))
    302         value = 0;
    303     else {
    304         // -2^{64} < fmodValue < 2^{64}.
    305         double fmodValue = fmod(trunc(d), std::numeric_limits<unsigned long long>::max() + 1.0);
    306         if (fmodValue >= 0) {
    307             // 0 <= fmodValue < 2^{64}.
    308             // 0 <= value < 2^{64}. This cast causes no loss.
    309             value = static_cast<unsigned long long>(fmodValue);
    310         } else {
    311             // -2^{64} < fmodValue < 0.
    312             // 0 < fmodValueInUnsignedLongLong < 2^{64}. This cast causes no loss.
    313             unsigned long long fmodValueInUnsignedLongLong = static_cast<unsigned long long>(-fmodValue);
    314             // -1 < (std::numeric_limits<unsigned long long>::max() - fmodValueInUnsignedLongLong) < 2^{64} - 1.
    315             // 0 < value < 2^{64}.
    316             value = std::numeric_limits<unsigned long long>::max() - fmodValueInUnsignedLongLong + 1;
    317         }
    318     }
    319 }
    320 
    321 namespace WTF {
    322 
    323 inline unsigned fastLog2(unsigned i)
    324 {
    325     unsigned log2 = 0;
    326     if (i & (i - 1))
    327         log2 += 1;
    328     if (i >> 16)
    329         log2 += 16, i >>= 16;
    330     if (i >> 8)
    331         log2 += 8, i >>= 8;
    332     if (i >> 4)
    333         log2 += 4, i >>= 4;
    334     if (i >> 2)
    335         log2 += 2, i >>= 2;
    336     if (i >> 1)
    337         log2 += 1;
    338     return log2;
    339 }
    340 
    341 } // namespace WTF
    342 
    343 #endif // #ifndef WTF_MathExtras_h
    344