summaryrefslogtreecommitdiff
path: root/Source/WTF/wtf/MathExtras.h
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WTF/wtf/MathExtras.h
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WTF/wtf/MathExtras.h')
-rw-r--r--Source/WTF/wtf/MathExtras.h184
1 files changed, 124 insertions, 60 deletions
diff --git a/Source/WTF/wtf/MathExtras.h b/Source/WTF/wtf/MathExtras.h
index 716f512e8..948c48ffa 100644
--- a/Source/WTF/wtf/MathExtras.h
+++ b/Source/WTF/wtf/MathExtras.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2013, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -69,17 +69,10 @@ const float piOverFourFloat = static_cast<float>(M_PI_4);
#ifndef M_SQRT2
const double sqrtOfTwoDouble = 1.41421356237309504880;
+const float sqrtOfTwoFloat = 1.41421356237309504880f;
#else
const double sqrtOfTwoDouble = M_SQRT2;
-#endif
-
-#if OS(DARWIN)
-
-// Work around a bug in the Mac OS X libc where ceil(-0.1) return +0.
-inline double wtf_ceil(double x) { return copysign(ceil(x), x); }
-
-#define ceil(x) wtf_ceil(x)
-
+const float sqrtOfTwoFloat = static_cast<float>(M_SQRT2);
#endif
#if OS(SOLARIS)
@@ -100,21 +93,6 @@ inline bool isinf(double x) { return !finite(x) && !isnand(x); }
#endif
-#if OS(OPENBSD)
-
-namespace std {
-
-#ifndef isfinite
-inline bool isfinite(double x) { return finite(x); }
-#endif
-#ifndef signbit
-inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x; return p->dbl_sign; }
-#endif
-
-} // namespace std
-
-#endif
-
#if COMPILER(MSVC)
// Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN instead of specific values.
@@ -140,37 +118,7 @@ extern "C" inline double wtf_atan2(double x, double y)
return result;
}
-// Work around a bug in the Microsoft CRT, where fmod(x, +-infinity) yields NaN instead of x.
-extern "C" inline double wtf_fmod(double x, double y) { return (!std::isinf(x) && std::isinf(y)) ? x : fmod(x, y); }
-
-// Work around a bug in the Microsoft CRT, where pow(NaN, 0) yields NaN instead of 1.
-extern "C" inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); }
-
#define atan2(x, y) wtf_atan2(x, y)
-#define fmod(x, y) wtf_fmod(x, y)
-#define pow(x, y) wtf_pow(x, y)
-
-// MSVC's math functions do not bring lrint.
-inline long int lrint(double flt)
-{
- int64_t intgr;
-#if CPU(X86)
- __asm {
- fld flt
- fistp intgr
- };
-#else
- ASSERT(std::isfinite(flt));
- double rounded = round(flt);
- intgr = static_cast<int64_t>(rounded);
- // If the fractional part is exactly 0.5, we need to check whether
- // the rounded result is even. If it is not we need to add 1 to
- // negative values and subtract one from positive values.
- if ((fabs(intgr - flt) == 0.5) & intgr)
- intgr -= ((intgr >> 62) | 1); // 1 with the sign of result, i.e. -1 or 1.
-#endif
- return static_cast<long int>(intgr);
-}
#endif // COMPILER(MSVC)
@@ -233,9 +181,12 @@ inline int clampToInteger(float value)
return clampTo<int>(value);
}
-inline int clampToInteger(unsigned x)
+template<typename T>
+inline int clampToInteger(T x)
{
- const unsigned intMax = static_cast<unsigned>(std::numeric_limits<int>::max());
+ static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
+
+ const T intMax = static_cast<unsigned>(std::numeric_limits<int>::max());
if (x >= intMax)
return std::numeric_limits<int>::max();
@@ -247,6 +198,15 @@ inline bool isWithinIntRange(float x)
return x > static_cast<float>(std::numeric_limits<int>::min()) && x < static_cast<float>(std::numeric_limits<int>::max());
}
+inline float normalizedFloat(float value)
+{
+ if (value > 0 && value < std::numeric_limits<float>::min())
+ return std::numeric_limits<float>::min();
+ if (value < 0 && value > -std::numeric_limits<float>::min())
+ return -std::numeric_limits<float>::min();
+ return value;
+}
+
template<typename T> inline bool hasOneBitSet(T value)
{
return !((value - 1) & value) && value;
@@ -264,9 +224,11 @@ template<typename T> inline bool hasTwoOrMoreBitsSet(T value)
template <typename T> inline unsigned getLSBSet(T value)
{
+ typedef typename std::make_unsigned<T>::type UnsignedT;
unsigned result = 0;
- while (value >>= 1)
+ UnsignedT unsignedValue = static_cast<UnsignedT>(value);
+ while (unsignedValue >>= 1)
++result;
return result;
@@ -412,6 +374,108 @@ inline unsigned fastLog2(unsigned i)
return log2;
}
+inline unsigned fastLog2(uint64_t value)
+{
+ unsigned high = static_cast<unsigned>(value >> 32);
+ if (high)
+ return fastLog2(high) + 32;
+ return fastLog2(static_cast<unsigned>(value));
+}
+
+template <typename T>
+inline typename std::enable_if<std::is_floating_point<T>::value, T>::type safeFPDivision(T u, T v)
+{
+ // Protect against overflow / underflow.
+ if (v < 1 && u > v * std::numeric_limits<T>::max())
+ return std::numeric_limits<T>::max();
+ if (v > 1 && u < v * std::numeric_limits<T>::min())
+ return 0;
+ return u / v;
+}
+
+// Floating point numbers comparison:
+// u is "essentially equal" [1][2] to v if: | u - v | / |u| <= e and | u - v | / |v| <= e
+//
+// [1] Knuth, D. E. "Accuracy of Floating Point Arithmetic." The Art of Computer Programming. 3rd ed. Vol. 2.
+// Boston: Addison-Wesley, 1998. 229-45.
+// [2] http://www.boost.org/doc/libs/1_34_0/libs/test/doc/components/test_tools/floating_point_comparison.html
+template <typename T>
+inline typename std::enable_if<std::is_floating_point<T>::value, bool>::type areEssentiallyEqual(T u, T v, T epsilon = std::numeric_limits<T>::epsilon())
+{
+ if (u == v)
+ return true;
+
+ const T delta = std::abs(u - v);
+ return safeFPDivision(delta, std::abs(u)) <= epsilon && safeFPDivision(delta, std::abs(v)) <= epsilon;
+}
+
+// Match behavior of Math.min, where NaN is returned if either argument is NaN.
+template <typename T>
+inline typename std::enable_if<std::is_floating_point<T>::value, T>::type nanPropagatingMin(T a, T b)
+{
+ return std::isnan(a) || std::isnan(b) ? std::numeric_limits<T>::quiet_NaN() : std::min(a, b);
+}
+
+// Match behavior of Math.max, where NaN is returned if either argument is NaN.
+template <typename T>
+inline typename std::enable_if<std::is_floating_point<T>::value, T>::type nanPropagatingMax(T a, T b)
+{
+ return std::isnan(a) || std::isnan(b) ? std::numeric_limits<T>::quiet_NaN() : std::max(a, b);
+}
+
+inline bool isIntegral(float value)
+{
+ return static_cast<int>(value) == value;
+}
+
+template<typename T>
+inline void incrementWithSaturation(T& value)
+{
+ if (value != std::numeric_limits<T>::max())
+ value++;
+}
+
+template<typename T>
+inline T leftShiftWithSaturation(T value, unsigned shiftAmount, T max = std::numeric_limits<T>::max())
+{
+ T result = value << shiftAmount;
+ // We will have saturated if shifting right doesn't recover the original value.
+ if (result >> shiftAmount != value)
+ return max;
+ if (result > max)
+ return max;
+ return result;
+}
+
+// Check if two ranges overlap assuming that neither range is empty.
+template<typename T>
+inline bool nonEmptyRangesOverlap(T leftMin, T leftMax, T rightMin, T rightMax)
+{
+ ASSERT(leftMin < leftMax);
+ ASSERT(rightMin < rightMax);
+
+ return leftMax > rightMin && rightMax > leftMin;
+}
+
+// Pass ranges with the min being inclusive and the max being exclusive. For example, this should
+// return false:
+//
+// rangesOverlap(0, 8, 8, 16)
+template<typename T>
+inline bool rangesOverlap(T leftMin, T leftMax, T rightMin, T rightMax)
+{
+ ASSERT(leftMin <= leftMax);
+ ASSERT(rightMin <= rightMax);
+
+ // Empty ranges interfere with nothing.
+ if (leftMin == leftMax)
+ return false;
+ if (rightMin == rightMax)
+ return false;
+
+ return nonEmptyRangesOverlap(leftMin, leftMax, rightMin, rightMax);
+}
+
} // namespace WTF
#endif // #ifndef WTF_MathExtras_h