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 |