xref: /dragonfly/contrib/openbsd_libm/src/s_ilogbl.c (revision 4382f29d99a100bd77a81697c2f699c11f6a472a)
1 /*        $OpenBSD: s_ilogbl.c,v 1.1 2008/12/09 20:00:35 martynas Exp $         */
2 /*
3  * From: @(#)s_ilogb.c 5.1 93/09/24
4  * ====================================================
5  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
6  *
7  * Developed at SunPro, a Sun Microsystems, Inc. business.
8  * Permission to use, copy, modify, and distribute this
9  * software is freely granted, provided that this notice
10  * is preserved.
11  * ====================================================
12  */
13 
14 #include <sys/types.h>
15 #include <machine/ieee.h>
16 #include <float.h>
17 #include <limits.h>
18 #include <math.h>
19 
20 int
ilogbl(long double x)21 ilogbl(long double x)
22 {
23           struct ieee_ext *p = (struct ieee_ext *)&x;
24           unsigned long m;
25           int b;
26 
27           if (p->ext_exp == 0) {
28                     if ((p->ext_fracl
29 #ifdef EXT_FRACLMBITS
30                               | p->ext_fraclm
31 #endif /* EXT_FRACLMBITS */
32 #ifdef EXT_FRACHMBITS
33                               | p->ext_frachm
34 #endif /* EXT_FRACHMBITS */
35                               | p->ext_frach) == 0)
36                               return (FP_ILOGB0);
37                     /* denormalized */
38                     if (p->ext_frach == 0
39 #ifdef EXT_FRACHMBITS
40                               && p->ext_frachm == 0
41 #endif
42                               ) {
43                               m = 1lu << (EXT_FRACLBITS - 1);
44                               for (b = EXT_FRACHBITS; !(p->ext_fracl & m); m >>= 1)
45                                         b++;
46 #if defined(EXT_FRACHMBITS) && defined(EXT_FRACLMBITS)
47                               m = 1lu << (EXT_FRACLMBITS - 1);
48                               for (b += EXT_FRACHMBITS; !(p->ext_fraclm & m); m >>= 1)
49                                         b++;
50 #endif /* defined(EXT_FRACHMBITS) && defined(EXT_FRACLMBITS) */
51                     } else {
52                               m = 1lu << (EXT_FRACHBITS - 1);
53                               for (b = 0; !(p->ext_frach & m); m >>= 1)
54                                         b++;
55 #ifdef EXT_FRACHMBITS
56                               m = 1lu << (EXT_FRACHMBITS - 1);
57                               for (; !(p->ext_frachm & m); m >>= 1)
58                                         b++;
59 #endif /* EXT_FRACHMBITS */
60                     }
61 #ifdef EXT_IMPLICIT_NBIT
62                     b++;
63 #endif
64                     return (LDBL_MIN_EXP - b - 1);
65           } else if (p->ext_exp < (LDBL_MAX_EXP << 1) - 1)
66                     return (p->ext_exp - LDBL_MAX_EXP + 1);
67           else if (p->ext_fracl != 0
68 #ifdef EXT_FRACLMBITS
69                     || p->ext_fraclm != 0
70 #endif /* EXT_FRACLMBITS */
71 #ifdef EXT_FRACHMBITS
72                     || p->ext_frachm != 0
73 #endif /* EXT_FRACHMBITS */
74                     || p->ext_frach != 0)
75                     return (FP_ILOGBNAN);
76           else
77                     return (INT_MAX);
78 }
79