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 <cmath> 30 #include <float.h> 31 #include <stdlib.h> 32 33 #if OS(SOLARIS) 34 #include <ieeefp.h> 35 #endif 36 37 #if OS(OPENBSD) 38 #include <sys/types.h> 39 #include <machine/ieee.h> 40 #endif 41 42 #if COMPILER(MSVC) 43 #if OS(WINCE) 44 #include <stdlib.h> 45 #endif 46 #include <limits> 47 #endif 48 49 #ifndef M_PI 50 const double piDouble = 3.14159265358979323846; 51 const float piFloat = 3.14159265358979323846f; 52 #else 53 const double piDouble = M_PI; 54 const float piFloat = static_cast<float>(M_PI); 55 #endif 56 57 #ifndef M_PI_4 58 const double piOverFourDouble = 0.785398163397448309616; 59 const float piOverFourFloat = 0.785398163397448309616f; 60 #else 61 const double piOverFourDouble = M_PI_4; 62 const float piOverFourFloat = static_cast<float>(M_PI_4); 63 #endif 64 65 #if OS(DARWIN) 66 67 // Work around a bug in the Mac OS X libc where ceil(-0.1) return +0. 68 inline double wtf_ceil(double x) { return copysign(ceil(x), x); } 69 70 #define ceil(x) wtf_ceil(x) 71 72 #endif 73 74 #if OS(SOLARIS) 75 76 #ifndef isfinite 77 inline bool isfinite(double x) { return finite(x) && !isnand(x); } 78 #endif 79 #ifndef isinf 80 inline bool isinf(double x) { return !finite(x) && !isnand(x); } 81 #endif 82 #ifndef signbit 83 inline bool signbit(double x) { return x < 0.0; } // FIXME: Wrong for negative 0. 84 #endif 85 86 #endif 87 88 #if OS(OPENBSD) 89 90 #ifndef isfinite 91 inline bool isfinite(double x) { return finite(x); } 92 #endif 93 #ifndef signbit 94 inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x; return p->dbl_sign; } 95 #endif 96 97 #endif 98 99 #if COMPILER(MSVC) || COMPILER(RVCT) 100 101 // We must not do 'num + 0.5' or 'num - 0.5' because they can cause precision loss. 102 static double round(double num) 103 { 104 double integer = ceil(num); 105 if (num > 0) 106 return integer - num > 0.5 ? integer - 1.0 : integer; 107 return integer - num >= 0.5 ? integer - 1.0 : integer; 108 } 109 static float roundf(float num) 110 { 111 float integer = ceilf(num); 112 if (num > 0) 113 return integer - num > 0.5f ? integer - 1.0f : integer; 114 return integer - num >= 0.5f ? integer - 1.0f : integer; 115 } 116 inline long long llround(double num) { return static_cast<long long>(round(num)); } 117 inline long long llroundf(float num) { return static_cast<long long>(roundf(num)); } 118 inline long lround(double num) { return static_cast<long>(round(num)); } 119 inline long lroundf(float num) { return static_cast<long>(roundf(num)); } 120 inline double trunc(double num) { return num > 0 ? floor(num) : ceil(num); } 121 122 #endif 123 124 #if COMPILER(MSVC) 125 126 inline bool isinf(double num) { return !_finite(num) && !_isnan(num); } 127 inline bool isnan(double num) { return !!_isnan(num); } 128 inline bool signbit(double num) { return _copysign(1.0, num) < 0; } 129 130 inline double nextafter(double x, double y) { return _nextafter(x, y); } 131 inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x + FLT_EPSILON; } 132 133 inline double copysign(double x, double y) { return _copysign(x, y); } 134 inline int isfinite(double x) { return _finite(x); } 135 136 // Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN instead of specific values. 137 inline double wtf_atan2(double x, double y) 138 { 139 double posInf = std::numeric_limits<double>::infinity(); 140 double negInf = -std::numeric_limits<double>::infinity(); 141 double nan = std::numeric_limits<double>::quiet_NaN(); 142 143 double result = nan; 144 145 if (x == posInf && y == posInf) 146 result = piOverFourDouble; 147 else if (x == posInf && y == negInf) 148 result = 3 * piOverFourDouble; 149 else if (x == negInf && y == posInf) 150 result = -piOverFourDouble; 151 else if (x == negInf && y == negInf) 152 result = -3 * piOverFourDouble; 153 else 154 result = ::atan2(x, y); 155 156 return result; 157 } 158 159 // Work around a bug in the Microsoft CRT, where fmod(x, +-infinity) yields NaN instead of x. 160 inline double wtf_fmod(double x, double y) { return (!isinf(x) && isinf(y)) ? x : fmod(x, y); } 161 162 // Work around a bug in the Microsoft CRT, where pow(NaN, 0) yields NaN instead of 1. 163 inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); } 164 165 #define atan2(x, y) wtf_atan2(x, y) 166 #define fmod(x, y) wtf_fmod(x, y) 167 #define pow(x, y) wtf_pow(x, y) 168 169 #endif // COMPILER(MSVC) 170 171 inline double deg2rad(double d) { return d * piDouble / 180.0; } 172 inline double rad2deg(double r) { return r * 180.0 / piDouble; } 173 inline double deg2grad(double d) { return d * 400.0 / 360.0; } 174 inline double grad2deg(double g) { return g * 360.0 / 400.0; } 175 inline double turn2deg(double t) { return t * 360.0; } 176 inline double deg2turn(double d) { return d / 360.0; } 177 inline double rad2grad(double r) { return r * 200.0 / piDouble; } 178 inline double grad2rad(double g) { return g * piDouble / 200.0; } 179 180 inline float deg2rad(float d) { return d * piFloat / 180.0f; } 181 inline float rad2deg(float r) { return r * 180.0f / piFloat; } 182 inline float deg2grad(float d) { return d * 400.0f / 360.0f; } 183 inline float grad2deg(float g) { return g * 360.0f / 400.0f; } 184 inline float turn2deg(float t) { return t * 360.0f; } 185 inline float deg2turn(float d) { return d / 360.0f; } 186 inline float rad2grad(float r) { return r * 200.0f / piFloat; } 187 inline float grad2rad(float g) { return g * piFloat / 200.0f; } 188 189 // ANDROID 190 // TODO: Upstream to webkit.org 191 #if !COMPILER(MSVC) && !COMPILER(RVCT) && !COMPILER(WINSCW) 192 using std::isfinite; 193 using std::isinf; 194 using std::isnan; 195 using std::signbit; 196 #endif 197 198 #endif // #ifndef WTF_MathExtras_h 199