From fe514951af4e67f05d17d796251af9a8229761eb Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 12 Apr 2012 00:16:01 -0400 Subject: [PATCH] optimize more integer cases in floatscan; comment the whole procedure --- src/internal/floatscan.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/internal/floatscan.c b/src/internal/floatscan.c index 28a09c25..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] 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)) -- 2.25.1