| 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 <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 std::is_arithmetic<U>::value>::type> { | 465 std::is_arithmetic<U>::value>::type> { |
| 466 using result_type = typename LowestValuePromotion<T, U>::type; | 466 using result_type = typename LowestValuePromotion<T, U>::type; |
| 467 template <typename V = result_type> | 467 template <typename V = result_type> |
| 468 static bool Do(T x, U y, V* result) { | 468 static bool Do(T x, U y, V* result) { |
| 469 *result = IsLess<T, U>::Test(x, y) ? static_cast<result_type>(x) | 469 *result = IsLess<T, U>::Test(x, y) ? static_cast<result_type>(x) |
| 470 : static_cast<result_type>(y); | 470 : static_cast<result_type>(y); |
| 471 return true; | 471 return true; |
| 472 } | 472 } |
| 473 }; | 473 }; |
| 474 | 474 |
| 475 template <typename T, | |
| 476 typename std::enable_if<std::is_integral<T>::value && | |
| 477 std::is_signed<T>::value>::type* = nullptr> | |
| 478 bool CheckedNeg(T value, T* result) { | |
| 479 // The negation of signed min is min, so catch that one. | |
| 480 if (value != std::numeric_limits<T>::lowest()) { | |
| 481 *result = static_cast<T>(-value); | |
| 482 return true; | |
| 483 } | |
| 484 return false; | |
| 485 } | |
| 486 | |
| 487 template <typename T, | |
| 488 typename std::enable_if<std::is_integral<T>::value && | |
| 489 !std::is_signed<T>::value>::type* = nullptr> | |
| 490 bool CheckedNeg(T value, T* result) { | |
| 491 if (!value) { | |
| 492 *result = static_cast<T>(0); | |
| 493 return true; | |
| 494 } | |
| 495 return false; | |
| 496 } | |
| 497 | |
| 498 template <typename T, | |
| 499 typename std::enable_if<std::is_integral<T>::value && | |
| 500 !std::is_signed<T>::value>::type* = nullptr> | |
| 501 bool CheckedInv(T value, T* result) { | |
| 502 *result = ~value; | |
| 503 return true; | |
| 504 } | |
| 505 | |
| 506 template <typename T, | |
| 507 typename std::enable_if<std::is_integral<T>::value && | |
| 508 std::is_signed<T>::value>::type* = nullptr> | |
| 509 bool CheckedAbs(T value, T* result) { | |
| 510 *result = static_cast<T>(SafeUnsignedAbs(value)); | |
| 511 return *result != std::numeric_limits<T>::lowest(); | |
| 512 } | |
| 513 | |
| 514 template <typename T, | |
| 515 typename std::enable_if<std::is_integral<T>::value && | |
| 516 !std::is_signed<T>::value>::type* = nullptr> | |
| 517 bool CheckedAbs(T value, T* result) { | |
| 518 // T is unsigned, so |value| must already be positive. | |
| 519 *result = value; | |
| 520 return true; | |
| 521 } | |
| 522 | |
| 523 // This is just boilerplate that wraps the standard floating point arithmetic. | 475 // This is just boilerplate that wraps the standard floating point arithmetic. |
| 524 // A macro isn't the nicest solution, but it beats rewriting these repeatedly. | 476 // A macro isn't the nicest solution, but it beats rewriting these repeatedly. |
| 525 #define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \ | 477 #define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \ |
| 526 template <typename T, typename U> \ | 478 template <typename T, typename U> \ |
| 527 struct Checked##NAME##Op< \ | 479 struct Checked##NAME##Op< \ |
| 528 T, U, typename std::enable_if<std::is_floating_point<T>::value || \ | 480 T, U, typename std::enable_if<std::is_floating_point<T>::value || \ |
| 529 std::is_floating_point<U>::value>::type> { \ | 481 std::is_floating_point<U>::value>::type> { \ |
| 530 using result_type = typename MaxExponentPromotion<T, U>::type; \ | 482 using result_type = typename MaxExponentPromotion<T, U>::type; \ |
| 531 template <typename V> \ | 483 template <typename V> \ |
| 532 static bool Do(T x, U y, V* result) { \ | 484 static bool Do(T x, U y, V* result) { \ |
| 533 using Promotion = typename MaxExponentPromotion<T, U>::type; \ | 485 using Promotion = typename MaxExponentPromotion<T, U>::type; \ |
| 534 Promotion presult = x OP y; \ | 486 Promotion presult = x OP y; \ |
| 535 *result = static_cast<V>(presult); \ | 487 *result = static_cast<V>(presult); \ |
| 536 return IsValueInRangeForNumericType<V>(presult); \ | 488 return IsValueInRangeForNumericType<V>(presult); \ |
| 537 } \ | 489 } \ |
| 538 }; | 490 }; |
| 539 | 491 |
| 540 BASE_FLOAT_ARITHMETIC_OPS(Add, +) | 492 BASE_FLOAT_ARITHMETIC_OPS(Add, +) |
| 541 BASE_FLOAT_ARITHMETIC_OPS(Sub, -) | 493 BASE_FLOAT_ARITHMETIC_OPS(Sub, -) |
| 542 BASE_FLOAT_ARITHMETIC_OPS(Mul, *) | 494 BASE_FLOAT_ARITHMETIC_OPS(Mul, *) |
| 543 BASE_FLOAT_ARITHMETIC_OPS(Div, /) | 495 BASE_FLOAT_ARITHMETIC_OPS(Div, /) |
| 544 | 496 |
| 545 #undef BASE_FLOAT_ARITHMETIC_OPS | 497 #undef BASE_FLOAT_ARITHMETIC_OPS |
| 546 | 498 |
| 547 template < | 499 // Wrap the unary operations to allow SFINAE when instantiating integrals versus |
| 548 typename T, | 500 // floating points. These don't perform any overflow checking. Rather, they |
| 549 typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> | 501 // exhibit well-defined overflow semantics and rely on the caller to detect |
| 550 bool CheckedNeg(T value, T* result) { | 502 // if an overflow occured. |
| 551 *result = static_cast<T>(-value); | 503 |
| 552 return true; | 504 template <typename T, |
| 505 typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> |
| 506 constexpr T NegateWrapper(T value) { |
| 507 using UnsignedT = typename std::make_unsigned<T>::type; |
| 508 // This will compile to a NEG on Intel, and is normal negation on ARM. |
| 509 return static_cast<T>(UnsignedT(0) - static_cast<UnsignedT>(value)); |
| 553 } | 510 } |
| 554 | 511 |
| 555 template < | 512 template < |
| 556 typename T, | 513 typename T, |
| 557 typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> | 514 typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> |
| 558 bool CheckedAbs(T value, T* result) { | 515 constexpr T NegateWrapper(T value) { |
| 559 *result = static_cast<T>(std::abs(value)); | 516 return -value; |
| 560 return true; | 517 } |
| 518 |
| 519 template <typename T, |
| 520 typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> |
| 521 constexpr typename std::make_unsigned<T>::type InvertWrapper(T value) { |
| 522 return ~value; |
| 523 } |
| 524 |
| 525 template <typename T, |
| 526 typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> |
| 527 constexpr T AbsWrapper(T value) { |
| 528 return static_cast<T>(SafeUnsignedAbs(value)); |
| 529 } |
| 530 |
| 531 template < |
| 532 typename T, |
| 533 typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> |
| 534 constexpr T AbsWrapper(T value) { |
| 535 return value < 0 ? -value : value; |
| 561 } | 536 } |
| 562 | 537 |
| 563 // Floats carry around their validity state with them, but integers do not. So, | 538 // Floats carry around their validity state with them, but integers do not. So, |
| 564 // we wrap the underlying value in a specialization in order to hide that detail | 539 // we wrap the underlying value in a specialization in order to hide that detail |
| 565 // and expose an interface via accessors. | 540 // and expose an interface via accessors. |
| 566 enum NumericRepresentation { | 541 enum NumericRepresentation { |
| 567 NUMERIC_INTEGER, | 542 NUMERIC_INTEGER, |
| 568 NUMERIC_FLOATING, | 543 NUMERIC_FLOATING, |
| 569 NUMERIC_UNKNOWN | 544 NUMERIC_UNKNOWN |
| 570 }; | 545 }; |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 using math = M<typename UnderlyingType<L>::type, | 662 using math = M<typename UnderlyingType<L>::type, |
| 688 typename UnderlyingType<R>::type, | 663 typename UnderlyingType<R>::type, |
| 689 void>; | 664 void>; |
| 690 using type = typename math::result_type; | 665 using type = typename math::result_type; |
| 691 }; | 666 }; |
| 692 | 667 |
| 693 } // namespace internal | 668 } // namespace internal |
| 694 } // namespace base | 669 } // namespace base |
| 695 | 670 |
| 696 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ | 671 #endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ |
| OLD | NEW |