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 |