1*2f2c0062Sguenther /* $OpenBSD: e_logl.c,v 1.2 2016/09/12 19:47:02 guenther Exp $ */
249393c00Smartynas
349393c00Smartynas /*
449393c00Smartynas * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
549393c00Smartynas *
649393c00Smartynas * Permission to use, copy, modify, and distribute this software for any
749393c00Smartynas * purpose with or without fee is hereby granted, provided that the above
849393c00Smartynas * copyright notice and this permission notice appear in all copies.
949393c00Smartynas *
1049393c00Smartynas * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1149393c00Smartynas * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1249393c00Smartynas * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1349393c00Smartynas * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1449393c00Smartynas * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1549393c00Smartynas * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1649393c00Smartynas * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1749393c00Smartynas */
1849393c00Smartynas
1949393c00Smartynas /* logl.c
2049393c00Smartynas *
2149393c00Smartynas * Natural logarithm for 128-bit long double precision.
2249393c00Smartynas *
2349393c00Smartynas *
2449393c00Smartynas *
2549393c00Smartynas * SYNOPSIS:
2649393c00Smartynas *
2749393c00Smartynas * long double x, y, logl();
2849393c00Smartynas *
2949393c00Smartynas * y = logl( x );
3049393c00Smartynas *
3149393c00Smartynas *
3249393c00Smartynas *
3349393c00Smartynas * DESCRIPTION:
3449393c00Smartynas *
3549393c00Smartynas * Returns the base e (2.718...) logarithm of x.
3649393c00Smartynas *
3749393c00Smartynas * The argument is separated into its exponent and fractional
3849393c00Smartynas * parts. Use of a lookup table increases the speed of the routine.
3949393c00Smartynas * The program uses logarithms tabulated at intervals of 1/128 to
4049393c00Smartynas * cover the domain from approximately 0.7 to 1.4.
4149393c00Smartynas *
4249393c00Smartynas * On the interval [-1/128, +1/128] the logarithm of 1+x is approximated by
4349393c00Smartynas * log(1+x) = x - 0.5 x^2 + x^3 P(x) .
4449393c00Smartynas *
4549393c00Smartynas *
4649393c00Smartynas *
4749393c00Smartynas * ACCURACY:
4849393c00Smartynas *
4949393c00Smartynas * Relative error:
5049393c00Smartynas * arithmetic domain # trials peak rms
5149393c00Smartynas * IEEE 0.875, 1.125 100000 1.2e-34 4.1e-35
5249393c00Smartynas * IEEE 0.125, 8 100000 1.2e-34 4.1e-35
5349393c00Smartynas *
5449393c00Smartynas *
5549393c00Smartynas * WARNING:
5649393c00Smartynas *
5749393c00Smartynas * This program uses integer operations on bit fields of floating-point
5849393c00Smartynas * numbers. It does not work with data structures other than the
5949393c00Smartynas * structure assumed.
6049393c00Smartynas *
6149393c00Smartynas */
6249393c00Smartynas
6349393c00Smartynas #include <math.h>
6449393c00Smartynas
6549393c00Smartynas #include "math_private.h"
6649393c00Smartynas
6749393c00Smartynas /* log(1+x) = x - .5 x^2 + x^3 l(x)
6849393c00Smartynas -.0078125 <= x <= +.0078125
6949393c00Smartynas peak relative error 1.2e-37 */
7049393c00Smartynas static const long double
7149393c00Smartynas l3 = 3.333333333333333333333333333333336096926E-1L,
7249393c00Smartynas l4 = -2.499999999999999999999999999486853077002E-1L,
7349393c00Smartynas l5 = 1.999999999999999999999999998515277861905E-1L,
7449393c00Smartynas l6 = -1.666666666666666666666798448356171665678E-1L,
7549393c00Smartynas l7 = 1.428571428571428571428808945895490721564E-1L,
7649393c00Smartynas l8 = -1.249999999999999987884655626377588149000E-1L,
7749393c00Smartynas l9 = 1.111111111111111093947834982832456459186E-1L,
7849393c00Smartynas l10 = -1.000000000000532974938900317952530453248E-1L,
7949393c00Smartynas l11 = 9.090909090915566247008015301349979892689E-2L,
8049393c00Smartynas l12 = -8.333333211818065121250921925397567745734E-2L,
8149393c00Smartynas l13 = 7.692307559897661630807048686258659316091E-2L,
8249393c00Smartynas l14 = -7.144242754190814657241902218399056829264E-2L,
8349393c00Smartynas l15 = 6.668057591071739754844678883223432347481E-2L;
8449393c00Smartynas
8549393c00Smartynas /* Lookup table of ln(t) - (t-1)
8649393c00Smartynas t = 0.5 + (k+26)/128)
8749393c00Smartynas k = 0, ..., 91 */
8849393c00Smartynas static const long double logtbl[92] = {
8949393c00Smartynas -5.5345593589352099112142921677820359632418E-2L,
9049393c00Smartynas -5.2108257402767124761784665198737642086148E-2L,
9149393c00Smartynas -4.8991686870576856279407775480686721935120E-2L,
9249393c00Smartynas -4.5993270766361228596215288742353061431071E-2L,
9349393c00Smartynas -4.3110481649613269682442058976885699556950E-2L,
9449393c00Smartynas -4.0340872319076331310838085093194799765520E-2L,
9549393c00Smartynas -3.7682072451780927439219005993827431503510E-2L,
9649393c00Smartynas -3.5131785416234343803903228503274262719586E-2L,
9749393c00Smartynas -3.2687785249045246292687241862699949178831E-2L,
9849393c00Smartynas -3.0347913785027239068190798397055267411813E-2L,
9949393c00Smartynas -2.8110077931525797884641940838507561326298E-2L,
10049393c00Smartynas -2.5972247078357715036426583294246819637618E-2L,
10149393c00Smartynas -2.3932450635346084858612873953407168217307E-2L,
10249393c00Smartynas -2.1988775689981395152022535153795155900240E-2L,
10349393c00Smartynas -2.0139364778244501615441044267387667496733E-2L,
10449393c00Smartynas -1.8382413762093794819267536615342902718324E-2L,
10549393c00Smartynas -1.6716169807550022358923589720001638093023E-2L,
10649393c00Smartynas -1.5138929457710992616226033183958974965355E-2L,
10749393c00Smartynas -1.3649036795397472900424896523305726435029E-2L,
10849393c00Smartynas -1.2244881690473465543308397998034325468152E-2L,
10949393c00Smartynas -1.0924898127200937840689817557742469105693E-2L,
11049393c00Smartynas -9.6875626072830301572839422532631079809328E-3L,
11149393c00Smartynas -8.5313926245226231463436209313499745894157E-3L,
11249393c00Smartynas -7.4549452072765973384933565912143044991706E-3L,
11349393c00Smartynas -6.4568155251217050991200599386801665681310E-3L,
11449393c00Smartynas -5.5356355563671005131126851708522185605193E-3L,
11549393c00Smartynas -4.6900728132525199028885749289712348829878E-3L,
11649393c00Smartynas -3.9188291218610470766469347968659624282519E-3L,
11749393c00Smartynas -3.2206394539524058873423550293617843896540E-3L,
11849393c00Smartynas -2.5942708080877805657374888909297113032132E-3L,
11949393c00Smartynas -2.0385211375711716729239156839929281289086E-3L,
12049393c00Smartynas -1.5522183228760777967376942769773768850872E-3L,
12149393c00Smartynas -1.1342191863606077520036253234446621373191E-3L,
12249393c00Smartynas -7.8340854719967065861624024730268350459991E-4L,
12349393c00Smartynas -4.9869831458030115699628274852562992756174E-4L,
12449393c00Smartynas -2.7902661731604211834685052867305795169688E-4L,
12549393c00Smartynas -1.2335696813916860754951146082826952093496E-4L,
12649393c00Smartynas -3.0677461025892873184042490943581654591817E-5L,
12749393c00Smartynas #define ZERO logtbl[38]
12849393c00Smartynas 0.0000000000000000000000000000000000000000E0L,
12949393c00Smartynas -3.0359557945051052537099938863236321874198E-5L,
13049393c00Smartynas -1.2081346403474584914595395755316412213151E-4L,
13149393c00Smartynas -2.7044071846562177120083903771008342059094E-4L,
13249393c00Smartynas -4.7834133324631162897179240322783590830326E-4L,
13349393c00Smartynas -7.4363569786340080624467487620270965403695E-4L,
13449393c00Smartynas -1.0654639687057968333207323853366578860679E-3L,
13549393c00Smartynas -1.4429854811877171341298062134712230604279E-3L,
13649393c00Smartynas -1.8753781835651574193938679595797367137975E-3L,
13749393c00Smartynas -2.3618380914922506054347222273705859653658E-3L,
13849393c00Smartynas -2.9015787624124743013946600163375853631299E-3L,
13949393c00Smartynas -3.4938307889254087318399313316921940859043E-3L,
14049393c00Smartynas -4.1378413103128673800485306215154712148146E-3L,
14149393c00Smartynas -4.8328735414488877044289435125365629849599E-3L,
14249393c00Smartynas -5.5782063183564351739381962360253116934243E-3L,
14349393c00Smartynas -6.3731336597098858051938306767880719015261E-3L,
14449393c00Smartynas -7.2169643436165454612058905294782949315193E-3L,
14549393c00Smartynas -8.1090214990427641365934846191367315083867E-3L,
14649393c00Smartynas -9.0486422112807274112838713105168375482480E-3L,
14749393c00Smartynas -1.0035177140880864314674126398350812606841E-2L,
14849393c00Smartynas -1.1067990155502102718064936259435676477423E-2L,
14949393c00Smartynas -1.2146457974158024928196575103115488672416E-2L,
15049393c00Smartynas -1.3269969823361415906628825374158424754308E-2L,
15149393c00Smartynas -1.4437927104692837124388550722759686270765E-2L,
15249393c00Smartynas -1.5649743073340777659901053944852735064621E-2L,
15349393c00Smartynas -1.6904842527181702880599758489058031645317E-2L,
15449393c00Smartynas -1.8202661505988007336096407340750378994209E-2L,
15549393c00Smartynas -1.9542647000370545390701192438691126552961E-2L,
15649393c00Smartynas -2.0924256670080119637427928803038530924742E-2L,
15749393c00Smartynas -2.2346958571309108496179613803760727786257E-2L,
15849393c00Smartynas -2.3810230892650362330447187267648486279460E-2L,
15949393c00Smartynas -2.5313561699385640380910474255652501521033E-2L,
16049393c00Smartynas -2.6856448685790244233704909690165496625399E-2L,
16149393c00Smartynas -2.8438398935154170008519274953860128449036E-2L,
16249393c00Smartynas -3.0058928687233090922411781058956589863039E-2L,
16349393c00Smartynas -3.1717563112854831855692484086486099896614E-2L,
16449393c00Smartynas -3.3413836095418743219397234253475252001090E-2L,
16549393c00Smartynas -3.5147290019036555862676702093393332533702E-2L,
16649393c00Smartynas -3.6917475563073933027920505457688955423688E-2L,
16749393c00Smartynas -3.8723951502862058660874073462456610731178E-2L,
16849393c00Smartynas -4.0566284516358241168330505467000838017425E-2L,
16949393c00Smartynas -4.2444048996543693813649967076598766917965E-2L,
17049393c00Smartynas -4.4356826869355401653098777649745233339196E-2L,
17149393c00Smartynas -4.6304207416957323121106944474331029996141E-2L,
17249393c00Smartynas -4.8285787106164123613318093945035804818364E-2L,
17349393c00Smartynas -5.0301169421838218987124461766244507342648E-2L,
17449393c00Smartynas -5.2349964705088137924875459464622098310997E-2L,
17549393c00Smartynas -5.4431789996103111613753440311680967840214E-2L,
17649393c00Smartynas -5.6546268881465384189752786409400404404794E-2L,
17749393c00Smartynas -5.8693031345788023909329239565012647817664E-2L,
17849393c00Smartynas -6.0871713627532018185577188079210189048340E-2L,
17949393c00Smartynas -6.3081958078862169742820420185833800925568E-2L,
18049393c00Smartynas -6.5323413029406789694910800219643791556918E-2L,
18149393c00Smartynas -6.7595732653791419081537811574227049288168E-2L
18249393c00Smartynas };
18349393c00Smartynas
18449393c00Smartynas /* ln(2) = ln2a + ln2b with extended precision. */
18549393c00Smartynas static const long double
18649393c00Smartynas ln2a = 6.93145751953125e-1L,
18749393c00Smartynas ln2b = 1.4286068203094172321214581765680755001344E-6L;
18849393c00Smartynas
18949393c00Smartynas long double
logl(long double x)19049393c00Smartynas logl(long double x)
19149393c00Smartynas {
19249393c00Smartynas long double z, y, w;
19349393c00Smartynas ieee_quad_shape_type u, t;
19449393c00Smartynas unsigned int m;
19549393c00Smartynas int k, e;
19649393c00Smartynas
19749393c00Smartynas u.value = x;
19849393c00Smartynas m = u.parts32.mswhi;
19949393c00Smartynas
20049393c00Smartynas /* Check for IEEE special cases. */
20149393c00Smartynas k = m & 0x7fffffff;
20249393c00Smartynas /* log(0) = -infinity. */
20349393c00Smartynas if ((k | u.parts32.mswlo | u.parts32.lswhi | u.parts32.lswlo) == 0)
20449393c00Smartynas {
20549393c00Smartynas return -0.5L / ZERO;
20649393c00Smartynas }
20749393c00Smartynas /* log ( x < 0 ) = NaN */
20849393c00Smartynas if (m & 0x80000000)
20949393c00Smartynas {
21049393c00Smartynas return (x - x) / ZERO;
21149393c00Smartynas }
21249393c00Smartynas /* log (infinity or NaN) */
21349393c00Smartynas if (k >= 0x7fff0000)
21449393c00Smartynas {
21549393c00Smartynas return x + x;
21649393c00Smartynas }
21749393c00Smartynas
21849393c00Smartynas /* Extract exponent and reduce domain to 0.703125 <= u < 1.40625 */
21949393c00Smartynas e = (int) (m >> 16) - (int) 0x3ffe;
22049393c00Smartynas m &= 0xffff;
22149393c00Smartynas u.parts32.mswhi = m | 0x3ffe0000;
22249393c00Smartynas m |= 0x10000;
22349393c00Smartynas /* Find lookup table index k from high order bits of the significand. */
22449393c00Smartynas if (m < 0x16800)
22549393c00Smartynas {
22649393c00Smartynas k = (m - 0xff00) >> 9;
22749393c00Smartynas /* t is the argument 0.5 + (k+26)/128
22849393c00Smartynas of the nearest item to u in the lookup table. */
22949393c00Smartynas t.parts32.mswhi = 0x3fff0000 + (k << 9);
23049393c00Smartynas t.parts32.mswlo = 0;
23149393c00Smartynas t.parts32.lswhi = 0;
23249393c00Smartynas t.parts32.lswlo = 0;
23349393c00Smartynas u.parts32.mswhi += 0x10000;
23449393c00Smartynas e -= 1;
23549393c00Smartynas k += 64;
23649393c00Smartynas }
23749393c00Smartynas else
23849393c00Smartynas {
23949393c00Smartynas k = (m - 0xfe00) >> 10;
24049393c00Smartynas t.parts32.mswhi = 0x3ffe0000 + (k << 10);
24149393c00Smartynas t.parts32.mswlo = 0;
24249393c00Smartynas t.parts32.lswhi = 0;
24349393c00Smartynas t.parts32.lswlo = 0;
24449393c00Smartynas }
24549393c00Smartynas /* On this interval the table is not used due to cancellation error. */
24649393c00Smartynas if ((x <= 1.0078125L) && (x >= 0.9921875L))
24749393c00Smartynas {
24849393c00Smartynas z = x - 1.0L;
24949393c00Smartynas k = 64;
25049393c00Smartynas t.value = 1.0L;
25149393c00Smartynas e = 0;
25249393c00Smartynas }
25349393c00Smartynas else
25449393c00Smartynas {
25549393c00Smartynas /* log(u) = log( t u/t ) = log(t) + log(u/t)
25649393c00Smartynas log(t) is tabulated in the lookup table.
25749393c00Smartynas Express log(u/t) = log(1+z), where z = u/t - 1 = (u-t)/t.
25849393c00Smartynas cf. Cody & Waite. */
25949393c00Smartynas z = (u.value - t.value) / t.value;
26049393c00Smartynas }
26149393c00Smartynas /* Series expansion of log(1+z). */
26249393c00Smartynas w = z * z;
26349393c00Smartynas y = ((((((((((((l15 * z
26449393c00Smartynas + l14) * z
26549393c00Smartynas + l13) * z
26649393c00Smartynas + l12) * z
26749393c00Smartynas + l11) * z
26849393c00Smartynas + l10) * z
26949393c00Smartynas + l9) * z
27049393c00Smartynas + l8) * z
27149393c00Smartynas + l7) * z
27249393c00Smartynas + l6) * z
27349393c00Smartynas + l5) * z
27449393c00Smartynas + l4) * z
27549393c00Smartynas + l3) * z * w;
27649393c00Smartynas y -= 0.5 * w;
27749393c00Smartynas y += e * ln2b; /* Base 2 exponent offset times ln(2). */
27849393c00Smartynas y += z;
27949393c00Smartynas y += logtbl[k-26]; /* log(t) - (t-1) */
28049393c00Smartynas y += (t.value - 1.0L);
28149393c00Smartynas y += e * ln2a;
28249393c00Smartynas return y;
28349393c00Smartynas }
284*2f2c0062Sguenther DEF_STD(logl);
285