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 43const double piDouble = M_PI; 44const float piFloat = static_cast<float>(M_PI); 45 46const double piOverTwoDouble = M_PI_2; 47const float piOverTwoFloat = static_cast<float>(M_PI_2); 48 49const double piOverFourDouble = M_PI_4; 50const float piOverFourFloat = static_cast<float>(M_PI_4); 51 52const double twoPiDouble = piDouble * 2.0; 53const 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. 58inline 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 66namespace std { 67 68#ifndef isfinite 69inline bool isfinite(double x) { return finite(x); } 70#endif 71#ifndef signbit 72inline 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. 82static 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} 89static 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} 96inline long long llround(double num) { return static_cast<long long>(round(num)); } 97inline long long llroundf(float num) { return static_cast<long long>(roundf(num)); } 98inline long lround(double num) { return static_cast<long>(round(num)); } 99inline long lroundf(float num) { return static_cast<long>(roundf(num)); } 100inline 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. 106inline 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 112inline 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 126namespace std { 127 128inline bool isinf(double num) { return !_finite(num) && !_isnan(num); } 129inline bool isnan(double num) { return !!_isnan(num); } 130inline bool isfinite(double x) { return _finite(x); } 131inline bool signbit(double num) { return _copysign(1.0, num) < 0; } 132 133} // namespace std 134 135inline double nextafter(double x, double y) { return _nextafter(x, y); } 136inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x + FLT_EPSILON; } 137 138inline 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. 143inline 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. 166inline 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. 169inline 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. 178inline 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 203inline double deg2rad(double d) { return d * piDouble / 180.0; } 204inline double rad2deg(double r) { return r * 180.0 / piDouble; } 205inline double deg2grad(double d) { return d * 400.0 / 360.0; } 206inline double grad2deg(double g) { return g * 360.0 / 400.0; } 207inline double turn2deg(double t) { return t * 360.0; } 208inline double deg2turn(double d) { return d / 360.0; } 209inline double rad2grad(double r) { return r * 200.0 / piDouble; } 210inline double grad2rad(double g) { return g * piDouble / 200.0; } 211inline double turn2grad(double t) { return t * 400; } 212inline double grad2turn(double g) { return g / 400; } 213 214inline float deg2rad(float d) { return d * piFloat / 180.0f; } 215inline float rad2deg(float r) { return r * 180.0f / piFloat; } 216inline float deg2grad(float d) { return d * 400.0f / 360.0f; } 217inline float grad2deg(float g) { return g * 360.0f / 400.0f; } 218inline float turn2deg(float t) { return t * 360.0f; } 219inline float deg2turn(float d) { return d / 360.0f; } 220inline float rad2grad(float r) { return r * 200.0f / piFloat; } 221inline float grad2rad(float g) { return g * piFloat / 200.0f; } 222inline float turn2grad(float t) { return t * 400; } 223inline float grad2turn(float g) { return g / 400; } 224 225// std::numeric_limits<T>::min() returns the smallest positive value for floating point types 226template<typename T> inline T defaultMinimumForClamp() { return std::numeric_limits<T>::min(); } 227template<> inline float defaultMinimumForClamp() { return -std::numeric_limits<float>::max(); } 228template<> inline double defaultMinimumForClamp() { return -std::numeric_limits<double>::max(); } 229template<typename T> inline T defaultMaximumForClamp() { return std::numeric_limits<T>::max(); } 230 231template<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} 239template<> inline long long int clampTo(double, long long int, long long int); // clampTo does not support long long ints. 240 241inline int clampToInteger(double value) 242{ 243 return clampTo<int>(value); 244} 245 246inline unsigned clampToUnsigned(double value) 247{ 248 return clampTo<unsigned>(value); 249} 250 251inline float clampToFloat(double value) 252{ 253 return clampTo<float>(value); 254} 255 256inline int clampToPositiveInteger(double value) 257{ 258 return clampTo<int>(value, 0); 259} 260 261inline int clampToInteger(float value) 262{ 263 return clampTo<int>(value); 264} 265 266inline 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 275inline 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 280static size_t greatestCommonDivisor(size_t a, size_t b) 281{ 282 return b ? greatestCommonDivisor(b, a % b) : a; 283} 284 285inline 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}. 299inline 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 321namespace WTF { 322 323inline 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