OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 | 25 |
26 #ifndef WTF_MathExtras_h | 26 #ifndef WTF_MathExtras_h |
27 #define WTF_MathExtras_h | 27 #define WTF_MathExtras_h |
28 | 28 |
| 29 #include "wtf/Assertions.h" |
29 #include "wtf/CPU.h" | 30 #include "wtf/CPU.h" |
| 31 #include <algorithm> |
30 #include <cmath> | 32 #include <cmath> |
31 #include <limits> | 33 #include <limits> |
32 | 34 |
33 #if COMPILER(MSVC) | 35 #if COMPILER(MSVC) |
34 #include "wtf/Assertions.h" | |
35 #include <stdint.h> | 36 #include <stdint.h> |
36 #endif | 37 #endif |
37 | 38 |
38 #if OS(OPENBSD) | 39 #if OS(OPENBSD) |
39 #include <sys/types.h> | 40 #include <sys/types.h> |
40 #include <machine/ieee.h> | 41 #include <machine/ieee.h> |
41 #endif | 42 #endif |
42 | 43 |
43 const double piDouble = M_PI; | 44 const double piDouble = M_PI; |
44 const float piFloat = static_cast<float>(M_PI); | 45 const float piFloat = static_cast<float>(M_PI); |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 inline float rad2deg(float r) { return r * 180.0f / piFloat; } | 216 inline float rad2deg(float r) { return r * 180.0f / piFloat; } |
216 inline float deg2grad(float d) { return d * 400.0f / 360.0f; } | 217 inline float deg2grad(float d) { return d * 400.0f / 360.0f; } |
217 inline float grad2deg(float g) { return g * 360.0f / 400.0f; } | 218 inline float grad2deg(float g) { return g * 360.0f / 400.0f; } |
218 inline float turn2deg(float t) { return t * 360.0f; } | 219 inline float turn2deg(float t) { return t * 360.0f; } |
219 inline float deg2turn(float d) { return d / 360.0f; } | 220 inline float deg2turn(float d) { return d / 360.0f; } |
220 inline float rad2grad(float r) { return r * 200.0f / piFloat; } | 221 inline float rad2grad(float r) { return r * 200.0f / piFloat; } |
221 inline float grad2rad(float g) { return g * piFloat / 200.0f; } | 222 inline float grad2rad(float g) { return g * piFloat / 200.0f; } |
222 inline float turn2grad(float t) { return t * 400; } | 223 inline float turn2grad(float t) { return t * 400; } |
223 inline float grad2turn(float g) { return g / 400; } | 224 inline float grad2turn(float g) { return g / 400; } |
224 | 225 |
225 // std::numeric_limits<T>::min() returns the smallest positive value for floatin
g point types | 226 // clampTo() is implemented by templated helper classes (to allow for partial |
226 template<typename T> inline T defaultMinimumForClamp() { return std::numeric_lim
its<T>::min(); } | 227 // template specialization) as well as several helper functions. |
227 template<> inline float defaultMinimumForClamp() { return -std::numeric_limits<f
loat>::max(); } | |
228 template<> inline double defaultMinimumForClamp() { return -std::numeric_limits<
double>::max(); } | |
229 template<typename T> inline T defaultMaximumForClamp() { return std::numeric_lim
its<T>::max(); } | |
230 | 228 |
231 template<typename T> inline T clampTo(double value, T min = defaultMinimumForCla
mp<T>(), T max = defaultMaximumForClamp<T>()) | 229 // This helper function can be called when we know that: |
| 230 // (1) The type signednesses match so the compiler will not produce signed vs. |
| 231 // unsigned warnings |
| 232 // (2) The default type promotions/conversions are sufficient to handle things |
| 233 // correctly |
| 234 template<typename LimitType, typename ValueType> inline LimitType clampToDirectC
omparison(ValueType value, LimitType min, LimitType max) |
232 { | 235 { |
233 if (value >= static_cast<double>(max)) | 236 if (value >= max) |
234 return max; | 237 return max; |
235 if (value <= static_cast<double>(min)) | 238 return (value <= min) ? min : static_cast<LimitType>(value); |
236 return min; | |
237 return static_cast<T>(value); | |
238 } | |
239 template<> inline long long int clampTo(double, long long int, long long int); /
/ clampTo does not support long long ints. | |
240 | |
241 inline int clampToInteger(double value) | |
242 { | |
243 return clampTo<int>(value); | |
244 } | 239 } |
245 | 240 |
246 inline unsigned clampToUnsigned(double value) | 241 // For any floating-point limits, or integral limits smaller than long long, we |
| 242 // can cast the limits to double without losing precision; then the only cases |
| 243 // where |value| can't be represented accurately as a double are the ones where |
| 244 // it's outside the limit range anyway. So doing all comparisons as doubles |
| 245 // will give correct results. |
| 246 // |
| 247 // In some cases, we can get better performance by using |
| 248 // clampToDirectComparison(). We use a templated class to switch between these |
| 249 // two cases (instead of simply using a conditional within one function) in |
| 250 // order to only compile the clampToDirectComparison() code for cases where it |
| 251 // will actually be used; this prevents the compiler from emitting warnings |
| 252 // about unsafe code (even though we wouldn't actually be executing that code). |
| 253 template<bool canUseDirectComparison, typename LimitType, typename ValueType> cl
ass ClampToNonLongLongHelper; |
| 254 template<typename LimitType, typename ValueType> class ClampToNonLongLongHelper<
true, LimitType, ValueType> { |
| 255 public: |
| 256 static inline LimitType clampTo(ValueType value, LimitType min, LimitType ma
x) |
| 257 { |
| 258 return clampToDirectComparison(value, min, max); |
| 259 } |
| 260 }; |
| 261 |
| 262 template<typename LimitType, typename ValueType> class ClampToNonLongLongHelper<
false, LimitType, ValueType> { |
| 263 public: |
| 264 static inline LimitType clampTo(ValueType value, LimitType min, LimitType ma
x) |
| 265 { |
| 266 const double doubleValue = static_cast<double>(value); |
| 267 if (doubleValue >= static_cast<double>(max)) |
| 268 return max; |
| 269 if (doubleValue <= static_cast<double>(min)) |
| 270 return min; |
| 271 // If the limit type is integer, we might get better performance by |
| 272 // casting |value| (as opposed to |doubleValue|) to the limit type. |
| 273 return std::numeric_limits<LimitType>::is_integer ? static_cast<LimitTyp
e>(value) : static_cast<LimitType>(doubleValue); |
| 274 } |
| 275 }; |
| 276 |
| 277 // The unspecialized version of this templated class handles clamping to |
| 278 // anything other than [unsigned] long long int limits. It simply uses the |
| 279 // class above to toggle between the "fast" and "safe" clamp implementations. |
| 280 template<typename LimitType, typename ValueType> class ClampToHelper { |
| 281 public: |
| 282 static inline LimitType clampTo(ValueType value, LimitType min, LimitType ma
x) |
| 283 { |
| 284 // We only use clampToDirectComparison() when the integerness and |
| 285 // signedness of the two types matches. |
| 286 // |
| 287 // If the integerness of the types doesn't match, then at best |
| 288 // clampToDirectComparison() won't be much more efficient than the |
| 289 // cast-everything-to-double method, since we'll need to convert to |
| 290 // floating point anyway; at worst, we risk incorrect results when |
| 291 // clamping a float to a 32-bit integral type due to potential precision |
| 292 // loss. |
| 293 // |
| 294 // If the signedness doesn't match, clampToDirectComparison() will |
| 295 // produce warnings about comparing signed vs. unsigned, which are apt |
| 296 // since negative signed values will be converted to large unsigned ones |
| 297 // and we'll get incorrect results. |
| 298 return ClampToNonLongLongHelper<std::numeric_limits<LimitType>::is_integ
er == std::numeric_limits<ValueType>::is_integer && std::numeric_limits<LimitTyp
e>::is_signed == std::numeric_limits<ValueType>::is_signed, LimitType, ValueType
>::clampTo(value, min, max); |
| 299 } |
| 300 }; |
| 301 |
| 302 // Clamping to [unsigned] long long int limits requires more care. These may |
| 303 // not be accurately representable as doubles, so instead we cast |value| to the |
| 304 // limit type. But that cast is undefined if |value| is floating point and |
| 305 // outside the representable range of the limit type, so we also have to check |
| 306 // for that case explicitly. |
| 307 template<typename ValueType> class ClampToHelper<long long int, ValueType> { |
| 308 public: |
| 309 static inline long long int clampTo(ValueType value, long long int min, long
long int max) |
| 310 { |
| 311 if (!std::numeric_limits<ValueType>::is_integer) { |
| 312 if (value > 0) { |
| 313 if (static_cast<double>(value) >= static_cast<double>(std::numer
ic_limits<long long int>::max())) |
| 314 return max; |
| 315 } else if (static_cast<double>(value) <= static_cast<double>(std::nu
meric_limits<long long int>::min())) { |
| 316 return min; |
| 317 } |
| 318 } |
| 319 // Note: If |value| were unsigned long long int, it could be larger than |
| 320 // the largest long long int, and this code would be wrong; we handle |
| 321 // this case with a separate full specialization below. |
| 322 return clampToDirectComparison(static_cast<long long int>(value), min, m
ax); |
| 323 } |
| 324 }; |
| 325 |
| 326 // This specialization handles the case where the above partial specialization |
| 327 // would be potentially incorrect. |
| 328 template<> class ClampToHelper<long long int, unsigned long long int> { |
| 329 public: |
| 330 static inline long long int clampTo(unsigned long long int value, long long
int min, long long int max) |
| 331 { |
| 332 if (max <= 0 || value >= static_cast<unsigned long long int>(max)) |
| 333 return max; |
| 334 const long long int longLongValue = static_cast<long long int>(value); |
| 335 return (longLongValue <= min) ? min : longLongValue; |
| 336 } |
| 337 }; |
| 338 |
| 339 // This is similar to the partial specialization that clamps to long long int, |
| 340 // but because the lower-bound check is done for integer value types as well, we |
| 341 // don't need a <unsigned long long int, long long int> full specialization. |
| 342 template<typename ValueType> class ClampToHelper<unsigned long long int, ValueTy
pe> { |
| 343 public: |
| 344 static inline unsigned long long int clampTo(ValueType value, unsigned long
long int min, unsigned long long int max) |
| 345 { |
| 346 if (value <= 0) |
| 347 return min; |
| 348 if (!std::numeric_limits<ValueType>::is_integer) { |
| 349 if (static_cast<double>(value) >= static_cast<double>(std::numeric_l
imits<unsigned long long int>::max())) |
| 350 return max; |
| 351 } |
| 352 return clampToDirectComparison(static_cast<unsigned long long int>(value
), min, max); |
| 353 } |
| 354 }; |
| 355 |
| 356 // This basically reimplements C++11's std::numeric_limits<T>::lowest(). |
| 357 template<typename T> inline T defaultMinimumForClamp() { return std::numeric_lim
its<T>::min(); } |
| 358 template<> inline float defaultMinimumForClamp<float>() { return -std::numeric_l
imits<float>::max(); } |
| 359 template<> inline double defaultMinimumForClamp<double>() { return -std::numeric
_limits<double>::max(); } |
| 360 |
| 361 // And, finally, the actual function for people to call. |
| 362 template<typename LimitType, typename ValueType> inline LimitType clampTo(ValueT
ype value, LimitType min = defaultMinimumForClamp<LimitType>(), LimitType max =
std::numeric_limits<LimitType>::max()) |
247 { | 363 { |
248 return clampTo<unsigned>(value); | 364 ASSERT(!std::isnan(static_cast<double>(value))); |
249 } | 365 ASSERT(min <= max); // This also ensures |min| and |max| aren't NaN. |
250 | 366 return ClampToHelper<LimitType, ValueType>::clampTo(value, min, max); |
251 inline float clampToFloat(double value) | |
252 { | |
253 return clampTo<float>(value); | |
254 } | |
255 | |
256 inline int clampToPositiveInteger(double value) | |
257 { | |
258 return clampTo<int>(value, 0); | |
259 } | |
260 | |
261 inline int clampToInteger(float value) | |
262 { | |
263 return clampTo<int>(value); | |
264 } | |
265 | |
266 inline 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 } | 367 } |
274 | 368 |
275 inline bool isWithinIntRange(float x) | 369 inline bool isWithinIntRange(float x) |
276 { | 370 { |
277 return x > static_cast<float>(std::numeric_limits<int>::min()) && x < static
_cast<float>(std::numeric_limits<int>::max()); | 371 return x > static_cast<float>(std::numeric_limits<int>::min()) && x < static
_cast<float>(std::numeric_limits<int>::max()); |
278 } | 372 } |
279 | 373 |
280 static size_t greatestCommonDivisor(size_t a, size_t b) | 374 static size_t greatestCommonDivisor(size_t a, size_t b) |
281 { | 375 { |
282 return b ? greatestCommonDivisor(b, a % b) : a; | 376 return b ? greatestCommonDivisor(b, a % b) : a; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 if (i >> 2) | 428 if (i >> 2) |
335 log2 += 2, i >>= 2; | 429 log2 += 2, i >>= 2; |
336 if (i >> 1) | 430 if (i >> 1) |
337 log2 += 1; | 431 log2 += 1; |
338 return log2; | 432 return log2; |
339 } | 433 } |
340 | 434 |
341 } // namespace WTF | 435 } // namespace WTF |
342 | 436 |
343 #endif // #ifndef WTF_MathExtras_h | 437 #endif // #ifndef WTF_MathExtras_h |
OLD | NEW |