| 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_H_ | 5 #ifndef BASE_NUMERICS_SAFE_MATH_H_ |
| 6 #define BASE_NUMERICS_SAFE_MATH_H_ | 6 #define BASE_NUMERICS_SAFE_MATH_H_ |
| 7 | 7 |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 | 9 |
| 10 #include <limits> | 10 #include <limits> |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 T ValueUnsafe() const { return state_.value(); } | 112 T ValueUnsafe() const { return state_.value(); } |
| 113 | 113 |
| 114 // Prototypes for the supported arithmetic operator overloads. | 114 // Prototypes for the supported arithmetic operator overloads. |
| 115 template <typename Src> CheckedNumeric& operator+=(Src rhs); | 115 template <typename Src> CheckedNumeric& operator+=(Src rhs); |
| 116 template <typename Src> CheckedNumeric& operator-=(Src rhs); | 116 template <typename Src> CheckedNumeric& operator-=(Src rhs); |
| 117 template <typename Src> CheckedNumeric& operator*=(Src rhs); | 117 template <typename Src> CheckedNumeric& operator*=(Src rhs); |
| 118 template <typename Src> CheckedNumeric& operator/=(Src rhs); | 118 template <typename Src> CheckedNumeric& operator/=(Src rhs); |
| 119 template <typename Src> CheckedNumeric& operator%=(Src rhs); | 119 template <typename Src> CheckedNumeric& operator%=(Src rhs); |
| 120 | 120 |
| 121 CheckedNumeric operator-() const { | 121 CheckedNumeric operator-() const { |
| 122 bool is_valid; | |
| 123 T value = CheckedNeg(state_.value(), &is_valid); | |
| 124 // Negation is always valid for floating point. | 122 // Negation is always valid for floating point. |
| 125 if (std::numeric_limits<T>::is_iec559) | 123 T value = 0; |
| 126 return CheckedNumeric<T>(value); | 124 bool is_valid = (std::numeric_limits<T>::is_iec559 || IsValid()) && |
| 127 | 125 CheckedNeg(state_.value(), &value); |
| 128 is_valid &= state_.is_valid(); | |
| 129 return CheckedNumeric<T>(value, is_valid); | 126 return CheckedNumeric<T>(value, is_valid); |
| 130 } | 127 } |
| 131 | 128 |
| 132 CheckedNumeric Abs() const { | 129 CheckedNumeric Abs() const { |
| 133 bool is_valid; | |
| 134 T value = CheckedAbs(state_.value(), &is_valid); | |
| 135 // Absolute value is always valid for floating point. | 130 // Absolute value is always valid for floating point. |
| 136 if (std::numeric_limits<T>::is_iec559) | 131 T value = 0; |
| 137 return CheckedNumeric<T>(value); | 132 bool is_valid = (std::numeric_limits<T>::is_iec559 || IsValid()) && |
| 138 | 133 CheckedAbs(state_.value(), &value); |
| 139 is_valid &= state_.is_valid(); | |
| 140 return CheckedNumeric<T>(value, is_valid); | 134 return CheckedNumeric<T>(value, is_valid); |
| 141 } | 135 } |
| 142 | 136 |
| 143 // This function is available only for integral types. It returns an unsigned | 137 // This function is available only for integral types. It returns an unsigned |
| 144 // integer of the same width as the source type, containing the absolute value | 138 // integer of the same width as the source type, containing the absolute value |
| 145 // of the source, and properly handling signed min. | 139 // of the source, and properly handling signed min. |
| 146 CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> UnsignedAbs() const { | 140 CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> UnsignedAbs() const { |
| 147 return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>( | 141 return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>( |
| 148 CheckedUnsignedAbs(state_.value()), state_.is_valid()); | 142 SafeUnsignedAbs(state_.value()), state_.is_valid()); |
| 149 } | 143 } |
| 150 | 144 |
| 151 CheckedNumeric& operator++() { | 145 CheckedNumeric& operator++() { |
| 152 *this += 1; | 146 *this += 1; |
| 153 return *this; | 147 return *this; |
| 154 } | 148 } |
| 155 | 149 |
| 156 CheckedNumeric operator++(int) { | 150 CheckedNumeric operator++(int) { |
| 157 CheckedNumeric value = *this; | 151 CheckedNumeric value = *this; |
| 158 *this += 1; | 152 *this += 1; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 // TODO(jschuh): extract these out into templates. | 207 // TODO(jschuh): extract these out into templates. |
| 214 #define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ | 208 #define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ |
| 215 /* Binary arithmetic operator for CheckedNumerics of the same type. */ \ | 209 /* Binary arithmetic operator for CheckedNumerics of the same type. */ \ |
| 216 template <typename T> \ | 210 template <typename T> \ |
| 217 CheckedNumeric<typename ArithmeticPromotion<T>::type> operator OP( \ | 211 CheckedNumeric<typename ArithmeticPromotion<T>::type> operator OP( \ |
| 218 const CheckedNumeric<T>& lhs, const CheckedNumeric<T>& rhs) { \ | 212 const CheckedNumeric<T>& lhs, const CheckedNumeric<T>& rhs) { \ |
| 219 typedef typename ArithmeticPromotion<T>::type Promotion; \ | 213 typedef typename ArithmeticPromotion<T>::type Promotion; \ |
| 220 /* Floating point always takes the fast path */ \ | 214 /* Floating point always takes the fast path */ \ |
| 221 if (std::numeric_limits<T>::is_iec559) \ | 215 if (std::numeric_limits<T>::is_iec559) \ |
| 222 return CheckedNumeric<T>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \ | 216 return CheckedNumeric<T>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \ |
| 217 if (!rhs.IsValid() || !lhs.IsValid()) \ |
| 218 return CheckedNumeric<Promotion>(0, false); \ |
| 223 if (IsIntegerArithmeticSafe<Promotion, T, T>::value) \ | 219 if (IsIntegerArithmeticSafe<Promotion, T, T>::value) \ |
| 224 return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ | 220 return CheckedNumeric<Promotion>(lhs.ValueUnsafe() \ |
| 225 rhs.IsValid() && lhs.IsValid()); \ | 221 OP rhs.ValueUnsafe()); \ |
| 226 bool is_valid = true; \ | 222 Promotion result = 0; \ |
| 227 T result = static_cast<T>( \ | 223 bool is_valid = \ |
| 228 Checked##NAME(static_cast<Promotion>(lhs.ValueUnsafe()), \ | 224 Checked##NAME(static_cast<Promotion>(lhs.ValueUnsafe()), \ |
| 229 static_cast<Promotion>(rhs.ValueUnsafe()), &is_valid)); \ | 225 static_cast<Promotion>(rhs.ValueUnsafe()), &result); \ |
| 230 return CheckedNumeric<Promotion>( \ | 226 return CheckedNumeric<Promotion>(result, is_valid); \ |
| 231 result, is_valid && lhs.IsValid() && rhs.IsValid()); \ | |
| 232 } \ | 227 } \ |
| 233 /* Assignment arithmetic operator implementation from CheckedNumeric. */ \ | 228 /* Assignment arithmetic operator implementation from CheckedNumeric. */ \ |
| 234 template <typename T> \ | 229 template <typename T> \ |
| 235 template <typename Src> \ | 230 template <typename Src> \ |
| 236 CheckedNumeric<T>& CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) { \ | 231 CheckedNumeric<T>& CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) { \ |
| 237 *this = CheckedNumeric<T>::cast(*this) \ | 232 *this = CheckedNumeric<T>::cast(*this) \ |
| 238 OP CheckedNumeric<typename UnderlyingType<Src>::type>::cast(rhs); \ | 233 OP CheckedNumeric<typename UnderlyingType<Src>::type>::cast(rhs); \ |
| 239 return *this; \ | 234 return *this; \ |
| 240 } \ | 235 } \ |
| 241 /* Binary arithmetic operator for CheckedNumeric of different type. */ \ | 236 /* Binary arithmetic operator for CheckedNumeric of different type. */ \ |
| 242 template <typename T, typename Src> \ | 237 template <typename T, typename Src> \ |
| 243 CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ | 238 CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ |
| 244 const CheckedNumeric<Src>& lhs, const CheckedNumeric<T>& rhs) { \ | 239 const CheckedNumeric<Src>& lhs, const CheckedNumeric<T>& rhs) { \ |
| 245 typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ | 240 typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ |
| 241 if (!rhs.IsValid() || !lhs.IsValid()) \ |
| 242 return CheckedNumeric<Promotion>(0, false); \ |
| 246 if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ | 243 if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ |
| 247 return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ | 244 return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe());\ |
| 248 rhs.IsValid() && lhs.IsValid()); \ | |
| 249 return CheckedNumeric<Promotion>::cast(lhs) \ | 245 return CheckedNumeric<Promotion>::cast(lhs) \ |
| 250 OP CheckedNumeric<Promotion>::cast(rhs); \ | 246 OP CheckedNumeric<Promotion>::cast(rhs); \ |
| 251 } \ | 247 } \ |
| 252 /* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \ | 248 /* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \ |
| 253 template <typename T, typename Src, \ | 249 template <typename T, typename Src, \ |
| 254 typename std::enable_if<std::is_arithmetic<Src>::value>::type* = \ | 250 typename std::enable_if<std::is_arithmetic<Src>::value>::type* = \ |
| 255 nullptr> \ | 251 nullptr> \ |
| 256 CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ | 252 CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ |
| 257 const CheckedNumeric<T>& lhs, Src rhs) { \ | 253 const CheckedNumeric<T>& lhs, Src rhs) { \ |
| 258 typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ | 254 typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ |
| (...skipping 25 matching lines...) Expand all Loading... |
| 284 | 280 |
| 285 #undef BASE_NUMERIC_ARITHMETIC_OPERATORS | 281 #undef BASE_NUMERIC_ARITHMETIC_OPERATORS |
| 286 | 282 |
| 287 } // namespace internal | 283 } // namespace internal |
| 288 | 284 |
| 289 using internal::CheckedNumeric; | 285 using internal::CheckedNumeric; |
| 290 | 286 |
| 291 } // namespace base | 287 } // namespace base |
| 292 | 288 |
| 293 #endif // BASE_NUMERICS_SAFE_MATH_H_ | 289 #endif // BASE_NUMERICS_SAFE_MATH_H_ |
| OLD | NEW |