xref: /freebsd-src/contrib/gdtoa/strtod.c (revision 8fa0b743820f61c661ba5f3ea0e3be0dc137910e)
1cc36ccd1SDavid Schultz /****************************************************************
2cc36ccd1SDavid Schultz 
3cc36ccd1SDavid Schultz The author of this software is David M. Gay.
4cc36ccd1SDavid Schultz 
5cc36ccd1SDavid Schultz Copyright (C) 1998-2001 by Lucent Technologies
6cc36ccd1SDavid Schultz All Rights Reserved
7cc36ccd1SDavid Schultz 
8cc36ccd1SDavid Schultz Permission to use, copy, modify, and distribute this software and
9cc36ccd1SDavid Schultz its documentation for any purpose and without fee is hereby
10cc36ccd1SDavid Schultz granted, provided that the above copyright notice appear in all
11cc36ccd1SDavid Schultz copies and that both that the copyright notice and this
12cc36ccd1SDavid Schultz permission notice and warranty disclaimer appear in supporting
13cc36ccd1SDavid Schultz documentation, and that the name of Lucent or any of its entities
14cc36ccd1SDavid Schultz not be used in advertising or publicity pertaining to
15cc36ccd1SDavid Schultz distribution of the software without specific, written prior
16cc36ccd1SDavid Schultz permission.
17cc36ccd1SDavid Schultz 
18cc36ccd1SDavid Schultz LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19cc36ccd1SDavid Schultz INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20cc36ccd1SDavid Schultz IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21cc36ccd1SDavid Schultz SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22cc36ccd1SDavid Schultz WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23cc36ccd1SDavid Schultz IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24cc36ccd1SDavid Schultz ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25cc36ccd1SDavid Schultz THIS SOFTWARE.
26cc36ccd1SDavid Schultz 
27cc36ccd1SDavid Schultz ****************************************************************/
28cc36ccd1SDavid Schultz 
29c88250a5SDavid Schultz /* Please send bug reports to David M. Gay (dmg at acm dot org,
30c88250a5SDavid Schultz  * with " at " changed at "@" and " dot " changed to ".").	*/
31cc36ccd1SDavid Schultz 
3210a381e5SDavid Schultz /* $FreeBSD$ */
3310a381e5SDavid Schultz 
34cc36ccd1SDavid Schultz #include "gdtoaimp.h"
35c88250a5SDavid Schultz #ifndef NO_FENV_H
36c88250a5SDavid Schultz #include <fenv.h>
37c88250a5SDavid Schultz #endif
38cc36ccd1SDavid Schultz 
39cc36ccd1SDavid Schultz #ifdef USE_LOCALE
40cc36ccd1SDavid Schultz #include "locale.h"
41cc36ccd1SDavid Schultz #endif
42cc36ccd1SDavid Schultz 
43cc36ccd1SDavid Schultz #ifdef IEEE_Arith
44cc36ccd1SDavid Schultz #ifndef NO_IEEE_Scale
45cc36ccd1SDavid Schultz #define Avoid_Underflow
46cc36ccd1SDavid Schultz #undef tinytens
47ae2cbf4cSDavid Schultz /* The factor of 2^106 in tinytens[4] helps us avoid setting the underflow */
48cc36ccd1SDavid Schultz /* flag unnecessarily.  It leads to a song and dance at the end of strtod. */
49cc36ccd1SDavid Schultz static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
50ae2cbf4cSDavid Schultz 		9007199254740992.*9007199254740992.e-256
51cc36ccd1SDavid Schultz 		};
52cc36ccd1SDavid Schultz #endif
53cc36ccd1SDavid Schultz #endif
54cc36ccd1SDavid Schultz 
55cc36ccd1SDavid Schultz #ifdef Honor_FLT_ROUNDS
56cc36ccd1SDavid Schultz #undef Check_FLT_ROUNDS
57cc36ccd1SDavid Schultz #define Check_FLT_ROUNDS
58cc36ccd1SDavid Schultz #else
59cc36ccd1SDavid Schultz #define Rounding Flt_Rounds
60cc36ccd1SDavid Schultz #endif
61cc36ccd1SDavid Schultz 
6250dad48bSDavid Schultz #ifdef Avoid_Underflow /*{*/
6350dad48bSDavid Schultz  static double
sulp(x,scale)6450dad48bSDavid Schultz sulp
6550dad48bSDavid Schultz #ifdef KR_headers
6650dad48bSDavid Schultz 	(x, scale) U *x; int scale;
6750dad48bSDavid Schultz #else
6850dad48bSDavid Schultz 	(U *x, int scale)
6950dad48bSDavid Schultz #endif
7050dad48bSDavid Schultz {
7150dad48bSDavid Schultz 	U u;
7250dad48bSDavid Schultz 	double rv;
7350dad48bSDavid Schultz 	int i;
7450dad48bSDavid Schultz 
7550dad48bSDavid Schultz 	rv = ulp(x);
7650dad48bSDavid Schultz 	if (!scale || (i = 2*P + 1 - ((word0(x) & Exp_mask) >> Exp_shift)) <= 0)
7750dad48bSDavid Schultz 		return rv; /* Is there an example where i <= 0 ? */
7850dad48bSDavid Schultz 	word0(&u) = Exp_1 + (i << Exp_shift);
7950dad48bSDavid Schultz 	word1(&u) = 0;
8050dad48bSDavid Schultz 	return rv * u.d;
8150dad48bSDavid Schultz 	}
8250dad48bSDavid Schultz #endif /*}*/
8350dad48bSDavid Schultz 
84cc36ccd1SDavid Schultz  double
strtod_l(s00,se,loc)85*3c87aa1dSDavid Chisnall strtod_l
86cc36ccd1SDavid Schultz #ifdef KR_headers
87*3c87aa1dSDavid Chisnall 	(s00, se, loc) CONST char *s00; char **se; locale_t loc
88cc36ccd1SDavid Schultz #else
89*3c87aa1dSDavid Chisnall 	(CONST char *s00, char **se, locale_t loc)
90cc36ccd1SDavid Schultz #endif
91cc36ccd1SDavid Schultz {
92cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
93cc36ccd1SDavid Schultz 	int scale;
94cc36ccd1SDavid Schultz #endif
95c88250a5SDavid Schultz 	int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign,
96cc36ccd1SDavid Schultz 		 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
97cc36ccd1SDavid Schultz 	CONST char *s, *s0, *s1;
9850dad48bSDavid Schultz 	double aadj;
99cc36ccd1SDavid Schultz 	Long L;
10050dad48bSDavid Schultz 	U adj, aadj1, rv, rv0;
101cc36ccd1SDavid Schultz 	ULong y, z;
102cc36ccd1SDavid Schultz 	Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
10350dad48bSDavid Schultz #ifdef Avoid_Underflow
10450dad48bSDavid Schultz 	ULong Lsb, Lsb1;
10550dad48bSDavid Schultz #endif
106cc36ccd1SDavid Schultz #ifdef SET_INEXACT
107cc36ccd1SDavid Schultz 	int inexact, oldinexact;
108cc36ccd1SDavid Schultz #endif
1094848dd08SDavid Schultz #ifdef USE_LOCALE /*{{*/
1104848dd08SDavid Schultz #ifdef NO_LOCALE_CACHE
111*3c87aa1dSDavid Chisnall 	char *decimalpoint = localeconv_l(loc)->decimal_point;
1124848dd08SDavid Schultz 	int dplen = strlen(decimalpoint);
1134848dd08SDavid Schultz #else
1144848dd08SDavid Schultz 	char *decimalpoint;
1154848dd08SDavid Schultz 	static char *decimalpoint_cache;
1164848dd08SDavid Schultz 	static int dplen;
1174848dd08SDavid Schultz 	if (!(s0 = decimalpoint_cache)) {
118*3c87aa1dSDavid Chisnall 		s0 = localeconv_l(loc)->decimal_point;
11950dad48bSDavid Schultz 		if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
1204848dd08SDavid Schultz 			strcpy(decimalpoint_cache, s0);
1214848dd08SDavid Schultz 			s0 = decimalpoint_cache;
1224848dd08SDavid Schultz 			}
1234848dd08SDavid Schultz 		dplen = strlen(s0);
1244848dd08SDavid Schultz 		}
1254848dd08SDavid Schultz 	decimalpoint = (char*)s0;
1264848dd08SDavid Schultz #endif /*NO_LOCALE_CACHE*/
1274848dd08SDavid Schultz #else  /*USE_LOCALE}{*/
1284848dd08SDavid Schultz #define dplen 1
1294848dd08SDavid Schultz #endif /*USE_LOCALE}}*/
1304848dd08SDavid Schultz 
131ae2cbf4cSDavid Schultz #ifdef Honor_FLT_ROUNDS /*{*/
132ae2cbf4cSDavid Schultz 	int Rounding;
133ae2cbf4cSDavid Schultz #ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
134ae2cbf4cSDavid Schultz 	Rounding = Flt_Rounds;
135ae2cbf4cSDavid Schultz #else /*}{*/
136ae2cbf4cSDavid Schultz 	Rounding = 1;
137ae2cbf4cSDavid Schultz 	switch(fegetround()) {
138ae2cbf4cSDavid Schultz 	  case FE_TOWARDZERO:	Rounding = 0; break;
139ae2cbf4cSDavid Schultz 	  case FE_UPWARD:	Rounding = 2; break;
140ae2cbf4cSDavid Schultz 	  case FE_DOWNWARD:	Rounding = 3;
141ae2cbf4cSDavid Schultz 	  }
142ae2cbf4cSDavid Schultz #endif /*}}*/
143ae2cbf4cSDavid Schultz #endif /*}*/
144cc36ccd1SDavid Schultz 
145c88250a5SDavid Schultz 	sign = nz0 = nz = decpt = 0;
14650dad48bSDavid Schultz 	dval(&rv) = 0.;
147cc36ccd1SDavid Schultz 	for(s = s00;;s++) switch(*s) {
148cc36ccd1SDavid Schultz 		case '-':
149cc36ccd1SDavid Schultz 			sign = 1;
150cc36ccd1SDavid Schultz 			/* no break */
151cc36ccd1SDavid Schultz 		case '+':
152cc36ccd1SDavid Schultz 			if (*++s)
153cc36ccd1SDavid Schultz 				goto break2;
154cc36ccd1SDavid Schultz 			/* no break */
155cc36ccd1SDavid Schultz 		case 0:
156cc36ccd1SDavid Schultz 			goto ret0;
157cc36ccd1SDavid Schultz 		case '\t':
158cc36ccd1SDavid Schultz 		case '\n':
159cc36ccd1SDavid Schultz 		case '\v':
160cc36ccd1SDavid Schultz 		case '\f':
161cc36ccd1SDavid Schultz 		case '\r':
162cc36ccd1SDavid Schultz 		case ' ':
163cc36ccd1SDavid Schultz 			continue;
164cc36ccd1SDavid Schultz 		default:
165cc36ccd1SDavid Schultz 			goto break2;
166cc36ccd1SDavid Schultz 		}
167cc36ccd1SDavid Schultz  break2:
168cc36ccd1SDavid Schultz 	if (*s == '0') {
1694848dd08SDavid Schultz #ifndef NO_HEX_FP /*{*/
170cc36ccd1SDavid Schultz 		{
171cc36ccd1SDavid Schultz 		static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
172cc36ccd1SDavid Schultz 		Long exp;
173cc36ccd1SDavid Schultz 		ULong bits[2];
174cc36ccd1SDavid Schultz 		switch(s[1]) {
175cc36ccd1SDavid Schultz 		  case 'x':
176cc36ccd1SDavid Schultz 		  case 'X':
177c88250a5SDavid Schultz 			{
17850dad48bSDavid Schultz #ifdef Honor_FLT_ROUNDS
179c88250a5SDavid Schultz 			FPI fpi1 = fpi;
180ae2cbf4cSDavid Schultz 			fpi1.rounding = Rounding;
18150dad48bSDavid Schultz #else
182c88250a5SDavid Schultz #define fpi1 fpi
18350dad48bSDavid Schultz #endif
184c88250a5SDavid Schultz 			switch((i = gethex(&s, &fpi1, &exp, &bb, sign)) & STRTOG_Retmask) {
185cc36ccd1SDavid Schultz 			  case STRTOG_NoNumber:
186cc36ccd1SDavid Schultz 				s = s00;
187cc36ccd1SDavid Schultz 				sign = 0;
188cc36ccd1SDavid Schultz 			  case STRTOG_Zero:
189cc36ccd1SDavid Schultz 				break;
190cc36ccd1SDavid Schultz 			  default:
19119927830SDavid Schultz 				if (bb) {
192cc36ccd1SDavid Schultz 					copybits(bits, fpi.nbits, bb);
193cc36ccd1SDavid Schultz 					Bfree(bb);
19419927830SDavid Schultz 					}
195cc36ccd1SDavid Schultz 				ULtod(((U*)&rv)->L, bits, exp, i);
196c88250a5SDavid Schultz 			  }}
197cc36ccd1SDavid Schultz 			goto ret;
198cc36ccd1SDavid Schultz 		  }
199cc36ccd1SDavid Schultz 		}
2004848dd08SDavid Schultz #endif /*}*/
201cc36ccd1SDavid Schultz 		nz0 = 1;
202cc36ccd1SDavid Schultz 		while(*++s == '0') ;
203cc36ccd1SDavid Schultz 		if (!*s)
204cc36ccd1SDavid Schultz 			goto ret;
205cc36ccd1SDavid Schultz 		}
206cc36ccd1SDavid Schultz 	s0 = s;
207cc36ccd1SDavid Schultz 	y = z = 0;
208cc36ccd1SDavid Schultz 	for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
209cc36ccd1SDavid Schultz 		if (nd < 9)
210cc36ccd1SDavid Schultz 			y = 10*y + c - '0';
211cc36ccd1SDavid Schultz 		else if (nd < 16)
212cc36ccd1SDavid Schultz 			z = 10*z + c - '0';
213cc36ccd1SDavid Schultz 	nd0 = nd;
214cc36ccd1SDavid Schultz #ifdef USE_LOCALE
2154848dd08SDavid Schultz 	if (c == *decimalpoint) {
2164848dd08SDavid Schultz 		for(i = 1; decimalpoint[i]; ++i)
2174848dd08SDavid Schultz 			if (s[i] != decimalpoint[i])
2184848dd08SDavid Schultz 				goto dig_done;
2194848dd08SDavid Schultz 		s += i;
2204848dd08SDavid Schultz 		c = *s;
22184781d47SDavid Schultz #else
2224848dd08SDavid Schultz 	if (c == '.') {
223cc36ccd1SDavid Schultz 		c = *++s;
2244848dd08SDavid Schultz #endif
2254848dd08SDavid Schultz 		decpt = 1;
226cc36ccd1SDavid Schultz 		if (!nd) {
227cc36ccd1SDavid Schultz 			for(; c == '0'; c = *++s)
228cc36ccd1SDavid Schultz 				nz++;
229cc36ccd1SDavid Schultz 			if (c > '0' && c <= '9') {
230cc36ccd1SDavid Schultz 				s0 = s;
231cc36ccd1SDavid Schultz 				nf += nz;
232cc36ccd1SDavid Schultz 				nz = 0;
233cc36ccd1SDavid Schultz 				goto have_dig;
234cc36ccd1SDavid Schultz 				}
235cc36ccd1SDavid Schultz 			goto dig_done;
236cc36ccd1SDavid Schultz 			}
237cc36ccd1SDavid Schultz 		for(; c >= '0' && c <= '9'; c = *++s) {
238cc36ccd1SDavid Schultz  have_dig:
239cc36ccd1SDavid Schultz 			nz++;
240cc36ccd1SDavid Schultz 			if (c -= '0') {
241cc36ccd1SDavid Schultz 				nf += nz;
242cc36ccd1SDavid Schultz 				for(i = 1; i < nz; i++)
243cc36ccd1SDavid Schultz 					if (nd++ < 9)
244cc36ccd1SDavid Schultz 						y *= 10;
245cc36ccd1SDavid Schultz 					else if (nd <= DBL_DIG + 1)
246cc36ccd1SDavid Schultz 						z *= 10;
247cc36ccd1SDavid Schultz 				if (nd++ < 9)
248cc36ccd1SDavid Schultz 					y = 10*y + c;
249cc36ccd1SDavid Schultz 				else if (nd <= DBL_DIG + 1)
250cc36ccd1SDavid Schultz 					z = 10*z + c;
251cc36ccd1SDavid Schultz 				nz = 0;
252cc36ccd1SDavid Schultz 				}
253cc36ccd1SDavid Schultz 			}
2544848dd08SDavid Schultz 		}/*}*/
255cc36ccd1SDavid Schultz  dig_done:
256cc36ccd1SDavid Schultz 	e = 0;
257cc36ccd1SDavid Schultz 	if (c == 'e' || c == 'E') {
258cc36ccd1SDavid Schultz 		if (!nd && !nz && !nz0) {
259cc36ccd1SDavid Schultz 			goto ret0;
260cc36ccd1SDavid Schultz 			}
261cc36ccd1SDavid Schultz 		s00 = s;
262cc36ccd1SDavid Schultz 		esign = 0;
263cc36ccd1SDavid Schultz 		switch(c = *++s) {
264cc36ccd1SDavid Schultz 			case '-':
265cc36ccd1SDavid Schultz 				esign = 1;
266cc36ccd1SDavid Schultz 			case '+':
267cc36ccd1SDavid Schultz 				c = *++s;
268cc36ccd1SDavid Schultz 			}
269cc36ccd1SDavid Schultz 		if (c >= '0' && c <= '9') {
270cc36ccd1SDavid Schultz 			while(c == '0')
271cc36ccd1SDavid Schultz 				c = *++s;
272cc36ccd1SDavid Schultz 			if (c > '0' && c <= '9') {
273cc36ccd1SDavid Schultz 				L = c - '0';
274cc36ccd1SDavid Schultz 				s1 = s;
275cc36ccd1SDavid Schultz 				while((c = *++s) >= '0' && c <= '9')
276cc36ccd1SDavid Schultz 					L = 10*L + c - '0';
277cc36ccd1SDavid Schultz 				if (s - s1 > 8 || L > 19999)
278cc36ccd1SDavid Schultz 					/* Avoid confusion from exponents
279cc36ccd1SDavid Schultz 					 * so large that e might overflow.
280cc36ccd1SDavid Schultz 					 */
281cc36ccd1SDavid Schultz 					e = 19999; /* safe for 16 bit ints */
282cc36ccd1SDavid Schultz 				else
283cc36ccd1SDavid Schultz 					e = (int)L;
284cc36ccd1SDavid Schultz 				if (esign)
285cc36ccd1SDavid Schultz 					e = -e;
286cc36ccd1SDavid Schultz 				}
287cc36ccd1SDavid Schultz 			else
288cc36ccd1SDavid Schultz 				e = 0;
289cc36ccd1SDavid Schultz 			}
290cc36ccd1SDavid Schultz 		else
291cc36ccd1SDavid Schultz 			s = s00;
292cc36ccd1SDavid Schultz 		}
293cc36ccd1SDavid Schultz 	if (!nd) {
294cc36ccd1SDavid Schultz 		if (!nz && !nz0) {
295cc36ccd1SDavid Schultz #ifdef INFNAN_CHECK
296cc36ccd1SDavid Schultz 			/* Check for Nan and Infinity */
297cc36ccd1SDavid Schultz 			ULong bits[2];
298cc36ccd1SDavid Schultz 			static FPI fpinan =	/* only 52 explicit bits */
299cc36ccd1SDavid Schultz 				{ 52, 1-1023-53+1, 2046-1023-53+1, 1, SI };
300c88250a5SDavid Schultz 			if (!decpt)
301cc36ccd1SDavid Schultz 			 switch(c) {
302cc36ccd1SDavid Schultz 			  case 'i':
303cc36ccd1SDavid Schultz 			  case 'I':
304cc36ccd1SDavid Schultz 				if (match(&s,"nf")) {
305cc36ccd1SDavid Schultz 					--s;
306cc36ccd1SDavid Schultz 					if (!match(&s,"inity"))
307cc36ccd1SDavid Schultz 						++s;
30850dad48bSDavid Schultz 					word0(&rv) = 0x7ff00000;
30950dad48bSDavid Schultz 					word1(&rv) = 0;
310cc36ccd1SDavid Schultz 					goto ret;
311cc36ccd1SDavid Schultz 					}
312cc36ccd1SDavid Schultz 				break;
313cc36ccd1SDavid Schultz 			  case 'n':
314cc36ccd1SDavid Schultz 			  case 'N':
315cc36ccd1SDavid Schultz 				if (match(&s, "an")) {
316cc36ccd1SDavid Schultz #ifndef No_Hex_NaN
317cc36ccd1SDavid Schultz 					if (*s == '(' /*)*/
318cc36ccd1SDavid Schultz 					 && hexnan(&s, &fpinan, bits)
319cc36ccd1SDavid Schultz 							== STRTOG_NaNbits) {
32050dad48bSDavid Schultz 						word0(&rv) = 0x7ff80000 | bits[1];
32150dad48bSDavid Schultz 						word1(&rv) = bits[0];
322cc36ccd1SDavid Schultz 						}
323cc36ccd1SDavid Schultz 					else {
324c88250a5SDavid Schultz #endif
32550dad48bSDavid Schultz 						word0(&rv) = NAN_WORD0;
32650dad48bSDavid Schultz 						word1(&rv) = NAN_WORD1;
327c88250a5SDavid Schultz #ifndef No_Hex_NaN
328cc36ccd1SDavid Schultz 						}
329cc36ccd1SDavid Schultz #endif
330cc36ccd1SDavid Schultz 					goto ret;
331cc36ccd1SDavid Schultz 					}
332cc36ccd1SDavid Schultz 			  }
333cc36ccd1SDavid Schultz #endif /* INFNAN_CHECK */
334cc36ccd1SDavid Schultz  ret0:
335cc36ccd1SDavid Schultz 			s = s00;
336cc36ccd1SDavid Schultz 			sign = 0;
337cc36ccd1SDavid Schultz 			}
338cc36ccd1SDavid Schultz 		goto ret;
339cc36ccd1SDavid Schultz 		}
340cc36ccd1SDavid Schultz 	e1 = e -= nf;
341cc36ccd1SDavid Schultz 
342cc36ccd1SDavid Schultz 	/* Now we have nd0 digits, starting at s0, followed by a
343cc36ccd1SDavid Schultz 	 * decimal point, followed by nd-nd0 digits.  The number we're
344cc36ccd1SDavid Schultz 	 * after is the integer represented by those digits times
345cc36ccd1SDavid Schultz 	 * 10**e */
346cc36ccd1SDavid Schultz 
347cc36ccd1SDavid Schultz 	if (!nd0)
348cc36ccd1SDavid Schultz 		nd0 = nd;
349cc36ccd1SDavid Schultz 	k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
35050dad48bSDavid Schultz 	dval(&rv) = y;
351cc36ccd1SDavid Schultz 	if (k > 9) {
352cc36ccd1SDavid Schultz #ifdef SET_INEXACT
353cc36ccd1SDavid Schultz 		if (k > DBL_DIG)
354cc36ccd1SDavid Schultz 			oldinexact = get_inexact();
355cc36ccd1SDavid Schultz #endif
35650dad48bSDavid Schultz 		dval(&rv) = tens[k - 9] * dval(&rv) + z;
357cc36ccd1SDavid Schultz 		}
358cc36ccd1SDavid Schultz 	bd0 = 0;
359cc36ccd1SDavid Schultz 	if (nd <= DBL_DIG
360cc36ccd1SDavid Schultz #ifndef RND_PRODQUOT
361cc36ccd1SDavid Schultz #ifndef Honor_FLT_ROUNDS
362cc36ccd1SDavid Schultz 		&& Flt_Rounds == 1
363cc36ccd1SDavid Schultz #endif
364cc36ccd1SDavid Schultz #endif
365cc36ccd1SDavid Schultz 			) {
366cc36ccd1SDavid Schultz 		if (!e)
367cc36ccd1SDavid Schultz 			goto ret;
36850dad48bSDavid Schultz #ifndef ROUND_BIASED_without_Round_Up
369cc36ccd1SDavid Schultz 		if (e > 0) {
370cc36ccd1SDavid Schultz 			if (e <= Ten_pmax) {
371cc36ccd1SDavid Schultz #ifdef VAX
372cc36ccd1SDavid Schultz 				goto vax_ovfl_check;
373cc36ccd1SDavid Schultz #else
374cc36ccd1SDavid Schultz #ifdef Honor_FLT_ROUNDS
375cc36ccd1SDavid Schultz 				/* round correctly FLT_ROUNDS = 2 or 3 */
376cc36ccd1SDavid Schultz 				if (sign) {
37750dad48bSDavid Schultz 					rv.d = -rv.d;
378cc36ccd1SDavid Schultz 					sign = 0;
379cc36ccd1SDavid Schultz 					}
380cc36ccd1SDavid Schultz #endif
38150dad48bSDavid Schultz 				/* rv = */ rounded_product(dval(&rv), tens[e]);
382cc36ccd1SDavid Schultz 				goto ret;
383cc36ccd1SDavid Schultz #endif
384cc36ccd1SDavid Schultz 				}
385cc36ccd1SDavid Schultz 			i = DBL_DIG - nd;
386cc36ccd1SDavid Schultz 			if (e <= Ten_pmax + i) {
387cc36ccd1SDavid Schultz 				/* A fancier test would sometimes let us do
388cc36ccd1SDavid Schultz 				 * this for larger i values.
389cc36ccd1SDavid Schultz 				 */
390cc36ccd1SDavid Schultz #ifdef Honor_FLT_ROUNDS
391cc36ccd1SDavid Schultz 				/* round correctly FLT_ROUNDS = 2 or 3 */
392cc36ccd1SDavid Schultz 				if (sign) {
39350dad48bSDavid Schultz 					rv.d = -rv.d;
394cc36ccd1SDavid Schultz 					sign = 0;
395cc36ccd1SDavid Schultz 					}
396cc36ccd1SDavid Schultz #endif
397cc36ccd1SDavid Schultz 				e -= i;
39850dad48bSDavid Schultz 				dval(&rv) *= tens[i];
399cc36ccd1SDavid Schultz #ifdef VAX
400cc36ccd1SDavid Schultz 				/* VAX exponent range is so narrow we must
401cc36ccd1SDavid Schultz 				 * worry about overflow here...
402cc36ccd1SDavid Schultz 				 */
403cc36ccd1SDavid Schultz  vax_ovfl_check:
40450dad48bSDavid Schultz 				word0(&rv) -= P*Exp_msk1;
40550dad48bSDavid Schultz 				/* rv = */ rounded_product(dval(&rv), tens[e]);
40650dad48bSDavid Schultz 				if ((word0(&rv) & Exp_mask)
407cc36ccd1SDavid Schultz 				 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
408cc36ccd1SDavid Schultz 					goto ovfl;
40950dad48bSDavid Schultz 				word0(&rv) += P*Exp_msk1;
410cc36ccd1SDavid Schultz #else
41150dad48bSDavid Schultz 				/* rv = */ rounded_product(dval(&rv), tens[e]);
412cc36ccd1SDavid Schultz #endif
413cc36ccd1SDavid Schultz 				goto ret;
414cc36ccd1SDavid Schultz 				}
415cc36ccd1SDavid Schultz 			}
416cc36ccd1SDavid Schultz #ifndef Inaccurate_Divide
417cc36ccd1SDavid Schultz 		else if (e >= -Ten_pmax) {
418cc36ccd1SDavid Schultz #ifdef Honor_FLT_ROUNDS
419cc36ccd1SDavid Schultz 			/* round correctly FLT_ROUNDS = 2 or 3 */
420cc36ccd1SDavid Schultz 			if (sign) {
42150dad48bSDavid Schultz 				rv.d = -rv.d;
422cc36ccd1SDavid Schultz 				sign = 0;
423cc36ccd1SDavid Schultz 				}
424cc36ccd1SDavid Schultz #endif
42550dad48bSDavid Schultz 			/* rv = */ rounded_quotient(dval(&rv), tens[-e]);
426cc36ccd1SDavid Schultz 			goto ret;
427cc36ccd1SDavid Schultz 			}
428cc36ccd1SDavid Schultz #endif
42950dad48bSDavid Schultz #endif /* ROUND_BIASED_without_Round_Up */
430cc36ccd1SDavid Schultz 		}
431cc36ccd1SDavid Schultz 	e1 += nd - k;
432cc36ccd1SDavid Schultz 
433cc36ccd1SDavid Schultz #ifdef IEEE_Arith
434cc36ccd1SDavid Schultz #ifdef SET_INEXACT
435cc36ccd1SDavid Schultz 	inexact = 1;
436cc36ccd1SDavid Schultz 	if (k <= DBL_DIG)
437cc36ccd1SDavid Schultz 		oldinexact = get_inexact();
438cc36ccd1SDavid Schultz #endif
439cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
440cc36ccd1SDavid Schultz 	scale = 0;
441cc36ccd1SDavid Schultz #endif
442cc36ccd1SDavid Schultz #ifdef Honor_FLT_ROUNDS
443ae2cbf4cSDavid Schultz 	if (Rounding >= 2) {
444cc36ccd1SDavid Schultz 		if (sign)
445ae2cbf4cSDavid Schultz 			Rounding = Rounding == 2 ? 0 : 2;
446cc36ccd1SDavid Schultz 		else
447ae2cbf4cSDavid Schultz 			if (Rounding != 2)
448ae2cbf4cSDavid Schultz 				Rounding = 0;
449cc36ccd1SDavid Schultz 		}
450cc36ccd1SDavid Schultz #endif
451cc36ccd1SDavid Schultz #endif /*IEEE_Arith*/
452cc36ccd1SDavid Schultz 
453cc36ccd1SDavid Schultz 	/* Get starting approximation = rv * 10**e1 */
454cc36ccd1SDavid Schultz 
455cc36ccd1SDavid Schultz 	if (e1 > 0) {
456cc36ccd1SDavid Schultz 		if ( (i = e1 & 15) !=0)
45750dad48bSDavid Schultz 			dval(&rv) *= tens[i];
458cc36ccd1SDavid Schultz 		if (e1 &= ~15) {
459cc36ccd1SDavid Schultz 			if (e1 > DBL_MAX_10_EXP) {
460cc36ccd1SDavid Schultz  ovfl:
461cc36ccd1SDavid Schultz 				/* Can't trust HUGE_VAL */
462cc36ccd1SDavid Schultz #ifdef IEEE_Arith
463cc36ccd1SDavid Schultz #ifdef Honor_FLT_ROUNDS
464ae2cbf4cSDavid Schultz 				switch(Rounding) {
465cc36ccd1SDavid Schultz 				  case 0: /* toward 0 */
466cc36ccd1SDavid Schultz 				  case 3: /* toward -infinity */
46750dad48bSDavid Schultz 					word0(&rv) = Big0;
46850dad48bSDavid Schultz 					word1(&rv) = Big1;
469cc36ccd1SDavid Schultz 					break;
470cc36ccd1SDavid Schultz 				  default:
47150dad48bSDavid Schultz 					word0(&rv) = Exp_mask;
47250dad48bSDavid Schultz 					word1(&rv) = 0;
473cc36ccd1SDavid Schultz 				  }
474cc36ccd1SDavid Schultz #else /*Honor_FLT_ROUNDS*/
47550dad48bSDavid Schultz 				word0(&rv) = Exp_mask;
47650dad48bSDavid Schultz 				word1(&rv) = 0;
477cc36ccd1SDavid Schultz #endif /*Honor_FLT_ROUNDS*/
478cc36ccd1SDavid Schultz #ifdef SET_INEXACT
479cc36ccd1SDavid Schultz 				/* set overflow bit */
48050dad48bSDavid Schultz 				dval(&rv0) = 1e300;
48150dad48bSDavid Schultz 				dval(&rv0) *= dval(&rv0);
482cc36ccd1SDavid Schultz #endif
483cc36ccd1SDavid Schultz #else /*IEEE_Arith*/
48450dad48bSDavid Schultz 				word0(&rv) = Big0;
48550dad48bSDavid Schultz 				word1(&rv) = Big1;
486cc36ccd1SDavid Schultz #endif /*IEEE_Arith*/
48750dad48bSDavid Schultz  range_err:
48850dad48bSDavid Schultz 				if (bd0) {
48950dad48bSDavid Schultz 					Bfree(bb);
49050dad48bSDavid Schultz 					Bfree(bd);
49150dad48bSDavid Schultz 					Bfree(bs);
49250dad48bSDavid Schultz 					Bfree(bd0);
49350dad48bSDavid Schultz 					Bfree(delta);
49450dad48bSDavid Schultz 					}
49550dad48bSDavid Schultz #ifndef NO_ERRNO
49650dad48bSDavid Schultz 				errno = ERANGE;
49750dad48bSDavid Schultz #endif
498cc36ccd1SDavid Schultz 				goto ret;
499cc36ccd1SDavid Schultz 				}
500cc36ccd1SDavid Schultz 			e1 >>= 4;
501cc36ccd1SDavid Schultz 			for(j = 0; e1 > 1; j++, e1 >>= 1)
502cc36ccd1SDavid Schultz 				if (e1 & 1)
50350dad48bSDavid Schultz 					dval(&rv) *= bigtens[j];
504cc36ccd1SDavid Schultz 		/* The last multiplication could overflow. */
50550dad48bSDavid Schultz 			word0(&rv) -= P*Exp_msk1;
50650dad48bSDavid Schultz 			dval(&rv) *= bigtens[j];
50750dad48bSDavid Schultz 			if ((z = word0(&rv) & Exp_mask)
508cc36ccd1SDavid Schultz 			 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
509cc36ccd1SDavid Schultz 				goto ovfl;
510cc36ccd1SDavid Schultz 			if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
511cc36ccd1SDavid Schultz 				/* set to largest number */
512cc36ccd1SDavid Schultz 				/* (Can't trust DBL_MAX) */
51350dad48bSDavid Schultz 				word0(&rv) = Big0;
51450dad48bSDavid Schultz 				word1(&rv) = Big1;
515cc36ccd1SDavid Schultz 				}
516cc36ccd1SDavid Schultz 			else
51750dad48bSDavid Schultz 				word0(&rv) += P*Exp_msk1;
518cc36ccd1SDavid Schultz 			}
519cc36ccd1SDavid Schultz 		}
520cc36ccd1SDavid Schultz 	else if (e1 < 0) {
521cc36ccd1SDavid Schultz 		e1 = -e1;
522cc36ccd1SDavid Schultz 		if ( (i = e1 & 15) !=0)
52350dad48bSDavid Schultz 			dval(&rv) /= tens[i];
524cc36ccd1SDavid Schultz 		if (e1 >>= 4) {
525cc36ccd1SDavid Schultz 			if (e1 >= 1 << n_bigtens)
526cc36ccd1SDavid Schultz 				goto undfl;
527cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
528cc36ccd1SDavid Schultz 			if (e1 & Scale_Bit)
529cc36ccd1SDavid Schultz 				scale = 2*P;
530cc36ccd1SDavid Schultz 			for(j = 0; e1 > 0; j++, e1 >>= 1)
531cc36ccd1SDavid Schultz 				if (e1 & 1)
53250dad48bSDavid Schultz 					dval(&rv) *= tinytens[j];
53350dad48bSDavid Schultz 			if (scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask)
534cc36ccd1SDavid Schultz 						>> Exp_shift)) > 0) {
535cc36ccd1SDavid Schultz 				/* scaled rv is denormal; zap j low bits */
536cc36ccd1SDavid Schultz 				if (j >= 32) {
53750dad48bSDavid Schultz 					word1(&rv) = 0;
538cc36ccd1SDavid Schultz 					if (j >= 53)
53950dad48bSDavid Schultz 					 word0(&rv) = (P+2)*Exp_msk1;
540cc36ccd1SDavid Schultz 					else
54150dad48bSDavid Schultz 					 word0(&rv) &= 0xffffffff << (j-32);
542cc36ccd1SDavid Schultz 					}
543cc36ccd1SDavid Schultz 				else
54450dad48bSDavid Schultz 					word1(&rv) &= 0xffffffff << j;
545cc36ccd1SDavid Schultz 				}
546cc36ccd1SDavid Schultz #else
547cc36ccd1SDavid Schultz 			for(j = 0; e1 > 1; j++, e1 >>= 1)
548cc36ccd1SDavid Schultz 				if (e1 & 1)
54950dad48bSDavid Schultz 					dval(&rv) *= tinytens[j];
550cc36ccd1SDavid Schultz 			/* The last multiplication could underflow. */
55150dad48bSDavid Schultz 			dval(&rv0) = dval(&rv);
55250dad48bSDavid Schultz 			dval(&rv) *= tinytens[j];
55350dad48bSDavid Schultz 			if (!dval(&rv)) {
55450dad48bSDavid Schultz 				dval(&rv) = 2.*dval(&rv0);
55550dad48bSDavid Schultz 				dval(&rv) *= tinytens[j];
556cc36ccd1SDavid Schultz #endif
55750dad48bSDavid Schultz 				if (!dval(&rv)) {
558cc36ccd1SDavid Schultz  undfl:
55950dad48bSDavid Schultz 					dval(&rv) = 0.;
56050dad48bSDavid Schultz 					goto range_err;
561cc36ccd1SDavid Schultz 					}
562cc36ccd1SDavid Schultz #ifndef Avoid_Underflow
56350dad48bSDavid Schultz 				word0(&rv) = Tiny0;
56450dad48bSDavid Schultz 				word1(&rv) = Tiny1;
565cc36ccd1SDavid Schultz 				/* The refinement below will clean
566cc36ccd1SDavid Schultz 				 * this approximation up.
567cc36ccd1SDavid Schultz 				 */
568cc36ccd1SDavid Schultz 				}
569cc36ccd1SDavid Schultz #endif
570cc36ccd1SDavid Schultz 			}
571cc36ccd1SDavid Schultz 		}
572cc36ccd1SDavid Schultz 
573cc36ccd1SDavid Schultz 	/* Now the hard part -- adjusting rv to the correct value.*/
574cc36ccd1SDavid Schultz 
575cc36ccd1SDavid Schultz 	/* Put digits into bd: true value = bd * 10^e */
576cc36ccd1SDavid Schultz 
5774848dd08SDavid Schultz 	bd0 = s2b(s0, nd0, nd, y, dplen);
578cc36ccd1SDavid Schultz 
579cc36ccd1SDavid Schultz 	for(;;) {
580cc36ccd1SDavid Schultz 		bd = Balloc(bd0->k);
581cc36ccd1SDavid Schultz 		Bcopy(bd, bd0);
58250dad48bSDavid Schultz 		bb = d2b(dval(&rv), &bbe, &bbbits);	/* rv = bb * 2^bbe */
583cc36ccd1SDavid Schultz 		bs = i2b(1);
584cc36ccd1SDavid Schultz 
585cc36ccd1SDavid Schultz 		if (e >= 0) {
586cc36ccd1SDavid Schultz 			bb2 = bb5 = 0;
587cc36ccd1SDavid Schultz 			bd2 = bd5 = e;
588cc36ccd1SDavid Schultz 			}
589cc36ccd1SDavid Schultz 		else {
590cc36ccd1SDavid Schultz 			bb2 = bb5 = -e;
591cc36ccd1SDavid Schultz 			bd2 = bd5 = 0;
592cc36ccd1SDavid Schultz 			}
593cc36ccd1SDavid Schultz 		if (bbe >= 0)
594cc36ccd1SDavid Schultz 			bb2 += bbe;
595cc36ccd1SDavid Schultz 		else
596cc36ccd1SDavid Schultz 			bd2 -= bbe;
597cc36ccd1SDavid Schultz 		bs2 = bb2;
598cc36ccd1SDavid Schultz #ifdef Honor_FLT_ROUNDS
599ae2cbf4cSDavid Schultz 		if (Rounding != 1)
600cc36ccd1SDavid Schultz 			bs2++;
601cc36ccd1SDavid Schultz #endif
602cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
60350dad48bSDavid Schultz 		Lsb = LSB;
60450dad48bSDavid Schultz 		Lsb1 = 0;
605cc36ccd1SDavid Schultz 		j = bbe - scale;
606cc36ccd1SDavid Schultz 		i = j + bbbits - 1;	/* logb(rv) */
607cc36ccd1SDavid Schultz 		j = P + 1 - bbbits;
60850dad48bSDavid Schultz 		if (i < Emin) {	/* denormal */
60950dad48bSDavid Schultz 			i = Emin - i;
61050dad48bSDavid Schultz 			j -= i;
61150dad48bSDavid Schultz 			if (i < 32)
61250dad48bSDavid Schultz 				Lsb <<= i;
61350dad48bSDavid Schultz 			else
61450dad48bSDavid Schultz 				Lsb1 = Lsb << (i-32);
61550dad48bSDavid Schultz 			}
616cc36ccd1SDavid Schultz #else /*Avoid_Underflow*/
617cc36ccd1SDavid Schultz #ifdef Sudden_Underflow
618cc36ccd1SDavid Schultz #ifdef IBM
619cc36ccd1SDavid Schultz 		j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
620cc36ccd1SDavid Schultz #else
621cc36ccd1SDavid Schultz 		j = P + 1 - bbbits;
622cc36ccd1SDavid Schultz #endif
623cc36ccd1SDavid Schultz #else /*Sudden_Underflow*/
624cc36ccd1SDavid Schultz 		j = bbe;
62550dad48bSDavid Schultz 		i = j + bbbits - 1;	/* logb(&rv) */
626cc36ccd1SDavid Schultz 		if (i < Emin)	/* denormal */
627cc36ccd1SDavid Schultz 			j += P - Emin;
628cc36ccd1SDavid Schultz 		else
629cc36ccd1SDavid Schultz 			j = P + 1 - bbbits;
630cc36ccd1SDavid Schultz #endif /*Sudden_Underflow*/
631cc36ccd1SDavid Schultz #endif /*Avoid_Underflow*/
632cc36ccd1SDavid Schultz 		bb2 += j;
633cc36ccd1SDavid Schultz 		bd2 += j;
634cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
635cc36ccd1SDavid Schultz 		bd2 += scale;
636cc36ccd1SDavid Schultz #endif
637cc36ccd1SDavid Schultz 		i = bb2 < bd2 ? bb2 : bd2;
638cc36ccd1SDavid Schultz 		if (i > bs2)
639cc36ccd1SDavid Schultz 			i = bs2;
640cc36ccd1SDavid Schultz 		if (i > 0) {
641cc36ccd1SDavid Schultz 			bb2 -= i;
642cc36ccd1SDavid Schultz 			bd2 -= i;
643cc36ccd1SDavid Schultz 			bs2 -= i;
644cc36ccd1SDavid Schultz 			}
645cc36ccd1SDavid Schultz 		if (bb5 > 0) {
646cc36ccd1SDavid Schultz 			bs = pow5mult(bs, bb5);
647cc36ccd1SDavid Schultz 			bb1 = mult(bs, bb);
648cc36ccd1SDavid Schultz 			Bfree(bb);
649cc36ccd1SDavid Schultz 			bb = bb1;
650cc36ccd1SDavid Schultz 			}
651cc36ccd1SDavid Schultz 		if (bb2 > 0)
652cc36ccd1SDavid Schultz 			bb = lshift(bb, bb2);
653cc36ccd1SDavid Schultz 		if (bd5 > 0)
654cc36ccd1SDavid Schultz 			bd = pow5mult(bd, bd5);
655cc36ccd1SDavid Schultz 		if (bd2 > 0)
656cc36ccd1SDavid Schultz 			bd = lshift(bd, bd2);
657cc36ccd1SDavid Schultz 		if (bs2 > 0)
658cc36ccd1SDavid Schultz 			bs = lshift(bs, bs2);
659cc36ccd1SDavid Schultz 		delta = diff(bb, bd);
660cc36ccd1SDavid Schultz 		dsign = delta->sign;
661cc36ccd1SDavid Schultz 		delta->sign = 0;
662cc36ccd1SDavid Schultz 		i = cmp(delta, bs);
663cc36ccd1SDavid Schultz #ifdef Honor_FLT_ROUNDS
664ae2cbf4cSDavid Schultz 		if (Rounding != 1) {
665cc36ccd1SDavid Schultz 			if (i < 0) {
666cc36ccd1SDavid Schultz 				/* Error is less than an ulp */
667cc36ccd1SDavid Schultz 				if (!delta->x[0] && delta->wds <= 1) {
668cc36ccd1SDavid Schultz 					/* exact */
669cc36ccd1SDavid Schultz #ifdef SET_INEXACT
670cc36ccd1SDavid Schultz 					inexact = 0;
671cc36ccd1SDavid Schultz #endif
672cc36ccd1SDavid Schultz 					break;
673cc36ccd1SDavid Schultz 					}
674ae2cbf4cSDavid Schultz 				if (Rounding) {
675cc36ccd1SDavid Schultz 					if (dsign) {
67650dad48bSDavid Schultz 						dval(&adj) = 1.;
677cc36ccd1SDavid Schultz 						goto apply_adj;
678cc36ccd1SDavid Schultz 						}
679cc36ccd1SDavid Schultz 					}
680cc36ccd1SDavid Schultz 				else if (!dsign) {
68150dad48bSDavid Schultz 					dval(&adj) = -1.;
68250dad48bSDavid Schultz 					if (!word1(&rv)
68350dad48bSDavid Schultz 					 && !(word0(&rv) & Frac_mask)) {
68450dad48bSDavid Schultz 						y = word0(&rv) & Exp_mask;
685cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
686cc36ccd1SDavid Schultz 						if (!scale || y > 2*P*Exp_msk1)
687cc36ccd1SDavid Schultz #else
688cc36ccd1SDavid Schultz 						if (y)
689cc36ccd1SDavid Schultz #endif
690cc36ccd1SDavid Schultz 						  {
691cc36ccd1SDavid Schultz 						  delta = lshift(delta,Log2P);
692cc36ccd1SDavid Schultz 						  if (cmp(delta, bs) <= 0)
69350dad48bSDavid Schultz 							dval(&adj) = -0.5;
694cc36ccd1SDavid Schultz 						  }
695cc36ccd1SDavid Schultz 						}
696cc36ccd1SDavid Schultz  apply_adj:
697cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
69850dad48bSDavid Schultz 					if (scale && (y = word0(&rv) & Exp_mask)
699cc36ccd1SDavid Schultz 						<= 2*P*Exp_msk1)
70050dad48bSDavid Schultz 					  word0(&adj) += (2*P+1)*Exp_msk1 - y;
701cc36ccd1SDavid Schultz #else
702cc36ccd1SDavid Schultz #ifdef Sudden_Underflow
70350dad48bSDavid Schultz 					if ((word0(&rv) & Exp_mask) <=
704cc36ccd1SDavid Schultz 							P*Exp_msk1) {
70550dad48bSDavid Schultz 						word0(&rv) += P*Exp_msk1;
70650dad48bSDavid Schultz 						dval(&rv) += adj*ulp(&rv);
70750dad48bSDavid Schultz 						word0(&rv) -= P*Exp_msk1;
708cc36ccd1SDavid Schultz 						}
709cc36ccd1SDavid Schultz 					else
710cc36ccd1SDavid Schultz #endif /*Sudden_Underflow*/
711cc36ccd1SDavid Schultz #endif /*Avoid_Underflow*/
71250dad48bSDavid Schultz 					dval(&rv) += adj.d*ulp(&rv);
713cc36ccd1SDavid Schultz 					}
714cc36ccd1SDavid Schultz 				break;
715cc36ccd1SDavid Schultz 				}
71650dad48bSDavid Schultz 			dval(&adj) = ratio(delta, bs);
71750dad48bSDavid Schultz 			if (adj.d < 1.)
71850dad48bSDavid Schultz 				dval(&adj) = 1.;
71950dad48bSDavid Schultz 			if (adj.d <= 0x7ffffffe) {
72050dad48bSDavid Schultz 				/* dval(&adj) = Rounding ? ceil(&adj) : floor(&adj); */
72150dad48bSDavid Schultz 				y = adj.d;
72250dad48bSDavid Schultz 				if (y != adj.d) {
723ae2cbf4cSDavid Schultz 					if (!((Rounding>>1) ^ dsign))
724cc36ccd1SDavid Schultz 						y++;
72550dad48bSDavid Schultz 					dval(&adj) = y;
726cc36ccd1SDavid Schultz 					}
727cc36ccd1SDavid Schultz 				}
728cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
72950dad48bSDavid Schultz 			if (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
73050dad48bSDavid Schultz 				word0(&adj) += (2*P+1)*Exp_msk1 - y;
731cc36ccd1SDavid Schultz #else
732cc36ccd1SDavid Schultz #ifdef Sudden_Underflow
73350dad48bSDavid Schultz 			if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
73450dad48bSDavid Schultz 				word0(&rv) += P*Exp_msk1;
73550dad48bSDavid Schultz 				dval(&adj) *= ulp(&rv);
736cc36ccd1SDavid Schultz 				if (dsign)
73750dad48bSDavid Schultz 					dval(&rv) += adj;
738cc36ccd1SDavid Schultz 				else
73950dad48bSDavid Schultz 					dval(&rv) -= adj;
74050dad48bSDavid Schultz 				word0(&rv) -= P*Exp_msk1;
741cc36ccd1SDavid Schultz 				goto cont;
742cc36ccd1SDavid Schultz 				}
743cc36ccd1SDavid Schultz #endif /*Sudden_Underflow*/
744cc36ccd1SDavid Schultz #endif /*Avoid_Underflow*/
74550dad48bSDavid Schultz 			dval(&adj) *= ulp(&rv);
746ae2cbf4cSDavid Schultz 			if (dsign) {
74750dad48bSDavid Schultz 				if (word0(&rv) == Big0 && word1(&rv) == Big1)
748ae2cbf4cSDavid Schultz 					goto ovfl;
74950dad48bSDavid Schultz 				dval(&rv) += adj.d;
750ae2cbf4cSDavid Schultz 				}
751cc36ccd1SDavid Schultz 			else
75250dad48bSDavid Schultz 				dval(&rv) -= adj.d;
753cc36ccd1SDavid Schultz 			goto cont;
754cc36ccd1SDavid Schultz 			}
755cc36ccd1SDavid Schultz #endif /*Honor_FLT_ROUNDS*/
756cc36ccd1SDavid Schultz 
757cc36ccd1SDavid Schultz 		if (i < 0) {
758cc36ccd1SDavid Schultz 			/* Error is less than half an ulp -- check for
759cc36ccd1SDavid Schultz 			 * special case of mantissa a power of two.
760cc36ccd1SDavid Schultz 			 */
76150dad48bSDavid Schultz 			if (dsign || word1(&rv) || word0(&rv) & Bndry_mask
762cc36ccd1SDavid Schultz #ifdef IEEE_Arith
763cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
76450dad48bSDavid Schultz 			 || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1
765cc36ccd1SDavid Schultz #else
76650dad48bSDavid Schultz 			 || (word0(&rv) & Exp_mask) <= Exp_msk1
767cc36ccd1SDavid Schultz #endif
768cc36ccd1SDavid Schultz #endif
769cc36ccd1SDavid Schultz 				) {
770cc36ccd1SDavid Schultz #ifdef SET_INEXACT
771cc36ccd1SDavid Schultz 				if (!delta->x[0] && delta->wds <= 1)
772cc36ccd1SDavid Schultz 					inexact = 0;
773cc36ccd1SDavid Schultz #endif
774cc36ccd1SDavid Schultz 				break;
775cc36ccd1SDavid Schultz 				}
776cc36ccd1SDavid Schultz 			if (!delta->x[0] && delta->wds <= 1) {
777cc36ccd1SDavid Schultz 				/* exact result */
778cc36ccd1SDavid Schultz #ifdef SET_INEXACT
779cc36ccd1SDavid Schultz 				inexact = 0;
780cc36ccd1SDavid Schultz #endif
781cc36ccd1SDavid Schultz 				break;
782cc36ccd1SDavid Schultz 				}
783cc36ccd1SDavid Schultz 			delta = lshift(delta,Log2P);
784cc36ccd1SDavid Schultz 			if (cmp(delta, bs) > 0)
785cc36ccd1SDavid Schultz 				goto drop_down;
786cc36ccd1SDavid Schultz 			break;
787cc36ccd1SDavid Schultz 			}
788cc36ccd1SDavid Schultz 		if (i == 0) {
789cc36ccd1SDavid Schultz 			/* exactly half-way between */
790cc36ccd1SDavid Schultz 			if (dsign) {
79150dad48bSDavid Schultz 				if ((word0(&rv) & Bndry_mask1) == Bndry_mask1
79250dad48bSDavid Schultz 				 &&  word1(&rv) == (
793cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
79450dad48bSDavid Schultz 			(scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
795cc36ccd1SDavid Schultz 		? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
796cc36ccd1SDavid Schultz #endif
797cc36ccd1SDavid Schultz 						   0xffffffff)) {
798cc36ccd1SDavid Schultz 					/*boundary case -- increment exponent*/
79950dad48bSDavid Schultz 					if (word0(&rv) == Big0 && word1(&rv) == Big1)
80050dad48bSDavid Schultz 						goto ovfl;
80150dad48bSDavid Schultz 					word0(&rv) = (word0(&rv) & Exp_mask)
802cc36ccd1SDavid Schultz 						+ Exp_msk1
803cc36ccd1SDavid Schultz #ifdef IBM
804cc36ccd1SDavid Schultz 						| Exp_msk1 >> 4
805cc36ccd1SDavid Schultz #endif
806cc36ccd1SDavid Schultz 						;
80750dad48bSDavid Schultz 					word1(&rv) = 0;
808cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
809cc36ccd1SDavid Schultz 					dsign = 0;
810cc36ccd1SDavid Schultz #endif
811cc36ccd1SDavid Schultz 					break;
812cc36ccd1SDavid Schultz 					}
813cc36ccd1SDavid Schultz 				}
81450dad48bSDavid Schultz 			else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
815cc36ccd1SDavid Schultz  drop_down:
816cc36ccd1SDavid Schultz 				/* boundary case -- decrement exponent */
817cc36ccd1SDavid Schultz #ifdef Sudden_Underflow /*{{*/
81850dad48bSDavid Schultz 				L = word0(&rv) & Exp_mask;
819cc36ccd1SDavid Schultz #ifdef IBM
820cc36ccd1SDavid Schultz 				if (L <  Exp_msk1)
821cc36ccd1SDavid Schultz #else
822cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
823cc36ccd1SDavid Schultz 				if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
824cc36ccd1SDavid Schultz #else
825cc36ccd1SDavid Schultz 				if (L <= Exp_msk1)
826cc36ccd1SDavid Schultz #endif /*Avoid_Underflow*/
827cc36ccd1SDavid Schultz #endif /*IBM*/
828cc36ccd1SDavid Schultz 					goto undfl;
829cc36ccd1SDavid Schultz 				L -= Exp_msk1;
830cc36ccd1SDavid Schultz #else /*Sudden_Underflow}{*/
831cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
832cc36ccd1SDavid Schultz 				if (scale) {
83350dad48bSDavid Schultz 					L = word0(&rv) & Exp_mask;
834cc36ccd1SDavid Schultz 					if (L <= (2*P+1)*Exp_msk1) {
835cc36ccd1SDavid Schultz 						if (L > (P+2)*Exp_msk1)
836cc36ccd1SDavid Schultz 							/* round even ==> */
837cc36ccd1SDavid Schultz 							/* accept rv */
838cc36ccd1SDavid Schultz 							break;
839cc36ccd1SDavid Schultz 						/* rv = smallest denormal */
840cc36ccd1SDavid Schultz 						goto undfl;
841cc36ccd1SDavid Schultz 						}
842cc36ccd1SDavid Schultz 					}
843cc36ccd1SDavid Schultz #endif /*Avoid_Underflow*/
84450dad48bSDavid Schultz 				L = (word0(&rv) & Exp_mask) - Exp_msk1;
845ae2cbf4cSDavid Schultz #endif /*Sudden_Underflow}}*/
84650dad48bSDavid Schultz 				word0(&rv) = L | Bndry_mask1;
84750dad48bSDavid Schultz 				word1(&rv) = 0xffffffff;
848cc36ccd1SDavid Schultz #ifdef IBM
849cc36ccd1SDavid Schultz 				goto cont;
850cc36ccd1SDavid Schultz #else
851cc36ccd1SDavid Schultz 				break;
852cc36ccd1SDavid Schultz #endif
853cc36ccd1SDavid Schultz 				}
854cc36ccd1SDavid Schultz #ifndef ROUND_BIASED
85550dad48bSDavid Schultz #ifdef Avoid_Underflow
85650dad48bSDavid Schultz 			if (Lsb1) {
85750dad48bSDavid Schultz 				if (!(word0(&rv) & Lsb1))
85850dad48bSDavid Schultz 					break;
85950dad48bSDavid Schultz 				}
86050dad48bSDavid Schultz 			else if (!(word1(&rv) & Lsb))
86150dad48bSDavid Schultz 				break;
86250dad48bSDavid Schultz #else
86350dad48bSDavid Schultz 			if (!(word1(&rv) & LSB))
864cc36ccd1SDavid Schultz 				break;
865cc36ccd1SDavid Schultz #endif
86650dad48bSDavid Schultz #endif
867cc36ccd1SDavid Schultz 			if (dsign)
86850dad48bSDavid Schultz #ifdef Avoid_Underflow
86950dad48bSDavid Schultz 				dval(&rv) += sulp(&rv, scale);
87050dad48bSDavid Schultz #else
87150dad48bSDavid Schultz 				dval(&rv) += ulp(&rv);
87250dad48bSDavid Schultz #endif
873cc36ccd1SDavid Schultz #ifndef ROUND_BIASED
874cc36ccd1SDavid Schultz 			else {
87550dad48bSDavid Schultz #ifdef Avoid_Underflow
87650dad48bSDavid Schultz 				dval(&rv) -= sulp(&rv, scale);
87750dad48bSDavid Schultz #else
87850dad48bSDavid Schultz 				dval(&rv) -= ulp(&rv);
87950dad48bSDavid Schultz #endif
880cc36ccd1SDavid Schultz #ifndef Sudden_Underflow
88150dad48bSDavid Schultz 				if (!dval(&rv))
882cc36ccd1SDavid Schultz 					goto undfl;
883cc36ccd1SDavid Schultz #endif
884cc36ccd1SDavid Schultz 				}
885cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
886cc36ccd1SDavid Schultz 			dsign = 1 - dsign;
887cc36ccd1SDavid Schultz #endif
888cc36ccd1SDavid Schultz #endif
889cc36ccd1SDavid Schultz 			break;
890cc36ccd1SDavid Schultz 			}
891cc36ccd1SDavid Schultz 		if ((aadj = ratio(delta, bs)) <= 2.) {
892cc36ccd1SDavid Schultz 			if (dsign)
89350dad48bSDavid Schultz 				aadj = dval(&aadj1) = 1.;
89450dad48bSDavid Schultz 			else if (word1(&rv) || word0(&rv) & Bndry_mask) {
895cc36ccd1SDavid Schultz #ifndef Sudden_Underflow
89650dad48bSDavid Schultz 				if (word1(&rv) == Tiny1 && !word0(&rv))
897cc36ccd1SDavid Schultz 					goto undfl;
898cc36ccd1SDavid Schultz #endif
899cc36ccd1SDavid Schultz 				aadj = 1.;
90050dad48bSDavid Schultz 				dval(&aadj1) = -1.;
901cc36ccd1SDavid Schultz 				}
902cc36ccd1SDavid Schultz 			else {
903cc36ccd1SDavid Schultz 				/* special case -- power of FLT_RADIX to be */
904cc36ccd1SDavid Schultz 				/* rounded down... */
905cc36ccd1SDavid Schultz 
906cc36ccd1SDavid Schultz 				if (aadj < 2./FLT_RADIX)
907cc36ccd1SDavid Schultz 					aadj = 1./FLT_RADIX;
908cc36ccd1SDavid Schultz 				else
909cc36ccd1SDavid Schultz 					aadj *= 0.5;
91050dad48bSDavid Schultz 				dval(&aadj1) = -aadj;
911cc36ccd1SDavid Schultz 				}
912cc36ccd1SDavid Schultz 			}
913cc36ccd1SDavid Schultz 		else {
914cc36ccd1SDavid Schultz 			aadj *= 0.5;
91550dad48bSDavid Schultz 			dval(&aadj1) = dsign ? aadj : -aadj;
916cc36ccd1SDavid Schultz #ifdef Check_FLT_ROUNDS
917cc36ccd1SDavid Schultz 			switch(Rounding) {
918cc36ccd1SDavid Schultz 				case 2: /* towards +infinity */
91950dad48bSDavid Schultz 					dval(&aadj1) -= 0.5;
920cc36ccd1SDavid Schultz 					break;
921cc36ccd1SDavid Schultz 				case 0: /* towards 0 */
922cc36ccd1SDavid Schultz 				case 3: /* towards -infinity */
92350dad48bSDavid Schultz 					dval(&aadj1) += 0.5;
924cc36ccd1SDavid Schultz 				}
925cc36ccd1SDavid Schultz #else
926cc36ccd1SDavid Schultz 			if (Flt_Rounds == 0)
92750dad48bSDavid Schultz 				dval(&aadj1) += 0.5;
928cc36ccd1SDavid Schultz #endif /*Check_FLT_ROUNDS*/
929cc36ccd1SDavid Schultz 			}
93050dad48bSDavid Schultz 		y = word0(&rv) & Exp_mask;
931cc36ccd1SDavid Schultz 
932cc36ccd1SDavid Schultz 		/* Check for overflow */
933cc36ccd1SDavid Schultz 
934cc36ccd1SDavid Schultz 		if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
93550dad48bSDavid Schultz 			dval(&rv0) = dval(&rv);
93650dad48bSDavid Schultz 			word0(&rv) -= P*Exp_msk1;
93750dad48bSDavid Schultz 			dval(&adj) = dval(&aadj1) * ulp(&rv);
93850dad48bSDavid Schultz 			dval(&rv) += dval(&adj);
93950dad48bSDavid Schultz 			if ((word0(&rv) & Exp_mask) >=
940cc36ccd1SDavid Schultz 					Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
94150dad48bSDavid Schultz 				if (word0(&rv0) == Big0 && word1(&rv0) == Big1)
942cc36ccd1SDavid Schultz 					goto ovfl;
94350dad48bSDavid Schultz 				word0(&rv) = Big0;
94450dad48bSDavid Schultz 				word1(&rv) = Big1;
945cc36ccd1SDavid Schultz 				goto cont;
946cc36ccd1SDavid Schultz 				}
947cc36ccd1SDavid Schultz 			else
94850dad48bSDavid Schultz 				word0(&rv) += P*Exp_msk1;
949cc36ccd1SDavid Schultz 			}
950cc36ccd1SDavid Schultz 		else {
951cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
952cc36ccd1SDavid Schultz 			if (scale && y <= 2*P*Exp_msk1) {
953cc36ccd1SDavid Schultz 				if (aadj <= 0x7fffffff) {
954cc36ccd1SDavid Schultz 					if ((z = aadj) <= 0)
955cc36ccd1SDavid Schultz 						z = 1;
956cc36ccd1SDavid Schultz 					aadj = z;
95750dad48bSDavid Schultz 					dval(&aadj1) = dsign ? aadj : -aadj;
958cc36ccd1SDavid Schultz 					}
95950dad48bSDavid Schultz 				word0(&aadj1) += (2*P+1)*Exp_msk1 - y;
960cc36ccd1SDavid Schultz 				}
96150dad48bSDavid Schultz 			dval(&adj) = dval(&aadj1) * ulp(&rv);
96250dad48bSDavid Schultz 			dval(&rv) += dval(&adj);
963cc36ccd1SDavid Schultz #else
964cc36ccd1SDavid Schultz #ifdef Sudden_Underflow
96550dad48bSDavid Schultz 			if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
96650dad48bSDavid Schultz 				dval(&rv0) = dval(&rv);
96750dad48bSDavid Schultz 				word0(&rv) += P*Exp_msk1;
96850dad48bSDavid Schultz 				dval(&adj) = dval(&aadj1) * ulp(&rv);
96950dad48bSDavid Schultz 				dval(&rv) += adj;
970cc36ccd1SDavid Schultz #ifdef IBM
97150dad48bSDavid Schultz 				if ((word0(&rv) & Exp_mask) <  P*Exp_msk1)
972cc36ccd1SDavid Schultz #else
97350dad48bSDavid Schultz 				if ((word0(&rv) & Exp_mask) <= P*Exp_msk1)
974cc36ccd1SDavid Schultz #endif
975cc36ccd1SDavid Schultz 					{
97650dad48bSDavid Schultz 					if (word0(&rv0) == Tiny0
97750dad48bSDavid Schultz 					 && word1(&rv0) == Tiny1)
978cc36ccd1SDavid Schultz 						goto undfl;
97950dad48bSDavid Schultz 					word0(&rv) = Tiny0;
98050dad48bSDavid Schultz 					word1(&rv) = Tiny1;
981cc36ccd1SDavid Schultz 					goto cont;
982cc36ccd1SDavid Schultz 					}
983cc36ccd1SDavid Schultz 				else
98450dad48bSDavid Schultz 					word0(&rv) -= P*Exp_msk1;
985cc36ccd1SDavid Schultz 				}
986cc36ccd1SDavid Schultz 			else {
98750dad48bSDavid Schultz 				dval(&adj) = dval(&aadj1) * ulp(&rv);
98850dad48bSDavid Schultz 				dval(&rv) += adj;
989cc36ccd1SDavid Schultz 				}
990cc36ccd1SDavid Schultz #else /*Sudden_Underflow*/
99150dad48bSDavid Schultz 			/* Compute dval(&adj) so that the IEEE rounding rules will
99250dad48bSDavid Schultz 			 * correctly round rv + dval(&adj) in some half-way cases.
99350dad48bSDavid Schultz 			 * If rv * ulp(&rv) is denormalized (i.e.,
994cc36ccd1SDavid Schultz 			 * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
995cc36ccd1SDavid Schultz 			 * trouble from bits lost to denormalization;
996cc36ccd1SDavid Schultz 			 * example: 1.2e-307 .
997cc36ccd1SDavid Schultz 			 */
998cc36ccd1SDavid Schultz 			if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
99950dad48bSDavid Schultz 				dval(&aadj1) = (double)(int)(aadj + 0.5);
1000cc36ccd1SDavid Schultz 				if (!dsign)
100150dad48bSDavid Schultz 					dval(&aadj1) = -dval(&aadj1);
1002cc36ccd1SDavid Schultz 				}
100350dad48bSDavid Schultz 			dval(&adj) = dval(&aadj1) * ulp(&rv);
100450dad48bSDavid Schultz 			dval(&rv) += adj;
1005cc36ccd1SDavid Schultz #endif /*Sudden_Underflow*/
1006cc36ccd1SDavid Schultz #endif /*Avoid_Underflow*/
1007cc36ccd1SDavid Schultz 			}
100850dad48bSDavid Schultz 		z = word0(&rv) & Exp_mask;
1009cc36ccd1SDavid Schultz #ifndef SET_INEXACT
1010cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
1011cc36ccd1SDavid Schultz 		if (!scale)
1012cc36ccd1SDavid Schultz #endif
1013cc36ccd1SDavid Schultz 		if (y == z) {
1014cc36ccd1SDavid Schultz 			/* Can we stop now? */
1015cc36ccd1SDavid Schultz 			L = (Long)aadj;
1016cc36ccd1SDavid Schultz 			aadj -= L;
1017cc36ccd1SDavid Schultz 			/* The tolerances below are conservative. */
101850dad48bSDavid Schultz 			if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) {
1019cc36ccd1SDavid Schultz 				if (aadj < .4999999 || aadj > .5000001)
1020cc36ccd1SDavid Schultz 					break;
1021cc36ccd1SDavid Schultz 				}
1022cc36ccd1SDavid Schultz 			else if (aadj < .4999999/FLT_RADIX)
1023cc36ccd1SDavid Schultz 				break;
1024cc36ccd1SDavid Schultz 			}
1025cc36ccd1SDavid Schultz #endif
1026cc36ccd1SDavid Schultz  cont:
1027cc36ccd1SDavid Schultz 		Bfree(bb);
1028cc36ccd1SDavid Schultz 		Bfree(bd);
1029cc36ccd1SDavid Schultz 		Bfree(bs);
1030cc36ccd1SDavid Schultz 		Bfree(delta);
1031cc36ccd1SDavid Schultz 		}
103250dad48bSDavid Schultz 	Bfree(bb);
103350dad48bSDavid Schultz 	Bfree(bd);
103450dad48bSDavid Schultz 	Bfree(bs);
103550dad48bSDavid Schultz 	Bfree(bd0);
103650dad48bSDavid Schultz 	Bfree(delta);
1037cc36ccd1SDavid Schultz #ifdef SET_INEXACT
1038cc36ccd1SDavid Schultz 	if (inexact) {
1039cc36ccd1SDavid Schultz 		if (!oldinexact) {
104050dad48bSDavid Schultz 			word0(&rv0) = Exp_1 + (70 << Exp_shift);
104150dad48bSDavid Schultz 			word1(&rv0) = 0;
104250dad48bSDavid Schultz 			dval(&rv0) += 1.;
1043cc36ccd1SDavid Schultz 			}
1044cc36ccd1SDavid Schultz 		}
1045cc36ccd1SDavid Schultz 	else if (!oldinexact)
1046cc36ccd1SDavid Schultz 		clear_inexact();
1047cc36ccd1SDavid Schultz #endif
1048cc36ccd1SDavid Schultz #ifdef Avoid_Underflow
1049cc36ccd1SDavid Schultz 	if (scale) {
105050dad48bSDavid Schultz 		word0(&rv0) = Exp_1 - 2*P*Exp_msk1;
105150dad48bSDavid Schultz 		word1(&rv0) = 0;
105250dad48bSDavid Schultz 		dval(&rv) *= dval(&rv0);
1053cc36ccd1SDavid Schultz #ifndef NO_ERRNO
1054cc36ccd1SDavid Schultz 		/* try to avoid the bug of testing an 8087 register value */
10554848dd08SDavid Schultz #ifdef IEEE_Arith
105650dad48bSDavid Schultz 		if (!(word0(&rv) & Exp_mask))
10574848dd08SDavid Schultz #else
105850dad48bSDavid Schultz 		if (word0(&rv) == 0 && word1(&rv) == 0)
10594848dd08SDavid Schultz #endif
1060cc36ccd1SDavid Schultz 			errno = ERANGE;
1061cc36ccd1SDavid Schultz #endif
1062cc36ccd1SDavid Schultz 		}
1063cc36ccd1SDavid Schultz #endif /* Avoid_Underflow */
1064cc36ccd1SDavid Schultz #ifdef SET_INEXACT
106550dad48bSDavid Schultz 	if (inexact && !(word0(&rv) & Exp_mask)) {
1066cc36ccd1SDavid Schultz 		/* set underflow bit */
106750dad48bSDavid Schultz 		dval(&rv0) = 1e-300;
106850dad48bSDavid Schultz 		dval(&rv0) *= dval(&rv0);
1069cc36ccd1SDavid Schultz 		}
1070cc36ccd1SDavid Schultz #endif
1071cc36ccd1SDavid Schultz  ret:
1072cc36ccd1SDavid Schultz 	if (se)
1073cc36ccd1SDavid Schultz 		*se = (char *)s;
107450dad48bSDavid Schultz 	return sign ? -dval(&rv) : dval(&rv);
1075cc36ccd1SDavid Schultz 	}
1076cc36ccd1SDavid Schultz 
1077*3c87aa1dSDavid Chisnall  double
strtod(s00,se,loc)1078*3c87aa1dSDavid Chisnall strtod
1079*3c87aa1dSDavid Chisnall #ifdef KR_headers
1080*3c87aa1dSDavid Chisnall 	(s00, se, loc) CONST char *s00; char **se; locale_t
1081*3c87aa1dSDavid Chisnall #else
1082*3c87aa1dSDavid Chisnall 	(CONST char *s00, char **se)
1083*3c87aa1dSDavid Chisnall #endif
1084*3c87aa1dSDavid Chisnall {
1085*3c87aa1dSDavid Chisnall 	return strtod_l(s00, se, __get_locale());
1086*3c87aa1dSDavid Chisnall }
1087*3c87aa1dSDavid Chisnall 
1088