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