Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3332)

Unified Diff: base/numerics/safe_numerics_unittest.cc

Issue 2945433003: Add ClampedNumeric templates (Closed)
Patch Set: final Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/numerics/safe_math_shared_impl.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/numerics/safe_numerics_unittest.cc
diff --git a/base/numerics/safe_numerics_unittest.cc b/base/numerics/safe_numerics_unittest.cc
index ec6d0037c9f0a0285844c179c9a40130fa4f9169..9fd9e8fd18eb0521bad1d2a683b28680a215c9d4 100644
--- a/base/numerics/safe_numerics_unittest.cc
+++ b/base/numerics/safe_numerics_unittest.cc
@@ -22,10 +22,12 @@
using std::numeric_limits;
using base::CheckedNumeric;
+using base::ClampedNumeric;
using base::IsValidForType;
using base::ValueOrDieForType;
using base::ValueOrDefaultForType;
using base::MakeCheckedNum;
+using base::MakeClampedNum;
using base::CheckMax;
using base::CheckMin;
using base::CheckAdd;
@@ -35,9 +37,20 @@ using base::CheckDiv;
using base::CheckMod;
using base::CheckLsh;
using base::CheckRsh;
+using base::ClampMax;
+using base::ClampMin;
+using base::ClampAdd;
+using base::ClampSub;
+using base::ClampMul;
+using base::ClampDiv;
+using base::ClampMod;
+using base::ClampLsh;
+using base::ClampRsh;
+using base::as_unsigned;
using base::checked_cast;
using base::IsValueInRangeForNumericType;
using base::IsValueNegative;
+using base::SaturationDefaultLimits;
using base::SizeT;
using base::StrictNumeric;
using base::MakeStrictNum;
@@ -131,6 +144,17 @@ template <typename U>
U GetNumericValueForTest(const CheckedNumeric<U>& src) {
return src.state_.value();
}
+
+template <typename U>
+U GetNumericValueForTest(const ClampedNumeric<U>& src) {
+ return static_cast<U>(src);
+}
+
+template <typename U>
+U GetNumericValueForTest(const U& src) {
+ return src;
+}
+
} // namespace internal.
} // namespace base.
@@ -145,6 +169,36 @@ struct LogOnFailure {
}
};
+template <typename T>
+constexpr T GetValue(const T& src) {
+ return src;
+}
+
+template <typename T, typename U>
+constexpr T GetValueAsDest(const U& src) {
+ return static_cast<T>(src);
+}
+
+template <typename T>
+constexpr T GetValue(const CheckedNumeric<T>& src) {
+ return src.template ValueOrDie<T, LogOnFailure>();
+}
+
+template <typename T, typename U>
+constexpr T GetValueAsDest(const CheckedNumeric<U>& src) {
+ return src.template ValueOrDie<T, LogOnFailure>();
+}
+
+template <typename T>
+constexpr T GetValue(const ClampedNumeric<T>& src) {
+ return static_cast<T>(src);
+}
+
+template <typename T, typename U>
+constexpr T GetValueAsDest(const ClampedNumeric<U>& src) {
+ return static_cast<T>(src);
+}
+
// Helper macros to wrap displaying the conversion types and line numbers.
#define TEST_EXPECTED_VALIDITY(expected, actual) \
EXPECT_EQ(expected, (actual).template Cast<Dst>().IsValid()) \
@@ -156,12 +210,7 @@ struct LogOnFailure {
// We have to handle promotions, so infer the underlying type below from actual.
#define TEST_EXPECTED_VALUE(expected, actual) \
- EXPECT_EQ(static_cast<typename std::decay<decltype(actual)>::type::type>( \
- expected), \
- ((actual) \
- .template ValueOrDie< \
- typename std::decay<decltype(actual)>::type::type, \
- LogOnFailure>())) \
+ EXPECT_EQ(GetValue(expected), GetValueAsDest<decltype(expected)>(actual)) \
<< "Result test: Value " << GetNumericValueForTest(actual) << " as " \
<< dst << " on line " << line
@@ -190,18 +239,34 @@ static void TestSpecializedArithmetic(
typename std::enable_if<numeric_limits<Dst>::is_integer &&
numeric_limits<Dst>::is_signed,
int>::type = 0) {
- using DstLimits = numeric_limits<Dst>;
+ using DstLimits = SaturationDefaultLimits<Dst>;
TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::lowest()));
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
TEST_EXPECTED_VALUE(DstLimits::max(),
MakeCheckedNum(-DstLimits::max()).Abs());
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(),
+ -ClampedNumeric<Dst>(DstLimits::lowest()));
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(),
+ ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).Abs());
+ TEST_EXPECTED_VALUE(DstLimits::max(),
+ MakeClampedNum(-DstLimits::max()).Abs());
+
TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
DstLimits::lowest());
+ TEST_EXPECTED_VALUE(DstLimits::max() - 1,
+ ClampedNumeric<Dst>(DstLimits::max()) + -1);
+ TEST_EXPECTED_VALUE(DstLimits::Underflow(),
+ ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
+ TEST_EXPECTED_VALUE(
+ DstLimits::Underflow(),
+ ClampedNumeric<Dst>(DstLimits::lowest()) + DstLimits::lowest());
+
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) - -1);
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
@@ -209,7 +274,20 @@ static void TestSpecializedArithmetic(
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
DstLimits::max());
+ TEST_EXPECTED_VALUE(DstLimits::Underflow(),
+ ClampedNumeric<Dst>(DstLimits::lowest()) - 1);
+ TEST_EXPECTED_VALUE(DstLimits::lowest() + 1,
+ ClampedNumeric<Dst>(DstLimits::lowest()) - -1);
+ TEST_EXPECTED_VALUE(
+ DstLimits::Overflow(),
+ ClampedNumeric<Dst>(DstLimits::max()) - DstLimits::lowest());
+ TEST_EXPECTED_VALUE(
+ DstLimits::Underflow(),
+ ClampedNumeric<Dst>(DstLimits::lowest()) - DstLimits::max());
+
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
+ TEST_EXPECTED_VALUE(DstLimits::Underflow(),
+ ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) / -1);
TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
@@ -222,19 +300,42 @@ static void TestSpecializedArithmetic(
CheckedNumeric<Dst>(DstLimits::lowest()) * Dst(1));
TEST_EXPECTED_VALUE(DstLimits::lowest(),
CheckedNumeric<Dst>(1) * Dst(DstLimits::lowest()));
- TEST_EXPECTED_VALUE(DstLimits::lowest(),
- MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
+ TEST_EXPECTED_VALUE(
+ typename std::make_unsigned<Dst>::type(0) - DstLimits::lowest(),
+ MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
TEST_EXPECTED_VALUE(DstLimits::max(),
MakeCheckedNum(DstLimits::max()).UnsignedAbs());
TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).UnsignedAbs());
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(),
+ ClampedNumeric<Dst>(DstLimits::lowest()) / -1);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(-1) / 2);
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(),
+ ClampedNumeric<Dst>(DstLimits::lowest()) * -1);
+ TEST_EXPECTED_VALUE(DstLimits::max(),
+ ClampedNumeric<Dst>(DstLimits::lowest() + 1) * Dst(-1));
+ TEST_EXPECTED_VALUE(DstLimits::max(),
+ ClampedNumeric<Dst>(-1) * Dst(DstLimits::lowest() + 1));
+ TEST_EXPECTED_VALUE(DstLimits::lowest(),
+ ClampedNumeric<Dst>(DstLimits::lowest()) * Dst(1));
+ TEST_EXPECTED_VALUE(DstLimits::lowest(),
+ ClampedNumeric<Dst>(1) * Dst(DstLimits::lowest()));
+ TEST_EXPECTED_VALUE(
+ typename std::make_unsigned<Dst>::type(0) - DstLimits::lowest(),
+ MakeClampedNum(DstLimits::lowest()).UnsignedAbs());
+ TEST_EXPECTED_VALUE(DstLimits::max(),
+ MakeClampedNum(DstLimits::max()).UnsignedAbs());
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0).UnsignedAbs());
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).UnsignedAbs());
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).UnsignedAbs());
+
// Modulus is legal only for integers.
TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-1) % -2);
+ TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % -2);
TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
// Test all the different modulus combinations.
@@ -266,6 +367,44 @@ static void TestSpecializedArithmetic(
0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
+ // Modulus is legal only for integers.
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>() % 1);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
+ TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(-1) % 2);
+ TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(-1) % -2);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 2);
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % 2);
+ // Test all the different modulus combinations.
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % ClampedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, 1 % ClampedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
+ ClampedNumeric<Dst> clamped_dst = 1;
+ TEST_EXPECTED_VALUE(0, clamped_dst %= 1);
+ TEST_EXPECTED_VALUE(Dst(1), ClampedNumeric<Dst>(1) % 0);
+ // Test bit shifts.
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(),
+ ClampedNumeric<Dst>(1)
+ << (IntegerBitsPlusSign<Dst>::value - 1U));
+ TEST_EXPECTED_VALUE(Dst(0), ClampedNumeric<Dst>(0)
+ << (IntegerBitsPlusSign<Dst>::value + 0U));
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(),
+ ClampedNumeric<Dst>(DstLimits::max()) << 1U);
+ TEST_EXPECTED_VALUE(
+ static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2U),
+ ClampedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2U));
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0)
+ << (IntegerBitsPlusSign<Dst>::value - 1U));
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) << 0U);
+ TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) << 1U);
+ TEST_EXPECTED_VALUE(
+ 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value + 0U));
+ TEST_EXPECTED_VALUE(
+ 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
+ TEST_EXPECTED_VALUE(
+ -1, ClampedNumeric<Dst>(-1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
+ TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(DstLimits::lowest()) >>
+ (IntegerBitsPlusSign<Dst>::value - 0U));
+
TestStrictPointerMath<Dst>();
}
@@ -277,7 +416,7 @@ static void TestSpecializedArithmetic(
typename std::enable_if<numeric_limits<Dst>::is_integer &&
!numeric_limits<Dst>::is_signed,
int>::type = 0) {
- using DstLimits = numeric_limits<Dst>;
+ using DstLimits = SaturationDefaultLimits<Dst>;
TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
@@ -296,6 +435,29 @@ static void TestSpecializedArithmetic(
TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
+ TEST_EXPECTED_VALUE(0, -ClampedNumeric<Dst>(DstLimits::lowest()));
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
+ TEST_EXPECTED_VALUE(DstLimits::Underflow(),
+ ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
+ TEST_EXPECTED_VALUE(DstLimits::Underflow(),
+ ClampedNumeric<Dst>(DstLimits::lowest()) - 1);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) / 2);
+ TEST_EXPECTED_VALUE(0,
+ ClampedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
+ TEST_EXPECTED_VALUE(
+ as_unsigned(
+ std::numeric_limits<typename std::make_signed<Dst>::type>::lowest()),
+ ClampedNumeric<typename std::make_signed<Dst>::type>(
+ std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
+ .UnsignedAbs());
+ TEST_EXPECTED_VALUE(DstLimits::lowest(),
+ MakeClampedNum(DstLimits::lowest()).UnsignedAbs());
+ TEST_EXPECTED_VALUE(DstLimits::max(),
+ MakeClampedNum(DstLimits::max()).UnsignedAbs());
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0).UnsignedAbs());
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).UnsignedAbs());
+
// Modulus is legal only for integers.
TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
@@ -350,6 +512,57 @@ static void TestSpecializedArithmetic(
CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0));
+ // Modulus is legal only for integers.
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>() % 1);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) % 2);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 2);
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % 2);
+ // Test all the different modulus combinations.
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % ClampedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, 1 % ClampedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
+ ClampedNumeric<Dst> clamped_dst = 1;
+ TEST_EXPECTED_VALUE(0, clamped_dst %= 1);
+ // Test that div by 0 is avoided but returns invalid result.
+ TEST_EXPECTED_VALUE(Dst(1), ClampedNumeric<Dst>(1) % 0);
+ // Test bit shifts.
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(),
+ ClampedNumeric<Dst>(1)
+ << as_unsigned(IntegerBitsPlusSign<Dst>::value));
+ TEST_EXPECTED_VALUE(Dst(0), ClampedNumeric<Dst>(0) << as_unsigned(
+ IntegerBitsPlusSign<Dst>::value));
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(),
+ ClampedNumeric<Dst>(DstLimits::max()) << 1U);
+ TEST_EXPECTED_VALUE(
+ static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1U),
+ ClampedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1U));
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) << 0U);
+ TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) << 1U);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) >>
+ as_unsigned(IntegerBitsPlusSign<Dst>::value));
+ TEST_EXPECTED_VALUE(
+ 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) & 1);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) & 0);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) & 1);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) & 0);
+ TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
+ MakeClampedNum(DstLimits::max()) & -1);
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) | 1);
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) | 0);
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(0) | 1);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) | 0);
+ TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
+ ClampedNumeric<Dst>(0) | static_cast<Dst>(-1));
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) ^ 1);
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) ^ 0);
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(0) ^ 1);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) ^ 0);
+ TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
+ ClampedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
+ TEST_EXPECTED_VALUE(DstLimits::max(), ~ClampedNumeric<Dst>(0));
+
TestStrictPointerMath<Dst>();
}
@@ -359,7 +572,7 @@ void TestSpecializedArithmetic(
const char* dst,
int line,
typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) {
- using DstLimits = numeric_limits<Dst>;
+ using DstLimits = SaturationDefaultLimits<Dst>;
TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
@@ -378,12 +591,39 @@ void TestSpecializedArithmetic(
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
+
+ TEST_EXPECTED_VALUE(DstLimits::max(),
+ -ClampedNumeric<Dst>(DstLimits::lowest()));
+
+ TEST_EXPECTED_VALUE(DstLimits::max(),
+ ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).Abs());
+
+ TEST_EXPECTED_VALUE(DstLimits::lowest() - 1,
+ ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
+ TEST_EXPECTED_VALUE(DstLimits::max() + 1,
+ ClampedNumeric<Dst>(DstLimits::max()) + 1);
+ TEST_EXPECTED_VALUE(
+ DstLimits::Underflow(),
+ ClampedNumeric<Dst>(DstLimits::lowest()) + DstLimits::lowest());
+
+ TEST_EXPECTED_VALUE(
+ DstLimits::Overflow(),
+ ClampedNumeric<Dst>(DstLimits::max()) - DstLimits::lowest());
+ TEST_EXPECTED_VALUE(
+ DstLimits::Underflow(),
+ ClampedNumeric<Dst>(DstLimits::lowest()) - DstLimits::max());
+
+ TEST_EXPECTED_VALUE(DstLimits::Underflow(),
+ ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
+
+ TEST_EXPECTED_VALUE(-0.5, ClampedNumeric<Dst>(-1.0) / 2);
}
// Generic arithmetic tests.
template <typename Dst>
static void TestArithmetic(const char* dst, int line) {
- using DstLimits = numeric_limits<Dst>;
+ using DstLimits = SaturationDefaultLimits<Dst>;
EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
EXPECT_EQ(false,
@@ -417,6 +657,27 @@ static void TestArithmetic(const char* dst, int line) {
checked_dst = 1;
TEST_EXPECTED_VALUE(1, checked_dst /= 1);
+ TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) + ClampedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) - ClampedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) * ClampedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / ClampedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(2, 1 + ClampedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, 1 - ClampedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, 1 * ClampedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, 1 / ClampedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) + 1);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) - 1);
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) * 1);
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / 1);
+ ClampedNumeric<Dst> clamped_dst = 1;
+ TEST_EXPECTED_VALUE(2, clamped_dst += 1);
+ clamped_dst = 1;
+ TEST_EXPECTED_VALUE(0, clamped_dst -= 1);
+ clamped_dst = 1;
+ TEST_EXPECTED_VALUE(1, clamped_dst *= 1);
+ clamped_dst = 1;
+ TEST_EXPECTED_VALUE(1, clamped_dst /= 1);
+
// Generic negation.
if (DstLimits::is_signed) {
TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
@@ -424,6 +685,12 @@ static void TestArithmetic(const char* dst, int line) {
TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
-CheckedNumeric<Dst>(DstLimits::max()));
+
+ TEST_EXPECTED_VALUE(0, -ClampedNumeric<Dst>());
+ TEST_EXPECTED_VALUE(-1, -ClampedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, -ClampedNumeric<Dst>(-1));
+ TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
+ -ClampedNumeric<Dst>(DstLimits::max()));
}
// Generic absolute value.
@@ -432,6 +699,11 @@ static void TestArithmetic(const char* dst, int line) {
TEST_EXPECTED_VALUE(DstLimits::max(),
CheckedNumeric<Dst>(DstLimits::max()).Abs());
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>().Abs());
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).Abs());
+ TEST_EXPECTED_VALUE(DstLimits::max(),
+ ClampedNumeric<Dst>(DstLimits::max()).Abs());
+
// Generic addition.
TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
@@ -441,6 +713,15 @@ static void TestArithmetic(const char* dst, int line) {
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) +
DstLimits::max());
+ TEST_EXPECTED_VALUE(1, (ClampedNumeric<Dst>() + 1));
+ TEST_EXPECTED_VALUE(2, (ClampedNumeric<Dst>(1) + 1));
+ if (numeric_limits<Dst>::is_signed)
+ TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(-1) + 1));
+ TEST_EXPECTED_VALUE(DstLimits::lowest() + 1,
+ ClampedNumeric<Dst>(DstLimits::lowest()) + 1);
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(),
+ ClampedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
+
// Generic subtraction.
TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
@@ -451,6 +732,17 @@ static void TestArithmetic(const char* dst, int line) {
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -1);
}
+ TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(1) - 1));
+ TEST_EXPECTED_VALUE(DstLimits::max() - 1,
+ ClampedNumeric<Dst>(DstLimits::max()) - 1);
+ if (numeric_limits<Dst>::is_signed) {
+ TEST_EXPECTED_VALUE(-1, (ClampedNumeric<Dst>() - 1));
+ TEST_EXPECTED_VALUE(-2, (ClampedNumeric<Dst>(-1) - 1));
+ } else {
+ TEST_EXPECTED_VALUE(DstLimits::max(),
+ ClampedNumeric<Dst>(DstLimits::max()) - -1);
+ }
+
// Generic multiplication.
TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
@@ -467,6 +759,22 @@ static void TestArithmetic(const char* dst, int line) {
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
DstLimits::max());
+ TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>() * 1));
+ TEST_EXPECTED_VALUE(1, (ClampedNumeric<Dst>(1) * 1));
+ TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(0) * 0));
+ if (numeric_limits<Dst>::is_signed) {
+ TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(-1) * 0));
+ TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(0) * -1));
+ TEST_EXPECTED_VALUE(-2, (ClampedNumeric<Dst>(-1) * 2));
+ } else {
+ TEST_EXPECTED_VALUE(DstLimits::Underflow(),
+ ClampedNumeric<Dst>(DstLimits::max()) * -2);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::max()) *
+ ClampedNumeric<uintmax_t>(-2));
+ }
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(),
+ ClampedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
+
// Generic division.
TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
@@ -474,6 +782,17 @@ static void TestArithmetic(const char* dst, int line) {
CheckedNumeric<Dst>(DstLimits::lowest()) / 2);
TEST_EXPECTED_VALUE(DstLimits::max() / 2,
CheckedNumeric<Dst>(DstLimits::max()) / 2);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) / 0);
+
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>() / 1);
+ TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / 1);
+ TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
+ ClampedNumeric<Dst>(DstLimits::lowest()) / 2);
+ TEST_EXPECTED_VALUE(DstLimits::max() / 2,
+ ClampedNumeric<Dst>(DstLimits::max()) / 2);
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(), ClampedNumeric<Dst>(1) / 0);
+ TEST_EXPECTED_VALUE(DstLimits::Underflow(), ClampedNumeric<Dst>(-1) / 0);
+ TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) / 0);
TestSpecializedArithmetic<Dst>(dst, line);
}
@@ -605,8 +924,8 @@ void TestStrictComparison() {
template <typename Dst, typename Src>
struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
static void Test(const char *dst, const char *src, int line) {
- using SrcLimits = numeric_limits<Src>;
- using DstLimits = numeric_limits<Dst>;
+ using SrcLimits = SaturationDefaultLimits<Src>;
+ using DstLimits = SaturationDefaultLimits<Dst>;
// Integral to floating.
static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) ||
// Not floating to integral and...
@@ -622,18 +941,26 @@ struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
TestStrictComparison<Dst, Src>();
const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
+ const ClampedNumeric<Dst> clamped_dst = SrcLimits::max();
TEST_EXPECTED_SUCCESS(checked_dst);
+ TEST_EXPECTED_VALUE(Dst(SrcLimits::max()), clamped_dst);
if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) {
// At least twice larger type.
TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
-
+ TEST_EXPECTED_VALUE(SrcLimits::max() * clamped_dst,
+ Dst(SrcLimits::max()) * SrcLimits::max());
} else { // Larger, but not at least twice as large.
TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
TEST_EXPECTED_SUCCESS(checked_dst + 1);
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(),
+ SrcLimits::max() * clamped_dst);
+ TEST_EXPECTED_VALUE(Dst(SrcLimits::max()) + Dst(1),
+ clamped_dst + Dst(1));
}
} else { // Same width type.
TEST_EXPECTED_FAILURE(checked_dst + 1);
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + Dst(1));
}
TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
@@ -653,8 +980,8 @@ struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
template <typename Dst, typename Src>
struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
static void Test(const char *dst, const char *src, int line) {
- using SrcLimits = numeric_limits<Src>;
- using DstLimits = numeric_limits<Dst>;
+ using SrcLimits = SaturationDefaultLimits<Src>;
+ using DstLimits = SaturationDefaultLimits<Dst>;
static_assert(SrcLimits::is_signed == DstLimits::is_signed,
"Destination and source sign must be the same");
static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
@@ -664,9 +991,14 @@ struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
const CheckedNumeric<Dst> checked_dst;
TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
- TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
+ TEST_EXPECTED_VALUE(1, checked_dst + Src(1));
TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
+ const ClampedNumeric<Dst> clamped_dst;
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
+ TEST_EXPECTED_VALUE(1, clamped_dst + Src(1));
+ TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst - SrcLimits::max());
+
TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
if (SrcLimits::is_iec559) {
@@ -689,10 +1021,12 @@ struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
}
} else if (SrcLimits::is_signed) {
TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
+ TEST_EXPECTED_VALUE(-1, clamped_dst - static_cast<Src>(1));
TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
} else {
TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
+ TEST_EXPECTED_VALUE(Dst(0), clamped_dst - static_cast<Src>(1));
TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
}
}
@@ -701,8 +1035,8 @@ struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
template <typename Dst, typename Src>
struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
static void Test(const char *dst, const char *src, int line) {
- using SrcLimits = numeric_limits<Src>;
- using DstLimits = numeric_limits<Dst>;
+ using SrcLimits = SaturationDefaultLimits<Src>;
+ using DstLimits = SaturationDefaultLimits<Dst>;
static_assert(MaxExponent<Dst>::value >= MaxExponent<Src>::value,
"Destination must be equal or wider than source.");
static_assert(SrcLimits::is_signed, "Source must be signed");
@@ -713,8 +1047,17 @@ struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
const CheckedNumeric<Dst> checked_dst;
TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
+ TEST_EXPECTED_SUCCESS(checked_dst * static_cast<Src>(-1));
TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
+ const ClampedNumeric<Dst> clamped_dst;
+ TEST_EXPECTED_VALUE(SrcLimits::max(), clamped_dst + SrcLimits::max());
+ TEST_EXPECTED_VALUE(DstLimits::Underflow(),
+ clamped_dst + static_cast<Src>(-1));
+ TEST_EXPECTED_VALUE(0, clamped_dst * static_cast<Src>(-1));
+ TEST_EXPECTED_VALUE(DstLimits::Underflow(),
+ clamped_dst + SrcLimits::lowest());
+
TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
@@ -725,8 +1068,8 @@ struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
template <typename Dst, typename Src>
struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
static void Test(const char *dst, const char *src, int line) {
- using SrcLimits = numeric_limits<Src>;
- using DstLimits = numeric_limits<Dst>;
+ using SrcLimits = SaturationDefaultLimits<Src>;
+ using DstLimits = SaturationDefaultLimits<Dst>;
static_assert(MaxExponent<Dst>::value < MaxExponent<Src>::value,
"Destination must be narrower than source.");
static_assert(SrcLimits::is_signed, "Source must be signed.");
@@ -740,12 +1083,20 @@ struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
+ const ClampedNumeric<Dst> clamped_dst;
+ TEST_EXPECTED_VALUE(1, clamped_dst + static_cast<Src>(1));
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
+ TEST_EXPECTED_VALUE(DstLimits::Underflow(),
+ clamped_dst + static_cast<Src>(-1));
+ TEST_EXPECTED_VALUE(DstLimits::Underflow(),
+ clamped_dst + SrcLimits::lowest());
+
TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
// Additional saturation tests.
- EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max())) << src;
+ EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
EXPECT_EQ(DstLimits::lowest(), saturated_cast<Dst>(SrcLimits::lowest()));
if (SrcLimits::is_iec559) {
@@ -776,8 +1127,8 @@ struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
template <typename Dst, typename Src>
struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
static void Test(const char *dst, const char *src, int line) {
- using SrcLimits = numeric_limits<Src>;
- using DstLimits = numeric_limits<Dst>;
+ using SrcLimits = SaturationDefaultLimits<Src>;
+ using DstLimits = SaturationDefaultLimits<Dst>;
static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
"Destination must be narrower or equal to source.");
static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
@@ -790,6 +1141,11 @@ struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
TEST_EXPECTED_VALUE(SrcLimits::lowest(), checked_dst + SrcLimits::lowest());
+ const ClampedNumeric<Dst> clamped_dst;
+ TEST_EXPECTED_VALUE(1, clamped_dst + static_cast<Src>(1));
+ TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
+ TEST_EXPECTED_VALUE(SrcLimits::lowest(), clamped_dst + SrcLimits::lowest());
+
TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
@@ -1167,20 +1523,41 @@ TEST(SafeNumerics, CompoundNumericOperations) {
}
TEST(SafeNumerics, VariadicNumericOperations) {
- auto a = CheckAdd(1, 2UL, MakeCheckedNum(3LL), 4).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
- auto b = CheckSub(MakeCheckedNum(20.0), 2UL, 4).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
- auto c = CheckMul(20.0, MakeCheckedNum(1), 5, 3UL).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
- auto d = CheckDiv(20.0, 2.0, MakeCheckedNum(5LL), -4).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
- auto e = CheckMod(MakeCheckedNum(20), 3).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
- auto f = CheckLsh(1, MakeCheckedNum(2)).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
- auto g = CheckRsh(4, MakeCheckedNum(2)).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
- auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
+ { // Synthetic scope to avoid variable naming collisions.
+ auto a = CheckAdd(1, 2UL, MakeCheckedNum(3LL), 4).ValueOrDie();
+ EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
+ auto b = CheckSub(MakeCheckedNum(20.0), 2UL, 4).ValueOrDie();
+ EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
+ auto c = CheckMul(20.0, MakeCheckedNum(1), 5, 3UL).ValueOrDie();
+ EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
+ auto d = CheckDiv(20.0, 2.0, MakeCheckedNum(5LL), -4).ValueOrDie();
+ EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
+ auto e = CheckMod(MakeCheckedNum(20), 3).ValueOrDie();
+ EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
+ auto f = CheckLsh(1, MakeCheckedNum(2)).ValueOrDie();
+ EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
+ auto g = CheckRsh(4, MakeCheckedNum(2)).ValueOrDie();
+ EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
+ auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie();
+ EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
+ }
+
+ {
+ auto a = ClampAdd(1, 2UL, MakeClampedNum(3LL), 4);
+ EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
+ auto b = ClampSub(MakeClampedNum(20.0), 2UL, 4);
+ EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
+ auto c = ClampMul(20.0, MakeClampedNum(1), 5, 3UL);
+ EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
+ auto d = ClampDiv(20.0, 2.0, MakeClampedNum(5LL), -4);
+ EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
+ auto e = ClampMod(MakeClampedNum(20), 3);
+ EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
+ auto f = ClampLsh(1, MakeClampedNum(2U));
+ EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
+ auto g = ClampRsh(4, MakeClampedNum(2U));
+ EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
+ auto h = ClampRsh(ClampAdd(1, 1, 1, 1), ClampSub(4U, 2));
+ EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
+ }
}
« no previous file with comments | « base/numerics/safe_math_shared_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698