| 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 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 !std::numeric_limits<T>::is_signed && | 231 !std::numeric_limits<T>::is_signed && |
| 232 (sizeof(T) * 2 > sizeof(uintmax_t)), | 232 (sizeof(T) * 2 > sizeof(uintmax_t)), |
| 233 T>::type | 233 T>::type |
| 234 CheckedMul(T x, T y, RangeConstraint* validity) { | 234 CheckedMul(T x, T y, RangeConstraint* validity) { |
| 235 *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y) | 235 *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y) |
| 236 ? RANGE_VALID | 236 ? RANGE_VALID |
| 237 : RANGE_OVERFLOW; | 237 : RANGE_OVERFLOW; |
| 238 return static_cast<T>(*validity == RANGE_VALID ? x * y : 0); | 238 return static_cast<T>(*validity == RANGE_VALID ? x * y : 0); |
| 239 } | 239 } |
| 240 | 240 |
| 241 // Division just requires a check for an invalid negation on signed min/-1. | 241 // Division just requires a check for a zero denominator or an invalid negation |
| 242 // on signed min/-1. |
| 242 template <typename T> | 243 template <typename T> |
| 243 T CheckedDiv(T x, | 244 T CheckedDiv(T x, |
| 244 T y, | 245 T y, |
| 245 RangeConstraint* validity, | 246 RangeConstraint* validity, |
| 246 typename std::enable_if<std::numeric_limits<T>::is_integer, | 247 typename std::enable_if<std::numeric_limits<T>::is_integer, |
| 247 int>::type = 0) { | 248 int>::type = 0) { |
| 249 if (y == 0) { |
| 250 *validity = RANGE_INVALID; |
| 251 return static_cast<T>(0); |
| 252 } |
| 248 if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() && | 253 if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() && |
| 249 y == static_cast<T>(-1)) { | 254 y == static_cast<T>(-1)) { |
| 250 *validity = RANGE_OVERFLOW; | 255 *validity = RANGE_OVERFLOW; |
| 251 return std::numeric_limits<T>::min(); | 256 return std::numeric_limits<T>::min(); |
| 252 } | 257 } |
| 253 | 258 |
| 254 *validity = RANGE_VALID; | 259 *validity = RANGE_VALID; |
| 255 return static_cast<T>(x / y); | 260 return static_cast<T>(x / y); |
| 256 } | 261 } |
| 257 | 262 |
| 258 template <typename T> | 263 template <typename T> |
| 259 typename std::enable_if<std::numeric_limits<T>::is_integer && | 264 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 260 std::numeric_limits<T>::is_signed, | 265 std::numeric_limits<T>::is_signed, |
| 261 T>::type | 266 T>::type |
| 262 CheckedMod(T x, T y, RangeConstraint* validity) { | 267 CheckedMod(T x, T y, RangeConstraint* validity) { |
| 263 *validity = y > 0 ? RANGE_VALID : RANGE_INVALID; | 268 *validity = y > 0 ? RANGE_VALID : RANGE_INVALID; |
| 264 return static_cast<T>(*validity == RANGE_VALID ? x % y: 0); | 269 return static_cast<T>(*validity == RANGE_VALID ? x % y: 0); |
| 265 } | 270 } |
| 266 | 271 |
| 267 template <typename T> | 272 template <typename T> |
| 268 typename std::enable_if<std::numeric_limits<T>::is_integer && | 273 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 269 !std::numeric_limits<T>::is_signed, | 274 !std::numeric_limits<T>::is_signed, |
| 270 T>::type | 275 T>::type |
| 271 CheckedMod(T x, T y, RangeConstraint* validity) { | 276 CheckedMod(T x, T y, RangeConstraint* validity) { |
| 272 *validity = RANGE_VALID; | 277 *validity = y != 0 ? RANGE_VALID : RANGE_INVALID; |
| 273 return static_cast<T>(x % y); | 278 return static_cast<T>(*validity == RANGE_VALID ? x % y: 0); |
| 274 } | 279 } |
| 275 | 280 |
| 276 template <typename T> | 281 template <typename T> |
| 277 typename std::enable_if<std::numeric_limits<T>::is_integer && | 282 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 278 std::numeric_limits<T>::is_signed, | 283 std::numeric_limits<T>::is_signed, |
| 279 T>::type | 284 T>::type |
| 280 CheckedNeg(T value, RangeConstraint* validity) { | 285 CheckedNeg(T value, RangeConstraint* validity) { |
| 281 *validity = | 286 *validity = |
| 282 value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; | 287 value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; |
| 283 // The negation of signed min is min, so catch that one. | 288 // The negation of signed min is min, so catch that one. |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 sizeof(T) >= (2 * sizeof(Lhs)) && | 528 sizeof(T) >= (2 * sizeof(Lhs)) && |
| 524 StaticDstRangeRelationToSrcRange<T, Rhs>::value != | 529 StaticDstRangeRelationToSrcRange<T, Rhs>::value != |
| 525 NUMERIC_RANGE_CONTAINED && | 530 NUMERIC_RANGE_CONTAINED && |
| 526 sizeof(T) >= (2 * sizeof(Rhs)); | 531 sizeof(T) >= (2 * sizeof(Rhs)); |
| 527 }; | 532 }; |
| 528 | 533 |
| 529 } // namespace internal | 534 } // namespace internal |
| 530 } // namespace base | 535 } // namespace base |
| 531 | 536 |
| 532 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ | 537 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ |
| OLD | NEW |