| 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 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 typename std::enable_if<std::numeric_limits<T>::is_integer && | 640 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 641 !std::numeric_limits<T>::is_signed, | 641 !std::numeric_limits<T>::is_signed, |
| 642 bool>::type | 642 bool>::type |
| 643 CheckedAbs(T value, T* result) { | 643 CheckedAbs(T value, T* result) { |
| 644 // T is unsigned, so |value| must already be positive. | 644 // T is unsigned, so |value| must already be positive. |
| 645 *result = value; | 645 *result = value; |
| 646 return true; | 646 return true; |
| 647 } | 647 } |
| 648 | 648 |
| 649 template <typename T> | 649 template <typename T> |
| 650 typename std::enable_if<std::numeric_limits<T>::is_integer && | 650 constexpr |
| 651 std::numeric_limits<T>::is_signed, | 651 typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 652 typename UnsignedIntegerForSize<T>::type>::type | 652 std::numeric_limits<T>::is_signed, |
| 653 SafeUnsignedAbs(T value) { | 653 typename UnsignedIntegerForSize<T>::type>::type |
| 654 SafeUnsignedAbs(T value) { |
| 654 typedef typename UnsignedIntegerForSize<T>::type UnsignedT; | 655 typedef typename UnsignedIntegerForSize<T>::type UnsignedT; |
| 655 return value == std::numeric_limits<T>::min() | 656 return value == std::numeric_limits<T>::min() |
| 656 ? static_cast<UnsignedT>(std::numeric_limits<T>::max()) + 1 | 657 ? static_cast<UnsignedT>(std::numeric_limits<T>::max()) + 1 |
| 657 : static_cast<UnsignedT>(std::abs(value)); | 658 : static_cast<UnsignedT>(std::abs(value)); |
| 658 } | 659 } |
| 659 | 660 |
| 660 template <typename T> | 661 template <typename T> |
| 661 typename std::enable_if<std::numeric_limits<T>::is_integer && | 662 constexpr typename std::enable_if<std::numeric_limits<T>::is_integer && |
| 662 !std::numeric_limits<T>::is_signed, | 663 !std::numeric_limits<T>::is_signed, |
| 663 T>::type | 664 T>::type |
| 664 SafeUnsignedAbs(T value) { | 665 SafeUnsignedAbs(T value) { |
| 665 // T is unsigned, so |value| must already be positive. | 666 // T is unsigned, so |value| must already be positive. |
| 666 return static_cast<T>(value); | 667 return static_cast<T>(value); |
| 667 } | 668 } |
| 668 | 669 |
| 669 // This is just boilerplate that wraps the standard floating point arithmetic. | 670 // This is just boilerplate that wraps the standard floating point arithmetic. |
| 670 // A macro isn't the nicest solution, but it beats rewriting these repeatedly. | 671 // A macro isn't the nicest solution, but it beats rewriting these repeatedly. |
| 671 #define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \ | 672 #define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \ |
| 672 template <typename T, typename U> \ | 673 template <typename T, typename U> \ |
| 673 struct Checked##NAME<T, U, typename std::enable_if< \ | 674 struct Checked##NAME<T, U, typename std::enable_if< \ |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 template <typename T> | 733 template <typename T> |
| 733 class CheckedNumericState<T, NUMERIC_INTEGER> { | 734 class CheckedNumericState<T, NUMERIC_INTEGER> { |
| 734 private: | 735 private: |
| 735 T value_; | 736 T value_; |
| 736 bool is_valid_; | 737 bool is_valid_; |
| 737 | 738 |
| 738 public: | 739 public: |
| 739 template <typename Src, NumericRepresentation type> | 740 template <typename Src, NumericRepresentation type> |
| 740 friend class CheckedNumericState; | 741 friend class CheckedNumericState; |
| 741 | 742 |
| 742 CheckedNumericState() : value_(0), is_valid_(true) {} | 743 constexpr CheckedNumericState() : value_(0), is_valid_(true) {} |
| 743 | 744 |
| 744 template <typename Src> | 745 template <typename Src> |
| 745 CheckedNumericState(Src value, bool is_valid) | 746 constexpr CheckedNumericState(Src value, bool is_valid) |
| 746 : value_(static_cast<T>(value)), | 747 : value_(static_cast<T>(value)), |
| 747 is_valid_(is_valid && | 748 is_valid_(is_valid && IsValueInRangeForNumericType<T>(value)) { |
| 748 (DstRangeRelationToSrcRange<T>(value) == RANGE_VALID)) { | |
| 749 static_assert(std::numeric_limits<Src>::is_specialized, | 749 static_assert(std::numeric_limits<Src>::is_specialized, |
| 750 "Argument must be numeric."); | 750 "Argument must be numeric."); |
| 751 } | 751 } |
| 752 | 752 |
| 753 // Copy constructor. | 753 // Copy constructor. |
| 754 template <typename Src> | 754 template <typename Src> |
| 755 CheckedNumericState(const CheckedNumericState<Src>& rhs) | 755 constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs) |
| 756 : value_(static_cast<T>(rhs.value())), is_valid_(rhs.IsValid()) {} | 756 : value_(static_cast<T>(rhs.value())), is_valid_(rhs.IsValid()) {} |
| 757 | 757 |
| 758 template <typename Src> | 758 template <typename Src> |
| 759 explicit CheckedNumericState( | 759 constexpr explicit CheckedNumericState( |
| 760 Src value, | 760 Src value, |
| 761 typename std::enable_if<std::numeric_limits<Src>::is_specialized, | 761 typename std::enable_if<std::numeric_limits<Src>::is_specialized, |
| 762 int>::type = 0) | 762 int>::type = 0) |
| 763 : value_(static_cast<T>(value)), | 763 : value_(static_cast<T>(value)), |
| 764 is_valid_(DstRangeRelationToSrcRange<T>(value) == RANGE_VALID) {} | 764 is_valid_(IsValueInRangeForNumericType<T>(value)) {} |
| 765 | 765 |
| 766 bool is_valid() const { return is_valid_; } | 766 constexpr bool is_valid() const { return is_valid_; } |
| 767 T value() const { return value_; } | 767 constexpr T value() const { return value_; } |
| 768 }; | 768 }; |
| 769 | 769 |
| 770 // Floating points maintain their own validity, but need translation wrappers. | 770 // Floating points maintain their own validity, but need translation wrappers. |
| 771 template <typename T> | 771 template <typename T> |
| 772 class CheckedNumericState<T, NUMERIC_FLOATING> { | 772 class CheckedNumericState<T, NUMERIC_FLOATING> { |
| 773 private: | 773 private: |
| 774 T value_; | 774 T value_; |
| 775 | 775 |
| 776 public: | 776 public: |
| 777 template <typename Src, NumericRepresentation type> | 777 template <typename Src, NumericRepresentation type> |
| 778 friend class CheckedNumericState; | 778 friend class CheckedNumericState; |
| 779 | 779 |
| 780 CheckedNumericState() : value_(0.0) {} | 780 constexpr CheckedNumericState() : value_(0.0) {} |
| 781 | 781 |
| 782 template <typename Src> | 782 template <typename Src> |
| 783 CheckedNumericState( | 783 constexpr CheckedNumericState( |
| 784 Src value, | 784 Src value, |
| 785 bool is_valid, | 785 bool is_valid, |
| 786 typename std::enable_if<std::numeric_limits<Src>::is_integer, int>::type = | 786 typename std::enable_if<std::numeric_limits<Src>::is_integer, int>::type = |
| 787 0) { | 787 0) |
| 788 value_ = (is_valid && (DstRangeRelationToSrcRange<T>(value) == RANGE_VALID)) | 788 : value_((is_valid && IsValueInRangeForNumericType<T>(value)) |
| 789 ? static_cast<T>(value) | 789 ? static_cast<T>(value) |
| 790 : std::numeric_limits<T>::quiet_NaN(); | 790 : std::numeric_limits<T>::quiet_NaN()) {} |
| 791 } | |
| 792 | 791 |
| 793 template <typename Src> | 792 template <typename Src> |
| 794 explicit CheckedNumericState( | 793 constexpr explicit CheckedNumericState( |
| 795 Src value, | 794 Src value, |
| 796 typename std::enable_if<std::numeric_limits<Src>::is_specialized, | 795 typename std::enable_if<std::numeric_limits<Src>::is_specialized, |
| 797 int>::type = 0) | 796 int>::type = 0) |
| 798 : value_(static_cast<T>(value)) {} | 797 : value_(static_cast<T>(value)) {} |
| 799 | 798 |
| 800 // Copy constructor. | 799 // Copy constructor. |
| 801 template <typename Src> | 800 template <typename Src> |
| 802 CheckedNumericState(const CheckedNumericState<Src>& rhs) | 801 constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs) |
| 803 : value_(static_cast<T>(rhs.value())) {} | 802 : value_(static_cast<T>(rhs.value())) {} |
| 804 | 803 |
| 805 bool is_valid() const { return std::isfinite(value_); } | 804 constexpr bool is_valid() const { return std::isfinite(value_); } |
| 806 T value() const { return value_; } | 805 constexpr T value() const { return value_; } |
| 807 }; | 806 }; |
| 808 | 807 |
| 809 } // namespace internal | 808 } // namespace internal |
| 810 } // namespace base | 809 } // namespace base |
| 811 | 810 |
| 812 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ | 811 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ |
| OLD | NEW |