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 <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <cmath> | 10 #include <cmath> |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 sizeof(Integer) * 2, | 83 sizeof(Integer) * 2, |
84 std::numeric_limits<Integer>::is_signed>::type>::type type; | 84 std::numeric_limits<Integer>::is_signed>::type>::type type; |
85 }; | 85 }; |
86 | 86 |
87 template <typename Integer> | 87 template <typename Integer> |
88 struct PositionOfSignBit { | 88 struct PositionOfSignBit { |
89 static const typename enable_if<std::numeric_limits<Integer>::is_integer, | 89 static const typename enable_if<std::numeric_limits<Integer>::is_integer, |
90 size_t>::type value = 8 * sizeof(Integer) - 1; | 90 size_t>::type value = 8 * sizeof(Integer) - 1; |
91 }; | 91 }; |
92 | 92 |
| 93 // This is used for UnsignedAbs, where we need to support floating-point |
| 94 // template instantiations even though we don't actually support the operations. |
| 95 // However, there is no corresponding implementation of e.g. CheckedUnsignedAbs, |
| 96 // so the float versions will not compile. |
| 97 template <typename Numeric, |
| 98 bool IsInteger = std::numeric_limits<Numeric>::is_integer, |
| 99 bool IsFloat = std::numeric_limits<Numeric>::is_iec559> |
| 100 struct UnsignedOrFloatForSize; |
| 101 |
| 102 template <typename Numeric> |
| 103 struct UnsignedOrFloatForSize<Numeric, true, false> { |
| 104 typedef typename UnsignedIntegerForSize<Numeric>::type type; |
| 105 }; |
| 106 |
| 107 template <typename Numeric> |
| 108 struct UnsignedOrFloatForSize<Numeric, false, true> { |
| 109 typedef Numeric type; |
| 110 }; |
| 111 |
93 // Helper templates for integer manipulations. | 112 // Helper templates for integer manipulations. |
94 | 113 |
95 template <typename T> | 114 template <typename T> |
96 bool HasSignBit(T x) { | 115 bool HasSignBit(T x) { |
97 // Cast to unsigned since right shift on signed is undefined. | 116 // Cast to unsigned since right shift on signed is undefined. |
98 return !!(static_cast<typename UnsignedIntegerForSize<T>::type>(x) >> | 117 return !!(static_cast<typename UnsignedIntegerForSize<T>::type>(x) >> |
99 PositionOfSignBit<T>::value); | 118 PositionOfSignBit<T>::value); |
100 } | 119 } |
101 | 120 |
102 // This wrapper undoes the standard integer promotions. | 121 // This wrapper undoes the standard integer promotions. |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 *validity = | 296 *validity = |
278 value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; | 297 value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; |
279 return static_cast<T>(std::abs(value)); | 298 return static_cast<T>(std::abs(value)); |
280 } | 299 } |
281 | 300 |
282 template <typename T> | 301 template <typename T> |
283 typename enable_if< | 302 typename enable_if< |
284 std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, | 303 std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, |
285 T>::type | 304 T>::type |
286 CheckedAbs(T value, RangeConstraint* validity) { | 305 CheckedAbs(T value, RangeConstraint* validity) { |
287 // Absolute value of a positive is just its identiy. | 306 // T is unsigned, so |value| must already be positive. |
288 *validity = RANGE_VALID; | 307 *validity = RANGE_VALID; |
289 return value; | 308 return value; |
290 } | 309 } |
291 | 310 |
| 311 template <typename T> |
| 312 typename enable_if<std::numeric_limits<T>::is_integer && |
| 313 std::numeric_limits<T>::is_signed, |
| 314 typename UnsignedIntegerForSize<T>::type>::type |
| 315 CheckedUnsignedAbs(T value) { |
| 316 typedef typename UnsignedIntegerForSize<T>::type UnsignedT; |
| 317 return value == std::numeric_limits<T>::min() |
| 318 ? static_cast<UnsignedT>(std::numeric_limits<T>::max()) + 1 |
| 319 : static_cast<UnsignedT>(std::abs(value)); |
| 320 } |
| 321 |
| 322 template <typename T> |
| 323 typename enable_if<std::numeric_limits<T>::is_integer && |
| 324 !std::numeric_limits<T>::is_signed, |
| 325 T>::type |
| 326 CheckedUnsignedAbs(T value) { |
| 327 // T is unsigned, so |value| must already be positive. |
| 328 return value; |
| 329 } |
| 330 |
292 // These are the floating point stubs that the compiler needs to see. Only the | 331 // These are the floating point stubs that the compiler needs to see. Only the |
293 // negation operation is ever called. | 332 // negation operation is ever called. |
294 #define BASE_FLOAT_ARITHMETIC_STUBS(NAME) \ | 333 #define BASE_FLOAT_ARITHMETIC_STUBS(NAME) \ |
295 template <typename T> \ | 334 template <typename T> \ |
296 typename enable_if<std::numeric_limits<T>::is_iec559, T>::type \ | 335 typename enable_if<std::numeric_limits<T>::is_iec559, T>::type \ |
297 Checked##NAME(T, T, RangeConstraint*) { \ | 336 Checked##NAME(T, T, RangeConstraint*) { \ |
298 NOTREACHED(); \ | 337 NOTREACHED(); \ |
299 return 0; \ | 338 return 0; \ |
300 } | 339 } |
301 | 340 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 sizeof(T) >= (2 * sizeof(Lhs)) && | 531 sizeof(T) >= (2 * sizeof(Lhs)) && |
493 StaticDstRangeRelationToSrcRange<T, Rhs>::value != | 532 StaticDstRangeRelationToSrcRange<T, Rhs>::value != |
494 NUMERIC_RANGE_CONTAINED && | 533 NUMERIC_RANGE_CONTAINED && |
495 sizeof(T) >= (2 * sizeof(Rhs)); | 534 sizeof(T) >= (2 * sizeof(Rhs)); |
496 }; | 535 }; |
497 | 536 |
498 } // namespace internal | 537 } // namespace internal |
499 } // namespace base | 538 } // namespace base |
500 | 539 |
501 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ | 540 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ |
OLD | NEW |