| 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_CONVERSIONS_H_ | 5 #ifndef BASE_NUMERICS_SAFE_CONVERSIONS_H_ |
| 6 #define BASE_NUMERICS_SAFE_CONVERSIONS_H_ | 6 #define BASE_NUMERICS_SAFE_CONVERSIONS_H_ |
| 7 | 7 |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 | 9 |
| 10 #include <limits> | 10 #include <limits> |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 static constexpr T lowest() { return std::numeric_limits<T>::lowest(); } | 99 static constexpr T lowest() { return std::numeric_limits<T>::lowest(); } |
| 100 static constexpr T Underflow() { | 100 static constexpr T Underflow() { |
| 101 return std::numeric_limits<T>::has_infinity | 101 return std::numeric_limits<T>::has_infinity |
| 102 ? std::numeric_limits<T>::infinity() * -1 | 102 ? std::numeric_limits<T>::infinity() * -1 |
| 103 : std::numeric_limits<T>::lowest(); | 103 : std::numeric_limits<T>::lowest(); |
| 104 } | 104 } |
| 105 }; | 105 }; |
| 106 | 106 |
| 107 namespace internal { | 107 namespace internal { |
| 108 | 108 |
| 109 template <typename T, template <typename> class S> | 109 template <typename Dst, template <typename> class S, typename Src> |
| 110 struct IsDefaultIntegralBounds { | |
| 111 static const bool value = | |
| 112 std::is_integral<T>::value && | |
| 113 S<T>::max() == SaturationDefaultHandler<T>::max() && | |
| 114 S<T>::lowest() == SaturationDefaultHandler<T>::lowest(); | |
| 115 }; | |
| 116 | |
| 117 // Integral to integral conversions have a special optimization for the | |
| 118 // standard bounds. | |
| 119 template <typename Dst, | |
| 120 template <typename> class S, | |
| 121 typename Src, | |
| 122 typename std::enable_if< | |
| 123 std::is_integral<Src>::value && | |
| 124 IsDefaultIntegralBounds<Dst, S>::value>::type* = nullptr> | |
| 125 constexpr Dst saturated_cast_impl(Src value, RangeCheck constraint) { | |
| 126 using UnsignedDst = typename std::make_unsigned<Dst>::type; | |
| 127 // The member fields in this class are lined up such that the compiler | |
| 128 // can saturate without branching in this case by adding the register | |
| 129 // with the bitfields directly to the integral max. | |
| 130 return constraint.IsValid() | |
| 131 ? static_cast<Dst>(value) | |
| 132 : static_cast<Dst>(UnsignedDst(constraint.IsUnderflowFlagSet()) + | |
| 133 std::numeric_limits<Dst>::max()); | |
| 134 } | |
| 135 | |
| 136 template <typename Dst, | |
| 137 template <typename> class S, | |
| 138 typename Src, | |
| 139 typename std::enable_if< | |
| 140 !std::is_integral<Src>::value || | |
| 141 !IsDefaultIntegralBounds<Dst, S>::value>::type* = nullptr> | |
| 142 constexpr Dst saturated_cast_impl(Src value, RangeCheck constraint) { | 110 constexpr Dst saturated_cast_impl(Src value, RangeCheck constraint) { |
| 143 // For some reason clang generates much better code when the branch is | 111 // For some reason clang generates much better code when the branch is |
| 144 // structured exactly this way, rather than a sequence of checks. | 112 // structured exactly this way, rather than a sequence of checks. |
| 145 return !constraint.IsOverflowFlagSet() | 113 return !constraint.IsOverflowFlagSet() |
| 146 ? (!constraint.IsUnderflowFlagSet() ? static_cast<Dst>(value) | 114 ? (!constraint.IsUnderflowFlagSet() ? static_cast<Dst>(value) |
| 147 : S<Dst>::Underflow()) | 115 : S<Dst>::Underflow()) |
| 148 // Skip this check for integral Src, which cannot be NaN. | 116 // Skip this check for integral Src, which cannot be NaN. |
| 149 : (std::is_integral<Src>::value || !constraint.IsUnderflowFlagSet() | 117 : (std::is_integral<Src>::value || !constraint.IsUnderflowFlagSet() |
| 150 ? S<Dst>::Overflow() | 118 ? S<Dst>::Overflow() |
| 151 : S<Dst>::NaN()); | 119 : S<Dst>::NaN()); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 using internal::StrictNumeric; | 263 using internal::StrictNumeric; |
| 296 using internal::MakeStrictNum; | 264 using internal::MakeStrictNum; |
| 297 using internal::IsValueNegative; | 265 using internal::IsValueNegative; |
| 298 | 266 |
| 299 // Explicitly make a shorter size_t alias for convenience. | 267 // Explicitly make a shorter size_t alias for convenience. |
| 300 using SizeT = StrictNumeric<size_t>; | 268 using SizeT = StrictNumeric<size_t>; |
| 301 | 269 |
| 302 } // namespace base | 270 } // namespace base |
| 303 | 271 |
| 304 #endif // BASE_NUMERICS_SAFE_CONVERSIONS_H_ | 272 #endif // BASE_NUMERICS_SAFE_CONVERSIONS_H_ |
| OLD | NEW |