e_log2.c revision 97413
159412Smsmith/* @(#)e_log10.c 5.1 93/09/24 */
265577Sdes/*
365577Sdes * ====================================================
459412Smsmith * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
559412Smsmith *
659412Smsmith * Developed at SunPro, a Sun Microsystems, Inc. business.
759412Smsmith * Permission to use, copy, modify, and distribute this
859412Smsmith * software is freely granted, provided that this notice
959412Smsmith * is preserved.
1059412Smsmith * ====================================================
1159412Smsmith */
1259412Smsmith
1359412Smsmith#ifndef lint
1459412Smsmithstatic char rcsid[] = "$FreeBSD: head/lib/msun/src/e_log10.c 97413 2002-05-28 18:15:04Z alfred $";
1559412Smsmith#endif
1659412Smsmith
1759412Smsmith/* __ieee754_log10(x)
1859412Smsmith * Return the base 10 logarithm of x
1959412Smsmith *
2059412Smsmith * Method :
2159412Smsmith *	Let log10_2hi = leading 40 bits of log10(2) and
2259412Smsmith *	    log10_2lo = log10(2) - log10_2hi,
2359412Smsmith *	    ivln10   = 1/log(10) rounded.
2459412Smsmith *	Then
2559412Smsmith *		n = ilogb(x),
2659412Smsmith *		if(n<0)  n = n+1;
2759412Smsmith *		x = scalbn(x,-n);
2859412Smsmith *		log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x))
2959412Smsmith *
3059412Smsmith * Note 1:
3159412Smsmith *	To guarantee log10(10**n)=n, where 10**n is normal, the rounding
3259412Smsmith *	mode must set to Round-to-Nearest.
3359412Smsmith * Note 2:
3459412Smsmith *	[1/log(10)] rounded to 53 bits has error  .198   ulps;
3559412Smsmith *	log10 is monotonic at all binary break points.
3659412Smsmith *
3759412Smsmith * Special cases:
3859412Smsmith *	log10(x) is NaN with signal if x < 0;
3959412Smsmith *	log10(+INF) is +INF with no signal; log10(0) is -INF with signal;
4059412Smsmith *	log10(NaN) is that NaN with no signal;
4159412Smsmith *	log10(10**N) = N  for N=0,1,...,22.
4259412Smsmith *
4359412Smsmith * Constants:
4459412Smsmith * The hexadecimal values are the intended ones for the following constants.
4559412Smsmith * The decimal values may be used, provided that the compiler will convert
4659412Smsmith * from decimal to binary accurately enough to produce the hexadecimal values
4759412Smsmith * shown.
4859412Smsmith */
4959412Smsmith
5059412Smsmith#include "math.h"
5159412Smsmith#include "math_private.h"
5259458Smsmith
5359412Smsmithstatic const double
5459412Smsmithtwo54      =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
5559412Smsmithivln10     =  4.34294481903251816668e-01, /* 0x3FDBCB7B, 0x1526E50E */
5659412Smsmithlog10_2hi  =  3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
5760860Sdeslog10_2lo  =  3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
5859412Smsmith
5959412Smsmithstatic const double zero   =  0.0;
6059412Smsmith
6159412Smsmithdouble
6259412Smsmith__generic___ieee754_log10(double x)
6359412Smsmith{
6459412Smsmith	double y,z;
6559412Smsmith	int32_t i,k,hx;
6659412Smsmith	u_int32_t lx;
6759412Smsmith
6859412Smsmith	EXTRACT_WORDS(hx,lx,x);
6959412Smsmith
7059412Smsmith        k=0;
7159412Smsmith        if (hx < 0x00100000) {                  /* x < 2**-1022  */
7259412Smsmith            if (((hx&0x7fffffff)|lx)==0)
7359412Smsmith                return -two54/zero;             /* log(+-0)=-inf */
7459412Smsmith            if (hx<0) return (x-x)/zero;        /* log(-#) = NaN */
7559412Smsmith            k -= 54; x *= two54; /* subnormal number, scale up x */
7659412Smsmith	    GET_HIGH_WORD(hx,x);
7759412Smsmith        }
7859412Smsmith	if (hx >= 0x7ff00000) return x+x;
7959412Smsmith	k += (hx>>20)-1023;
8059412Smsmith	i  = ((u_int32_t)k&0x80000000)>>31;
8159412Smsmith        hx = (hx&0x000fffff)|((0x3ff-i)<<20);
8259412Smsmith        y  = (double)(k+i);
8359412Smsmith	SET_HIGH_WORD(x,hx);
8459412Smsmith	z  = y*log10_2lo + ivln10*__ieee754_log(x);
8559412Smsmith	return  z+y*log10_2hi;
8660860Sdes}
8759412Smsmith