Chromium Code Reviews| Index: base/numerics/safe_conversions_impl.h |
| diff --git a/base/numerics/safe_conversions_impl.h b/base/numerics/safe_conversions_impl.h |
| index f383d9c07a60664cb075a8191dc0ee09754343ac..774a5373ab96afb0c1829f53ede5ca4f6e72c5fa 100644 |
| --- a/base/numerics/safe_conversions_impl.h |
| +++ b/base/numerics/safe_conversions_impl.h |
| @@ -30,6 +30,52 @@ struct IntegerBitsPlusSign { |
| std::is_signed<NumericType>::value; |
| }; |
| +// Helper templates for integer manipulations. |
| + |
| +template <typename Integer> |
| +struct PositionOfSignBit { |
| + static const size_t value = IntegerBitsPlusSign<Integer>::value - 1; |
| +}; |
| + |
| +template <typename T> |
| +constexpr bool HasSignBit(T x) { |
| + // Cast to unsigned since right shift on signed is undefined. |
| + return !!(static_cast<typename std::make_unsigned<T>::type>(x) >> |
| + PositionOfSignBit<T>::value); |
| +} |
| + |
| +// This wrapper undoes the standard integer promotions. |
|
scottmg
2016/12/09 22:48:24
I don't see this getting used?
jschuh
2016/12/09 22:58:05
It is in safe_math_impl.h. I just moved it because
|
| +template <typename T> |
| +constexpr T BinaryComplement(T x) { |
| + return static_cast<T>(~x); |
| +} |
| + |
| +// This performs a safe, non-branching absolute value via unsigned overflow. |
| +template <typename T, |
| + typename std::enable_if<!std::is_signed<T>::value>::type* = nullptr> |
|
scottmg
2016/12/09 23:27:02
std::is_integral<T>::value &&
in the enable_if fo
jschuh
2016/12/09 23:31:28
I had that originally, but there are no unsigned n
|
| +constexpr T SafeUnsignedAbsImpl(T value, T sign_mask) { |
| + return (value + sign_mask) ^ sign_mask; |
| +} |
| + |
| +template <typename T, |
| + typename std::enable_if<std::is_integral<T>::value && |
| + std::is_signed<T>::value>::type* = nullptr> |
| +constexpr typename std::make_unsigned<T>::type SafeUnsignedAbs(T value) { |
| + using UnsignedT = typename std::make_unsigned<T>::type; |
| + return SafeUnsignedAbsImpl( |
| + static_cast<UnsignedT>(value), |
| + // The sign mask is all ones for negative and zero otherwise. |
| + static_cast<UnsignedT>(-static_cast<T>(HasSignBit(value)))); |
| +} |
| + |
| +template <typename T, |
| + typename std::enable_if<std::is_integral<T>::value && |
| + !std::is_signed<T>::value>::type* = nullptr> |
| +constexpr T SafeUnsignedAbs(T value) { |
| + // T is unsigned, so |value| must already be positive. |
| + return static_cast<T>(value); |
| +} |
| + |
| enum IntegerRepresentation { |
| INTEGER_REPRESENTATION_UNSIGNED, |
| INTEGER_REPRESENTATION_SIGNED |
| @@ -288,11 +334,6 @@ struct TwiceWiderInteger { |
| IsSigned>::type; |
| }; |
| -template <typename Integer> |
| -struct PositionOfSignBit { |
| - static const size_t value = IntegerBitsPlusSign<Integer>::value - 1; |
| -}; |
| - |
| enum ArithmeticPromotionCategory { |
| LEFT_PROMOTION, // Use the type of the left-hand argument. |
| RIGHT_PROMOTION // Use the type of the right-hand argument. |