11181b21fSPeter Avalos /****************************************************************
21181b21fSPeter Avalos
31181b21fSPeter Avalos The author of this software is David M. Gay.
41181b21fSPeter Avalos
51181b21fSPeter Avalos Copyright (C) 1998-2001 by Lucent Technologies
61181b21fSPeter Avalos All Rights Reserved
71181b21fSPeter Avalos
81181b21fSPeter Avalos Permission to use, copy, modify, and distribute this software and
91181b21fSPeter Avalos its documentation for any purpose and without fee is hereby
101181b21fSPeter Avalos granted, provided that the above copyright notice appear in all
111181b21fSPeter Avalos copies and that both that the copyright notice and this
121181b21fSPeter Avalos permission notice and warranty disclaimer appear in supporting
131181b21fSPeter Avalos documentation, and that the name of Lucent or any of its entities
141181b21fSPeter Avalos not be used in advertising or publicity pertaining to
151181b21fSPeter Avalos distribution of the software without specific, written prior
161181b21fSPeter Avalos permission.
171181b21fSPeter Avalos
181181b21fSPeter Avalos LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
191181b21fSPeter Avalos INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
201181b21fSPeter Avalos IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
211181b21fSPeter Avalos SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
221181b21fSPeter Avalos WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
231181b21fSPeter Avalos IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
241181b21fSPeter Avalos ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
251181b21fSPeter Avalos THIS SOFTWARE.
261181b21fSPeter Avalos
271181b21fSPeter Avalos ****************************************************************/
281181b21fSPeter Avalos
291181b21fSPeter Avalos /* Please send bug reports to David M. Gay (dmg at acm dot org,
301181b21fSPeter Avalos * with " at " changed at "@" and " dot " changed to "."). */
311181b21fSPeter Avalos
321181b21fSPeter Avalos #include "gdtoaimp.h"
331181b21fSPeter Avalos
341181b21fSPeter Avalos #ifdef USE_LOCALE
351181b21fSPeter Avalos #include "locale.h"
361181b21fSPeter Avalos #endif
371181b21fSPeter Avalos
381181b21fSPeter Avalos static CONST int
391181b21fSPeter Avalos fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21,
401181b21fSPeter Avalos 24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
411181b21fSPeter Avalos 47, 49, 52
421181b21fSPeter Avalos #ifdef VAX
431181b21fSPeter Avalos , 54, 56
441181b21fSPeter Avalos #endif
451181b21fSPeter Avalos };
461181b21fSPeter Avalos
471181b21fSPeter Avalos Bigint *
481181b21fSPeter Avalos #ifdef KR_headers
increment(b)491181b21fSPeter Avalos increment(b) Bigint *b;
501181b21fSPeter Avalos #else
511181b21fSPeter Avalos increment(Bigint *b)
521181b21fSPeter Avalos #endif
531181b21fSPeter Avalos {
541181b21fSPeter Avalos ULong *x, *xe;
551181b21fSPeter Avalos Bigint *b1;
561181b21fSPeter Avalos #ifdef Pack_16
571181b21fSPeter Avalos ULong carry = 1, y;
581181b21fSPeter Avalos #endif
591181b21fSPeter Avalos
601181b21fSPeter Avalos x = b->x;
611181b21fSPeter Avalos xe = x + b->wds;
621181b21fSPeter Avalos #ifdef Pack_32
631181b21fSPeter Avalos do {
641181b21fSPeter Avalos if (*x < (ULong)0xffffffffL) {
651181b21fSPeter Avalos ++*x;
661181b21fSPeter Avalos return b;
671181b21fSPeter Avalos }
681181b21fSPeter Avalos *x++ = 0;
691181b21fSPeter Avalos } while(x < xe);
701181b21fSPeter Avalos #else
711181b21fSPeter Avalos do {
721181b21fSPeter Avalos y = *x + carry;
731181b21fSPeter Avalos carry = y >> 16;
741181b21fSPeter Avalos *x++ = y & 0xffff;
751181b21fSPeter Avalos if (!carry)
761181b21fSPeter Avalos return b;
771181b21fSPeter Avalos } while(x < xe);
781181b21fSPeter Avalos if (carry)
791181b21fSPeter Avalos #endif
801181b21fSPeter Avalos {
811181b21fSPeter Avalos if (b->wds >= b->maxwds) {
821181b21fSPeter Avalos b1 = Balloc(b->k+1);
831181b21fSPeter Avalos Bcopy(b1,b);
841181b21fSPeter Avalos Bfree(b);
851181b21fSPeter Avalos b = b1;
861181b21fSPeter Avalos }
871181b21fSPeter Avalos b->x[b->wds++] = 1;
881181b21fSPeter Avalos }
891181b21fSPeter Avalos return b;
901181b21fSPeter Avalos }
911181b21fSPeter Avalos
921181b21fSPeter Avalos void
931181b21fSPeter Avalos #ifdef KR_headers
decrement(b)941181b21fSPeter Avalos decrement(b) Bigint *b;
951181b21fSPeter Avalos #else
961181b21fSPeter Avalos decrement(Bigint *b)
971181b21fSPeter Avalos #endif
981181b21fSPeter Avalos {
991181b21fSPeter Avalos ULong *x, *xe;
1001181b21fSPeter Avalos #ifdef Pack_16
1011181b21fSPeter Avalos ULong borrow = 1, y;
1021181b21fSPeter Avalos #endif
1031181b21fSPeter Avalos
1041181b21fSPeter Avalos x = b->x;
1051181b21fSPeter Avalos xe = x + b->wds;
1061181b21fSPeter Avalos #ifdef Pack_32
1071181b21fSPeter Avalos do {
1081181b21fSPeter Avalos if (*x) {
1091181b21fSPeter Avalos --*x;
1101181b21fSPeter Avalos break;
1111181b21fSPeter Avalos }
1121181b21fSPeter Avalos *x++ = 0xffffffffL;
1131181b21fSPeter Avalos }
1141181b21fSPeter Avalos while(x < xe);
1151181b21fSPeter Avalos #else
1161181b21fSPeter Avalos do {
1171181b21fSPeter Avalos y = *x - borrow;
1181181b21fSPeter Avalos borrow = (y & 0x10000) >> 16;
1191181b21fSPeter Avalos *x++ = y & 0xffff;
1201181b21fSPeter Avalos } while(borrow && x < xe);
1211181b21fSPeter Avalos #endif
1221181b21fSPeter Avalos }
1231181b21fSPeter Avalos
1241181b21fSPeter Avalos static int
1251181b21fSPeter Avalos #ifdef KR_headers
all_on(b,n)1261181b21fSPeter Avalos all_on(b, n) Bigint *b; int n;
1271181b21fSPeter Avalos #else
1281181b21fSPeter Avalos all_on(Bigint *b, int n)
1291181b21fSPeter Avalos #endif
1301181b21fSPeter Avalos {
1311181b21fSPeter Avalos ULong *x, *xe;
1321181b21fSPeter Avalos
1331181b21fSPeter Avalos x = b->x;
1341181b21fSPeter Avalos xe = x + (n >> kshift);
1351181b21fSPeter Avalos while(x < xe)
1361181b21fSPeter Avalos if ((*x++ & ALL_ON) != ALL_ON)
1371181b21fSPeter Avalos return 0;
1381181b21fSPeter Avalos if (n &= kmask)
1391181b21fSPeter Avalos return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON;
1401181b21fSPeter Avalos return 1;
1411181b21fSPeter Avalos }
1421181b21fSPeter Avalos
1431181b21fSPeter Avalos Bigint *
1441181b21fSPeter Avalos #ifdef KR_headers
set_ones(b,n)1451181b21fSPeter Avalos set_ones(b, n) Bigint *b; int n;
1461181b21fSPeter Avalos #else
1471181b21fSPeter Avalos set_ones(Bigint *b, int n)
1481181b21fSPeter Avalos #endif
1491181b21fSPeter Avalos {
1501181b21fSPeter Avalos int k;
1511181b21fSPeter Avalos ULong *x, *xe;
1521181b21fSPeter Avalos
1531181b21fSPeter Avalos k = (n + ((1 << kshift) - 1)) >> kshift;
1541181b21fSPeter Avalos if (b->k < k) {
1551181b21fSPeter Avalos Bfree(b);
1561181b21fSPeter Avalos b = Balloc(k);
1571181b21fSPeter Avalos }
1581181b21fSPeter Avalos k = n >> kshift;
1591181b21fSPeter Avalos if (n &= kmask)
1601181b21fSPeter Avalos k++;
1611181b21fSPeter Avalos b->wds = k;
1621181b21fSPeter Avalos x = b->x;
1631181b21fSPeter Avalos xe = x + k;
1641181b21fSPeter Avalos while(x < xe)
1651181b21fSPeter Avalos *x++ = ALL_ON;
1661181b21fSPeter Avalos if (n)
1671181b21fSPeter Avalos x[-1] >>= ULbits - n;
1681181b21fSPeter Avalos return b;
1691181b21fSPeter Avalos }
1701181b21fSPeter Avalos
1711181b21fSPeter Avalos static int
rvOK(d,fpi,exp,bits,exact,rd,irv)1721181b21fSPeter Avalos rvOK
1731181b21fSPeter Avalos #ifdef KR_headers
1741181b21fSPeter Avalos (d, fpi, exp, bits, exact, rd, irv)
1752a5b511eSPeter Avalos U *d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
1761181b21fSPeter Avalos #else
1772a5b511eSPeter Avalos (U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
1781181b21fSPeter Avalos #endif
1791181b21fSPeter Avalos {
1801181b21fSPeter Avalos Bigint *b;
1811181b21fSPeter Avalos ULong carry, inex, lostbits;
1821181b21fSPeter Avalos int bdif, e, j, k, k1, nb, rv;
1831181b21fSPeter Avalos
1841181b21fSPeter Avalos carry = rv = 0;
1852a5b511eSPeter Avalos b = d2b(dval(d), &e, &bdif);
1861181b21fSPeter Avalos bdif -= nb = fpi->nbits;
1871181b21fSPeter Avalos e += bdif;
1881181b21fSPeter Avalos if (bdif <= 0) {
1891181b21fSPeter Avalos if (exact)
1901181b21fSPeter Avalos goto trunc;
1911181b21fSPeter Avalos goto ret;
1921181b21fSPeter Avalos }
1931181b21fSPeter Avalos if (P == nb) {
1941181b21fSPeter Avalos if (
1951181b21fSPeter Avalos #ifndef IMPRECISE_INEXACT
1961181b21fSPeter Avalos exact &&
1971181b21fSPeter Avalos #endif
1981181b21fSPeter Avalos fpi->rounding ==
1991181b21fSPeter Avalos #ifdef RND_PRODQUOT
2001181b21fSPeter Avalos FPI_Round_near
2011181b21fSPeter Avalos #else
2021181b21fSPeter Avalos Flt_Rounds
2031181b21fSPeter Avalos #endif
2041181b21fSPeter Avalos ) goto trunc;
2051181b21fSPeter Avalos goto ret;
2061181b21fSPeter Avalos }
2071181b21fSPeter Avalos switch(rd) {
2081181b21fSPeter Avalos case 1: /* round down (toward -Infinity) */
2091181b21fSPeter Avalos goto trunc;
2101181b21fSPeter Avalos case 2: /* round up (toward +Infinity) */
2111181b21fSPeter Avalos break;
2121181b21fSPeter Avalos default: /* round near */
2131181b21fSPeter Avalos k = bdif - 1;
2141181b21fSPeter Avalos if (k < 0)
2151181b21fSPeter Avalos goto trunc;
2161181b21fSPeter Avalos if (!k) {
2171181b21fSPeter Avalos if (!exact)
2181181b21fSPeter Avalos goto ret;
2191181b21fSPeter Avalos if (b->x[0] & 2)
2201181b21fSPeter Avalos break;
2211181b21fSPeter Avalos goto trunc;
2221181b21fSPeter Avalos }
2231181b21fSPeter Avalos if (b->x[k>>kshift] & ((ULong)1 << (k & kmask)))
2241181b21fSPeter Avalos break;
2251181b21fSPeter Avalos goto trunc;
2261181b21fSPeter Avalos }
2271181b21fSPeter Avalos /* "break" cases: round up 1 bit, then truncate; bdif > 0 */
2281181b21fSPeter Avalos carry = 1;
2291181b21fSPeter Avalos trunc:
2301181b21fSPeter Avalos inex = lostbits = 0;
2311181b21fSPeter Avalos if (bdif > 0) {
2321181b21fSPeter Avalos if ( (lostbits = any_on(b, bdif)) !=0)
2331181b21fSPeter Avalos inex = STRTOG_Inexlo;
2341181b21fSPeter Avalos rshift(b, bdif);
2351181b21fSPeter Avalos if (carry) {
2361181b21fSPeter Avalos inex = STRTOG_Inexhi;
2371181b21fSPeter Avalos b = increment(b);
2381181b21fSPeter Avalos if ( (j = nb & kmask) !=0)
2391181b21fSPeter Avalos j = ULbits - j;
2401181b21fSPeter Avalos if (hi0bits(b->x[b->wds - 1]) != j) {
2411181b21fSPeter Avalos if (!lostbits)
2421181b21fSPeter Avalos lostbits = b->x[0] & 1;
2431181b21fSPeter Avalos rshift(b, 1);
2441181b21fSPeter Avalos e++;
2451181b21fSPeter Avalos }
2461181b21fSPeter Avalos }
2471181b21fSPeter Avalos }
2481181b21fSPeter Avalos else if (bdif < 0)
2491181b21fSPeter Avalos b = lshift(b, -bdif);
2501181b21fSPeter Avalos if (e < fpi->emin) {
2511181b21fSPeter Avalos k = fpi->emin - e;
2521181b21fSPeter Avalos e = fpi->emin;
2531181b21fSPeter Avalos if (k > nb || fpi->sudden_underflow) {
2541181b21fSPeter Avalos b->wds = inex = 0;
2551181b21fSPeter Avalos *irv = STRTOG_Underflow | STRTOG_Inexlo;
2561181b21fSPeter Avalos }
2571181b21fSPeter Avalos else {
2581181b21fSPeter Avalos k1 = k - 1;
2591181b21fSPeter Avalos if (k1 > 0 && !lostbits)
2601181b21fSPeter Avalos lostbits = any_on(b, k1);
2611181b21fSPeter Avalos if (!lostbits && !exact)
2621181b21fSPeter Avalos goto ret;
2631181b21fSPeter Avalos lostbits |=
2641181b21fSPeter Avalos carry = b->x[k1>>kshift] & (1 << (k1 & kmask));
2651181b21fSPeter Avalos rshift(b, k);
2661181b21fSPeter Avalos *irv = STRTOG_Denormal;
2671181b21fSPeter Avalos if (carry) {
2681181b21fSPeter Avalos b = increment(b);
2691181b21fSPeter Avalos inex = STRTOG_Inexhi | STRTOG_Underflow;
2701181b21fSPeter Avalos }
2711181b21fSPeter Avalos else if (lostbits)
2721181b21fSPeter Avalos inex = STRTOG_Inexlo | STRTOG_Underflow;
2731181b21fSPeter Avalos }
2741181b21fSPeter Avalos }
2751181b21fSPeter Avalos else if (e > fpi->emax) {
2761181b21fSPeter Avalos e = fpi->emax + 1;
2771181b21fSPeter Avalos *irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
2781181b21fSPeter Avalos #ifndef NO_ERRNO
2791181b21fSPeter Avalos errno = ERANGE;
2801181b21fSPeter Avalos #endif
2811181b21fSPeter Avalos b->wds = inex = 0;
2821181b21fSPeter Avalos }
2831181b21fSPeter Avalos *exp = e;
2841181b21fSPeter Avalos copybits(bits, nb, b);
2851181b21fSPeter Avalos *irv |= inex;
2861181b21fSPeter Avalos rv = 1;
2871181b21fSPeter Avalos ret:
2881181b21fSPeter Avalos Bfree(b);
2891181b21fSPeter Avalos return rv;
2901181b21fSPeter Avalos }
2911181b21fSPeter Avalos
2921181b21fSPeter Avalos static int
2931181b21fSPeter Avalos #ifdef KR_headers
mantbits(d)2942a5b511eSPeter Avalos mantbits(d) U *d;
2951181b21fSPeter Avalos #else
2962a5b511eSPeter Avalos mantbits(U *d)
2971181b21fSPeter Avalos #endif
2981181b21fSPeter Avalos {
2991181b21fSPeter Avalos ULong L;
3001181b21fSPeter Avalos #ifdef VAX
3011181b21fSPeter Avalos L = word1(d) << 16 | word1(d) >> 16;
3021181b21fSPeter Avalos if (L)
3031181b21fSPeter Avalos #else
3041181b21fSPeter Avalos if ( (L = word1(d)) !=0)
3051181b21fSPeter Avalos #endif
3061181b21fSPeter Avalos return P - lo0bits(&L);
3071181b21fSPeter Avalos #ifdef VAX
3081181b21fSPeter Avalos L = word0(d) << 16 | word0(d) >> 16 | Exp_msk11;
3091181b21fSPeter Avalos #else
3101181b21fSPeter Avalos L = word0(d) | Exp_msk1;
3111181b21fSPeter Avalos #endif
3121181b21fSPeter Avalos return P - 32 - lo0bits(&L);
3131181b21fSPeter Avalos }
3141181b21fSPeter Avalos
3151181b21fSPeter Avalos int
strtodg_l(s00,se,fpi,exp,bits,loc)316*0d5acd74SJohn Marino strtodg_l
3171181b21fSPeter Avalos #ifdef KR_headers
318*0d5acd74SJohn Marino (s00, se, fpi, exp, bits, loc)
319*0d5acd74SJohn Marino CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; locale_t loc;
3201181b21fSPeter Avalos #else
321*0d5acd74SJohn Marino (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits, locale_t loc)
3221181b21fSPeter Avalos #endif
3231181b21fSPeter Avalos {
3241181b21fSPeter Avalos int abe, abits, asub;
3251181b21fSPeter Avalos int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm;
3261181b21fSPeter Avalos int dsign, e, e1, e2, emin, esign, finished, i, inex, irv;
3271181b21fSPeter Avalos int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
3281181b21fSPeter Avalos int sudden_underflow;
3291181b21fSPeter Avalos CONST char *s, *s0, *s1;
3302a5b511eSPeter Avalos double adj0, tol;
3311181b21fSPeter Avalos Long L;
3322a5b511eSPeter Avalos U adj, rv;
3331181b21fSPeter Avalos ULong *b, *be, y, z;
3341181b21fSPeter Avalos Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
3351181b21fSPeter Avalos #ifdef USE_LOCALE /*{{*/
3361181b21fSPeter Avalos #ifdef NO_LOCALE_CACHE
337*0d5acd74SJohn Marino char *decimalpoint = localeconv_l(loc)->decimal_point;
3381181b21fSPeter Avalos int dplen = strlen(decimalpoint);
3391181b21fSPeter Avalos #else
3401181b21fSPeter Avalos char *decimalpoint;
3411181b21fSPeter Avalos static char *decimalpoint_cache;
3421181b21fSPeter Avalos static int dplen;
3431181b21fSPeter Avalos if (!(s0 = decimalpoint_cache)) {
344*0d5acd74SJohn Marino s0 = localeconv_l(loc)->decimal_point;
3452a5b511eSPeter Avalos if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
3461181b21fSPeter Avalos strcpy(decimalpoint_cache, s0);
3471181b21fSPeter Avalos s0 = decimalpoint_cache;
3481181b21fSPeter Avalos }
3491181b21fSPeter Avalos dplen = strlen(s0);
3501181b21fSPeter Avalos }
3511181b21fSPeter Avalos decimalpoint = (char*)s0;
3521181b21fSPeter Avalos #endif /*NO_LOCALE_CACHE*/
3531181b21fSPeter Avalos #else /*USE_LOCALE}{*/
3541181b21fSPeter Avalos #define dplen 1
3551181b21fSPeter Avalos #endif /*USE_LOCALE}}*/
3561181b21fSPeter Avalos
3571181b21fSPeter Avalos irv = STRTOG_Zero;
3581181b21fSPeter Avalos denorm = sign = nz0 = nz = 0;
3592a5b511eSPeter Avalos dval(&rv) = 0.;
3601181b21fSPeter Avalos rvb = 0;
3611181b21fSPeter Avalos nbits = fpi->nbits;
3621181b21fSPeter Avalos for(s = s00;;s++) switch(*s) {
3631181b21fSPeter Avalos case '-':
3641181b21fSPeter Avalos sign = 1;
3651181b21fSPeter Avalos /* no break */
3661181b21fSPeter Avalos case '+':
3671181b21fSPeter Avalos if (*++s)
3681181b21fSPeter Avalos goto break2;
3691181b21fSPeter Avalos /* no break */
3701181b21fSPeter Avalos case 0:
3711181b21fSPeter Avalos sign = 0;
3721181b21fSPeter Avalos irv = STRTOG_NoNumber;
3731181b21fSPeter Avalos s = s00;
3741181b21fSPeter Avalos goto ret;
3751181b21fSPeter Avalos case '\t':
3761181b21fSPeter Avalos case '\n':
3771181b21fSPeter Avalos case '\v':
3781181b21fSPeter Avalos case '\f':
3791181b21fSPeter Avalos case '\r':
3801181b21fSPeter Avalos case ' ':
3811181b21fSPeter Avalos continue;
3821181b21fSPeter Avalos default:
3831181b21fSPeter Avalos goto break2;
3841181b21fSPeter Avalos }
3851181b21fSPeter Avalos break2:
3861181b21fSPeter Avalos if (*s == '0') {
3871181b21fSPeter Avalos #ifndef NO_HEX_FP
3881181b21fSPeter Avalos switch(s[1]) {
3891181b21fSPeter Avalos case 'x':
3901181b21fSPeter Avalos case 'X':
3911181b21fSPeter Avalos irv = gethex(&s, fpi, exp, &rvb, sign);
3921181b21fSPeter Avalos if (irv == STRTOG_NoNumber) {
3931181b21fSPeter Avalos s = s00;
3941181b21fSPeter Avalos sign = 0;
3951181b21fSPeter Avalos }
3961181b21fSPeter Avalos goto ret;
3971181b21fSPeter Avalos }
3981181b21fSPeter Avalos #endif
3991181b21fSPeter Avalos nz0 = 1;
4001181b21fSPeter Avalos while(*++s == '0') ;
4011181b21fSPeter Avalos if (!*s)
4021181b21fSPeter Avalos goto ret;
4031181b21fSPeter Avalos }
4041181b21fSPeter Avalos sudden_underflow = fpi->sudden_underflow;
4051181b21fSPeter Avalos s0 = s;
4061181b21fSPeter Avalos y = z = 0;
4071181b21fSPeter Avalos for(decpt = nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
4081181b21fSPeter Avalos if (nd < 9)
4091181b21fSPeter Avalos y = 10*y + c - '0';
4101181b21fSPeter Avalos else if (nd < 16)
4111181b21fSPeter Avalos z = 10*z + c - '0';
4121181b21fSPeter Avalos nd0 = nd;
4131181b21fSPeter Avalos #ifdef USE_LOCALE
4141181b21fSPeter Avalos if (c == *decimalpoint) {
4151181b21fSPeter Avalos for(i = 1; decimalpoint[i]; ++i)
4161181b21fSPeter Avalos if (s[i] != decimalpoint[i])
4171181b21fSPeter Avalos goto dig_done;
4181181b21fSPeter Avalos s += i;
4191181b21fSPeter Avalos c = *s;
4201181b21fSPeter Avalos #else
4211181b21fSPeter Avalos if (c == '.') {
4221181b21fSPeter Avalos c = *++s;
4231181b21fSPeter Avalos #endif
4241181b21fSPeter Avalos decpt = 1;
4251181b21fSPeter Avalos if (!nd) {
4261181b21fSPeter Avalos for(; c == '0'; c = *++s)
4271181b21fSPeter Avalos nz++;
4281181b21fSPeter Avalos if (c > '0' && c <= '9') {
4291181b21fSPeter Avalos s0 = s;
4301181b21fSPeter Avalos nf += nz;
4311181b21fSPeter Avalos nz = 0;
4321181b21fSPeter Avalos goto have_dig;
4331181b21fSPeter Avalos }
4341181b21fSPeter Avalos goto dig_done;
4351181b21fSPeter Avalos }
4361181b21fSPeter Avalos for(; c >= '0' && c <= '9'; c = *++s) {
4371181b21fSPeter Avalos have_dig:
4381181b21fSPeter Avalos nz++;
4391181b21fSPeter Avalos if (c -= '0') {
4401181b21fSPeter Avalos nf += nz;
4411181b21fSPeter Avalos for(i = 1; i < nz; i++)
4421181b21fSPeter Avalos if (nd++ < 9)
4431181b21fSPeter Avalos y *= 10;
4441181b21fSPeter Avalos else if (nd <= DBL_DIG + 1)
4451181b21fSPeter Avalos z *= 10;
4461181b21fSPeter Avalos if (nd++ < 9)
4471181b21fSPeter Avalos y = 10*y + c;
4481181b21fSPeter Avalos else if (nd <= DBL_DIG + 1)
4491181b21fSPeter Avalos z = 10*z + c;
4501181b21fSPeter Avalos nz = 0;
4511181b21fSPeter Avalos }
4521181b21fSPeter Avalos }
4531181b21fSPeter Avalos }/*}*/
4541181b21fSPeter Avalos dig_done:
4551181b21fSPeter Avalos e = 0;
4561181b21fSPeter Avalos if (c == 'e' || c == 'E') {
4571181b21fSPeter Avalos if (!nd && !nz && !nz0) {
4581181b21fSPeter Avalos irv = STRTOG_NoNumber;
4591181b21fSPeter Avalos s = s00;
4601181b21fSPeter Avalos goto ret;
4611181b21fSPeter Avalos }
4621181b21fSPeter Avalos s00 = s;
4631181b21fSPeter Avalos esign = 0;
4641181b21fSPeter Avalos switch(c = *++s) {
4651181b21fSPeter Avalos case '-':
4661181b21fSPeter Avalos esign = 1;
4671181b21fSPeter Avalos case '+':
4681181b21fSPeter Avalos c = *++s;
4691181b21fSPeter Avalos }
4701181b21fSPeter Avalos if (c >= '0' && c <= '9') {
4711181b21fSPeter Avalos while(c == '0')
4721181b21fSPeter Avalos c = *++s;
4731181b21fSPeter Avalos if (c > '0' && c <= '9') {
4741181b21fSPeter Avalos L = c - '0';
4751181b21fSPeter Avalos s1 = s;
4761181b21fSPeter Avalos while((c = *++s) >= '0' && c <= '9')
4771181b21fSPeter Avalos L = 10*L + c - '0';
4781181b21fSPeter Avalos if (s - s1 > 8 || L > 19999)
4791181b21fSPeter Avalos /* Avoid confusion from exponents
4801181b21fSPeter Avalos * so large that e might overflow.
4811181b21fSPeter Avalos */
4821181b21fSPeter Avalos e = 19999; /* safe for 16 bit ints */
4831181b21fSPeter Avalos else
4841181b21fSPeter Avalos e = (int)L;
4851181b21fSPeter Avalos if (esign)
4861181b21fSPeter Avalos e = -e;
4871181b21fSPeter Avalos }
4881181b21fSPeter Avalos else
4891181b21fSPeter Avalos e = 0;
4901181b21fSPeter Avalos }
4911181b21fSPeter Avalos else
4921181b21fSPeter Avalos s = s00;
4931181b21fSPeter Avalos }
4941181b21fSPeter Avalos if (!nd) {
4951181b21fSPeter Avalos if (!nz && !nz0) {
4961181b21fSPeter Avalos #ifdef INFNAN_CHECK
4971181b21fSPeter Avalos /* Check for Nan and Infinity */
4981181b21fSPeter Avalos if (!decpt)
4991181b21fSPeter Avalos switch(c) {
5001181b21fSPeter Avalos case 'i':
5011181b21fSPeter Avalos case 'I':
5021181b21fSPeter Avalos if (match(&s,"nf")) {
5031181b21fSPeter Avalos --s;
5041181b21fSPeter Avalos if (!match(&s,"inity"))
5051181b21fSPeter Avalos ++s;
5061181b21fSPeter Avalos irv = STRTOG_Infinite;
5071181b21fSPeter Avalos goto infnanexp;
5081181b21fSPeter Avalos }
5091181b21fSPeter Avalos break;
5101181b21fSPeter Avalos case 'n':
5111181b21fSPeter Avalos case 'N':
5121181b21fSPeter Avalos if (match(&s, "an")) {
5131181b21fSPeter Avalos irv = STRTOG_NaN;
5141181b21fSPeter Avalos *exp = fpi->emax + 1;
5151181b21fSPeter Avalos #ifndef No_Hex_NaN
5161181b21fSPeter Avalos if (*s == '(') /*)*/
5171181b21fSPeter Avalos irv = hexnan(&s, fpi, bits);
5181181b21fSPeter Avalos #endif
5191181b21fSPeter Avalos goto infnanexp;
5201181b21fSPeter Avalos }
5211181b21fSPeter Avalos }
5221181b21fSPeter Avalos #endif /* INFNAN_CHECK */
5231181b21fSPeter Avalos irv = STRTOG_NoNumber;
5241181b21fSPeter Avalos s = s00;
5251181b21fSPeter Avalos }
5261181b21fSPeter Avalos goto ret;
5271181b21fSPeter Avalos }
5281181b21fSPeter Avalos
5291181b21fSPeter Avalos irv = STRTOG_Normal;
5301181b21fSPeter Avalos e1 = e -= nf;
5311181b21fSPeter Avalos rd = 0;
5321181b21fSPeter Avalos switch(fpi->rounding & 3) {
5331181b21fSPeter Avalos case FPI_Round_up:
5341181b21fSPeter Avalos rd = 2 - sign;
5351181b21fSPeter Avalos break;
5361181b21fSPeter Avalos case FPI_Round_zero:
5371181b21fSPeter Avalos rd = 1;
5381181b21fSPeter Avalos break;
5391181b21fSPeter Avalos case FPI_Round_down:
5401181b21fSPeter Avalos rd = 1 + sign;
5411181b21fSPeter Avalos }
5421181b21fSPeter Avalos
5431181b21fSPeter Avalos /* Now we have nd0 digits, starting at s0, followed by a
5441181b21fSPeter Avalos * decimal point, followed by nd-nd0 digits. The number we're
5451181b21fSPeter Avalos * after is the integer represented by those digits times
5461181b21fSPeter Avalos * 10**e */
5471181b21fSPeter Avalos
5481181b21fSPeter Avalos if (!nd0)
5491181b21fSPeter Avalos nd0 = nd;
5501181b21fSPeter Avalos k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
5512a5b511eSPeter Avalos dval(&rv) = y;
5521181b21fSPeter Avalos if (k > 9)
5532a5b511eSPeter Avalos dval(&rv) = tens[k - 9] * dval(&rv) + z;
5541181b21fSPeter Avalos bd0 = 0;
5551181b21fSPeter Avalos if (nbits <= P && nd <= DBL_DIG) {
5561181b21fSPeter Avalos if (!e) {
5572a5b511eSPeter Avalos if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv))
5581181b21fSPeter Avalos goto ret;
5591181b21fSPeter Avalos }
5601181b21fSPeter Avalos else if (e > 0) {
5611181b21fSPeter Avalos if (e <= Ten_pmax) {
5621181b21fSPeter Avalos #ifdef VAX
5631181b21fSPeter Avalos goto vax_ovfl_check;
5641181b21fSPeter Avalos #else
5652a5b511eSPeter Avalos i = fivesbits[e] + mantbits(&rv) <= P;
5662a5b511eSPeter Avalos /* rv = */ rounded_product(dval(&rv), tens[e]);
5672a5b511eSPeter Avalos if (rvOK(&rv, fpi, exp, bits, i, rd, &irv))
5681181b21fSPeter Avalos goto ret;
5691181b21fSPeter Avalos e1 -= e;
5701181b21fSPeter Avalos goto rv_notOK;
5711181b21fSPeter Avalos #endif
5721181b21fSPeter Avalos }
5731181b21fSPeter Avalos i = DBL_DIG - nd;
5741181b21fSPeter Avalos if (e <= Ten_pmax + i) {
5751181b21fSPeter Avalos /* A fancier test would sometimes let us do
5761181b21fSPeter Avalos * this for larger i values.
5771181b21fSPeter Avalos */
5781181b21fSPeter Avalos e2 = e - i;
5791181b21fSPeter Avalos e1 -= i;
5802a5b511eSPeter Avalos dval(&rv) *= tens[i];
5811181b21fSPeter Avalos #ifdef VAX
5821181b21fSPeter Avalos /* VAX exponent range is so narrow we must
5831181b21fSPeter Avalos * worry about overflow here...
5841181b21fSPeter Avalos */
5851181b21fSPeter Avalos vax_ovfl_check:
5862a5b511eSPeter Avalos dval(&adj) = dval(&rv);
5872a5b511eSPeter Avalos word0(&adj) -= P*Exp_msk1;
5882a5b511eSPeter Avalos /* adj = */ rounded_product(dval(&adj), tens[e2]);
5892a5b511eSPeter Avalos if ((word0(&adj) & Exp_mask)
5901181b21fSPeter Avalos > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
5911181b21fSPeter Avalos goto rv_notOK;
5922a5b511eSPeter Avalos word0(&adj) += P*Exp_msk1;
5932a5b511eSPeter Avalos dval(&rv) = dval(&adj);
5941181b21fSPeter Avalos #else
5952a5b511eSPeter Avalos /* rv = */ rounded_product(dval(&rv), tens[e2]);
5961181b21fSPeter Avalos #endif
5972a5b511eSPeter Avalos if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
5981181b21fSPeter Avalos goto ret;
5991181b21fSPeter Avalos e1 -= e2;
6001181b21fSPeter Avalos }
6011181b21fSPeter Avalos }
6021181b21fSPeter Avalos #ifndef Inaccurate_Divide
6031181b21fSPeter Avalos else if (e >= -Ten_pmax) {
6042a5b511eSPeter Avalos /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
6052a5b511eSPeter Avalos if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
6061181b21fSPeter Avalos goto ret;
6071181b21fSPeter Avalos e1 -= e;
6081181b21fSPeter Avalos }
6091181b21fSPeter Avalos #endif
6101181b21fSPeter Avalos }
6111181b21fSPeter Avalos rv_notOK:
6121181b21fSPeter Avalos e1 += nd - k;
6131181b21fSPeter Avalos
6141181b21fSPeter Avalos /* Get starting approximation = rv * 10**e1 */
6151181b21fSPeter Avalos
6161181b21fSPeter Avalos e2 = 0;
6171181b21fSPeter Avalos if (e1 > 0) {
6181181b21fSPeter Avalos if ( (i = e1 & 15) !=0)
6192a5b511eSPeter Avalos dval(&rv) *= tens[i];
6201181b21fSPeter Avalos if (e1 &= ~15) {
6211181b21fSPeter Avalos e1 >>= 4;
6222a5b511eSPeter Avalos while(e1 >= (1 << (n_bigtens-1))) {
6232a5b511eSPeter Avalos e2 += ((word0(&rv) & Exp_mask)
6241181b21fSPeter Avalos >> Exp_shift1) - Bias;
6252a5b511eSPeter Avalos word0(&rv) &= ~Exp_mask;
6262a5b511eSPeter Avalos word0(&rv) |= Bias << Exp_shift1;
6272a5b511eSPeter Avalos dval(&rv) *= bigtens[n_bigtens-1];
6282a5b511eSPeter Avalos e1 -= 1 << (n_bigtens-1);
6291181b21fSPeter Avalos }
6302a5b511eSPeter Avalos e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
6312a5b511eSPeter Avalos word0(&rv) &= ~Exp_mask;
6322a5b511eSPeter Avalos word0(&rv) |= Bias << Exp_shift1;
6331181b21fSPeter Avalos for(j = 0; e1 > 0; j++, e1 >>= 1)
6341181b21fSPeter Avalos if (e1 & 1)
6352a5b511eSPeter Avalos dval(&rv) *= bigtens[j];
6361181b21fSPeter Avalos }
6371181b21fSPeter Avalos }
6381181b21fSPeter Avalos else if (e1 < 0) {
6391181b21fSPeter Avalos e1 = -e1;
6401181b21fSPeter Avalos if ( (i = e1 & 15) !=0)
6412a5b511eSPeter Avalos dval(&rv) /= tens[i];
6421181b21fSPeter Avalos if (e1 &= ~15) {
6431181b21fSPeter Avalos e1 >>= 4;
6442a5b511eSPeter Avalos while(e1 >= (1 << (n_bigtens-1))) {
6452a5b511eSPeter Avalos e2 += ((word0(&rv) & Exp_mask)
6461181b21fSPeter Avalos >> Exp_shift1) - Bias;
6472a5b511eSPeter Avalos word0(&rv) &= ~Exp_mask;
6482a5b511eSPeter Avalos word0(&rv) |= Bias << Exp_shift1;
6492a5b511eSPeter Avalos dval(&rv) *= tinytens[n_bigtens-1];
6502a5b511eSPeter Avalos e1 -= 1 << (n_bigtens-1);
6511181b21fSPeter Avalos }
6522a5b511eSPeter Avalos e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
6532a5b511eSPeter Avalos word0(&rv) &= ~Exp_mask;
6542a5b511eSPeter Avalos word0(&rv) |= Bias << Exp_shift1;
6551181b21fSPeter Avalos for(j = 0; e1 > 0; j++, e1 >>= 1)
6561181b21fSPeter Avalos if (e1 & 1)
6572a5b511eSPeter Avalos dval(&rv) *= tinytens[j];
6581181b21fSPeter Avalos }
6591181b21fSPeter Avalos }
6601181b21fSPeter Avalos #ifdef IBM
6611181b21fSPeter Avalos /* e2 is a correction to the (base 2) exponent of the return
6621181b21fSPeter Avalos * value, reflecting adjustments above to avoid overflow in the
6631181b21fSPeter Avalos * native arithmetic. For native IBM (base 16) arithmetic, we
6641181b21fSPeter Avalos * must multiply e2 by 4 to change from base 16 to 2.
6651181b21fSPeter Avalos */
6661181b21fSPeter Avalos e2 <<= 2;
6671181b21fSPeter Avalos #endif
6682a5b511eSPeter Avalos rvb = d2b(dval(&rv), &rve, &rvbits); /* rv = rvb * 2^rve */
6691181b21fSPeter Avalos rve += e2;
6701181b21fSPeter Avalos if ((j = rvbits - nbits) > 0) {
6711181b21fSPeter Avalos rshift(rvb, j);
6721181b21fSPeter Avalos rvbits = nbits;
6731181b21fSPeter Avalos rve += j;
6741181b21fSPeter Avalos }
6751181b21fSPeter Avalos bb0 = 0; /* trailing zero bits in rvb */
6761181b21fSPeter Avalos e2 = rve + rvbits - nbits;
6771181b21fSPeter Avalos if (e2 > fpi->emax + 1)
6781181b21fSPeter Avalos goto huge;
6791181b21fSPeter Avalos rve1 = rve + rvbits - nbits;
6801181b21fSPeter Avalos if (e2 < (emin = fpi->emin)) {
6811181b21fSPeter Avalos denorm = 1;
6821181b21fSPeter Avalos j = rve - emin;
6831181b21fSPeter Avalos if (j > 0) {
6841181b21fSPeter Avalos rvb = lshift(rvb, j);
6851181b21fSPeter Avalos rvbits += j;
6861181b21fSPeter Avalos }
6871181b21fSPeter Avalos else if (j < 0) {
6881181b21fSPeter Avalos rvbits += j;
6891181b21fSPeter Avalos if (rvbits <= 0) {
6901181b21fSPeter Avalos if (rvbits < -1) {
6911181b21fSPeter Avalos ufl:
6921181b21fSPeter Avalos rvb->wds = 0;
6931181b21fSPeter Avalos rvb->x[0] = 0;
6941181b21fSPeter Avalos *exp = emin;
6951181b21fSPeter Avalos irv = STRTOG_Underflow | STRTOG_Inexlo;
6961181b21fSPeter Avalos goto ret;
6971181b21fSPeter Avalos }
6981181b21fSPeter Avalos rvb->x[0] = rvb->wds = rvbits = 1;
6991181b21fSPeter Avalos }
7001181b21fSPeter Avalos else
7011181b21fSPeter Avalos rshift(rvb, -j);
7021181b21fSPeter Avalos }
7031181b21fSPeter Avalos rve = rve1 = emin;
7041181b21fSPeter Avalos if (sudden_underflow && e2 + 1 < emin)
7051181b21fSPeter Avalos goto ufl;
7061181b21fSPeter Avalos }
7071181b21fSPeter Avalos
7081181b21fSPeter Avalos /* Now the hard part -- adjusting rv to the correct value.*/
7091181b21fSPeter Avalos
7101181b21fSPeter Avalos /* Put digits into bd: true value = bd * 10^e */
7111181b21fSPeter Avalos
7121181b21fSPeter Avalos bd0 = s2b(s0, nd0, nd, y, dplen);
7131181b21fSPeter Avalos
7141181b21fSPeter Avalos for(;;) {
7151181b21fSPeter Avalos bd = Balloc(bd0->k);
7161181b21fSPeter Avalos Bcopy(bd, bd0);
7171181b21fSPeter Avalos bb = Balloc(rvb->k);
7181181b21fSPeter Avalos Bcopy(bb, rvb);
7191181b21fSPeter Avalos bbbits = rvbits - bb0;
7201181b21fSPeter Avalos bbe = rve + bb0;
7211181b21fSPeter Avalos bs = i2b(1);
7221181b21fSPeter Avalos
7231181b21fSPeter Avalos if (e >= 0) {
7241181b21fSPeter Avalos bb2 = bb5 = 0;
7251181b21fSPeter Avalos bd2 = bd5 = e;
7261181b21fSPeter Avalos }
7271181b21fSPeter Avalos else {
7281181b21fSPeter Avalos bb2 = bb5 = -e;
7291181b21fSPeter Avalos bd2 = bd5 = 0;
7301181b21fSPeter Avalos }
7311181b21fSPeter Avalos if (bbe >= 0)
7321181b21fSPeter Avalos bb2 += bbe;
7331181b21fSPeter Avalos else
7341181b21fSPeter Avalos bd2 -= bbe;
7351181b21fSPeter Avalos bs2 = bb2;
7361181b21fSPeter Avalos j = nbits + 1 - bbbits;
7371181b21fSPeter Avalos i = bbe + bbbits - nbits;
7381181b21fSPeter Avalos if (i < emin) /* denormal */
7391181b21fSPeter Avalos j += i - emin;
7401181b21fSPeter Avalos bb2 += j;
7411181b21fSPeter Avalos bd2 += j;
7421181b21fSPeter Avalos i = bb2 < bd2 ? bb2 : bd2;
7431181b21fSPeter Avalos if (i > bs2)
7441181b21fSPeter Avalos i = bs2;
7451181b21fSPeter Avalos if (i > 0) {
7461181b21fSPeter Avalos bb2 -= i;
7471181b21fSPeter Avalos bd2 -= i;
7481181b21fSPeter Avalos bs2 -= i;
7491181b21fSPeter Avalos }
7501181b21fSPeter Avalos if (bb5 > 0) {
7511181b21fSPeter Avalos bs = pow5mult(bs, bb5);
7521181b21fSPeter Avalos bb1 = mult(bs, bb);
7531181b21fSPeter Avalos Bfree(bb);
7541181b21fSPeter Avalos bb = bb1;
7551181b21fSPeter Avalos }
7561181b21fSPeter Avalos bb2 -= bb0;
7571181b21fSPeter Avalos if (bb2 > 0)
7581181b21fSPeter Avalos bb = lshift(bb, bb2);
7591181b21fSPeter Avalos else if (bb2 < 0)
7601181b21fSPeter Avalos rshift(bb, -bb2);
7611181b21fSPeter Avalos if (bd5 > 0)
7621181b21fSPeter Avalos bd = pow5mult(bd, bd5);
7631181b21fSPeter Avalos if (bd2 > 0)
7641181b21fSPeter Avalos bd = lshift(bd, bd2);
7651181b21fSPeter Avalos if (bs2 > 0)
7661181b21fSPeter Avalos bs = lshift(bs, bs2);
7671181b21fSPeter Avalos asub = 1;
7681181b21fSPeter Avalos inex = STRTOG_Inexhi;
7691181b21fSPeter Avalos delta = diff(bb, bd);
7701181b21fSPeter Avalos if (delta->wds <= 1 && !delta->x[0])
7711181b21fSPeter Avalos break;
7721181b21fSPeter Avalos dsign = delta->sign;
7731181b21fSPeter Avalos delta->sign = finished = 0;
7741181b21fSPeter Avalos L = 0;
7751181b21fSPeter Avalos i = cmp(delta, bs);
7761181b21fSPeter Avalos if (rd && i <= 0) {
7771181b21fSPeter Avalos irv = STRTOG_Normal;
7781181b21fSPeter Avalos if ( (finished = dsign ^ (rd&1)) !=0) {
7791181b21fSPeter Avalos if (dsign != 0) {
7801181b21fSPeter Avalos irv |= STRTOG_Inexhi;
7811181b21fSPeter Avalos goto adj1;
7821181b21fSPeter Avalos }
7831181b21fSPeter Avalos irv |= STRTOG_Inexlo;
7841181b21fSPeter Avalos if (rve1 == emin)
7851181b21fSPeter Avalos goto adj1;
7861181b21fSPeter Avalos for(i = 0, j = nbits; j >= ULbits;
7871181b21fSPeter Avalos i++, j -= ULbits) {
7881181b21fSPeter Avalos if (rvb->x[i] & ALL_ON)
7891181b21fSPeter Avalos goto adj1;
7901181b21fSPeter Avalos }
7911181b21fSPeter Avalos if (j > 1 && lo0bits(rvb->x + i) < j - 1)
7921181b21fSPeter Avalos goto adj1;
7931181b21fSPeter Avalos rve = rve1 - 1;
7941181b21fSPeter Avalos rvb = set_ones(rvb, rvbits = nbits);
7951181b21fSPeter Avalos break;
7961181b21fSPeter Avalos }
7971181b21fSPeter Avalos irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi;
7981181b21fSPeter Avalos break;
7991181b21fSPeter Avalos }
8001181b21fSPeter Avalos if (i < 0) {
8011181b21fSPeter Avalos /* Error is less than half an ulp -- check for
8021181b21fSPeter Avalos * special case of mantissa a power of two.
8031181b21fSPeter Avalos */
8041181b21fSPeter Avalos irv = dsign
8051181b21fSPeter Avalos ? STRTOG_Normal | STRTOG_Inexlo
8061181b21fSPeter Avalos : STRTOG_Normal | STRTOG_Inexhi;
8071181b21fSPeter Avalos if (dsign || bbbits > 1 || denorm || rve1 == emin)
8081181b21fSPeter Avalos break;
8091181b21fSPeter Avalos delta = lshift(delta,1);
8101181b21fSPeter Avalos if (cmp(delta, bs) > 0) {
8111181b21fSPeter Avalos irv = STRTOG_Normal | STRTOG_Inexlo;
8121181b21fSPeter Avalos goto drop_down;
8131181b21fSPeter Avalos }
8141181b21fSPeter Avalos break;
8151181b21fSPeter Avalos }
8161181b21fSPeter Avalos if (i == 0) {
8171181b21fSPeter Avalos /* exactly half-way between */
8181181b21fSPeter Avalos if (dsign) {
8191181b21fSPeter Avalos if (denorm && all_on(rvb, rvbits)) {
8201181b21fSPeter Avalos /*boundary case -- increment exponent*/
8211181b21fSPeter Avalos rvb->wds = 1;
8221181b21fSPeter Avalos rvb->x[0] = 1;
8231181b21fSPeter Avalos rve = emin + nbits - (rvbits = 1);
8241181b21fSPeter Avalos irv = STRTOG_Normal | STRTOG_Inexhi;
8251181b21fSPeter Avalos denorm = 0;
8261181b21fSPeter Avalos break;
8271181b21fSPeter Avalos }
8281181b21fSPeter Avalos irv = STRTOG_Normal | STRTOG_Inexlo;
8291181b21fSPeter Avalos }
8301181b21fSPeter Avalos else if (bbbits == 1) {
8311181b21fSPeter Avalos irv = STRTOG_Normal;
8321181b21fSPeter Avalos drop_down:
8331181b21fSPeter Avalos /* boundary case -- decrement exponent */
8341181b21fSPeter Avalos if (rve1 == emin) {
8351181b21fSPeter Avalos irv = STRTOG_Normal | STRTOG_Inexhi;
8361181b21fSPeter Avalos if (rvb->wds == 1 && rvb->x[0] == 1)
8371181b21fSPeter Avalos sudden_underflow = 1;
8381181b21fSPeter Avalos break;
8391181b21fSPeter Avalos }
8401181b21fSPeter Avalos rve -= nbits;
8411181b21fSPeter Avalos rvb = set_ones(rvb, rvbits = nbits);
8421181b21fSPeter Avalos break;
8431181b21fSPeter Avalos }
8441181b21fSPeter Avalos else
8451181b21fSPeter Avalos irv = STRTOG_Normal | STRTOG_Inexhi;
8462a5b511eSPeter Avalos if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
8471181b21fSPeter Avalos break;
8481181b21fSPeter Avalos if (dsign) {
8491181b21fSPeter Avalos rvb = increment(rvb);
8501181b21fSPeter Avalos j = kmask & (ULbits - (rvbits & kmask));
8511181b21fSPeter Avalos if (hi0bits(rvb->x[rvb->wds - 1]) != j)
8521181b21fSPeter Avalos rvbits++;
8531181b21fSPeter Avalos irv = STRTOG_Normal | STRTOG_Inexhi;
8541181b21fSPeter Avalos }
8551181b21fSPeter Avalos else {
8561181b21fSPeter Avalos if (bbbits == 1)
8571181b21fSPeter Avalos goto undfl;
8581181b21fSPeter Avalos decrement(rvb);
8591181b21fSPeter Avalos irv = STRTOG_Normal | STRTOG_Inexlo;
8601181b21fSPeter Avalos }
8611181b21fSPeter Avalos break;
8621181b21fSPeter Avalos }
8632a5b511eSPeter Avalos if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
8641181b21fSPeter Avalos adj1:
8651181b21fSPeter Avalos inex = STRTOG_Inexlo;
8661181b21fSPeter Avalos if (dsign) {
8671181b21fSPeter Avalos asub = 0;
8681181b21fSPeter Avalos inex = STRTOG_Inexhi;
8691181b21fSPeter Avalos }
8701181b21fSPeter Avalos else if (denorm && bbbits <= 1) {
8711181b21fSPeter Avalos undfl:
8721181b21fSPeter Avalos rvb->wds = 0;
8731181b21fSPeter Avalos rve = emin;
8741181b21fSPeter Avalos irv = STRTOG_Underflow | STRTOG_Inexlo;
8751181b21fSPeter Avalos break;
8761181b21fSPeter Avalos }
8772a5b511eSPeter Avalos adj0 = dval(&adj) = 1.;
8781181b21fSPeter Avalos }
8791181b21fSPeter Avalos else {
8802a5b511eSPeter Avalos adj0 = dval(&adj) *= 0.5;
8811181b21fSPeter Avalos if (dsign) {
8821181b21fSPeter Avalos asub = 0;
8831181b21fSPeter Avalos inex = STRTOG_Inexlo;
8841181b21fSPeter Avalos }
8852a5b511eSPeter Avalos if (dval(&adj) < 2147483647.) {
8861181b21fSPeter Avalos L = adj0;
8871181b21fSPeter Avalos adj0 -= L;
8881181b21fSPeter Avalos switch(rd) {
8891181b21fSPeter Avalos case 0:
8901181b21fSPeter Avalos if (adj0 >= .5)
8911181b21fSPeter Avalos goto inc_L;
8921181b21fSPeter Avalos break;
8931181b21fSPeter Avalos case 1:
8941181b21fSPeter Avalos if (asub && adj0 > 0.)
8951181b21fSPeter Avalos goto inc_L;
8961181b21fSPeter Avalos break;
8971181b21fSPeter Avalos case 2:
8981181b21fSPeter Avalos if (!asub && adj0 > 0.) {
8991181b21fSPeter Avalos inc_L:
9001181b21fSPeter Avalos L++;
9011181b21fSPeter Avalos inex = STRTOG_Inexact - inex;
9021181b21fSPeter Avalos }
9031181b21fSPeter Avalos }
9042a5b511eSPeter Avalos dval(&adj) = L;
9051181b21fSPeter Avalos }
9061181b21fSPeter Avalos }
9071181b21fSPeter Avalos y = rve + rvbits;
9081181b21fSPeter Avalos
9092a5b511eSPeter Avalos /* adj *= ulp(dval(&rv)); */
9101181b21fSPeter Avalos /* if (asub) rv -= adj; else rv += adj; */
9111181b21fSPeter Avalos
9121181b21fSPeter Avalos if (!denorm && rvbits < nbits) {
9131181b21fSPeter Avalos rvb = lshift(rvb, j = nbits - rvbits);
9141181b21fSPeter Avalos rve -= j;
9151181b21fSPeter Avalos rvbits = nbits;
9161181b21fSPeter Avalos }
9172a5b511eSPeter Avalos ab = d2b(dval(&adj), &abe, &abits);
9181181b21fSPeter Avalos if (abe < 0)
9191181b21fSPeter Avalos rshift(ab, -abe);
9201181b21fSPeter Avalos else if (abe > 0)
9211181b21fSPeter Avalos ab = lshift(ab, abe);
9221181b21fSPeter Avalos rvb0 = rvb;
9231181b21fSPeter Avalos if (asub) {
9241181b21fSPeter Avalos /* rv -= adj; */
9251181b21fSPeter Avalos j = hi0bits(rvb->x[rvb->wds-1]);
9261181b21fSPeter Avalos rvb = diff(rvb, ab);
9271181b21fSPeter Avalos k = rvb0->wds - 1;
9281181b21fSPeter Avalos if (denorm)
9291181b21fSPeter Avalos /* do nothing */;
9301181b21fSPeter Avalos else if (rvb->wds <= k
9311181b21fSPeter Avalos || hi0bits( rvb->x[k]) >
9321181b21fSPeter Avalos hi0bits(rvb0->x[k])) {
9331181b21fSPeter Avalos /* unlikely; can only have lost 1 high bit */
9341181b21fSPeter Avalos if (rve1 == emin) {
9351181b21fSPeter Avalos --rvbits;
9361181b21fSPeter Avalos denorm = 1;
9371181b21fSPeter Avalos }
9381181b21fSPeter Avalos else {
9391181b21fSPeter Avalos rvb = lshift(rvb, 1);
9401181b21fSPeter Avalos --rve;
9411181b21fSPeter Avalos --rve1;
9421181b21fSPeter Avalos L = finished = 0;
9431181b21fSPeter Avalos }
9441181b21fSPeter Avalos }
9451181b21fSPeter Avalos }
9461181b21fSPeter Avalos else {
9471181b21fSPeter Avalos rvb = sum(rvb, ab);
9481181b21fSPeter Avalos k = rvb->wds - 1;
9491181b21fSPeter Avalos if (k >= rvb0->wds
9501181b21fSPeter Avalos || hi0bits(rvb->x[k]) < hi0bits(rvb0->x[k])) {
9511181b21fSPeter Avalos if (denorm) {
9521181b21fSPeter Avalos if (++rvbits == nbits)
9531181b21fSPeter Avalos denorm = 0;
9541181b21fSPeter Avalos }
9551181b21fSPeter Avalos else {
9561181b21fSPeter Avalos rshift(rvb, 1);
9571181b21fSPeter Avalos rve++;
9581181b21fSPeter Avalos rve1++;
9591181b21fSPeter Avalos L = 0;
9601181b21fSPeter Avalos }
9611181b21fSPeter Avalos }
9621181b21fSPeter Avalos }
9631181b21fSPeter Avalos Bfree(ab);
9641181b21fSPeter Avalos Bfree(rvb0);
9651181b21fSPeter Avalos if (finished)
9661181b21fSPeter Avalos break;
9671181b21fSPeter Avalos
9681181b21fSPeter Avalos z = rve + rvbits;
9691181b21fSPeter Avalos if (y == z && L) {
9701181b21fSPeter Avalos /* Can we stop now? */
9712a5b511eSPeter Avalos tol = dval(&adj) * 5e-16; /* > max rel error */
9722a5b511eSPeter Avalos dval(&adj) = adj0 - .5;
9732a5b511eSPeter Avalos if (dval(&adj) < -tol) {
9741181b21fSPeter Avalos if (adj0 > tol) {
9751181b21fSPeter Avalos irv |= inex;
9761181b21fSPeter Avalos break;
9771181b21fSPeter Avalos }
9781181b21fSPeter Avalos }
9792a5b511eSPeter Avalos else if (dval(&adj) > tol && adj0 < 1. - tol) {
9801181b21fSPeter Avalos irv |= inex;
9811181b21fSPeter Avalos break;
9821181b21fSPeter Avalos }
9831181b21fSPeter Avalos }
9841181b21fSPeter Avalos bb0 = denorm ? 0 : trailz(rvb);
9851181b21fSPeter Avalos Bfree(bb);
9861181b21fSPeter Avalos Bfree(bd);
9871181b21fSPeter Avalos Bfree(bs);
9881181b21fSPeter Avalos Bfree(delta);
9891181b21fSPeter Avalos }
9901181b21fSPeter Avalos if (!denorm && (j = nbits - rvbits)) {
9911181b21fSPeter Avalos if (j > 0)
9921181b21fSPeter Avalos rvb = lshift(rvb, j);
9931181b21fSPeter Avalos else
9941181b21fSPeter Avalos rshift(rvb, -j);
9951181b21fSPeter Avalos rve -= j;
9961181b21fSPeter Avalos }
9971181b21fSPeter Avalos *exp = rve;
9981181b21fSPeter Avalos Bfree(bb);
9991181b21fSPeter Avalos Bfree(bd);
10001181b21fSPeter Avalos Bfree(bs);
10011181b21fSPeter Avalos Bfree(bd0);
10021181b21fSPeter Avalos Bfree(delta);
10031181b21fSPeter Avalos if (rve > fpi->emax) {
10041181b21fSPeter Avalos switch(fpi->rounding & 3) {
10051181b21fSPeter Avalos case FPI_Round_near:
10061181b21fSPeter Avalos goto huge;
10071181b21fSPeter Avalos case FPI_Round_up:
10081181b21fSPeter Avalos if (!sign)
10091181b21fSPeter Avalos goto huge;
10101181b21fSPeter Avalos break;
10111181b21fSPeter Avalos case FPI_Round_down:
10121181b21fSPeter Avalos if (sign)
10131181b21fSPeter Avalos goto huge;
10141181b21fSPeter Avalos }
10151181b21fSPeter Avalos /* Round to largest representable magnitude */
10161181b21fSPeter Avalos Bfree(rvb);
10171181b21fSPeter Avalos rvb = 0;
10181181b21fSPeter Avalos irv = STRTOG_Normal | STRTOG_Inexlo;
10191181b21fSPeter Avalos *exp = fpi->emax;
10201181b21fSPeter Avalos b = bits;
10211181b21fSPeter Avalos be = b + ((fpi->nbits + 31) >> 5);
10221181b21fSPeter Avalos while(b < be)
10231181b21fSPeter Avalos *b++ = -1;
10241181b21fSPeter Avalos if ((j = fpi->nbits & 0x1f))
10251181b21fSPeter Avalos *--be >>= (32 - j);
10261181b21fSPeter Avalos goto ret;
10271181b21fSPeter Avalos huge:
10281181b21fSPeter Avalos rvb->wds = 0;
10291181b21fSPeter Avalos irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
10301181b21fSPeter Avalos #ifndef NO_ERRNO
10311181b21fSPeter Avalos errno = ERANGE;
10321181b21fSPeter Avalos #endif
10331181b21fSPeter Avalos infnanexp:
10341181b21fSPeter Avalos *exp = fpi->emax + 1;
10351181b21fSPeter Avalos }
10361181b21fSPeter Avalos ret:
10371181b21fSPeter Avalos if (denorm) {
10381181b21fSPeter Avalos if (sudden_underflow) {
10391181b21fSPeter Avalos rvb->wds = 0;
10401181b21fSPeter Avalos irv = STRTOG_Underflow | STRTOG_Inexlo;
10411181b21fSPeter Avalos #ifndef NO_ERRNO
10421181b21fSPeter Avalos errno = ERANGE;
10431181b21fSPeter Avalos #endif
10441181b21fSPeter Avalos }
10451181b21fSPeter Avalos else {
10461181b21fSPeter Avalos irv = (irv & ~STRTOG_Retmask) |
10471181b21fSPeter Avalos (rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
10481181b21fSPeter Avalos if (irv & STRTOG_Inexact) {
10491181b21fSPeter Avalos irv |= STRTOG_Underflow;
10501181b21fSPeter Avalos #ifndef NO_ERRNO
10511181b21fSPeter Avalos errno = ERANGE;
10521181b21fSPeter Avalos #endif
10531181b21fSPeter Avalos }
10541181b21fSPeter Avalos }
10551181b21fSPeter Avalos }
10561181b21fSPeter Avalos if (se)
10571181b21fSPeter Avalos *se = (char *)s;
10581181b21fSPeter Avalos if (sign)
10591181b21fSPeter Avalos irv |= STRTOG_Neg;
10601181b21fSPeter Avalos if (rvb) {
10611181b21fSPeter Avalos copybits(bits, nbits, rvb);
10621181b21fSPeter Avalos Bfree(rvb);
10631181b21fSPeter Avalos }
10641181b21fSPeter Avalos return irv;
10651181b21fSPeter Avalos }
1066