math: fix pow signed shift ub
[oweals/musl.git] / src / math / ilogbl.c
1 #include <limits.h>
2 #include "libm.h"
3
4 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
5 int ilogbl(long double x)
6 {
7         return ilogb(x);
8 }
9 #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384
10 int ilogbl(long double x)
11 {
12         #pragma STDC FENV_ACCESS ON
13         union ldshape u = {x};
14         uint64_t m = u.i.m;
15         int e = u.i.se & 0x7fff;
16
17         if (!e) {
18                 if (m == 0) {
19                         FORCE_EVAL(0/0.0f);
20                         return FP_ILOGB0;
21                 }
22                 /* subnormal x */
23                 for (e = -0x3fff+1; m>>63 == 0; e--, m<<=1);
24                 return e;
25         }
26         if (e == 0x7fff) {
27                 FORCE_EVAL(0/0.0f);
28                 return m<<1 ? FP_ILOGBNAN : INT_MAX;
29         }
30         return e - 0x3fff;
31 }
32 #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384
33 int ilogbl(long double x)
34 {
35         #pragma STDC FENV_ACCESS ON
36         union ldshape u = {x};
37         int e = u.i.se & 0x7fff;
38
39         if (!e) {
40                 if (x == 0) {
41                         FORCE_EVAL(0/0.0f);
42                         return FP_ILOGB0;
43                 }
44                 /* subnormal x */
45                 x *= 0x1p120;
46                 return ilogbl(x) - 120;
47         }
48         if (e == 0x7fff) {
49                 FORCE_EVAL(0/0.0f);
50                 u.i.se = 0;
51                 return u.f ? FP_ILOGBNAN : INT_MAX;
52         }
53         return e - 0x3fff;
54 }
55 #endif