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
32cc36ccd1SDavid Schultz #include "gdtoaimp.h"
33cc36ccd1SDavid Schultz
34cc36ccd1SDavid Schultz #ifdef USE_LOCALE
35cc36ccd1SDavid Schultz #include "locale.h"
36cc36ccd1SDavid Schultz #endif
37cc36ccd1SDavid Schultz
38cc36ccd1SDavid Schultz static CONST int
39cc36ccd1SDavid Schultz fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21,
40cc36ccd1SDavid Schultz 24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
41cc36ccd1SDavid Schultz 47, 49, 52
42cc36ccd1SDavid Schultz #ifdef VAX
43cc36ccd1SDavid Schultz , 54, 56
44cc36ccd1SDavid Schultz #endif
45cc36ccd1SDavid Schultz };
46cc36ccd1SDavid Schultz
47cc36ccd1SDavid Schultz Bigint *
48cc36ccd1SDavid Schultz #ifdef KR_headers
increment(b)49cc36ccd1SDavid Schultz increment(b) Bigint *b;
50cc36ccd1SDavid Schultz #else
51cc36ccd1SDavid Schultz increment(Bigint *b)
52cc36ccd1SDavid Schultz #endif
53cc36ccd1SDavid Schultz {
54cc36ccd1SDavid Schultz ULong *x, *xe;
55cc36ccd1SDavid Schultz Bigint *b1;
56cc36ccd1SDavid Schultz #ifdef Pack_16
57cc36ccd1SDavid Schultz ULong carry = 1, y;
58cc36ccd1SDavid Schultz #endif
59cc36ccd1SDavid Schultz
60cc36ccd1SDavid Schultz x = b->x;
61cc36ccd1SDavid Schultz xe = x + b->wds;
62cc36ccd1SDavid Schultz #ifdef Pack_32
63cc36ccd1SDavid Schultz do {
64cc36ccd1SDavid Schultz if (*x < (ULong)0xffffffffL) {
65cc36ccd1SDavid Schultz ++*x;
66cc36ccd1SDavid Schultz return b;
67cc36ccd1SDavid Schultz }
68cc36ccd1SDavid Schultz *x++ = 0;
69cc36ccd1SDavid Schultz } while(x < xe);
70cc36ccd1SDavid Schultz #else
71cc36ccd1SDavid Schultz do {
72cc36ccd1SDavid Schultz y = *x + carry;
73cc36ccd1SDavid Schultz carry = y >> 16;
74cc36ccd1SDavid Schultz *x++ = y & 0xffff;
75cc36ccd1SDavid Schultz if (!carry)
76cc36ccd1SDavid Schultz return b;
77cc36ccd1SDavid Schultz } while(x < xe);
78cc36ccd1SDavid Schultz if (carry)
79cc36ccd1SDavid Schultz #endif
80cc36ccd1SDavid Schultz {
81cc36ccd1SDavid Schultz if (b->wds >= b->maxwds) {
82cc36ccd1SDavid Schultz b1 = Balloc(b->k+1);
83cc36ccd1SDavid Schultz Bcopy(b1,b);
84cc36ccd1SDavid Schultz Bfree(b);
85cc36ccd1SDavid Schultz b = b1;
86cc36ccd1SDavid Schultz }
87cc36ccd1SDavid Schultz b->x[b->wds++] = 1;
88cc36ccd1SDavid Schultz }
89cc36ccd1SDavid Schultz return b;
90cc36ccd1SDavid Schultz }
91cc36ccd1SDavid Schultz
92ae2cbf4cSDavid Schultz void
93cc36ccd1SDavid Schultz #ifdef KR_headers
decrement(b)94cc36ccd1SDavid Schultz decrement(b) Bigint *b;
95cc36ccd1SDavid Schultz #else
96cc36ccd1SDavid Schultz decrement(Bigint *b)
97cc36ccd1SDavid Schultz #endif
98cc36ccd1SDavid Schultz {
99cc36ccd1SDavid Schultz ULong *x, *xe;
100cc36ccd1SDavid Schultz #ifdef Pack_16
101cc36ccd1SDavid Schultz ULong borrow = 1, y;
102cc36ccd1SDavid Schultz #endif
103cc36ccd1SDavid Schultz
104cc36ccd1SDavid Schultz x = b->x;
105cc36ccd1SDavid Schultz xe = x + b->wds;
106cc36ccd1SDavid Schultz #ifdef Pack_32
107cc36ccd1SDavid Schultz do {
108cc36ccd1SDavid Schultz if (*x) {
109cc36ccd1SDavid Schultz --*x;
110cc36ccd1SDavid Schultz break;
111cc36ccd1SDavid Schultz }
112cc36ccd1SDavid Schultz *x++ = 0xffffffffL;
113cc36ccd1SDavid Schultz }
114cc36ccd1SDavid Schultz while(x < xe);
115cc36ccd1SDavid Schultz #else
116cc36ccd1SDavid Schultz do {
117cc36ccd1SDavid Schultz y = *x - borrow;
118cc36ccd1SDavid Schultz borrow = (y & 0x10000) >> 16;
119cc36ccd1SDavid Schultz *x++ = y & 0xffff;
120cc36ccd1SDavid Schultz } while(borrow && x < xe);
121cc36ccd1SDavid Schultz #endif
122cc36ccd1SDavid Schultz }
123cc36ccd1SDavid Schultz
124cc36ccd1SDavid Schultz static int
125cc36ccd1SDavid Schultz #ifdef KR_headers
all_on(b,n)126cc36ccd1SDavid Schultz all_on(b, n) Bigint *b; int n;
127cc36ccd1SDavid Schultz #else
128cc36ccd1SDavid Schultz all_on(Bigint *b, int n)
129cc36ccd1SDavid Schultz #endif
130cc36ccd1SDavid Schultz {
131cc36ccd1SDavid Schultz ULong *x, *xe;
132cc36ccd1SDavid Schultz
133cc36ccd1SDavid Schultz x = b->x;
134cc36ccd1SDavid Schultz xe = x + (n >> kshift);
135cc36ccd1SDavid Schultz while(x < xe)
136cc36ccd1SDavid Schultz if ((*x++ & ALL_ON) != ALL_ON)
137cc36ccd1SDavid Schultz return 0;
138cc36ccd1SDavid Schultz if (n &= kmask)
139cc36ccd1SDavid Schultz return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON;
140cc36ccd1SDavid Schultz return 1;
141cc36ccd1SDavid Schultz }
142cc36ccd1SDavid Schultz
143cc36ccd1SDavid Schultz Bigint *
144cc36ccd1SDavid Schultz #ifdef KR_headers
set_ones(b,n)145cc36ccd1SDavid Schultz set_ones(b, n) Bigint *b; int n;
146cc36ccd1SDavid Schultz #else
147cc36ccd1SDavid Schultz set_ones(Bigint *b, int n)
148cc36ccd1SDavid Schultz #endif
149cc36ccd1SDavid Schultz {
150cc36ccd1SDavid Schultz int k;
151cc36ccd1SDavid Schultz ULong *x, *xe;
152cc36ccd1SDavid Schultz
153cc36ccd1SDavid Schultz k = (n + ((1 << kshift) - 1)) >> kshift;
154cc36ccd1SDavid Schultz if (b->k < k) {
155cc36ccd1SDavid Schultz Bfree(b);
156cc36ccd1SDavid Schultz b = Balloc(k);
157cc36ccd1SDavid Schultz }
158cc36ccd1SDavid Schultz k = n >> kshift;
159cc36ccd1SDavid Schultz if (n &= kmask)
160cc36ccd1SDavid Schultz k++;
161cc36ccd1SDavid Schultz b->wds = k;
162cc36ccd1SDavid Schultz x = b->x;
163cc36ccd1SDavid Schultz xe = x + k;
164cc36ccd1SDavid Schultz while(x < xe)
165cc36ccd1SDavid Schultz *x++ = ALL_ON;
166cc36ccd1SDavid Schultz if (n)
167cc36ccd1SDavid Schultz x[-1] >>= ULbits - n;
168cc36ccd1SDavid Schultz return b;
169cc36ccd1SDavid Schultz }
170cc36ccd1SDavid Schultz
171cc36ccd1SDavid Schultz static int
rvOK(d,fpi,exp,bits,exact,rd,irv)172cc36ccd1SDavid Schultz rvOK
173cc36ccd1SDavid Schultz #ifdef KR_headers
174cc36ccd1SDavid Schultz (d, fpi, exp, bits, exact, rd, irv)
17550dad48bSDavid Schultz U *d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
176cc36ccd1SDavid Schultz #else
17750dad48bSDavid Schultz (U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
178cc36ccd1SDavid Schultz #endif
179cc36ccd1SDavid Schultz {
180cc36ccd1SDavid Schultz Bigint *b;
181cc36ccd1SDavid Schultz ULong carry, inex, lostbits;
182cc36ccd1SDavid Schultz int bdif, e, j, k, k1, nb, rv;
183cc36ccd1SDavid Schultz
184cc36ccd1SDavid Schultz carry = rv = 0;
18550dad48bSDavid Schultz b = d2b(dval(d), &e, &bdif);
186cc36ccd1SDavid Schultz bdif -= nb = fpi->nbits;
187cc36ccd1SDavid Schultz e += bdif;
188cc36ccd1SDavid Schultz if (bdif <= 0) {
189cc36ccd1SDavid Schultz if (exact)
190cc36ccd1SDavid Schultz goto trunc;
191cc36ccd1SDavid Schultz goto ret;
192cc36ccd1SDavid Schultz }
193cc36ccd1SDavid Schultz if (P == nb) {
194cc36ccd1SDavid Schultz if (
195cc36ccd1SDavid Schultz #ifndef IMPRECISE_INEXACT
196cc36ccd1SDavid Schultz exact &&
197cc36ccd1SDavid Schultz #endif
198cc36ccd1SDavid Schultz fpi->rounding ==
199cc36ccd1SDavid Schultz #ifdef RND_PRODQUOT
200cc36ccd1SDavid Schultz FPI_Round_near
201cc36ccd1SDavid Schultz #else
202cc36ccd1SDavid Schultz Flt_Rounds
203cc36ccd1SDavid Schultz #endif
204cc36ccd1SDavid Schultz ) goto trunc;
205cc36ccd1SDavid Schultz goto ret;
206cc36ccd1SDavid Schultz }
207cc36ccd1SDavid Schultz switch(rd) {
208ae2cbf4cSDavid Schultz case 1: /* round down (toward -Infinity) */
209cc36ccd1SDavid Schultz goto trunc;
210ae2cbf4cSDavid Schultz case 2: /* round up (toward +Infinity) */
211cc36ccd1SDavid Schultz break;
212cc36ccd1SDavid Schultz default: /* round near */
213cc36ccd1SDavid Schultz k = bdif - 1;
214cc36ccd1SDavid Schultz if (k < 0)
215cc36ccd1SDavid Schultz goto trunc;
216cc36ccd1SDavid Schultz if (!k) {
217cc36ccd1SDavid Schultz if (!exact)
218cc36ccd1SDavid Schultz goto ret;
219cc36ccd1SDavid Schultz if (b->x[0] & 2)
220cc36ccd1SDavid Schultz break;
221cc36ccd1SDavid Schultz goto trunc;
222cc36ccd1SDavid Schultz }
223cc36ccd1SDavid Schultz if (b->x[k>>kshift] & ((ULong)1 << (k & kmask)))
224cc36ccd1SDavid Schultz break;
225cc36ccd1SDavid Schultz goto trunc;
226cc36ccd1SDavid Schultz }
227cc36ccd1SDavid Schultz /* "break" cases: round up 1 bit, then truncate; bdif > 0 */
228cc36ccd1SDavid Schultz carry = 1;
229cc36ccd1SDavid Schultz trunc:
230cc36ccd1SDavid Schultz inex = lostbits = 0;
231cc36ccd1SDavid Schultz if (bdif > 0) {
232cc36ccd1SDavid Schultz if ( (lostbits = any_on(b, bdif)) !=0)
233cc36ccd1SDavid Schultz inex = STRTOG_Inexlo;
234cc36ccd1SDavid Schultz rshift(b, bdif);
235cc36ccd1SDavid Schultz if (carry) {
236cc36ccd1SDavid Schultz inex = STRTOG_Inexhi;
237cc36ccd1SDavid Schultz b = increment(b);
238cc36ccd1SDavid Schultz if ( (j = nb & kmask) !=0)
239c88250a5SDavid Schultz j = ULbits - j;
240cc36ccd1SDavid Schultz if (hi0bits(b->x[b->wds - 1]) != j) {
241cc36ccd1SDavid Schultz if (!lostbits)
242cc36ccd1SDavid Schultz lostbits = b->x[0] & 1;
243cc36ccd1SDavid Schultz rshift(b, 1);
244cc36ccd1SDavid Schultz e++;
245cc36ccd1SDavid Schultz }
246cc36ccd1SDavid Schultz }
247cc36ccd1SDavid Schultz }
248cc36ccd1SDavid Schultz else if (bdif < 0)
249cc36ccd1SDavid Schultz b = lshift(b, -bdif);
250cc36ccd1SDavid Schultz if (e < fpi->emin) {
251cc36ccd1SDavid Schultz k = fpi->emin - e;
252cc36ccd1SDavid Schultz e = fpi->emin;
253cc36ccd1SDavid Schultz if (k > nb || fpi->sudden_underflow) {
254cc36ccd1SDavid Schultz b->wds = inex = 0;
255cc36ccd1SDavid Schultz *irv = STRTOG_Underflow | STRTOG_Inexlo;
256cc36ccd1SDavid Schultz }
257cc36ccd1SDavid Schultz else {
258cc36ccd1SDavid Schultz k1 = k - 1;
259cc36ccd1SDavid Schultz if (k1 > 0 && !lostbits)
260cc36ccd1SDavid Schultz lostbits = any_on(b, k1);
261cc36ccd1SDavid Schultz if (!lostbits && !exact)
262cc36ccd1SDavid Schultz goto ret;
263cc36ccd1SDavid Schultz lostbits |=
264cc36ccd1SDavid Schultz carry = b->x[k1>>kshift] & (1 << (k1 & kmask));
265cc36ccd1SDavid Schultz rshift(b, k);
266cc36ccd1SDavid Schultz *irv = STRTOG_Denormal;
267cc36ccd1SDavid Schultz if (carry) {
268cc36ccd1SDavid Schultz b = increment(b);
269cc36ccd1SDavid Schultz inex = STRTOG_Inexhi | STRTOG_Underflow;
270cc36ccd1SDavid Schultz }
271cc36ccd1SDavid Schultz else if (lostbits)
272cc36ccd1SDavid Schultz inex = STRTOG_Inexlo | STRTOG_Underflow;
273cc36ccd1SDavid Schultz }
274cc36ccd1SDavid Schultz }
275cc36ccd1SDavid Schultz else if (e > fpi->emax) {
276cc36ccd1SDavid Schultz e = fpi->emax + 1;
277cc36ccd1SDavid Schultz *irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
278cc36ccd1SDavid Schultz #ifndef NO_ERRNO
279cc36ccd1SDavid Schultz errno = ERANGE;
280cc36ccd1SDavid Schultz #endif
281cc36ccd1SDavid Schultz b->wds = inex = 0;
282cc36ccd1SDavid Schultz }
283cc36ccd1SDavid Schultz *exp = e;
284cc36ccd1SDavid Schultz copybits(bits, nb, b);
285cc36ccd1SDavid Schultz *irv |= inex;
286cc36ccd1SDavid Schultz rv = 1;
287cc36ccd1SDavid Schultz ret:
288cc36ccd1SDavid Schultz Bfree(b);
289cc36ccd1SDavid Schultz return rv;
290cc36ccd1SDavid Schultz }
291cc36ccd1SDavid Schultz
292cc36ccd1SDavid Schultz static int
293cc36ccd1SDavid Schultz #ifdef KR_headers
mantbits(d)29450dad48bSDavid Schultz mantbits(d) U *d;
295cc36ccd1SDavid Schultz #else
29650dad48bSDavid Schultz mantbits(U *d)
297cc36ccd1SDavid Schultz #endif
298cc36ccd1SDavid Schultz {
299cc36ccd1SDavid Schultz ULong L;
300cc36ccd1SDavid Schultz #ifdef VAX
301cc36ccd1SDavid Schultz L = word1(d) << 16 | word1(d) >> 16;
302cc36ccd1SDavid Schultz if (L)
303cc36ccd1SDavid Schultz #else
304cc36ccd1SDavid Schultz if ( (L = word1(d)) !=0)
305cc36ccd1SDavid Schultz #endif
306cc36ccd1SDavid Schultz return P - lo0bits(&L);
307cc36ccd1SDavid Schultz #ifdef VAX
308cc36ccd1SDavid Schultz L = word0(d) << 16 | word0(d) >> 16 | Exp_msk11;
309cc36ccd1SDavid Schultz #else
310cc36ccd1SDavid Schultz L = word0(d) | Exp_msk1;
311cc36ccd1SDavid Schultz #endif
312cc36ccd1SDavid Schultz return P - 32 - lo0bits(&L);
313cc36ccd1SDavid Schultz }
314cc36ccd1SDavid Schultz
315cc36ccd1SDavid Schultz int
strtodg_l(s00,se,fpi,exp,bits,loc)316*3c87aa1dSDavid Chisnall strtodg_l
317cc36ccd1SDavid Schultz #ifdef KR_headers
318*3c87aa1dSDavid Chisnall (s00, se, fpi, exp, bits, loc)
319*3c87aa1dSDavid Chisnall CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; locale_t loc;
320cc36ccd1SDavid Schultz #else
321*3c87aa1dSDavid Chisnall (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits, locale_t loc)
322cc36ccd1SDavid Schultz #endif
323cc36ccd1SDavid Schultz {
324cc36ccd1SDavid Schultz int abe, abits, asub;
325c88250a5SDavid Schultz int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm;
326c88250a5SDavid Schultz int dsign, e, e1, e2, emin, esign, finished, i, inex, irv;
327cc36ccd1SDavid Schultz int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
328cc36ccd1SDavid Schultz int sudden_underflow;
329cc36ccd1SDavid Schultz CONST char *s, *s0, *s1;
33050dad48bSDavid Schultz double adj0, tol;
331cc36ccd1SDavid Schultz Long L;
33250dad48bSDavid Schultz U adj, rv;
333ae2cbf4cSDavid Schultz ULong *b, *be, y, z;
334cc36ccd1SDavid Schultz Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
3354848dd08SDavid Schultz #ifdef USE_LOCALE /*{{*/
3364848dd08SDavid Schultz #ifdef NO_LOCALE_CACHE
337*3c87aa1dSDavid Chisnall char *decimalpoint = localeconv_l(loc)->decimal_point;
3384848dd08SDavid Schultz int dplen = strlen(decimalpoint);
3394848dd08SDavid Schultz #else
3404848dd08SDavid Schultz char *decimalpoint;
3414848dd08SDavid Schultz static char *decimalpoint_cache;
3424848dd08SDavid Schultz static int dplen;
3434848dd08SDavid Schultz if (!(s0 = decimalpoint_cache)) {
344*3c87aa1dSDavid Chisnall s0 = localeconv_l(loc)->decimal_point;
34550dad48bSDavid Schultz if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
3464848dd08SDavid Schultz strcpy(decimalpoint_cache, s0);
3474848dd08SDavid Schultz s0 = decimalpoint_cache;
3484848dd08SDavid Schultz }
3494848dd08SDavid Schultz dplen = strlen(s0);
3504848dd08SDavid Schultz }
3514848dd08SDavid Schultz decimalpoint = (char*)s0;
3524848dd08SDavid Schultz #endif /*NO_LOCALE_CACHE*/
3534848dd08SDavid Schultz #else /*USE_LOCALE}{*/
3544848dd08SDavid Schultz #define dplen 1
3554848dd08SDavid Schultz #endif /*USE_LOCALE}}*/
356cc36ccd1SDavid Schultz
357cc36ccd1SDavid Schultz irv = STRTOG_Zero;
358cc36ccd1SDavid Schultz denorm = sign = nz0 = nz = 0;
35950dad48bSDavid Schultz dval(&rv) = 0.;
360cc36ccd1SDavid Schultz rvb = 0;
361cc36ccd1SDavid Schultz nbits = fpi->nbits;
362cc36ccd1SDavid Schultz for(s = s00;;s++) switch(*s) {
363cc36ccd1SDavid Schultz case '-':
364cc36ccd1SDavid Schultz sign = 1;
365cc36ccd1SDavid Schultz /* no break */
366cc36ccd1SDavid Schultz case '+':
367cc36ccd1SDavid Schultz if (*++s)
368cc36ccd1SDavid Schultz goto break2;
369cc36ccd1SDavid Schultz /* no break */
370cc36ccd1SDavid Schultz case 0:
371cc36ccd1SDavid Schultz sign = 0;
372cc36ccd1SDavid Schultz irv = STRTOG_NoNumber;
373cc36ccd1SDavid Schultz s = s00;
374cc36ccd1SDavid Schultz goto ret;
375cc36ccd1SDavid Schultz case '\t':
376cc36ccd1SDavid Schultz case '\n':
377cc36ccd1SDavid Schultz case '\v':
378cc36ccd1SDavid Schultz case '\f':
379cc36ccd1SDavid Schultz case '\r':
380cc36ccd1SDavid Schultz case ' ':
381cc36ccd1SDavid Schultz continue;
382cc36ccd1SDavid Schultz default:
383cc36ccd1SDavid Schultz goto break2;
384cc36ccd1SDavid Schultz }
385cc36ccd1SDavid Schultz break2:
386cc36ccd1SDavid Schultz if (*s == '0') {
387cc36ccd1SDavid Schultz #ifndef NO_HEX_FP
388cc36ccd1SDavid Schultz switch(s[1]) {
389cc36ccd1SDavid Schultz case 'x':
390cc36ccd1SDavid Schultz case 'X':
391cc36ccd1SDavid Schultz irv = gethex(&s, fpi, exp, &rvb, sign);
392cc36ccd1SDavid Schultz if (irv == STRTOG_NoNumber) {
393cc36ccd1SDavid Schultz s = s00;
394cc36ccd1SDavid Schultz sign = 0;
395cc36ccd1SDavid Schultz }
396cc36ccd1SDavid Schultz goto ret;
397cc36ccd1SDavid Schultz }
398cc36ccd1SDavid Schultz #endif
399cc36ccd1SDavid Schultz nz0 = 1;
400cc36ccd1SDavid Schultz while(*++s == '0') ;
401cc36ccd1SDavid Schultz if (!*s)
402cc36ccd1SDavid Schultz goto ret;
403cc36ccd1SDavid Schultz }
404cc36ccd1SDavid Schultz sudden_underflow = fpi->sudden_underflow;
405cc36ccd1SDavid Schultz s0 = s;
406cc36ccd1SDavid Schultz y = z = 0;
407c88250a5SDavid Schultz for(decpt = nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
408cc36ccd1SDavid Schultz if (nd < 9)
409cc36ccd1SDavid Schultz y = 10*y + c - '0';
410cc36ccd1SDavid Schultz else if (nd < 16)
411cc36ccd1SDavid Schultz z = 10*z + c - '0';
412cc36ccd1SDavid Schultz nd0 = nd;
413cc36ccd1SDavid Schultz #ifdef USE_LOCALE
4144848dd08SDavid Schultz if (c == *decimalpoint) {
4154848dd08SDavid Schultz for(i = 1; decimalpoint[i]; ++i)
4164848dd08SDavid Schultz if (s[i] != decimalpoint[i])
4174848dd08SDavid Schultz goto dig_done;
4184848dd08SDavid Schultz s += i;
4194848dd08SDavid Schultz c = *s;
42084781d47SDavid Schultz #else
4214848dd08SDavid Schultz if (c == '.') {
422cc36ccd1SDavid Schultz c = *++s;
4234848dd08SDavid Schultz #endif
4244848dd08SDavid Schultz decpt = 1;
425cc36ccd1SDavid Schultz if (!nd) {
426cc36ccd1SDavid Schultz for(; c == '0'; c = *++s)
427cc36ccd1SDavid Schultz nz++;
428cc36ccd1SDavid Schultz if (c > '0' && c <= '9') {
429cc36ccd1SDavid Schultz s0 = s;
430cc36ccd1SDavid Schultz nf += nz;
431cc36ccd1SDavid Schultz nz = 0;
432cc36ccd1SDavid Schultz goto have_dig;
433cc36ccd1SDavid Schultz }
434cc36ccd1SDavid Schultz goto dig_done;
435cc36ccd1SDavid Schultz }
436cc36ccd1SDavid Schultz for(; c >= '0' && c <= '9'; c = *++s) {
437cc36ccd1SDavid Schultz have_dig:
438cc36ccd1SDavid Schultz nz++;
439cc36ccd1SDavid Schultz if (c -= '0') {
440cc36ccd1SDavid Schultz nf += nz;
441cc36ccd1SDavid Schultz for(i = 1; i < nz; i++)
442cc36ccd1SDavid Schultz if (nd++ < 9)
443cc36ccd1SDavid Schultz y *= 10;
444cc36ccd1SDavid Schultz else if (nd <= DBL_DIG + 1)
445cc36ccd1SDavid Schultz z *= 10;
446cc36ccd1SDavid Schultz if (nd++ < 9)
447cc36ccd1SDavid Schultz y = 10*y + c;
448cc36ccd1SDavid Schultz else if (nd <= DBL_DIG + 1)
449cc36ccd1SDavid Schultz z = 10*z + c;
450cc36ccd1SDavid Schultz nz = 0;
451cc36ccd1SDavid Schultz }
452cc36ccd1SDavid Schultz }
4534848dd08SDavid Schultz }/*}*/
454cc36ccd1SDavid Schultz dig_done:
455cc36ccd1SDavid Schultz e = 0;
456cc36ccd1SDavid Schultz if (c == 'e' || c == 'E') {
457cc36ccd1SDavid Schultz if (!nd && !nz && !nz0) {
458cc36ccd1SDavid Schultz irv = STRTOG_NoNumber;
459cc36ccd1SDavid Schultz s = s00;
460cc36ccd1SDavid Schultz goto ret;
461cc36ccd1SDavid Schultz }
462cc36ccd1SDavid Schultz s00 = s;
463cc36ccd1SDavid Schultz esign = 0;
464cc36ccd1SDavid Schultz switch(c = *++s) {
465cc36ccd1SDavid Schultz case '-':
466cc36ccd1SDavid Schultz esign = 1;
467cc36ccd1SDavid Schultz case '+':
468cc36ccd1SDavid Schultz c = *++s;
469cc36ccd1SDavid Schultz }
470cc36ccd1SDavid Schultz if (c >= '0' && c <= '9') {
471cc36ccd1SDavid Schultz while(c == '0')
472cc36ccd1SDavid Schultz c = *++s;
473cc36ccd1SDavid Schultz if (c > '0' && c <= '9') {
474cc36ccd1SDavid Schultz L = c - '0';
475cc36ccd1SDavid Schultz s1 = s;
476cc36ccd1SDavid Schultz while((c = *++s) >= '0' && c <= '9')
477cc36ccd1SDavid Schultz L = 10*L + c - '0';
478cc36ccd1SDavid Schultz if (s - s1 > 8 || L > 19999)
479cc36ccd1SDavid Schultz /* Avoid confusion from exponents
480cc36ccd1SDavid Schultz * so large that e might overflow.
481cc36ccd1SDavid Schultz */
482cc36ccd1SDavid Schultz e = 19999; /* safe for 16 bit ints */
483cc36ccd1SDavid Schultz else
484cc36ccd1SDavid Schultz e = (int)L;
485cc36ccd1SDavid Schultz if (esign)
486cc36ccd1SDavid Schultz e = -e;
487cc36ccd1SDavid Schultz }
488cc36ccd1SDavid Schultz else
489cc36ccd1SDavid Schultz e = 0;
490cc36ccd1SDavid Schultz }
491cc36ccd1SDavid Schultz else
492cc36ccd1SDavid Schultz s = s00;
493cc36ccd1SDavid Schultz }
494cc36ccd1SDavid Schultz if (!nd) {
495cc36ccd1SDavid Schultz if (!nz && !nz0) {
496cc36ccd1SDavid Schultz #ifdef INFNAN_CHECK
497cc36ccd1SDavid Schultz /* Check for Nan and Infinity */
498c88250a5SDavid Schultz if (!decpt)
499cc36ccd1SDavid Schultz switch(c) {
500cc36ccd1SDavid Schultz case 'i':
501cc36ccd1SDavid Schultz case 'I':
502cc36ccd1SDavid Schultz if (match(&s,"nf")) {
503cc36ccd1SDavid Schultz --s;
504cc36ccd1SDavid Schultz if (!match(&s,"inity"))
505cc36ccd1SDavid Schultz ++s;
506cc36ccd1SDavid Schultz irv = STRTOG_Infinite;
507cc36ccd1SDavid Schultz goto infnanexp;
508cc36ccd1SDavid Schultz }
509cc36ccd1SDavid Schultz break;
510cc36ccd1SDavid Schultz case 'n':
511cc36ccd1SDavid Schultz case 'N':
512cc36ccd1SDavid Schultz if (match(&s, "an")) {
513cc36ccd1SDavid Schultz irv = STRTOG_NaN;
514cc36ccd1SDavid Schultz *exp = fpi->emax + 1;
515cc36ccd1SDavid Schultz #ifndef No_Hex_NaN
516cc36ccd1SDavid Schultz if (*s == '(') /*)*/
517cc36ccd1SDavid Schultz irv = hexnan(&s, fpi, bits);
518cc36ccd1SDavid Schultz #endif
519cc36ccd1SDavid Schultz goto infnanexp;
520cc36ccd1SDavid Schultz }
521cc36ccd1SDavid Schultz }
522cc36ccd1SDavid Schultz #endif /* INFNAN_CHECK */
523cc36ccd1SDavid Schultz irv = STRTOG_NoNumber;
524cc36ccd1SDavid Schultz s = s00;
525cc36ccd1SDavid Schultz }
526cc36ccd1SDavid Schultz goto ret;
527cc36ccd1SDavid Schultz }
528cc36ccd1SDavid Schultz
529cc36ccd1SDavid Schultz irv = STRTOG_Normal;
530cc36ccd1SDavid Schultz e1 = e -= nf;
531cc36ccd1SDavid Schultz rd = 0;
532cc36ccd1SDavid Schultz switch(fpi->rounding & 3) {
533cc36ccd1SDavid Schultz case FPI_Round_up:
534cc36ccd1SDavid Schultz rd = 2 - sign;
535cc36ccd1SDavid Schultz break;
536cc36ccd1SDavid Schultz case FPI_Round_zero:
537cc36ccd1SDavid Schultz rd = 1;
538cc36ccd1SDavid Schultz break;
539cc36ccd1SDavid Schultz case FPI_Round_down:
540cc36ccd1SDavid Schultz rd = 1 + sign;
541cc36ccd1SDavid Schultz }
542cc36ccd1SDavid Schultz
543cc36ccd1SDavid Schultz /* Now we have nd0 digits, starting at s0, followed by a
544cc36ccd1SDavid Schultz * decimal point, followed by nd-nd0 digits. The number we're
545cc36ccd1SDavid Schultz * after is the integer represented by those digits times
546cc36ccd1SDavid Schultz * 10**e */
547cc36ccd1SDavid Schultz
548cc36ccd1SDavid Schultz if (!nd0)
549cc36ccd1SDavid Schultz nd0 = nd;
550cc36ccd1SDavid Schultz k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
55150dad48bSDavid Schultz dval(&rv) = y;
552cc36ccd1SDavid Schultz if (k > 9)
55350dad48bSDavid Schultz dval(&rv) = tens[k - 9] * dval(&rv) + z;
554cc36ccd1SDavid Schultz bd0 = 0;
555cc36ccd1SDavid Schultz if (nbits <= P && nd <= DBL_DIG) {
556cc36ccd1SDavid Schultz if (!e) {
55750dad48bSDavid Schultz if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv))
558cc36ccd1SDavid Schultz goto ret;
559cc36ccd1SDavid Schultz }
560cc36ccd1SDavid Schultz else if (e > 0) {
561cc36ccd1SDavid Schultz if (e <= Ten_pmax) {
562cc36ccd1SDavid Schultz #ifdef VAX
563cc36ccd1SDavid Schultz goto vax_ovfl_check;
564cc36ccd1SDavid Schultz #else
56550dad48bSDavid Schultz i = fivesbits[e] + mantbits(&rv) <= P;
56650dad48bSDavid Schultz /* rv = */ rounded_product(dval(&rv), tens[e]);
56750dad48bSDavid Schultz if (rvOK(&rv, fpi, exp, bits, i, rd, &irv))
568cc36ccd1SDavid Schultz goto ret;
569cc36ccd1SDavid Schultz e1 -= e;
570cc36ccd1SDavid Schultz goto rv_notOK;
571cc36ccd1SDavid Schultz #endif
572cc36ccd1SDavid Schultz }
573cc36ccd1SDavid Schultz i = DBL_DIG - nd;
574cc36ccd1SDavid Schultz if (e <= Ten_pmax + i) {
575cc36ccd1SDavid Schultz /* A fancier test would sometimes let us do
576cc36ccd1SDavid Schultz * this for larger i values.
577cc36ccd1SDavid Schultz */
578cc36ccd1SDavid Schultz e2 = e - i;
579cc36ccd1SDavid Schultz e1 -= i;
58050dad48bSDavid Schultz dval(&rv) *= tens[i];
581cc36ccd1SDavid Schultz #ifdef VAX
582cc36ccd1SDavid Schultz /* VAX exponent range is so narrow we must
583cc36ccd1SDavid Schultz * worry about overflow here...
584cc36ccd1SDavid Schultz */
585cc36ccd1SDavid Schultz vax_ovfl_check:
58650dad48bSDavid Schultz dval(&adj) = dval(&rv);
58750dad48bSDavid Schultz word0(&adj) -= P*Exp_msk1;
58850dad48bSDavid Schultz /* adj = */ rounded_product(dval(&adj), tens[e2]);
58950dad48bSDavid Schultz if ((word0(&adj) & Exp_mask)
590cc36ccd1SDavid Schultz > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
591cc36ccd1SDavid Schultz goto rv_notOK;
59250dad48bSDavid Schultz word0(&adj) += P*Exp_msk1;
59350dad48bSDavid Schultz dval(&rv) = dval(&adj);
594cc36ccd1SDavid Schultz #else
59550dad48bSDavid Schultz /* rv = */ rounded_product(dval(&rv), tens[e2]);
596cc36ccd1SDavid Schultz #endif
59750dad48bSDavid Schultz if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
598cc36ccd1SDavid Schultz goto ret;
599cc36ccd1SDavid Schultz e1 -= e2;
600cc36ccd1SDavid Schultz }
601cc36ccd1SDavid Schultz }
602cc36ccd1SDavid Schultz #ifndef Inaccurate_Divide
603cc36ccd1SDavid Schultz else if (e >= -Ten_pmax) {
60450dad48bSDavid Schultz /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
60550dad48bSDavid Schultz if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
606cc36ccd1SDavid Schultz goto ret;
607cc36ccd1SDavid Schultz e1 -= e;
608cc36ccd1SDavid Schultz }
609cc36ccd1SDavid Schultz #endif
610cc36ccd1SDavid Schultz }
611cc36ccd1SDavid Schultz rv_notOK:
612cc36ccd1SDavid Schultz e1 += nd - k;
613cc36ccd1SDavid Schultz
614cc36ccd1SDavid Schultz /* Get starting approximation = rv * 10**e1 */
615cc36ccd1SDavid Schultz
616cc36ccd1SDavid Schultz e2 = 0;
617cc36ccd1SDavid Schultz if (e1 > 0) {
618cc36ccd1SDavid Schultz if ( (i = e1 & 15) !=0)
61950dad48bSDavid Schultz dval(&rv) *= tens[i];
620cc36ccd1SDavid Schultz if (e1 &= ~15) {
621cc36ccd1SDavid Schultz e1 >>= 4;
62250dad48bSDavid Schultz while(e1 >= (1 << (n_bigtens-1))) {
62350dad48bSDavid Schultz e2 += ((word0(&rv) & Exp_mask)
624cc36ccd1SDavid Schultz >> Exp_shift1) - Bias;
62550dad48bSDavid Schultz word0(&rv) &= ~Exp_mask;
62650dad48bSDavid Schultz word0(&rv) |= Bias << Exp_shift1;
62750dad48bSDavid Schultz dval(&rv) *= bigtens[n_bigtens-1];
62850dad48bSDavid Schultz e1 -= 1 << (n_bigtens-1);
629cc36ccd1SDavid Schultz }
63050dad48bSDavid Schultz e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
63150dad48bSDavid Schultz word0(&rv) &= ~Exp_mask;
63250dad48bSDavid Schultz word0(&rv) |= Bias << Exp_shift1;
633cc36ccd1SDavid Schultz for(j = 0; e1 > 0; j++, e1 >>= 1)
634cc36ccd1SDavid Schultz if (e1 & 1)
63550dad48bSDavid Schultz dval(&rv) *= bigtens[j];
636cc36ccd1SDavid Schultz }
637cc36ccd1SDavid Schultz }
638cc36ccd1SDavid Schultz else if (e1 < 0) {
639cc36ccd1SDavid Schultz e1 = -e1;
640cc36ccd1SDavid Schultz if ( (i = e1 & 15) !=0)
64150dad48bSDavid Schultz dval(&rv) /= tens[i];
642cc36ccd1SDavid Schultz if (e1 &= ~15) {
643cc36ccd1SDavid Schultz e1 >>= 4;
64450dad48bSDavid Schultz while(e1 >= (1 << (n_bigtens-1))) {
64550dad48bSDavid Schultz e2 += ((word0(&rv) & Exp_mask)
646cc36ccd1SDavid Schultz >> Exp_shift1) - Bias;
64750dad48bSDavid Schultz word0(&rv) &= ~Exp_mask;
64850dad48bSDavid Schultz word0(&rv) |= Bias << Exp_shift1;
64950dad48bSDavid Schultz dval(&rv) *= tinytens[n_bigtens-1];
65050dad48bSDavid Schultz e1 -= 1 << (n_bigtens-1);
651cc36ccd1SDavid Schultz }
65250dad48bSDavid Schultz e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
65350dad48bSDavid Schultz word0(&rv) &= ~Exp_mask;
65450dad48bSDavid Schultz word0(&rv) |= Bias << Exp_shift1;
655cc36ccd1SDavid Schultz for(j = 0; e1 > 0; j++, e1 >>= 1)
656cc36ccd1SDavid Schultz if (e1 & 1)
65750dad48bSDavid Schultz dval(&rv) *= tinytens[j];
658cc36ccd1SDavid Schultz }
659cc36ccd1SDavid Schultz }
660c88250a5SDavid Schultz #ifdef IBM
661c88250a5SDavid Schultz /* e2 is a correction to the (base 2) exponent of the return
662c88250a5SDavid Schultz * value, reflecting adjustments above to avoid overflow in the
663c88250a5SDavid Schultz * native arithmetic. For native IBM (base 16) arithmetic, we
664c88250a5SDavid Schultz * must multiply e2 by 4 to change from base 16 to 2.
665c88250a5SDavid Schultz */
666c88250a5SDavid Schultz e2 <<= 2;
667c88250a5SDavid Schultz #endif
66850dad48bSDavid Schultz rvb = d2b(dval(&rv), &rve, &rvbits); /* rv = rvb * 2^rve */
669cc36ccd1SDavid Schultz rve += e2;
670cc36ccd1SDavid Schultz if ((j = rvbits - nbits) > 0) {
671cc36ccd1SDavid Schultz rshift(rvb, j);
672cc36ccd1SDavid Schultz rvbits = nbits;
673cc36ccd1SDavid Schultz rve += j;
674cc36ccd1SDavid Schultz }
675cc36ccd1SDavid Schultz bb0 = 0; /* trailing zero bits in rvb */
676cc36ccd1SDavid Schultz e2 = rve + rvbits - nbits;
677c88250a5SDavid Schultz if (e2 > fpi->emax + 1)
678c88250a5SDavid Schultz goto huge;
679cc36ccd1SDavid Schultz rve1 = rve + rvbits - nbits;
680cc36ccd1SDavid Schultz if (e2 < (emin = fpi->emin)) {
681cc36ccd1SDavid Schultz denorm = 1;
682cc36ccd1SDavid Schultz j = rve - emin;
683cc36ccd1SDavid Schultz if (j > 0) {
684cc36ccd1SDavid Schultz rvb = lshift(rvb, j);
685cc36ccd1SDavid Schultz rvbits += j;
686cc36ccd1SDavid Schultz }
687cc36ccd1SDavid Schultz else if (j < 0) {
688cc36ccd1SDavid Schultz rvbits += j;
689cc36ccd1SDavid Schultz if (rvbits <= 0) {
690cc36ccd1SDavid Schultz if (rvbits < -1) {
691cc36ccd1SDavid Schultz ufl:
692cc36ccd1SDavid Schultz rvb->wds = 0;
693cc36ccd1SDavid Schultz rvb->x[0] = 0;
694cc36ccd1SDavid Schultz *exp = emin;
695cc36ccd1SDavid Schultz irv = STRTOG_Underflow | STRTOG_Inexlo;
696cc36ccd1SDavid Schultz goto ret;
697cc36ccd1SDavid Schultz }
698cc36ccd1SDavid Schultz rvb->x[0] = rvb->wds = rvbits = 1;
699cc36ccd1SDavid Schultz }
700cc36ccd1SDavid Schultz else
701cc36ccd1SDavid Schultz rshift(rvb, -j);
702cc36ccd1SDavid Schultz }
703cc36ccd1SDavid Schultz rve = rve1 = emin;
704cc36ccd1SDavid Schultz if (sudden_underflow && e2 + 1 < emin)
705cc36ccd1SDavid Schultz goto ufl;
706cc36ccd1SDavid Schultz }
707cc36ccd1SDavid Schultz
708cc36ccd1SDavid Schultz /* Now the hard part -- adjusting rv to the correct value.*/
709cc36ccd1SDavid Schultz
710cc36ccd1SDavid Schultz /* Put digits into bd: true value = bd * 10^e */
711cc36ccd1SDavid Schultz
7124848dd08SDavid Schultz bd0 = s2b(s0, nd0, nd, y, dplen);
713cc36ccd1SDavid Schultz
714cc36ccd1SDavid Schultz for(;;) {
715cc36ccd1SDavid Schultz bd = Balloc(bd0->k);
716cc36ccd1SDavid Schultz Bcopy(bd, bd0);
717cc36ccd1SDavid Schultz bb = Balloc(rvb->k);
718cc36ccd1SDavid Schultz Bcopy(bb, rvb);
719cc36ccd1SDavid Schultz bbbits = rvbits - bb0;
720cc36ccd1SDavid Schultz bbe = rve + bb0;
721cc36ccd1SDavid Schultz bs = i2b(1);
722cc36ccd1SDavid Schultz
723cc36ccd1SDavid Schultz if (e >= 0) {
724cc36ccd1SDavid Schultz bb2 = bb5 = 0;
725cc36ccd1SDavid Schultz bd2 = bd5 = e;
726cc36ccd1SDavid Schultz }
727cc36ccd1SDavid Schultz else {
728cc36ccd1SDavid Schultz bb2 = bb5 = -e;
729cc36ccd1SDavid Schultz bd2 = bd5 = 0;
730cc36ccd1SDavid Schultz }
731cc36ccd1SDavid Schultz if (bbe >= 0)
732cc36ccd1SDavid Schultz bb2 += bbe;
733cc36ccd1SDavid Schultz else
734cc36ccd1SDavid Schultz bd2 -= bbe;
735cc36ccd1SDavid Schultz bs2 = bb2;
736cc36ccd1SDavid Schultz j = nbits + 1 - bbbits;
737cc36ccd1SDavid Schultz i = bbe + bbbits - nbits;
738cc36ccd1SDavid Schultz if (i < emin) /* denormal */
739cc36ccd1SDavid Schultz j += i - emin;
740cc36ccd1SDavid Schultz bb2 += j;
741cc36ccd1SDavid Schultz bd2 += j;
742cc36ccd1SDavid Schultz i = bb2 < bd2 ? bb2 : bd2;
743cc36ccd1SDavid Schultz if (i > bs2)
744cc36ccd1SDavid Schultz i = bs2;
745cc36ccd1SDavid Schultz if (i > 0) {
746cc36ccd1SDavid Schultz bb2 -= i;
747cc36ccd1SDavid Schultz bd2 -= i;
748cc36ccd1SDavid Schultz bs2 -= i;
749cc36ccd1SDavid Schultz }
750cc36ccd1SDavid Schultz if (bb5 > 0) {
751cc36ccd1SDavid Schultz bs = pow5mult(bs, bb5);
752cc36ccd1SDavid Schultz bb1 = mult(bs, bb);
753cc36ccd1SDavid Schultz Bfree(bb);
754cc36ccd1SDavid Schultz bb = bb1;
755cc36ccd1SDavid Schultz }
756cc36ccd1SDavid Schultz bb2 -= bb0;
757cc36ccd1SDavid Schultz if (bb2 > 0)
758cc36ccd1SDavid Schultz bb = lshift(bb, bb2);
759cc36ccd1SDavid Schultz else if (bb2 < 0)
760cc36ccd1SDavid Schultz rshift(bb, -bb2);
761cc36ccd1SDavid Schultz if (bd5 > 0)
762cc36ccd1SDavid Schultz bd = pow5mult(bd, bd5);
763cc36ccd1SDavid Schultz if (bd2 > 0)
764cc36ccd1SDavid Schultz bd = lshift(bd, bd2);
765cc36ccd1SDavid Schultz if (bs2 > 0)
766cc36ccd1SDavid Schultz bs = lshift(bs, bs2);
767cc36ccd1SDavid Schultz asub = 1;
768cc36ccd1SDavid Schultz inex = STRTOG_Inexhi;
769cc36ccd1SDavid Schultz delta = diff(bb, bd);
770cc36ccd1SDavid Schultz if (delta->wds <= 1 && !delta->x[0])
771cc36ccd1SDavid Schultz break;
772cc36ccd1SDavid Schultz dsign = delta->sign;
773cc36ccd1SDavid Schultz delta->sign = finished = 0;
774cc36ccd1SDavid Schultz L = 0;
775cc36ccd1SDavid Schultz i = cmp(delta, bs);
776cc36ccd1SDavid Schultz if (rd && i <= 0) {
777cc36ccd1SDavid Schultz irv = STRTOG_Normal;
778cc36ccd1SDavid Schultz if ( (finished = dsign ^ (rd&1)) !=0) {
779cc36ccd1SDavid Schultz if (dsign != 0) {
780cc36ccd1SDavid Schultz irv |= STRTOG_Inexhi;
781cc36ccd1SDavid Schultz goto adj1;
782cc36ccd1SDavid Schultz }
783cc36ccd1SDavid Schultz irv |= STRTOG_Inexlo;
784cc36ccd1SDavid Schultz if (rve1 == emin)
785cc36ccd1SDavid Schultz goto adj1;
786cc36ccd1SDavid Schultz for(i = 0, j = nbits; j >= ULbits;
787cc36ccd1SDavid Schultz i++, j -= ULbits) {
788cc36ccd1SDavid Schultz if (rvb->x[i] & ALL_ON)
789cc36ccd1SDavid Schultz goto adj1;
790cc36ccd1SDavid Schultz }
791cc36ccd1SDavid Schultz if (j > 1 && lo0bits(rvb->x + i) < j - 1)
792cc36ccd1SDavid Schultz goto adj1;
793cc36ccd1SDavid Schultz rve = rve1 - 1;
794cc36ccd1SDavid Schultz rvb = set_ones(rvb, rvbits = nbits);
795cc36ccd1SDavid Schultz break;
796cc36ccd1SDavid Schultz }
797cc36ccd1SDavid Schultz irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi;
798cc36ccd1SDavid Schultz break;
799cc36ccd1SDavid Schultz }
800cc36ccd1SDavid Schultz if (i < 0) {
801cc36ccd1SDavid Schultz /* Error is less than half an ulp -- check for
802cc36ccd1SDavid Schultz * special case of mantissa a power of two.
803cc36ccd1SDavid Schultz */
804cc36ccd1SDavid Schultz irv = dsign
805cc36ccd1SDavid Schultz ? STRTOG_Normal | STRTOG_Inexlo
806cc36ccd1SDavid Schultz : STRTOG_Normal | STRTOG_Inexhi;
807cc36ccd1SDavid Schultz if (dsign || bbbits > 1 || denorm || rve1 == emin)
808cc36ccd1SDavid Schultz break;
809cc36ccd1SDavid Schultz delta = lshift(delta,1);
810cc36ccd1SDavid Schultz if (cmp(delta, bs) > 0) {
811cc36ccd1SDavid Schultz irv = STRTOG_Normal | STRTOG_Inexlo;
812cc36ccd1SDavid Schultz goto drop_down;
813cc36ccd1SDavid Schultz }
814cc36ccd1SDavid Schultz break;
815cc36ccd1SDavid Schultz }
816cc36ccd1SDavid Schultz if (i == 0) {
817cc36ccd1SDavid Schultz /* exactly half-way between */
818cc36ccd1SDavid Schultz if (dsign) {
819cc36ccd1SDavid Schultz if (denorm && all_on(rvb, rvbits)) {
820cc36ccd1SDavid Schultz /*boundary case -- increment exponent*/
821cc36ccd1SDavid Schultz rvb->wds = 1;
822cc36ccd1SDavid Schultz rvb->x[0] = 1;
823cc36ccd1SDavid Schultz rve = emin + nbits - (rvbits = 1);
824cc36ccd1SDavid Schultz irv = STRTOG_Normal | STRTOG_Inexhi;
825cc36ccd1SDavid Schultz denorm = 0;
826cc36ccd1SDavid Schultz break;
827cc36ccd1SDavid Schultz }
828cc36ccd1SDavid Schultz irv = STRTOG_Normal | STRTOG_Inexlo;
829cc36ccd1SDavid Schultz }
830cc36ccd1SDavid Schultz else if (bbbits == 1) {
831cc36ccd1SDavid Schultz irv = STRTOG_Normal;
832cc36ccd1SDavid Schultz drop_down:
833cc36ccd1SDavid Schultz /* boundary case -- decrement exponent */
834cc36ccd1SDavid Schultz if (rve1 == emin) {
835cc36ccd1SDavid Schultz irv = STRTOG_Normal | STRTOG_Inexhi;
836cc36ccd1SDavid Schultz if (rvb->wds == 1 && rvb->x[0] == 1)
837cc36ccd1SDavid Schultz sudden_underflow = 1;
838cc36ccd1SDavid Schultz break;
839cc36ccd1SDavid Schultz }
840cc36ccd1SDavid Schultz rve -= nbits;
841cc36ccd1SDavid Schultz rvb = set_ones(rvb, rvbits = nbits);
842cc36ccd1SDavid Schultz break;
843cc36ccd1SDavid Schultz }
844cc36ccd1SDavid Schultz else
845cc36ccd1SDavid Schultz irv = STRTOG_Normal | STRTOG_Inexhi;
84650dad48bSDavid Schultz if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
847cc36ccd1SDavid Schultz break;
848cc36ccd1SDavid Schultz if (dsign) {
849cc36ccd1SDavid Schultz rvb = increment(rvb);
850ae2cbf4cSDavid Schultz j = kmask & (ULbits - (rvbits & kmask));
851ae2cbf4cSDavid Schultz if (hi0bits(rvb->x[rvb->wds - 1]) != j)
852cc36ccd1SDavid Schultz rvbits++;
853cc36ccd1SDavid Schultz irv = STRTOG_Normal | STRTOG_Inexhi;
854cc36ccd1SDavid Schultz }
855cc36ccd1SDavid Schultz else {
856cc36ccd1SDavid Schultz if (bbbits == 1)
857cc36ccd1SDavid Schultz goto undfl;
858cc36ccd1SDavid Schultz decrement(rvb);
859cc36ccd1SDavid Schultz irv = STRTOG_Normal | STRTOG_Inexlo;
860cc36ccd1SDavid Schultz }
861cc36ccd1SDavid Schultz break;
862cc36ccd1SDavid Schultz }
86350dad48bSDavid Schultz if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
864cc36ccd1SDavid Schultz adj1:
865cc36ccd1SDavid Schultz inex = STRTOG_Inexlo;
866cc36ccd1SDavid Schultz if (dsign) {
867cc36ccd1SDavid Schultz asub = 0;
868cc36ccd1SDavid Schultz inex = STRTOG_Inexhi;
869cc36ccd1SDavid Schultz }
870cc36ccd1SDavid Schultz else if (denorm && bbbits <= 1) {
871cc36ccd1SDavid Schultz undfl:
872cc36ccd1SDavid Schultz rvb->wds = 0;
873cc36ccd1SDavid Schultz rve = emin;
874cc36ccd1SDavid Schultz irv = STRTOG_Underflow | STRTOG_Inexlo;
875cc36ccd1SDavid Schultz break;
876cc36ccd1SDavid Schultz }
87750dad48bSDavid Schultz adj0 = dval(&adj) = 1.;
878cc36ccd1SDavid Schultz }
879cc36ccd1SDavid Schultz else {
88050dad48bSDavid Schultz adj0 = dval(&adj) *= 0.5;
881cc36ccd1SDavid Schultz if (dsign) {
882cc36ccd1SDavid Schultz asub = 0;
883cc36ccd1SDavid Schultz inex = STRTOG_Inexlo;
884cc36ccd1SDavid Schultz }
88550dad48bSDavid Schultz if (dval(&adj) < 2147483647.) {
886cc36ccd1SDavid Schultz L = adj0;
887cc36ccd1SDavid Schultz adj0 -= L;
888cc36ccd1SDavid Schultz switch(rd) {
889cc36ccd1SDavid Schultz case 0:
890cc36ccd1SDavid Schultz if (adj0 >= .5)
891cc36ccd1SDavid Schultz goto inc_L;
892cc36ccd1SDavid Schultz break;
893cc36ccd1SDavid Schultz case 1:
894cc36ccd1SDavid Schultz if (asub && adj0 > 0.)
895cc36ccd1SDavid Schultz goto inc_L;
896cc36ccd1SDavid Schultz break;
897cc36ccd1SDavid Schultz case 2:
898cc36ccd1SDavid Schultz if (!asub && adj0 > 0.) {
899cc36ccd1SDavid Schultz inc_L:
900cc36ccd1SDavid Schultz L++;
901cc36ccd1SDavid Schultz inex = STRTOG_Inexact - inex;
902cc36ccd1SDavid Schultz }
903cc36ccd1SDavid Schultz }
90450dad48bSDavid Schultz dval(&adj) = L;
905cc36ccd1SDavid Schultz }
906cc36ccd1SDavid Schultz }
907cc36ccd1SDavid Schultz y = rve + rvbits;
908cc36ccd1SDavid Schultz
90950dad48bSDavid Schultz /* adj *= ulp(dval(&rv)); */
910cc36ccd1SDavid Schultz /* if (asub) rv -= adj; else rv += adj; */
911cc36ccd1SDavid Schultz
912cc36ccd1SDavid Schultz if (!denorm && rvbits < nbits) {
913cc36ccd1SDavid Schultz rvb = lshift(rvb, j = nbits - rvbits);
914cc36ccd1SDavid Schultz rve -= j;
915cc36ccd1SDavid Schultz rvbits = nbits;
916cc36ccd1SDavid Schultz }
91750dad48bSDavid Schultz ab = d2b(dval(&adj), &abe, &abits);
918cc36ccd1SDavid Schultz if (abe < 0)
919cc36ccd1SDavid Schultz rshift(ab, -abe);
920cc36ccd1SDavid Schultz else if (abe > 0)
921cc36ccd1SDavid Schultz ab = lshift(ab, abe);
922cc36ccd1SDavid Schultz rvb0 = rvb;
923cc36ccd1SDavid Schultz if (asub) {
924cc36ccd1SDavid Schultz /* rv -= adj; */
925cc36ccd1SDavid Schultz j = hi0bits(rvb->x[rvb->wds-1]);
926cc36ccd1SDavid Schultz rvb = diff(rvb, ab);
927cc36ccd1SDavid Schultz k = rvb0->wds - 1;
928cc36ccd1SDavid Schultz if (denorm)
929cc36ccd1SDavid Schultz /* do nothing */;
930cc36ccd1SDavid Schultz else if (rvb->wds <= k
931cc36ccd1SDavid Schultz || hi0bits( rvb->x[k]) >
932cc36ccd1SDavid Schultz hi0bits(rvb0->x[k])) {
933cc36ccd1SDavid Schultz /* unlikely; can only have lost 1 high bit */
934cc36ccd1SDavid Schultz if (rve1 == emin) {
935cc36ccd1SDavid Schultz --rvbits;
936cc36ccd1SDavid Schultz denorm = 1;
937cc36ccd1SDavid Schultz }
938cc36ccd1SDavid Schultz else {
939cc36ccd1SDavid Schultz rvb = lshift(rvb, 1);
940cc36ccd1SDavid Schultz --rve;
941cc36ccd1SDavid Schultz --rve1;
942cc36ccd1SDavid Schultz L = finished = 0;
943cc36ccd1SDavid Schultz }
944cc36ccd1SDavid Schultz }
945cc36ccd1SDavid Schultz }
946cc36ccd1SDavid Schultz else {
947cc36ccd1SDavid Schultz rvb = sum(rvb, ab);
948cc36ccd1SDavid Schultz k = rvb->wds - 1;
949cc36ccd1SDavid Schultz if (k >= rvb0->wds
950cc36ccd1SDavid Schultz || hi0bits(rvb->x[k]) < hi0bits(rvb0->x[k])) {
951cc36ccd1SDavid Schultz if (denorm) {
952cc36ccd1SDavid Schultz if (++rvbits == nbits)
953cc36ccd1SDavid Schultz denorm = 0;
954cc36ccd1SDavid Schultz }
955cc36ccd1SDavid Schultz else {
956cc36ccd1SDavid Schultz rshift(rvb, 1);
957cc36ccd1SDavid Schultz rve++;
958cc36ccd1SDavid Schultz rve1++;
959cc36ccd1SDavid Schultz L = 0;
960cc36ccd1SDavid Schultz }
961cc36ccd1SDavid Schultz }
962cc36ccd1SDavid Schultz }
963cc36ccd1SDavid Schultz Bfree(ab);
964cc36ccd1SDavid Schultz Bfree(rvb0);
965cc36ccd1SDavid Schultz if (finished)
966cc36ccd1SDavid Schultz break;
967cc36ccd1SDavid Schultz
968cc36ccd1SDavid Schultz z = rve + rvbits;
969cc36ccd1SDavid Schultz if (y == z && L) {
970cc36ccd1SDavid Schultz /* Can we stop now? */
97150dad48bSDavid Schultz tol = dval(&adj) * 5e-16; /* > max rel error */
97250dad48bSDavid Schultz dval(&adj) = adj0 - .5;
97350dad48bSDavid Schultz if (dval(&adj) < -tol) {
974cc36ccd1SDavid Schultz if (adj0 > tol) {
975cc36ccd1SDavid Schultz irv |= inex;
976cc36ccd1SDavid Schultz break;
977cc36ccd1SDavid Schultz }
978cc36ccd1SDavid Schultz }
97950dad48bSDavid Schultz else if (dval(&adj) > tol && adj0 < 1. - tol) {
980cc36ccd1SDavid Schultz irv |= inex;
981cc36ccd1SDavid Schultz break;
982cc36ccd1SDavid Schultz }
983cc36ccd1SDavid Schultz }
984cc36ccd1SDavid Schultz bb0 = denorm ? 0 : trailz(rvb);
985cc36ccd1SDavid Schultz Bfree(bb);
986cc36ccd1SDavid Schultz Bfree(bd);
987cc36ccd1SDavid Schultz Bfree(bs);
988cc36ccd1SDavid Schultz Bfree(delta);
989cc36ccd1SDavid Schultz }
990c88250a5SDavid Schultz if (!denorm && (j = nbits - rvbits)) {
991c88250a5SDavid Schultz if (j > 0)
992cc36ccd1SDavid Schultz rvb = lshift(rvb, j);
993c88250a5SDavid Schultz else
994c88250a5SDavid Schultz rshift(rvb, -j);
995cc36ccd1SDavid Schultz rve -= j;
996cc36ccd1SDavid Schultz }
997cc36ccd1SDavid Schultz *exp = rve;
998cc36ccd1SDavid Schultz Bfree(bb);
999cc36ccd1SDavid Schultz Bfree(bd);
1000cc36ccd1SDavid Schultz Bfree(bs);
1001cc36ccd1SDavid Schultz Bfree(bd0);
1002cc36ccd1SDavid Schultz Bfree(delta);
1003c88250a5SDavid Schultz if (rve > fpi->emax) {
1004ae2cbf4cSDavid Schultz switch(fpi->rounding & 3) {
1005ae2cbf4cSDavid Schultz case FPI_Round_near:
1006ae2cbf4cSDavid Schultz goto huge;
1007ae2cbf4cSDavid Schultz case FPI_Round_up:
1008ae2cbf4cSDavid Schultz if (!sign)
1009ae2cbf4cSDavid Schultz goto huge;
1010ae2cbf4cSDavid Schultz break;
1011ae2cbf4cSDavid Schultz case FPI_Round_down:
1012ae2cbf4cSDavid Schultz if (sign)
1013ae2cbf4cSDavid Schultz goto huge;
1014ae2cbf4cSDavid Schultz }
1015ae2cbf4cSDavid Schultz /* Round to largest representable magnitude */
1016ae2cbf4cSDavid Schultz Bfree(rvb);
1017ae2cbf4cSDavid Schultz rvb = 0;
1018ae2cbf4cSDavid Schultz irv = STRTOG_Normal | STRTOG_Inexlo;
1019ae2cbf4cSDavid Schultz *exp = fpi->emax;
1020ae2cbf4cSDavid Schultz b = bits;
10214848dd08SDavid Schultz be = b + ((fpi->nbits + 31) >> 5);
1022ae2cbf4cSDavid Schultz while(b < be)
1023ae2cbf4cSDavid Schultz *b++ = -1;
1024ae2cbf4cSDavid Schultz if ((j = fpi->nbits & 0x1f))
1025ae2cbf4cSDavid Schultz *--be >>= (32 - j);
1026ae2cbf4cSDavid Schultz goto ret;
1027c88250a5SDavid Schultz huge:
1028c88250a5SDavid Schultz rvb->wds = 0;
1029c88250a5SDavid Schultz irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
1030c88250a5SDavid Schultz #ifndef NO_ERRNO
1031c88250a5SDavid Schultz errno = ERANGE;
1032c88250a5SDavid Schultz #endif
1033c88250a5SDavid Schultz infnanexp:
1034c88250a5SDavid Schultz *exp = fpi->emax + 1;
1035c88250a5SDavid Schultz }
1036cc36ccd1SDavid Schultz ret:
1037cc36ccd1SDavid Schultz if (denorm) {
1038cc36ccd1SDavid Schultz if (sudden_underflow) {
1039cc36ccd1SDavid Schultz rvb->wds = 0;
1040cc36ccd1SDavid Schultz irv = STRTOG_Underflow | STRTOG_Inexlo;
1041ae2cbf4cSDavid Schultz #ifndef NO_ERRNO
1042ae2cbf4cSDavid Schultz errno = ERANGE;
1043ae2cbf4cSDavid Schultz #endif
1044cc36ccd1SDavid Schultz }
1045cc36ccd1SDavid Schultz else {
1046cc36ccd1SDavid Schultz irv = (irv & ~STRTOG_Retmask) |
1047cc36ccd1SDavid Schultz (rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
1048ae2cbf4cSDavid Schultz if (irv & STRTOG_Inexact) {
1049cc36ccd1SDavid Schultz irv |= STRTOG_Underflow;
1050ae2cbf4cSDavid Schultz #ifndef NO_ERRNO
1051ae2cbf4cSDavid Schultz errno = ERANGE;
1052ae2cbf4cSDavid Schultz #endif
1053ae2cbf4cSDavid Schultz }
1054cc36ccd1SDavid Schultz }
1055cc36ccd1SDavid Schultz }
1056cc36ccd1SDavid Schultz if (se)
1057cc36ccd1SDavid Schultz *se = (char *)s;
1058cc36ccd1SDavid Schultz if (sign)
1059cc36ccd1SDavid Schultz irv |= STRTOG_Neg;
1060cc36ccd1SDavid Schultz if (rvb) {
1061cc36ccd1SDavid Schultz copybits(bits, nbits, rvb);
1062cc36ccd1SDavid Schultz Bfree(rvb);
1063cc36ccd1SDavid Schultz }
1064cc36ccd1SDavid Schultz return irv;
1065cc36ccd1SDavid Schultz }
1066