Modified: trunk/Source/WTF/wtf/MathExtras.h (241191 => 241192)
--- trunk/Source/WTF/wtf/MathExtras.h 2019-02-08 08:48:35 UTC (rev 241191)
+++ trunk/Source/WTF/wtf/MathExtras.h 2019-02-08 09:46:36 UTC (rev 241192)
@@ -123,16 +123,111 @@
template<> constexpr double defaultMinimumForClamp() { return -std::numeric_limits<double>::max(); }
template<typename T> constexpr T defaultMaximumForClamp() { return std::numeric_limits<T>::max(); }
-template<typename T> inline T clampTo(double value, T min = defaultMinimumForClamp<T>(), T max = defaultMaximumForClamp<T>())
+// Same type in and out.
+template<typename TargetType, typename SourceType>
+typename std::enable_if<std::is_same<TargetType, SourceType>::value, TargetType>::type
+clampTo(SourceType value, TargetType min = defaultMinimumForClamp<TargetType>(), TargetType max = defaultMaximumForClamp<TargetType>())
{
- if (value >= static_cast<double>(max))
+ if (value >= max)
return max;
- if (value <= static_cast<double>(min))
+ if (value <= min)
return min;
- return static_cast<T>(value);
+ return value;
}
-template<> inline long long int clampTo(double, long long int, long long int); // clampTo does not support long long ints.
+// Floating point source.
+template<typename TargetType, typename SourceType>
+typename std::enable_if<!std::is_same<TargetType, SourceType>::value
+ && std::is_floating_point<SourceType>::value
+ && !(std::is_floating_point<TargetType>::value && sizeof(TargetType) > sizeof(SourceType)), TargetType>::type
+clampTo(SourceType value, TargetType min = defaultMinimumForClamp<TargetType>(), TargetType max = defaultMaximumForClamp<TargetType>())
+{
+ if (value >= static_cast<SourceType>(max))
+ return max;
+ if (value <= static_cast<SourceType>(min))
+ return min;
+ return static_cast<TargetType>(value);
+}
+
+template<typename TargetType, typename SourceType>
+typename std::enable_if<!std::is_same<TargetType, SourceType>::value
+ && std::is_floating_point<SourceType>::value
+ && std::is_floating_point<TargetType>::value
+ && (sizeof(TargetType) > sizeof(SourceType)), TargetType>::type
+clampTo(SourceType value, TargetType min = defaultMinimumForClamp<TargetType>(), TargetType max = defaultMaximumForClamp<TargetType>())
+{
+ TargetType convertedValue = static_cast<TargetType>(value);
+ if (convertedValue >= max)
+ return max;
+ if (convertedValue <= min)
+ return min;
+ return convertedValue;
+}
+
+// Source and Target have the same sign and Source is larger or equal to Target
+template<typename TargetType, typename SourceType>
+typename std::enable_if<!std::is_same<TargetType, SourceType>::value
+ && std::numeric_limits<SourceType>::is_integer
+ && std::numeric_limits<TargetType>::is_integer
+ && std::numeric_limits<TargetType>::is_signed == std::numeric_limits<SourceType>::is_signed
+ && sizeof(SourceType) >= sizeof(TargetType), TargetType>::type
+clampTo(SourceType value, TargetType min = defaultMinimumForClamp<TargetType>(), TargetType max = defaultMaximumForClamp<TargetType>())
+{
+ if (value >= static_cast<SourceType>(max))
+ return max;
+ if (value <= static_cast<SourceType>(min))
+ return min;
+ return static_cast<TargetType>(value);
+}
+
+// Clamping a unsigned integer to the max signed value.
+template<typename TargetType, typename SourceType>
+typename std::enable_if<!std::is_same<TargetType, SourceType>::value
+ && std::numeric_limits<SourceType>::is_integer
+ && std::numeric_limits<TargetType>::is_integer
+ && std::numeric_limits<TargetType>::is_signed
+ && !std::numeric_limits<SourceType>::is_signed
+ && sizeof(SourceType) >= sizeof(TargetType), TargetType>::type
+clampTo(SourceType value)
+{
+ TargetType max = std::numeric_limits<TargetType>::max();
+ if (value >= static_cast<SourceType>(max))
+ return max;
+ return static_cast<TargetType>(value);
+}
+
+// Clamping a signed integer into a valid unsigned integer.
+template<typename TargetType, typename SourceType>
+typename std::enable_if<!std::is_same<TargetType, SourceType>::value
+ && std::numeric_limits<SourceType>::is_integer
+ && std::numeric_limits<TargetType>::is_integer
+ && !std::numeric_limits<TargetType>::is_signed
+ && std::numeric_limits<SourceType>::is_signed
+ && sizeof(SourceType) == sizeof(TargetType), TargetType>::type
+clampTo(SourceType value)
+{
+ if (value < 0)
+ return 0;
+ return static_cast<TargetType>(value);
+}
+
+template<typename TargetType, typename SourceType>
+typename std::enable_if<!std::is_same<TargetType, SourceType>::value
+ && std::numeric_limits<SourceType>::is_integer
+ && std::numeric_limits<TargetType>::is_integer
+ && !std::numeric_limits<TargetType>::is_signed
+ && std::numeric_limits<SourceType>::is_signed
+ && (sizeof(SourceType) > sizeof(TargetType)), TargetType>::type
+clampTo(SourceType value)
+{
+ if (value < 0)
+ return 0;
+ TargetType max = std::numeric_limits<TargetType>::max();
+ if (value >= static_cast<SourceType>(max))
+ return max;
+ return static_cast<TargetType>(value);
+}
+
inline int clampToInteger(double value)
{
return clampTo<int>(value);
Modified: trunk/Source/WebCore/rendering/style/RenderStyle.h (241191 => 241192)
--- trunk/Source/WebCore/rendering/style/RenderStyle.h 2019-02-08 08:48:35 UTC (rev 241191)
+++ trunk/Source/WebCore/rendering/style/RenderStyle.h 2019-02-08 09:46:36 UTC (rev 241192)
@@ -1055,7 +1055,7 @@
void setTextStrokeWidth(float w) { SET_VAR(m_rareInheritedData, textStrokeWidth, w); }
void setTextFillColor(const Color& c) { SET_VAR(m_rareInheritedData, textFillColor, c); }
void setCaretColor(const Color& c) { SET_VAR(m_rareInheritedData, caretColor, c); }
- void setOpacity(float f) { float v = clampTo<float>(f, 0, 1); SET_VAR(m_rareNonInheritedData, opacity, v); }
+ void setOpacity(float f) { float v = clampTo<float>(f, 0.f, 1.f); SET_VAR(m_rareNonInheritedData, opacity, v); }
void setAppearance(ControlPart a) { SET_VAR(m_rareNonInheritedData, appearance, a); }
// For valid values of box-align see http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/#alignment
void setBoxAlign(BoxAlignment a) { SET_NESTED_VAR(m_rareNonInheritedData, deprecatedFlexibleBox, align, static_cast<unsigned>(a)); }
@@ -2196,7 +2196,7 @@
inline void RenderStyle::setShapeImageThreshold(float shapeImageThreshold)
{
- float clampedShapeImageThreshold = clampTo<float>(shapeImageThreshold, 0, 1);
+ float clampedShapeImageThreshold = clampTo<float>(shapeImageThreshold, 0.f, 1.f);
SET_VAR(m_rareNonInheritedData, shapeImageThreshold, clampedShapeImageThreshold);
}
Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/MathExtras.cpp (241191 => 241192)
--- trunk/Tools/TestWebKitAPI/Tests/WTF/MathExtras.cpp 2019-02-08 08:48:35 UTC (rev 241191)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/MathExtras.cpp 2019-02-08 09:46:36 UTC (rev 241192)
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2012 Intel Corporation
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -174,6 +175,238 @@
EXPECT_EQ(clampTo<unsigned>(-1), 0u);
}
+#if !COMPILER(MSVC)
+template<typename TargetType, typename SourceType>
+static void testClampFloatingPointToFloatingPoint()
+{
+ // No clamping.
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(0)), static_cast<TargetType>(0));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(1)), static_cast<TargetType>(1));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(1.5)), static_cast<TargetType>(1.5));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(-1)), static_cast<TargetType>(-1));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(-1.5)), static_cast<TargetType>(-1.5));
+
+ // Explicit boundaries, clamped or not.
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(-42), static_cast<SourceType>(-42.5)), static_cast<TargetType>(-42));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(-43), static_cast<SourceType>(-42.5)), static_cast<TargetType>(static_cast<SourceType>(-42.5)));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(42), static_cast<SourceType>(41), static_cast<SourceType>(42.5)), static_cast<TargetType>(42));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(43), static_cast<SourceType>(41), static_cast<SourceType>(42.5)), static_cast<TargetType>(static_cast<SourceType>(42.5)));
+
+ // Integer bounds.
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::max()) + 1), static_cast<TargetType>(std::numeric_limits<int32_t>::max()) + 1);
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int64_t>::max())), static_cast<TargetType>(std::numeric_limits<int64_t>::max()));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::max()) + 1), static_cast<TargetType>(std::numeric_limits<int32_t>::max()) + 1);
+
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::min())), static_cast<TargetType>(std::numeric_limits<int32_t>::min()));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int64_t>::min())), static_cast<TargetType>(std::numeric_limits<int64_t>::min()));
+
+ if (std::is_same<TargetType, double>::value && std::is_same<SourceType, float>::value) {
+ // If the source is float and target is double, the input of those cases has lost bits in float.
+ // In that case, we also round the expectation to float.
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::max())), static_cast<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::max())));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::min()) - 1), static_cast<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::min()) - 1));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::min()) - 1), static_cast<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::min()) - 1));
+ } else {
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::max())), static_cast<TargetType>(std::numeric_limits<int32_t>::max()));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::min()) - 1), static_cast<TargetType>(std::numeric_limits<int32_t>::min()) - 1);
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::min()) - 1), static_cast<TargetType>(std::numeric_limits<int32_t>::min()) - 1);
+ }
+
+ // At the limit.
+ EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<TargetType>::max()), std::numeric_limits<TargetType>::max());
+ EXPECT_EQ(clampTo<TargetType>(-std::numeric_limits<TargetType>::max()), -std::numeric_limits<TargetType>::max());
+
+ // At Epsilon from the limit.
+ TargetType epsilon = std::numeric_limits<TargetType>::epsilon();
+ EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<TargetType>::max() - epsilon), std::numeric_limits<TargetType>::max() - epsilon);
+ EXPECT_EQ(clampTo<TargetType>(-std::numeric_limits<TargetType>::max() + epsilon), -std::numeric_limits<TargetType>::max() + epsilon);
+
+ // Infinity.
+ EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::infinity()), std::numeric_limits<TargetType>::max());
+ EXPECT_EQ(clampTo<TargetType>(-std::numeric_limits<SourceType>::infinity()), -std::numeric_limits<TargetType>::max());
+}
+
+TEST(WTF, clampFloatingPointToFloatingPoint)
+{
+ testClampFloatingPointToFloatingPoint<float, float>();
+ testClampFloatingPointToFloatingPoint<double, double>();
+
+ testClampFloatingPointToFloatingPoint<double, float>();
+ testClampFloatingPointToFloatingPoint<float, double>();
+
+ // Large double into smaller float.
+ EXPECT_EQ(clampTo<float>(static_cast<double>(std::numeric_limits<float>::max())), std::numeric_limits<float>::max());
+ EXPECT_EQ(clampTo<float>(-static_cast<double>(std::numeric_limits<float>::max())), -std::numeric_limits<float>::max());
+ EXPECT_EQ(clampTo<float>(static_cast<double>(std::numeric_limits<float>::max()) + 1), std::numeric_limits<float>::max());
+ EXPECT_EQ(clampTo<float>(-static_cast<double>(std::numeric_limits<float>::max()) - 1), -std::numeric_limits<float>::max());
+ EXPECT_EQ(clampTo<float>(std::numeric_limits<double>::max()), std::numeric_limits<float>::max());
+ EXPECT_EQ(clampTo<float>(-std::numeric_limits<double>::max()), -std::numeric_limits<float>::max());
+
+ float floatEspilon = std::numeric_limits<float>::epsilon();
+ double doubleEspilon = std::numeric_limits<double>::epsilon();
+ EXPECT_EQ(clampTo<float>(static_cast<double>(std::numeric_limits<float>::max()) + doubleEspilon), std::numeric_limits<float>::max());
+ EXPECT_EQ(clampTo<float>(static_cast<double>(std::numeric_limits<float>::max()) - doubleEspilon), std::numeric_limits<float>::max());
+ EXPECT_EQ(clampTo<float>(static_cast<double>(std::numeric_limits<float>::max()) + floatEspilon), std::numeric_limits<float>::max());
+ EXPECT_EQ(clampTo<float>(static_cast<double>(std::numeric_limits<float>::max()) - floatEspilon), std::numeric_limits<float>::max() - floatEspilon);
+}
+#endif // !COMPILER(MSVC)
+
+template<typename FloatingPointType>
+static void testClampFloatingPointToInteger()
+{
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(0)), 0);
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(1)), 1);
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(-1)), -1);
+ if (std::is_same<FloatingPointType, double>::value)
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::max()) - 1.f), std::numeric_limits<int32_t>::max() - 1);
+ else
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::max()) - 1.f), std::numeric_limits<int32_t>::max());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::max())), std::numeric_limits<int32_t>::max());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::max()) + 1.f), std::numeric_limits<int32_t>::max());
+
+ if (std::is_same<FloatingPointType, double>::value)
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::min()) + 1.f), std::numeric_limits<int32_t>::min() + 1);
+ else
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::min()) + 1.f), std::numeric_limits<int32_t>::min());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::min())), std::numeric_limits<int32_t>::min());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::min()) - 1.f), std::numeric_limits<int32_t>::min());
+
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<uint32_t>::max())), std::numeric_limits<int32_t>::max());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<uint32_t>::max()) + 1.f), std::numeric_limits<int32_t>::max());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<uint32_t>::min())), 0.f);
+
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int64_t>::max())), std::numeric_limits<int32_t>::max());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int64_t>::max()) + 1.f), std::numeric_limits<int32_t>::max());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int64_t>::min())), std::numeric_limits<int32_t>::min());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int64_t>::min()) - 1.f), std::numeric_limits<int32_t>::min());
+
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<uint64_t>::max())), std::numeric_limits<int32_t>::max());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<uint64_t>::max()) + 1.f), std::numeric_limits<int32_t>::max());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<uint64_t>::min())), 0.f);
+
+ FloatingPointType epsilon = std::numeric_limits<FloatingPointType>::epsilon();
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::max()) - epsilon), std::numeric_limits<int32_t>::max());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::max()) + epsilon), std::numeric_limits<int32_t>::max());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::min()) - epsilon), std::numeric_limits<int32_t>::min());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::min()) + epsilon), std::numeric_limits<int32_t>::min());
+
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<FloatingPointType>::infinity())), std::numeric_limits<int32_t>::max());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(-std::numeric_limits<FloatingPointType>::infinity())), std::numeric_limits<int32_t>::min());
+}
+
+TEST(WTF, clampFloatToInt)
+{
+ testClampFloatingPointToInteger<float>();
+ testClampFloatingPointToInteger<double>();
+
+ // 2**24 = 16777216, the largest integer representable exactly as float.
+ EXPECT_EQ(clampTo<int32_t>(static_cast<float>(16777215)), 16777215);
+ EXPECT_EQ(clampTo<int32_t>(static_cast<float>(16777216)), 16777216);
+ EXPECT_EQ(clampTo<int32_t>(static_cast<float>(16777217)), 16777216);
+ EXPECT_EQ(clampTo<int32_t>(static_cast<double>(16777216)), 16777216);
+ EXPECT_EQ(clampTo<int32_t>(static_cast<double>(16777217)), 16777217);
+
+ EXPECT_EQ(clampTo<int16_t>(static_cast<float>(16777215)), std::numeric_limits<int16_t>::max());
+ EXPECT_EQ(clampTo<int16_t>(static_cast<float>(16777216)), std::numeric_limits<int16_t>::max());
+ EXPECT_EQ(clampTo<int16_t>(static_cast<float>(16777217)), std::numeric_limits<int16_t>::max());
+
+ // 2**53 = 9007199254740992, the largest integer representable exactly as double.
+ EXPECT_EQ(clampTo<uint64_t>(static_cast<double>(9007199254740991)), static_cast<uint64_t>(9007199254740991));
+ EXPECT_EQ(clampTo<uint64_t>(static_cast<double>(9007199254740992)), static_cast<uint64_t>(9007199254740992));
+ EXPECT_EQ(clampTo<uint64_t>(static_cast<double>(9007199254740993)), static_cast<uint64_t>(9007199254740992));
+
+ EXPECT_EQ(clampTo<int32_t>(static_cast<double>(9007199254740991)), std::numeric_limits<int32_t>::max());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<double>(9007199254740992)), std::numeric_limits<int32_t>::max());
+ EXPECT_EQ(clampTo<int32_t>(static_cast<double>(9007199254740993)), std::numeric_limits<int32_t>::max());
+}
+
+template<typename TargetType, typename SourceType>
+static void testClampSameSignIntegers()
+{
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(0)), static_cast<TargetType>(0));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(1)), static_cast<TargetType>(1));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(-1)), std::numeric_limits<TargetType>::is_signed ? static_cast<TargetType>(-1) : std::numeric_limits<TargetType>::max());
+
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::min())), std::numeric_limits<TargetType>::min());
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::max())), std::numeric_limits<TargetType>::max());
+
+ EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::min()), std::numeric_limits<TargetType>::min());
+ EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::max()), std::numeric_limits<TargetType>::max());
+}
+
+TEST(WTF, clampSameSignIntegers)
+{
+ testClampSameSignIntegers<char, char>();
+ testClampSameSignIntegers<unsigned char, unsigned char>();
+ testClampSameSignIntegers<char, int32_t>();
+ testClampSameSignIntegers<unsigned char, uint32_t>();
+ testClampSameSignIntegers<char, int64_t>();
+ testClampSameSignIntegers<unsigned char, uint64_t>();
+
+ testClampSameSignIntegers<int32_t, int32_t>();
+ testClampSameSignIntegers<uint32_t, uint32_t>();
+ testClampSameSignIntegers<int32_t, int64_t>();
+ testClampSameSignIntegers<uint32_t, uint64_t>();
+ testClampSameSignIntegers<int16_t, int64_t>();
+ testClampSameSignIntegers<uint16_t, uint64_t>();
+}
+
+template<typename TargetType, typename SourceType>
+static void testClampUnsignedToSigned()
+{
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(0)), static_cast<TargetType>(0));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(1)), static_cast<TargetType>(1));
+
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::max()) - 1), std::numeric_limits<TargetType>::max() - 1);
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::max())), std::numeric_limits<TargetType>::max());
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::max()) + 1), std::numeric_limits<TargetType>::max());
+ EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::max()), std::numeric_limits<TargetType>::max());
+ EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::max() - 1), std::numeric_limits<TargetType>::max());
+}
+
+TEST(WTF, clampUnsignedToSigned)
+{
+ testClampUnsignedToSigned<char, unsigned char>();
+ testClampUnsignedToSigned<char, uint32_t>();
+ testClampUnsignedToSigned<int32_t, uint32_t>();
+ testClampUnsignedToSigned<int64_t, uint64_t>();
+ testClampUnsignedToSigned<int32_t, uint64_t>();
+ testClampUnsignedToSigned<int16_t, uint32_t>();
+ testClampUnsignedToSigned<int16_t, uint64_t>();
+}
+
+template<typename TargetType, typename SourceType>
+static void testClampSignedToUnsigned()
+{
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(0)), static_cast<TargetType>(0));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(1)), static_cast<TargetType>(1));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(-1)), static_cast<TargetType>(0));
+
+ if (sizeof(TargetType) < sizeof(SourceType)) {
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::min())), static_cast<TargetType>(0));
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::max()) - 1), std::numeric_limits<TargetType>::max() - 1);
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::max())), std::numeric_limits<TargetType>::max());
+ EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::max()) + 1), std::numeric_limits<TargetType>::max());
+ }
+
+ EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::min()), static_cast<TargetType>(0));
+ if (sizeof(TargetType) < sizeof(SourceType))
+ EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::max()), std::numeric_limits<TargetType>::max());
+ else
+ EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::max()), static_cast<TargetType>(std::numeric_limits<SourceType>::max()));
+}
+
+TEST(WTF, clampSignedToUnsigned)
+{
+ testClampSignedToUnsigned<unsigned char, char>();
+ testClampSignedToUnsigned<unsigned char, int32_t>();
+ testClampSignedToUnsigned<uint32_t, int32_t>();
+ testClampSignedToUnsigned<uint64_t, int64_t>();
+ testClampSignedToUnsigned<uint32_t, int64_t>();
+ testClampSignedToUnsigned<uint16_t, int32_t>();
+ testClampSignedToUnsigned<uint16_t, int64_t>();
+}
+
TEST(WTF, roundUpToPowerOfTwo)
{
EXPECT_EQ(WTF::roundUpToPowerOfTwo(UINT32_MAX), 0U);