X-Git-Url: http://nsz.repo.hu/git/?p=musl;a=blobdiff_plain;f=src%2Finternal%2Ffloatscan.c;h=0e1f6d06a4ad7593bf909d9c7f38586ee469f147;hp=a76daa460c0c5ce58924c24ff76c2df618d47f3b;hb=fe514951af4e67f05d17d796251af9a8229761eb;hpb=96acdae944f44a4a757cd98de297490fea2dddb5 diff --git a/src/internal/floatscan.c b/src/internal/floatscan.c index a76daa46..0e1f6d06 100644 --- a/src/internal/floatscan.c +++ b/src/internal/floatscan.c @@ -59,12 +59,15 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po int i, j, k, a, z; long long lrp=-1, dc=0; long long e10=0; + int lnz = 0; int gotdig = 0; int rp; int e2; long double y; long double frac=0; long double bias=0; + static const int p10s[] = { 10, 100, 1000, 10000, + 100000, 1000000, 10000000, 100000000 }; j=0; k=0; @@ -78,6 +81,7 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po if (lrp!=-1) break; lrp = dc; } else if (k < KMAX-2) { + if (c!='0') lnz = dc; dc++; if (j) x[k] = x[k]*10 + c-'0'; else x[k] = c-'0'; @@ -114,9 +118,11 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po return 0; } - if (!x[0]) - return sign * 0.0; - if (lrp==dc && (!k || (k==1 && !j)) && (bits>30 || 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; @@ -127,6 +133,7 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po 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) { - static const int p10s[] = { - 100000000, 10000000, 1000000, 100000, - 10000, 1000, 100, 10 - }; int rpm9 = rp>=0 ? rp%9 : rp%9+9; - int p10 = p10s[rpm9-1]; + int p10 = p10s[8-rpm9]; uint32_t carry = 0; for (k=a; k!=z; k++) { uint32_t tmp = x[k] % p10; @@ -159,6 +172,7 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po 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] 9+9*LD_B1B_DIG) sh = 9; e2 += sh; - for (i=0; (k=(a+i & MASK))!=z && i>sh) + carry; carry = (1000000000>>sh) * tmp; @@ -210,7 +225,7 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po rp -= 9; } } - if (carry && k==z) { + if (carry) { if ((z+1 & MASK) != a) { x[z] = carry; z = (z+1 & MASK); @@ -218,6 +233,7 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po } } + /* Assemble desired bits into floating point variable */ 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)); @@ -237,6 +255,7 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po 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))