17b36286aSmartynas /****************************************************************
27b36286aSmartynas
37b36286aSmartynas The author of this software is David M. Gay.
47b36286aSmartynas
57b36286aSmartynas Copyright (C) 1998-2001 by Lucent Technologies
67b36286aSmartynas All Rights Reserved
77b36286aSmartynas
87b36286aSmartynas Permission to use, copy, modify, and distribute this software and
97b36286aSmartynas its documentation for any purpose and without fee is hereby
107b36286aSmartynas granted, provided that the above copyright notice appear in all
117b36286aSmartynas copies and that both that the copyright notice and this
127b36286aSmartynas permission notice and warranty disclaimer appear in supporting
137b36286aSmartynas documentation, and that the name of Lucent or any of its entities
147b36286aSmartynas not be used in advertising or publicity pertaining to
157b36286aSmartynas distribution of the software without specific, written prior
167b36286aSmartynas permission.
177b36286aSmartynas
187b36286aSmartynas LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
197b36286aSmartynas INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
207b36286aSmartynas IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
217b36286aSmartynas SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
227b36286aSmartynas WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
237b36286aSmartynas IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
247b36286aSmartynas ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
257b36286aSmartynas THIS SOFTWARE.
267b36286aSmartynas
277b36286aSmartynas ****************************************************************/
287b36286aSmartynas
297b36286aSmartynas /* Please send bug reports to David M. Gay (dmg at acm dot org,
307b36286aSmartynas * with " at " changed at "@" and " dot " changed to "."). */
317b36286aSmartynas
327b36286aSmartynas #include "gdtoaimp.h"
337b36286aSmartynas
347b36286aSmartynas #ifdef USE_LOCALE
357b36286aSmartynas #include "locale.h"
367b36286aSmartynas #endif
377b36286aSmartynas
387b36286aSmartynas static CONST int
397b36286aSmartynas fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21,
407b36286aSmartynas 24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
417b36286aSmartynas 47, 49, 52
427b36286aSmartynas #ifdef VAX
437b36286aSmartynas , 54, 56
447b36286aSmartynas #endif
457b36286aSmartynas };
467b36286aSmartynas
477b36286aSmartynas Bigint *
487b36286aSmartynas #ifdef KR_headers
increment(b)497b36286aSmartynas increment(b) Bigint *b;
507b36286aSmartynas #else
517b36286aSmartynas increment(Bigint *b)
527b36286aSmartynas #endif
537b36286aSmartynas {
547b36286aSmartynas ULong *x, *xe;
557b36286aSmartynas Bigint *b1;
567b36286aSmartynas #ifdef Pack_16
577b36286aSmartynas ULong carry = 1, y;
587b36286aSmartynas #endif
597b36286aSmartynas
607b36286aSmartynas x = b->x;
617b36286aSmartynas xe = x + b->wds;
627b36286aSmartynas #ifdef Pack_32
637b36286aSmartynas do {
647b36286aSmartynas if (*x < (ULong)0xffffffffL) {
657b36286aSmartynas ++*x;
667b36286aSmartynas return b;
677b36286aSmartynas }
687b36286aSmartynas *x++ = 0;
697b36286aSmartynas } while(x < xe);
707b36286aSmartynas #else
717b36286aSmartynas do {
727b36286aSmartynas y = *x + carry;
737b36286aSmartynas carry = y >> 16;
747b36286aSmartynas *x++ = y & 0xffff;
757b36286aSmartynas if (!carry)
767b36286aSmartynas return b;
777b36286aSmartynas } while(x < xe);
787b36286aSmartynas if (carry)
797b36286aSmartynas #endif
807b36286aSmartynas {
817b36286aSmartynas if (b->wds >= b->maxwds) {
827b36286aSmartynas b1 = Balloc(b->k+1);
83384cfdc1Smartynas if (b1 == NULL)
84384cfdc1Smartynas return (NULL);
857b36286aSmartynas Bcopy(b1,b);
867b36286aSmartynas Bfree(b);
877b36286aSmartynas b = b1;
887b36286aSmartynas }
897b36286aSmartynas b->x[b->wds++] = 1;
907b36286aSmartynas }
917b36286aSmartynas return b;
927b36286aSmartynas }
937b36286aSmartynas
94aad11945Smartynas void
957b36286aSmartynas #ifdef KR_headers
decrement(b)967b36286aSmartynas decrement(b) Bigint *b;
977b36286aSmartynas #else
987b36286aSmartynas decrement(Bigint *b)
997b36286aSmartynas #endif
1007b36286aSmartynas {
1017b36286aSmartynas ULong *x, *xe;
1027b36286aSmartynas #ifdef Pack_16
1037b36286aSmartynas ULong borrow = 1, y;
1047b36286aSmartynas #endif
1057b36286aSmartynas
1067b36286aSmartynas x = b->x;
1077b36286aSmartynas xe = x + b->wds;
1087b36286aSmartynas #ifdef Pack_32
1097b36286aSmartynas do {
1107b36286aSmartynas if (*x) {
1117b36286aSmartynas --*x;
1127b36286aSmartynas break;
1137b36286aSmartynas }
1147b36286aSmartynas *x++ = 0xffffffffL;
1157b36286aSmartynas }
1167b36286aSmartynas while(x < xe);
1177b36286aSmartynas #else
1187b36286aSmartynas do {
1197b36286aSmartynas y = *x - borrow;
1207b36286aSmartynas borrow = (y & 0x10000) >> 16;
1217b36286aSmartynas *x++ = y & 0xffff;
1227b36286aSmartynas } while(borrow && x < xe);
1237b36286aSmartynas #endif
1247b36286aSmartynas }
1257b36286aSmartynas
1267b36286aSmartynas static int
1277b36286aSmartynas #ifdef KR_headers
all_on(b,n)1287b36286aSmartynas all_on(b, n) Bigint *b; int n;
1297b36286aSmartynas #else
1307b36286aSmartynas all_on(Bigint *b, int n)
1317b36286aSmartynas #endif
1327b36286aSmartynas {
1337b36286aSmartynas ULong *x, *xe;
1347b36286aSmartynas
1357b36286aSmartynas x = b->x;
1367b36286aSmartynas xe = x + (n >> kshift);
1377b36286aSmartynas while(x < xe)
1387b36286aSmartynas if ((*x++ & ALL_ON) != ALL_ON)
1397b36286aSmartynas return 0;
1407b36286aSmartynas if (n &= kmask)
1417b36286aSmartynas return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON;
1427b36286aSmartynas return 1;
1437b36286aSmartynas }
1447b36286aSmartynas
1457b36286aSmartynas Bigint *
1467b36286aSmartynas #ifdef KR_headers
set_ones(b,n)1477b36286aSmartynas set_ones(b, n) Bigint *b; int n;
1487b36286aSmartynas #else
1497b36286aSmartynas set_ones(Bigint *b, int n)
1507b36286aSmartynas #endif
1517b36286aSmartynas {
1527b36286aSmartynas int k;
1537b36286aSmartynas ULong *x, *xe;
1547b36286aSmartynas
1557b36286aSmartynas k = (n + ((1 << kshift) - 1)) >> kshift;
1567b36286aSmartynas if (b->k < k) {
1577b36286aSmartynas Bfree(b);
1587b36286aSmartynas b = Balloc(k);
159384cfdc1Smartynas if (b == NULL)
160384cfdc1Smartynas return (NULL);
1617b36286aSmartynas }
1627b36286aSmartynas k = n >> kshift;
1637b36286aSmartynas if (n &= kmask)
1647b36286aSmartynas k++;
1657b36286aSmartynas b->wds = k;
1667b36286aSmartynas x = b->x;
1677b36286aSmartynas xe = x + k;
1687b36286aSmartynas while(x < xe)
1697b36286aSmartynas *x++ = ALL_ON;
1707b36286aSmartynas if (n)
1717b36286aSmartynas x[-1] >>= ULbits - n;
1727b36286aSmartynas return b;
1737b36286aSmartynas }
1747b36286aSmartynas
1757b36286aSmartynas static int
rvOK(d,fpi,exp,bits,exact,rd,irv)1767b36286aSmartynas rvOK
1777b36286aSmartynas #ifdef KR_headers
1787b36286aSmartynas (d, fpi, exp, bits, exact, rd, irv)
1791a653cbcSmartynas U *d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
1807b36286aSmartynas #else
1811a653cbcSmartynas (U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
1827b36286aSmartynas #endif
1837b36286aSmartynas {
1847b36286aSmartynas Bigint *b;
1857b36286aSmartynas ULong carry, inex, lostbits;
1867b36286aSmartynas int bdif, e, j, k, k1, nb, rv;
1877b36286aSmartynas
1887b36286aSmartynas carry = rv = 0;
1891a653cbcSmartynas b = d2b(dval(d), &e, &bdif);
190384cfdc1Smartynas if (b == NULL) {
191384cfdc1Smartynas *irv = STRTOG_NoMemory;
1921a653cbcSmartynas return (1);
193384cfdc1Smartynas }
1947b36286aSmartynas bdif -= nb = fpi->nbits;
1957b36286aSmartynas e += bdif;
1967b36286aSmartynas if (bdif <= 0) {
1977b36286aSmartynas if (exact)
1987b36286aSmartynas goto trunc;
1997b36286aSmartynas goto ret;
2007b36286aSmartynas }
2017b36286aSmartynas if (P == nb) {
2027b36286aSmartynas if (
2037b36286aSmartynas #ifndef IMPRECISE_INEXACT
2047b36286aSmartynas exact &&
2057b36286aSmartynas #endif
2067b36286aSmartynas fpi->rounding ==
2077b36286aSmartynas #ifdef RND_PRODQUOT
2087b36286aSmartynas FPI_Round_near
2097b36286aSmartynas #else
2107b36286aSmartynas Flt_Rounds
2117b36286aSmartynas #endif
2127b36286aSmartynas ) goto trunc;
2137b36286aSmartynas goto ret;
2147b36286aSmartynas }
2157b36286aSmartynas switch(rd) {
216aad11945Smartynas case 1: /* round down (toward -Infinity) */
2177b36286aSmartynas goto trunc;
218aad11945Smartynas case 2: /* round up (toward +Infinity) */
2197b36286aSmartynas break;
2207b36286aSmartynas default: /* round near */
2217b36286aSmartynas k = bdif - 1;
2227b36286aSmartynas if (k < 0)
2237b36286aSmartynas goto trunc;
2247b36286aSmartynas if (!k) {
2257b36286aSmartynas if (!exact)
2267b36286aSmartynas goto ret;
2277b36286aSmartynas if (b->x[0] & 2)
2287b36286aSmartynas break;
2297b36286aSmartynas goto trunc;
2307b36286aSmartynas }
2317b36286aSmartynas if (b->x[k>>kshift] & ((ULong)1 << (k & kmask)))
2327b36286aSmartynas break;
2337b36286aSmartynas goto trunc;
2347b36286aSmartynas }
2357b36286aSmartynas /* "break" cases: round up 1 bit, then truncate; bdif > 0 */
2367b36286aSmartynas carry = 1;
2377b36286aSmartynas trunc:
2387b36286aSmartynas inex = lostbits = 0;
2397b36286aSmartynas if (bdif > 0) {
2407b36286aSmartynas if ( (lostbits = any_on(b, bdif)) !=0)
2417b36286aSmartynas inex = STRTOG_Inexlo;
2427b36286aSmartynas rshift(b, bdif);
2437b36286aSmartynas if (carry) {
2447b36286aSmartynas inex = STRTOG_Inexhi;
2457b36286aSmartynas b = increment(b);
246384cfdc1Smartynas if (b == NULL) {
247384cfdc1Smartynas *irv = STRTOG_NoMemory;
2481a653cbcSmartynas return (1);
249384cfdc1Smartynas }
2507b36286aSmartynas if ( (j = nb & kmask) !=0)
2517b36286aSmartynas j = ULbits - j;
2527b36286aSmartynas if (hi0bits(b->x[b->wds - 1]) != j) {
2537b36286aSmartynas if (!lostbits)
2547b36286aSmartynas lostbits = b->x[0] & 1;
2557b36286aSmartynas rshift(b, 1);
2567b36286aSmartynas e++;
2577b36286aSmartynas }
2587b36286aSmartynas }
2597b36286aSmartynas }
260384cfdc1Smartynas else if (bdif < 0) {
2617b36286aSmartynas b = lshift(b, -bdif);
262384cfdc1Smartynas if (b == NULL) {
263384cfdc1Smartynas *irv = STRTOG_NoMemory;
2641a653cbcSmartynas return (1);
265384cfdc1Smartynas }
266384cfdc1Smartynas }
2677b36286aSmartynas if (e < fpi->emin) {
2687b36286aSmartynas k = fpi->emin - e;
2697b36286aSmartynas e = fpi->emin;
2707b36286aSmartynas if (k > nb || fpi->sudden_underflow) {
2717b36286aSmartynas b->wds = inex = 0;
2727b36286aSmartynas *irv = STRTOG_Underflow | STRTOG_Inexlo;
2737b36286aSmartynas }
2747b36286aSmartynas else {
2757b36286aSmartynas k1 = k - 1;
2767b36286aSmartynas if (k1 > 0 && !lostbits)
2777b36286aSmartynas lostbits = any_on(b, k1);
2787b36286aSmartynas if (!lostbits && !exact)
2797b36286aSmartynas goto ret;
2807b36286aSmartynas lostbits |=
2817b36286aSmartynas carry = b->x[k1>>kshift] & (1 << (k1 & kmask));
2827b36286aSmartynas rshift(b, k);
2837b36286aSmartynas *irv = STRTOG_Denormal;
2847b36286aSmartynas if (carry) {
2857b36286aSmartynas b = increment(b);
286384cfdc1Smartynas if (b == NULL) {
287384cfdc1Smartynas *irv = STRTOG_NoMemory;
2881a653cbcSmartynas return (1);
289384cfdc1Smartynas }
2907b36286aSmartynas inex = STRTOG_Inexhi | STRTOG_Underflow;
2917b36286aSmartynas }
2927b36286aSmartynas else if (lostbits)
2937b36286aSmartynas inex = STRTOG_Inexlo | STRTOG_Underflow;
2947b36286aSmartynas }
2957b36286aSmartynas }
2967b36286aSmartynas else if (e > fpi->emax) {
2977b36286aSmartynas e = fpi->emax + 1;
2987b36286aSmartynas *irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
2997b36286aSmartynas #ifndef NO_ERRNO
3007b36286aSmartynas errno = ERANGE;
3017b36286aSmartynas #endif
3027b36286aSmartynas b->wds = inex = 0;
3037b36286aSmartynas }
3047b36286aSmartynas *exp = e;
3057b36286aSmartynas copybits(bits, nb, b);
3067b36286aSmartynas *irv |= inex;
3077b36286aSmartynas rv = 1;
3087b36286aSmartynas ret:
3097b36286aSmartynas Bfree(b);
3107b36286aSmartynas return rv;
3117b36286aSmartynas }
3127b36286aSmartynas
3137b36286aSmartynas static int
3147b36286aSmartynas #ifdef KR_headers
mantbits(d)3151a653cbcSmartynas mantbits(d) U *d;
3167b36286aSmartynas #else
3171a653cbcSmartynas mantbits(U *d)
3187b36286aSmartynas #endif
3197b36286aSmartynas {
3207b36286aSmartynas ULong L;
3217b36286aSmartynas #ifdef VAX
3227b36286aSmartynas L = word1(d) << 16 | word1(d) >> 16;
3237b36286aSmartynas if (L)
3247b36286aSmartynas #else
3257b36286aSmartynas if ( (L = word1(d)) !=0)
3267b36286aSmartynas #endif
3277b36286aSmartynas return P - lo0bits(&L);
3287b36286aSmartynas #ifdef VAX
3297b36286aSmartynas L = word0(d) << 16 | word0(d) >> 16 | Exp_msk11;
3307b36286aSmartynas #else
3317b36286aSmartynas L = word0(d) | Exp_msk1;
3327b36286aSmartynas #endif
3337b36286aSmartynas return P - 32 - lo0bits(&L);
3347b36286aSmartynas }
3357b36286aSmartynas
3367b36286aSmartynas int
strtodg(s00,se,fpi,exp,bits)3377b36286aSmartynas strtodg
3387b36286aSmartynas #ifdef KR_headers
3397b36286aSmartynas (s00, se, fpi, exp, bits)
3407b36286aSmartynas CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits;
3417b36286aSmartynas #else
3427b36286aSmartynas (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits)
3437b36286aSmartynas #endif
3447b36286aSmartynas {
3457b36286aSmartynas int abe, abits, asub;
3467b36286aSmartynas int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm;
3477b36286aSmartynas int dsign, e, e1, e2, emin, esign, finished, i, inex, irv;
3487b36286aSmartynas int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
3497b36286aSmartynas int sudden_underflow;
3507b36286aSmartynas CONST char *s, *s0, *s1;
3511a653cbcSmartynas double adj0, tol;
3527b36286aSmartynas Long L;
3531a653cbcSmartynas U adj, rv;
354aad11945Smartynas ULong *b, *be, y, z;
3557b36286aSmartynas Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
3561a653cbcSmartynas #ifdef USE_LOCALE /*{{*/
357aad11945Smartynas #ifdef NO_LOCALE_CACHE
358aad11945Smartynas char *decimalpoint = localeconv()->decimal_point;
3591a653cbcSmartynas int dplen = strlen(decimalpoint);
360aad11945Smartynas #else
361aad11945Smartynas char *decimalpoint;
362aad11945Smartynas static char *decimalpoint_cache;
3631a653cbcSmartynas static int dplen;
364aad11945Smartynas if (!(s0 = decimalpoint_cache)) {
365aad11945Smartynas s0 = localeconv()->decimal_point;
366*5b44245bSderaadt decimalpoint_cache = strdup(s0);
3671a653cbcSmartynas dplen = strlen(s0);
368aad11945Smartynas }
369aad11945Smartynas decimalpoint = (char*)s0;
3701a653cbcSmartynas #endif /*NO_LOCALE_CACHE*/
3711a653cbcSmartynas #else /*USE_LOCALE}{*/
3721a653cbcSmartynas #define dplen 1
3731a653cbcSmartynas #endif /*USE_LOCALE}}*/
3747b36286aSmartynas
3757b36286aSmartynas irv = STRTOG_Zero;
3767b36286aSmartynas denorm = sign = nz0 = nz = 0;
3771a653cbcSmartynas dval(&rv) = 0.;
3787b36286aSmartynas rvb = 0;
3797b36286aSmartynas nbits = fpi->nbits;
3807b36286aSmartynas for(s = s00;;s++) switch(*s) {
3817b36286aSmartynas case '-':
3827b36286aSmartynas sign = 1;
3837b36286aSmartynas /* no break */
3847b36286aSmartynas case '+':
3857b36286aSmartynas if (*++s)
3867b36286aSmartynas goto break2;
3877b36286aSmartynas /* no break */
3887b36286aSmartynas case 0:
3897b36286aSmartynas sign = 0;
3907b36286aSmartynas irv = STRTOG_NoNumber;
3917b36286aSmartynas s = s00;
3927b36286aSmartynas goto ret;
3937b36286aSmartynas case '\t':
3947b36286aSmartynas case '\n':
3957b36286aSmartynas case '\v':
3967b36286aSmartynas case '\f':
3977b36286aSmartynas case '\r':
3987b36286aSmartynas case ' ':
3997b36286aSmartynas continue;
4007b36286aSmartynas default:
4017b36286aSmartynas goto break2;
4027b36286aSmartynas }
4037b36286aSmartynas break2:
4047b36286aSmartynas if (*s == '0') {
4057b36286aSmartynas #ifndef NO_HEX_FP
4067b36286aSmartynas switch(s[1]) {
4077b36286aSmartynas case 'x':
4087b36286aSmartynas case 'X':
4097b36286aSmartynas irv = gethex(&s, fpi, exp, &rvb, sign);
410384cfdc1Smartynas if (irv == STRTOG_NoMemory)
411384cfdc1Smartynas return (STRTOG_NoMemory);
4127b36286aSmartynas if (irv == STRTOG_NoNumber) {
4137b36286aSmartynas s = s00;
4147b36286aSmartynas sign = 0;
4157b36286aSmartynas }
4167b36286aSmartynas goto ret;
4177b36286aSmartynas }
4187b36286aSmartynas #endif
4197b36286aSmartynas nz0 = 1;
4207b36286aSmartynas while(*++s == '0') ;
4217b36286aSmartynas if (!*s)
4227b36286aSmartynas goto ret;
4237b36286aSmartynas }
4247b36286aSmartynas sudden_underflow = fpi->sudden_underflow;
4257b36286aSmartynas s0 = s;
4267b36286aSmartynas y = z = 0;
4277b36286aSmartynas for(decpt = nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
4287b36286aSmartynas if (nd < 9)
4297b36286aSmartynas y = 10*y + c - '0';
4307b36286aSmartynas else if (nd < 16)
4317b36286aSmartynas z = 10*z + c - '0';
4327b36286aSmartynas nd0 = nd;
4337b36286aSmartynas #ifdef USE_LOCALE
434aad11945Smartynas if (c == *decimalpoint) {
435aad11945Smartynas for(i = 1; decimalpoint[i]; ++i)
436aad11945Smartynas if (s[i] != decimalpoint[i])
437aad11945Smartynas goto dig_done;
438aad11945Smartynas s += i;
439aad11945Smartynas c = *s;
4407b36286aSmartynas #else
441aad11945Smartynas if (c == '.') {
4427b36286aSmartynas c = *++s;
443aad11945Smartynas #endif
444aad11945Smartynas decpt = 1;
4457b36286aSmartynas if (!nd) {
4467b36286aSmartynas for(; c == '0'; c = *++s)
4477b36286aSmartynas nz++;
4487b36286aSmartynas if (c > '0' && c <= '9') {
4497b36286aSmartynas s0 = s;
4507b36286aSmartynas nf += nz;
4517b36286aSmartynas nz = 0;
4527b36286aSmartynas goto have_dig;
4537b36286aSmartynas }
4547b36286aSmartynas goto dig_done;
4557b36286aSmartynas }
4567b36286aSmartynas for(; c >= '0' && c <= '9'; c = *++s) {
4577b36286aSmartynas have_dig:
4587b36286aSmartynas nz++;
4597b36286aSmartynas if (c -= '0') {
4607b36286aSmartynas nf += nz;
4617b36286aSmartynas for(i = 1; i < nz; i++)
4627b36286aSmartynas if (nd++ < 9)
4637b36286aSmartynas y *= 10;
4647b36286aSmartynas else if (nd <= DBL_DIG + 1)
4657b36286aSmartynas z *= 10;
4667b36286aSmartynas if (nd++ < 9)
4677b36286aSmartynas y = 10*y + c;
4687b36286aSmartynas else if (nd <= DBL_DIG + 1)
4697b36286aSmartynas z = 10*z + c;
4707b36286aSmartynas nz = 0;
4717b36286aSmartynas }
4727b36286aSmartynas }
473aad11945Smartynas }/*}*/
4747b36286aSmartynas dig_done:
4757b36286aSmartynas e = 0;
4767b36286aSmartynas if (c == 'e' || c == 'E') {
4777b36286aSmartynas if (!nd && !nz && !nz0) {
4787b36286aSmartynas irv = STRTOG_NoNumber;
4797b36286aSmartynas s = s00;
4807b36286aSmartynas goto ret;
4817b36286aSmartynas }
4827b36286aSmartynas s00 = s;
4837b36286aSmartynas esign = 0;
4847b36286aSmartynas switch(c = *++s) {
4857b36286aSmartynas case '-':
4867b36286aSmartynas esign = 1;
4877b36286aSmartynas case '+':
4887b36286aSmartynas c = *++s;
4897b36286aSmartynas }
4907b36286aSmartynas if (c >= '0' && c <= '9') {
4917b36286aSmartynas while(c == '0')
4927b36286aSmartynas c = *++s;
4937b36286aSmartynas if (c > '0' && c <= '9') {
4947b36286aSmartynas L = c - '0';
4957b36286aSmartynas s1 = s;
4967b36286aSmartynas while((c = *++s) >= '0' && c <= '9')
4977b36286aSmartynas L = 10*L + c - '0';
4987b36286aSmartynas if (s - s1 > 8 || L > 19999)
4997b36286aSmartynas /* Avoid confusion from exponents
5007b36286aSmartynas * so large that e might overflow.
5017b36286aSmartynas */
5027b36286aSmartynas e = 19999; /* safe for 16 bit ints */
5037b36286aSmartynas else
5047b36286aSmartynas e = (int)L;
5057b36286aSmartynas if (esign)
5067b36286aSmartynas e = -e;
5077b36286aSmartynas }
5087b36286aSmartynas else
5097b36286aSmartynas e = 0;
5107b36286aSmartynas }
5117b36286aSmartynas else
5127b36286aSmartynas s = s00;
5137b36286aSmartynas }
5147b36286aSmartynas if (!nd) {
5157b36286aSmartynas if (!nz && !nz0) {
5167b36286aSmartynas #ifdef INFNAN_CHECK
5177b36286aSmartynas /* Check for Nan and Infinity */
5187b36286aSmartynas if (!decpt)
5197b36286aSmartynas switch(c) {
5207b36286aSmartynas case 'i':
5217b36286aSmartynas case 'I':
5227b36286aSmartynas if (match(&s,"nf")) {
5237b36286aSmartynas --s;
5247b36286aSmartynas if (!match(&s,"inity"))
5257b36286aSmartynas ++s;
5267b36286aSmartynas irv = STRTOG_Infinite;
5277b36286aSmartynas goto infnanexp;
5287b36286aSmartynas }
5297b36286aSmartynas break;
5307b36286aSmartynas case 'n':
5317b36286aSmartynas case 'N':
5327b36286aSmartynas if (match(&s, "an")) {
5337b36286aSmartynas irv = STRTOG_NaN;
5347b36286aSmartynas *exp = fpi->emax + 1;
5357b36286aSmartynas #ifndef No_Hex_NaN
5367b36286aSmartynas if (*s == '(') /*)*/
5377b36286aSmartynas irv = hexnan(&s, fpi, bits);
5387b36286aSmartynas #endif
5397b36286aSmartynas goto infnanexp;
5407b36286aSmartynas }
5417b36286aSmartynas }
5427b36286aSmartynas #endif /* INFNAN_CHECK */
5437b36286aSmartynas irv = STRTOG_NoNumber;
5447b36286aSmartynas s = s00;
5457b36286aSmartynas }
5467b36286aSmartynas goto ret;
5477b36286aSmartynas }
5487b36286aSmartynas
5497b36286aSmartynas irv = STRTOG_Normal;
5507b36286aSmartynas e1 = e -= nf;
5517b36286aSmartynas rd = 0;
5527b36286aSmartynas switch(fpi->rounding & 3) {
5537b36286aSmartynas case FPI_Round_up:
5547b36286aSmartynas rd = 2 - sign;
5557b36286aSmartynas break;
5567b36286aSmartynas case FPI_Round_zero:
5577b36286aSmartynas rd = 1;
5587b36286aSmartynas break;
5597b36286aSmartynas case FPI_Round_down:
5607b36286aSmartynas rd = 1 + sign;
5617b36286aSmartynas }
5627b36286aSmartynas
5637b36286aSmartynas /* Now we have nd0 digits, starting at s0, followed by a
5647b36286aSmartynas * decimal point, followed by nd-nd0 digits. The number we're
5657b36286aSmartynas * after is the integer represented by those digits times
5667b36286aSmartynas * 10**e */
5677b36286aSmartynas
5687b36286aSmartynas if (!nd0)
5697b36286aSmartynas nd0 = nd;
5707b36286aSmartynas k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
5711a653cbcSmartynas dval(&rv) = y;
5727b36286aSmartynas if (k > 9)
5731a653cbcSmartynas dval(&rv) = tens[k - 9] * dval(&rv) + z;
5747b36286aSmartynas bd0 = 0;
5757b36286aSmartynas if (nbits <= P && nd <= DBL_DIG) {
5767b36286aSmartynas if (!e) {
5771a653cbcSmartynas if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv)) {
578384cfdc1Smartynas if (irv == STRTOG_NoMemory)
579384cfdc1Smartynas return (STRTOG_NoMemory);
5807b36286aSmartynas goto ret;
5817b36286aSmartynas }
582384cfdc1Smartynas }
5837b36286aSmartynas else if (e > 0) {
5847b36286aSmartynas if (e <= Ten_pmax) {
5857b36286aSmartynas #ifdef VAX
5867b36286aSmartynas goto vax_ovfl_check;
5877b36286aSmartynas #else
5881a653cbcSmartynas i = fivesbits[e] + mantbits(&rv) <= P;
5891a653cbcSmartynas /* rv = */ rounded_product(dval(&rv), tens[e]);
5901a653cbcSmartynas if (rvOK(&rv, fpi, exp, bits, i, rd, &irv)) {
591384cfdc1Smartynas if (irv == STRTOG_NoMemory)
592384cfdc1Smartynas return (STRTOG_NoMemory);
5937b36286aSmartynas goto ret;
594384cfdc1Smartynas }
5957b36286aSmartynas e1 -= e;
5967b36286aSmartynas goto rv_notOK;
5977b36286aSmartynas #endif
5987b36286aSmartynas }
5997b36286aSmartynas i = DBL_DIG - nd;
6007b36286aSmartynas if (e <= Ten_pmax + i) {
6017b36286aSmartynas /* A fancier test would sometimes let us do
6027b36286aSmartynas * this for larger i values.
6037b36286aSmartynas */
6047b36286aSmartynas e2 = e - i;
6057b36286aSmartynas e1 -= i;
6061a653cbcSmartynas dval(&rv) *= tens[i];
6077b36286aSmartynas #ifdef VAX
6087b36286aSmartynas /* VAX exponent range is so narrow we must
6097b36286aSmartynas * worry about overflow here...
6107b36286aSmartynas */
6117b36286aSmartynas vax_ovfl_check:
6121a653cbcSmartynas dval(&adj) = dval(&rv);
6131a653cbcSmartynas word0(&adj) -= P*Exp_msk1;
6141a653cbcSmartynas /* adj = */ rounded_product(dval(&adj), tens[e2]);
6151a653cbcSmartynas if ((word0(&adj) & Exp_mask)
6167b36286aSmartynas > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
6177b36286aSmartynas goto rv_notOK;
6181a653cbcSmartynas word0(&adj) += P*Exp_msk1;
6191a653cbcSmartynas dval(&rv) = dval(&adj);
6207b36286aSmartynas #else
6211a653cbcSmartynas /* rv = */ rounded_product(dval(&rv), tens[e2]);
6227b36286aSmartynas #endif
6231a653cbcSmartynas if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv)) {
624384cfdc1Smartynas if (irv == STRTOG_NoMemory)
625384cfdc1Smartynas return (STRTOG_NoMemory);
6267b36286aSmartynas goto ret;
627384cfdc1Smartynas }
6287b36286aSmartynas e1 -= e2;
6297b36286aSmartynas }
6307b36286aSmartynas }
6317b36286aSmartynas #ifndef Inaccurate_Divide
6327b36286aSmartynas else if (e >= -Ten_pmax) {
6331a653cbcSmartynas /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
6341a653cbcSmartynas if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv)) {
635384cfdc1Smartynas if (irv == STRTOG_NoMemory)
636384cfdc1Smartynas return (STRTOG_NoMemory);
6377b36286aSmartynas goto ret;
638384cfdc1Smartynas }
6397b36286aSmartynas e1 -= e;
6407b36286aSmartynas }
6417b36286aSmartynas #endif
6427b36286aSmartynas }
6437b36286aSmartynas rv_notOK:
6447b36286aSmartynas e1 += nd - k;
6457b36286aSmartynas
6467b36286aSmartynas /* Get starting approximation = rv * 10**e1 */
6477b36286aSmartynas
6487b36286aSmartynas e2 = 0;
6497b36286aSmartynas if (e1 > 0) {
6507b36286aSmartynas if ( (i = e1 & 15) !=0)
6511a653cbcSmartynas dval(&rv) *= tens[i];
6527b36286aSmartynas if (e1 &= ~15) {
6537b36286aSmartynas e1 >>= 4;
6541a653cbcSmartynas while(e1 >= (1 << (n_bigtens-1))) {
6551a653cbcSmartynas e2 += ((word0(&rv) & Exp_mask)
6567b36286aSmartynas >> Exp_shift1) - Bias;
6571a653cbcSmartynas word0(&rv) &= ~Exp_mask;
6581a653cbcSmartynas word0(&rv) |= Bias << Exp_shift1;
6591a653cbcSmartynas dval(&rv) *= bigtens[n_bigtens-1];
6601a653cbcSmartynas e1 -= 1 << (n_bigtens-1);
6617b36286aSmartynas }
6621a653cbcSmartynas e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
6631a653cbcSmartynas word0(&rv) &= ~Exp_mask;
6641a653cbcSmartynas word0(&rv) |= Bias << Exp_shift1;
6657b36286aSmartynas for(j = 0; e1 > 0; j++, e1 >>= 1)
6667b36286aSmartynas if (e1 & 1)
6671a653cbcSmartynas dval(&rv) *= bigtens[j];
6687b36286aSmartynas }
6697b36286aSmartynas }
6707b36286aSmartynas else if (e1 < 0) {
6717b36286aSmartynas e1 = -e1;
6727b36286aSmartynas if ( (i = e1 & 15) !=0)
6731a653cbcSmartynas dval(&rv) /= tens[i];
6747b36286aSmartynas if (e1 &= ~15) {
6757b36286aSmartynas e1 >>= 4;
6761a653cbcSmartynas while(e1 >= (1 << (n_bigtens-1))) {
6771a653cbcSmartynas e2 += ((word0(&rv) & Exp_mask)
6787b36286aSmartynas >> Exp_shift1) - Bias;
6791a653cbcSmartynas word0(&rv) &= ~Exp_mask;
6801a653cbcSmartynas word0(&rv) |= Bias << Exp_shift1;
6811a653cbcSmartynas dval(&rv) *= tinytens[n_bigtens-1];
6821a653cbcSmartynas e1 -= 1 << (n_bigtens-1);
6837b36286aSmartynas }
6841a653cbcSmartynas e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
6851a653cbcSmartynas word0(&rv) &= ~Exp_mask;
6861a653cbcSmartynas word0(&rv) |= Bias << Exp_shift1;
6877b36286aSmartynas for(j = 0; e1 > 0; j++, e1 >>= 1)
6887b36286aSmartynas if (e1 & 1)
6891a653cbcSmartynas dval(&rv) *= tinytens[j];
6907b36286aSmartynas }
6917b36286aSmartynas }
6927b36286aSmartynas #ifdef IBM
6937b36286aSmartynas /* e2 is a correction to the (base 2) exponent of the return
6947b36286aSmartynas * value, reflecting adjustments above to avoid overflow in the
6957b36286aSmartynas * native arithmetic. For native IBM (base 16) arithmetic, we
6967b36286aSmartynas * must multiply e2 by 4 to change from base 16 to 2.
6977b36286aSmartynas */
6987b36286aSmartynas e2 <<= 2;
6997b36286aSmartynas #endif
7001a653cbcSmartynas rvb = d2b(dval(&rv), &rve, &rvbits); /* rv = rvb * 2^rve */
701384cfdc1Smartynas if (rvb == NULL)
702384cfdc1Smartynas return (STRTOG_NoMemory);
7037b36286aSmartynas rve += e2;
7047b36286aSmartynas if ((j = rvbits - nbits) > 0) {
7057b36286aSmartynas rshift(rvb, j);
7067b36286aSmartynas rvbits = nbits;
7077b36286aSmartynas rve += j;
7087b36286aSmartynas }
7097b36286aSmartynas bb0 = 0; /* trailing zero bits in rvb */
7107b36286aSmartynas e2 = rve + rvbits - nbits;
7117b36286aSmartynas if (e2 > fpi->emax + 1)
7127b36286aSmartynas goto huge;
7137b36286aSmartynas rve1 = rve + rvbits - nbits;
7147b36286aSmartynas if (e2 < (emin = fpi->emin)) {
7157b36286aSmartynas denorm = 1;
7167b36286aSmartynas j = rve - emin;
7177b36286aSmartynas if (j > 0) {
7187b36286aSmartynas rvb = lshift(rvb, j);
719384cfdc1Smartynas if (rvb == NULL)
720384cfdc1Smartynas return (STRTOG_NoMemory);
7217b36286aSmartynas rvbits += j;
7227b36286aSmartynas }
7237b36286aSmartynas else if (j < 0) {
7247b36286aSmartynas rvbits += j;
7257b36286aSmartynas if (rvbits <= 0) {
7267b36286aSmartynas if (rvbits < -1) {
7277b36286aSmartynas ufl:
7287b36286aSmartynas rvb->wds = 0;
7297b36286aSmartynas rvb->x[0] = 0;
7307b36286aSmartynas *exp = emin;
7317b36286aSmartynas irv = STRTOG_Underflow | STRTOG_Inexlo;
7327b36286aSmartynas goto ret;
7337b36286aSmartynas }
7347b36286aSmartynas rvb->x[0] = rvb->wds = rvbits = 1;
7357b36286aSmartynas }
7367b36286aSmartynas else
7377b36286aSmartynas rshift(rvb, -j);
7387b36286aSmartynas }
7397b36286aSmartynas rve = rve1 = emin;
7407b36286aSmartynas if (sudden_underflow && e2 + 1 < emin)
7417b36286aSmartynas goto ufl;
7427b36286aSmartynas }
7437b36286aSmartynas
7447b36286aSmartynas /* Now the hard part -- adjusting rv to the correct value.*/
7457b36286aSmartynas
7467b36286aSmartynas /* Put digits into bd: true value = bd * 10^e */
7477b36286aSmartynas
7481a653cbcSmartynas bd0 = s2b(s0, nd0, nd, y, dplen);
749384cfdc1Smartynas if (bd0 == NULL)
750384cfdc1Smartynas return (STRTOG_NoMemory);
7517b36286aSmartynas
7527b36286aSmartynas for(;;) {
7537b36286aSmartynas bd = Balloc(bd0->k);
754384cfdc1Smartynas if (bd == NULL)
755384cfdc1Smartynas return (STRTOG_NoMemory);
7567b36286aSmartynas Bcopy(bd, bd0);
7577b36286aSmartynas bb = Balloc(rvb->k);
758384cfdc1Smartynas if (bb == NULL)
759384cfdc1Smartynas return (STRTOG_NoMemory);
7607b36286aSmartynas Bcopy(bb, rvb);
7617b36286aSmartynas bbbits = rvbits - bb0;
7627b36286aSmartynas bbe = rve + bb0;
7637b36286aSmartynas bs = i2b(1);
764384cfdc1Smartynas if (bs == NULL)
765384cfdc1Smartynas return (STRTOG_NoMemory);
7667b36286aSmartynas
7677b36286aSmartynas if (e >= 0) {
7687b36286aSmartynas bb2 = bb5 = 0;
7697b36286aSmartynas bd2 = bd5 = e;
7707b36286aSmartynas }
7717b36286aSmartynas else {
7727b36286aSmartynas bb2 = bb5 = -e;
7737b36286aSmartynas bd2 = bd5 = 0;
7747b36286aSmartynas }
7757b36286aSmartynas if (bbe >= 0)
7767b36286aSmartynas bb2 += bbe;
7777b36286aSmartynas else
7787b36286aSmartynas bd2 -= bbe;
7797b36286aSmartynas bs2 = bb2;
7807b36286aSmartynas j = nbits + 1 - bbbits;
7817b36286aSmartynas i = bbe + bbbits - nbits;
7827b36286aSmartynas if (i < emin) /* denormal */
7837b36286aSmartynas j += i - emin;
7847b36286aSmartynas bb2 += j;
7857b36286aSmartynas bd2 += j;
7867b36286aSmartynas i = bb2 < bd2 ? bb2 : bd2;
7877b36286aSmartynas if (i > bs2)
7887b36286aSmartynas i = bs2;
7897b36286aSmartynas if (i > 0) {
7907b36286aSmartynas bb2 -= i;
7917b36286aSmartynas bd2 -= i;
7927b36286aSmartynas bs2 -= i;
7937b36286aSmartynas }
7947b36286aSmartynas if (bb5 > 0) {
7957b36286aSmartynas bs = pow5mult(bs, bb5);
796384cfdc1Smartynas if (bs == NULL)
797384cfdc1Smartynas return (STRTOG_NoMemory);
7987b36286aSmartynas bb1 = mult(bs, bb);
799384cfdc1Smartynas if (bb1 == NULL)
800384cfdc1Smartynas return (STRTOG_NoMemory);
8017b36286aSmartynas Bfree(bb);
8027b36286aSmartynas bb = bb1;
8037b36286aSmartynas }
8047b36286aSmartynas bb2 -= bb0;
805384cfdc1Smartynas if (bb2 > 0) {
8067b36286aSmartynas bb = lshift(bb, bb2);
807384cfdc1Smartynas if (bb == NULL)
808384cfdc1Smartynas return (STRTOG_NoMemory);
809384cfdc1Smartynas }
8107b36286aSmartynas else if (bb2 < 0)
8117b36286aSmartynas rshift(bb, -bb2);
812384cfdc1Smartynas if (bd5 > 0) {
8137b36286aSmartynas bd = pow5mult(bd, bd5);
814384cfdc1Smartynas if (bd == NULL)
815384cfdc1Smartynas return (STRTOG_NoMemory);
816384cfdc1Smartynas }
817384cfdc1Smartynas if (bd2 > 0) {
8187b36286aSmartynas bd = lshift(bd, bd2);
819384cfdc1Smartynas if (bd == NULL)
820384cfdc1Smartynas return (STRTOG_NoMemory);
821384cfdc1Smartynas }
822384cfdc1Smartynas if (bs2 > 0) {
8237b36286aSmartynas bs = lshift(bs, bs2);
824384cfdc1Smartynas if (bs == NULL)
825384cfdc1Smartynas return (STRTOG_NoMemory);
826384cfdc1Smartynas }
8277b36286aSmartynas asub = 1;
8287b36286aSmartynas inex = STRTOG_Inexhi;
8297b36286aSmartynas delta = diff(bb, bd);
830384cfdc1Smartynas if (delta == NULL)
831384cfdc1Smartynas return (STRTOG_NoMemory);
8327b36286aSmartynas if (delta->wds <= 1 && !delta->x[0])
8337b36286aSmartynas break;
8347b36286aSmartynas dsign = delta->sign;
8357b36286aSmartynas delta->sign = finished = 0;
8367b36286aSmartynas L = 0;
8377b36286aSmartynas i = cmp(delta, bs);
8387b36286aSmartynas if (rd && i <= 0) {
8397b36286aSmartynas irv = STRTOG_Normal;
8407b36286aSmartynas if ( (finished = dsign ^ (rd&1)) !=0) {
8417b36286aSmartynas if (dsign != 0) {
8427b36286aSmartynas irv |= STRTOG_Inexhi;
8437b36286aSmartynas goto adj1;
8447b36286aSmartynas }
8457b36286aSmartynas irv |= STRTOG_Inexlo;
8467b36286aSmartynas if (rve1 == emin)
8477b36286aSmartynas goto adj1;
8487b36286aSmartynas for(i = 0, j = nbits; j >= ULbits;
8497b36286aSmartynas i++, j -= ULbits) {
8507b36286aSmartynas if (rvb->x[i] & ALL_ON)
8517b36286aSmartynas goto adj1;
8527b36286aSmartynas }
8537b36286aSmartynas if (j > 1 && lo0bits(rvb->x + i) < j - 1)
8547b36286aSmartynas goto adj1;
8557b36286aSmartynas rve = rve1 - 1;
8567b36286aSmartynas rvb = set_ones(rvb, rvbits = nbits);
857384cfdc1Smartynas if (rvb == NULL)
858384cfdc1Smartynas return (STRTOG_NoMemory);
8597b36286aSmartynas break;
8607b36286aSmartynas }
8617b36286aSmartynas irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi;
8627b36286aSmartynas break;
8637b36286aSmartynas }
8647b36286aSmartynas if (i < 0) {
8657b36286aSmartynas /* Error is less than half an ulp -- check for
8667b36286aSmartynas * special case of mantissa a power of two.
8677b36286aSmartynas */
8687b36286aSmartynas irv = dsign
8697b36286aSmartynas ? STRTOG_Normal | STRTOG_Inexlo
8707b36286aSmartynas : STRTOG_Normal | STRTOG_Inexhi;
8717b36286aSmartynas if (dsign || bbbits > 1 || denorm || rve1 == emin)
8727b36286aSmartynas break;
8737b36286aSmartynas delta = lshift(delta,1);
874384cfdc1Smartynas if (delta == NULL)
875384cfdc1Smartynas return (STRTOG_NoMemory);
8767b36286aSmartynas if (cmp(delta, bs) > 0) {
8777b36286aSmartynas irv = STRTOG_Normal | STRTOG_Inexlo;
8787b36286aSmartynas goto drop_down;
8797b36286aSmartynas }
8807b36286aSmartynas break;
8817b36286aSmartynas }
8827b36286aSmartynas if (i == 0) {
8837b36286aSmartynas /* exactly half-way between */
8847b36286aSmartynas if (dsign) {
8857b36286aSmartynas if (denorm && all_on(rvb, rvbits)) {
8867b36286aSmartynas /*boundary case -- increment exponent*/
8877b36286aSmartynas rvb->wds = 1;
8887b36286aSmartynas rvb->x[0] = 1;
8897b36286aSmartynas rve = emin + nbits - (rvbits = 1);
8907b36286aSmartynas irv = STRTOG_Normal | STRTOG_Inexhi;
8917b36286aSmartynas denorm = 0;
8927b36286aSmartynas break;
8937b36286aSmartynas }
8947b36286aSmartynas irv = STRTOG_Normal | STRTOG_Inexlo;
8957b36286aSmartynas }
8967b36286aSmartynas else if (bbbits == 1) {
8977b36286aSmartynas irv = STRTOG_Normal;
8987b36286aSmartynas drop_down:
8997b36286aSmartynas /* boundary case -- decrement exponent */
9007b36286aSmartynas if (rve1 == emin) {
9017b36286aSmartynas irv = STRTOG_Normal | STRTOG_Inexhi;
9027b36286aSmartynas if (rvb->wds == 1 && rvb->x[0] == 1)
9037b36286aSmartynas sudden_underflow = 1;
9047b36286aSmartynas break;
9057b36286aSmartynas }
9067b36286aSmartynas rve -= nbits;
9077b36286aSmartynas rvb = set_ones(rvb, rvbits = nbits);
908384cfdc1Smartynas if (rvb == NULL)
909384cfdc1Smartynas return (STRTOG_NoMemory);
9107b36286aSmartynas break;
9117b36286aSmartynas }
9127b36286aSmartynas else
9137b36286aSmartynas irv = STRTOG_Normal | STRTOG_Inexhi;
9141a653cbcSmartynas if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
9157b36286aSmartynas break;
9167b36286aSmartynas if (dsign) {
9177b36286aSmartynas rvb = increment(rvb);
918384cfdc1Smartynas if (rvb == NULL)
919384cfdc1Smartynas return (STRTOG_NoMemory);
9207b36286aSmartynas j = kmask & (ULbits - (rvbits & kmask));
9217b36286aSmartynas if (hi0bits(rvb->x[rvb->wds - 1]) != j)
9227b36286aSmartynas rvbits++;
9237b36286aSmartynas irv = STRTOG_Normal | STRTOG_Inexhi;
9247b36286aSmartynas }
9257b36286aSmartynas else {
9267b36286aSmartynas if (bbbits == 1)
9277b36286aSmartynas goto undfl;
9287b36286aSmartynas decrement(rvb);
9297b36286aSmartynas irv = STRTOG_Normal | STRTOG_Inexlo;
9307b36286aSmartynas }
9317b36286aSmartynas break;
9327b36286aSmartynas }
9331a653cbcSmartynas if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
9347b36286aSmartynas adj1:
9357b36286aSmartynas inex = STRTOG_Inexlo;
9367b36286aSmartynas if (dsign) {
9377b36286aSmartynas asub = 0;
9387b36286aSmartynas inex = STRTOG_Inexhi;
9397b36286aSmartynas }
9407b36286aSmartynas else if (denorm && bbbits <= 1) {
9417b36286aSmartynas undfl:
9427b36286aSmartynas rvb->wds = 0;
9437b36286aSmartynas rve = emin;
9447b36286aSmartynas irv = STRTOG_Underflow | STRTOG_Inexlo;
9457b36286aSmartynas break;
9467b36286aSmartynas }
9471a653cbcSmartynas adj0 = dval(&adj) = 1.;
9487b36286aSmartynas }
9497b36286aSmartynas else {
9501a653cbcSmartynas adj0 = dval(&adj) *= 0.5;
9517b36286aSmartynas if (dsign) {
9527b36286aSmartynas asub = 0;
9537b36286aSmartynas inex = STRTOG_Inexlo;
9547b36286aSmartynas }
9551a653cbcSmartynas if (dval(&adj) < 2147483647.) {
9567b36286aSmartynas L = adj0;
9577b36286aSmartynas adj0 -= L;
9587b36286aSmartynas switch(rd) {
9597b36286aSmartynas case 0:
9607b36286aSmartynas if (adj0 >= .5)
9617b36286aSmartynas goto inc_L;
9627b36286aSmartynas break;
9637b36286aSmartynas case 1:
9647b36286aSmartynas if (asub && adj0 > 0.)
9657b36286aSmartynas goto inc_L;
9667b36286aSmartynas break;
9677b36286aSmartynas case 2:
9687b36286aSmartynas if (!asub && adj0 > 0.) {
9697b36286aSmartynas inc_L:
9707b36286aSmartynas L++;
9717b36286aSmartynas inex = STRTOG_Inexact - inex;
9727b36286aSmartynas }
9737b36286aSmartynas }
9741a653cbcSmartynas dval(&adj) = L;
9757b36286aSmartynas }
9767b36286aSmartynas }
9777b36286aSmartynas y = rve + rvbits;
9787b36286aSmartynas
9791a653cbcSmartynas /* adj *= ulp(dval(&rv)); */
9807b36286aSmartynas /* if (asub) rv -= adj; else rv += adj; */
9817b36286aSmartynas
9827b36286aSmartynas if (!denorm && rvbits < nbits) {
9837b36286aSmartynas rvb = lshift(rvb, j = nbits - rvbits);
984384cfdc1Smartynas if (rvb == NULL)
985384cfdc1Smartynas return (STRTOG_NoMemory);
9867b36286aSmartynas rve -= j;
9877b36286aSmartynas rvbits = nbits;
9887b36286aSmartynas }
9891a653cbcSmartynas ab = d2b(dval(&adj), &abe, &abits);
990384cfdc1Smartynas if (ab == NULL)
991384cfdc1Smartynas return (STRTOG_NoMemory);
9927b36286aSmartynas if (abe < 0)
9937b36286aSmartynas rshift(ab, -abe);
994384cfdc1Smartynas else if (abe > 0) {
9957b36286aSmartynas ab = lshift(ab, abe);
996384cfdc1Smartynas if (ab == NULL)
997384cfdc1Smartynas return (STRTOG_NoMemory);
998384cfdc1Smartynas }
9997b36286aSmartynas rvb0 = rvb;
10007b36286aSmartynas if (asub) {
10017b36286aSmartynas /* rv -= adj; */
10027b36286aSmartynas j = hi0bits(rvb->x[rvb->wds-1]);
10037b36286aSmartynas rvb = diff(rvb, ab);
1004384cfdc1Smartynas if (rvb == NULL)
1005384cfdc1Smartynas return (STRTOG_NoMemory);
10067b36286aSmartynas k = rvb0->wds - 1;
10077b36286aSmartynas if (denorm)
10087b36286aSmartynas /* do nothing */;
10097b36286aSmartynas else if (rvb->wds <= k
10107b36286aSmartynas || hi0bits( rvb->x[k]) >
10117b36286aSmartynas hi0bits(rvb0->x[k])) {
10127b36286aSmartynas /* unlikely; can only have lost 1 high bit */
10137b36286aSmartynas if (rve1 == emin) {
10147b36286aSmartynas --rvbits;
10157b36286aSmartynas denorm = 1;
10167b36286aSmartynas }
10177b36286aSmartynas else {
10187b36286aSmartynas rvb = lshift(rvb, 1);
1019384cfdc1Smartynas if (rvb == NULL)
1020384cfdc1Smartynas return (STRTOG_NoMemory);
10217b36286aSmartynas --rve;
10227b36286aSmartynas --rve1;
10237b36286aSmartynas L = finished = 0;
10247b36286aSmartynas }
10257b36286aSmartynas }
10267b36286aSmartynas }
10277b36286aSmartynas else {
10287b36286aSmartynas rvb = sum(rvb, ab);
1029384cfdc1Smartynas if (rvb == NULL)
1030384cfdc1Smartynas return (STRTOG_NoMemory);
10317b36286aSmartynas k = rvb->wds - 1;
10327b36286aSmartynas if (k >= rvb0->wds
10337b36286aSmartynas || hi0bits(rvb->x[k]) < hi0bits(rvb0->x[k])) {
10347b36286aSmartynas if (denorm) {
10357b36286aSmartynas if (++rvbits == nbits)
10367b36286aSmartynas denorm = 0;
10377b36286aSmartynas }
10387b36286aSmartynas else {
10397b36286aSmartynas rshift(rvb, 1);
10407b36286aSmartynas rve++;
10417b36286aSmartynas rve1++;
10427b36286aSmartynas L = 0;
10437b36286aSmartynas }
10447b36286aSmartynas }
10457b36286aSmartynas }
10467b36286aSmartynas Bfree(ab);
10477b36286aSmartynas Bfree(rvb0);
10487b36286aSmartynas if (finished)
10497b36286aSmartynas break;
10507b36286aSmartynas
10517b36286aSmartynas z = rve + rvbits;
10527b36286aSmartynas if (y == z && L) {
10537b36286aSmartynas /* Can we stop now? */
10541a653cbcSmartynas tol = dval(&adj) * 5e-16; /* > max rel error */
10551a653cbcSmartynas dval(&adj) = adj0 - .5;
10561a653cbcSmartynas if (dval(&adj) < -tol) {
10577b36286aSmartynas if (adj0 > tol) {
10587b36286aSmartynas irv |= inex;
10597b36286aSmartynas break;
10607b36286aSmartynas }
10617b36286aSmartynas }
10621a653cbcSmartynas else if (dval(&adj) > tol && adj0 < 1. - tol) {
10637b36286aSmartynas irv |= inex;
10647b36286aSmartynas break;
10657b36286aSmartynas }
10667b36286aSmartynas }
10677b36286aSmartynas bb0 = denorm ? 0 : trailz(rvb);
10687b36286aSmartynas Bfree(bb);
10697b36286aSmartynas Bfree(bd);
10707b36286aSmartynas Bfree(bs);
10717b36286aSmartynas Bfree(delta);
10727b36286aSmartynas }
10737b36286aSmartynas if (!denorm && (j = nbits - rvbits)) {
1074384cfdc1Smartynas if (j > 0) {
10757b36286aSmartynas rvb = lshift(rvb, j);
1076384cfdc1Smartynas if (rvb == NULL)
1077384cfdc1Smartynas return (STRTOG_NoMemory);
1078384cfdc1Smartynas }
10797b36286aSmartynas else
10807b36286aSmartynas rshift(rvb, -j);
10817b36286aSmartynas rve -= j;
10827b36286aSmartynas }
10837b36286aSmartynas *exp = rve;
10847b36286aSmartynas Bfree(bb);
10857b36286aSmartynas Bfree(bd);
10867b36286aSmartynas Bfree(bs);
10877b36286aSmartynas Bfree(bd0);
10887b36286aSmartynas Bfree(delta);
10897b36286aSmartynas if (rve > fpi->emax) {
1090aad11945Smartynas switch(fpi->rounding & 3) {
1091aad11945Smartynas case FPI_Round_near:
1092aad11945Smartynas goto huge;
1093aad11945Smartynas case FPI_Round_up:
1094aad11945Smartynas if (!sign)
1095aad11945Smartynas goto huge;
1096aad11945Smartynas break;
1097aad11945Smartynas case FPI_Round_down:
1098aad11945Smartynas if (sign)
1099aad11945Smartynas goto huge;
1100aad11945Smartynas }
1101aad11945Smartynas /* Round to largest representable magnitude */
1102aad11945Smartynas Bfree(rvb);
1103aad11945Smartynas rvb = 0;
1104aad11945Smartynas irv = STRTOG_Normal | STRTOG_Inexlo;
1105aad11945Smartynas *exp = fpi->emax;
1106aad11945Smartynas b = bits;
1107aad11945Smartynas be = b + ((fpi->nbits + 31) >> 5);
1108aad11945Smartynas while(b < be)
1109aad11945Smartynas *b++ = -1;
1110aad11945Smartynas if ((j = fpi->nbits & 0x1f))
1111aad11945Smartynas *--be >>= (32 - j);
1112aad11945Smartynas goto ret;
11137b36286aSmartynas huge:
11147b36286aSmartynas rvb->wds = 0;
11157b36286aSmartynas irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
11167b36286aSmartynas #ifndef NO_ERRNO
11177b36286aSmartynas errno = ERANGE;
11187b36286aSmartynas #endif
11197b36286aSmartynas infnanexp:
11207b36286aSmartynas *exp = fpi->emax + 1;
11217b36286aSmartynas }
11227b36286aSmartynas ret:
11237b36286aSmartynas if (denorm) {
11247b36286aSmartynas if (sudden_underflow) {
11257b36286aSmartynas rvb->wds = 0;
11267b36286aSmartynas irv = STRTOG_Underflow | STRTOG_Inexlo;
1127aad11945Smartynas #ifndef NO_ERRNO
1128aad11945Smartynas errno = ERANGE;
1129aad11945Smartynas #endif
11307b36286aSmartynas }
11317b36286aSmartynas else {
11327b36286aSmartynas irv = (irv & ~STRTOG_Retmask) |
11337b36286aSmartynas (rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
1134aad11945Smartynas if (irv & STRTOG_Inexact) {
11357b36286aSmartynas irv |= STRTOG_Underflow;
1136aad11945Smartynas #ifndef NO_ERRNO
1137aad11945Smartynas errno = ERANGE;
1138aad11945Smartynas #endif
1139aad11945Smartynas }
11407b36286aSmartynas }
11417b36286aSmartynas }
11427b36286aSmartynas if (se)
11437b36286aSmartynas *se = (char *)s;
11447b36286aSmartynas if (sign)
11457b36286aSmartynas irv |= STRTOG_Neg;
11467b36286aSmartynas if (rvb) {
11477b36286aSmartynas copybits(bits, nbits, rvb);
11487b36286aSmartynas Bfree(rvb);
11497b36286aSmartynas }
11507b36286aSmartynas return irv;
11517b36286aSmartynas }
1152