math: fix pow signed shift ub
[oweals/musl.git] / src / math / nextafterf.c
1 #include "libm.h"
2
3 float nextafterf(float x, float y)
4 {
5         union {float f; uint32_t i;} ux={x}, uy={y};
6         uint32_t ax, ay, e;
7
8         if (isnan(x) || isnan(y))
9                 return x + y;
10         if (ux.i == uy.i)
11                 return y;
12         ax = ux.i & 0x7fffffff;
13         ay = uy.i & 0x7fffffff;
14         if (ax == 0) {
15                 if (ay == 0)
16                         return y;
17                 ux.i = (uy.i & 0x80000000) | 1;
18         } else if (ax > ay || ((ux.i ^ uy.i) & 0x80000000))
19                 ux.i--;
20         else
21                 ux.i++;
22         e = ux.i & 0x7f800000;
23         /* raise overflow if ux.f is infinite and x is finite */
24         if (e == 0x7f800000)
25                 FORCE_EVAL(x+x);
26         /* raise underflow if ux.f is subnormal or zero */
27         if (e == 0)
28                 FORCE_EVAL(x*x + ux.f*ux.f);
29         return ux.f;
30 }