1 /* ef_log.c -- float version of e_log.c.
2  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
3  */
4 
5 /*
6  * ====================================================
7  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8  *
9  * Developed at SunPro, a Sun Microsystems, Inc. business.
10  * Permission to use, copy, modify, and distribute this
11  * software is freely granted, provided that this notice
12  * is preserved.
13  * ====================================================
14  */
15 
16 #include "fdlibm.h"
17 
18 #if __OBSOLETE_MATH_FLOAT
19 static const float ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
20     ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
21     two25 = 3.355443200e+07, /* 0x4c000000 */
22     Lg1 = 6.6666668653e-01, /* 3F2AAAAB */
23     Lg2 = 4.0000000596e-01, /* 3ECCCCCD */
24     Lg3 = 2.8571429849e-01, /* 3E924925 */
25     Lg4 = 2.2222198546e-01, /* 3E638E29 */
26     Lg5 = 1.8183572590e-01, /* 3E3A3325 */
27     Lg6 = 1.5313838422e-01, /* 3E1CD04F */
28     Lg7 = 1.4798198640e-01; /* 3E178897 */
29 
30 static const float zero = 0.0;
31 
32 float
logf(float x)33 logf(float x)
34 {
35     float hfsq, f, s, z, R, w, t1, t2, dk;
36     __int32_t k, ix, i, j;
37 
38     GET_FLOAT_WORD(ix, x);
39 
40     k = 0;
41     if (FLT_UWORD_IS_ZERO(ix & 0x7fffffff))
42         return __math_divzerof(1); /* log(+-0)=-inf */
43     if (ix < 0)
44         return __math_invalidf(x); /* log(-#) = NaN */
45     if (!FLT_UWORD_IS_FINITE(ix))
46         return x + x;
47     if (FLT_UWORD_IS_SUBNORMAL(ix)) {
48         k -= 25;
49         x *= two25; /* subnormal number, scale up x */
50         GET_FLOAT_WORD(ix, x);
51     }
52     k += (ix >> 23) - 127;
53     ix &= 0x007fffff;
54     i = (ix + (0x95f64 << 3)) & 0x800000;
55     SET_FLOAT_WORD(x, ix | (i ^ 0x3f800000)); /* normalize x or x/2 */
56     k += (i >> 23);
57     f = x - (float)1.0;
58     if ((0x007fffff & (15 + ix)) < 16) { /* |f| < 2**-20 */
59         if (f == zero) {
60             if (k == 0)
61                 return zero;
62             else {
63                 dk = (float)k;
64                 return dk * ln2_hi + dk * ln2_lo;
65             }
66         }
67         R = f * f * ((float)0.5 - (float)0.33333333333333333 * f);
68         if (k == 0)
69             return f - R;
70         else {
71             dk = (float)k;
72             return dk * ln2_hi - ((R - dk * ln2_lo) - f);
73         }
74     }
75     s = f / ((float)2.0 + f);
76     dk = (float)k;
77     z = s * s;
78     i = ix - (0x6147a << 3);
79     w = z * z;
80     j = (0x6b851 << 3) - ix;
81     t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
82     t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
83     i |= j;
84     R = t2 + t1;
85     if (i > 0) {
86         hfsq = (float)0.5 * f * f;
87         if (k == 0)
88             return f - (hfsq - s * (hfsq + R));
89         else
90             return dk * ln2_hi - ((hfsq - (s * (hfsq + R) + dk * ln2_lo)) - f);
91     } else {
92         if (k == 0)
93             return f - s * (f - R);
94         else
95             return dk * ln2_hi - ((s * (f - R) - dk * ln2_lo) - f);
96     }
97 }
98 
99 _MATH_ALIAS_f_f(log)
100 
101 #else
102 #include "../common/sf_log.c"
103 #endif /* __OBSOLETE_MATH_FLOAT */
104