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 "wtf/StdLibExtras.h"
     31 #include <algorithm>
     32 #include <cmath>
     33 #include <float.h>
     34 #include <limits>
     35 #include <stdint.h>
     36 #include <stdlib.h>
     37 
     38 #if OS(SOLARIS)
     39 #include <ieeefp.h>
     40 #endif
     41 
     42 #if OS(OPENBSD)
     43 #include <sys/types.h>
     44 #include <machine/ieee.h>
     45 #endif
     46 
     47 #ifndef M_PI
     48 const double piDouble = 3.14159265358979323846;
     49 const float piFloat = 3.14159265358979323846f;
     50 #else
     51 const double piDouble = M_PI;
     52 const float piFloat = static_cast<float>(M_PI);
     53 #endif
     54 
     55 #ifndef M_PI_2
     56 const double piOverTwoDouble = 1.57079632679489661923;
     57 const float piOverTwoFloat = 1.57079632679489661923f;
     58 #else
     59 const double piOverTwoDouble = M_PI_2;
     60 const float piOverTwoFloat = static_cast<float>(M_PI_2);
     61 #endif
     62 
     63 #ifndef M_PI_4
     64 const double piOverFourDouble = 0.785398163397448309616;
     65 const float piOverFourFloat = 0.785398163397448309616f;
     66 #else
     67 const double piOverFourDouble = M_PI_4;
     68 const float piOverFourFloat = static_cast<float>(M_PI_4);
     69 #endif
     70 
     71 #if OS(DARWIN)
     72 
     73 // Work around a bug in the Mac OS X libc where ceil(-0.1) return +0.
     74 inline double wtf_ceil(double x) { return copysign(ceil(x), x); }
     75 
     76 #define ceil(x) wtf_ceil(x)
     77 
     78 #endif
     79 
     80 #if OS(SOLARIS)
     81 
     82 namespace std {
     83 
     84 #ifndef isfinite
     85 inline bool isfinite(double x) { return finite(x) && !isnand(x); }
     86 #endif
     87 #ifndef signbit
     88 inline bool signbit(double x) { return copysign(1.0, x) < 0; }
     89 #endif
     90 #ifndef isinf
     91 inline bool isinf(double x) { return !finite(x) && !isnand(x); }
     92 #endif
     93 
     94 } // namespace std
     95 
     96 #endif
     97 
     98 #if OS(OPENBSD)
     99 
    100 namespace std {
    101 
    102 #ifndef isfinite
    103 inline bool isfinite(double x) { return finite(x); }
    104 #endif
    105 #ifndef signbit
    106 inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x; return p->dbl_sign; }
    107 #endif
    108 
    109 } // namespace std
    110 
    111 #endif
    112 
    113 #if COMPILER(MSVC)
    114 
    115 // We must not do 'num + 0.5' or 'num - 0.5' because they can cause precision loss.
    116 static double round(double num)
    117 {
    118     double integer = ceil(num);
    119     if (num > 0)
    120         return integer - num > 0.5 ? integer - 1.0 : integer;
    121     return integer - num >= 0.5 ? integer - 1.0 : integer;
    122 }
    123 static float roundf(float num)
    124 {
    125     float integer = ceilf(num);
    126     if (num > 0)
    127         return integer - num > 0.5f ? integer - 1.0f : integer;
    128     return integer - num >= 0.5f ? integer - 1.0f : integer;
    129 }
    130 inline long long llround(double num) { return static_cast<long long>(round(num)); }
    131 inline long long llroundf(float num) { return static_cast<long long>(roundf(num)); }
    132 inline long lround(double num) { return static_cast<long>(round(num)); }
    133 inline long lroundf(float num) { return static_cast<long>(roundf(num)); }
    134 inline double trunc(double num) { return num > 0 ? floor(num) : ceil(num); }
    135 
    136 #endif
    137 
    138 #if OS(ANDROID) || COMPILER(MSVC)
    139 // ANDROID and MSVC's math.h does not currently supply log2 or log2f.
    140 inline double log2(double num)
    141 {
    142     // This constant is roughly M_LN2, which is not provided by default on Windows and Android.
    143     return log(num) / 0.693147180559945309417232121458176568;
    144 }
    145 
    146 inline float log2f(float num)
    147 {
    148     // This constant is roughly M_LN2, which is not provided by default on Windows and Android.
    149     return logf(num) / 0.693147180559945309417232121458176568f;
    150 }
    151 #endif
    152 
    153 #if COMPILER(MSVC)
    154 
    155 namespace std {
    156 
    157 inline bool isinf(double num) { return !_finite(num) && !_isnan(num); }
    158 inline bool isnan(double num) { return !!_isnan(num); }
    159 inline bool isfinite(double x) { return _finite(x); }
    160 inline bool signbit(double num) { return _copysign(1.0, num) < 0; }
    161 
    162 } // namespace std
    163 
    164 inline double nextafter(double x, double y) { return _nextafter(x, y); }
    165 inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x + FLT_EPSILON; }
    166 
    167 inline double copysign(double x, double y) { return _copysign(x, y); }
    168 
    169 // Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN instead of specific values.
    170 inline double wtf_atan2(double x, double y)
    171 {
    172     double posInf = std::numeric_limits<double>::infinity();
    173     double negInf = -std::numeric_limits<double>::infinity();
    174     double nan = std::numeric_limits<double>::quiet_NaN();
    175 
    176     double result = nan;
    177 
    178     if (x == posInf && y == posInf)
    179         result = piOverFourDouble;
    180     else if (x == posInf && y == negInf)
    181         result = 3 * piOverFourDouble;
    182     else if (x == negInf && y == posInf)
    183         result = -piOverFourDouble;
    184     else if (x == negInf && y == negInf)
    185         result = -3 * piOverFourDouble;
    186     else
    187         result = ::atan2(x, y);
    188 
    189     return result;
    190 }
    191 
    192 // Work around a bug in the Microsoft CRT, where fmod(x, +-infinity) yields NaN instead of x.
    193 inline double wtf_fmod(double x, double y) { return (!std::isinf(x) && std::isinf(y)) ? x : fmod(x, y); }
    194 
    195 // Work around a bug in the Microsoft CRT, where pow(NaN, 0) yields NaN instead of 1.
    196 inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); }
    197 
    198 #define atan2(x, y) wtf_atan2(x, y)
    199 #define fmod(x, y) wtf_fmod(x, y)
    200 #define pow(x, y) wtf_pow(x, y)
    201 
    202 // MSVC's math functions do not bring lrint.
    203 inline long int lrint(double flt)
    204 {
    205     int64_t intgr;
    206 #if CPU(X86)
    207     __asm {
    208         fld flt
    209         fistp intgr
    210     };
    211 #else
    212     ASSERT(std::isfinite(flt));
    213     double rounded = round(flt);
    214     intgr = static_cast<int64_t>(rounded);
    215     // If the fractional part is exactly 0.5, we need to check whether
    216     // the rounded result is even. If it is not we need to add 1 to
    217     // negative values and subtract one from positive values.
    218     if ((fabs(intgr - flt) == 0.5) & intgr)
    219         intgr -= ((intgr >> 62) | 1); // 1 with the sign of result, i.e. -1 or 1.
    220 #endif
    221     return static_cast<long int>(intgr);
    222 }
    223 
    224 #endif // COMPILER(MSVC)
    225 
    226 inline double deg2rad(double d)  { return d * piDouble / 180.0; }
    227 inline double rad2deg(double r)  { return r * 180.0 / piDouble; }
    228 inline double deg2grad(double d) { return d * 400.0 / 360.0; }
    229 inline double grad2deg(double g) { return g * 360.0 / 400.0; }
    230 inline double turn2deg(double t) { return t * 360.0; }
    231 inline double deg2turn(double d) { return d / 360.0; }
    232 inline double rad2grad(double r) { return r * 200.0 / piDouble; }
    233 inline double grad2rad(double g) { return g * piDouble / 200.0; }
    234 
    235 inline float deg2rad(float d)  { return d * piFloat / 180.0f; }
    236 inline float rad2deg(float r)  { return r * 180.0f / piFloat; }
    237 inline float deg2grad(float d) { return d * 400.0f / 360.0f; }
    238 inline float grad2deg(float g) { return g * 360.0f / 400.0f; }
    239 inline float turn2deg(float t) { return t * 360.0f; }
    240 inline float deg2turn(float d) { return d / 360.0f; }
    241 inline float rad2grad(float r) { return r * 200.0f / piFloat; }
    242 inline float grad2rad(float g) { return g * piFloat / 200.0f; }
    243 
    244 // std::numeric_limits<T>::min() returns the smallest positive value for floating point types
    245 template<typename T> inline T defaultMinimumForClamp() { return std::numeric_limits<T>::min(); }
    246 template<> inline float defaultMinimumForClamp() { return -std::numeric_limits<float>::max(); }
    247 template<> inline double defaultMinimumForClamp() { return -std::numeric_limits<double>::max(); }
    248 template<typename T> inline T defaultMaximumForClamp() { return std::numeric_limits<T>::max(); }
    249 
    250 template<typename T> inline T clampTo(double value, T min = defaultMinimumForClamp<T>(), T max = defaultMaximumForClamp<T>())
    251 {
    252     if (value >= static_cast<double>(max))
    253         return max;
    254     if (value <= static_cast<double>(min))
    255         return min;
    256     return static_cast<T>(value);
    257 }
    258 template<> inline long long int clampTo(double, long long int, long long int); // clampTo does not support long long ints.
    259 
    260 inline int clampToInteger(double value)
    261 {
    262     return clampTo<int>(value);
    263 }
    264 
    265 inline float clampToFloat(double value)
    266 {
    267     return clampTo<float>(value);
    268 }
    269 
    270 inline int clampToPositiveInteger(double value)
    271 {
    272     return clampTo<int>(value, 0);
    273 }
    274 
    275 inline int clampToInteger(float value)
    276 {
    277     return clampTo<int>(value);
    278 }
    279 
    280 inline int clampToInteger(unsigned x)
    281 {
    282     const unsigned intMax = static_cast<unsigned>(std::numeric_limits<int>::max());
    283 
    284     if (x >= intMax)
    285         return std::numeric_limits<int>::max();
    286     return static_cast<int>(x);
    287 }
    288 
    289 inline bool isWithinIntRange(float x)
    290 {
    291     return x > static_cast<float>(std::numeric_limits<int>::min()) && x < static_cast<float>(std::numeric_limits<int>::max());
    292 }
    293 
    294 #ifndef UINT64_C
    295 #if COMPILER(MSVC)
    296 #define UINT64_C(c) c ## ui64
    297 #else
    298 #define UINT64_C(c) c ## ull
    299 #endif
    300 #endif
    301 
    302 // Calculate d % 2^{64}.
    303 inline void doubleToInteger(double d, unsigned long long& value)
    304 {
    305     if (std::isnan(d) || std::isinf(d))
    306         value = 0;
    307     else {
    308         // -2^{64} < fmodValue < 2^{64}.
    309         double fmodValue = fmod(trunc(d), std::numeric_limits<unsigned long long>::max() + 1.0);
    310         if (fmodValue >= 0) {
    311             // 0 <= fmodValue < 2^{64}.
    312             // 0 <= value < 2^{64}. This cast causes no loss.
    313             value = static_cast<unsigned long long>(fmodValue);
    314         } else {
    315             // -2^{64} < fmodValue < 0.
    316             // 0 < fmodValueInUnsignedLongLong < 2^{64}. This cast causes no loss.
    317             unsigned long long fmodValueInUnsignedLongLong = static_cast<unsigned long long>(-fmodValue);
    318             // -1 < (std::numeric_limits<unsigned long long>::max() - fmodValueInUnsignedLongLong) < 2^{64} - 1.
    319             // 0 < value < 2^{64}.
    320             value = std::numeric_limits<unsigned long long>::max() - fmodValueInUnsignedLongLong + 1;
    321         }
    322     }
    323 }
    324 
    325 namespace WTF {
    326 
    327 inline unsigned fastLog2(unsigned i)
    328 {
    329     unsigned log2 = 0;
    330     if (i & (i - 1))
    331         log2 += 1;
    332     if (i >> 16)
    333         log2 += 16, i >>= 16;
    334     if (i >> 8)
    335         log2 += 8, i >>= 8;
    336     if (i >> 4)
    337         log2 += 4, i >>= 4;
    338     if (i >> 2)
    339         log2 += 2, i >>= 2;
    340     if (i >> 1)
    341         log2 += 1;
    342     return log2;
    343 }
    344 
    345 } // namespace WTF
    346 
    347 #endif // #ifndef WTF_MathExtras_h
    348