1da2e3ebdSchin #include "FEATURE/uwin"
2da2e3ebdSchin 
3da2e3ebdSchin #if !_UWIN
4da2e3ebdSchin 
_STUB_log()5da2e3ebdSchin void _STUB_log(){}
6da2e3ebdSchin 
7da2e3ebdSchin #else
8da2e3ebdSchin 
9da2e3ebdSchin /*
10da2e3ebdSchin  * Copyright (c) 1992, 1993
11da2e3ebdSchin  *	The Regents of the University of California.  All rights reserved.
12da2e3ebdSchin  *
13da2e3ebdSchin  * Redistribution and use in source and binary forms, with or without
14da2e3ebdSchin  * modification, are permitted provided that the following conditions
15da2e3ebdSchin  * are met:
16da2e3ebdSchin  * 1. Redistributions of source code must retain the above copyright
17da2e3ebdSchin  *    notice, this list of conditions and the following disclaimer.
18da2e3ebdSchin  * 2. Redistributions in binary form must reproduce the above copyright
19da2e3ebdSchin  *    notice, this list of conditions and the following disclaimer in the
20da2e3ebdSchin  *    documentation and/or other materials provided with the distribution.
21da2e3ebdSchin  * 3. Neither the name of the University nor the names of its contributors
22da2e3ebdSchin  *    may be used to endorse or promote products derived from this software
23da2e3ebdSchin  *    without specific prior written permission.
24da2e3ebdSchin  *
25da2e3ebdSchin  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26da2e3ebdSchin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27da2e3ebdSchin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28da2e3ebdSchin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29da2e3ebdSchin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30da2e3ebdSchin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31da2e3ebdSchin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32da2e3ebdSchin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33da2e3ebdSchin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34da2e3ebdSchin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35da2e3ebdSchin  * SUCH DAMAGE.
36da2e3ebdSchin  */
37da2e3ebdSchin 
38da2e3ebdSchin #ifndef lint
39da2e3ebdSchin static char sccsid[] = "@(#)log.c	8.2 (Berkeley) 11/30/93";
40da2e3ebdSchin #endif /* not lint */
41da2e3ebdSchin 
42da2e3ebdSchin #include <math.h>
43da2e3ebdSchin #include <errno.h>
44da2e3ebdSchin 
45da2e3ebdSchin #include "mathimpl.h"
46da2e3ebdSchin 
47da2e3ebdSchin /* Table-driven natural logarithm.
48da2e3ebdSchin  *
49da2e3ebdSchin  * This code was derived, with minor modifications, from:
50da2e3ebdSchin  *	Peter Tang, "Table-Driven Implementation of the
51da2e3ebdSchin  *	Logarithm in IEEE Floating-Point arithmetic." ACM Trans.
52da2e3ebdSchin  *	Math Software, vol 16. no 4, pp 378-400, Dec 1990).
53da2e3ebdSchin  *
54da2e3ebdSchin  * Calculates log(2^m*F*(1+f/F)), |f/j| <= 1/256,
55da2e3ebdSchin  * where F = j/128 for j an integer in [0, 128].
56da2e3ebdSchin  *
57da2e3ebdSchin  * log(2^m) = log2_hi*m + log2_tail*m
58da2e3ebdSchin  * since m is an integer, the dominant term is exact.
59da2e3ebdSchin  * m has at most 10 digits (for subnormal numbers),
60da2e3ebdSchin  * and log2_hi has 11 trailing zero bits.
61da2e3ebdSchin  *
62da2e3ebdSchin  * log(F) = logF_hi[j] + logF_lo[j] is in tabular form in log_table.h
63da2e3ebdSchin  * logF_hi[] + 512 is exact.
64da2e3ebdSchin  *
65da2e3ebdSchin  * log(1+f/F) = 2*f/(2*F + f) + 1/12 * (2*f/(2*F + f))**3 + ...
66da2e3ebdSchin  * the leading term is calculated to extra precision in two
67da2e3ebdSchin  * parts, the larger of which adds exactly to the dominant
68da2e3ebdSchin  * m and F terms.
69da2e3ebdSchin  * There are two cases:
70da2e3ebdSchin  *	1. when m, j are non-zero (m | j), use absolute
71da2e3ebdSchin  *	   precision for the leading term.
72da2e3ebdSchin  *	2. when m = j = 0, |1-x| < 1/256, and log(x) ~= (x-1).
73da2e3ebdSchin  *	   In this case, use a relative precision of 24 bits.
74da2e3ebdSchin  * (This is done differently in the original paper)
75da2e3ebdSchin  *
76da2e3ebdSchin  * Special cases:
77da2e3ebdSchin  *	0	return signalling -Inf
78da2e3ebdSchin  *	neg	return signalling NaN
79da2e3ebdSchin  *	+Inf	return +Inf
80da2e3ebdSchin */
81da2e3ebdSchin 
82da2e3ebdSchin #if defined(vax) || defined(tahoe)
83da2e3ebdSchin #define _IEEE		0
84da2e3ebdSchin #define TRUNC(x)	x = (double) (float) (x)
85da2e3ebdSchin #else
86da2e3ebdSchin #define _IEEE		1
87da2e3ebdSchin #define endian		(((*(int *) &one)) ? 1 : 0)
88da2e3ebdSchin #define TRUNC(x)	*(((int *) &x) + endian) &= 0xf8000000
89da2e3ebdSchin #define infnan(x)	0.0
90da2e3ebdSchin #endif
91da2e3ebdSchin 
92da2e3ebdSchin #define N 128
93da2e3ebdSchin 
94da2e3ebdSchin /* Table of log(Fj) = logF_head[j] + logF_tail[j], for Fj = 1+j/128.
95da2e3ebdSchin  * Used for generation of extend precision logarithms.
96da2e3ebdSchin  * The constant 35184372088832 is 2^45, so the divide is exact.
97da2e3ebdSchin  * It ensures correct reading of logF_head, even for inaccurate
98da2e3ebdSchin  * decimal-to-binary conversion routines.  (Everybody gets the
99da2e3ebdSchin  * right answer for integers less than 2^53.)
100da2e3ebdSchin  * Values for log(F) were generated using error < 10^-57 absolute
101da2e3ebdSchin  * with the bc -l package.
102da2e3ebdSchin */
103da2e3ebdSchin static double	A1 = 	  .08333333333333178827;
104da2e3ebdSchin static double	A2 = 	  .01250000000377174923;
105da2e3ebdSchin static double	A3 =	 .002232139987919447809;
106da2e3ebdSchin static double	A4 =	.0004348877777076145742;
107da2e3ebdSchin 
108da2e3ebdSchin static double logF_head[N+1] = {
109da2e3ebdSchin 	0.,
110da2e3ebdSchin 	.007782140442060381246,
111da2e3ebdSchin 	.015504186535963526694,
112da2e3ebdSchin 	.023167059281547608406,
113da2e3ebdSchin 	.030771658666765233647,
114da2e3ebdSchin 	.038318864302141264488,
115da2e3ebdSchin 	.045809536031242714670,
116da2e3ebdSchin 	.053244514518837604555,
117da2e3ebdSchin 	.060624621816486978786,
118da2e3ebdSchin 	.067950661908525944454,
119da2e3ebdSchin 	.075223421237524235039,
120da2e3ebdSchin 	.082443669210988446138,
121da2e3ebdSchin 	.089612158689760690322,
122da2e3ebdSchin 	.096729626458454731618,
123da2e3ebdSchin 	.103796793681567578460,
124da2e3ebdSchin 	.110814366340264314203,
125da2e3ebdSchin 	.117783035656430001836,
126da2e3ebdSchin 	.124703478501032805070,
127da2e3ebdSchin 	.131576357788617315236,
128da2e3ebdSchin 	.138402322859292326029,
129da2e3ebdSchin 	.145182009844575077295,
130da2e3ebdSchin 	.151916042025732167530,
131da2e3ebdSchin 	.158605030176659056451,
132da2e3ebdSchin 	.165249572895390883786,
133da2e3ebdSchin 	.171850256926518341060,
134da2e3ebdSchin 	.178407657472689606947,
135da2e3ebdSchin 	.184922338493834104156,
136da2e3ebdSchin 	.191394852999565046047,
137da2e3ebdSchin 	.197825743329758552135,
138da2e3ebdSchin 	.204215541428766300668,
139da2e3ebdSchin 	.210564769107350002741,
140da2e3ebdSchin 	.216873938300523150246,
141da2e3ebdSchin 	.223143551314024080056,
142da2e3ebdSchin 	.229374101064877322642,
143da2e3ebdSchin 	.235566071312860003672,
144da2e3ebdSchin 	.241719936886966024758,
145da2e3ebdSchin 	.247836163904594286577,
146da2e3ebdSchin 	.253915209980732470285,
147da2e3ebdSchin 	.259957524436686071567,
148da2e3ebdSchin 	.265963548496984003577,
149da2e3ebdSchin 	.271933715484010463114,
150da2e3ebdSchin 	.277868451003087102435,
151da2e3ebdSchin 	.283768173130738432519,
152da2e3ebdSchin 	.289633292582948342896,
153da2e3ebdSchin 	.295464212893421063199,
154da2e3ebdSchin 	.301261330578199704177,
155da2e3ebdSchin 	.307025035294827830512,
156da2e3ebdSchin 	.312755710004239517729,
157da2e3ebdSchin 	.318453731118097493890,
158da2e3ebdSchin 	.324119468654316733591,
159da2e3ebdSchin 	.329753286372579168528,
160da2e3ebdSchin 	.335355541920762334484,
161da2e3ebdSchin 	.340926586970454081892,
162da2e3ebdSchin 	.346466767346100823488,
163da2e3ebdSchin 	.351976423156884266063,
164da2e3ebdSchin 	.357455888922231679316,
165da2e3ebdSchin 	.362905493689140712376,
166da2e3ebdSchin 	.368325561158599157352,
167da2e3ebdSchin 	.373716409793814818840,
168da2e3ebdSchin 	.379078352934811846353,
169da2e3ebdSchin 	.384411698910298582632,
170da2e3ebdSchin 	.389716751140440464951,
171da2e3ebdSchin 	.394993808240542421117,
172da2e3ebdSchin 	.400243164127459749579,
173da2e3ebdSchin 	.405465108107819105498,
174da2e3ebdSchin 	.410659924985338875558,
175da2e3ebdSchin 	.415827895143593195825,
176da2e3ebdSchin 	.420969294644237379543,
177da2e3ebdSchin 	.426084395310681429691,
178da2e3ebdSchin 	.431173464818130014464,
179da2e3ebdSchin 	.436236766774527495726,
180da2e3ebdSchin 	.441274560805140936281,
181da2e3ebdSchin 	.446287102628048160113,
182da2e3ebdSchin 	.451274644139630254358,
183da2e3ebdSchin 	.456237433481874177232,
184da2e3ebdSchin 	.461175715122408291790,
185da2e3ebdSchin 	.466089729924533457960,
186da2e3ebdSchin 	.470979715219073113985,
187da2e3ebdSchin 	.475845904869856894947,
188da2e3ebdSchin 	.480688529345570714212,
189da2e3ebdSchin 	.485507815781602403149,
190da2e3ebdSchin 	.490303988045525329653,
191da2e3ebdSchin 	.495077266798034543171,
192da2e3ebdSchin 	.499827869556611403822,
193da2e3ebdSchin 	.504556010751912253908,
194da2e3ebdSchin 	.509261901790523552335,
195da2e3ebdSchin 	.513945751101346104405,
196da2e3ebdSchin 	.518607764208354637958,
197da2e3ebdSchin 	.523248143765158602036,
198da2e3ebdSchin 	.527867089620485785417,
199da2e3ebdSchin 	.532464798869114019908,
200da2e3ebdSchin 	.537041465897345915436,
201da2e3ebdSchin 	.541597282432121573947,
202da2e3ebdSchin 	.546132437597407260909,
203da2e3ebdSchin 	.550647117952394182793,
204da2e3ebdSchin 	.555141507540611200965,
205da2e3ebdSchin 	.559615787935399566777,
206da2e3ebdSchin 	.564070138285387656651,
207da2e3ebdSchin 	.568504735352689749561,
208da2e3ebdSchin 	.572919753562018740922,
209da2e3ebdSchin 	.577315365035246941260,
210da2e3ebdSchin 	.581691739635061821900,
211da2e3ebdSchin 	.586049045003164792433,
212da2e3ebdSchin 	.590387446602107957005,
213da2e3ebdSchin 	.594707107746216934174,
214da2e3ebdSchin 	.599008189645246602594,
215da2e3ebdSchin 	.603290851438941899687,
216da2e3ebdSchin 	.607555250224322662688,
217da2e3ebdSchin 	.611801541106615331955,
218da2e3ebdSchin 	.616029877215623855590,
219da2e3ebdSchin 	.620240409751204424537,
220da2e3ebdSchin 	.624433288012369303032,
221da2e3ebdSchin 	.628608659422752680256,
222da2e3ebdSchin 	.632766669570628437213,
223da2e3ebdSchin 	.636907462236194987781,
224da2e3ebdSchin 	.641031179420679109171,
225da2e3ebdSchin 	.645137961373620782978,
226da2e3ebdSchin 	.649227946625615004450,
227da2e3ebdSchin 	.653301272011958644725,
228da2e3ebdSchin 	.657358072709030238911,
229da2e3ebdSchin 	.661398482245203922502,
230da2e3ebdSchin 	.665422632544505177065,
231da2e3ebdSchin 	.669430653942981734871,
232da2e3ebdSchin 	.673422675212350441142,
233da2e3ebdSchin 	.677398823590920073911,
234da2e3ebdSchin 	.681359224807238206267,
235da2e3ebdSchin 	.685304003098281100392,
236da2e3ebdSchin 	.689233281238557538017,
237da2e3ebdSchin 	.693147180560117703862
238da2e3ebdSchin };
239da2e3ebdSchin 
240da2e3ebdSchin static double logF_tail[N+1] = {
241da2e3ebdSchin 	0.,
242da2e3ebdSchin 	-.00000000000000543229938420049,
243da2e3ebdSchin 	 .00000000000000172745674997061,
244da2e3ebdSchin 	-.00000000000001323017818229233,
245da2e3ebdSchin 	-.00000000000001154527628289872,
246da2e3ebdSchin 	-.00000000000000466529469958300,
247da2e3ebdSchin 	 .00000000000005148849572685810,
248da2e3ebdSchin 	-.00000000000002532168943117445,
249da2e3ebdSchin 	-.00000000000005213620639136504,
250da2e3ebdSchin 	-.00000000000001819506003016881,
251da2e3ebdSchin 	 .00000000000006329065958724544,
252da2e3ebdSchin 	 .00000000000008614512936087814,
253da2e3ebdSchin 	-.00000000000007355770219435028,
254da2e3ebdSchin 	 .00000000000009638067658552277,
255da2e3ebdSchin 	 .00000000000007598636597194141,
256da2e3ebdSchin 	 .00000000000002579999128306990,
257da2e3ebdSchin 	-.00000000000004654729747598444,
258da2e3ebdSchin 	-.00000000000007556920687451336,
259da2e3ebdSchin 	 .00000000000010195735223708472,
260da2e3ebdSchin 	-.00000000000017319034406422306,
261da2e3ebdSchin 	-.00000000000007718001336828098,
262da2e3ebdSchin 	 .00000000000010980754099855238,
263da2e3ebdSchin 	-.00000000000002047235780046195,
264da2e3ebdSchin 	-.00000000000008372091099235912,
265da2e3ebdSchin 	 .00000000000014088127937111135,
266da2e3ebdSchin 	 .00000000000012869017157588257,
267da2e3ebdSchin 	 .00000000000017788850778198106,
268da2e3ebdSchin 	 .00000000000006440856150696891,
269da2e3ebdSchin 	 .00000000000016132822667240822,
270da2e3ebdSchin 	-.00000000000007540916511956188,
271da2e3ebdSchin 	-.00000000000000036507188831790,
272da2e3ebdSchin 	 .00000000000009120937249914984,
273da2e3ebdSchin 	 .00000000000018567570959796010,
274da2e3ebdSchin 	-.00000000000003149265065191483,
275da2e3ebdSchin 	-.00000000000009309459495196889,
276da2e3ebdSchin 	 .00000000000017914338601329117,
277da2e3ebdSchin 	-.00000000000001302979717330866,
278da2e3ebdSchin 	 .00000000000023097385217586939,
279da2e3ebdSchin 	 .00000000000023999540484211737,
280da2e3ebdSchin 	 .00000000000015393776174455408,
281da2e3ebdSchin 	-.00000000000036870428315837678,
282da2e3ebdSchin 	 .00000000000036920375082080089,
283da2e3ebdSchin 	-.00000000000009383417223663699,
284da2e3ebdSchin 	 .00000000000009433398189512690,
285da2e3ebdSchin 	 .00000000000041481318704258568,
286da2e3ebdSchin 	-.00000000000003792316480209314,
287da2e3ebdSchin 	 .00000000000008403156304792424,
288da2e3ebdSchin 	-.00000000000034262934348285429,
289da2e3ebdSchin 	 .00000000000043712191957429145,
290da2e3ebdSchin 	-.00000000000010475750058776541,
291da2e3ebdSchin 	-.00000000000011118671389559323,
292da2e3ebdSchin 	 .00000000000037549577257259853,
293da2e3ebdSchin 	 .00000000000013912841212197565,
294da2e3ebdSchin 	 .00000000000010775743037572640,
295da2e3ebdSchin 	 .00000000000029391859187648000,
296da2e3ebdSchin 	-.00000000000042790509060060774,
297da2e3ebdSchin 	 .00000000000022774076114039555,
298da2e3ebdSchin 	 .00000000000010849569622967912,
299da2e3ebdSchin 	-.00000000000023073801945705758,
300da2e3ebdSchin 	 .00000000000015761203773969435,
301da2e3ebdSchin 	 .00000000000003345710269544082,
302da2e3ebdSchin 	-.00000000000041525158063436123,
303da2e3ebdSchin 	 .00000000000032655698896907146,
304da2e3ebdSchin 	-.00000000000044704265010452446,
305da2e3ebdSchin 	 .00000000000034527647952039772,
306da2e3ebdSchin 	-.00000000000007048962392109746,
307da2e3ebdSchin 	 .00000000000011776978751369214,
308da2e3ebdSchin 	-.00000000000010774341461609578,
309da2e3ebdSchin 	 .00000000000021863343293215910,
310da2e3ebdSchin 	 .00000000000024132639491333131,
311da2e3ebdSchin 	 .00000000000039057462209830700,
312da2e3ebdSchin 	-.00000000000026570679203560751,
313da2e3ebdSchin 	 .00000000000037135141919592021,
314da2e3ebdSchin 	-.00000000000017166921336082431,
315da2e3ebdSchin 	-.00000000000028658285157914353,
316da2e3ebdSchin 	-.00000000000023812542263446809,
317da2e3ebdSchin 	 .00000000000006576659768580062,
318da2e3ebdSchin 	-.00000000000028210143846181267,
319da2e3ebdSchin 	 .00000000000010701931762114254,
320da2e3ebdSchin 	 .00000000000018119346366441110,
321da2e3ebdSchin 	 .00000000000009840465278232627,
322da2e3ebdSchin 	-.00000000000033149150282752542,
323da2e3ebdSchin 	-.00000000000018302857356041668,
324da2e3ebdSchin 	-.00000000000016207400156744949,
325da2e3ebdSchin 	 .00000000000048303314949553201,
326da2e3ebdSchin 	-.00000000000071560553172382115,
327da2e3ebdSchin 	 .00000000000088821239518571855,
328da2e3ebdSchin 	-.00000000000030900580513238244,
329da2e3ebdSchin 	-.00000000000061076551972851496,
330da2e3ebdSchin 	 .00000000000035659969663347830,
331da2e3ebdSchin 	 .00000000000035782396591276383,
332da2e3ebdSchin 	-.00000000000046226087001544578,
333da2e3ebdSchin 	 .00000000000062279762917225156,
334da2e3ebdSchin 	 .00000000000072838947272065741,
335da2e3ebdSchin 	 .00000000000026809646615211673,
336da2e3ebdSchin 	-.00000000000010960825046059278,
337da2e3ebdSchin 	 .00000000000002311949383800537,
338da2e3ebdSchin 	-.00000000000058469058005299247,
339da2e3ebdSchin 	-.00000000000002103748251144494,
340da2e3ebdSchin 	-.00000000000023323182945587408,
341da2e3ebdSchin 	-.00000000000042333694288141916,
342da2e3ebdSchin 	-.00000000000043933937969737844,
343da2e3ebdSchin 	 .00000000000041341647073835565,
344da2e3ebdSchin 	 .00000000000006841763641591466,
345da2e3ebdSchin 	 .00000000000047585534004430641,
346da2e3ebdSchin 	 .00000000000083679678674757695,
347da2e3ebdSchin 	-.00000000000085763734646658640,
348da2e3ebdSchin 	 .00000000000021913281229340092,
349da2e3ebdSchin 	-.00000000000062242842536431148,
350da2e3ebdSchin 	-.00000000000010983594325438430,
351da2e3ebdSchin 	 .00000000000065310431377633651,
352da2e3ebdSchin 	-.00000000000047580199021710769,
353da2e3ebdSchin 	-.00000000000037854251265457040,
354da2e3ebdSchin 	 .00000000000040939233218678664,
355da2e3ebdSchin 	 .00000000000087424383914858291,
356da2e3ebdSchin 	 .00000000000025218188456842882,
357da2e3ebdSchin 	-.00000000000003608131360422557,
358da2e3ebdSchin 	-.00000000000050518555924280902,
359da2e3ebdSchin 	 .00000000000078699403323355317,
360da2e3ebdSchin 	-.00000000000067020876961949060,
361da2e3ebdSchin 	 .00000000000016108575753932458,
362da2e3ebdSchin 	 .00000000000058527188436251509,
363da2e3ebdSchin 	-.00000000000035246757297904791,
364da2e3ebdSchin 	-.00000000000018372084495629058,
365da2e3ebdSchin 	 .00000000000088606689813494916,
366da2e3ebdSchin 	 .00000000000066486268071468700,
367da2e3ebdSchin 	 .00000000000063831615170646519,
368da2e3ebdSchin 	 .00000000000025144230728376072,
369da2e3ebdSchin 	-.00000000000017239444525614834
370da2e3ebdSchin };
371da2e3ebdSchin 
372da2e3ebdSchin #if !_lib_log
373da2e3ebdSchin 
374da2e3ebdSchin extern double
375da2e3ebdSchin #ifdef _ANSI_SOURCE
log(double x)376da2e3ebdSchin log(double x)
377da2e3ebdSchin #else
378da2e3ebdSchin log(x) double x;
379da2e3ebdSchin #endif
380da2e3ebdSchin {
381da2e3ebdSchin 	int m, j;
382da2e3ebdSchin 	double F, f, g, q, u, u2, v, zero = 0.0, one = 1.0;
383da2e3ebdSchin 	volatile double u1;
384da2e3ebdSchin 
385da2e3ebdSchin 	/* Catch special cases */
386da2e3ebdSchin 	if (x <= 0)
387da2e3ebdSchin 		if (_IEEE && x == zero)	/* log(0) = -Inf */
388da2e3ebdSchin 			return (-one/zero);
389da2e3ebdSchin 		else if (_IEEE)		/* log(neg) = NaN */
390da2e3ebdSchin 			return (zero/zero);
391da2e3ebdSchin 		else if (x == zero)	/* NOT REACHED IF _IEEE */
392da2e3ebdSchin 			return (infnan(-ERANGE));
393da2e3ebdSchin 		else
394da2e3ebdSchin 			return (infnan(EDOM));
395da2e3ebdSchin 	else if (!finite(x))
396da2e3ebdSchin 		if (_IEEE)		/* x = NaN, Inf */
397da2e3ebdSchin 			return (x+x);
398da2e3ebdSchin 		else
399da2e3ebdSchin 			return (infnan(ERANGE));
400da2e3ebdSchin 
401da2e3ebdSchin 	/* Argument reduction: 1 <= g < 2; x/2^m = g;	*/
402da2e3ebdSchin 	/* y = F*(1 + f/F) for |f| <= 2^-8		*/
403da2e3ebdSchin 
404da2e3ebdSchin 	m = logb(x);
405da2e3ebdSchin 	g = ldexp(x, -m);
406da2e3ebdSchin 	if (_IEEE && m == -1022) {
407da2e3ebdSchin 		j = logb(g), m += j;
408da2e3ebdSchin 		g = ldexp(g, -j);
409da2e3ebdSchin 	}
410da2e3ebdSchin 	j = N*(g-1) + .5;
411da2e3ebdSchin 	F = (1.0/N) * j + 1;	/* F*128 is an integer in [128, 512] */
412da2e3ebdSchin 	f = g - F;
413da2e3ebdSchin 
414da2e3ebdSchin 	/* Approximate expansion for log(1+f/F) ~= u + q */
415da2e3ebdSchin 	g = 1/(2*F+f);
416da2e3ebdSchin 	u = 2*f*g;
417da2e3ebdSchin 	v = u*u;
418da2e3ebdSchin 	q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
419da2e3ebdSchin 
420da2e3ebdSchin     /* case 1: u1 = u rounded to 2^-43 absolute.  Since u < 2^-8,
421da2e3ebdSchin      * 	       u1 has at most 35 bits, and F*u1 is exact, as F has < 8 bits.
422da2e3ebdSchin      *         It also adds exactly to |m*log2_hi + log_F_head[j] | < 750
423da2e3ebdSchin     */
424da2e3ebdSchin 	if (m | j)
425da2e3ebdSchin 		u1 = u + 513, u1 -= 513;
426da2e3ebdSchin 
427da2e3ebdSchin     /* case 2:	|1-x| < 1/256. The m- and j- dependent terms are zero;
428da2e3ebdSchin      * 		u1 = u to 24 bits.
429da2e3ebdSchin     */
430da2e3ebdSchin 	else
431da2e3ebdSchin 		u1 = u, TRUNC(u1);
432da2e3ebdSchin 	u2 = (2.0*(f - F*u1) - u1*f) * g;
433da2e3ebdSchin 			/* u1 + u2 = 2f/(2F+f) to extra precision.	*/
434da2e3ebdSchin 
435da2e3ebdSchin 	/* log(x) = log(2^m*F*(1+f/F)) =				*/
436da2e3ebdSchin 	/* (m*log2_hi+logF_head[j]+u1) + (m*log2_lo+logF_tail[j]+q);	*/
437da2e3ebdSchin 	/* (exact) + (tiny)						*/
438da2e3ebdSchin 
439da2e3ebdSchin 	u1 += m*logF_head[N] + logF_head[j];		/* exact */
440da2e3ebdSchin 	u2 = (u2 + logF_tail[j]) + q;			/* tiny */
441da2e3ebdSchin 	u2 += logF_tail[N]*m;
442da2e3ebdSchin 	return (u1 + u2);
443da2e3ebdSchin }
444da2e3ebdSchin 
445da2e3ebdSchin #endif
446da2e3ebdSchin 
447da2e3ebdSchin /*
448da2e3ebdSchin  * Extra precision variant, returning struct {double a, b;};
449da2e3ebdSchin  * log(x) = a+b to 63 bits, with a is rounded to 26 bits.
450da2e3ebdSchin  */
451da2e3ebdSchin struct Double
452da2e3ebdSchin #ifdef _ANSI_SOURCE
__log__D(double x)453da2e3ebdSchin __log__D(double x)
454da2e3ebdSchin #else
455da2e3ebdSchin __log__D(x) double x;
456da2e3ebdSchin #endif
457da2e3ebdSchin {
458da2e3ebdSchin 	int m, j;
459da2e3ebdSchin 	double F, f, g, q, u, v, u2, one = 1.0;
460da2e3ebdSchin 	volatile double u1;
461da2e3ebdSchin 	struct Double r;
462da2e3ebdSchin 
463da2e3ebdSchin 	/* Argument reduction: 1 <= g < 2; x/2^m = g;	*/
464da2e3ebdSchin 	/* y = F*(1 + f/F) for |f| <= 2^-8		*/
465da2e3ebdSchin 
466da2e3ebdSchin 	m = (int)logb(x);
467da2e3ebdSchin 	g = ldexp(x, -m);
468da2e3ebdSchin 	if (_IEEE && m == -1022) {
469da2e3ebdSchin 		j = (int)logb(g), m += j;
470da2e3ebdSchin 		g = ldexp(g, -j);
471da2e3ebdSchin 	}
472da2e3ebdSchin 	j = (int)(N*(g-1) + .5);
473da2e3ebdSchin 	F = (1.0/N) * j + 1;
474da2e3ebdSchin 	f = g - F;
475da2e3ebdSchin 
476da2e3ebdSchin 	g = 1/(2*F+f);
477da2e3ebdSchin 	u = 2*f*g;
478da2e3ebdSchin 	v = u*u;
479da2e3ebdSchin 	q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
480da2e3ebdSchin 	if (m | j)
481da2e3ebdSchin 		u1 = u + 513, u1 -= 513;
482da2e3ebdSchin 	else
483da2e3ebdSchin 		u1 = u, TRUNC(u1);
484da2e3ebdSchin 	u2 = (2.0*(f - F*u1) - u1*f) * g;
485da2e3ebdSchin 
486da2e3ebdSchin 	u1 += m*logF_head[N] + logF_head[j];
487da2e3ebdSchin 
488da2e3ebdSchin 	u2 +=  logF_tail[j]; u2 += q;
489da2e3ebdSchin 	u2 += logF_tail[N]*m;
490da2e3ebdSchin 	r.a = u1 + u2;			/* Only difference is here */
491da2e3ebdSchin 	TRUNC(r.a);
492da2e3ebdSchin 	r.b = (u1 - r.a) + u2;
493da2e3ebdSchin 	return (r);
494da2e3ebdSchin }
495da2e3ebdSchin 
496da2e3ebdSchin #endif
497