[PATCH] Define midpoint and lerp functions for C++20 (P0811R3)
Jonathan Wakely
jwakely@redhat.com
Tue Jun 25 13:19:00 GMT 2019
On 25/06/19 10:12 +0100, Jonathan Wakely wrote:
>On 25/06/19 11:06 +0200, Rainer Orth wrote:
>>Hi Jonathan,
>>
>>>On 12/03/19 23:04 +0000, Jonathan Wakely wrote:
>>>>On 12/03/19 22:49 +0000, Joseph Myers wrote:
>>>>>On Tue, 5 Mar 2019, Jonathan Wakely wrote:
>>>>>
>>>>>>The midpoint and lerp functions for floating point types come straight
>>>>>>from the P0811R3 proposal, with no attempt at optimization.
>>>>>
>>>>>I don't know whether P0811R3 states different requirements from the public
>>>>>P0811R2, but the implementation of midpoint using isnormal does *not*
>>>>>satisfy "at most one inexact operation occurs" and is *not* correctly
>>>>>rounded, contrary to the claims made in P0811R2.
>>>>
>>>>I did wonder how the implementation in the paper was meant to meet the
>>>>stated requirements, but I didn't wonder too hard.
>>>>
>>>>>Consider e.g. midpoint(DBL_MIN + DBL_TRUE_MIN, DBL_MIN + DBL_TRUE_MIN).
>>>>>The value DBL_MIN + DBL_TRUE_MIN is normal, but dividing it by 2 is
>>>>>inexact (and so that midpoint implementation would produce DBL_MIN as
>>>>>result, so failing to satisfy midpoint(x, x) == x).
>>>>>
>>>>>Replacing isnormal(x) by something like isgreaterequal(fabs(x), MIN*2)
>>>>>would avoid those inexact divisions, but there would still be spurious
>>>>>overflows in non-default rounding modes for e.g. midpoint(DBL_MAX,
>>>>>DBL_TRUE_MIN) in FE_UPWARD mode, so failing "No overflow occurs" if that's
>>>>>meant to apply in all rounding modes.
>>>>
>>>>Thanks for this review, and the useful cases to test. Ed is working on
>>>>adding some more tests, so maybe he can also look at improving the
>>>>code :-)
>>>
>>>I've committed r272616 to make this case work. This is the proposal
>>>author's most recent suggestion for the implementation.
>>>
>>>Tested x86_64-linux, committed to trunk.
>>
>>the 26_numerics/midpoint/floating.cc test now FAILs on Solaris (sparc
>>and x86, 32 and 64-bit):
>>
>>+FAIL: 26_numerics/midpoint/floating.cc (test for excess errors)
>>+UNRESOLVED: 26_numerics/midpoint/floating.cc compilation failed to produce executable
>>
>>Excess errors:
>>/vol/gcc/src/hg/trunk/local/libstdc++-v3/testsuite/26_numerics/midpoint/floating.cc:65: error: non-constant condition for static assertion
>>/vol/gcc/src/hg/trunk/local/libstdc++-v3/testsuite/26_numerics/midpoint/floating.cc:65: error: 'constexpr std::enable_if_t<__and_v<std::is_arithmetic<_Tp>, std::is_same<typename std::remove_cv< <template-parameter-1-1> >::type, _Tp>, std::__not_<std::is_same<_Tp, bool> > >, _Tp> std::midpoint(_Tp, _Tp) [with _Tp = double; std::enable_if_t<__and_v<std::is_arithmetic<_Tp>, std::is_same<typename std::remove_cv< <template-parameter-1-1> >::type, _Tp>, std::__not_<std::is_same<_Tp, bool> > >, _Tp> = double]' called in a constant expression
>>/var/gcc/regression/trunk/11-gcc/build/i386-pc-solaris2.11/libstdc++-v3/include/numeric:199: error: call to non-'constexpr' function 'double std::abs(double)'
>>/vol/gcc/src/hg/trunk/local/libstdc++-v3/testsuite/26_numerics/midpoint/floating.cc:68: error: non-constant condition for static assertion
>>/vol/gcc/src/hg/trunk/local/libstdc++-v3/testsuite/26_numerics/midpoint/floating.cc:68: error: 'constexpr std::enable_if_t<__and_v<std::is_arithmetic<_Tp>, std::is_same<typename std::remove_cv< <template-parameter-1-1> >::type, _Tp>, std::__not_<std::is_same<_Tp, bool> > >, _Tp> std::midpoint(_Tp, _Tp) [with _Tp = float; std::enable_if_t<__and_v<std::is_arithmetic<_Tp>, std::is_same<typename std::remove_cv< <template-parameter-1-1> >::type, _Tp>, std::__not_<std::is_same<_Tp, bool> > >, _Tp> = float]' called in a constant expression
>>/var/gcc/regression/trunk/11-gcc/build/i386-pc-solaris2.11/libstdc++-v3/include/numeric:199: error: call to non-'constexpr' function 'float std::abs(float)'
>>/vol/gcc/src/hg/trunk/local/libstdc++-v3/testsuite/26_numerics/midpoint/floating.cc:71: error: non-constant condition for static assertion
>>/vol/gcc/src/hg/trunk/local/libstdc++-v3/testsuite/26_numerics/midpoint/floating.cc:71: error: 'constexpr std::enable_if_t<__and_v<std::is_arithmetic<_Tp>, std::is_same<typename std::remove_cv< <template-parameter-1-1> >::type, _Tp>, std::__not_<std::is_same<_Tp, bool> > >, _Tp> std::midpoint(_Tp, _Tp) [with _Tp = long double; std::enable_if_t<__and_v<std::is_arithmetic<_Tp>, std::is_same<typename std::remove_cv< <template-parameter-1-1> >::type, _Tp>, std::__not_<std::is_same<_Tp, bool> > >, _Tp> = long double]' called in a constant expression
>>/var/gcc/regression/trunk/11-gcc/build/i386-pc-solaris2.11/libstdc++-v3/include/numeric:199: error: call to non-'constexpr' function 'long double std::abs(long double)'
>
>Doh, I looked in <cmath> and saw that we get std::abs(double) from the
>Solaris headers, and then forgot and used it anyway.
>
>I'll replace that right away, thanks.
Should be fixed at r272653.
Tested x86_64-linux, committed to trunk.
More information about the Libstdc++
mailing list