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 <algorithm> 30 #include <cmath> 31 #include <float.h> 32 #include <limits> 33 #include <stdlib.h> 34 35 #if OS(SOLARIS) 36 #include <ieeefp.h> 37 #endif 38 39 #if OS(OPENBSD) 40 #include <sys/types.h> 41 #include <machine/ieee.h> 42 #endif 43 44 #if COMPILER(MSVC) 45 #if OS(WINCE) 46 #include <stdlib.h> 47 #endif 48 #include <limits> 49 #endif 50 51 #ifndef M_PI 52 const double piDouble = 3.14159265358979323846; 53 const float piFloat = 3.14159265358979323846f; 54 #else 55 const double piDouble = M_PI; 56 const float piFloat = static_cast<float>(M_PI); 57 #endif 58 59 #ifndef M_PI_2 60 const double piOverTwoDouble = 1.57079632679489661923; 61 const float piOverTwoFloat = 1.57079632679489661923f; 62 #else 63 const double piOverTwoDouble = M_PI_2; 64 const float piOverTwoFloat = static_cast<float>(M_PI_2); 65 #endif 66 67 #ifndef M_PI_4 68 const double piOverFourDouble = 0.785398163397448309616; 69 const float piOverFourFloat = 0.785398163397448309616f; 70 #else 71 const double piOverFourDouble = M_PI_4; 72 const float piOverFourFloat = static_cast<float>(M_PI_4); 73 #endif 74 75 #if OS(DARWIN) 76 77 // Work around a bug in the Mac OS X libc where ceil(-0.1) return +0. 78 inline double wtf_ceil(double x) { return copysign(ceil(x), x); } 79 80 #define ceil(x) wtf_ceil(x) 81 82 #endif 83 84 #if OS(SOLARIS) 85 86 #ifndef isfinite 87 inline bool isfinite(double x) { return finite(x) && !isnand(x); } 88 #endif 89 #ifndef isinf 90 inline bool isinf(double x) { return !finite(x) && !isnand(x); } 91 #endif 92 #ifndef signbit 93 inline bool signbit(double x) { return copysign(1.0, x) < 0; } 94 #endif 95 96 #endif 97 98 #if OS(OPENBSD) 99 100 #ifndef isfinite 101 inline bool isfinite(double x) { return finite(x); } 102 #endif 103 #ifndef signbit 104 inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x; return p->dbl_sign; } 105 #endif 106 107 #endif 108 109 #if COMPILER(MSVC) || (COMPILER(RVCT) && !(RVCT_VERSION_AT_LEAST(3, 0, 0, 0))) 110 111 // We must not do 'num + 0.5' or 'num - 0.5' because they can cause precision loss. 112 static double round(double num) 113 { 114 double integer = ceil(num); 115 if (num > 0) 116 return integer - num > 0.5 ? integer - 1.0 : integer; 117 return integer - num >= 0.5 ? integer - 1.0 : integer; 118 } 119 static float roundf(float num) 120 { 121 float integer = ceilf(num); 122 if (num > 0) 123 return integer - num > 0.5f ? integer - 1.0f : integer; 124 return integer - num >= 0.5f ? integer - 1.0f : integer; 125 } 126 inline long long llround(double num) { return static_cast<long long>(round(num)); } 127 inline long long llroundf(float num) { return static_cast<long long>(roundf(num)); } 128 inline long lround(double num) { return static_cast<long>(round(num)); } 129 inline long lroundf(float num) { return static_cast<long>(roundf(num)); } 130 inline double trunc(double num) { return num > 0 ? floor(num) : ceil(num); } 131 132 #endif 133 134 #if COMPILER(MSVC) 135 // The 64bit version of abs() is already defined in stdlib.h which comes with VC10 136 #if COMPILER(MSVC9_OR_LOWER) 137 inline long long abs(long long num) { return _abs64(num); } 138 #endif 139 140 inline bool isinf(double num) { return !_finite(num) && !_isnan(num); } 141 inline bool isnan(double num) { return !!_isnan(num); } 142 inline bool signbit(double num) { return _copysign(1.0, num) < 0; } 143 144 inline double nextafter(double x, double y) { return _nextafter(x, y); } 145 inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x + FLT_EPSILON; } 146 147 inline double copysign(double x, double y) { return _copysign(x, y); } 148 inline int isfinite(double x) { return _finite(x); } 149 150 // MSVC's math.h does not currently supply log2. 151 inline double log2(double num) 152 { 153 // This constant is roughly M_LN2, which is not provided by default on Windows. 154 return log(num) / 0.693147180559945309417232121458176568; 155 } 156 157 // Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN instead of specific values. 158 inline double wtf_atan2(double x, double y) 159 { 160 double posInf = std::numeric_limits<double>::infinity(); 161 double negInf = -std::numeric_limits<double>::infinity(); 162 double nan = std::numeric_limits<double>::quiet_NaN(); 163 164 double result = nan; 165 166 if (x == posInf && y == posInf) 167 result = piOverFourDouble; 168 else if (x == posInf && y == negInf) 169 result = 3 * piOverFourDouble; 170 else if (x == negInf && y == posInf) 171 result = -piOverFourDouble; 172 else if (x == negInf && y == negInf) 173 result = -3 * piOverFourDouble; 174 else 175 result = ::atan2(x, y); 176 177 return result; 178 } 179 180 // Work around a bug in the Microsoft CRT, where fmod(x, +-infinity) yields NaN instead of x. 181 inline double wtf_fmod(double x, double y) { return (!isinf(x) && isinf(y)) ? x : fmod(x, y); } 182 183 // Work around a bug in the Microsoft CRT, where pow(NaN, 0) yields NaN instead of 1. 184 inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); } 185 186 #define atan2(x, y) wtf_atan2(x, y) 187 #define fmod(x, y) wtf_fmod(x, y) 188 #define pow(x, y) wtf_pow(x, y) 189 190 #endif // COMPILER(MSVC) 191 192 inline double deg2rad(double d) { return d * piDouble / 180.0; } 193 inline double rad2deg(double r) { return r * 180.0 / piDouble; } 194 inline double deg2grad(double d) { return d * 400.0 / 360.0; } 195 inline double grad2deg(double g) { return g * 360.0 / 400.0; } 196 inline double turn2deg(double t) { return t * 360.0; } 197 inline double deg2turn(double d) { return d / 360.0; } 198 inline double rad2grad(double r) { return r * 200.0 / piDouble; } 199 inline double grad2rad(double g) { return g * piDouble / 200.0; } 200 201 inline float deg2rad(float d) { return d * piFloat / 180.0f; } 202 inline float rad2deg(float r) { return r * 180.0f / piFloat; } 203 inline float deg2grad(float d) { return d * 400.0f / 360.0f; } 204 inline float grad2deg(float g) { return g * 360.0f / 400.0f; } 205 inline float turn2deg(float t) { return t * 360.0f; } 206 inline float deg2turn(float d) { return d / 360.0f; } 207 inline float rad2grad(float r) { return r * 200.0f / piFloat; } 208 inline float grad2rad(float g) { return g * piFloat / 200.0f; } 209 210 inline int clampToInteger(double d) 211 { 212 const double minIntAsDouble = std::numeric_limits<int>::min(); 213 const double maxIntAsDouble = std::numeric_limits<int>::max(); 214 return static_cast<int>(std::max(std::min(d, maxIntAsDouble), minIntAsDouble)); 215 } 216 217 inline int clampToPositiveInteger(double d) 218 { 219 const double maxIntAsDouble = std::numeric_limits<int>::max(); 220 return static_cast<int>(std::max<double>(std::min(d, maxIntAsDouble), 0)); 221 } 222 223 inline int clampToInteger(float x) 224 { 225 static const int s_intMax = std::numeric_limits<int>::max(); 226 static const int s_intMin = std::numeric_limits<int>::min(); 227 228 if (x >= static_cast<float>(s_intMax)) 229 return s_intMax; 230 if (x < static_cast<float>(s_intMin)) 231 return s_intMin; 232 return static_cast<int>(x); 233 } 234 235 inline int clampToPositiveInteger(float x) 236 { 237 static const int s_intMax = std::numeric_limits<int>::max(); 238 239 if (x >= static_cast<float>(s_intMax)) 240 return s_intMax; 241 if (x < 0) 242 return 0; 243 return static_cast<int>(x); 244 } 245 246 inline int clampToInteger(unsigned value) 247 { 248 return static_cast<int>(std::min(value, static_cast<unsigned>(std::numeric_limits<int>::max()))); 249 } 250 251 #if !COMPILER(MSVC) && !(COMPILER(RVCT) && PLATFORM(BREWMP)) && !OS(SOLARIS) && !OS(SYMBIAN) 252 using std::isfinite; 253 using std::isinf; 254 using std::isnan; 255 using std::signbit; 256 #endif 257 258 #endif // #ifndef WTF_MathExtras_h 259