1 | /* s_ilogbl.c -- long double version of s_ilogb.c. |
2 | */ |
3 | |
4 | /* |
5 | * ==================================================== |
6 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
7 | * |
8 | * Developed at SunPro, a Sun Microsystems, Inc. business. |
9 | * Permission to use, copy, modify, and distribute this |
10 | * software is freely granted, provided that this notice |
11 | * is preserved. |
12 | * ==================================================== |
13 | */ |
14 | |
15 | #if defined(LIBM_SCCS) && !defined(lint) |
16 | static char rcsid[] = "$NetBSD: $" ; |
17 | #endif |
18 | |
19 | /* ilogbl(long double x) |
20 | * return the binary exponent of non-zero x |
21 | * ilogbl(0) = FP_ILOGB0 |
22 | * ilogbl(NaN) = FP_ILOGBNAN (no signal is raised) |
23 | * ilogbl(+-Inf) = INT_MAX (no signal is raised) |
24 | */ |
25 | |
26 | #include <limits.h> |
27 | #include <math.h> |
28 | #include <math_private.h> |
29 | #include <math_ldbl_opt.h> |
30 | |
31 | int __ieee754_ilogbl(long double x) |
32 | { |
33 | int64_t hx, hxs; |
34 | int ix; |
35 | double xhi, xlo; |
36 | |
37 | ldbl_unpack (x, &xhi, &xlo); |
38 | EXTRACT_WORDS64 (hx, xhi); |
39 | hxs = hx; |
40 | hx &= 0x7fffffffffffffffLL; |
41 | if(hx <= 0x0010000000000000LL) { |
42 | if(hx==0) |
43 | return FP_ILOGB0; /* ilogbl(0) = FP_ILOGB0 */ |
44 | else /* subnormal x */ |
45 | for (ix = -1022, hx<<=11; hx>0; hx<<=1) ix -=1; |
46 | return ix; |
47 | } |
48 | else if (hx < 0x7ff0000000000000LL) |
49 | { |
50 | int hexp = (hx >> 52) - 0x3ff; |
51 | /* If the high part is a power of 2, and the low part is |
52 | nonzero with the opposite sign, the low part affects |
53 | the exponent. */ |
54 | if ((hx & 0x000fffffffffffffLL) == 0) |
55 | { |
56 | int64_t lx; |
57 | EXTRACT_WORDS64 (lx, xlo); |
58 | if ((hxs ^ lx) < 0 && (lx & 0x7fffffffffffffffLL) != 0) |
59 | hexp--; |
60 | } |
61 | return hexp; |
62 | } |
63 | else if (FP_ILOGBNAN != INT_MAX) { |
64 | /* ISO C99 requires ilogbl(+-Inf) == INT_MAX. */ |
65 | if (hx==0x7ff0000000000000LL) |
66 | return INT_MAX; |
67 | } |
68 | return FP_ILOGBNAN; |
69 | } |
70 | |