/* @(#)z_logarithm.c 1.0 98/08/13 */ /****************************************************************** * The following routines are coded directly from the algorithms * and coefficients given in "Software Manual for the Elementary * Functions" by William J. Cody, Jr. and William Waite, Prentice * Hall, 1980. ******************************************************************/ /* FUNCTION <>, <>, <>, <>, <>, <>---natural or base 10 logarithms INDEX log INDEX logf INDEX log10 INDEX log10f ANSI_SYNOPSIS #include double log(double <[x]>); float logf(float <[x]>); double log10(double <[x]>); float log10f(float <[x]>); TRAD_SYNOPSIS #include double log(<[x]>); double <[x]>; float logf(<[x]>); float <[x]>; double log10(<[x]>); double <[x]>; float log10f(<[x]>); float <[x]>; DESCRIPTION Return the natural or base 10 logarithm of <[x]>, that is, its logarithm base e (where e is the base of the natural system of logarithms, 2.71828@dots{}) or base 10. <> and <> are identical save for the return and argument types. <> and <> are identical save for the return and argument types. RETURNS Normally, returns the calculated value. When <[x]> is zero, the returned value is <<-HUGE_VAL>> and <> is set to <>. When <[x]> is negative, the returned value is <<-HUGE_VAL>> and <> is set to <>. You can control the error behavior via <>. PORTABILITY <> is ANSI, <> is an extension. <> is ANSI, <> is an extension. */ /****************************************************************** * Logarithm * * Input: * x - floating point value * ten - indicates base ten numbers * * Output: * logarithm of x * * Description: * This routine calculates logarithms. * *****************************************************************/ #include "fdlibm.h" #include "zmath.h" #ifndef _DOUBLE_IS_32BITS static const double a[] = { -0.64124943423745581147e+02, 0.16383943563021534222e+02, -0.78956112887481257267 }; static const double b[] = { -0.76949932108494879777e+03, 0.31203222091924532844e+03, -0.35667977739034646171e+02 }; static const double C1 = 22713.0 / 32768.0; static const double C2 = 1.428606820309417232e-06; static const double C3 = 0.43429448190325182765; double _DEFUN (logarithm, (double, int), double x _AND int ten) { int N; double f, w, z; /* Check for domain error here. */ if (x <= 0.0) { errno = ERANGE; return (z_notanum.d); } /* Get the exponent and mantissa where x = f * 2^N. */ f = frexp (x, &N); z = f - 0.5; if (f > __SQRT_HALF) z = (z - 0.5) / (f * 0.5 + 0.5); else { N--; z /= (z * 0.5 + 0.5); } w = z * z; /* Use Newton's method with 4 terms. */ z += z * w * ((a[2] * w + a[1]) * w + a[0]) / (((w + b[2]) * w + b[1]) * w + b[0]); if (N != 0) z = (N * C2 + z) + N * C1; if (ten) z *= C3; return (z); } #endif /* _DOUBLE_IS_32BITS */