Chromium Code Reviews| 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 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 467 using result_type = typename UnsignedIntegerForSize< | 467 using result_type = typename UnsignedIntegerForSize< |
| 468 typename MaxExponentPromotion<T, U>::type>::type; | 468 typename MaxExponentPromotion<T, U>::type>::type; |
| 469 template <typename V = result_type> | 469 template <typename V = result_type> |
| 470 static bool Do(T x, U y, V* result) { | 470 static bool Do(T x, U y, V* result) { |
| 471 result_type tmp = static_cast<result_type>(x) ^ static_cast<result_type>(y); | 471 result_type tmp = static_cast<result_type>(x) ^ static_cast<result_type>(y); |
| 472 *result = static_cast<V>(tmp); | 472 *result = static_cast<V>(tmp); |
| 473 return IsValueInRangeForNumericType<V>(tmp); | 473 return IsValueInRangeForNumericType<V>(tmp); |
| 474 } | 474 } |
| 475 }; | 475 }; |
| 476 | 476 |
| 477 // Max doesn't really need to be implemented this way because it can't fail, | |
| 478 // but it makes the code much cleaner to use the MathOp wrappers. | |
| 479 template <typename T, typename U, class Enable = void> | |
| 480 struct CheckedMaxOp {}; | |
| 481 | |
| 482 template <typename T, typename U> | |
| 483 struct CheckedMaxOp< | |
| 484 T, | |
| 485 U, | |
| 486 typename std::enable_if<std::is_arithmetic<T>::value && | |
| 487 std::is_arithmetic<U>::value>::type> { | |
| 488 using result_type = typename MaxExponentPromotion<T, U>::type; | |
| 489 template <typename V = result_type> | |
| 490 static bool Do(T x, U y, V* result) { | |
| 491 *result = IsGreater<T, U>::Test(x, y) ? static_cast<result_type>(x) | |
| 492 : static_cast<result_type>(y); | |
| 493 return true; | |
| 494 } | |
| 495 }; | |
| 496 | |
| 497 // Min doesn't really need to be implemented this way because it can't fail, | |
| 498 // but it makes the code much cleaner to use the MathOp wrappers. | |
| 499 template <typename T, typename U, class Enable = void> | |
| 500 struct CheckedMinOp {}; | |
| 501 | |
| 502 template <typename T, typename U> | |
| 503 struct CheckedMinOp< | |
| 504 T, | |
| 505 U, | |
| 506 typename std::enable_if<std::is_arithmetic<T>::value && | |
| 507 std::is_arithmetic<U>::value>::type> { | |
| 508 using result_type = typename LowestValuePromotion<T, U>::type; | |
| 509 template <typename V = result_type> | |
| 510 static bool Do(T x, U y, V* result) { | |
| 511 *result = IsLess<T, U>::Test(x, y) ? static_cast<result_type>(x) | |
| 512 : static_cast<result_type>(y); | |
| 513 return true; | |
| 514 } | |
| 515 }; | |
| 516 | |
| 477 template <typename T> | 517 template <typename T> |
| 478 typename std::enable_if<std::numeric_limits<T>::is_integer && | 518 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 479 std::numeric_limits<T>::is_signed, | 519 std::numeric_limits<T>::is_signed, |
| 480 bool>::type | 520 bool>::type |
| 481 CheckedNeg(T value, T* result) { | 521 CheckedNeg(T value, T* result) { |
| 482 // The negation of signed min is min, so catch that one. | 522 // The negation of signed min is min, so catch that one. |
| 483 if (value != std::numeric_limits<T>::min()) { | 523 if (value != std::numeric_limits<T>::min()) { |
| 484 *result = static_cast<T>(-value); | 524 *result = static_cast<T>(-value); |
| 485 return true; | 525 return true; |
| 486 } | 526 } |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 681 Src value, | 721 Src value, |
| 682 typename std::enable_if<std::numeric_limits<Src>::is_specialized, | 722 typename std::enable_if<std::numeric_limits<Src>::is_specialized, |
| 683 int>::type = 0) | 723 int>::type = 0) |
| 684 : value_(static_cast<T>(value)) {} | 724 : value_(static_cast<T>(value)) {} |
| 685 | 725 |
| 686 // Copy constructor. | 726 // Copy constructor. |
| 687 template <typename Src> | 727 template <typename Src> |
| 688 constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs) | 728 constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs) |
| 689 : value_(static_cast<T>(rhs.value())) {} | 729 : value_(static_cast<T>(rhs.value())) {} |
| 690 | 730 |
| 691 constexpr bool is_valid() const { return std::isfinite(value_); } | 731 constexpr bool is_valid() const { |
| 732 // Written this way because std::isfinite is not reliably constexpr. | |
| 733 // TODO(jschuh): Fix this if the libraries ever get fixed. | |
| 734 return value_ <= std::numeric_limits<T>::max() && | |
|
dcheng
2016/12/03 21:34:29
Out of curiosity, how come this used to work?
jschuh
2016/12/03 22:29:12
We didn't have any code tickling the constexpr pat
| |
| 735 value_ >= std::numeric_limits<T>::lowest(); | |
| 736 } | |
| 692 constexpr T value() const { return value_; } | 737 constexpr T value() const { return value_; } |
| 693 }; | 738 }; |
| 694 | 739 |
| 695 template <template <typename, typename, typename> class M, | 740 template <template <typename, typename, typename> class M, |
| 696 typename L, | 741 typename L, |
| 697 typename R> | 742 typename R> |
| 698 struct MathWrapper { | 743 struct MathWrapper { |
| 699 using math = M<typename UnderlyingType<L>::type, | 744 using math = M<typename UnderlyingType<L>::type, |
| 700 typename UnderlyingType<R>::type, | 745 typename UnderlyingType<R>::type, |
| 701 void>; | 746 void>; |
| 702 using type = typename math::result_type; | 747 using type = typename math::result_type; |
| 703 }; | 748 }; |
| 704 | 749 |
| 705 } // namespace internal | 750 } // namespace internal |
| 706 } // namespace base | 751 } // namespace base |
| 707 | 752 |
| 708 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ | 753 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ |
| OLD | NEW |