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