1112158Sdas/****************************************************************
2112158Sdas
3112158SdasThe author of this software is David M. Gay.
4112158Sdas
5112158SdasCopyright (C) 1998-2001 by Lucent Technologies
6112158SdasAll Rights Reserved
7112158Sdas
8112158SdasPermission to use, copy, modify, and distribute this software and
9112158Sdasits documentation for any purpose and without fee is hereby
10112158Sdasgranted, provided that the above copyright notice appear in all
11112158Sdascopies and that both that the copyright notice and this
12112158Sdaspermission notice and warranty disclaimer appear in supporting
13112158Sdasdocumentation, and that the name of Lucent or any of its entities
14112158Sdasnot be used in advertising or publicity pertaining to
15112158Sdasdistribution of the software without specific, written prior
16112158Sdaspermission.
17112158Sdas
18112158SdasLUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19112158SdasINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20112158SdasIN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21112158SdasSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22112158SdasWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23112158SdasIN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24112158SdasARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25112158SdasTHIS SOFTWARE.
26112158Sdas
27112158Sdas****************************************************************/
28112158Sdas
29165743Sdas/* Please send bug reports to David M. Gay (dmg at acm dot org,
30165743Sdas * with " at " changed at "@" and " dot " changed to ".").	*/
31112158Sdas
32174679Sdas/* $FreeBSD$ */
33174679Sdas
34112158Sdas#include "gdtoaimp.h"
35165743Sdas#ifndef NO_FENV_H
36165743Sdas#include <fenv.h>
37165743Sdas#endif
38112158Sdas
39112158Sdas#ifdef USE_LOCALE
40112158Sdas#include "locale.h"
41112158Sdas#endif
42112158Sdas
43112158Sdas#ifdef IEEE_Arith
44112158Sdas#ifndef NO_IEEE_Scale
45112158Sdas#define Avoid_Underflow
46112158Sdas#undef tinytens
47182709Sdas/* The factor of 2^106 in tinytens[4] helps us avoid setting the underflow */
48112158Sdas/* flag unnecessarily.  It leads to a song and dance at the end of strtod. */
49112158Sdasstatic CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
50182709Sdas		9007199254740992.*9007199254740992.e-256
51112158Sdas		};
52112158Sdas#endif
53112158Sdas#endif
54112158Sdas
55112158Sdas#ifdef Honor_FLT_ROUNDS
56112158Sdas#undef Check_FLT_ROUNDS
57112158Sdas#define Check_FLT_ROUNDS
58112158Sdas#else
59112158Sdas#define Rounding Flt_Rounds
60112158Sdas#endif
61112158Sdas
62219557Sdas#ifdef Avoid_Underflow /*{*/
63219557Sdas static double
64219557Sdassulp
65219557Sdas#ifdef KR_headers
66219557Sdas	(x, scale) U *x; int scale;
67219557Sdas#else
68219557Sdas	(U *x, int scale)
69219557Sdas#endif
70219557Sdas{
71219557Sdas	U u;
72219557Sdas	double rv;
73219557Sdas	int i;
74219557Sdas
75219557Sdas	rv = ulp(x);
76219557Sdas	if (!scale || (i = 2*P + 1 - ((word0(x) & Exp_mask) >> Exp_shift)) <= 0)
77219557Sdas		return rv; /* Is there an example where i <= 0 ? */
78219557Sdas	word0(&u) = Exp_1 + (i << Exp_shift);
79219557Sdas	word1(&u) = 0;
80219557Sdas	return rv * u.d;
81219557Sdas	}
82219557Sdas#endif /*}*/
83219557Sdas
84112158Sdas double
85235785Stheravenstrtod_l
86112158Sdas#ifdef KR_headers
87235785Stheraven	(s00, se, loc) CONST char *s00; char **se; locale_t loc
88112158Sdas#else
89235785Stheraven	(CONST char *s00, char **se, locale_t loc)
90112158Sdas#endif
91112158Sdas{
92112158Sdas#ifdef Avoid_Underflow
93112158Sdas	int scale;
94112158Sdas#endif
95165743Sdas	int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign,
96112158Sdas		 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
97112158Sdas	CONST char *s, *s0, *s1;
98219557Sdas	double aadj;
99112158Sdas	Long L;
100219557Sdas	U adj, aadj1, rv, rv0;
101112158Sdas	ULong y, z;
102112158Sdas	Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
103219557Sdas#ifdef Avoid_Underflow
104219557Sdas	ULong Lsb, Lsb1;
105219557Sdas#endif
106112158Sdas#ifdef SET_INEXACT
107112158Sdas	int inexact, oldinexact;
108112158Sdas#endif
109187808Sdas#ifdef USE_LOCALE /*{{*/
110187808Sdas#ifdef NO_LOCALE_CACHE
111235785Stheraven	char *decimalpoint = localeconv_l(loc)->decimal_point;
112187808Sdas	int dplen = strlen(decimalpoint);
113187808Sdas#else
114187808Sdas	char *decimalpoint;
115187808Sdas	static char *decimalpoint_cache;
116187808Sdas	static int dplen;
117187808Sdas	if (!(s0 = decimalpoint_cache)) {
118235785Stheraven		s0 = localeconv_l(loc)->decimal_point;
119219557Sdas		if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
120187808Sdas			strcpy(decimalpoint_cache, s0);
121187808Sdas			s0 = decimalpoint_cache;
122187808Sdas			}
123187808Sdas		dplen = strlen(s0);
124187808Sdas		}
125187808Sdas	decimalpoint = (char*)s0;
126187808Sdas#endif /*NO_LOCALE_CACHE*/
127187808Sdas#else  /*USE_LOCALE}{*/
128187808Sdas#define dplen 1
129187808Sdas#endif /*USE_LOCALE}}*/
130187808Sdas
131182709Sdas#ifdef Honor_FLT_ROUNDS /*{*/
132182709Sdas	int Rounding;
133182709Sdas#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
134182709Sdas	Rounding = Flt_Rounds;
135182709Sdas#else /*}{*/
136182709Sdas	Rounding = 1;
137182709Sdas	switch(fegetround()) {
138182709Sdas	  case FE_TOWARDZERO:	Rounding = 0; break;
139182709Sdas	  case FE_UPWARD:	Rounding = 2; break;
140182709Sdas	  case FE_DOWNWARD:	Rounding = 3;
141182709Sdas	  }
142182709Sdas#endif /*}}*/
143182709Sdas#endif /*}*/
144112158Sdas
145165743Sdas	sign = nz0 = nz = decpt = 0;
146219557Sdas	dval(&rv) = 0.;
147112158Sdas	for(s = s00;;s++) switch(*s) {
148112158Sdas		case '-':
149112158Sdas			sign = 1;
150112158Sdas			/* no break */
151112158Sdas		case '+':
152112158Sdas			if (*++s)
153112158Sdas				goto break2;
154112158Sdas			/* no break */
155112158Sdas		case 0:
156112158Sdas			goto ret0;
157112158Sdas		case '\t':
158112158Sdas		case '\n':
159112158Sdas		case '\v':
160112158Sdas		case '\f':
161112158Sdas		case '\r':
162112158Sdas		case ' ':
163112158Sdas			continue;
164112158Sdas		default:
165112158Sdas			goto break2;
166112158Sdas		}
167112158Sdas break2:
168112158Sdas	if (*s == '0') {
169187808Sdas#ifndef NO_HEX_FP /*{*/
170112158Sdas		{
171112158Sdas		static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
172112158Sdas		Long exp;
173112158Sdas		ULong bits[2];
174112158Sdas		switch(s[1]) {
175112158Sdas		  case 'x':
176112158Sdas		  case 'X':
177165743Sdas			{
178219557Sdas#ifdef Honor_FLT_ROUNDS
179165743Sdas			FPI fpi1 = fpi;
180182709Sdas			fpi1.rounding = Rounding;
181219557Sdas#else
182165743Sdas#define fpi1 fpi
183219557Sdas#endif
184165743Sdas			switch((i = gethex(&s, &fpi1, &exp, &bb, sign)) & STRTOG_Retmask) {
185112158Sdas			  case STRTOG_NoNumber:
186112158Sdas				s = s00;
187112158Sdas				sign = 0;
188112158Sdas			  case STRTOG_Zero:
189112158Sdas				break;
190112158Sdas			  default:
191124703Sdas				if (bb) {
192124703Sdas					copybits(bits, fpi.nbits, bb);
193124703Sdas					Bfree(bb);
194124703Sdas					}
195112158Sdas				ULtod(((U*)&rv)->L, bits, exp, i);
196165743Sdas			  }}
197112158Sdas			goto ret;
198112158Sdas		  }
199112158Sdas		}
200187808Sdas#endif /*}*/
201112158Sdas		nz0 = 1;
202112158Sdas		while(*++s == '0') ;
203112158Sdas		if (!*s)
204112158Sdas			goto ret;
205112158Sdas		}
206112158Sdas	s0 = s;
207112158Sdas	y = z = 0;
208112158Sdas	for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
209112158Sdas		if (nd < 9)
210112158Sdas			y = 10*y + c - '0';
211112158Sdas		else if (nd < 16)
212112158Sdas			z = 10*z + c - '0';
213112158Sdas	nd0 = nd;
214112158Sdas#ifdef USE_LOCALE
215187808Sdas	if (c == *decimalpoint) {
216187808Sdas		for(i = 1; decimalpoint[i]; ++i)
217187808Sdas			if (s[i] != decimalpoint[i])
218187808Sdas				goto dig_done;
219187808Sdas		s += i;
220187808Sdas		c = *s;
221112415Sdas#else
222187808Sdas	if (c == '.') {
223187808Sdas		c = *++s;
224112158Sdas#endif
225165743Sdas		decpt = 1;
226112158Sdas		if (!nd) {
227112158Sdas			for(; c == '0'; c = *++s)
228112158Sdas				nz++;
229112158Sdas			if (c > '0' && c <= '9') {
230112158Sdas				s0 = s;
231112158Sdas				nf += nz;
232112158Sdas				nz = 0;
233112158Sdas				goto have_dig;
234112158Sdas				}
235112158Sdas			goto dig_done;
236112158Sdas			}
237112158Sdas		for(; c >= '0' && c <= '9'; c = *++s) {
238112158Sdas have_dig:
239112158Sdas			nz++;
240112158Sdas			if (c -= '0') {
241112158Sdas				nf += nz;
242112158Sdas				for(i = 1; i < nz; i++)
243112158Sdas					if (nd++ < 9)
244112158Sdas						y *= 10;
245112158Sdas					else if (nd <= DBL_DIG + 1)
246112158Sdas						z *= 10;
247112158Sdas				if (nd++ < 9)
248112158Sdas					y = 10*y + c;
249112158Sdas				else if (nd <= DBL_DIG + 1)
250112158Sdas					z = 10*z + c;
251112158Sdas				nz = 0;
252112158Sdas				}
253112158Sdas			}
254187808Sdas		}/*}*/
255112158Sdas dig_done:
256112158Sdas	e = 0;
257112158Sdas	if (c == 'e' || c == 'E') {
258112158Sdas		if (!nd && !nz && !nz0) {
259112158Sdas			goto ret0;
260112158Sdas			}
261112158Sdas		s00 = s;
262112158Sdas		esign = 0;
263112158Sdas		switch(c = *++s) {
264112158Sdas			case '-':
265112158Sdas				esign = 1;
266112158Sdas			case '+':
267112158Sdas				c = *++s;
268112158Sdas			}
269112158Sdas		if (c >= '0' && c <= '9') {
270112158Sdas			while(c == '0')
271112158Sdas				c = *++s;
272112158Sdas			if (c > '0' && c <= '9') {
273112158Sdas				L = c - '0';
274112158Sdas				s1 = s;
275112158Sdas				while((c = *++s) >= '0' && c <= '9')
276112158Sdas					L = 10*L + c - '0';
277112158Sdas				if (s - s1 > 8 || L > 19999)
278112158Sdas					/* Avoid confusion from exponents
279112158Sdas					 * so large that e might overflow.
280112158Sdas					 */
281112158Sdas					e = 19999; /* safe for 16 bit ints */
282112158Sdas				else
283112158Sdas					e = (int)L;
284112158Sdas				if (esign)
285112158Sdas					e = -e;
286112158Sdas				}
287112158Sdas			else
288112158Sdas				e = 0;
289112158Sdas			}
290112158Sdas		else
291112158Sdas			s = s00;
292112158Sdas		}
293112158Sdas	if (!nd) {
294112158Sdas		if (!nz && !nz0) {
295112158Sdas#ifdef INFNAN_CHECK
296112158Sdas			/* Check for Nan and Infinity */
297112158Sdas			ULong bits[2];
298112158Sdas			static FPI fpinan =	/* only 52 explicit bits */
299112158Sdas				{ 52, 1-1023-53+1, 2046-1023-53+1, 1, SI };
300165743Sdas			if (!decpt)
301165743Sdas			 switch(c) {
302112158Sdas			  case 'i':
303112158Sdas			  case 'I':
304112158Sdas				if (match(&s,"nf")) {
305112158Sdas					--s;
306112158Sdas					if (!match(&s,"inity"))
307112158Sdas						++s;
308219557Sdas					word0(&rv) = 0x7ff00000;
309219557Sdas					word1(&rv) = 0;
310112158Sdas					goto ret;
311112158Sdas					}
312112158Sdas				break;
313112158Sdas			  case 'n':
314112158Sdas			  case 'N':
315112158Sdas				if (match(&s, "an")) {
316112158Sdas#ifndef No_Hex_NaN
317112158Sdas					if (*s == '(' /*)*/
318112158Sdas					 && hexnan(&s, &fpinan, bits)
319112158Sdas							== STRTOG_NaNbits) {
320219557Sdas						word0(&rv) = 0x7ff80000 | bits[1];
321219557Sdas						word1(&rv) = bits[0];
322112158Sdas						}
323112158Sdas					else {
324165743Sdas#endif
325219557Sdas						word0(&rv) = NAN_WORD0;
326219557Sdas						word1(&rv) = NAN_WORD1;
327165743Sdas#ifndef No_Hex_NaN
328112158Sdas						}
329112158Sdas#endif
330112158Sdas					goto ret;
331112158Sdas					}
332112158Sdas			  }
333112158Sdas#endif /* INFNAN_CHECK */
334112158Sdas ret0:
335112158Sdas			s = s00;
336112158Sdas			sign = 0;
337112158Sdas			}
338112158Sdas		goto ret;
339112158Sdas		}
340112158Sdas	e1 = e -= nf;
341112158Sdas
342112158Sdas	/* Now we have nd0 digits, starting at s0, followed by a
343112158Sdas	 * decimal point, followed by nd-nd0 digits.  The number we're
344112158Sdas	 * after is the integer represented by those digits times
345112158Sdas	 * 10**e */
346112158Sdas
347112158Sdas	if (!nd0)
348112158Sdas		nd0 = nd;
349112158Sdas	k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
350219557Sdas	dval(&rv) = y;
351112158Sdas	if (k > 9) {
352112158Sdas#ifdef SET_INEXACT
353112158Sdas		if (k > DBL_DIG)
354112158Sdas			oldinexact = get_inexact();
355112158Sdas#endif
356219557Sdas		dval(&rv) = tens[k - 9] * dval(&rv) + z;
357112158Sdas		}
358112158Sdas	bd0 = 0;
359112158Sdas	if (nd <= DBL_DIG
360112158Sdas#ifndef RND_PRODQUOT
361112158Sdas#ifndef Honor_FLT_ROUNDS
362112158Sdas		&& Flt_Rounds == 1
363112158Sdas#endif
364112158Sdas#endif
365112158Sdas			) {
366112158Sdas		if (!e)
367112158Sdas			goto ret;
368219557Sdas#ifndef ROUND_BIASED_without_Round_Up
369112158Sdas		if (e > 0) {
370112158Sdas			if (e <= Ten_pmax) {
371112158Sdas#ifdef VAX
372112158Sdas				goto vax_ovfl_check;
373112158Sdas#else
374112158Sdas#ifdef Honor_FLT_ROUNDS
375112158Sdas				/* round correctly FLT_ROUNDS = 2 or 3 */
376112158Sdas				if (sign) {
377219557Sdas					rv.d = -rv.d;
378112158Sdas					sign = 0;
379112158Sdas					}
380112158Sdas#endif
381219557Sdas				/* rv = */ rounded_product(dval(&rv), tens[e]);
382112158Sdas				goto ret;
383112158Sdas#endif
384112158Sdas				}
385112158Sdas			i = DBL_DIG - nd;
386112158Sdas			if (e <= Ten_pmax + i) {
387112158Sdas				/* A fancier test would sometimes let us do
388112158Sdas				 * this for larger i values.
389112158Sdas				 */
390112158Sdas#ifdef Honor_FLT_ROUNDS
391112158Sdas				/* round correctly FLT_ROUNDS = 2 or 3 */
392112158Sdas				if (sign) {
393219557Sdas					rv.d = -rv.d;
394112158Sdas					sign = 0;
395112158Sdas					}
396112158Sdas#endif
397112158Sdas				e -= i;
398219557Sdas				dval(&rv) *= tens[i];
399112158Sdas#ifdef VAX
400112158Sdas				/* VAX exponent range is so narrow we must
401112158Sdas				 * worry about overflow here...
402112158Sdas				 */
403112158Sdas vax_ovfl_check:
404219557Sdas				word0(&rv) -= P*Exp_msk1;
405219557Sdas				/* rv = */ rounded_product(dval(&rv), tens[e]);
406219557Sdas				if ((word0(&rv) & Exp_mask)
407112158Sdas				 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
408112158Sdas					goto ovfl;
409219557Sdas				word0(&rv) += P*Exp_msk1;
410112158Sdas#else
411219557Sdas				/* rv = */ rounded_product(dval(&rv), tens[e]);
412112158Sdas#endif
413112158Sdas				goto ret;
414112158Sdas				}
415112158Sdas			}
416112158Sdas#ifndef Inaccurate_Divide
417112158Sdas		else if (e >= -Ten_pmax) {
418112158Sdas#ifdef Honor_FLT_ROUNDS
419112158Sdas			/* round correctly FLT_ROUNDS = 2 or 3 */
420112158Sdas			if (sign) {
421219557Sdas				rv.d = -rv.d;
422112158Sdas				sign = 0;
423112158Sdas				}
424112158Sdas#endif
425219557Sdas			/* rv = */ rounded_quotient(dval(&rv), tens[-e]);
426112158Sdas			goto ret;
427112158Sdas			}
428112158Sdas#endif
429219557Sdas#endif /* ROUND_BIASED_without_Round_Up */
430112158Sdas		}
431112158Sdas	e1 += nd - k;
432112158Sdas
433112158Sdas#ifdef IEEE_Arith
434112158Sdas#ifdef SET_INEXACT
435112158Sdas	inexact = 1;
436112158Sdas	if (k <= DBL_DIG)
437112158Sdas		oldinexact = get_inexact();
438112158Sdas#endif
439112158Sdas#ifdef Avoid_Underflow
440112158Sdas	scale = 0;
441112158Sdas#endif
442112158Sdas#ifdef Honor_FLT_ROUNDS
443182709Sdas	if (Rounding >= 2) {
444112158Sdas		if (sign)
445182709Sdas			Rounding = Rounding == 2 ? 0 : 2;
446112158Sdas		else
447182709Sdas			if (Rounding != 2)
448182709Sdas				Rounding = 0;
449112158Sdas		}
450112158Sdas#endif
451112158Sdas#endif /*IEEE_Arith*/
452112158Sdas
453112158Sdas	/* Get starting approximation = rv * 10**e1 */
454112158Sdas
455112158Sdas	if (e1 > 0) {
456112158Sdas		if ( (i = e1 & 15) !=0)
457219557Sdas			dval(&rv) *= tens[i];
458112158Sdas		if (e1 &= ~15) {
459112158Sdas			if (e1 > DBL_MAX_10_EXP) {
460112158Sdas ovfl:
461112158Sdas				/* Can't trust HUGE_VAL */
462112158Sdas#ifdef IEEE_Arith
463112158Sdas#ifdef Honor_FLT_ROUNDS
464182709Sdas				switch(Rounding) {
465112158Sdas				  case 0: /* toward 0 */
466112158Sdas				  case 3: /* toward -infinity */
467219557Sdas					word0(&rv) = Big0;
468219557Sdas					word1(&rv) = Big1;
469112158Sdas					break;
470112158Sdas				  default:
471219557Sdas					word0(&rv) = Exp_mask;
472219557Sdas					word1(&rv) = 0;
473112158Sdas				  }
474112158Sdas#else /*Honor_FLT_ROUNDS*/
475219557Sdas				word0(&rv) = Exp_mask;
476219557Sdas				word1(&rv) = 0;
477112158Sdas#endif /*Honor_FLT_ROUNDS*/
478112158Sdas#ifdef SET_INEXACT
479112158Sdas				/* set overflow bit */
480219557Sdas				dval(&rv0) = 1e300;
481219557Sdas				dval(&rv0) *= dval(&rv0);
482112158Sdas#endif
483112158Sdas#else /*IEEE_Arith*/
484219557Sdas				word0(&rv) = Big0;
485219557Sdas				word1(&rv) = Big1;
486112158Sdas#endif /*IEEE_Arith*/
487219557Sdas range_err:
488219557Sdas				if (bd0) {
489219557Sdas					Bfree(bb);
490219557Sdas					Bfree(bd);
491219557Sdas					Bfree(bs);
492219557Sdas					Bfree(bd0);
493219557Sdas					Bfree(delta);
494219557Sdas					}
495219557Sdas#ifndef NO_ERRNO
496219557Sdas				errno = ERANGE;
497219557Sdas#endif
498112158Sdas				goto ret;
499112158Sdas				}
500112158Sdas			e1 >>= 4;
501112158Sdas			for(j = 0; e1 > 1; j++, e1 >>= 1)
502112158Sdas				if (e1 & 1)
503219557Sdas					dval(&rv) *= bigtens[j];
504112158Sdas		/* The last multiplication could overflow. */
505219557Sdas			word0(&rv) -= P*Exp_msk1;
506219557Sdas			dval(&rv) *= bigtens[j];
507219557Sdas			if ((z = word0(&rv) & Exp_mask)
508112158Sdas			 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
509112158Sdas				goto ovfl;
510112158Sdas			if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
511112158Sdas				/* set to largest number */
512112158Sdas				/* (Can't trust DBL_MAX) */
513219557Sdas				word0(&rv) = Big0;
514219557Sdas				word1(&rv) = Big1;
515112158Sdas				}
516112158Sdas			else
517219557Sdas				word0(&rv) += P*Exp_msk1;
518112158Sdas			}
519112158Sdas		}
520112158Sdas	else if (e1 < 0) {
521112158Sdas		e1 = -e1;
522112158Sdas		if ( (i = e1 & 15) !=0)
523219557Sdas			dval(&rv) /= tens[i];
524112158Sdas		if (e1 >>= 4) {
525112158Sdas			if (e1 >= 1 << n_bigtens)
526112158Sdas				goto undfl;
527112158Sdas#ifdef Avoid_Underflow
528112158Sdas			if (e1 & Scale_Bit)
529112158Sdas				scale = 2*P;
530112158Sdas			for(j = 0; e1 > 0; j++, e1 >>= 1)
531112158Sdas				if (e1 & 1)
532219557Sdas					dval(&rv) *= tinytens[j];
533219557Sdas			if (scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask)
534112158Sdas						>> Exp_shift)) > 0) {
535112158Sdas				/* scaled rv is denormal; zap j low bits */
536112158Sdas				if (j >= 32) {
537219557Sdas					word1(&rv) = 0;
538112158Sdas					if (j >= 53)
539219557Sdas					 word0(&rv) = (P+2)*Exp_msk1;
540112158Sdas					else
541219557Sdas					 word0(&rv) &= 0xffffffff << (j-32);
542112158Sdas					}
543112158Sdas				else
544219557Sdas					word1(&rv) &= 0xffffffff << j;
545112158Sdas				}
546112158Sdas#else
547112158Sdas			for(j = 0; e1 > 1; j++, e1 >>= 1)
548112158Sdas				if (e1 & 1)
549219557Sdas					dval(&rv) *= tinytens[j];
550112158Sdas			/* The last multiplication could underflow. */
551219557Sdas			dval(&rv0) = dval(&rv);
552219557Sdas			dval(&rv) *= tinytens[j];
553219557Sdas			if (!dval(&rv)) {
554219557Sdas				dval(&rv) = 2.*dval(&rv0);
555219557Sdas				dval(&rv) *= tinytens[j];
556112158Sdas#endif
557219557Sdas				if (!dval(&rv)) {
558112158Sdas undfl:
559219557Sdas					dval(&rv) = 0.;
560219557Sdas					goto range_err;
561112158Sdas					}
562112158Sdas#ifndef Avoid_Underflow
563219557Sdas				word0(&rv) = Tiny0;
564219557Sdas				word1(&rv) = Tiny1;
565112158Sdas				/* The refinement below will clean
566112158Sdas				 * this approximation up.
567112158Sdas				 */
568112158Sdas				}
569112158Sdas#endif
570112158Sdas			}
571112158Sdas		}
572112158Sdas
573112158Sdas	/* Now the hard part -- adjusting rv to the correct value.*/
574112158Sdas
575112158Sdas	/* Put digits into bd: true value = bd * 10^e */
576112158Sdas
577187808Sdas	bd0 = s2b(s0, nd0, nd, y, dplen);
578112158Sdas
579112158Sdas	for(;;) {
580112158Sdas		bd = Balloc(bd0->k);
581112158Sdas		Bcopy(bd, bd0);
582219557Sdas		bb = d2b(dval(&rv), &bbe, &bbbits);	/* rv = bb * 2^bbe */
583112158Sdas		bs = i2b(1);
584112158Sdas
585112158Sdas		if (e >= 0) {
586112158Sdas			bb2 = bb5 = 0;
587112158Sdas			bd2 = bd5 = e;
588112158Sdas			}
589112158Sdas		else {
590112158Sdas			bb2 = bb5 = -e;
591112158Sdas			bd2 = bd5 = 0;
592112158Sdas			}
593112158Sdas		if (bbe >= 0)
594112158Sdas			bb2 += bbe;
595112158Sdas		else
596112158Sdas			bd2 -= bbe;
597112158Sdas		bs2 = bb2;
598112158Sdas#ifdef Honor_FLT_ROUNDS
599182709Sdas		if (Rounding != 1)
600112158Sdas			bs2++;
601112158Sdas#endif
602112158Sdas#ifdef Avoid_Underflow
603219557Sdas		Lsb = LSB;
604219557Sdas		Lsb1 = 0;
605112158Sdas		j = bbe - scale;
606112158Sdas		i = j + bbbits - 1;	/* logb(rv) */
607219557Sdas		j = P + 1 - bbbits;
608219557Sdas		if (i < Emin) {	/* denormal */
609219557Sdas			i = Emin - i;
610219557Sdas			j -= i;
611219557Sdas			if (i < 32)
612219557Sdas				Lsb <<= i;
613219557Sdas			else
614219557Sdas				Lsb1 = Lsb << (i-32);
615219557Sdas			}
616112158Sdas#else /*Avoid_Underflow*/
617112158Sdas#ifdef Sudden_Underflow
618112158Sdas#ifdef IBM
619112158Sdas		j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
620112158Sdas#else
621112158Sdas		j = P + 1 - bbbits;
622112158Sdas#endif
623112158Sdas#else /*Sudden_Underflow*/
624112158Sdas		j = bbe;
625219557Sdas		i = j + bbbits - 1;	/* logb(&rv) */
626112158Sdas		if (i < Emin)	/* denormal */
627112158Sdas			j += P - Emin;
628112158Sdas		else
629112158Sdas			j = P + 1 - bbbits;
630112158Sdas#endif /*Sudden_Underflow*/
631112158Sdas#endif /*Avoid_Underflow*/
632112158Sdas		bb2 += j;
633112158Sdas		bd2 += j;
634112158Sdas#ifdef Avoid_Underflow
635112158Sdas		bd2 += scale;
636112158Sdas#endif
637112158Sdas		i = bb2 < bd2 ? bb2 : bd2;
638112158Sdas		if (i > bs2)
639112158Sdas			i = bs2;
640112158Sdas		if (i > 0) {
641112158Sdas			bb2 -= i;
642112158Sdas			bd2 -= i;
643112158Sdas			bs2 -= i;
644112158Sdas			}
645112158Sdas		if (bb5 > 0) {
646112158Sdas			bs = pow5mult(bs, bb5);
647112158Sdas			bb1 = mult(bs, bb);
648112158Sdas			Bfree(bb);
649112158Sdas			bb = bb1;
650112158Sdas			}
651112158Sdas		if (bb2 > 0)
652112158Sdas			bb = lshift(bb, bb2);
653112158Sdas		if (bd5 > 0)
654112158Sdas			bd = pow5mult(bd, bd5);
655112158Sdas		if (bd2 > 0)
656112158Sdas			bd = lshift(bd, bd2);
657112158Sdas		if (bs2 > 0)
658112158Sdas			bs = lshift(bs, bs2);
659112158Sdas		delta = diff(bb, bd);
660112158Sdas		dsign = delta->sign;
661112158Sdas		delta->sign = 0;
662112158Sdas		i = cmp(delta, bs);
663112158Sdas#ifdef Honor_FLT_ROUNDS
664182709Sdas		if (Rounding != 1) {
665112158Sdas			if (i < 0) {
666112158Sdas				/* Error is less than an ulp */
667112158Sdas				if (!delta->x[0] && delta->wds <= 1) {
668112158Sdas					/* exact */
669112158Sdas#ifdef SET_INEXACT
670112158Sdas					inexact = 0;
671112158Sdas#endif
672112158Sdas					break;
673112158Sdas					}
674182709Sdas				if (Rounding) {
675112158Sdas					if (dsign) {
676219557Sdas						dval(&adj) = 1.;
677112158Sdas						goto apply_adj;
678112158Sdas						}
679112158Sdas					}
680112158Sdas				else if (!dsign) {
681219557Sdas					dval(&adj) = -1.;
682219557Sdas					if (!word1(&rv)
683219557Sdas					 && !(word0(&rv) & Frac_mask)) {
684219557Sdas						y = word0(&rv) & Exp_mask;
685112158Sdas#ifdef Avoid_Underflow
686112158Sdas						if (!scale || y > 2*P*Exp_msk1)
687112158Sdas#else
688112158Sdas						if (y)
689112158Sdas#endif
690112158Sdas						  {
691112158Sdas						  delta = lshift(delta,Log2P);
692112158Sdas						  if (cmp(delta, bs) <= 0)
693219557Sdas							dval(&adj) = -0.5;
694112158Sdas						  }
695112158Sdas						}
696112158Sdas apply_adj:
697112158Sdas#ifdef Avoid_Underflow
698219557Sdas					if (scale && (y = word0(&rv) & Exp_mask)
699112158Sdas						<= 2*P*Exp_msk1)
700219557Sdas					  word0(&adj) += (2*P+1)*Exp_msk1 - y;
701112158Sdas#else
702112158Sdas#ifdef Sudden_Underflow
703219557Sdas					if ((word0(&rv) & Exp_mask) <=
704112158Sdas							P*Exp_msk1) {
705219557Sdas						word0(&rv) += P*Exp_msk1;
706219557Sdas						dval(&rv) += adj*ulp(&rv);
707219557Sdas						word0(&rv) -= P*Exp_msk1;
708112158Sdas						}
709112158Sdas					else
710112158Sdas#endif /*Sudden_Underflow*/
711112158Sdas#endif /*Avoid_Underflow*/
712219557Sdas					dval(&rv) += adj.d*ulp(&rv);
713112158Sdas					}
714112158Sdas				break;
715112158Sdas				}
716219557Sdas			dval(&adj) = ratio(delta, bs);
717219557Sdas			if (adj.d < 1.)
718219557Sdas				dval(&adj) = 1.;
719219557Sdas			if (adj.d <= 0x7ffffffe) {
720219557Sdas				/* dval(&adj) = Rounding ? ceil(&adj) : floor(&adj); */
721219557Sdas				y = adj.d;
722219557Sdas				if (y != adj.d) {
723182709Sdas					if (!((Rounding>>1) ^ dsign))
724112158Sdas						y++;
725219557Sdas					dval(&adj) = y;
726112158Sdas					}
727112158Sdas				}
728112158Sdas#ifdef Avoid_Underflow
729219557Sdas			if (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
730219557Sdas				word0(&adj) += (2*P+1)*Exp_msk1 - y;
731112158Sdas#else
732112158Sdas#ifdef Sudden_Underflow
733219557Sdas			if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
734219557Sdas				word0(&rv) += P*Exp_msk1;
735219557Sdas				dval(&adj) *= ulp(&rv);
736112158Sdas				if (dsign)
737219557Sdas					dval(&rv) += adj;
738112158Sdas				else
739219557Sdas					dval(&rv) -= adj;
740219557Sdas				word0(&rv) -= P*Exp_msk1;
741112158Sdas				goto cont;
742112158Sdas				}
743112158Sdas#endif /*Sudden_Underflow*/
744112158Sdas#endif /*Avoid_Underflow*/
745219557Sdas			dval(&adj) *= ulp(&rv);
746182709Sdas			if (dsign) {
747219557Sdas				if (word0(&rv) == Big0 && word1(&rv) == Big1)
748182709Sdas					goto ovfl;
749219557Sdas				dval(&rv) += adj.d;
750182709Sdas				}
751112158Sdas			else
752219557Sdas				dval(&rv) -= adj.d;
753112158Sdas			goto cont;
754112158Sdas			}
755112158Sdas#endif /*Honor_FLT_ROUNDS*/
756112158Sdas
757112158Sdas		if (i < 0) {
758112158Sdas			/* Error is less than half an ulp -- check for
759112158Sdas			 * special case of mantissa a power of two.
760112158Sdas			 */
761219557Sdas			if (dsign || word1(&rv) || word0(&rv) & Bndry_mask
762112158Sdas#ifdef IEEE_Arith
763112158Sdas#ifdef Avoid_Underflow
764219557Sdas			 || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1
765112158Sdas#else
766219557Sdas			 || (word0(&rv) & Exp_mask) <= Exp_msk1
767112158Sdas#endif
768112158Sdas#endif
769112158Sdas				) {
770112158Sdas#ifdef SET_INEXACT
771112158Sdas				if (!delta->x[0] && delta->wds <= 1)
772112158Sdas					inexact = 0;
773112158Sdas#endif
774112158Sdas				break;
775112158Sdas				}
776112158Sdas			if (!delta->x[0] && delta->wds <= 1) {
777112158Sdas				/* exact result */
778112158Sdas#ifdef SET_INEXACT
779112158Sdas				inexact = 0;
780112158Sdas#endif
781112158Sdas				break;
782112158Sdas				}
783112158Sdas			delta = lshift(delta,Log2P);
784112158Sdas			if (cmp(delta, bs) > 0)
785112158Sdas				goto drop_down;
786112158Sdas			break;
787112158Sdas			}
788112158Sdas		if (i == 0) {
789112158Sdas			/* exactly half-way between */
790112158Sdas			if (dsign) {
791219557Sdas				if ((word0(&rv) & Bndry_mask1) == Bndry_mask1
792219557Sdas				 &&  word1(&rv) == (
793112158Sdas#ifdef Avoid_Underflow
794219557Sdas			(scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
795112158Sdas		? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
796112158Sdas#endif
797112158Sdas						   0xffffffff)) {
798112158Sdas					/*boundary case -- increment exponent*/
799219557Sdas					if (word0(&rv) == Big0 && word1(&rv) == Big1)
800219557Sdas						goto ovfl;
801219557Sdas					word0(&rv) = (word0(&rv) & Exp_mask)
802112158Sdas						+ Exp_msk1
803112158Sdas#ifdef IBM
804112158Sdas						| Exp_msk1 >> 4
805112158Sdas#endif
806112158Sdas						;
807219557Sdas					word1(&rv) = 0;
808112158Sdas#ifdef Avoid_Underflow
809112158Sdas					dsign = 0;
810112158Sdas#endif
811112158Sdas					break;
812112158Sdas					}
813112158Sdas				}
814219557Sdas			else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
815112158Sdas drop_down:
816112158Sdas				/* boundary case -- decrement exponent */
817112158Sdas#ifdef Sudden_Underflow /*{{*/
818219557Sdas				L = word0(&rv) & Exp_mask;
819112158Sdas#ifdef IBM
820112158Sdas				if (L <  Exp_msk1)
821112158Sdas#else
822112158Sdas#ifdef Avoid_Underflow
823112158Sdas				if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
824112158Sdas#else
825112158Sdas				if (L <= Exp_msk1)
826112158Sdas#endif /*Avoid_Underflow*/
827112158Sdas#endif /*IBM*/
828112158Sdas					goto undfl;
829112158Sdas				L -= Exp_msk1;
830112158Sdas#else /*Sudden_Underflow}{*/
831112158Sdas#ifdef Avoid_Underflow
832112158Sdas				if (scale) {
833219557Sdas					L = word0(&rv) & Exp_mask;
834112158Sdas					if (L <= (2*P+1)*Exp_msk1) {
835112158Sdas						if (L > (P+2)*Exp_msk1)
836112158Sdas							/* round even ==> */
837112158Sdas							/* accept rv */
838112158Sdas							break;
839112158Sdas						/* rv = smallest denormal */
840112158Sdas						goto undfl;
841112158Sdas						}
842112158Sdas					}
843112158Sdas#endif /*Avoid_Underflow*/
844219557Sdas				L = (word0(&rv) & Exp_mask) - Exp_msk1;
845182709Sdas#endif /*Sudden_Underflow}}*/
846219557Sdas				word0(&rv) = L | Bndry_mask1;
847219557Sdas				word1(&rv) = 0xffffffff;
848112158Sdas#ifdef IBM
849112158Sdas				goto cont;
850112158Sdas#else
851112158Sdas				break;
852112158Sdas#endif
853112158Sdas				}
854112158Sdas#ifndef ROUND_BIASED
855219557Sdas#ifdef Avoid_Underflow
856219557Sdas			if (Lsb1) {
857219557Sdas				if (!(word0(&rv) & Lsb1))
858219557Sdas					break;
859219557Sdas				}
860219557Sdas			else if (!(word1(&rv) & Lsb))
861112158Sdas				break;
862219557Sdas#else
863219557Sdas			if (!(word1(&rv) & LSB))
864219557Sdas				break;
865112158Sdas#endif
866219557Sdas#endif
867112158Sdas			if (dsign)
868219557Sdas#ifdef Avoid_Underflow
869219557Sdas				dval(&rv) += sulp(&rv, scale);
870219557Sdas#else
871219557Sdas				dval(&rv) += ulp(&rv);
872219557Sdas#endif
873112158Sdas#ifndef ROUND_BIASED
874112158Sdas			else {
875219557Sdas#ifdef Avoid_Underflow
876219557Sdas				dval(&rv) -= sulp(&rv, scale);
877219557Sdas#else
878219557Sdas				dval(&rv) -= ulp(&rv);
879219557Sdas#endif
880112158Sdas#ifndef Sudden_Underflow
881219557Sdas				if (!dval(&rv))
882112158Sdas					goto undfl;
883112158Sdas#endif
884112158Sdas				}
885112158Sdas#ifdef Avoid_Underflow
886112158Sdas			dsign = 1 - dsign;
887112158Sdas#endif
888112158Sdas#endif
889112158Sdas			break;
890112158Sdas			}
891112158Sdas		if ((aadj = ratio(delta, bs)) <= 2.) {
892112158Sdas			if (dsign)
893219557Sdas				aadj = dval(&aadj1) = 1.;
894219557Sdas			else if (word1(&rv) || word0(&rv) & Bndry_mask) {
895112158Sdas#ifndef Sudden_Underflow
896219557Sdas				if (word1(&rv) == Tiny1 && !word0(&rv))
897112158Sdas					goto undfl;
898112158Sdas#endif
899112158Sdas				aadj = 1.;
900219557Sdas				dval(&aadj1) = -1.;
901112158Sdas				}
902112158Sdas			else {
903112158Sdas				/* special case -- power of FLT_RADIX to be */
904112158Sdas				/* rounded down... */
905112158Sdas
906112158Sdas				if (aadj < 2./FLT_RADIX)
907112158Sdas					aadj = 1./FLT_RADIX;
908112158Sdas				else
909112158Sdas					aadj *= 0.5;
910219557Sdas				dval(&aadj1) = -aadj;
911112158Sdas				}
912112158Sdas			}
913112158Sdas		else {
914112158Sdas			aadj *= 0.5;
915219557Sdas			dval(&aadj1) = dsign ? aadj : -aadj;
916112158Sdas#ifdef Check_FLT_ROUNDS
917112158Sdas			switch(Rounding) {
918112158Sdas				case 2: /* towards +infinity */
919219557Sdas					dval(&aadj1) -= 0.5;
920112158Sdas					break;
921112158Sdas				case 0: /* towards 0 */
922112158Sdas				case 3: /* towards -infinity */
923219557Sdas					dval(&aadj1) += 0.5;
924112158Sdas				}
925112158Sdas#else
926112158Sdas			if (Flt_Rounds == 0)
927219557Sdas				dval(&aadj1) += 0.5;
928112158Sdas#endif /*Check_FLT_ROUNDS*/
929112158Sdas			}
930219557Sdas		y = word0(&rv) & Exp_mask;
931112158Sdas
932112158Sdas		/* Check for overflow */
933112158Sdas
934112158Sdas		if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
935219557Sdas			dval(&rv0) = dval(&rv);
936219557Sdas			word0(&rv) -= P*Exp_msk1;
937219557Sdas			dval(&adj) = dval(&aadj1) * ulp(&rv);
938219557Sdas			dval(&rv) += dval(&adj);
939219557Sdas			if ((word0(&rv) & Exp_mask) >=
940112158Sdas					Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
941219557Sdas				if (word0(&rv0) == Big0 && word1(&rv0) == Big1)
942112158Sdas					goto ovfl;
943219557Sdas				word0(&rv) = Big0;
944219557Sdas				word1(&rv) = Big1;
945112158Sdas				goto cont;
946112158Sdas				}
947112158Sdas			else
948219557Sdas				word0(&rv) += P*Exp_msk1;
949112158Sdas			}
950112158Sdas		else {
951112158Sdas#ifdef Avoid_Underflow
952112158Sdas			if (scale && y <= 2*P*Exp_msk1) {
953112158Sdas				if (aadj <= 0x7fffffff) {
954112158Sdas					if ((z = aadj) <= 0)
955112158Sdas						z = 1;
956112158Sdas					aadj = z;
957219557Sdas					dval(&aadj1) = dsign ? aadj : -aadj;
958112158Sdas					}
959219557Sdas				word0(&aadj1) += (2*P+1)*Exp_msk1 - y;
960112158Sdas				}
961219557Sdas			dval(&adj) = dval(&aadj1) * ulp(&rv);
962219557Sdas			dval(&rv) += dval(&adj);
963112158Sdas#else
964112158Sdas#ifdef Sudden_Underflow
965219557Sdas			if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
966219557Sdas				dval(&rv0) = dval(&rv);
967219557Sdas				word0(&rv) += P*Exp_msk1;
968219557Sdas				dval(&adj) = dval(&aadj1) * ulp(&rv);
969219557Sdas				dval(&rv) += adj;
970112158Sdas#ifdef IBM
971219557Sdas				if ((word0(&rv) & Exp_mask) <  P*Exp_msk1)
972112158Sdas#else
973219557Sdas				if ((word0(&rv) & Exp_mask) <= P*Exp_msk1)
974112158Sdas#endif
975112158Sdas					{
976219557Sdas					if (word0(&rv0) == Tiny0
977219557Sdas					 && word1(&rv0) == Tiny1)
978112158Sdas						goto undfl;
979219557Sdas					word0(&rv) = Tiny0;
980219557Sdas					word1(&rv) = Tiny1;
981112158Sdas					goto cont;
982112158Sdas					}
983112158Sdas				else
984219557Sdas					word0(&rv) -= P*Exp_msk1;
985112158Sdas				}
986112158Sdas			else {
987219557Sdas				dval(&adj) = dval(&aadj1) * ulp(&rv);
988219557Sdas				dval(&rv) += adj;
989112158Sdas				}
990112158Sdas#else /*Sudden_Underflow*/
991219557Sdas			/* Compute dval(&adj) so that the IEEE rounding rules will
992219557Sdas			 * correctly round rv + dval(&adj) in some half-way cases.
993219557Sdas			 * If rv * ulp(&rv) is denormalized (i.e.,
994112158Sdas			 * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
995112158Sdas			 * trouble from bits lost to denormalization;
996112158Sdas			 * example: 1.2e-307 .
997112158Sdas			 */
998112158Sdas			if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
999219557Sdas				dval(&aadj1) = (double)(int)(aadj + 0.5);
1000112158Sdas				if (!dsign)
1001219557Sdas					dval(&aadj1) = -dval(&aadj1);
1002112158Sdas				}
1003219557Sdas			dval(&adj) = dval(&aadj1) * ulp(&rv);
1004219557Sdas			dval(&rv) += adj;
1005112158Sdas#endif /*Sudden_Underflow*/
1006112158Sdas#endif /*Avoid_Underflow*/
1007112158Sdas			}
1008219557Sdas		z = word0(&rv) & Exp_mask;
1009112158Sdas#ifndef SET_INEXACT
1010112158Sdas#ifdef Avoid_Underflow
1011112158Sdas		if (!scale)
1012112158Sdas#endif
1013112158Sdas		if (y == z) {
1014112158Sdas			/* Can we stop now? */
1015112158Sdas			L = (Long)aadj;
1016112158Sdas			aadj -= L;
1017112158Sdas			/* The tolerances below are conservative. */
1018219557Sdas			if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) {
1019112158Sdas				if (aadj < .4999999 || aadj > .5000001)
1020112158Sdas					break;
1021112158Sdas				}
1022112158Sdas			else if (aadj < .4999999/FLT_RADIX)
1023112158Sdas				break;
1024112158Sdas			}
1025112158Sdas#endif
1026112158Sdas cont:
1027112158Sdas		Bfree(bb);
1028112158Sdas		Bfree(bd);
1029112158Sdas		Bfree(bs);
1030112158Sdas		Bfree(delta);
1031112158Sdas		}
1032219557Sdas	Bfree(bb);
1033219557Sdas	Bfree(bd);
1034219557Sdas	Bfree(bs);
1035219557Sdas	Bfree(bd0);
1036219557Sdas	Bfree(delta);
1037112158Sdas#ifdef SET_INEXACT
1038112158Sdas	if (inexact) {
1039112158Sdas		if (!oldinexact) {
1040219557Sdas			word0(&rv0) = Exp_1 + (70 << Exp_shift);
1041219557Sdas			word1(&rv0) = 0;
1042219557Sdas			dval(&rv0) += 1.;
1043112158Sdas			}
1044112158Sdas		}
1045112158Sdas	else if (!oldinexact)
1046112158Sdas		clear_inexact();
1047112158Sdas#endif
1048112158Sdas#ifdef Avoid_Underflow
1049112158Sdas	if (scale) {
1050219557Sdas		word0(&rv0) = Exp_1 - 2*P*Exp_msk1;
1051219557Sdas		word1(&rv0) = 0;
1052219557Sdas		dval(&rv) *= dval(&rv0);
1053112158Sdas#ifndef NO_ERRNO
1054112158Sdas		/* try to avoid the bug of testing an 8087 register value */
1055187808Sdas#ifdef IEEE_Arith
1056219557Sdas		if (!(word0(&rv) & Exp_mask))
1057187808Sdas#else
1058219557Sdas		if (word0(&rv) == 0 && word1(&rv) == 0)
1059187808Sdas#endif
1060112158Sdas			errno = ERANGE;
1061112158Sdas#endif
1062112158Sdas		}
1063112158Sdas#endif /* Avoid_Underflow */
1064112158Sdas#ifdef SET_INEXACT
1065219557Sdas	if (inexact && !(word0(&rv) & Exp_mask)) {
1066112158Sdas		/* set underflow bit */
1067219557Sdas		dval(&rv0) = 1e-300;
1068219557Sdas		dval(&rv0) *= dval(&rv0);
1069112158Sdas		}
1070112158Sdas#endif
1071112158Sdas ret:
1072112158Sdas	if (se)
1073112158Sdas		*se = (char *)s;
1074219557Sdas	return sign ? -dval(&rv) : dval(&rv);
1075112158Sdas	}
1076112158Sdas
1077235785Stheraven double
1078235785Stheravenstrtod
1079235785Stheraven#ifdef KR_headers
1080235785Stheraven	(s00, se, loc) CONST char *s00; char **se; locale_t
1081235785Stheraven#else
1082235785Stheraven	(CONST char *s00, char **se)
1083235785Stheraven#endif
1084235785Stheraven{
1085235785Stheraven	return strtod_l(s00, se, __get_locale());
1086235785Stheraven}
1087235785Stheraven
1088