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 typename 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 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 // Absolute value of a positive is just its identiy. |
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 // Absolute value of a positive is just its identiy. | |
Jeffrey Yasskin
2015/09/15 23:58:25
"T is unsigned, so |value| must already be positiv
| |
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 |