1*9feb722eSchristos /* $NetBSD: strtodg.c,v 1.13 2021/05/06 16:15:33 christos Exp $ */
27684d5e0Skleink
37684d5e0Skleink /****************************************************************
47684d5e0Skleink
57684d5e0Skleink The author of this software is David M. Gay.
67684d5e0Skleink
77684d5e0Skleink Copyright (C) 1998-2001 by Lucent Technologies
87684d5e0Skleink All Rights Reserved
97684d5e0Skleink
107684d5e0Skleink Permission to use, copy, modify, and distribute this software and
117684d5e0Skleink its documentation for any purpose and without fee is hereby
127684d5e0Skleink granted, provided that the above copyright notice appear in all
137684d5e0Skleink copies and that both that the copyright notice and this
147684d5e0Skleink permission notice and warranty disclaimer appear in supporting
157684d5e0Skleink documentation, and that the name of Lucent or any of its entities
167684d5e0Skleink not be used in advertising or publicity pertaining to
177684d5e0Skleink distribution of the software without specific, written prior
187684d5e0Skleink permission.
197684d5e0Skleink
207684d5e0Skleink LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
217684d5e0Skleink INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
227684d5e0Skleink IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
237684d5e0Skleink SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
247684d5e0Skleink WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
257684d5e0Skleink IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
267684d5e0Skleink ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
277684d5e0Skleink THIS SOFTWARE.
287684d5e0Skleink
297684d5e0Skleink ****************************************************************/
307684d5e0Skleink
317684d5e0Skleink /* Please send bug reports to David M. Gay (dmg at acm dot org,
327684d5e0Skleink * with " at " changed at "@" and " dot " changed to "."). */
337684d5e0Skleink
347684d5e0Skleink #include "gdtoaimp.h"
357684d5e0Skleink
367684d5e0Skleink #ifdef USE_LOCALE
377684d5e0Skleink #include "locale.h"
387684d5e0Skleink #endif
397684d5e0Skleink
40648512f8She #ifndef VAX
417684d5e0Skleink static CONST int
427684d5e0Skleink fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21,
437684d5e0Skleink 24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
447684d5e0Skleink 47, 49, 52
457684d5e0Skleink };
46648512f8She #endif
477684d5e0Skleink
487684d5e0Skleink Bigint *
497684d5e0Skleink #ifdef KR_headers
increment(b)507684d5e0Skleink increment(b) Bigint *b;
517684d5e0Skleink #else
527684d5e0Skleink increment(Bigint *b)
537684d5e0Skleink #endif
547684d5e0Skleink {
557684d5e0Skleink ULong *x, *xe;
567684d5e0Skleink Bigint *b1;
577684d5e0Skleink #ifdef Pack_16
587684d5e0Skleink ULong carry = 1, y;
597684d5e0Skleink #endif
607684d5e0Skleink
617684d5e0Skleink x = b->x;
627684d5e0Skleink xe = x + b->wds;
637684d5e0Skleink #ifdef Pack_32
647684d5e0Skleink do {
657684d5e0Skleink if (*x < (ULong)0xffffffffL) {
667684d5e0Skleink ++*x;
677684d5e0Skleink return b;
687684d5e0Skleink }
697684d5e0Skleink *x++ = 0;
707684d5e0Skleink } while(x < xe);
717684d5e0Skleink #else
727684d5e0Skleink do {
737684d5e0Skleink y = *x + carry;
747684d5e0Skleink carry = y >> 16;
757684d5e0Skleink *x++ = y & 0xffff;
767684d5e0Skleink if (!carry)
777684d5e0Skleink return b;
787684d5e0Skleink } while(x < xe);
797684d5e0Skleink if (carry)
807684d5e0Skleink #endif
817684d5e0Skleink {
827684d5e0Skleink if (b->wds >= b->maxwds) {
837684d5e0Skleink b1 = Balloc(b->k+1);
84ab625449Schristos if (b1 == NULL)
85ab625449Schristos return NULL;
867684d5e0Skleink Bcopy(b1,b);
877684d5e0Skleink Bfree(b);
887684d5e0Skleink b = b1;
897684d5e0Skleink }
907684d5e0Skleink b->x[b->wds++] = 1;
917684d5e0Skleink }
927684d5e0Skleink return b;
937684d5e0Skleink }
947684d5e0Skleink
9561e56760Schristos void
967684d5e0Skleink #ifdef KR_headers
decrement(b)977684d5e0Skleink decrement(b) Bigint *b;
987684d5e0Skleink #else
997684d5e0Skleink decrement(Bigint *b)
1007684d5e0Skleink #endif
1017684d5e0Skleink {
1027684d5e0Skleink ULong *x, *xe;
1037684d5e0Skleink #ifdef Pack_16
1047684d5e0Skleink ULong borrow = 1, y;
1057684d5e0Skleink #endif
1067684d5e0Skleink
1077684d5e0Skleink x = b->x;
1087684d5e0Skleink xe = x + b->wds;
1097684d5e0Skleink #ifdef Pack_32
1107684d5e0Skleink do {
1117684d5e0Skleink if (*x) {
1127684d5e0Skleink --*x;
1137684d5e0Skleink break;
1147684d5e0Skleink }
115ac898a26Skleink *x++ = 0xffffffffUL;
1167684d5e0Skleink }
1177684d5e0Skleink while(x < xe);
1187684d5e0Skleink #else
1197684d5e0Skleink do {
1207684d5e0Skleink y = *x - borrow;
1217684d5e0Skleink borrow = (y & 0x10000) >> 16;
1227684d5e0Skleink *x++ = y & 0xffff;
1237684d5e0Skleink } while(borrow && x < xe);
1247684d5e0Skleink #endif
1257684d5e0Skleink }
1267684d5e0Skleink
1277684d5e0Skleink static int
1287684d5e0Skleink #ifdef KR_headers
all_on(b,n)129f8228ce4Skleink all_on(b, n) CONST Bigint *b; int n;
1307684d5e0Skleink #else
131f8228ce4Skleink all_on(CONST Bigint *b, int n)
1327684d5e0Skleink #endif
1337684d5e0Skleink {
134f8228ce4Skleink CONST ULong *x, *xe;
1357684d5e0Skleink
1367684d5e0Skleink x = b->x;
137ac898a26Skleink xe = x + ((unsigned int)n >> kshift);
1387684d5e0Skleink while(x < xe)
1397684d5e0Skleink if ((*x++ & ALL_ON) != ALL_ON)
1407684d5e0Skleink return 0;
1417684d5e0Skleink if (n &= kmask)
1427684d5e0Skleink return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON;
1437684d5e0Skleink return 1;
1447684d5e0Skleink }
1457684d5e0Skleink
1467684d5e0Skleink Bigint *
1477684d5e0Skleink #ifdef KR_headers
set_ones(b,n)1487684d5e0Skleink set_ones(b, n) Bigint *b; int n;
1497684d5e0Skleink #else
1507684d5e0Skleink set_ones(Bigint *b, int n)
1517684d5e0Skleink #endif
1527684d5e0Skleink {
1537684d5e0Skleink int k;
1547684d5e0Skleink ULong *x, *xe;
1557684d5e0Skleink
156ac898a26Skleink k = (unsigned int)(n + ((1 << kshift) - 1)) >> kshift;
1577684d5e0Skleink if (b->k < k) {
1587684d5e0Skleink Bfree(b);
1597684d5e0Skleink b = Balloc(k);
160ab625449Schristos if (b == NULL)
161ab625449Schristos return NULL;
1627684d5e0Skleink }
163ac898a26Skleink k = (unsigned int)n >> kshift;
1647684d5e0Skleink if (n &= kmask)
1657684d5e0Skleink k++;
1667684d5e0Skleink b->wds = k;
1677684d5e0Skleink x = b->x;
1687684d5e0Skleink xe = x + k;
1697684d5e0Skleink while(x < xe)
1707684d5e0Skleink *x++ = ALL_ON;
1717684d5e0Skleink if (n)
1727684d5e0Skleink x[-1] >>= ULbits - n;
1737684d5e0Skleink return b;
1747684d5e0Skleink }
1757684d5e0Skleink
1767684d5e0Skleink static int
rvOK(d,fpi,expt,bits,exact,rd,irv)1777684d5e0Skleink rvOK
1787684d5e0Skleink #ifdef KR_headers
179ac898a26Skleink (d, fpi, expt, bits, exact, rd, irv)
18061e56760Schristos U *d; CONST FPI *fpi; Long *expt; ULong *bits; int exact, rd, *irv;
1817684d5e0Skleink #else
18261e56760Schristos (U *d, CONST FPI *fpi, Long *expt, ULong *bits, int exact, int rd, int *irv)
1837684d5e0Skleink #endif
1847684d5e0Skleink {
1857684d5e0Skleink Bigint *b;
1867684d5e0Skleink ULong carry, inex, lostbits;
1877684d5e0Skleink int bdif, e, j, k, k1, nb, rv;
1887684d5e0Skleink
1897684d5e0Skleink carry = rv = 0;
19061e56760Schristos b = d2b(dval(d), &e, &bdif);
1917684d5e0Skleink bdif -= nb = fpi->nbits;
1927684d5e0Skleink e += bdif;
1937684d5e0Skleink if (bdif <= 0) {
1947684d5e0Skleink if (exact)
1957684d5e0Skleink goto trunc;
1967684d5e0Skleink goto ret;
1977684d5e0Skleink }
1987684d5e0Skleink if (P == nb) {
1997684d5e0Skleink if (
2007684d5e0Skleink #ifndef IMPRECISE_INEXACT
2017684d5e0Skleink exact &&
2027684d5e0Skleink #endif
2037684d5e0Skleink fpi->rounding ==
2047684d5e0Skleink #ifdef RND_PRODQUOT
2057684d5e0Skleink FPI_Round_near
2067684d5e0Skleink #else
2077684d5e0Skleink Flt_Rounds
2087684d5e0Skleink #endif
2097684d5e0Skleink ) goto trunc;
2107684d5e0Skleink goto ret;
2117684d5e0Skleink }
2127684d5e0Skleink switch(rd) {
21361e56760Schristos case 1: /* round down (toward -Infinity) */
2147684d5e0Skleink goto trunc;
21561e56760Schristos case 2: /* round up (toward +Infinity) */
2167684d5e0Skleink break;
2177684d5e0Skleink default: /* round near */
2187684d5e0Skleink k = bdif - 1;
2197684d5e0Skleink if (!k) {
2207684d5e0Skleink if (!exact)
2217684d5e0Skleink goto ret;
2227684d5e0Skleink if (b->x[0] & 2)
2237684d5e0Skleink break;
2247684d5e0Skleink goto trunc;
2257684d5e0Skleink }
226ac898a26Skleink if (b->x[(unsigned int)k>>kshift] & ((ULong)1 << (k & kmask)))
2277684d5e0Skleink break;
2287684d5e0Skleink goto trunc;
2297684d5e0Skleink }
2307684d5e0Skleink /* "break" cases: round up 1 bit, then truncate; bdif > 0 */
2317684d5e0Skleink carry = 1;
2327684d5e0Skleink trunc:
2337684d5e0Skleink inex = lostbits = 0;
2347684d5e0Skleink if (bdif > 0) {
2357684d5e0Skleink if ( (lostbits = any_on(b, bdif)) !=0)
2367684d5e0Skleink inex = STRTOG_Inexlo;
2377684d5e0Skleink rshift(b, bdif);
2387684d5e0Skleink if (carry) {
2397684d5e0Skleink inex = STRTOG_Inexhi;
2407684d5e0Skleink b = increment(b);
2417684d5e0Skleink if ( (j = nb & kmask) !=0)
2427684d5e0Skleink j = ULbits - j;
2437684d5e0Skleink if (hi0bits(b->x[b->wds - 1]) != j) {
2447684d5e0Skleink if (!lostbits)
2457684d5e0Skleink lostbits = b->x[0] & 1;
2467684d5e0Skleink rshift(b, 1);
2477684d5e0Skleink e++;
2487684d5e0Skleink }
2497684d5e0Skleink }
2507684d5e0Skleink }
251*9feb722eSchristos else if (bdif < 0) {
2527684d5e0Skleink b = lshift(b, -bdif);
253*9feb722eSchristos if (b == NULL)
254*9feb722eSchristos return STRTOG_NoMemory;
255*9feb722eSchristos }
2567684d5e0Skleink if (e < fpi->emin) {
2577684d5e0Skleink k = fpi->emin - e;
2587684d5e0Skleink e = fpi->emin;
2597684d5e0Skleink if (k > nb || fpi->sudden_underflow) {
2607684d5e0Skleink b->wds = inex = 0;
2617684d5e0Skleink *irv = STRTOG_Underflow | STRTOG_Inexlo;
2627684d5e0Skleink }
2637684d5e0Skleink else {
2647684d5e0Skleink k1 = k - 1;
2657684d5e0Skleink if (k1 > 0 && !lostbits)
2667684d5e0Skleink lostbits = any_on(b, k1);
2677684d5e0Skleink if (!lostbits && !exact)
2687684d5e0Skleink goto ret;
2697684d5e0Skleink lostbits |=
270ac898a26Skleink carry = b->x[(unsigned int)k1>>kshift] &
271ac898a26Skleink (1 << (k1 & kmask));
2727684d5e0Skleink rshift(b, k);
2737684d5e0Skleink *irv = STRTOG_Denormal;
2747684d5e0Skleink if (carry) {
2757684d5e0Skleink b = increment(b);
2767684d5e0Skleink inex = STRTOG_Inexhi | STRTOG_Underflow;
2777684d5e0Skleink }
2787684d5e0Skleink else if (lostbits)
2797684d5e0Skleink inex = STRTOG_Inexlo | STRTOG_Underflow;
2807684d5e0Skleink }
2817684d5e0Skleink }
2827684d5e0Skleink else if (e > fpi->emax) {
2837684d5e0Skleink e = fpi->emax + 1;
2847684d5e0Skleink *irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
2857684d5e0Skleink #ifndef NO_ERRNO
2867684d5e0Skleink errno = ERANGE;
2877684d5e0Skleink #endif
2887684d5e0Skleink b->wds = inex = 0;
2897684d5e0Skleink }
290ac898a26Skleink *expt = e;
2917684d5e0Skleink copybits(bits, nb, b);
2927684d5e0Skleink *irv |= inex;
2937684d5e0Skleink rv = 1;
2947684d5e0Skleink ret:
2957684d5e0Skleink Bfree(b);
2967684d5e0Skleink return rv;
2977684d5e0Skleink }
2987684d5e0Skleink
299ac898a26Skleink #ifndef VAX
3007684d5e0Skleink static int
3017684d5e0Skleink #ifdef KR_headers
mantbits(d)30261e56760Schristos mantbits(d) U *d;
3037684d5e0Skleink #else
30461e56760Schristos mantbits(U *d)
3057684d5e0Skleink #endif
3067684d5e0Skleink {
3077684d5e0Skleink ULong L;
3087684d5e0Skleink #ifdef VAX
3097684d5e0Skleink L = word1(d) << 16 | word1(d) >> 16;
3107684d5e0Skleink if (L)
3117684d5e0Skleink #else
3127684d5e0Skleink if ( (L = word1(d)) !=0)
3137684d5e0Skleink #endif
3147684d5e0Skleink return P - lo0bits(&L);
3157684d5e0Skleink #ifdef VAX
3167684d5e0Skleink L = word0(d) << 16 | word0(d) >> 16 | Exp_msk11;
3177684d5e0Skleink #else
3187684d5e0Skleink L = word0(d) | Exp_msk1;
3197684d5e0Skleink #endif
3207684d5e0Skleink return P - 32 - lo0bits(&L);
3217684d5e0Skleink }
322ac898a26Skleink #endif /* !VAX */
3237684d5e0Skleink
3247684d5e0Skleink int
strtodg(CONST char * s00,char ** se,CONST FPI * fpi,Long * expt,ULong * bits,locale_t loc)325c99aac45Sjoerg strtodg(CONST char *s00, char **se, CONST FPI *fpi, Long *expt, ULong *bits,
326c99aac45Sjoerg locale_t loc)
3277684d5e0Skleink {
3287684d5e0Skleink int abe, abits, asub;
329648512f8She #ifdef INFNAN_CHECK
330648512f8She int decpt;
331648512f8She #endif
332648512f8She int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, denorm;
3337684d5e0Skleink int dsign, e, e1, e2, emin, esign, finished, i, inex, irv;
3347684d5e0Skleink int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
335ac898a26Skleink int sudden_underflow = 0; /* pacify gcc */
3367684d5e0Skleink CONST char *s, *s0, *s1;
33761e56760Schristos double adj0, tol;
3387684d5e0Skleink Long L;
33961e56760Schristos U adj, rv;
34061e56760Schristos ULong *b, *be, y, z;
3417684d5e0Skleink Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
34261e56760Schristos #ifdef USE_LOCALE /*{{*/
343c99aac45Sjoerg char *decimalpoint = localeconv_l(loc)->decimal_point;
34461e56760Schristos size_t dplen = strlen(decimalpoint);
34561e56760Schristos #endif /*USE_LOCALE}}*/
3467684d5e0Skleink
347da78757bSmrg e2 = 0; /* XXX gcc */
348da78757bSmrg
3497684d5e0Skleink irv = STRTOG_Zero;
3507684d5e0Skleink denorm = sign = nz0 = nz = 0;
35161e56760Schristos dval(&rv) = 0.;
3527684d5e0Skleink rvb = 0;
3537684d5e0Skleink nbits = fpi->nbits;
3547684d5e0Skleink for(s = s00;;s++) switch(*s) {
3557684d5e0Skleink case '-':
3567684d5e0Skleink sign = 1;
357ac898a26Skleink /* FALLTHROUGH */
3587684d5e0Skleink case '+':
3597684d5e0Skleink if (*++s)
3607684d5e0Skleink goto break2;
361ac898a26Skleink /* FALLTHROUGH */
3627684d5e0Skleink case 0:
3637684d5e0Skleink sign = 0;
3647684d5e0Skleink irv = STRTOG_NoNumber;
3657684d5e0Skleink s = s00;
3667684d5e0Skleink goto ret;
3677684d5e0Skleink case '\t':
3687684d5e0Skleink case '\n':
3697684d5e0Skleink case '\v':
3707684d5e0Skleink case '\f':
3717684d5e0Skleink case '\r':
3727684d5e0Skleink case ' ':
3737684d5e0Skleink continue;
3747684d5e0Skleink default:
3757684d5e0Skleink goto break2;
3767684d5e0Skleink }
3777684d5e0Skleink break2:
3787684d5e0Skleink if (*s == '0') {
3797684d5e0Skleink #ifndef NO_HEX_FP
3807684d5e0Skleink switch(s[1]) {
3817684d5e0Skleink case 'x':
3827684d5e0Skleink case 'X':
3830feb0f12Sjoerg irv = gethex(&s, fpi, expt, &rvb, sign, loc);
3847684d5e0Skleink if (irv == STRTOG_NoNumber) {
3857684d5e0Skleink s = s00;
3867684d5e0Skleink sign = 0;
3877684d5e0Skleink }
3887684d5e0Skleink goto ret;
3897684d5e0Skleink }
3907684d5e0Skleink #endif
3917684d5e0Skleink nz0 = 1;
3927684d5e0Skleink while(*++s == '0') ;
3937684d5e0Skleink if (!*s)
3947684d5e0Skleink goto ret;
3957684d5e0Skleink }
3967684d5e0Skleink sudden_underflow = fpi->sudden_underflow;
3977684d5e0Skleink s0 = s;
3987684d5e0Skleink y = z = 0;
399648512f8She #ifdef INFNAN_CHECK
400648512f8She decpt = 0;
401648512f8She #endif
402648512f8She for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
4037684d5e0Skleink if (nd < 9)
4047684d5e0Skleink y = 10*y + c - '0';
4057684d5e0Skleink else if (nd < 16)
4067684d5e0Skleink z = 10*z + c - '0';
4077684d5e0Skleink nd0 = nd;
4087684d5e0Skleink #ifdef USE_LOCALE
40961e56760Schristos if (c == *decimalpoint) {
41061e56760Schristos for(i = 1; decimalpoint[i]; ++i)
41161e56760Schristos if (s[i] != decimalpoint[i])
41261e56760Schristos goto dig_done;
41361e56760Schristos s += i;
41461e56760Schristos c = *s;
4157684d5e0Skleink #else
41661e56760Schristos if (c == '.') {
4177684d5e0Skleink c = *++s;
41861e56760Schristos #endif
419648512f8She #ifdef INFNAN_CHECK
42061e56760Schristos decpt = 1;
421648512f8She #endif
4227684d5e0Skleink if (!nd) {
4237684d5e0Skleink for(; c == '0'; c = *++s)
4247684d5e0Skleink nz++;
4257684d5e0Skleink if (c > '0' && c <= '9') {
4267684d5e0Skleink s0 = s;
4277684d5e0Skleink nf += nz;
4287684d5e0Skleink nz = 0;
4297684d5e0Skleink goto have_dig;
4307684d5e0Skleink }
4317684d5e0Skleink goto dig_done;
4327684d5e0Skleink }
4337684d5e0Skleink for(; c >= '0' && c <= '9'; c = *++s) {
4347684d5e0Skleink have_dig:
4357684d5e0Skleink nz++;
4367684d5e0Skleink if (c -= '0') {
4377684d5e0Skleink nf += nz;
4387684d5e0Skleink for(i = 1; i < nz; i++)
4397684d5e0Skleink if (nd++ < 9)
4407684d5e0Skleink y *= 10;
4417684d5e0Skleink else if (nd <= DBL_DIG + 1)
4427684d5e0Skleink z *= 10;
4437684d5e0Skleink if (nd++ < 9)
4447684d5e0Skleink y = 10*y + c;
4457684d5e0Skleink else if (nd <= DBL_DIG + 1)
4467684d5e0Skleink z = 10*z + c;
4477684d5e0Skleink nz = 0;
4487684d5e0Skleink }
4497684d5e0Skleink }
45061e56760Schristos }/*}*/
4517684d5e0Skleink dig_done:
4527684d5e0Skleink e = 0;
4537684d5e0Skleink if (c == 'e' || c == 'E') {
4547684d5e0Skleink if (!nd && !nz && !nz0) {
4557684d5e0Skleink irv = STRTOG_NoNumber;
4567684d5e0Skleink s = s00;
4577684d5e0Skleink goto ret;
4587684d5e0Skleink }
4597684d5e0Skleink s00 = s;
4607684d5e0Skleink esign = 0;
4617684d5e0Skleink switch(c = *++s) {
4627684d5e0Skleink case '-':
4637684d5e0Skleink esign = 1;
464ac898a26Skleink /* FALLTHROUGH */
4657684d5e0Skleink case '+':
4667684d5e0Skleink c = *++s;
4677684d5e0Skleink }
4687684d5e0Skleink if (c >= '0' && c <= '9') {
4697684d5e0Skleink while(c == '0')
4707684d5e0Skleink c = *++s;
4717684d5e0Skleink if (c > '0' && c <= '9') {
4727684d5e0Skleink L = c - '0';
4737684d5e0Skleink s1 = s;
4747684d5e0Skleink while((c = *++s) >= '0' && c <= '9')
4757684d5e0Skleink L = 10*L + c - '0';
4767684d5e0Skleink if (s - s1 > 8 || L > 19999)
4777684d5e0Skleink /* Avoid confusion from exponents
4787684d5e0Skleink * so large that e might overflow.
4797684d5e0Skleink */
4807684d5e0Skleink e = 19999; /* safe for 16 bit ints */
4817684d5e0Skleink else
4827684d5e0Skleink e = (int)L;
4837684d5e0Skleink if (esign)
4847684d5e0Skleink e = -e;
4857684d5e0Skleink }
4867684d5e0Skleink else
4877684d5e0Skleink e = 0;
4887684d5e0Skleink }
4897684d5e0Skleink else
4907684d5e0Skleink s = s00;
4917684d5e0Skleink }
4927684d5e0Skleink if (!nd) {
4937684d5e0Skleink if (!nz && !nz0) {
4947684d5e0Skleink #ifdef INFNAN_CHECK
4957684d5e0Skleink /* Check for Nan and Infinity */
4967684d5e0Skleink if (!decpt)
4977684d5e0Skleink switch(c) {
4987684d5e0Skleink case 'i':
4997684d5e0Skleink case 'I':
5007684d5e0Skleink if (match(&s,"nf")) {
5017684d5e0Skleink --s;
5027684d5e0Skleink if (!match(&s,"inity"))
5037684d5e0Skleink ++s;
5047684d5e0Skleink irv = STRTOG_Infinite;
5057684d5e0Skleink goto infnanexp;
5067684d5e0Skleink }
5077684d5e0Skleink break;
5087684d5e0Skleink case 'n':
5097684d5e0Skleink case 'N':
5107684d5e0Skleink if (match(&s, "an")) {
5117684d5e0Skleink irv = STRTOG_NaN;
512ac898a26Skleink *expt = fpi->emax + 1;
5137684d5e0Skleink #ifndef No_Hex_NaN
5147684d5e0Skleink if (*s == '(') /*)*/
5157684d5e0Skleink irv = hexnan(&s, fpi, bits);
5167684d5e0Skleink #endif
5177684d5e0Skleink goto infnanexp;
5187684d5e0Skleink }
5197684d5e0Skleink }
5207684d5e0Skleink #endif /* INFNAN_CHECK */
5217684d5e0Skleink irv = STRTOG_NoNumber;
5227684d5e0Skleink s = s00;
5237684d5e0Skleink }
5247684d5e0Skleink goto ret;
5257684d5e0Skleink }
5267684d5e0Skleink
5277684d5e0Skleink irv = STRTOG_Normal;
5287684d5e0Skleink e1 = e -= nf;
5297684d5e0Skleink rd = 0;
5307684d5e0Skleink switch(fpi->rounding & 3) {
5317684d5e0Skleink case FPI_Round_up:
5327684d5e0Skleink rd = 2 - sign;
5337684d5e0Skleink break;
5347684d5e0Skleink case FPI_Round_zero:
5357684d5e0Skleink rd = 1;
5367684d5e0Skleink break;
5377684d5e0Skleink case FPI_Round_down:
5387684d5e0Skleink rd = 1 + sign;
5397684d5e0Skleink }
5407684d5e0Skleink
5417684d5e0Skleink /* Now we have nd0 digits, starting at s0, followed by a
5427684d5e0Skleink * decimal point, followed by nd-nd0 digits. The number we're
5437684d5e0Skleink * after is the integer represented by those digits times
5447684d5e0Skleink * 10**e */
5457684d5e0Skleink
5467684d5e0Skleink if (!nd0)
5477684d5e0Skleink nd0 = nd;
5487684d5e0Skleink k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
54961e56760Schristos dval(&rv) = y;
5507684d5e0Skleink if (k > 9)
55161e56760Schristos dval(&rv) = tens[k - 9] * dval(&rv) + z;
5527684d5e0Skleink bd0 = 0;
5537684d5e0Skleink if (nbits <= P && nd <= DBL_DIG) {
5547684d5e0Skleink if (!e) {
55561e56760Schristos if (rvOK(&rv, fpi, expt, bits, 1, rd, &irv))
5567684d5e0Skleink goto ret;
5577684d5e0Skleink }
5587684d5e0Skleink else if (e > 0) {
5597684d5e0Skleink if (e <= Ten_pmax) {
5607684d5e0Skleink #ifdef VAX
5617684d5e0Skleink goto vax_ovfl_check;
5627684d5e0Skleink #else
56361e56760Schristos i = fivesbits[e] + mantbits(&rv) <= P;
56461e56760Schristos /* rv = */ rounded_product(dval(&rv), tens[e]);
56561e56760Schristos if (rvOK(&rv, fpi, expt, bits, i, rd, &irv))
5667684d5e0Skleink goto ret;
5677684d5e0Skleink e1 -= e;
5687684d5e0Skleink goto rv_notOK;
5697684d5e0Skleink #endif
5707684d5e0Skleink }
5717684d5e0Skleink i = DBL_DIG - nd;
5727684d5e0Skleink if (e <= Ten_pmax + i) {
5737684d5e0Skleink /* A fancier test would sometimes let us do
5747684d5e0Skleink * this for larger i values.
5757684d5e0Skleink */
5767684d5e0Skleink e2 = e - i;
5777684d5e0Skleink e1 -= i;
57861e56760Schristos dval(&rv) *= tens[i];
5797684d5e0Skleink #ifdef VAX
5807684d5e0Skleink /* VAX exponent range is so narrow we must
5817684d5e0Skleink * worry about overflow here...
5827684d5e0Skleink */
5837684d5e0Skleink vax_ovfl_check:
58461e56760Schristos dval(&adj) = dval(&rv);
58561e56760Schristos word0(&adj) -= P*Exp_msk1;
58661e56760Schristos /* adj = */ rounded_product(dval(&adj), tens[e2]);
58761e56760Schristos if ((word0(&adj) & Exp_mask)
5887684d5e0Skleink > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
5897684d5e0Skleink goto rv_notOK;
59061e56760Schristos word0(&adj) += P*Exp_msk1;
59161e56760Schristos dval(&rv) = dval(&adj);
5927684d5e0Skleink #else
59361e56760Schristos /* rv = */ rounded_product(dval(&rv), tens[e2]);
5947684d5e0Skleink #endif
59561e56760Schristos if (rvOK(&rv, fpi, expt, bits, 0, rd, &irv))
5967684d5e0Skleink goto ret;
5977684d5e0Skleink e1 -= e2;
5987684d5e0Skleink }
5997684d5e0Skleink }
6007684d5e0Skleink #ifndef Inaccurate_Divide
6017684d5e0Skleink else if (e >= -Ten_pmax) {
60261e56760Schristos /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
60361e56760Schristos if (rvOK(&rv, fpi, expt, bits, 0, rd, &irv))
6047684d5e0Skleink goto ret;
6057684d5e0Skleink e1 -= e;
6067684d5e0Skleink }
6077684d5e0Skleink #endif
6087684d5e0Skleink }
6097684d5e0Skleink rv_notOK:
6107684d5e0Skleink e1 += nd - k;
6117684d5e0Skleink
6127684d5e0Skleink /* Get starting approximation = rv * 10**e1 */
6137684d5e0Skleink
6147684d5e0Skleink e2 = 0;
6157684d5e0Skleink if (e1 > 0) {
6167684d5e0Skleink if ( (i = e1 & 15) !=0)
61761e56760Schristos dval(&rv) *= tens[i];
6187684d5e0Skleink if (e1 &= ~15) {
619ac898a26Skleink e1 = (unsigned int)e1 >> 4;
620ac898a26Skleink while(e1 >= (1 << (n_bigtens-1))) {
62161e56760Schristos e2 += ((word0(&rv) & Exp_mask)
6227684d5e0Skleink >> Exp_shift1) - Bias;
62361e56760Schristos word0(&rv) &= ~Exp_mask;
62461e56760Schristos word0(&rv) |= Bias << Exp_shift1;
62561e56760Schristos dval(&rv) *= bigtens[n_bigtens-1];
626ac898a26Skleink e1 -= 1 << (n_bigtens-1);
6277684d5e0Skleink }
62861e56760Schristos e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
62961e56760Schristos word0(&rv) &= ~Exp_mask;
63061e56760Schristos word0(&rv) |= Bias << Exp_shift1;
631374ecd4bSchristos for(j = 0; e1 > 0; j++, e1 = (unsigned int)e1 >> 1)
6327684d5e0Skleink if (e1 & 1)
63361e56760Schristos dval(&rv) *= bigtens[j];
6347684d5e0Skleink }
6357684d5e0Skleink }
6367684d5e0Skleink else if (e1 < 0) {
6377684d5e0Skleink e1 = -e1;
6387684d5e0Skleink if ( (i = e1 & 15) !=0)
63961e56760Schristos dval(&rv) /= tens[i];
6407684d5e0Skleink if (e1 &= ~15) {
641ac898a26Skleink e1 = (unsigned int)e1 >> 4;
642ac898a26Skleink while(e1 >= (1 << (n_bigtens-1))) {
64361e56760Schristos e2 += ((word0(&rv) & Exp_mask)
6447684d5e0Skleink >> Exp_shift1) - Bias;
64561e56760Schristos word0(&rv) &= ~Exp_mask;
64661e56760Schristos word0(&rv) |= Bias << Exp_shift1;
64761e56760Schristos dval(&rv) *= tinytens[n_bigtens-1];
648ac898a26Skleink e1 -= 1 << (n_bigtens-1);
6497684d5e0Skleink }
65061e56760Schristos e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
65161e56760Schristos word0(&rv) &= ~Exp_mask;
65261e56760Schristos word0(&rv) |= Bias << Exp_shift1;
653374ecd4bSchristos for(j = 0; e1 > 0; j++, e1 = (unsigned int)e1 >> 1)
6547684d5e0Skleink if (e1 & 1)
65561e56760Schristos dval(&rv) *= tinytens[j];
6567684d5e0Skleink }
6577684d5e0Skleink }
6587684d5e0Skleink #ifdef IBM
6597684d5e0Skleink /* e2 is a correction to the (base 2) exponent of the return
6607684d5e0Skleink * value, reflecting adjustments above to avoid overflow in the
6617684d5e0Skleink * native arithmetic. For native IBM (base 16) arithmetic, we
6627684d5e0Skleink * must multiply e2 by 4 to change from base 16 to 2.
6637684d5e0Skleink */
6647684d5e0Skleink e2 <<= 2;
6657684d5e0Skleink #endif
66661e56760Schristos rvb = d2b(dval(&rv), &rve, &rvbits); /* rv = rvb * 2^rve */
667ab625449Schristos if (rvb == NULL)
668ab625449Schristos return STRTOG_NoMemory;
6697684d5e0Skleink rve += e2;
6707684d5e0Skleink if ((j = rvbits - nbits) > 0) {
6717684d5e0Skleink rshift(rvb, j);
6727684d5e0Skleink rvbits = nbits;
6737684d5e0Skleink rve += j;
6747684d5e0Skleink }
6757684d5e0Skleink bb0 = 0; /* trailing zero bits in rvb */
6767684d5e0Skleink e2 = rve + rvbits - nbits;
6777684d5e0Skleink if (e2 > fpi->emax + 1)
6787684d5e0Skleink goto huge;
6797684d5e0Skleink rve1 = rve + rvbits - nbits;
6807684d5e0Skleink if (e2 < (emin = fpi->emin)) {
6817684d5e0Skleink denorm = 1;
6827684d5e0Skleink j = rve - emin;
6837684d5e0Skleink if (j > 0) {
6847684d5e0Skleink rvb = lshift(rvb, j);
685*9feb722eSchristos if (rvb == NULL)
686*9feb722eSchristos return STRTOG_NoMemory;
6877684d5e0Skleink rvbits += j;
6887684d5e0Skleink }
6897684d5e0Skleink else if (j < 0) {
6907684d5e0Skleink rvbits += j;
6917684d5e0Skleink if (rvbits <= 0) {
6927684d5e0Skleink if (rvbits < -1) {
6937684d5e0Skleink ufl:
6947684d5e0Skleink rvb->wds = 0;
6957684d5e0Skleink rvb->x[0] = 0;
696ac898a26Skleink *expt = emin;
6977684d5e0Skleink irv = STRTOG_Underflow | STRTOG_Inexlo;
6987684d5e0Skleink goto ret;
6997684d5e0Skleink }
7007684d5e0Skleink rvb->x[0] = rvb->wds = rvbits = 1;
7017684d5e0Skleink }
7027684d5e0Skleink else
7037684d5e0Skleink rshift(rvb, -j);
7047684d5e0Skleink }
7057684d5e0Skleink rve = rve1 = emin;
7067684d5e0Skleink if (sudden_underflow && e2 + 1 < emin)
7077684d5e0Skleink goto ufl;
7087684d5e0Skleink }
7097684d5e0Skleink
7107684d5e0Skleink /* Now the hard part -- adjusting rv to the correct value.*/
7117684d5e0Skleink
7127684d5e0Skleink /* Put digits into bd: true value = bd * 10^e */
7137684d5e0Skleink
71461e56760Schristos bd0 = s2b(s0, nd0, nd, y, dplen);
7157684d5e0Skleink
7167684d5e0Skleink for(;;) {
7177684d5e0Skleink bd = Balloc(bd0->k);
718ab625449Schristos if (bd == NULL)
719ab625449Schristos return STRTOG_NoMemory;
7207684d5e0Skleink Bcopy(bd, bd0);
7217684d5e0Skleink bb = Balloc(rvb->k);
722ab625449Schristos if (bb == NULL)
723ab625449Schristos return STRTOG_NoMemory;
7247684d5e0Skleink Bcopy(bb, rvb);
7257684d5e0Skleink bbbits = rvbits - bb0;
7267684d5e0Skleink bbe = rve + bb0;
7277684d5e0Skleink bs = i2b(1);
728ab625449Schristos if (bs == NULL)
729ab625449Schristos return STRTOG_NoMemory;
7307684d5e0Skleink
7317684d5e0Skleink if (e >= 0) {
7327684d5e0Skleink bb2 = bb5 = 0;
7337684d5e0Skleink bd2 = bd5 = e;
7347684d5e0Skleink }
7357684d5e0Skleink else {
7367684d5e0Skleink bb2 = bb5 = -e;
7377684d5e0Skleink bd2 = bd5 = 0;
7387684d5e0Skleink }
7397684d5e0Skleink if (bbe >= 0)
7407684d5e0Skleink bb2 += bbe;
7417684d5e0Skleink else
7427684d5e0Skleink bd2 -= bbe;
7437684d5e0Skleink bs2 = bb2;
7447684d5e0Skleink j = nbits + 1 - bbbits;
7457684d5e0Skleink i = bbe + bbbits - nbits;
7467684d5e0Skleink if (i < emin) /* denormal */
7477684d5e0Skleink j += i - emin;
7487684d5e0Skleink bb2 += j;
7497684d5e0Skleink bd2 += j;
7507684d5e0Skleink i = bb2 < bd2 ? bb2 : bd2;
7517684d5e0Skleink if (i > bs2)
7527684d5e0Skleink i = bs2;
7537684d5e0Skleink if (i > 0) {
7547684d5e0Skleink bb2 -= i;
7557684d5e0Skleink bd2 -= i;
7567684d5e0Skleink bs2 -= i;
7577684d5e0Skleink }
7587684d5e0Skleink if (bb5 > 0) {
7597684d5e0Skleink bs = pow5mult(bs, bb5);
760ab625449Schristos if (bs == NULL)
761ab625449Schristos return STRTOG_NoMemory;
7627684d5e0Skleink bb1 = mult(bs, bb);
763ab625449Schristos if (bb1 == NULL)
764ab625449Schristos return STRTOG_NoMemory;
7657684d5e0Skleink Bfree(bb);
7667684d5e0Skleink bb = bb1;
7677684d5e0Skleink }
7687684d5e0Skleink bb2 -= bb0;
769ab625449Schristos if (bb2 > 0) {
7707684d5e0Skleink bb = lshift(bb, bb2);
771ab625449Schristos if (bb == NULL)
772ab625449Schristos return STRTOG_NoMemory;
773ab625449Schristos }
7747684d5e0Skleink else if (bb2 < 0)
7757684d5e0Skleink rshift(bb, -bb2);
776ab625449Schristos if (bd5 > 0) {
7777684d5e0Skleink bd = pow5mult(bd, bd5);
778ab625449Schristos if (bd == NULL)
779ab625449Schristos return STRTOG_NoMemory;
780ab625449Schristos }
781ab625449Schristos if (bd2 > 0) {
7827684d5e0Skleink bd = lshift(bd, bd2);
783ab625449Schristos if (bd == NULL)
784ab625449Schristos return STRTOG_NoMemory;
785ab625449Schristos }
786ab625449Schristos if (bs2 > 0) {
7877684d5e0Skleink bs = lshift(bs, bs2);
788ab625449Schristos if (bs == NULL)
789ab625449Schristos return STRTOG_NoMemory;
790ab625449Schristos }
7917684d5e0Skleink asub = 1;
7927684d5e0Skleink inex = STRTOG_Inexhi;
7937684d5e0Skleink delta = diff(bb, bd);
794ab625449Schristos if (delta == NULL)
795ab625449Schristos return STRTOG_NoMemory;
7967684d5e0Skleink if (delta->wds <= 1 && !delta->x[0])
7977684d5e0Skleink break;
7987684d5e0Skleink dsign = delta->sign;
7997684d5e0Skleink delta->sign = finished = 0;
8007684d5e0Skleink L = 0;
8017684d5e0Skleink i = cmp(delta, bs);
8027684d5e0Skleink if (rd && i <= 0) {
8037684d5e0Skleink irv = STRTOG_Normal;
8047684d5e0Skleink if ( (finished = dsign ^ (rd&1)) !=0) {
8057684d5e0Skleink if (dsign != 0) {
8067684d5e0Skleink irv |= STRTOG_Inexhi;
8077684d5e0Skleink goto adj1;
8087684d5e0Skleink }
8097684d5e0Skleink irv |= STRTOG_Inexlo;
8107684d5e0Skleink if (rve1 == emin)
8117684d5e0Skleink goto adj1;
8127684d5e0Skleink for(i = 0, j = nbits; j >= ULbits;
8137684d5e0Skleink i++, j -= ULbits) {
8147684d5e0Skleink if (rvb->x[i] & ALL_ON)
8157684d5e0Skleink goto adj1;
8167684d5e0Skleink }
8177684d5e0Skleink if (j > 1 && lo0bits(rvb->x + i) < j - 1)
8187684d5e0Skleink goto adj1;
8197684d5e0Skleink rve = rve1 - 1;
8207684d5e0Skleink rvb = set_ones(rvb, rvbits = nbits);
821ab625449Schristos if (rvb == NULL)
822ab625449Schristos return STRTOG_NoMemory;
8237684d5e0Skleink break;
8247684d5e0Skleink }
8257684d5e0Skleink irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi;
8267684d5e0Skleink break;
8277684d5e0Skleink }
8287684d5e0Skleink if (i < 0) {
8297684d5e0Skleink /* Error is less than half an ulp -- check for
8307684d5e0Skleink * special case of mantissa a power of two.
8317684d5e0Skleink */
8327684d5e0Skleink irv = dsign
8337684d5e0Skleink ? STRTOG_Normal | STRTOG_Inexlo
8347684d5e0Skleink : STRTOG_Normal | STRTOG_Inexhi;
8357684d5e0Skleink if (dsign || bbbits > 1 || denorm || rve1 == emin)
8367684d5e0Skleink break;
8377684d5e0Skleink delta = lshift(delta,1);
838ab625449Schristos if (delta == NULL)
839ab625449Schristos return STRTOG_NoMemory;
8407684d5e0Skleink if (cmp(delta, bs) > 0) {
8417684d5e0Skleink irv = STRTOG_Normal | STRTOG_Inexlo;
8427684d5e0Skleink goto drop_down;
8437684d5e0Skleink }
8447684d5e0Skleink break;
8457684d5e0Skleink }
8467684d5e0Skleink if (i == 0) {
8477684d5e0Skleink /* exactly half-way between */
8487684d5e0Skleink if (dsign) {
8497684d5e0Skleink if (denorm && all_on(rvb, rvbits)) {
8507684d5e0Skleink /*boundary case -- increment exponent*/
8517684d5e0Skleink rvb->wds = 1;
8527684d5e0Skleink rvb->x[0] = 1;
8537684d5e0Skleink rve = emin + nbits - (rvbits = 1);
8547684d5e0Skleink irv = STRTOG_Normal | STRTOG_Inexhi;
8557684d5e0Skleink denorm = 0;
8567684d5e0Skleink break;
8577684d5e0Skleink }
8587684d5e0Skleink irv = STRTOG_Normal | STRTOG_Inexlo;
8597684d5e0Skleink }
8607684d5e0Skleink else if (bbbits == 1) {
8617684d5e0Skleink irv = STRTOG_Normal;
8627684d5e0Skleink drop_down:
8637684d5e0Skleink /* boundary case -- decrement exponent */
8647684d5e0Skleink if (rve1 == emin) {
8657684d5e0Skleink irv = STRTOG_Normal | STRTOG_Inexhi;
8667684d5e0Skleink if (rvb->wds == 1 && rvb->x[0] == 1)
8677684d5e0Skleink sudden_underflow = 1;
8687684d5e0Skleink break;
8697684d5e0Skleink }
8707684d5e0Skleink rve -= nbits;
8717684d5e0Skleink rvb = set_ones(rvb, rvbits = nbits);
872ab625449Schristos if (rvb == NULL)
873ab625449Schristos return STRTOG_NoMemory;
8747684d5e0Skleink break;
8757684d5e0Skleink }
8767684d5e0Skleink else
8777684d5e0Skleink irv = STRTOG_Normal | STRTOG_Inexhi;
878ac898a26Skleink if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
8797684d5e0Skleink break;
8807684d5e0Skleink if (dsign) {
8817684d5e0Skleink rvb = increment(rvb);
882ab625449Schristos if (rvb == NULL)
883ab625449Schristos return STRTOG_NoMemory;
88461e56760Schristos j = kmask & (ULbits - (rvbits & kmask));
88561e56760Schristos if (hi0bits(rvb->x[rvb->wds - 1]) != j)
8867684d5e0Skleink rvbits++;
8877684d5e0Skleink irv = STRTOG_Normal | STRTOG_Inexhi;
8887684d5e0Skleink }
8897684d5e0Skleink else {
8907684d5e0Skleink if (bbbits == 1)
8917684d5e0Skleink goto undfl;
8927684d5e0Skleink decrement(rvb);
8937684d5e0Skleink irv = STRTOG_Normal | STRTOG_Inexlo;
8947684d5e0Skleink }
8957684d5e0Skleink break;
8967684d5e0Skleink }
89761e56760Schristos if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
8987684d5e0Skleink adj1:
8997684d5e0Skleink inex = STRTOG_Inexlo;
9007684d5e0Skleink if (dsign) {
9017684d5e0Skleink asub = 0;
9027684d5e0Skleink inex = STRTOG_Inexhi;
9037684d5e0Skleink }
9047684d5e0Skleink else if (denorm && bbbits <= 1) {
9057684d5e0Skleink undfl:
9067684d5e0Skleink rvb->wds = 0;
9077684d5e0Skleink rve = emin;
9087684d5e0Skleink irv = STRTOG_Underflow | STRTOG_Inexlo;
9097684d5e0Skleink break;
9107684d5e0Skleink }
91161e56760Schristos adj0 = dval(&adj) = 1.;
9127684d5e0Skleink }
9137684d5e0Skleink else {
91461e56760Schristos adj0 = dval(&adj) *= 0.5;
9157684d5e0Skleink if (dsign) {
9167684d5e0Skleink asub = 0;
9177684d5e0Skleink inex = STRTOG_Inexlo;
9187684d5e0Skleink }
91961e56760Schristos if (dval(&adj) < 2147483647.) {
9207684d5e0Skleink L = adj0;
9217684d5e0Skleink adj0 -= L;
9227684d5e0Skleink switch(rd) {
9237684d5e0Skleink case 0:
9247684d5e0Skleink if (adj0 >= .5)
9257684d5e0Skleink goto inc_L;
9267684d5e0Skleink break;
9277684d5e0Skleink case 1:
9287684d5e0Skleink if (asub && adj0 > 0.)
9297684d5e0Skleink goto inc_L;
9307684d5e0Skleink break;
9317684d5e0Skleink case 2:
9327684d5e0Skleink if (!asub && adj0 > 0.) {
9337684d5e0Skleink inc_L:
9347684d5e0Skleink L++;
9357684d5e0Skleink inex = STRTOG_Inexact - inex;
9367684d5e0Skleink }
9377684d5e0Skleink }
93861e56760Schristos dval(&adj) = L;
9397684d5e0Skleink }
9407684d5e0Skleink }
9417684d5e0Skleink y = rve + rvbits;
9427684d5e0Skleink
94361e56760Schristos /* adj *= ulp(dval(&rv)); */
9447684d5e0Skleink /* if (asub) rv -= adj; else rv += adj; */
9457684d5e0Skleink
9467684d5e0Skleink if (!denorm && rvbits < nbits) {
9477684d5e0Skleink rvb = lshift(rvb, j = nbits - rvbits);
948ab625449Schristos if (rvb == NULL)
949ab625449Schristos return STRTOG_NoMemory;
9507684d5e0Skleink rve -= j;
9517684d5e0Skleink rvbits = nbits;
9527684d5e0Skleink }
95361e56760Schristos ab = d2b(dval(&adj), &abe, &abits);
954ab625449Schristos if (ab == NULL)
955ab625449Schristos return STRTOG_NoMemory;
9567684d5e0Skleink if (abe < 0)
9577684d5e0Skleink rshift(ab, -abe);
958*9feb722eSchristos else if (abe > 0) {
9597684d5e0Skleink ab = lshift(ab, abe);
960*9feb722eSchristos if (ab == NULL)
961*9feb722eSchristos return STRTOG_NoMemory;
962*9feb722eSchristos }
9637684d5e0Skleink rvb0 = rvb;
9647684d5e0Skleink if (asub) {
9657684d5e0Skleink /* rv -= adj; */
9667684d5e0Skleink j = hi0bits(rvb->x[rvb->wds-1]);
9677684d5e0Skleink rvb = diff(rvb, ab);
968ab625449Schristos if (rvb == NULL)
969ab625449Schristos return STRTOG_NoMemory;
9707684d5e0Skleink k = rvb0->wds - 1;
9717684d5e0Skleink if (denorm)
9727684d5e0Skleink /* do nothing */;
9737684d5e0Skleink else if (rvb->wds <= k
9747684d5e0Skleink || hi0bits( rvb->x[k]) >
9757684d5e0Skleink hi0bits(rvb0->x[k])) {
9767684d5e0Skleink /* unlikely; can only have lost 1 high bit */
9777684d5e0Skleink if (rve1 == emin) {
9787684d5e0Skleink --rvbits;
9797684d5e0Skleink denorm = 1;
9807684d5e0Skleink }
9817684d5e0Skleink else {
9827684d5e0Skleink rvb = lshift(rvb, 1);
983ab625449Schristos if (rvb == NULL)
984ab625449Schristos return STRTOG_NoMemory;
9857684d5e0Skleink --rve;
9867684d5e0Skleink --rve1;
9877684d5e0Skleink L = finished = 0;
9887684d5e0Skleink }
9897684d5e0Skleink }
9907684d5e0Skleink }
9917684d5e0Skleink else {
9927684d5e0Skleink rvb = sum(rvb, ab);
993ab625449Schristos if (rvb == NULL)
994ab625449Schristos return STRTOG_NoMemory;
9957684d5e0Skleink k = rvb->wds - 1;
9967684d5e0Skleink if (k >= rvb0->wds
9977684d5e0Skleink || hi0bits(rvb->x[k]) < hi0bits(rvb0->x[k])) {
9987684d5e0Skleink if (denorm) {
9997684d5e0Skleink if (++rvbits == nbits)
10007684d5e0Skleink denorm = 0;
10017684d5e0Skleink }
10027684d5e0Skleink else {
10037684d5e0Skleink rshift(rvb, 1);
10047684d5e0Skleink rve++;
10057684d5e0Skleink rve1++;
10067684d5e0Skleink L = 0;
10077684d5e0Skleink }
10087684d5e0Skleink }
10097684d5e0Skleink }
10107684d5e0Skleink Bfree(ab);
10117684d5e0Skleink Bfree(rvb0);
10127684d5e0Skleink if (finished)
10137684d5e0Skleink break;
10147684d5e0Skleink
10157684d5e0Skleink z = rve + rvbits;
10167684d5e0Skleink if (y == z && L) {
10177684d5e0Skleink /* Can we stop now? */
101861e56760Schristos tol = dval(&adj) * 5e-16; /* > max rel error */
101961e56760Schristos dval(&adj) = adj0 - .5;
102061e56760Schristos if (dval(&adj) < -tol) {
10217684d5e0Skleink if (adj0 > tol) {
10227684d5e0Skleink irv |= inex;
10237684d5e0Skleink break;
10247684d5e0Skleink }
10257684d5e0Skleink }
102661e56760Schristos else if (dval(&adj) > tol && adj0 < 1. - tol) {
10277684d5e0Skleink irv |= inex;
10287684d5e0Skleink break;
10297684d5e0Skleink }
10307684d5e0Skleink }
10317684d5e0Skleink bb0 = denorm ? 0 : trailz(rvb);
10327684d5e0Skleink Bfree(bb);
10337684d5e0Skleink Bfree(bd);
10347684d5e0Skleink Bfree(bs);
10357684d5e0Skleink Bfree(delta);
10367684d5e0Skleink }
10377684d5e0Skleink if (!denorm && (j = nbits - rvbits)) {
1038*9feb722eSchristos if (j > 0) {
10397684d5e0Skleink rvb = lshift(rvb, j);
1040*9feb722eSchristos if (rvb == NULL)
1041*9feb722eSchristos return STRTOG_NoMemory;
1042*9feb722eSchristos }
10437684d5e0Skleink else
10447684d5e0Skleink rshift(rvb, -j);
10457684d5e0Skleink rve -= j;
10467684d5e0Skleink }
1047ac898a26Skleink *expt = rve;
10487684d5e0Skleink Bfree(bb);
10497684d5e0Skleink Bfree(bd);
10507684d5e0Skleink Bfree(bs);
10517684d5e0Skleink Bfree(bd0);
10527684d5e0Skleink Bfree(delta);
10537684d5e0Skleink if (rve > fpi->emax) {
105461e56760Schristos switch(fpi->rounding & 3) {
105561e56760Schristos case FPI_Round_near:
105661e56760Schristos goto huge;
105761e56760Schristos case FPI_Round_up:
105861e56760Schristos if (!sign)
105961e56760Schristos goto huge;
106061e56760Schristos break;
106161e56760Schristos case FPI_Round_down:
106261e56760Schristos if (sign)
106361e56760Schristos goto huge;
106461e56760Schristos }
106561e56760Schristos /* Round to largest representable magnitude */
106661e56760Schristos Bfree(rvb);
106761e56760Schristos rvb = 0;
106861e56760Schristos irv = STRTOG_Normal | STRTOG_Inexlo;
106961e56760Schristos *expt = fpi->emax;
107061e56760Schristos b = bits;
1071374ecd4bSchristos be = b + ((unsigned int)(fpi->nbits + 31) >> 5);
107261e56760Schristos while(b < be)
1073374ecd4bSchristos *b++ = (unsigned int)-1;
1074374ecd4bSchristos if ((j = fpi->nbits & 0x1f) != 0)
107561e56760Schristos *--be >>= (32 - j);
107661e56760Schristos goto ret;
10777684d5e0Skleink huge:
10787684d5e0Skleink rvb->wds = 0;
10797684d5e0Skleink irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
10807684d5e0Skleink #ifndef NO_ERRNO
10817684d5e0Skleink errno = ERANGE;
10827684d5e0Skleink #endif
1083ac898a26Skleink #ifdef INFNAN_CHECK
10847684d5e0Skleink infnanexp:
1085ac898a26Skleink #endif
1086ac898a26Skleink *expt = fpi->emax + 1;
10877684d5e0Skleink }
10887684d5e0Skleink ret:
10897684d5e0Skleink if (denorm) {
10907684d5e0Skleink if (sudden_underflow) {
10917684d5e0Skleink rvb->wds = 0;
10927684d5e0Skleink irv = STRTOG_Underflow | STRTOG_Inexlo;
109361e56760Schristos #ifndef NO_ERRNO
109461e56760Schristos errno = ERANGE;
109561e56760Schristos #endif
10967684d5e0Skleink }
10977684d5e0Skleink else {
10987684d5e0Skleink irv = (irv & ~STRTOG_Retmask) |
10997684d5e0Skleink (rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
110061e56760Schristos if (irv & STRTOG_Inexact) {
11017684d5e0Skleink irv |= STRTOG_Underflow;
110261e56760Schristos #ifndef NO_ERRNO
110361e56760Schristos errno = ERANGE;
110461e56760Schristos #endif
110561e56760Schristos }
11067684d5e0Skleink }
11077684d5e0Skleink }
11087684d5e0Skleink if (se)
1109ac898a26Skleink *se = __UNCONST(s);
11107684d5e0Skleink if (sign)
11117684d5e0Skleink irv |= STRTOG_Neg;
11127684d5e0Skleink if (rvb) {
11137684d5e0Skleink copybits(bits, nbits, rvb);
11147684d5e0Skleink Bfree(rvb);
11157684d5e0Skleink }
11167684d5e0Skleink return irv;
11177684d5e0Skleink }
1118