Commit ae87b773 authored by Gabriel Charette's avatar Gabriel Charette Committed by Commit Bot

constexpr TimeDelta::operator/

The mul/div operators are tricky. operator/ works when |a| is small
enough (in absolute value) to deterministically not risk overflow.

operator*() on the other hand doesn't because of a limitation in
__builtin_mul_overflow. We could do some template hacking to make
operator*(a) == operator/(1.0/a) when |a| is a constant expression.

Bug: 761570
Change-Id: I9906edfc049017ad19872e4a586b2ec675404850
Reviewed-on: https://chromium-review.googlesource.com/886344Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarYuri Wiitala <miu@chromium.org>
Commit-Queue: Gabriel Charette <gab@chromium.org>
Cr-Commit-Position: refs/heads/master@{#532947}
parent fb27199b
......@@ -218,7 +218,9 @@ class BASE_EXPORT TimeDelta {
}
constexpr TimeDelta operator-() const { return TimeDelta(-delta_); }
// Computations with numeric types.
// Computations with numeric types. operator*() isn't constexpr because of a
// limitation around __builtin_mul_overflow (but operator/(1.0/a) works for
// |a|'s of "reasonable" size -- i.e. that don't risk overflow).
template <typename T>
TimeDelta operator*(T a) const {
CheckedNumeric<int64_t> rv(delta_);
......@@ -231,7 +233,7 @@ class BASE_EXPORT TimeDelta {
return TimeDelta(std::numeric_limits<int64_t>::max());
}
template <typename T>
TimeDelta operator/(T a) const {
constexpr TimeDelta operator/(T a) const {
CheckedNumeric<int64_t> rv(delta_);
rv /= a;
if (rv.IsValid())
......@@ -247,7 +249,7 @@ class BASE_EXPORT TimeDelta {
return *this = (*this * a);
}
template <typename T>
TimeDelta& operator/=(T a) {
constexpr TimeDelta& operator/=(T a) {
return *this = (*this / a);
}
......
......@@ -1322,70 +1322,82 @@ TEST(TimeDelta, NumericOperators) {
constexpr double d = 0.5;
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(TimeDelta::FromMilliseconds(1000) * d));
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(TimeDelta::FromMilliseconds(1000) / d));
static_assert(TimeDelta::FromMilliseconds(2000) ==
(TimeDelta::FromMilliseconds(1000) / d),
"");
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(TimeDelta::FromMilliseconds(1000) *= d));
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(TimeDelta::FromMilliseconds(1000) /= d));
static_assert(TimeDelta::FromMilliseconds(2000) ==
(TimeDelta::FromMilliseconds(1000) /= d),
"");
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(d * TimeDelta::FromMilliseconds(1000)));
constexpr float f = 0.5;
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(TimeDelta::FromMilliseconds(1000) * f));
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(TimeDelta::FromMilliseconds(1000) / f));
static_assert(TimeDelta::FromMilliseconds(2000) ==
(TimeDelta::FromMilliseconds(1000) / f),
"");
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(TimeDelta::FromMilliseconds(1000) *= f));
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(TimeDelta::FromMilliseconds(1000) /= f));
static_assert(TimeDelta::FromMilliseconds(2000) ==
(TimeDelta::FromMilliseconds(1000) /= f),
"");
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(f * TimeDelta::FromMilliseconds(1000)));
constexpr int i = 2;
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(TimeDelta::FromMilliseconds(1000) * i));
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(TimeDelta::FromMilliseconds(1000) / i));
static_assert(TimeDelta::FromMilliseconds(500) ==
(TimeDelta::FromMilliseconds(1000) / i),
"");
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(TimeDelta::FromMilliseconds(1000) *= i));
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(TimeDelta::FromMilliseconds(1000) /= i));
static_assert(TimeDelta::FromMilliseconds(500) ==
(TimeDelta::FromMilliseconds(1000) /= i),
"");
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(i * TimeDelta::FromMilliseconds(1000)));
constexpr int64_t i64 = 2;
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(TimeDelta::FromMilliseconds(1000) * i64));
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(TimeDelta::FromMilliseconds(1000) / i64));
static_assert(TimeDelta::FromMilliseconds(500) ==
(TimeDelta::FromMilliseconds(1000) / i64),
"");
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(TimeDelta::FromMilliseconds(1000) *= i64));
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(TimeDelta::FromMilliseconds(1000) /= i64));
static_assert(TimeDelta::FromMilliseconds(500) ==
(TimeDelta::FromMilliseconds(1000) /= i64),
"");
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(i64 * TimeDelta::FromMilliseconds(1000)));
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(TimeDelta::FromMilliseconds(1000) * 0.5));
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(TimeDelta::FromMilliseconds(1000) / 0.5));
static_assert(TimeDelta::FromMilliseconds(2000) ==
(TimeDelta::FromMilliseconds(1000) / 0.5),
"");
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(TimeDelta::FromMilliseconds(1000) *= 0.5));
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(TimeDelta::FromMilliseconds(1000) /= 0.5));
static_assert(TimeDelta::FromMilliseconds(2000) ==
(TimeDelta::FromMilliseconds(1000) /= 0.5),
"");
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(0.5 * TimeDelta::FromMilliseconds(1000)));
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(TimeDelta::FromMilliseconds(1000) * 2));
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(TimeDelta::FromMilliseconds(1000) / 2));
static_assert(TimeDelta::FromMilliseconds(500) ==
(TimeDelta::FromMilliseconds(1000) / 2),
"");
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(TimeDelta::FromMilliseconds(1000) *= 2));
EXPECT_EQ(TimeDelta::FromMilliseconds(500),
(TimeDelta::FromMilliseconds(1000) /= 2));
static_assert(TimeDelta::FromMilliseconds(500) ==
(TimeDelta::FromMilliseconds(1000) /= 2),
"");
EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
(2 * TimeDelta::FromMilliseconds(1000)));
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment