Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <alpine.LRH.2.02.2108151759330.14038@key0.esi.com.au>
Date: Sun, 15 Aug 2021 18:24:31 +1000 (AEST)
From: Damian McGuckin <damianm@....com.au>
To: musl@...ts.openwall.com
cc: Szabolcs Nagy <nsz@...t70.net>
Subject: Re: [PATCH #2] Properly simplified nextafter()


Hi Stefan,

On Sun, 15 Aug 2021, Stefan Kanthak wrote:

> __attribute__((noinline))
> double nextafter(double x, double y)
> {
> union {double f; unsigned long long i;} ux={x}, uy={y};
> unsigned long long ax, ay;
> int e;
>
> if (isnan(x) || isnan(y))
>  return x + y;
> if (ux.i == uy.i)
>  return y;
> #ifdef PATCH
> ax = ux.i << 1;
> ay = uy.i << 1;
> #else
> ax = ux.i & -1ULL/2;
> ay = uy.i & -1ULL/2;
> #endif
> if (ax == 0) {
>  if (ay == 0)
>   return y;
>  ux.i = (uy.i & 1ULL<<63) | 1;
> #ifdef PATCH
> } else if (ax < ay == (long long) ux.i < 0)
> #else
> } else if (ax > ay || ((ux.i ^ uy.i) & 1ULL<<63))
> #endif
>  ux.i--;
> else
>  ux.i++;
> e = ux.i >> 52 & 0x7ff;
> /* raise overflow if ux.f is infinite and x is finite */
> if (e == 0x7ff)
>  FORCE_EVAL(x + x);
> /* raise underflow if ux.f is subnormal or zero */
> if (e == 0)
>  FORCE_EVAL(x*x + ux.f*ux.f);
> return ux.f;
> }

Maybe I am missing something and my brain is in weekend-mode ...

I did a quick check and ran the above code for some test cases:

nextafter(-9.7500000000e+01, 3.5000000000e+01) = -9.7500000000e+01
yourpatch(-9.7500000000e+01, 3.5000000000e+01) = -9.7500000000e+01

The error is 2.8421709430e-14

nextafter(-9.7500000000e+01, -3.5000000000e+01) = -9.7500000000e+01
yourpatch(-9.7500000000e+01, -3.5000000000e+01) = -9.7500000000e+01

The error is 2.8421709430e-14

nextafter(-inf, inf) = -1.7976931349e+308 Correct
yourpatch(-inf, inf) = -nan Incorrect

This is against standard GLIB.

Comparing the normal MUSL code against GLIB, there are no errors.

If I change this line:

 	} else if (ax < ay == (long long) ux.i < 0)

to
 	} else if (x < y == (long long) ux.i < 0)

Your code works flawlessly. But it introduces a floating point comparison.

- Damian

Pacific Engineering Systems International, 277-279 Broadway, Glebe NSW 2037
Ph:+61-2-8571-0847 .. Fx:+61-2-9692-9623 | unsolicited email not wanted here
Views & opinions here are mine and not those of any past or present employer

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.