diff options
-rw-r--r-- | base/numerics/clamped_math.h | 5 | ||||
-rw-r--r-- | base/numerics/saturated_arithmetic.h | 40 | ||||
-rw-r--r-- | base/numerics/saturated_arithmetic_arm.h | 30 | ||||
-rw-r--r-- | base/numerics/saturated_arithmetic_unittest.cc | 72 | ||||
-rw-r--r-- | ui/gfx/geometry/point.h | 18 | ||||
-rw-r--r-- | ui/gfx/geometry/rect.cc | 19 | ||||
-rw-r--r-- | ui/gfx/geometry/rect.h | 2 | ||||
-rw-r--r-- | ui/gfx/geometry/size.cc | 6 | ||||
-rw-r--r-- | ui/gfx/geometry/vector2d.cc | 10 |
9 files changed, 32 insertions, 170 deletions
diff --git a/base/numerics/clamped_math.h b/base/numerics/clamped_math.h index 799043aa3d..620bfd8f07 100644 --- a/base/numerics/clamped_math.h +++ b/base/numerics/clamped_math.h @@ -176,6 +176,11 @@ class ClampedNumeric { value_); } + // This method extracts the raw integer value without saturating it to the + // destination type as the conversion operator does. This is useful when + // e.g. assigning to an auto type or passing as a deduced template parameter. + constexpr T RawValue() const { return value_; } + private: T value_; diff --git a/base/numerics/saturated_arithmetic.h b/base/numerics/saturated_arithmetic.h index 74fbba808d..504fcd8f79 100644 --- a/base/numerics/saturated_arithmetic.h +++ b/base/numerics/saturated_arithmetic.h @@ -22,46 +22,6 @@ namespace base { -ALWAYS_INLINE int32_t SaturatedAddition(int32_t a, int32_t b) { - uint32_t ua = a; - uint32_t ub = b; - uint32_t result = ua + ub; - - // Can only overflow if the signed bit of the two values match. If the - // signed bit of the result and one of the values differ it overflowed. - // The branch compiles to a CMOVNS instruction on x86. - if (~(ua ^ ub) & (result ^ ua) & (1 << 31)) - return std::numeric_limits<int>::max() + (ua >> 31); - - return result; -} - -ALWAYS_INLINE int32_t SaturatedSubtraction(int32_t a, int32_t b) { - uint32_t ua = a; - uint32_t ub = b; - uint32_t result = ua - ub; - - // Can only overflow if the signed bit of the two input values differ. If - // the signed bit of the result and the first value differ it overflowed. - // The branch compiles to a CMOVNS instruction on x86. - if ((ua ^ ub) & (result ^ ua) & (1 << 31)) - return std::numeric_limits<int>::max() + (ua >> 31); - - return result; -} - -ALWAYS_INLINE int32_t SaturatedNegative(int32_t a) { - if (UNLIKELY(a == std::numeric_limits<int>::min())) - return std::numeric_limits<int>::max(); - return -a; -} - -ALWAYS_INLINE int32_t SaturatedAbsolute(int32_t a) { - if (a >= 0) - return a; - return SaturatedNegative(a); -} - ALWAYS_INLINE int GetMaxSaturatedSetResultForTesting(int fractional_shift) { // For C version the set function maxes out to max int, this differs from // the ARM asm version, see saturated_arithmetic_arm.h for the equivalent asm diff --git a/base/numerics/saturated_arithmetic_arm.h b/base/numerics/saturated_arithmetic_arm.h index 732f5f2c1f..21701aa40f 100644 --- a/base/numerics/saturated_arithmetic_arm.h +++ b/base/numerics/saturated_arithmetic_arm.h @@ -9,36 +9,6 @@ namespace base { -inline int32_t SaturatedAddition(int32_t a, int32_t b) { - int32_t result; - - asm("qadd %[output],%[first],%[second]" - : [output] "=r"(result) - : [first] "r"(a), [second] "r"(b)); - - return result; -} - -inline int32_t SaturatedSubtraction(int32_t a, int32_t b) { - int32_t result; - - asm("qsub %[output],%[first],%[second]" - : [output] "=r"(result) - : [first] "r"(a), [second] "r"(b)); - - return result; -} - -inline int32_t SaturatedNegative(int32_t a) { - return SaturatedSubtraction(0, a); -} - -inline int32_t SaturatedAbsolute(int32_t a) { - if (a >= 0) - return a; - return SaturatedNegative(a); -} - inline int GetMaxSaturatedSetResultForTesting(int fractional_shift) { // For ARM Asm version the set function maxes out to the biggest // possible integer part with the fractional part zero'd out. diff --git a/base/numerics/saturated_arithmetic_unittest.cc b/base/numerics/saturated_arithmetic_unittest.cc index 498f5b7710..aa323c2e0e 100644 --- a/base/numerics/saturated_arithmetic_unittest.cc +++ b/base/numerics/saturated_arithmetic_unittest.cc @@ -12,78 +12,6 @@ namespace base { -TEST(SaturatedArithmeticTest, Addition) { - int int_max = std::numeric_limits<int>::max(); - int int_min = std::numeric_limits<int>::min(); - - EXPECT_EQ(0, SaturatedAddition(0, 0)); - EXPECT_EQ(1, SaturatedAddition(0, 1)); - EXPECT_EQ(100, SaturatedAddition(0, 100)); - EXPECT_EQ(150, SaturatedAddition(100, 50)); - - EXPECT_EQ(-1, SaturatedAddition(0, -1)); - EXPECT_EQ(0, SaturatedAddition(1, -1)); - EXPECT_EQ(50, SaturatedAddition(100, -50)); - EXPECT_EQ(-50, SaturatedAddition(50, -100)); - - EXPECT_EQ(int_max - 1, SaturatedAddition(int_max - 1, 0)); - EXPECT_EQ(int_max, SaturatedAddition(int_max - 1, 1)); - EXPECT_EQ(int_max, SaturatedAddition(int_max - 1, 2)); - EXPECT_EQ(int_max - 1, SaturatedAddition(0, int_max - 1)); - EXPECT_EQ(int_max, SaturatedAddition(1, int_max - 1)); - EXPECT_EQ(int_max, SaturatedAddition(2, int_max - 1)); - EXPECT_EQ(int_max, SaturatedAddition(int_max - 1, int_max - 1)); - EXPECT_EQ(int_max, SaturatedAddition(int_max, int_max)); - - EXPECT_EQ(int_min, SaturatedAddition(int_min, 0)); - EXPECT_EQ(int_min + 1, SaturatedAddition(int_min + 1, 0)); - EXPECT_EQ(int_min + 2, SaturatedAddition(int_min + 1, 1)); - EXPECT_EQ(int_min + 3, SaturatedAddition(int_min + 1, 2)); - EXPECT_EQ(int_min, SaturatedAddition(int_min + 1, -1)); - EXPECT_EQ(int_min, SaturatedAddition(int_min + 1, -2)); - EXPECT_EQ(int_min + 1, SaturatedAddition(0, int_min + 1)); - EXPECT_EQ(int_min, SaturatedAddition(-1, int_min + 1)); - EXPECT_EQ(int_min, SaturatedAddition(-2, int_min + 1)); - - EXPECT_EQ(int_max / 2 + 10000, SaturatedAddition(int_max / 2, 10000)); - EXPECT_EQ(int_max, SaturatedAddition(int_max / 2 + 1, int_max / 2 + 1)); - EXPECT_EQ(-1, SaturatedAddition(int_min, int_max)); -} - -TEST(SaturatedArithmeticTest, Subtraction) { - int int_max = std::numeric_limits<int>::max(); - int int_min = std::numeric_limits<int>::min(); - - EXPECT_EQ(0, SaturatedSubtraction(0, 0)); - EXPECT_EQ(-1, SaturatedSubtraction(0, 1)); - EXPECT_EQ(-100, SaturatedSubtraction(0, 100)); - EXPECT_EQ(50, SaturatedSubtraction(100, 50)); - - EXPECT_EQ(1, SaturatedSubtraction(0, -1)); - EXPECT_EQ(2, SaturatedSubtraction(1, -1)); - EXPECT_EQ(150, SaturatedSubtraction(100, -50)); - EXPECT_EQ(150, SaturatedSubtraction(50, -100)); - - EXPECT_EQ(int_max, SaturatedSubtraction(int_max, 0)); - EXPECT_EQ(int_max - 1, SaturatedSubtraction(int_max, 1)); - EXPECT_EQ(int_max - 1, SaturatedSubtraction(int_max - 1, 0)); - EXPECT_EQ(int_max, SaturatedSubtraction(int_max - 1, -1)); - EXPECT_EQ(int_max, SaturatedSubtraction(int_max - 1, -2)); - EXPECT_EQ(-int_max + 1, SaturatedSubtraction(0, int_max - 1)); - EXPECT_EQ(-int_max, SaturatedSubtraction(-1, int_max - 1)); - EXPECT_EQ(-int_max - 1, SaturatedSubtraction(-2, int_max - 1)); - EXPECT_EQ(-int_max - 1, SaturatedSubtraction(-3, int_max - 1)); - - EXPECT_EQ(int_min, SaturatedSubtraction(int_min, 0)); - EXPECT_EQ(int_min + 1, SaturatedSubtraction(int_min + 1, 0)); - EXPECT_EQ(int_min, SaturatedSubtraction(int_min + 1, 1)); - EXPECT_EQ(int_min, SaturatedSubtraction(int_min + 1, 2)); - - EXPECT_EQ(0, SaturatedSubtraction(int_min, int_min)); - EXPECT_EQ(0, SaturatedSubtraction(int_max, int_max)); - EXPECT_EQ(int_max, SaturatedSubtraction(int_max, int_min)); -} - TEST(SaturatedArithmeticTest, SetSigned) { int int_max = std::numeric_limits<int>::max(); int int_min = std::numeric_limits<int>::min(); diff --git a/ui/gfx/geometry/point.h b/ui/gfx/geometry/point.h index bb248d5432..b1ba5065de 100644 --- a/ui/gfx/geometry/point.h +++ b/ui/gfx/geometry/point.h @@ -9,7 +9,7 @@ #include <string> #include <tuple> -#include "base/numerics/saturated_arithmetic.h" +#include "base/numerics/clamped_math.h" #include "build/build_config.h" #include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/gfx_export.h" @@ -56,18 +56,18 @@ class GFX_EXPORT Point { } void Offset(int delta_x, int delta_y) { - x_ = base::SaturatedAddition(x_, delta_x); - y_ = base::SaturatedAddition(y_, delta_y); + x_ = base::ClampAdd(x_, delta_x); + y_ = base::ClampAdd(y_, delta_y); } void operator+=(const Vector2d& vector) { - x_ = base::SaturatedAddition(x_, vector.x()); - y_ = base::SaturatedAddition(y_, vector.y()); + x_ = base::ClampAdd(x_, vector.x()); + y_ = base::ClampAdd(y_, vector.y()); } void operator-=(const Vector2d& vector) { - x_ = base::SaturatedSubtraction(x_, vector.x()); - y_ = base::SaturatedSubtraction(y_, vector.y()); + x_ = base::ClampSub(x_, vector.x()); + y_ = base::ClampSub(y_, vector.y()); } void SetToMin(const Point& other); @@ -116,8 +116,8 @@ inline Point operator-(const Point& lhs, const Vector2d& rhs) { } inline Vector2d operator-(const Point& lhs, const Point& rhs) { - return Vector2d(base::SaturatedSubtraction(lhs.x(), rhs.x()), - base::SaturatedSubtraction(lhs.y(), rhs.y())); + return Vector2d(base::ClampSub(lhs.x(), rhs.x()), + base::ClampSub(lhs.y(), rhs.y())); } inline Point PointAtOffsetFromOrigin(const Vector2d& offset_from_origin) { diff --git a/ui/gfx/geometry/rect.cc b/ui/gfx/geometry/rect.cc index b5ceda5829..a1735d028c 100644 --- a/ui/gfx/geometry/rect.cc +++ b/ui/gfx/geometry/rect.cc @@ -15,7 +15,7 @@ #endif #include "base/logging.h" -#include "base/numerics/saturated_arithmetic.h" +#include "base/numerics/clamped_math.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "ui/gfx/geometry/insets.h" @@ -69,8 +69,8 @@ static void SaturatedClampRange(int min, int max, int* origin, int* span) { return; } - int effective_span = base::SaturatedSubtraction(max, min); - int span_loss = base::SaturatedSubtraction(max, min + effective_span); + int effective_span = base::ClampSub(max, min); + int span_loss = base::ClampSub(max, base::ClampAdd(min, effective_span)); // If the desired width is within the limits of ints, we can just // use the simple computations to represent the range precisely. @@ -83,12 +83,13 @@ static void SaturatedClampRange(int min, int max, int* origin, int* span) { // Now we have to approximate. If one of min or max is close enough // to zero we choose to represent that one precisely. The other side is // probably practically "infinite", so we move it. - if (base::SaturatedAbsolute(max) < std::numeric_limits<int>::max() / 2) { + if (base::SafeUnsignedAbs(max) < + base::as_unsigned(std::numeric_limits<int>::max() / 2)) { // Maintain origin + span == max. *span = effective_span; *origin = max - effective_span; - } else if (base::SaturatedAbsolute(min) < - std::numeric_limits<int>::max() / 2) { + } else if (base::SafeUnsignedAbs(min) < + base::as_unsigned(std::numeric_limits<int>::max() / 2)) { // Maintain origin == min. *span = effective_span; *origin = min; @@ -116,10 +117,8 @@ void Rect::Inset(int left, int top, int right, int bottom) { origin_ += Vector2d(left, top); // left+right might overflow/underflow, but width() - (left+right) might // overflow as well. - set_width(base::SaturatedSubtraction(width(), - base::SaturatedAddition(left, right))); - set_height(base::SaturatedSubtraction(height(), - base::SaturatedAddition(top, bottom))); + set_width(base::ClampSub(width(), base::ClampAdd(left, right))); + set_height(base::ClampSub(height(), base::ClampAdd(top, bottom))); } void Rect::Offset(int horizontal, int vertical) { diff --git a/ui/gfx/geometry/rect.h b/ui/gfx/geometry/rect.h index 1858d44d2c..4e914b8ca6 100644 --- a/ui/gfx/geometry/rect.h +++ b/ui/gfx/geometry/rect.h @@ -227,7 +227,7 @@ class GFX_EXPORT Rect { // Clamp the size to avoid integer overflow in bottom() and right(). // This returns the width given an origin and a width. - // TODO(enne): this should probably use base::SaturatedAddition, but that + // TODO(enne): this should probably use base::ClampAdd, but that // function is not a constexpr. static constexpr int GetClampedValue(int origin, int size) { return AddWouldOverflow(origin, size) diff --git a/ui/gfx/geometry/size.cc b/ui/gfx/geometry/size.cc index 69486723a1..781b84d7f5 100644 --- a/ui/gfx/geometry/size.cc +++ b/ui/gfx/geometry/size.cc @@ -12,8 +12,8 @@ #include <ApplicationServices/ApplicationServices.h> #endif +#include "base/numerics/clamped_math.h" #include "base/numerics/safe_math.h" -#include "base/numerics/saturated_arithmetic.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "ui/gfx/geometry/safe_integer_conversions.h" @@ -58,8 +58,8 @@ base::CheckedNumeric<int> Size::GetCheckedArea() const { } void Size::Enlarge(int grow_width, int grow_height) { - SetSize(base::SaturatedAddition(width(), grow_width), - base::SaturatedAddition(height(), grow_height)); + SetSize(base::ClampAdd(width(), grow_width), + base::ClampAdd(height(), grow_height)); } void Size::SetToMin(const Size& other) { diff --git a/ui/gfx/geometry/vector2d.cc b/ui/gfx/geometry/vector2d.cc index 2b4875c39c..0ce3b20baa 100644 --- a/ui/gfx/geometry/vector2d.cc +++ b/ui/gfx/geometry/vector2d.cc @@ -6,7 +6,7 @@ #include <cmath> -#include "base/numerics/saturated_arithmetic.h" +#include "base/numerics/clamped_math.h" #include "base/strings/stringprintf.h" namespace gfx { @@ -16,13 +16,13 @@ bool Vector2d::IsZero() const { } void Vector2d::Add(const Vector2d& other) { - x_ = base::SaturatedAddition(other.x_, x_); - y_ = base::SaturatedAddition(other.y_, y_); + x_ = base::ClampAdd(other.x_, x_); + y_ = base::ClampAdd(other.y_, y_); } void Vector2d::Subtract(const Vector2d& other) { - x_ = base::SaturatedSubtraction(x_, other.x_); - y_ = base::SaturatedSubtraction(y_, other.y_); + x_ = base::ClampSub(x_, other.x_); + y_ = base::ClampSub(y_, other.y_); } int64_t Vector2d::LengthSquared() const { |