134126Sbostic /*
261309Sbostic * Copyright (c) 1992, 1993
361309Sbostic * The Regents of the University of California. All rights reserved.
434126Sbostic *
542657Sbostic * %sccs.include.redist.c%
624601Szliu */
724601Szliu
824601Szliu #ifndef lint
9*64992Smckusick static char sccsid[] = "@(#)log.c 8.2 (Berkeley) 11/30/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 */
7357453Sbostic static double A1 = .08333333333333178827;
7457453Sbostic static double A2 = .01250000000377174923;
7557453Sbostic static double A3 = .002232139987919447809;
7657453Sbostic static double A4 = .0004348877777076145742;
7757442Sbostic
7857453Sbostic static 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
21057453Sbostic static 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
log(double x)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 volatile double u1;
35235679Sbostic
35356955Sbostic /* Catch special cases */
35456955Sbostic if (x <= 0)
35556955Sbostic if (_IEEE && x == zero) /* log(0) = -Inf */
35656955Sbostic return (-one/zero);
35756955Sbostic else if (_IEEE) /* log(neg) = NaN */
35856955Sbostic return (zero/zero);
35956955Sbostic else if (x == zero) /* NOT REACHED IF _IEEE */
36056955Sbostic return (infnan(-ERANGE));
36156955Sbostic else
36256955Sbostic return (infnan(EDOM));
36356955Sbostic else if (!finite(x))
36456955Sbostic if (_IEEE) /* x = NaN, Inf */
36556955Sbostic return (x+x);
36656955Sbostic else
36756955Sbostic return (infnan(ERANGE));
36856955Sbostic
36956955Sbostic /* Argument reduction: 1 <= g < 2; x/2^m = g; */
37056955Sbostic /* y = F*(1 + f/F) for |f| <= 2^-8 */
37135679Sbostic
37256955Sbostic m = logb(x);
37356955Sbostic g = ldexp(x, -m);
37456955Sbostic if (_IEEE && m == -1022) {
37556955Sbostic j = logb(g), m += j;
37656955Sbostic g = ldexp(g, -j);
37756955Sbostic }
37856955Sbostic j = N*(g-1) + .5;
37956955Sbostic F = (1.0/N) * j + 1; /* F*128 is an integer in [128, 512] */
38056955Sbostic f = g - F;
38135679Sbostic
38256955Sbostic /* Approximate expansion for log(1+f/F) ~= u + q */
38356955Sbostic g = 1/(2*F+f);
38456955Sbostic u = 2*f*g;
38556955Sbostic v = u*u;
38656955Sbostic q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
38735679Sbostic
38856955Sbostic /* case 1: u1 = u rounded to 2^-43 absolute. Since u < 2^-8,
38956955Sbostic * u1 has at most 35 bits, and F*u1 is exact, as F has < 8 bits.
39056955Sbostic * It also adds exactly to |m*log2_hi + log_F_head[j] | < 750
39156955Sbostic */
39256955Sbostic if (m | j)
39356955Sbostic u1 = u + 513, u1 -= 513;
39424601Szliu
39556955Sbostic /* case 2: |1-x| < 1/256. The m- and j- dependent terms are zero;
39656955Sbostic * u1 = u to 24 bits.
39756955Sbostic */
39856955Sbostic else
39956955Sbostic u1 = u, TRUNC(u1);
40056955Sbostic u2 = (2.0*(f - F*u1) - u1*f) * g;
40156955Sbostic /* u1 + u2 = 2f/(2F+f) to extra precision. */
40224601Szliu
40356955Sbostic /* log(x) = log(2^m*F*(1+f/F)) = */
40456955Sbostic /* (m*log2_hi+logF_head[j]+u1) + (m*log2_lo+logF_tail[j]+q); */
40556955Sbostic /* (exact) + (tiny) */
40624601Szliu
40756955Sbostic u1 += m*logF_head[N] + logF_head[j]; /* exact */
40856955Sbostic u2 = (u2 + logF_tail[j]) + q; /* tiny */
40956955Sbostic u2 += logF_tail[N]*m;
41056955Sbostic return (u1 + u2);
41156955Sbostic }
41224601Szliu
41357442Sbostic /*
41457442Sbostic * Extra precision variant, returning struct {double a, b;};
41557442Sbostic * log(x) = a+b to 63 bits, with a is rounded to 26 bits.
41656955Sbostic */
41756955Sbostic struct Double
41856955Sbostic #ifdef _ANSI_SOURCE
__log__D(double x)41957452Sbostic __log__D(double x)
42056955Sbostic #else
42157452Sbostic __log__D(x) double x;
42256955Sbostic #endif
42356955Sbostic {
42456955Sbostic int m, j;
42557442Sbostic double F, f, g, q, u, v, u2, one = 1.0;
42656955Sbostic volatile double u1;
42756955Sbostic struct Double r;
42824601Szliu
42956955Sbostic /* Argument reduction: 1 <= g < 2; x/2^m = g; */
43056955Sbostic /* y = F*(1 + f/F) for |f| <= 2^-8 */
43124601Szliu
43256955Sbostic m = logb(x);
43356955Sbostic g = ldexp(x, -m);
43456955Sbostic if (_IEEE && m == -1022) {
43556955Sbostic j = logb(g), m += j;
43656955Sbostic g = ldexp(g, -j);
43724601Szliu }
43856955Sbostic j = N*(g-1) + .5;
43956955Sbostic F = (1.0/N) * j + 1;
44056955Sbostic f = g - F;
44124601Szliu
44256955Sbostic g = 1/(2*F+f);
44356955Sbostic u = 2*f*g;
44456955Sbostic v = u*u;
44556955Sbostic q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
44656955Sbostic if (m | j)
44756955Sbostic u1 = u + 513, u1 -= 513;
44856955Sbostic else
44956955Sbostic u1 = u, TRUNC(u1);
45056955Sbostic u2 = (2.0*(f - F*u1) - u1*f) * g;
45124601Szliu
45256955Sbostic u1 += m*logF_head[N] + logF_head[j];
45324601Szliu
45456955Sbostic u2 += logF_tail[j]; u2 += q;
45556955Sbostic u2 += logF_tail[N]*m;
45656955Sbostic r.a = u1 + u2; /* Only difference is here */
45756955Sbostic TRUNC(r.a);
45856955Sbostic r.b = (u1 - r.a) + u2;
45956955Sbostic return (r);
46024601Szliu }
461