Index: base/numerics/safe_math_impl.h |
diff --git a/base/numerics/safe_math_impl.h b/base/numerics/safe_math_impl.h |
index 15de619e76fae11ce35d8ecac5b950c4e7ba432b..c6fbf704cc6a75db199db406f6a16a598885ae36 100644 |
--- a/base/numerics/safe_math_impl.h |
+++ b/base/numerics/safe_math_impl.h |
@@ -23,78 +23,6 @@ namespace internal { |
// but it may not be fast. This code could be split based on |
// platform/architecture and replaced with potentially faster implementations. |
-// Integer promotion templates used by the portable checked integer arithmetic. |
-template <size_t Size, bool IsSigned> |
-struct IntegerForSizeAndSign; |
-template <> |
-struct IntegerForSizeAndSign<1, true> { |
- typedef int8_t type; |
-}; |
-template <> |
-struct IntegerForSizeAndSign<1, false> { |
- typedef uint8_t type; |
-}; |
-template <> |
-struct IntegerForSizeAndSign<2, true> { |
- typedef int16_t type; |
-}; |
-template <> |
-struct IntegerForSizeAndSign<2, false> { |
- typedef uint16_t type; |
-}; |
-template <> |
-struct IntegerForSizeAndSign<4, true> { |
- typedef int32_t type; |
-}; |
-template <> |
-struct IntegerForSizeAndSign<4, false> { |
- typedef uint32_t type; |
-}; |
-template <> |
-struct IntegerForSizeAndSign<8, true> { |
- typedef int64_t type; |
-}; |
-template <> |
-struct IntegerForSizeAndSign<8, false> { |
- typedef uint64_t type; |
- static_assert(sizeof(uintmax_t) == 8, |
- "Max integer size not supported for this toolchain."); |
-}; |
- |
-// WARNING: We have no IntegerForSizeAndSign<16, *>. If we ever add one to |
-// support 128-bit math, then the ArithmeticPromotion template below will need |
-// to be updated (or more likely replaced with a decltype expression). |
- |
-template <typename Integer> |
-struct UnsignedIntegerForSize { |
- typedef typename std::enable_if< |
- std::numeric_limits<Integer>::is_integer, |
- typename IntegerForSizeAndSign<sizeof(Integer), false>::type>::type type; |
-}; |
- |
-template <typename Integer> |
-struct SignedIntegerForSize { |
- typedef typename std::enable_if< |
- std::numeric_limits<Integer>::is_integer, |
- typename IntegerForSizeAndSign<sizeof(Integer), true>::type>::type type; |
-}; |
- |
-template <typename Integer> |
-struct TwiceWiderInteger { |
- typedef typename std::enable_if< |
- std::numeric_limits<Integer>::is_integer, |
- typename IntegerForSizeAndSign< |
- sizeof(Integer) * 2, |
- std::numeric_limits<Integer>::is_signed>::type>::type type; |
-}; |
- |
-template <typename Integer> |
-struct PositionOfSignBit { |
- static const typename std::enable_if<std::numeric_limits<Integer>::is_integer, |
- size_t>::type value = |
- CHAR_BIT * sizeof(Integer) - 1; |
-}; |
- |
// This is used for UnsignedAbs, where we need to support floating-point |
// template instantiations even though we don't actually support the operations. |
// However, there is no corresponding implementation of e.g. SafeUnsignedAbs, |
@@ -129,106 +57,6 @@ constexpr T BinaryComplement(T x) { |
return static_cast<T>(~x); |
} |
-enum ArithmeticPromotionCategory { |
- LEFT_PROMOTION, // Use the type of the left-hand argument. |
- RIGHT_PROMOTION, // Use the type of the right-hand argument. |
- MAX_EXPONENT_PROMOTION, // Use the type supporting the largest exponent. |
- BIG_ENOUGH_PROMOTION // Attempt to find a big enough type. |
-}; |
- |
-template <ArithmeticPromotionCategory Promotion, |
- typename Lhs, |
- typename Rhs = Lhs> |
-struct ArithmeticPromotion; |
- |
-template <typename Lhs, |
- typename Rhs, |
- ArithmeticPromotionCategory Promotion = |
- (MaxExponent<Lhs>::value > MaxExponent<Rhs>::value) |
- ? LEFT_PROMOTION |
- : RIGHT_PROMOTION> |
-struct MaxExponentPromotion; |
- |
-template <typename Lhs, typename Rhs> |
-struct MaxExponentPromotion<Lhs, Rhs, LEFT_PROMOTION> { |
- using type = Lhs; |
-}; |
- |
-template <typename Lhs, typename Rhs> |
-struct MaxExponentPromotion<Lhs, Rhs, RIGHT_PROMOTION> { |
- using type = Rhs; |
-}; |
- |
-template <typename Lhs, |
- typename Rhs = Lhs, |
- bool is_intmax_type = |
- std::is_integral< |
- typename MaxExponentPromotion<Lhs, Rhs>::type>::value && |
- sizeof(typename MaxExponentPromotion<Lhs, Rhs>::type) == |
- sizeof(intmax_t), |
- bool is_max_exponent = |
- StaticDstRangeRelationToSrcRange< |
- typename MaxExponentPromotion<Lhs, Rhs>::type, |
- Lhs>::value == |
- NUMERIC_RANGE_CONTAINED&& StaticDstRangeRelationToSrcRange< |
- typename MaxExponentPromotion<Lhs, Rhs>::type, |
- Rhs>::value == NUMERIC_RANGE_CONTAINED> |
-struct BigEnoughPromotion; |
- |
-// The side with the max exponent is big enough. |
-template <typename Lhs, typename Rhs, bool is_intmax_type> |
-struct BigEnoughPromotion<Lhs, Rhs, is_intmax_type, true> { |
- using type = typename MaxExponentPromotion<Lhs, Rhs>::type; |
- static const bool is_contained = true; |
-}; |
- |
-// We can use a twice wider type to fit. |
-template <typename Lhs, typename Rhs> |
-struct BigEnoughPromotion<Lhs, Rhs, false, false> { |
- using type = typename IntegerForSizeAndSign< |
- sizeof(typename MaxExponentPromotion<Lhs, Rhs>::type) * 2, |
- std::is_signed<Lhs>::value || std::is_signed<Rhs>::value>::type; |
- static const bool is_contained = true; |
-}; |
- |
-// No type is large enough. |
-template <typename Lhs, typename Rhs> |
-struct BigEnoughPromotion<Lhs, Rhs, true, false> { |
- using type = typename MaxExponentPromotion<Lhs, Rhs>::type; |
- static const bool is_contained = false; |
-}; |
- |
-// These are the supported promotion types. |
- |
-// Use the type supporting the largest exponent. |
-template <typename Lhs, typename Rhs> |
-struct ArithmeticPromotion<MAX_EXPONENT_PROMOTION, Lhs, Rhs> { |
- using type = typename MaxExponentPromotion<Lhs, Rhs>::type; |
- static const bool is_contained = true; |
-}; |
- |
-// Attempt to find a big enough type. |
-template <typename Lhs, typename Rhs> |
-struct ArithmeticPromotion<BIG_ENOUGH_PROMOTION, Lhs, Rhs> { |
- using type = typename BigEnoughPromotion<Lhs, Rhs>::type; |
- static const bool is_contained = BigEnoughPromotion<Lhs, Rhs>::is_contained; |
-}; |
- |
-// We can statically check if operations on the provided types can wrap, so we |
-// can skip the checked operations if they're not needed. So, for an integer we |
-// care if the destination type preserves the sign and is twice the width of |
-// the source. |
-template <typename T, typename Lhs, typename Rhs> |
-struct IsIntegerArithmeticSafe { |
- static const bool value = !std::numeric_limits<T>::is_iec559 && |
- StaticDstRangeRelationToSrcRange<T, Lhs>::value == |
- NUMERIC_RANGE_CONTAINED && |
- sizeof(T) >= (2 * sizeof(Lhs)) && |
- StaticDstRangeRelationToSrcRange<T, Rhs>::value != |
- NUMERIC_RANGE_CONTAINED && |
- sizeof(T) >= (2 * sizeof(Rhs)); |
-}; |
- |
// Probe for builtin math overflow support on Clang and version check on GCC. |
#if defined(__has_builtin) |
#define USE_OVERFLOW_BUILTINS (__has_builtin(__builtin_add_overflow)) |
@@ -872,32 +700,6 @@ class CheckedNumericState<T, NUMERIC_FLOATING> { |
constexpr T value() const { return value_; } |
}; |
-// The following are helper templates used in the CheckedNumeric class. |
-template <typename T> |
-class CheckedNumeric; |
- |
-// Used to treat CheckedNumeric and arithmetic underlying types the same. |
-template <typename T> |
-struct UnderlyingType { |
- using type = T; |
- static const bool is_numeric = std::is_arithmetic<T>::value; |
- static const bool is_checked = false; |
-}; |
- |
-template <typename T> |
-struct UnderlyingType<CheckedNumeric<T>> { |
- using type = T; |
- static const bool is_numeric = true; |
- static const bool is_checked = true; |
-}; |
- |
-template <typename L, typename R> |
-struct IsCheckedOp { |
- static const bool value = |
- UnderlyingType<L>::is_numeric && UnderlyingType<R>::is_numeric && |
- (UnderlyingType<L>::is_checked || UnderlyingType<R>::is_checked); |
-}; |
- |
template <template <typename, typename, typename> class M, |
typename L, |
typename R> |