[PATCH] Define midpoint and lerp functions for C++20 (P0811R3)

Jonathan Wakely jwakely@redhat.com
Tue Jun 25 09:12:00 GMT 2019


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.




More information about the Libstdc++ mailing list