Performance optimizations for base/numerics absolute value and multiply
Removes a number of branches from the calculations. Also now exporting
SafeUnsignedAbs as a public API.
NOTRY=true
Review-Url: https://codereview.chromium.org/2566733002
Cr-Commit-Position: refs/heads/master@{#437769}
diff --git a/base/numerics/safe_numerics_unittest.cc b/base/numerics/safe_numerics_unittest.cc
index 985a308..c0cc514 100644
--- a/base/numerics/safe_numerics_unittest.cc
+++ b/base/numerics/safe_numerics_unittest.cc
@@ -106,12 +106,15 @@
#define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
#define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
-#define TEST_EXPECTED_VALUE(expected, actual) \
- EXPECT_EQ(static_cast<Dst>(expected), \
- ((actual) \
- .template Cast<Dst>() \
- .template ValueOrDie<Dst, LogOnFailure>())) \
- << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
+// 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>())) \
+ << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
<< dst << " on line " << line
// Test the simple pointer arithmetic overrides.
@@ -143,6 +146,8 @@
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_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
@@ -161,6 +166,13 @@
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) / -1);
TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * -1);
+ TEST_EXPECTED_VALUE(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());
// Modulus is legal only for integers.
TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
@@ -221,6 +233,12 @@
CheckedNumeric<typename std::make_signed<Dst>::type>(
std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
.UnsignedAbs());
+ TEST_EXPECTED_VALUE(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());
// Modulus is legal only for integers.
TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);