This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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.



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]