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