math: fix pow signed shift ub
[oweals/musl.git] / src / math / modf.c
1 #include "libm.h"
2
3 double modf(double x, double *iptr)
4 {
5         union {double f; uint64_t i;} u = {x};
6         uint64_t mask;
7         int e = (int)(u.i>>52 & 0x7ff) - 0x3ff;
8
9         /* no fractional part */
10         if (e >= 52) {
11                 *iptr = x;
12                 if (e == 0x400 && u.i<<12 != 0) /* nan */
13                         return x;
14                 u.i &= 1ULL<<63;
15                 return u.f;
16         }
17
18         /* no integral part*/
19         if (e < 0) {
20                 u.i &= 1ULL<<63;
21                 *iptr = u.f;
22                 return x;
23         }
24
25         mask = -1ULL>>12>>e;
26         if ((u.i & mask) == 0) {
27                 *iptr = x;
28                 u.i &= 1ULL<<63;
29                 return u.f;
30         }
31         u.i &= ~mask;
32         *iptr = u.f;
33         return x - u.f;
34 }