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() && |
| 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 |