https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114018

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
If you want a function with 2 arguments of the same type, that is
std::nextafter.
In C, nexttoward{f,,l} has first argument of float, double and long double, so
the last one is always long double.
Now, https://eel.is/c++draft/cmath.syn lists
constexpr floating-point-type nextafter(floating-point-type x,
floating-point-type y);
constexpr float nextafterf(float x, float y);
constexpr long double nextafterl(long double x, long double y);
which is correct and
constexpr floating-point-type nexttoward(floating-point-type x, long double y);
constexpr float nexttowardf(float x, long double y);
constexpr long double nexttowardl(long double x, long double y);
which I believe is a bug in the standard, finding next representable number in
direction of long double which might have smaller or uncomparable precision or
range doesn't make much sense.
See
https://gcc.gnu.org/pipermail/gcc-patches/2022-September/602667.html
for more details.  At that point it was
constexpr floating-point-type nexttoward(floating-point-type x,
floating-point-type y);
constexpr float nexttowardf(float x, long double y);
constexpr long double nexttowardl(long double x, long double y);
which was also backwards incompatible change because before the C++23 changes
it was
constexpr double nexttoward(double x, long double y);
constexpr float nexttoward(float x, long double y);
constexpr long double nexttowardl(long double x, long double y);
constexpr float nexttowardf(float x, long double y);
constexpr long double nexttowardl(long double x, long double y);
What is in the standard now looks wrong to me as well, e.g. if long double is
IBM extended format and floating-point-type is std::float128_t, C++23 doesn't
even allow comparison between those two types:
error: invalid operands to binary > (have ‘_Float128’ and ‘long double’)
    4 |   return x > y;
      |          ~~^~~
and very difficult to implement, both because of that because having to handle
all possible long double representations vs. all extended floating point types.
As Joseph said in the above thread, C23 has
_FloatN nextafterfN(_FloatN x, _FloatN y);
_FloatNx nextafterfNx(_FloatNx x, _FloatNx y);
_FloatN nextupfN(_FloatN x);
_FloatNx nextupfNx(_FloatNx x);
_FloatN nextdownfN(_FloatN x);
_FloatNx nextdownfNx(_FloatNx x);
but nexttoward remains double, float and long double only.
Because nexttoward is only meaningful if long double is a superset of the other
floating point type, which is the case for float/double.

Reply via email to