/* ef_log.c -- float version of e_log.c. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #include "fdlibm.h" #if __OBSOLETE_MATH_FLOAT static const float ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ two25 = 3.355443200e+07, /* 0x4c000000 */ Lg1 = 6.6666668653e-01, /* 3F2AAAAB */ Lg2 = 4.0000000596e-01, /* 3ECCCCCD */ Lg3 = 2.8571429849e-01, /* 3E924925 */ Lg4 = 2.2222198546e-01, /* 3E638E29 */ Lg5 = 1.8183572590e-01, /* 3E3A3325 */ Lg6 = 1.5313838422e-01, /* 3E1CD04F */ Lg7 = 1.4798198640e-01; /* 3E178897 */ static const float zero = 0.0; float logf(float x) { float hfsq, f, s, z, R, w, t1, t2, dk; __int32_t k, ix, i, j; GET_FLOAT_WORD(ix, x); k = 0; if (FLT_UWORD_IS_ZERO(ix & 0x7fffffff)) return __math_divzerof(1); /* log(+-0)=-inf */ if (ix < 0) return __math_invalidf(x); /* log(-#) = NaN */ if (!FLT_UWORD_IS_FINITE(ix)) return x + x; if (FLT_UWORD_IS_SUBNORMAL(ix)) { k -= 25; x *= two25; /* subnormal number, scale up x */ GET_FLOAT_WORD(ix, x); } k += (ix >> 23) - 127; ix &= 0x007fffff; i = (ix + (0x95f64 << 3)) & 0x800000; SET_FLOAT_WORD(x, ix | (i ^ 0x3f800000)); /* normalize x or x/2 */ k += (i >> 23); f = x - (float)1.0; if ((0x007fffff & (15 + ix)) < 16) { /* |f| < 2**-20 */ if (f == zero) { if (k == 0) return zero; else { dk = (float)k; return dk * ln2_hi + dk * ln2_lo; } } R = f * f * ((float)0.5 - (float)0.33333333333333333 * f); if (k == 0) return f - R; else { dk = (float)k; return dk * ln2_hi - ((R - dk * ln2_lo) - f); } } s = f / ((float)2.0 + f); dk = (float)k; z = s * s; i = ix - (0x6147a << 3); w = z * z; j = (0x6b851 << 3) - ix; t1 = w * (Lg2 + w * (Lg4 + w * Lg6)); t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7))); i |= j; R = t2 + t1; if (i > 0) { hfsq = (float)0.5 * f * f; if (k == 0) return f - (hfsq - s * (hfsq + R)); else return dk * ln2_hi - ((hfsq - (s * (hfsq + R) + dk * ln2_lo)) - f); } else { if (k == 0) return f - s * (f - R); else return dk * ln2_hi - ((s * (f - R) - dk * ln2_lo) - f); } } _MATH_ALIAS_f_f(log) #else #include "../common/sf_log.c" #endif /* __OBSOLETE_MATH_FLOAT */