| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_NUMERICS_SAFE_MATH_IMPL_H_ | 5 #ifndef BASE_NUMERICS_SAFE_MATH_IMPL_H_ |
| 6 #define BASE_NUMERICS_SAFE_MATH_IMPL_H_ | 6 #define BASE_NUMERICS_SAFE_MATH_IMPL_H_ |
| 7 | 7 |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 #else | 50 #else |
| 51 #define USE_OVERFLOW_BUILTINS (0) | 51 #define USE_OVERFLOW_BUILTINS (0) |
| 52 #endif | 52 #endif |
| 53 | 53 |
| 54 template <typename T, | 54 template <typename T, |
| 55 typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> | 55 typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> |
| 56 bool CheckedAddImpl(T x, T y, T* result) { | 56 bool CheckedAddImpl(T x, T y, T* result) { |
| 57 // Since the value of x+y is undefined if we have a signed type, we compute | 57 // Since the value of x+y is undefined if we have a signed type, we compute |
| 58 // it using the unsigned type of the same size. | 58 // it using the unsigned type of the same size. |
| 59 using UnsignedDst = typename std::make_unsigned<T>::type; | 59 using UnsignedDst = typename std::make_unsigned<T>::type; |
| 60 using SignedDst = typename std::make_signed<T>::type; |
| 60 UnsignedDst ux = static_cast<UnsignedDst>(x); | 61 UnsignedDst ux = static_cast<UnsignedDst>(x); |
| 61 UnsignedDst uy = static_cast<UnsignedDst>(y); | 62 UnsignedDst uy = static_cast<UnsignedDst>(y); |
| 62 UnsignedDst uresult = static_cast<UnsignedDst>(ux + uy); | 63 UnsignedDst uresult = static_cast<UnsignedDst>(ux + uy); |
| 63 *result = static_cast<T>(uresult); | 64 *result = static_cast<T>(uresult); |
| 64 // Addition is valid if the sign of (x + y) is equal to either that of x or | 65 // Addition is valid if the sign of (x + y) is equal to either that of x or |
| 65 // that of y. | 66 // that of y. |
| 66 return (std::is_signed<T>::value) | 67 return (std::is_signed<T>::value) |
| 67 ? HasSignBit(BinaryComplement( | 68 ? static_cast<SignedDst>((uresult ^ ux) & (uresult ^ uy)) >= 0 |
| 68 static_cast<UnsignedDst>((uresult ^ ux) & (uresult ^ uy)))) | 69 : uresult >= uy; // Unsigned is either valid or underflow. |
| 69 : (BinaryComplement(x) >= | |
| 70 y); // Unsigned is either valid or underflow. | |
| 71 } | 70 } |
| 72 | 71 |
| 73 template <typename T, typename U, class Enable = void> | 72 template <typename T, typename U, class Enable = void> |
| 74 struct CheckedAddOp {}; | 73 struct CheckedAddOp {}; |
| 75 | 74 |
| 76 template <typename T, typename U> | 75 template <typename T, typename U> |
| 77 struct CheckedAddOp<T, | 76 struct CheckedAddOp<T, |
| 78 U, | 77 U, |
| 79 typename std::enable_if<std::is_integral<T>::value && | 78 typename std::enable_if<std::is_integral<T>::value && |
| 80 std::is_integral<U>::value>::type> { | 79 std::is_integral<U>::value>::type> { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 102 #endif | 101 #endif |
| 103 } | 102 } |
| 104 }; | 103 }; |
| 105 | 104 |
| 106 template <typename T, | 105 template <typename T, |
| 107 typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> | 106 typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> |
| 108 bool CheckedSubImpl(T x, T y, T* result) { | 107 bool CheckedSubImpl(T x, T y, T* result) { |
| 109 // Since the value of x+y is undefined if we have a signed type, we compute | 108 // Since the value of x+y is undefined if we have a signed type, we compute |
| 110 // it using the unsigned type of the same size. | 109 // it using the unsigned type of the same size. |
| 111 using UnsignedDst = typename std::make_unsigned<T>::type; | 110 using UnsignedDst = typename std::make_unsigned<T>::type; |
| 111 using SignedDst = typename std::make_signed<T>::type; |
| 112 UnsignedDst ux = static_cast<UnsignedDst>(x); | 112 UnsignedDst ux = static_cast<UnsignedDst>(x); |
| 113 UnsignedDst uy = static_cast<UnsignedDst>(y); | 113 UnsignedDst uy = static_cast<UnsignedDst>(y); |
| 114 UnsignedDst uresult = static_cast<UnsignedDst>(ux - uy); | 114 UnsignedDst uresult = static_cast<UnsignedDst>(ux - uy); |
| 115 *result = static_cast<T>(uresult); | 115 *result = static_cast<T>(uresult); |
| 116 // Subtraction is valid if either x and y have same sign, or (x-y) and x have | 116 // Subtraction is valid if either x and y have same sign, or (x-y) and x have |
| 117 // the same sign. | 117 // the same sign. |
| 118 return (std::is_signed<T>::value) | 118 return (std::is_signed<T>::value) |
| 119 ? HasSignBit(BinaryComplement( | 119 ? static_cast<SignedDst>((uresult ^ ux) & (ux ^ uy)) >= 0 |
| 120 static_cast<UnsignedDst>((uresult ^ ux) & (ux ^ uy)))) | 120 : x >= y; |
| 121 : (x >= y); | |
| 122 } | 121 } |
| 123 | 122 |
| 124 template <typename T, typename U, class Enable = void> | 123 template <typename T, typename U, class Enable = void> |
| 125 struct CheckedSubOp {}; | 124 struct CheckedSubOp {}; |
| 126 | 125 |
| 127 template <typename T, typename U> | 126 template <typename T, typename U> |
| 128 struct CheckedSubOp<T, | 127 struct CheckedSubOp<T, |
| 129 U, | 128 U, |
| 130 typename std::enable_if<std::is_integral<T>::value && | 129 typename std::enable_if<std::is_integral<T>::value && |
| 131 std::is_integral<U>::value>::type> { | 130 std::is_integral<U>::value>::type> { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 | 172 |
| 174 template <typename T, | 173 template <typename T, |
| 175 typename std::enable_if< | 174 typename std::enable_if< |
| 176 std::is_integral<T>::value && std::is_signed<T>::value && | 175 std::is_integral<T>::value && std::is_signed<T>::value && |
| 177 ((IntegerBitsPlusSign<T>::value * 2) > | 176 ((IntegerBitsPlusSign<T>::value * 2) > |
| 178 IntegerBitsPlusSign<intmax_t>::value)>::type* = nullptr> | 177 IntegerBitsPlusSign<intmax_t>::value)>::type* = nullptr> |
| 179 bool CheckedMulImpl(T x, T y, T* result) { | 178 bool CheckedMulImpl(T x, T y, T* result) { |
| 180 // Since the value of x*y is potentially undefined if we have a signed type, | 179 // Since the value of x*y is potentially undefined if we have a signed type, |
| 181 // we compute it using the unsigned type of the same size. | 180 // we compute it using the unsigned type of the same size. |
| 182 using UnsignedDst = typename std::make_unsigned<T>::type; | 181 using UnsignedDst = typename std::make_unsigned<T>::type; |
| 183 const T is_negative = HasSignBit(x) ^ HasSignBit(y); | |
| 184 const UnsignedDst ux = SafeUnsignedAbs(x); | 182 const UnsignedDst ux = SafeUnsignedAbs(x); |
| 185 const UnsignedDst uy = SafeUnsignedAbs(y); | 183 const UnsignedDst uy = SafeUnsignedAbs(y); |
| 186 UnsignedDst uresult = static_cast<UnsignedDst>(ux * uy); | 184 UnsignedDst uresult = static_cast<UnsignedDst>(ux * uy); |
| 187 // This is a non-branching conditional negation. | 185 // This is a non-branching conditional negation. |
| 186 const T is_negative = (x ^ y) < 0; |
| 188 *result = static_cast<T>((uresult ^ -is_negative) + is_negative); | 187 *result = static_cast<T>((uresult ^ -is_negative) + is_negative); |
| 189 // This uses the unsigned overflow check on the absolute value, with a +1 | 188 // This uses the unsigned overflow check on the absolute value, with a +1 |
| 190 // bound for a negative result. | 189 // bound for a negative result. |
| 191 return (uy == 0 || | 190 return (uy == 0 || |
| 192 ux <= (static_cast<UnsignedDst>(std::numeric_limits<T>::max()) + | 191 ux <= (static_cast<UnsignedDst>(std::numeric_limits<T>::max()) + |
| 193 is_negative) / | 192 is_negative) / |
| 194 uy); | 193 uy); |
| 195 } | 194 } |
| 196 | 195 |
| 197 template <typename T, | 196 template <typename T, |
| (...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 using math = M<typename UnderlyingType<L>::type, | 687 using math = M<typename UnderlyingType<L>::type, |
| 689 typename UnderlyingType<R>::type, | 688 typename UnderlyingType<R>::type, |
| 690 void>; | 689 void>; |
| 691 using type = typename math::result_type; | 690 using type = typename math::result_type; |
| 692 }; | 691 }; |
| 693 | 692 |
| 694 } // namespace internal | 693 } // namespace internal |
| 695 } // namespace base | 694 } // namespace base |
| 696 | 695 |
| 697 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ | 696 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ |
| OLD | NEW |