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

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

Issue 2545253002: Add support for CheckedNumeric Max and Min constexpr functions (Closed)
Patch Set: stupid compilers with weak constexpr float support Created 4 years 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
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 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698