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)21ilogbl(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