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*57452Sbostic static char sccsid[] = "@(#)log.c 5.11 (Berkeley) 01/10/93"; 1034126Sbostic #endif /* not lint */ 1124601Szliu 1256955Sbostic #include <math.h> 1356955Sbostic #include <errno.h> 1456955Sbostic 1557158Smcilroy #include "mathimpl.h" 1656955Sbostic 1756955Sbostic /* Table-driven natural logarithm. 1824601Szliu * 1956955Sbostic * This code was derived, with minor modifications, from: 2056955Sbostic * Peter Tang, "Table-Driven Implementation of the 2156955Sbostic * Logarithm in IEEE Floating-Point arithmetic." ACM Trans. 2256955Sbostic * Math Software, vol 16. no 4, pp 378-400, Dec 1990). 2324601Szliu * 2456955Sbostic * Calculates log(2^m*F*(1+f/F)), |f/j| <= 1/256, 2556955Sbostic * where F = j/128 for j an integer in [0, 128]. 2624601Szliu * 2756955Sbostic * log(2^m) = log2_hi*m + log2_tail*m 2856955Sbostic * since m is an integer, the dominant term is exact. 2956955Sbostic * m has at most 10 digits (for subnormal numbers), 3056955Sbostic * and log2_hi has 11 trailing zero bits. 3124601Szliu * 3256955Sbostic * log(F) = logF_hi[j] + logF_lo[j] is in tabular form in log_table.h 3356955Sbostic * logF_hi[] + 512 is exact. 3424601Szliu * 3556955Sbostic * log(1+f/F) = 2*f/(2*F + f) + 1/12 * (2*f/(2*F + f))**3 + ... 3656955Sbostic * the leading term is calculated to extra precision in two 3756955Sbostic * parts, the larger of which adds exactly to the dominant 3856955Sbostic * m and F terms. 3956955Sbostic * There are two cases: 4056955Sbostic * 1. when m, j are non-zero (m | j), use absolute 4156955Sbostic * precision for the leading term. 4256955Sbostic * 2. when m = j = 0, |1-x| < 1/256, and log(x) ~= (x-1). 4356955Sbostic * In this case, use a relative precision of 24 bits. 4456955Sbostic * (This is done differently in the original paper) 4524601Szliu * 4624601Szliu * Special cases: 4756955Sbostic * 0 return signalling -Inf 4856955Sbostic * neg return signalling NaN 4956955Sbostic * +Inf return +Inf 5056955Sbostic */ 5124601Szliu 5256955Sbostic #if defined(vax) || defined(tahoe) 5357156Smcilroy #define _IEEE 0 5457156Smcilroy #define TRUNC(x) x = (double) (float) (x) 5556955Sbostic #else 5657442Sbostic #define _IEEE 1 5757156Smcilroy #define endian (((*(int *) &one)) ? 1 : 0) 5857156Smcilroy #define TRUNC(x) *(((int *) &x) + endian) &= 0xf8000000 5957156Smcilroy #define infnan(x) 0.0 6056955Sbostic #endif 6124601Szliu 6257442Sbostic #define N 128 6357442Sbostic 6457442Sbostic /* Table of log(Fj) = logF_head[j] + logF_tail[j], for Fj = 1+j/128. 6557442Sbostic * Used for generation of extend precision logarithms. 6657442Sbostic * The constant 35184372088832 is 2^45, so the divide is exact. 6757442Sbostic * It ensures correct reading of logF_head, even for inaccurate 6857442Sbostic * decimal-to-binary conversion routines. (Everybody gets the 6957442Sbostic * right answer for integers less than 2^53.) 7057442Sbostic * Values for log(F) were generated using error < 10^-57 absolute 7157442Sbostic * with the bc -l package. 7257442Sbostic */ 7357442Sbostic double A1 = .08333333333333178827; 7457442Sbostic double A2 = .01250000000377174923; 7557442Sbostic double A3 = .002232139987919447809; 7657442Sbostic double A4 = .0004348877777076145742; 7757442Sbostic 7857442Sbostic double logF_head[N+1] = { 7957442Sbostic 0., 8057442Sbostic .007782140442060381246, 8157442Sbostic .015504186535963526694, 8257442Sbostic .023167059281547608406, 8357442Sbostic .030771658666765233647, 8457442Sbostic .038318864302141264488, 8557442Sbostic .045809536031242714670, 8657442Sbostic .053244514518837604555, 8757442Sbostic .060624621816486978786, 8857442Sbostic .067950661908525944454, 8957442Sbostic .075223421237524235039, 9057442Sbostic .082443669210988446138, 9157442Sbostic .089612158689760690322, 9257442Sbostic .096729626458454731618, 9357442Sbostic .103796793681567578460, 9457442Sbostic .110814366340264314203, 9557442Sbostic .117783035656430001836, 9657442Sbostic .124703478501032805070, 9757442Sbostic .131576357788617315236, 9857442Sbostic .138402322859292326029, 9957442Sbostic .145182009844575077295, 10057442Sbostic .151916042025732167530, 10157442Sbostic .158605030176659056451, 10257442Sbostic .165249572895390883786, 10357442Sbostic .171850256926518341060, 10457442Sbostic .178407657472689606947, 10557442Sbostic .184922338493834104156, 10657442Sbostic .191394852999565046047, 10757442Sbostic .197825743329758552135, 10857442Sbostic .204215541428766300668, 10957442Sbostic .210564769107350002741, 11057442Sbostic .216873938300523150246, 11157442Sbostic .223143551314024080056, 11257442Sbostic .229374101064877322642, 11357442Sbostic .235566071312860003672, 11457442Sbostic .241719936886966024758, 11557442Sbostic .247836163904594286577, 11657442Sbostic .253915209980732470285, 11757442Sbostic .259957524436686071567, 11857442Sbostic .265963548496984003577, 11957442Sbostic .271933715484010463114, 12057442Sbostic .277868451003087102435, 12157442Sbostic .283768173130738432519, 12257442Sbostic .289633292582948342896, 12357442Sbostic .295464212893421063199, 12457442Sbostic .301261330578199704177, 12557442Sbostic .307025035294827830512, 12657442Sbostic .312755710004239517729, 12757442Sbostic .318453731118097493890, 12857442Sbostic .324119468654316733591, 12957442Sbostic .329753286372579168528, 13057442Sbostic .335355541920762334484, 13157442Sbostic .340926586970454081892, 13257442Sbostic .346466767346100823488, 13357442Sbostic .351976423156884266063, 13457442Sbostic .357455888922231679316, 13557442Sbostic .362905493689140712376, 13657442Sbostic .368325561158599157352, 13757442Sbostic .373716409793814818840, 13857442Sbostic .379078352934811846353, 13957442Sbostic .384411698910298582632, 14057442Sbostic .389716751140440464951, 14157442Sbostic .394993808240542421117, 14257442Sbostic .400243164127459749579, 14357442Sbostic .405465108107819105498, 14457442Sbostic .410659924985338875558, 14557442Sbostic .415827895143593195825, 14657442Sbostic .420969294644237379543, 14757442Sbostic .426084395310681429691, 14857442Sbostic .431173464818130014464, 14957442Sbostic .436236766774527495726, 15057442Sbostic .441274560805140936281, 15157442Sbostic .446287102628048160113, 15257442Sbostic .451274644139630254358, 15357442Sbostic .456237433481874177232, 15457442Sbostic .461175715122408291790, 15557442Sbostic .466089729924533457960, 15657442Sbostic .470979715219073113985, 15757442Sbostic .475845904869856894947, 15857442Sbostic .480688529345570714212, 15957442Sbostic .485507815781602403149, 16057442Sbostic .490303988045525329653, 16157442Sbostic .495077266798034543171, 16257442Sbostic .499827869556611403822, 16357442Sbostic .504556010751912253908, 16457442Sbostic .509261901790523552335, 16557442Sbostic .513945751101346104405, 16657442Sbostic .518607764208354637958, 16757442Sbostic .523248143765158602036, 16857442Sbostic .527867089620485785417, 16957442Sbostic .532464798869114019908, 17057442Sbostic .537041465897345915436, 17157442Sbostic .541597282432121573947, 17257442Sbostic .546132437597407260909, 17357442Sbostic .550647117952394182793, 17457442Sbostic .555141507540611200965, 17557442Sbostic .559615787935399566777, 17657442Sbostic .564070138285387656651, 17757442Sbostic .568504735352689749561, 17857442Sbostic .572919753562018740922, 17957442Sbostic .577315365035246941260, 18057442Sbostic .581691739635061821900, 18157442Sbostic .586049045003164792433, 18257442Sbostic .590387446602107957005, 18357442Sbostic .594707107746216934174, 18457442Sbostic .599008189645246602594, 18557442Sbostic .603290851438941899687, 18657442Sbostic .607555250224322662688, 18757442Sbostic .611801541106615331955, 18857442Sbostic .616029877215623855590, 18957442Sbostic .620240409751204424537, 19057442Sbostic .624433288012369303032, 19157442Sbostic .628608659422752680256, 19257442Sbostic .632766669570628437213, 19357442Sbostic .636907462236194987781, 19457442Sbostic .641031179420679109171, 19557442Sbostic .645137961373620782978, 19657442Sbostic .649227946625615004450, 19757442Sbostic .653301272011958644725, 19857442Sbostic .657358072709030238911, 19957442Sbostic .661398482245203922502, 20057442Sbostic .665422632544505177065, 20157442Sbostic .669430653942981734871, 20257442Sbostic .673422675212350441142, 20357442Sbostic .677398823590920073911, 20457442Sbostic .681359224807238206267, 20557442Sbostic .685304003098281100392, 20657442Sbostic .689233281238557538017, 20757442Sbostic .693147180560117703862 20857442Sbostic }; 20957442Sbostic 21057442Sbostic double logF_tail[N+1] = { 21157442Sbostic 0., 21257442Sbostic -.00000000000000543229938420049, 21357442Sbostic .00000000000000172745674997061, 21457442Sbostic -.00000000000001323017818229233, 21557442Sbostic -.00000000000001154527628289872, 21657442Sbostic -.00000000000000466529469958300, 21757442Sbostic .00000000000005148849572685810, 21857442Sbostic -.00000000000002532168943117445, 21957442Sbostic -.00000000000005213620639136504, 22057442Sbostic -.00000000000001819506003016881, 22157442Sbostic .00000000000006329065958724544, 22257442Sbostic .00000000000008614512936087814, 22357442Sbostic -.00000000000007355770219435028, 22457442Sbostic .00000000000009638067658552277, 22557442Sbostic .00000000000007598636597194141, 22657442Sbostic .00000000000002579999128306990, 22757442Sbostic -.00000000000004654729747598444, 22857442Sbostic -.00000000000007556920687451336, 22957442Sbostic .00000000000010195735223708472, 23057442Sbostic -.00000000000017319034406422306, 23157442Sbostic -.00000000000007718001336828098, 23257442Sbostic .00000000000010980754099855238, 23357442Sbostic -.00000000000002047235780046195, 23457442Sbostic -.00000000000008372091099235912, 23557442Sbostic .00000000000014088127937111135, 23657442Sbostic .00000000000012869017157588257, 23757442Sbostic .00000000000017788850778198106, 23857442Sbostic .00000000000006440856150696891, 23957442Sbostic .00000000000016132822667240822, 24057442Sbostic -.00000000000007540916511956188, 24157442Sbostic -.00000000000000036507188831790, 24257442Sbostic .00000000000009120937249914984, 24357442Sbostic .00000000000018567570959796010, 24457442Sbostic -.00000000000003149265065191483, 24557442Sbostic -.00000000000009309459495196889, 24657442Sbostic .00000000000017914338601329117, 24757442Sbostic -.00000000000001302979717330866, 24857442Sbostic .00000000000023097385217586939, 24957442Sbostic .00000000000023999540484211737, 25057442Sbostic .00000000000015393776174455408, 25157442Sbostic -.00000000000036870428315837678, 25257442Sbostic .00000000000036920375082080089, 25357442Sbostic -.00000000000009383417223663699, 25457442Sbostic .00000000000009433398189512690, 25557442Sbostic .00000000000041481318704258568, 25657442Sbostic -.00000000000003792316480209314, 25757442Sbostic .00000000000008403156304792424, 25857442Sbostic -.00000000000034262934348285429, 25957442Sbostic .00000000000043712191957429145, 26057442Sbostic -.00000000000010475750058776541, 26157442Sbostic -.00000000000011118671389559323, 26257442Sbostic .00000000000037549577257259853, 26357442Sbostic .00000000000013912841212197565, 26457442Sbostic .00000000000010775743037572640, 26557442Sbostic .00000000000029391859187648000, 26657442Sbostic -.00000000000042790509060060774, 26757442Sbostic .00000000000022774076114039555, 26857442Sbostic .00000000000010849569622967912, 26957442Sbostic -.00000000000023073801945705758, 27057442Sbostic .00000000000015761203773969435, 27157442Sbostic .00000000000003345710269544082, 27257442Sbostic -.00000000000041525158063436123, 27357442Sbostic .00000000000032655698896907146, 27457442Sbostic -.00000000000044704265010452446, 27557442Sbostic .00000000000034527647952039772, 27657442Sbostic -.00000000000007048962392109746, 27757442Sbostic .00000000000011776978751369214, 27857442Sbostic -.00000000000010774341461609578, 27957442Sbostic .00000000000021863343293215910, 28057442Sbostic .00000000000024132639491333131, 28157442Sbostic .00000000000039057462209830700, 28257442Sbostic -.00000000000026570679203560751, 28357442Sbostic .00000000000037135141919592021, 28457442Sbostic -.00000000000017166921336082431, 28557442Sbostic -.00000000000028658285157914353, 28657442Sbostic -.00000000000023812542263446809, 28757442Sbostic .00000000000006576659768580062, 28857442Sbostic -.00000000000028210143846181267, 28957442Sbostic .00000000000010701931762114254, 29057442Sbostic .00000000000018119346366441110, 29157442Sbostic .00000000000009840465278232627, 29257442Sbostic -.00000000000033149150282752542, 29357442Sbostic -.00000000000018302857356041668, 29457442Sbostic -.00000000000016207400156744949, 29557442Sbostic .00000000000048303314949553201, 29657442Sbostic -.00000000000071560553172382115, 29757442Sbostic .00000000000088821239518571855, 29857442Sbostic -.00000000000030900580513238244, 29957442Sbostic -.00000000000061076551972851496, 30057442Sbostic .00000000000035659969663347830, 30157442Sbostic .00000000000035782396591276383, 30257442Sbostic -.00000000000046226087001544578, 30357442Sbostic .00000000000062279762917225156, 30457442Sbostic .00000000000072838947272065741, 30557442Sbostic .00000000000026809646615211673, 30657442Sbostic -.00000000000010960825046059278, 30757442Sbostic .00000000000002311949383800537, 30857442Sbostic -.00000000000058469058005299247, 30957442Sbostic -.00000000000002103748251144494, 31057442Sbostic -.00000000000023323182945587408, 31157442Sbostic -.00000000000042333694288141916, 31257442Sbostic -.00000000000043933937969737844, 31357442Sbostic .00000000000041341647073835565, 31457442Sbostic .00000000000006841763641591466, 31557442Sbostic .00000000000047585534004430641, 31657442Sbostic .00000000000083679678674757695, 31757442Sbostic -.00000000000085763734646658640, 31857442Sbostic .00000000000021913281229340092, 31957442Sbostic -.00000000000062242842536431148, 32057442Sbostic -.00000000000010983594325438430, 32157442Sbostic .00000000000065310431377633651, 32257442Sbostic -.00000000000047580199021710769, 32357442Sbostic -.00000000000037854251265457040, 32457442Sbostic .00000000000040939233218678664, 32557442Sbostic .00000000000087424383914858291, 32657442Sbostic .00000000000025218188456842882, 32757442Sbostic -.00000000000003608131360422557, 32857442Sbostic -.00000000000050518555924280902, 32957442Sbostic .00000000000078699403323355317, 33057442Sbostic -.00000000000067020876961949060, 33157442Sbostic .00000000000016108575753932458, 33257442Sbostic .00000000000058527188436251509, 33357442Sbostic -.00000000000035246757297904791, 33457442Sbostic -.00000000000018372084495629058, 33557442Sbostic .00000000000088606689813494916, 33657442Sbostic .00000000000066486268071468700, 33757442Sbostic .00000000000063831615170646519, 33857442Sbostic .00000000000025144230728376072, 33957442Sbostic -.00000000000017239444525614834 34057442Sbostic }; 34157442Sbostic 34256955Sbostic double 34356955Sbostic #ifdef _ANSI_SOURCE 34456955Sbostic log(double x) 34556955Sbostic #else 34656955Sbostic log(x) double x; 34756955Sbostic #endif 34856955Sbostic { 34956955Sbostic int m, j; 35056955Sbostic double F, f, g, q, u, u2, v, zero = 0.0, one = 1.0; 35156955Sbostic double logb(), ldexp(); 35256955Sbostic volatile double u1; 35335679Sbostic 35456955Sbostic /* Catch special cases */ 35556955Sbostic if (x <= 0) 35656955Sbostic if (_IEEE && x == zero) /* log(0) = -Inf */ 35756955Sbostic return (-one/zero); 35856955Sbostic else if (_IEEE) /* log(neg) = NaN */ 35956955Sbostic return (zero/zero); 36056955Sbostic else if (x == zero) /* NOT REACHED IF _IEEE */ 36156955Sbostic return (infnan(-ERANGE)); 36256955Sbostic else 36356955Sbostic return (infnan(EDOM)); 36456955Sbostic else if (!finite(x)) 36556955Sbostic if (_IEEE) /* x = NaN, Inf */ 36656955Sbostic return (x+x); 36756955Sbostic else 36856955Sbostic return (infnan(ERANGE)); 36956955Sbostic 37056955Sbostic /* Argument reduction: 1 <= g < 2; x/2^m = g; */ 37156955Sbostic /* y = F*(1 + f/F) for |f| <= 2^-8 */ 37235679Sbostic 37356955Sbostic m = logb(x); 37456955Sbostic g = ldexp(x, -m); 37556955Sbostic if (_IEEE && m == -1022) { 37656955Sbostic j = logb(g), m += j; 37756955Sbostic g = ldexp(g, -j); 37856955Sbostic } 37956955Sbostic j = N*(g-1) + .5; 38056955Sbostic F = (1.0/N) * j + 1; /* F*128 is an integer in [128, 512] */ 38156955Sbostic f = g - F; 38235679Sbostic 38356955Sbostic /* Approximate expansion for log(1+f/F) ~= u + q */ 38456955Sbostic g = 1/(2*F+f); 38556955Sbostic u = 2*f*g; 38656955Sbostic v = u*u; 38756955Sbostic q = u*v*(A1 + v*(A2 + v*(A3 + v*A4))); 38835679Sbostic 38956955Sbostic /* case 1: u1 = u rounded to 2^-43 absolute. Since u < 2^-8, 39056955Sbostic * u1 has at most 35 bits, and F*u1 is exact, as F has < 8 bits. 39156955Sbostic * It also adds exactly to |m*log2_hi + log_F_head[j] | < 750 39256955Sbostic */ 39356955Sbostic if (m | j) 39456955Sbostic u1 = u + 513, u1 -= 513; 39524601Szliu 39656955Sbostic /* case 2: |1-x| < 1/256. The m- and j- dependent terms are zero; 39756955Sbostic * u1 = u to 24 bits. 39856955Sbostic */ 39956955Sbostic else 40056955Sbostic u1 = u, TRUNC(u1); 40156955Sbostic u2 = (2.0*(f - F*u1) - u1*f) * g; 40256955Sbostic /* u1 + u2 = 2f/(2F+f) to extra precision. */ 40324601Szliu 40456955Sbostic /* log(x) = log(2^m*F*(1+f/F)) = */ 40556955Sbostic /* (m*log2_hi+logF_head[j]+u1) + (m*log2_lo+logF_tail[j]+q); */ 40656955Sbostic /* (exact) + (tiny) */ 40724601Szliu 40856955Sbostic u1 += m*logF_head[N] + logF_head[j]; /* exact */ 40956955Sbostic u2 = (u2 + logF_tail[j]) + q; /* tiny */ 41056955Sbostic u2 += logF_tail[N]*m; 41156955Sbostic return (u1 + u2); 41256955Sbostic } 41324601Szliu 41457442Sbostic /* 41557442Sbostic * Extra precision variant, returning struct {double a, b;}; 41657442Sbostic * log(x) = a+b to 63 bits, with a is rounded to 26 bits. 41756955Sbostic */ 41856955Sbostic struct Double 41956955Sbostic #ifdef _ANSI_SOURCE 420*57452Sbostic __log__D(double x) 42156955Sbostic #else 422*57452Sbostic __log__D(x) double x; 42356955Sbostic #endif 42456955Sbostic { 42556955Sbostic int m, j; 42657442Sbostic double F, f, g, q, u, v, u2, one = 1.0; 42756955Sbostic double logb(), ldexp(); 42856955Sbostic volatile double u1; 42956955Sbostic struct Double r; 43024601Szliu 43156955Sbostic /* Argument reduction: 1 <= g < 2; x/2^m = g; */ 43256955Sbostic /* y = F*(1 + f/F) for |f| <= 2^-8 */ 43324601Szliu 43456955Sbostic m = logb(x); 43556955Sbostic g = ldexp(x, -m); 43656955Sbostic if (_IEEE && m == -1022) { 43756955Sbostic j = logb(g), m += j; 43856955Sbostic g = ldexp(g, -j); 43924601Szliu } 44056955Sbostic j = N*(g-1) + .5; 44156955Sbostic F = (1.0/N) * j + 1; 44256955Sbostic f = g - F; 44324601Szliu 44456955Sbostic g = 1/(2*F+f); 44556955Sbostic u = 2*f*g; 44656955Sbostic v = u*u; 44756955Sbostic q = u*v*(A1 + v*(A2 + v*(A3 + v*A4))); 44856955Sbostic if (m | j) 44956955Sbostic u1 = u + 513, u1 -= 513; 45056955Sbostic else 45156955Sbostic u1 = u, TRUNC(u1); 45256955Sbostic u2 = (2.0*(f - F*u1) - u1*f) * g; 45324601Szliu 45456955Sbostic u1 += m*logF_head[N] + logF_head[j]; 45524601Szliu 45656955Sbostic u2 += logF_tail[j]; u2 += q; 45756955Sbostic u2 += logF_tail[N]*m; 45856955Sbostic r.a = u1 + u2; /* Only difference is here */ 45956955Sbostic TRUNC(r.a); 46056955Sbostic r.b = (u1 - r.a) + u2; 46156955Sbostic return (r); 46224601Szliu } 463