OLD | NEW |
1 /* | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. | 2 // Use of this source code is governed by a BSD-style license that can be |
3 * | 3 // found in the LICENSE file. |
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 | 4 |
26 #ifndef WTF_MathExtras_h | 5 #include "platform/wtf/MathExtras.h" |
27 #define WTF_MathExtras_h | |
28 | 6 |
29 #include "wtf/Allocator.h" | 7 // The contents of this header was moved to platform/wtf as part of |
30 #include "wtf/Assertions.h" | 8 // WTF migration project. See the following post for details: |
31 #include "wtf/CPU.h" | 9 // https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gY
CAAJ |
32 #include <cmath> | |
33 #include <cstddef> | |
34 #include <limits> | |
35 | |
36 #if COMPILER(MSVC) | |
37 // Make math.h behave like other platforms. | |
38 #define _USE_MATH_DEFINES | |
39 // Even if math.h was already included, including math.h again with | |
40 // _USE_MATH_DEFINES adds the extra defines. | |
41 #include <math.h> | |
42 #include <stdint.h> | |
43 #endif | |
44 | |
45 #if OS(OPENBSD) | |
46 #include <machine/ieee.h> | |
47 #include <sys/types.h> | |
48 #endif | |
49 | |
50 const double piDouble = M_PI; | |
51 const float piFloat = static_cast<float>(M_PI); | |
52 | |
53 const double piOverTwoDouble = M_PI_2; | |
54 const float piOverTwoFloat = static_cast<float>(M_PI_2); | |
55 | |
56 const double piOverFourDouble = M_PI_4; | |
57 const float piOverFourFloat = static_cast<float>(M_PI_4); | |
58 | |
59 const double twoPiDouble = piDouble * 2.0; | |
60 const float twoPiFloat = piFloat * 2.0f; | |
61 | |
62 #if COMPILER(MSVC) | |
63 | |
64 // VS2013 has most of the math functions now, but we still need to work | |
65 // around various differences in behavior of Inf. | |
66 | |
67 // Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN | |
68 // instead of specific values. | |
69 inline double wtf_atan2(double x, double y) { | |
70 double posInf = std::numeric_limits<double>::infinity(); | |
71 double negInf = -std::numeric_limits<double>::infinity(); | |
72 double nan = std::numeric_limits<double>::quiet_NaN(); | |
73 | |
74 double result = nan; | |
75 | |
76 if (x == posInf && y == posInf) | |
77 result = piOverFourDouble; | |
78 else if (x == posInf && y == negInf) | |
79 result = 3 * piOverFourDouble; | |
80 else if (x == negInf && y == posInf) | |
81 result = -piOverFourDouble; | |
82 else if (x == negInf && y == negInf) | |
83 result = -3 * piOverFourDouble; | |
84 else | |
85 result = ::atan2(x, y); | |
86 | |
87 return result; | |
88 } | |
89 | |
90 // Work around a bug in the Microsoft CRT, where fmod(x, +-infinity) yields NaN | |
91 // instead of x. | |
92 inline double wtf_fmod(double x, double y) { | |
93 return (!std::isinf(x) && std::isinf(y)) ? x : fmod(x, y); | |
94 } | |
95 | |
96 // Work around a bug in the Microsoft CRT, where pow(NaN, 0) yields NaN instead | |
97 // of 1. | |
98 inline double wtf_pow(double x, double y) { | |
99 return y == 0 ? 1 : pow(x, y); | |
100 } | |
101 | |
102 #define atan2(x, y) wtf_atan2(x, y) | |
103 #define fmod(x, y) wtf_fmod(x, y) | |
104 #define pow(x, y) wtf_pow(x, y) | |
105 | |
106 #endif // COMPILER(MSVC) | |
107 | |
108 inline double deg2rad(double d) { | |
109 return d * piDouble / 180.0; | |
110 } | |
111 inline double rad2deg(double r) { | |
112 return r * 180.0 / piDouble; | |
113 } | |
114 inline double deg2grad(double d) { | |
115 return d * 400.0 / 360.0; | |
116 } | |
117 inline double grad2deg(double g) { | |
118 return g * 360.0 / 400.0; | |
119 } | |
120 inline double turn2deg(double t) { | |
121 return t * 360.0; | |
122 } | |
123 inline double deg2turn(double d) { | |
124 return d / 360.0; | |
125 } | |
126 inline double rad2grad(double r) { | |
127 return r * 200.0 / piDouble; | |
128 } | |
129 inline double grad2rad(double g) { | |
130 return g * piDouble / 200.0; | |
131 } | |
132 inline double turn2grad(double t) { | |
133 return t * 400; | |
134 } | |
135 inline double grad2turn(double g) { | |
136 return g / 400; | |
137 } | |
138 | |
139 inline float deg2rad(float d) { | |
140 return d * piFloat / 180.0f; | |
141 } | |
142 inline float rad2deg(float r) { | |
143 return r * 180.0f / piFloat; | |
144 } | |
145 inline float deg2grad(float d) { | |
146 return d * 400.0f / 360.0f; | |
147 } | |
148 inline float grad2deg(float g) { | |
149 return g * 360.0f / 400.0f; | |
150 } | |
151 inline float turn2deg(float t) { | |
152 return t * 360.0f; | |
153 } | |
154 inline float deg2turn(float d) { | |
155 return d / 360.0f; | |
156 } | |
157 inline float rad2grad(float r) { | |
158 return r * 200.0f / piFloat; | |
159 } | |
160 inline float grad2rad(float g) { | |
161 return g * piFloat / 200.0f; | |
162 } | |
163 inline float turn2grad(float t) { | |
164 return t * 400; | |
165 } | |
166 inline float grad2turn(float g) { | |
167 return g / 400; | |
168 } | |
169 | |
170 // clampTo() is implemented by templated helper classes (to allow for partial | |
171 // template specialization) as well as several helper functions. | |
172 | |
173 // This helper function can be called when we know that: | |
174 // (1) The type signednesses match so the compiler will not produce signed vs. | |
175 // unsigned warnings | |
176 // (2) The default type promotions/conversions are sufficient to handle things | |
177 // correctly | |
178 template <typename LimitType, typename ValueType> | |
179 inline LimitType clampToDirectComparison(ValueType value, | |
180 LimitType min, | |
181 LimitType max) { | |
182 if (value >= max) | |
183 return max; | |
184 return (value <= min) ? min : static_cast<LimitType>(value); | |
185 } | |
186 | |
187 // For any floating-point limits, or integral limits smaller than long long, we | |
188 // can cast the limits to double without losing precision; then the only cases | |
189 // where |value| can't be represented accurately as a double are the ones where | |
190 // it's outside the limit range anyway. So doing all comparisons as doubles | |
191 // will give correct results. | |
192 // | |
193 // In some cases, we can get better performance by using | |
194 // clampToDirectComparison(). We use a templated class to switch between these | |
195 // two cases (instead of simply using a conditional within one function) in | |
196 // order to only compile the clampToDirectComparison() code for cases where it | |
197 // will actually be used; this prevents the compiler from emitting warnings | |
198 // about unsafe code (even though we wouldn't actually be executing that code). | |
199 template <bool canUseDirectComparison, typename LimitType, typename ValueType> | |
200 class ClampToNonLongLongHelper; | |
201 template <typename LimitType, typename ValueType> | |
202 class ClampToNonLongLongHelper<true, LimitType, ValueType> { | |
203 STATIC_ONLY(ClampToNonLongLongHelper); | |
204 | |
205 public: | |
206 static inline LimitType clampTo(ValueType value, | |
207 LimitType min, | |
208 LimitType max) { | |
209 return clampToDirectComparison(value, min, max); | |
210 } | |
211 }; | |
212 | |
213 template <typename LimitType, typename ValueType> | |
214 class ClampToNonLongLongHelper<false, LimitType, ValueType> { | |
215 STATIC_ONLY(ClampToNonLongLongHelper); | |
216 | |
217 public: | |
218 static inline LimitType clampTo(ValueType value, | |
219 LimitType min, | |
220 LimitType max) { | |
221 const double doubleValue = static_cast<double>(value); | |
222 if (doubleValue >= static_cast<double>(max)) | |
223 return max; | |
224 if (doubleValue <= static_cast<double>(min)) | |
225 return min; | |
226 // If the limit type is integer, we might get better performance by | |
227 // casting |value| (as opposed to |doubleValue|) to the limit type. | |
228 return std::numeric_limits<LimitType>::is_integer | |
229 ? static_cast<LimitType>(value) | |
230 : static_cast<LimitType>(doubleValue); | |
231 } | |
232 }; | |
233 | |
234 // The unspecialized version of this templated class handles clamping to | |
235 // anything other than [unsigned] long long int limits. It simply uses the | |
236 // class above to toggle between the "fast" and "safe" clamp implementations. | |
237 template <typename LimitType, typename ValueType> | |
238 class ClampToHelper { | |
239 public: | |
240 static inline LimitType clampTo(ValueType value, | |
241 LimitType min, | |
242 LimitType max) { | |
243 // We only use clampToDirectComparison() when the integerness and | |
244 // signedness of the two types matches. | |
245 // | |
246 // If the integerness of the types doesn't match, then at best | |
247 // clampToDirectComparison() won't be much more efficient than the | |
248 // cast-everything-to-double method, since we'll need to convert to | |
249 // floating point anyway; at worst, we risk incorrect results when | |
250 // clamping a float to a 32-bit integral type due to potential precision | |
251 // loss. | |
252 // | |
253 // If the signedness doesn't match, clampToDirectComparison() will | |
254 // produce warnings about comparing signed vs. unsigned, which are apt | |
255 // since negative signed values will be converted to large unsigned ones | |
256 // and we'll get incorrect results. | |
257 return ClampToNonLongLongHelper < | |
258 std::numeric_limits<LimitType>::is_integer == | |
259 std::numeric_limits<ValueType>::is_integer && | |
260 std::numeric_limits<LimitType>::is_signed == | |
261 std::numeric_limits<ValueType>::is_signed, | |
262 LimitType, ValueType > ::clampTo(value, min, max); | |
263 } | |
264 }; | |
265 | |
266 // Clamping to [unsigned] long long int limits requires more care. These may | |
267 // not be accurately representable as doubles, so instead we cast |value| to the | |
268 // limit type. But that cast is undefined if |value| is floating point and | |
269 // outside the representable range of the limit type, so we also have to check | |
270 // for that case explicitly. | |
271 template <typename ValueType> | |
272 class ClampToHelper<long long int, ValueType> { | |
273 STATIC_ONLY(ClampToHelper); | |
274 | |
275 public: | |
276 static inline long long int clampTo(ValueType value, | |
277 long long int min, | |
278 long long int max) { | |
279 if (!std::numeric_limits<ValueType>::is_integer) { | |
280 if (value > 0) { | |
281 if (static_cast<double>(value) >= | |
282 static_cast<double>(std::numeric_limits<long long int>::max())) | |
283 return max; | |
284 } else if (static_cast<double>(value) <= | |
285 static_cast<double>( | |
286 std::numeric_limits<long long int>::min())) { | |
287 return min; | |
288 } | |
289 } | |
290 // Note: If |value| were unsigned long long int, it could be larger than | |
291 // the largest long long int, and this code would be wrong; we handle | |
292 // this case with a separate full specialization below. | |
293 return clampToDirectComparison(static_cast<long long int>(value), min, max); | |
294 } | |
295 }; | |
296 | |
297 // This specialization handles the case where the above partial specialization | |
298 // would be potentially incorrect. | |
299 template <> | |
300 class ClampToHelper<long long int, unsigned long long int> { | |
301 STATIC_ONLY(ClampToHelper); | |
302 | |
303 public: | |
304 static inline long long int clampTo(unsigned long long int value, | |
305 long long int min, | |
306 long long int max) { | |
307 if (max <= 0 || value >= static_cast<unsigned long long int>(max)) | |
308 return max; | |
309 const long long int longLongValue = static_cast<long long int>(value); | |
310 return (longLongValue <= min) ? min : longLongValue; | |
311 } | |
312 }; | |
313 | |
314 // This is similar to the partial specialization that clamps to long long int, | |
315 // but because the lower-bound check is done for integer value types as well, we | |
316 // don't need a <unsigned long long int, long long int> full specialization. | |
317 template <typename ValueType> | |
318 class ClampToHelper<unsigned long long int, ValueType> { | |
319 STATIC_ONLY(ClampToHelper); | |
320 | |
321 public: | |
322 static inline unsigned long long int clampTo(ValueType value, | |
323 unsigned long long int min, | |
324 unsigned long long int max) { | |
325 if (value <= 0) | |
326 return min; | |
327 if (!std::numeric_limits<ValueType>::is_integer) { | |
328 if (static_cast<double>(value) >= | |
329 static_cast<double>( | |
330 std::numeric_limits<unsigned long long int>::max())) | |
331 return max; | |
332 } | |
333 return clampToDirectComparison(static_cast<unsigned long long int>(value), | |
334 min, max); | |
335 } | |
336 }; | |
337 | |
338 template <typename T> | |
339 inline T defaultMaximumForClamp() { | |
340 return std::numeric_limits<T>::max(); | |
341 } | |
342 // This basically reimplements C++11's std::numeric_limits<T>::lowest(). | |
343 template <typename T> | |
344 inline T defaultMinimumForClamp() { | |
345 return std::numeric_limits<T>::min(); | |
346 } | |
347 template <> | |
348 inline float defaultMinimumForClamp<float>() { | |
349 return -std::numeric_limits<float>::max(); | |
350 } | |
351 template <> | |
352 inline double defaultMinimumForClamp<double>() { | |
353 return -std::numeric_limits<double>::max(); | |
354 } | |
355 | |
356 // And, finally, the actual function for people to call. | |
357 template <typename LimitType, typename ValueType> | |
358 inline LimitType clampTo(ValueType value, | |
359 LimitType min = defaultMinimumForClamp<LimitType>(), | |
360 LimitType max = defaultMaximumForClamp<LimitType>()) { | |
361 DCHECK(!std::isnan(static_cast<double>(value))); | |
362 DCHECK_LE(min, max); // This also ensures |min| and |max| aren't NaN. | |
363 return ClampToHelper<LimitType, ValueType>::clampTo(value, min, max); | |
364 } | |
365 | |
366 inline bool isWithinIntRange(float x) { | |
367 return x > static_cast<float>(std::numeric_limits<int>::min()) && | |
368 x < static_cast<float>(std::numeric_limits<int>::max()); | |
369 } | |
370 | |
371 static size_t greatestCommonDivisor(size_t a, size_t b) { | |
372 return b ? greatestCommonDivisor(b, a % b) : a; | |
373 } | |
374 | |
375 inline size_t lowestCommonMultiple(size_t a, size_t b) { | |
376 return a && b ? a / greatestCommonDivisor(a, b) * b : 0; | |
377 } | |
378 | |
379 #ifndef UINT64_C | |
380 #if COMPILER(MSVC) | |
381 #define UINT64_C(c) c##ui64 | |
382 #else | |
383 #define UINT64_C(c) c##ull | |
384 #endif | |
385 #endif | |
386 | |
387 // Calculate d % 2^{64}. | |
388 inline void doubleToInteger(double d, unsigned long long& value) { | |
389 if (std::isnan(d) || std::isinf(d)) { | |
390 value = 0; | |
391 } else { | |
392 // -2^{64} < fmodValue < 2^{64}. | |
393 double fmodValue = | |
394 fmod(trunc(d), std::numeric_limits<unsigned long long>::max() + 1.0); | |
395 if (fmodValue >= 0) { | |
396 // 0 <= fmodValue < 2^{64}. | |
397 // 0 <= value < 2^{64}. This cast causes no loss. | |
398 value = static_cast<unsigned long long>(fmodValue); | |
399 } else { | |
400 // -2^{64} < fmodValue < 0. | |
401 // 0 < fmodValueInUnsignedLongLong < 2^{64}. This cast causes no loss. | |
402 unsigned long long fmodValueInUnsignedLongLong = | |
403 static_cast<unsigned long long>(-fmodValue); | |
404 // -1 < (std::numeric_limits<unsigned long long>::max() - | |
405 // fmodValueInUnsignedLongLong) | |
406 // < 2^{64} - 1. | |
407 // 0 < value < 2^{64}. | |
408 value = std::numeric_limits<unsigned long long>::max() - | |
409 fmodValueInUnsignedLongLong + 1; | |
410 } | |
411 } | |
412 } | |
413 | |
414 namespace WTF { | |
415 | |
416 inline unsigned fastLog2(unsigned i) { | |
417 unsigned log2 = 0; | |
418 if (i & (i - 1)) | |
419 log2 += 1; | |
420 if (i >> 16) | |
421 log2 += 16, i >>= 16; | |
422 if (i >> 8) | |
423 log2 += 8, i >>= 8; | |
424 if (i >> 4) | |
425 log2 += 4, i >>= 4; | |
426 if (i >> 2) | |
427 log2 += 2, i >>= 2; | |
428 if (i >> 1) | |
429 log2 += 1; | |
430 return log2; | |
431 } | |
432 | |
433 } // namespace WTF | |
434 | |
435 #endif // #ifndef WTF_MathExtras_h | |
OLD | NEW |