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