xref: /csrg-svn/lib/libm/common_source/log.c (revision 57158)
134126Sbostic /*
256955Sbostic  * Copyright (c) 1992 Regents of the University of California.
334126Sbostic  * All rights reserved.
434126Sbostic  *
542657Sbostic  * %sccs.include.redist.c%
624601Szliu  */
724601Szliu 
824601Szliu #ifndef lint
9*57158Smcilroy static char sccsid[] = "@(#)log.c	5.9 (Berkeley) 12/16/92";
1034126Sbostic #endif /* not lint */
1124601Szliu 
1256955Sbostic #include <math.h>
1356955Sbostic #include <errno.h>
1456955Sbostic 
1556955Sbostic #include "log_table.h"
16*57158Smcilroy #include "mathimpl.h"
1756955Sbostic 
1856955Sbostic /* Table-driven natural logarithm.
1924601Szliu  *
2056955Sbostic  * This code was derived, with minor modifications, from:
2156955Sbostic  *	Peter Tang, "Table-Driven Implementation of the
2256955Sbostic  *	Logarithm in IEEE Floating-Point arithmetic." ACM Trans.
2356955Sbostic  *	Math Software, vol 16. no 4, pp 378-400, Dec 1990).
2424601Szliu  *
2556955Sbostic  * Calculates log(2^m*F*(1+f/F)), |f/j| <= 1/256,
2656955Sbostic  * where F = j/128 for j an integer in [0, 128].
2724601Szliu  *
2856955Sbostic  * log(2^m) = log2_hi*m + log2_tail*m
2956955Sbostic  * since m is an integer, the dominant term is exact.
3056955Sbostic  * m has at most 10 digits (for subnormal numbers),
3156955Sbostic  * and log2_hi has 11 trailing zero bits.
3224601Szliu  *
3356955Sbostic  * log(F) = logF_hi[j] + logF_lo[j] is in tabular form in log_table.h
3456955Sbostic  * logF_hi[] + 512 is exact.
3524601Szliu  *
3656955Sbostic  * log(1+f/F) = 2*f/(2*F + f) + 1/12 * (2*f/(2*F + f))**3 + ...
3756955Sbostic  * the leading term is calculated to extra precision in two
3856955Sbostic  * parts, the larger of which adds exactly to the dominant
3956955Sbostic  * m and F terms.
4056955Sbostic  * There are two cases:
4156955Sbostic  *	1. when m, j are non-zero (m | j), use absolute
4256955Sbostic  *	   precision for the leading term.
4356955Sbostic  *	2. when m = j = 0, |1-x| < 1/256, and log(x) ~= (x-1).
4456955Sbostic  *	   In this case, use a relative precision of 24 bits.
4556955Sbostic  * (This is done differently in the original paper)
4624601Szliu  *
4724601Szliu  * Special cases:
4856955Sbostic  *	0	return signalling -Inf
4956955Sbostic  *	neg	return signalling NaN
5056955Sbostic  *	+Inf	return +Inf
5156955Sbostic */
5224601Szliu 
5356955Sbostic #if defined(vax) || defined(tahoe)
5457156Smcilroy #define _IEEE		0
5557156Smcilroy #define TRUNC(x)	x = (double) (float) (x)
5656955Sbostic #else
5756955Sbostic #define _IEEE	1
5857156Smcilroy #define endian		(((*(int *) &one)) ? 1 : 0)
5957156Smcilroy #define TRUNC(x)	*(((int *) &x) + endian) &= 0xf8000000
6057156Smcilroy #define infnan(x)	0.0
6156955Sbostic #endif
6224601Szliu 
6356955Sbostic double
6456955Sbostic #ifdef _ANSI_SOURCE
6556955Sbostic log(double x)
6656955Sbostic #else
6756955Sbostic log(x) double x;
6856955Sbostic #endif
6956955Sbostic {
7056955Sbostic 	int m, j;
7156955Sbostic 	double F, f, g, q, u, u2, v, zero = 0.0, one = 1.0;
7256955Sbostic 	double logb(), ldexp();
7356955Sbostic 	volatile double u1;
7435679Sbostic 
7556955Sbostic 	/* Catch special cases */
7656955Sbostic 	if (x <= 0)
7756955Sbostic 		if (_IEEE && x == zero)	/* log(0) = -Inf */
7856955Sbostic 			return (-one/zero);
7956955Sbostic 		else if (_IEEE)		/* log(neg) = NaN */
8056955Sbostic 			return (zero/zero);
8156955Sbostic 		else if (x == zero)	/* NOT REACHED IF _IEEE */
8256955Sbostic 			return (infnan(-ERANGE));
8356955Sbostic 		else
8456955Sbostic 			return (infnan(EDOM));
8556955Sbostic 	else if (!finite(x))
8656955Sbostic 		if (_IEEE)		/* x = NaN, Inf */
8756955Sbostic 			return (x+x);
8856955Sbostic 		else
8956955Sbostic 			return (infnan(ERANGE));
9056955Sbostic 
9156955Sbostic 	/* Argument reduction: 1 <= g < 2; x/2^m = g;	*/
9256955Sbostic 	/* y = F*(1 + f/F) for |f| <= 2^-8		*/
9335679Sbostic 
9456955Sbostic 	m = logb(x);
9556955Sbostic 	g = ldexp(x, -m);
9656955Sbostic 	if (_IEEE && m == -1022) {
9756955Sbostic 		j = logb(g), m += j;
9856955Sbostic 		g = ldexp(g, -j);
9956955Sbostic 	}
10056955Sbostic 	j = N*(g-1) + .5;
10156955Sbostic 	F = (1.0/N) * j + 1;	/* F*128 is an integer in [128, 512] */
10256955Sbostic 	f = g - F;
10335679Sbostic 
10456955Sbostic 	/* Approximate expansion for log(1+f/F) ~= u + q */
10556955Sbostic 	g = 1/(2*F+f);
10656955Sbostic 	u = 2*f*g;
10756955Sbostic 	v = u*u;
10856955Sbostic 	q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
10935679Sbostic 
11056955Sbostic     /* case 1: u1 = u rounded to 2^-43 absolute.  Since u < 2^-8,
11156955Sbostic      * 	       u1 has at most 35 bits, and F*u1 is exact, as F has < 8 bits.
11256955Sbostic      *         It also adds exactly to |m*log2_hi + log_F_head[j] | < 750
11356955Sbostic     */
11456955Sbostic 	if (m | j)
11556955Sbostic 		u1 = u + 513, u1 -= 513;
11624601Szliu 
11756955Sbostic     /* case 2:	|1-x| < 1/256. The m- and j- dependent terms are zero;
11856955Sbostic      * 		u1 = u to 24 bits.
11956955Sbostic     */
12056955Sbostic 	else
12156955Sbostic 		u1 = u, TRUNC(u1);
12256955Sbostic 	u2 = (2.0*(f - F*u1) - u1*f) * g;
12356955Sbostic 			/* u1 + u2 = 2f/(2F+f) to extra precision.	*/
12424601Szliu 
12556955Sbostic 	/* log(x) = log(2^m*F*(1+f/F)) =				*/
12656955Sbostic 	/* (m*log2_hi+logF_head[j]+u1) + (m*log2_lo+logF_tail[j]+q);	*/
12756955Sbostic 	/* (exact) + (tiny)						*/
12824601Szliu 
12956955Sbostic 	u1 += m*logF_head[N] + logF_head[j];		/* exact */
13056955Sbostic 	u2 = (u2 + logF_tail[j]) + q;			/* tiny */
13156955Sbostic 	u2 += logF_tail[N]*m;
13256955Sbostic 	return (u1 + u2);
13356955Sbostic }
13424601Szliu 
13556955Sbostic /* Extra precision variant, returning
13656955Sbostic  * struct {double a, b;}; log(x) = a+b to 63 bits, with
13756955Sbostic  * a is rounded to 26 bits.
13856955Sbostic  */
13956955Sbostic struct Double
14056955Sbostic #ifdef _ANSI_SOURCE
14156955Sbostic log__D(double x)
14256955Sbostic #else
14356955Sbostic log__D(x) double x;
14456955Sbostic #endif
14556955Sbostic {
14656955Sbostic 	int m, j;
14756955Sbostic 	double F, f, g, q, u, v, u2;
14856955Sbostic 	double logb(), ldexp();
14956955Sbostic 	volatile double u1;
15056955Sbostic 	struct Double r;
15124601Szliu 
15256955Sbostic 	/* Argument reduction: 1 <= g < 2; x/2^m = g;	*/
15356955Sbostic 	/* y = F*(1 + f/F) for |f| <= 2^-8		*/
15424601Szliu 
15556955Sbostic 	m = logb(x);
15656955Sbostic 	g = ldexp(x, -m);
15756955Sbostic 	if (_IEEE && m == -1022) {
15856955Sbostic 		j = logb(g), m += j;
15956955Sbostic 		g = ldexp(g, -j);
16024601Szliu 	}
16156955Sbostic 	j = N*(g-1) + .5;
16256955Sbostic 	F = (1.0/N) * j + 1;
16356955Sbostic 	f = g - F;
16424601Szliu 
16556955Sbostic 	g = 1/(2*F+f);
16656955Sbostic 	u = 2*f*g;
16756955Sbostic 	v = u*u;
16856955Sbostic 	q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
16956955Sbostic 	if (m | j)
17056955Sbostic 		u1 = u + 513, u1 -= 513;
17156955Sbostic 	else
17256955Sbostic 		u1 = u, TRUNC(u1);
17356955Sbostic 	u2 = (2.0*(f - F*u1) - u1*f) * g;
17424601Szliu 
17556955Sbostic 	u1 += m*logF_head[N] + logF_head[j];
17624601Szliu 
17756955Sbostic 	u2 +=  logF_tail[j]; u2 += q;
17856955Sbostic 	u2 += logF_tail[N]*m;
17956955Sbostic 	r.a = u1 + u2;			/* Only difference is here */
18056955Sbostic 	TRUNC(r.a);
18156955Sbostic 	r.b = (u1 - r.a) + u2;
18256955Sbostic 	return (r);
18324601Szliu }
184