X-Git-Url: http://nsz.repo.hu/git/?p=musl;a=blobdiff_plain;f=src%2Finternal%2Ffloatscan.c;h=0e1f6d06a4ad7593bf909d9c7f38586ee469f147;hp=3875719b42e064bd5b15e104a9ddb8b4abee8cf5;hb=fe514951af4e67f05d17d796251af9a8229761eb;hpb=c5ff29699cb3cccf8dcd8e44ddf4dcb7599e585c diff --git a/src/internal/floatscan.c b/src/internal/floatscan.c index 3875719b..0e1f6d06 100644 --- a/src/internal/floatscan.c +++ b/src/internal/floatscan.c @@ -44,7 +44,7 @@ static long long scanexp(FILE *f, int pok) } for (x=0; c-'0'<10U && x30 || x[0]>>bits==0)) + /* Handle zero specially to avoid nasty special cases later */ + if (!x[0]) return sign * 0.0; + + /* Optimize small integers (w/no exponent) and over/under-flow */ + if (lrp==dc && dc<10 && (bits>30 || x[0]>>bits==0)) return sign * (long double)x[0]; if (lrp > -emin/2) { errno = ERANGE; @@ -130,6 +133,7 @@ static long double decfloat(FILE *f, int bits, int emin, int sign, int pok) return sign * LDBL_MIN * LDBL_MIN; } + /* Align incomplete final B1B digit */ if (k30 || x[0]>>bitlim==0) + return sign * (long double)x[0] * p10s[rp-10]; + } + + /* Align radix point to B1B digit boundary */ + if (rp % 9) { + int rpm9 = rp>=0 ? rp%9 : rp%9+9; + int p10 = p10s[8-rpm9]; + uint32_t carry = 0; + for (k=a; k!=z; k++) { + uint32_t tmp = x[k] % p10; + x[k] = x[k]/p10 + carry; + carry = 1000000000/p10 * tmp; + if (k==a && !x[k]) { + a = (a+1 & MASK); + rp -= 9; + } + } + if (carry) x[z++] = carry; + rp += 9-rpm9; + } + + /* Upscale until desired number of bits are left of radix point */ + while (rp < 9*LD_B1B_DIG || (rp == 9*LD_B1B_DIG && x[a]>sh) * tmp; if (k==a && !x[k]) { a = (a+1 & MASK); + i--; rp -= 9; } } @@ -225,16 +233,21 @@ static long double decfloat(FILE *f, int bits, int emin, int sign, int pok) } } - for (y=i=0; i LDBL_MANT_DIG+e2-emin) { bits = LDBL_MANT_DIG+e2-emin; if (bits<0) bits=0; } + /* Calculate bias term to force rounding, move out lower bits */ if (bits < LDBL_MANT_DIG) { bias = copysignl(scalbn(1, 2*LDBL_MANT_DIG-bits-1), y); frac = fmodl(y, scalbn(1, LDBL_MANT_DIG-bits)); @@ -242,6 +255,7 @@ static long double decfloat(FILE *f, int bits, int emin, int sign, int pok) y += bias; } + /* Process tail of decimal input so it can affect rounding */ if ((a+i & MASK) != z) { uint32_t t = x[a+i & MASK]; if (t < 500000000 && (t || (a+i+1 & MASK) != z)) @@ -336,6 +350,8 @@ static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok) } e2 = 0; } + } else { + shunget(f); } e2 += 4*rp - 32; @@ -434,9 +450,9 @@ long double __floatscan(FILE *f, int c, int prec, int pok) c = shgetc(f); if ((c|32) == 'x') return hexfloat(f, bits, emin, sign, pok); + shunget(f); c = '0'; } - shunget(f); - return decfloat(f, bits, emin, sign, pok); + return decfloat(f, c, bits, emin, sign, pok); }