Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(484)

Side by Side Diff: base/numerics/safe_math_impl.h

Issue 2522543002: Convert simple CheckedNumeric functions to constexpr (Closed)
Patch Set: complete Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/numerics/safe_math.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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_
OLDNEW
« no previous file with comments | « base/numerics/safe_math.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698