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
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