]>
Commit | Line | Data |
---|---|---|
b37bf2e1 | 1 | /* |
4e4e5a6f | 2 | * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. |
b37bf2e1 A |
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 | ||
14957cd0 | 29 | #include <algorithm> |
4e4e5a6f | 30 | #include <cmath> |
f9bf01c6 | 31 | #include <float.h> |
14957cd0 | 32 | #include <limits> |
b37bf2e1 | 33 | #include <stdlib.h> |
b37bf2e1 | 34 | |
f9bf01c6 | 35 | #if OS(SOLARIS) |
b37bf2e1 A |
36 | #include <ieeefp.h> |
37 | #endif | |
38 | ||
f9bf01c6 | 39 | #if OS(OPENBSD) |
9dae56ea A |
40 | #include <sys/types.h> |
41 | #include <machine/ieee.h> | |
42 | #endif | |
b37bf2e1 | 43 | |
9dae56ea | 44 | #if COMPILER(MSVC) |
f9bf01c6 | 45 | #if OS(WINCE) |
9dae56ea | 46 | #include <stdlib.h> |
9dae56ea | 47 | #endif |
b37bf2e1 | 48 | #include <limits> |
b37bf2e1 A |
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 | ||
14957cd0 A |
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 | ||
b37bf2e1 A |
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 | ||
f9bf01c6 | 75 | #if OS(DARWIN) |
9dae56ea A |
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 | ||
f9bf01c6 | 84 | #if OS(SOLARIS) |
b37bf2e1 A |
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 | |
14957cd0 | 93 | inline bool signbit(double x) { return copysign(1.0, x) < 0; } |
b37bf2e1 A |
94 | #endif |
95 | ||
96 | #endif | |
97 | ||
f9bf01c6 | 98 | #if OS(OPENBSD) |
9dae56ea A |
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 | ||
14957cd0 | 109 | #if COMPILER(MSVC) || (COMPILER(RVCT) && !(RVCT_VERSION_AT_LEAST(3, 0, 0, 0))) |
b37bf2e1 | 110 | |
4e4e5a6f A |
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)); } | |
b37bf2e1 A |
130 | inline double trunc(double num) { return num > 0 ? floor(num) : ceil(num); } |
131 | ||
9dae56ea A |
132 | #endif |
133 | ||
134 | #if COMPILER(MSVC) | |
4e4e5a6f A |
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 | |
9dae56ea A |
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 | ||
b37bf2e1 A |
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 | ||
14957cd0 A |
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 | ||
b37bf2e1 A |
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 | { | |
9dae56ea A |
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(); | |
b37bf2e1 A |
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 | ||
b37bf2e1 A |
190 | #endif // COMPILER(MSVC) |
191 | ||
b37bf2e1 A |
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; } | |
9dae56ea A |
196 | inline double turn2deg(double t) { return t * 360.0; } |
197 | inline double deg2turn(double d) { return d / 360.0; } | |
b37bf2e1 A |
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; } | |
9dae56ea A |
205 | inline float turn2deg(float t) { return t * 360.0f; } |
206 | inline float deg2turn(float d) { return d / 360.0f; } | |
b37bf2e1 A |
207 | inline float rad2grad(float r) { return r * 200.0f / piFloat; } |
208 | inline float grad2rad(float g) { return g * piFloat / 200.0f; } | |
209 | ||
14957cd0 A |
210 | inline int clampToInteger(double x) |
211 | { | |
212 | const double intMax = static_cast<double>(std::numeric_limits<int>::max()); | |
213 | const double intMin = static_cast<double>(std::numeric_limits<int>::min()); | |
214 | ||
215 | if (x >= intMax) | |
216 | return std::numeric_limits<int>::max(); | |
217 | if (x <= intMin) | |
218 | return std::numeric_limits<int>::min(); | |
219 | return static_cast<int>(x); | |
220 | } | |
221 | ||
222 | inline float clampToFloat(double x) | |
223 | { | |
224 | const double floatMax = static_cast<double>(std::numeric_limits<float>::max()); | |
225 | const double floatMin = -static_cast<double>(std::numeric_limits<float>::max()); | |
226 | ||
227 | if (x >= floatMax) | |
228 | return std::numeric_limits<float>::max(); | |
229 | if (x <= floatMin) | |
230 | return -std::numeric_limits<float>::max(); | |
231 | return static_cast<float>(x); | |
232 | } | |
233 | ||
234 | inline int clampToPositiveInteger(double x) | |
235 | { | |
236 | const double intMax = static_cast<double>(std::numeric_limits<int>::max()); | |
237 | ||
238 | if (x >= intMax) | |
239 | return std::numeric_limits<int>::max(); | |
240 | if (x <= 0) | |
241 | return 0; | |
242 | return static_cast<int>(x); | |
243 | } | |
244 | ||
245 | inline int clampToInteger(float x) | |
246 | { | |
247 | const float intMax = static_cast<float>(std::numeric_limits<int>::max()); | |
248 | const float intMin = static_cast<float>(std::numeric_limits<int>::min()); | |
249 | ||
250 | if (x >= intMax) | |
251 | return std::numeric_limits<int>::max(); | |
252 | if (x <= intMin) | |
253 | return std::numeric_limits<int>::min(); | |
254 | return static_cast<int>(x); | |
255 | } | |
256 | ||
257 | inline int clampToPositiveInteger(float x) | |
258 | { | |
259 | const float intMax = static_cast<float>(std::numeric_limits<int>::max()); | |
260 | ||
261 | if (x >= intMax) | |
262 | return std::numeric_limits<int>::max(); | |
263 | if (x <= 0) | |
264 | return 0; | |
265 | return static_cast<int>(x); | |
266 | } | |
267 | ||
268 | inline int clampToInteger(unsigned x) | |
269 | { | |
270 | const unsigned intMax = static_cast<unsigned>(std::numeric_limits<int>::max()); | |
271 | ||
272 | if (x >= intMax) | |
273 | return std::numeric_limits<int>::max(); | |
274 | return static_cast<int>(x); | |
275 | } | |
276 | ||
1df5f87f A |
277 | inline bool isWithinIntRange(float x) |
278 | { | |
279 | return x > static_cast<float>(std::numeric_limits<int>::min()) && x < static_cast<float>(std::numeric_limits<int>::max()); | |
280 | } | |
281 | ||
14957cd0 | 282 | #if !COMPILER(MSVC) && !(COMPILER(RVCT) && PLATFORM(BREWMP)) && !OS(SOLARIS) && !OS(SYMBIAN) |
4e4e5a6f A |
283 | using std::isfinite; |
284 | using std::isinf; | |
285 | using std::isnan; | |
286 | using std::signbit; | |
287 | #endif | |
288 | ||
b37bf2e1 | 289 | #endif // #ifndef WTF_MathExtras_h |