| 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 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 | 216 |
| 217 } else { | 217 } else { |
| 218 if (y > 0) | 218 if (y > 0) |
| 219 *validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID | 219 *validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID |
| 220 : RANGE_UNDERFLOW; | 220 : RANGE_UNDERFLOW; |
| 221 else | 221 else |
| 222 *validity = | 222 *validity = |
| 223 y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW; | 223 y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW; |
| 224 } | 224 } |
| 225 | 225 |
| 226 return static_cast<T>(x * y); | 226 return static_cast<T>(*validity == RANGE_VALID ? x * y : 0); |
| 227 } | 227 } |
| 228 | 228 |
| 229 template <typename T> | 229 template <typename T> |
| 230 typename std::enable_if<std::numeric_limits<T>::is_integer && | 230 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 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>(x * y); | 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 an invalid negation on signed min/-1. |
| 242 template <typename T> | 242 template <typename T> |
| 243 T CheckedDiv(T x, | 243 T CheckedDiv(T x, |
| 244 T y, | 244 T y, |
| 245 RangeConstraint* validity, | 245 RangeConstraint* validity, |
| 246 typename std::enable_if<std::numeric_limits<T>::is_integer, | 246 typename std::enable_if<std::numeric_limits<T>::is_integer, |
| 247 int>::type = 0) { | 247 int>::type = 0) { |
| 248 if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() && | 248 if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() && |
| 249 y == static_cast<T>(-1)) { | 249 y == static_cast<T>(-1)) { |
| 250 *validity = RANGE_OVERFLOW; | 250 *validity = RANGE_OVERFLOW; |
| 251 return std::numeric_limits<T>::min(); | 251 return std::numeric_limits<T>::min(); |
| 252 } | 252 } |
| 253 | 253 |
| 254 *validity = RANGE_VALID; | 254 *validity = RANGE_VALID; |
| 255 return static_cast<T>(x / y); | 255 return static_cast<T>(x / y); |
| 256 } | 256 } |
| 257 | 257 |
| 258 template <typename T> | 258 template <typename T> |
| 259 typename std::enable_if<std::numeric_limits<T>::is_integer && | 259 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 260 std::numeric_limits<T>::is_signed, | 260 std::numeric_limits<T>::is_signed, |
| 261 T>::type | 261 T>::type |
| 262 CheckedMod(T x, T y, RangeConstraint* validity) { | 262 CheckedMod(T x, T y, RangeConstraint* validity) { |
| 263 *validity = y > 0 ? RANGE_VALID : RANGE_INVALID; | 263 *validity = y > 0 ? RANGE_VALID : RANGE_INVALID; |
| 264 return static_cast<T>(x % y); | 264 return static_cast<T>(*validity == RANGE_VALID ? x % y: 0); |
| 265 } | 265 } |
| 266 | 266 |
| 267 template <typename T> | 267 template <typename T> |
| 268 typename std::enable_if<std::numeric_limits<T>::is_integer && | 268 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 269 !std::numeric_limits<T>::is_signed, | 269 !std::numeric_limits<T>::is_signed, |
| 270 T>::type | 270 T>::type |
| 271 CheckedMod(T x, T y, RangeConstraint* validity) { | 271 CheckedMod(T x, T y, RangeConstraint* validity) { |
| 272 *validity = RANGE_VALID; | 272 *validity = RANGE_VALID; |
| 273 return static_cast<T>(x % y); | 273 return static_cast<T>(x % y); |
| 274 } | 274 } |
| 275 | 275 |
| 276 template <typename T> | 276 template <typename T> |
| 277 typename std::enable_if<std::numeric_limits<T>::is_integer && | 277 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 278 std::numeric_limits<T>::is_signed, | 278 std::numeric_limits<T>::is_signed, |
| 279 T>::type | 279 T>::type |
| 280 CheckedNeg(T value, RangeConstraint* validity) { | 280 CheckedNeg(T value, RangeConstraint* validity) { |
| 281 *validity = | 281 *validity = |
| 282 value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; | 282 value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; |
| 283 // The negation of signed min is min, so catch that one. | 283 // The negation of signed min is min, so catch that one. |
| 284 return static_cast<T>(-value); | 284 return static_cast<T>(*validity == RANGE_VALID ? -value : 0); |
| 285 } | 285 } |
| 286 | 286 |
| 287 template <typename T> | 287 template <typename T> |
| 288 typename std::enable_if<std::numeric_limits<T>::is_integer && | 288 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 289 !std::numeric_limits<T>::is_signed, | 289 !std::numeric_limits<T>::is_signed, |
| 290 T>::type | 290 T>::type |
| 291 CheckedNeg(T value, RangeConstraint* validity) { | 291 CheckedNeg(T value, RangeConstraint* validity) { |
| 292 // The only legal unsigned negation is zero. | 292 // The only legal unsigned negation is zero. |
| 293 *validity = value ? RANGE_UNDERFLOW : RANGE_VALID; | 293 *validity = value ? RANGE_UNDERFLOW : RANGE_VALID; |
| 294 return static_cast<T>( | 294 return static_cast<T>(*validity == RANGE_VALID ? |
| 295 -static_cast<typename SignedIntegerForSize<T>::type>(value)); | 295 -static_cast<typename SignedIntegerForSize<T>::type>(value) : 0); |
| 296 } | 296 } |
| 297 | 297 |
| 298 template <typename T> | 298 template <typename T> |
| 299 typename std::enable_if<std::numeric_limits<T>::is_integer && | 299 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 300 std::numeric_limits<T>::is_signed, | 300 std::numeric_limits<T>::is_signed, |
| 301 T>::type | 301 T>::type |
| 302 CheckedAbs(T value, RangeConstraint* validity) { | 302 CheckedAbs(T value, RangeConstraint* validity) { |
| 303 *validity = | 303 *validity = |
| 304 value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; | 304 value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; |
| 305 return static_cast<T>(std::abs(value)); | 305 return static_cast<T>(*validity == RANGE_VALID ? std::abs(value) : 0); |
| 306 } | 306 } |
| 307 | 307 |
| 308 template <typename T> | 308 template <typename T> |
| 309 typename std::enable_if<std::numeric_limits<T>::is_integer && | 309 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 310 !std::numeric_limits<T>::is_signed, | 310 !std::numeric_limits<T>::is_signed, |
| 311 T>::type | 311 T>::type |
| 312 CheckedAbs(T value, RangeConstraint* validity) { | 312 CheckedAbs(T value, RangeConstraint* validity) { |
| 313 // T is unsigned, so |value| must already be positive. | 313 // T is unsigned, so |value| must already be positive. |
| 314 *validity = RANGE_VALID; | 314 *validity = RANGE_VALID; |
| 315 return value; | 315 return value; |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 sizeof(T) >= (2 * sizeof(Lhs)) && | 523 sizeof(T) >= (2 * sizeof(Lhs)) && |
| 524 StaticDstRangeRelationToSrcRange<T, Rhs>::value != | 524 StaticDstRangeRelationToSrcRange<T, Rhs>::value != |
| 525 NUMERIC_RANGE_CONTAINED && | 525 NUMERIC_RANGE_CONTAINED && |
| 526 sizeof(T) >= (2 * sizeof(Rhs)); | 526 sizeof(T) >= (2 * sizeof(Rhs)); |
| 527 }; | 527 }; |
| 528 | 528 |
| 529 } // namespace internal | 529 } // namespace internal |
| 530 } // namespace base | 530 } // namespace base |
| 531 | 531 |
| 532 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ | 532 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ |
| OLD | NEW |