-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Finish P0811R3 midpoint and lerp #1048
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fd1590b
d554f60
e3a405a
e5c0662
e2f612b
033632e
98b19bb
fbd2c52
9305264
c9a2ba5
57e9826
af71038
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -536,21 +536,16 @@ _CONSTEXPR20 void iota(_FwdIt _First, _FwdIt _Last, _Ty _Val) { | |
|
|
||
| #if _HAS_CXX17 | ||
| // FUNCTION TEMPLATE _Abs_u | ||
| template <class _Arithmetic> | ||
| _NODISCARD constexpr auto _Abs_u(const _Arithmetic _Val) noexcept { | ||
| template <class _Integral> | ||
| _NODISCARD constexpr auto _Abs_u(const _Integral _Val) noexcept { | ||
| // computes absolute value of _Val (converting to an unsigned integer type if necessary to avoid overflow | ||
| // representing the negation of the minimum value) | ||
| if constexpr (is_floating_point_v<_Arithmetic>) { | ||
| // TRANSITION, P0553: this mishandles NaNs | ||
| if (_Val < 0) { | ||
| return -_Val; | ||
| } | ||
| static_assert(is_integral_v<_Integral>); | ||
|
|
||
| return _Val; | ||
| } else if constexpr (is_signed_v<_Arithmetic>) { | ||
| using _Unsigned = make_unsigned_t<_Arithmetic>; | ||
| if constexpr (is_signed_v<_Integral>) { | ||
| using _Unsigned = make_unsigned_t<_Integral>; | ||
| if (_Val < 0) { | ||
| // note static_cast to _Unsigned such that _Arithmetic == short returns unsigned short rather than int | ||
| // note static_cast to _Unsigned such that _Integral == short returns unsigned short rather than int | ||
| return static_cast<_Unsigned>(_Unsigned{0} - static_cast<_Unsigned>(_Val)); | ||
| } | ||
|
|
||
|
|
@@ -619,9 +614,24 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> lcm(const _Mt _Mx, const _Nt _Nx) n | |
| template <class _Ty, enable_if_t<is_arithmetic_v<_Ty> && !is_same_v<remove_cv_t<_Ty>, bool>, int> = 0> | ||
| _NODISCARD constexpr _Ty midpoint(const _Ty _Val1, const _Ty _Val2) noexcept { | ||
| if constexpr (is_floating_point_v<_Ty>) { | ||
| if (_STD is_constant_evaluated()) { | ||
| if (_STD _Is_nan(_Val1)) { | ||
| return _Val1; | ||
| } | ||
|
|
||
| if (_STD _Is_nan(_Val2)) { | ||
| return _Val2; | ||
| } | ||
| } else { | ||
| if (_STD _Is_nan(_Val1) || _STD _Is_nan(_Val2)) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Before I purposely put this test below the high limit tests before the NaN tests because we expect NaNs to be uncommon; you're fixing
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Performing the high limit test with Alternative approaches:
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, to raise floating point exceptions. Can you add a comment to places where you do seemingly needless operations to raise the right exceptions and add tests for that? Otherwise that's likely to break. (I understand that requires
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmmm actually it looks like we already have an so you should just be able to do that. |
||
| // raise FE_INVALID if at least one of _Val1 and _Val2 is signaling NaN | ||
| return _Val1 + _Val2; | ||
| } | ||
| } | ||
|
|
||
| constexpr _Ty _High_limit = (numeric_limits<_Ty>::max)() / 2; | ||
| const auto _Val1_a = _Abs_u(_Val1); | ||
| const auto _Val2_a = _Abs_u(_Val2); | ||
| const auto _Val1_a = _Float_abs(_Val1); | ||
| const auto _Val2_a = _Float_abs(_Val2); | ||
| if (_Val1_a <= _High_limit && _Val2_a <= _High_limit) { | ||
| // _Val1 and _Val2 are small enough that _Val1 + _Val2 won't overflow | ||
|
|
||
|
|
@@ -637,22 +647,12 @@ _NODISCARD constexpr _Ty midpoint(const _Ty _Val1, const _Ty _Val2) noexcept { | |
| return (_Val1 + _Val2) / 2; | ||
| } | ||
|
|
||
| // TRANSITION, P0553: the next two branches handle NaNs but don't produce correct behavior under /fp:fast or | ||
| // -fassociative-math | ||
| if (_Val1 != _Val1) { | ||
| return _Val1; | ||
| } | ||
|
|
||
| if (_Val2 != _Val2) { | ||
| return _Val2; | ||
| } | ||
|
|
||
| // Here at least one of {_Val1, _Val2} has large magnitude. | ||
| // Therefore, if one of the values is too small to divide by 2 exactly, the small magnitude is much less than | ||
| // one ULP of the result, so we can add it directly without the potentially inexact division by 2. | ||
|
|
||
| // In the default rounding mode this less than one ULP difference will always be rounded away, so under | ||
| // /fp:precise or /fp:fast we could avoid these tests if we had some means of detecting it in the caller. | ||
| // /fp:fast we could avoid these tests if we had some means of detecting it in the caller. | ||
| constexpr _Ty _Low_limit = (numeric_limits<_Ty>::min)() * 2; | ||
| if (_Val1_a < _Low_limit) { | ||
| return _Val1 + _Val2 / 2; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.