11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* @(#)e_log10.c 1.3 95/01/18 */
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ====================================================
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Developed at SunSoft, a Sun Microsystems, Inc. business.
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * software is freely granted, provided that this notice
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is preserved.
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ====================================================
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef lint
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char rcsid[] = "$FreeBSD: src/lib/msun/src/e_log10.c,v 1.11 2005/02/04 18:26:06 das Exp $";
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* __ieee754_log10(x)
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Return the base 10 logarithm of x
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Method :
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Let log10_2hi = leading 40 bits of log10(2) and
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	    log10_2lo = log10(2) - log10_2hi,
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	    ivln10   = 1/log(10) rounded.
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Then
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *		n = ilogb(x),
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *		if(n<0)  n = n+1;
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *		x = scalbn(x,-n);
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *		log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x))
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Note 1:
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	To guarantee log10(10**n)=n, where 10**n is normal, the rounding
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	mode must set to Round-to-Nearest.
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Note 2:
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	[1/log(10)] rounded to 53 bits has error  .198   ulps;
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	log10 is monotonic at all binary break points.
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Special cases:
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	log10(x) is NaN with signal if x < 0;
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	log10(+INF) is +INF with no signal; log10(0) is -INF with signal;
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	log10(NaN) is that NaN with no signal;
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	log10(10**N) = N  for N=0,1,...,22.
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Constants:
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The hexadecimal values are the intended ones for the following constants.
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The decimal values may be used, provided that the compiler will convert
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * from decimal to binary accurately enough to produce the hexadecimal values
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * shown.
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math.h"
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math_private.h"
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const double
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttwo54      =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectivln10     =  4.34294481903251816668e-01, /* 0x3FDBCB7B, 0x1526E50E */
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectlog10_2hi  =  3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectlog10_2lo  =  3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const double zero   =  0.0;
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdouble
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__ieee754_log10(double x)
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	double y,z;
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int32_t i,k,hx;
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_int32_t lx;
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	EXTRACT_WORDS(hx,lx,x);
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        k=0;
721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if (hx < 0x00100000) {                  /* x < 2**-1022  */
731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if (((hx&0x7fffffff)|lx)==0)
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return -two54/zero;             /* log(+-0)=-inf */
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if (hx<0) return (x-x)/zero;        /* log(-#) = NaN */
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            k -= 54; x *= two54; /* subnormal number, scale up x */
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    GET_HIGH_WORD(hx,x);
781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        }
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (hx >= 0x7ff00000) return x+x;
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	k += (hx>>20)-1023;
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	i  = ((u_int32_t)k&0x80000000)>>31;
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        hx = (hx&0x000fffff)|((0x3ff-i)<<20);
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        y  = (double)(k+i);
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	SET_HIGH_WORD(x,hx);
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	z  = y*log10_2lo + ivln10*__ieee754_log(x);
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return  z+y*log10_2hi;
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
88