Fast-track obviously over-large and over-small exponents during decimal->

integer conversion.  In some such cases this makes us one or two orders
of magnitude faster than NetBSD's libc.  Glibc seems to have a similar
fast path.

Also, tighten up some upper bounds to save a bit of memory.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42984 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Neil Booth 2007-10-15 15:00:55 +00:00
parent 65f8d3bf6b
commit 686700e325

View File

@ -59,7 +59,7 @@ namespace llvm {
/* A tight upper bound on number of parts required to hold the value /* A tight upper bound on number of parts required to hold the value
pow(5, power) is pow(5, power) is
power * 1024 / (441 * integerPartWidth) + 1 power * 815 / (351 * integerPartWidth) + 1
However, whilst the result may require only this many parts, However, whilst the result may require only this many parts,
because we are multiplying two values to get it, the because we are multiplying two values to get it, the
@ -70,8 +70,8 @@ namespace llvm {
const unsigned int maxExponent = 16383; const unsigned int maxExponent = 16383;
const unsigned int maxPrecision = 113; const unsigned int maxPrecision = 113;
const unsigned int maxPowerOfFiveExponent = maxExponent + maxPrecision - 1; const unsigned int maxPowerOfFiveExponent = maxExponent + maxPrecision - 1;
const unsigned int maxPowerOfFiveParts = 2 + ((maxPowerOfFiveExponent * 1024) const unsigned int maxPowerOfFiveParts = 2 + ((maxPowerOfFiveExponent * 815)
/ (441 * integerPartWidth)); / (351 * integerPartWidth));
} }
/* Put a bunch of private, handy routines in an anonymous namespace. */ /* Put a bunch of private, handy routines in an anonymous namespace. */
@ -226,12 +226,19 @@ namespace {
dddd.dddd[eE][+-]ddd dddd.dddd[eE][+-]ddd
where the decimal point and exponent are optional, fill out the where the decimal point and exponent are optional, fill out the
structure D. If the value is zero, V->firstSigDigit structure D. Exponent is appropriate if the significand is
points to a zero, and the return exponent is zero. */ treated as an integer, and normalizedExponent if the significand
is taken to have the decimal point after a single leading
non-zero digit.
If the value is zero, V->firstSigDigit points to a zero, and the
return exponent is zero.
*/
struct decimalInfo { struct decimalInfo {
const char *firstSigDigit; const char *firstSigDigit;
const char *lastSigDigit; const char *lastSigDigit;
int exponent; int exponent;
int normalizedExponent;
}; };
void void
@ -243,6 +250,7 @@ namespace {
D->firstSigDigit = p; D->firstSigDigit = p;
D->exponent = 0; D->exponent = 0;
D->normalizedExponent = 0;
for (;;) { for (;;) {
if (*p == '.') { if (*p == '.') {
@ -270,8 +278,10 @@ namespace {
while (*p == '0'); while (*p == '0');
while (*p == '.'); while (*p == '.');
/* Adjust the specified exponent for any decimal point. */ /* Adjust the exponents for any decimal point. */
D->exponent += (dot - p) - (dot > p); D->exponent += (dot - p) - (dot > p);
D->normalizedExponent = (D->exponent + (p - D->firstSigDigit)
- (dot > D->firstSigDigit && dot < p));
} }
D->lastSigDigit = p; D->lastSigDigit = p;
@ -2079,19 +2089,45 @@ APFloat::convertFromDecimalString(const char *p, roundingMode rounding_mode)
/* Scan the text. */ /* Scan the text. */
interpretDecimal(p, &D); interpretDecimal(p, &D);
/* Handle the quick cases. First the case of no significant digits,
i.e. zero, and then exponents that are obviously too large or too
small. Writing L for log 10 / log 2, a number d.ddddd*10^exp
definitely overflows if
(exp - 1) * L >= maxExponent
and definitely underflows to zero where
(exp + 1) * L <= minExponent - precision
With integer arithmetic the tightest bounds for L are
93/28 < L < 196/59 [ numerator <= 256 ]
42039/12655 < L < 28738/8651 [ numerator <= 65536 ]
*/
if (*D.firstSigDigit == '0') { if (*D.firstSigDigit == '0') {
category = fcZero; category = fcZero;
fs = opOK; fs = opOK;
} else if ((D.normalizedExponent + 1) * 28738
<= 8651 * (semantics->minExponent - (int) semantics->precision)) {
/* Underflow to zero and round. */
zeroSignificand();
fs = normalize(rounding_mode, lfLessThanHalf);
} else if ((D.normalizedExponent - 1) * 42039
>= 12655 * semantics->maxExponent) {
/* Overflow and round. */
fs = handleOverflow(rounding_mode);
} else { } else {
integerPart *decSignificand; integerPart *decSignificand;
unsigned int partCount; unsigned int partCount;
/* A tight upper bound on number of bits required to hold an /* A tight upper bound on number of bits required to hold an
N-digit decimal integer is N * 256 / 77. Allocate enough space N-digit decimal integer is N * 196 / 59. Allocate enough space
to hold the full significand, and an extra part required by to hold the full significand, and an extra part required by
tcMultiplyPart. */ tcMultiplyPart. */
partCount = (D.lastSigDigit - D.firstSigDigit) + 1; partCount = (D.lastSigDigit - D.firstSigDigit) + 1;
partCount = partCountForBits(1 + 256 * partCount / 77); partCount = partCountForBits(1 + 196 * partCount / 59);
decSignificand = new integerPart[partCount + 1]; decSignificand = new integerPart[partCount + 1];
partCount = 0; partCount = 0;