mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
Separate out parsing of decimal number. Use this to only allocate
memory for the significand once up-front. Also ignore insignificant trailing zeroes; this saves unnecessary multiplications later. llvm-svn: 42964
This commit is contained in:
parent
850c8739dc
commit
a352eb14cd
@ -80,16 +80,11 @@ namespace {
|
|||||||
return ((bits) + integerPartWidth - 1) / integerPartWidth;
|
return ((bits) + integerPartWidth - 1) / integerPartWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
/* Returns 0U-9U. Return values >= 10U are not digits. */
|
||||||
digitValue(unsigned int c)
|
inline unsigned int
|
||||||
|
decDigitValue(unsigned int c)
|
||||||
{
|
{
|
||||||
unsigned int r;
|
return c - '0';
|
||||||
|
|
||||||
r = c - '0';
|
|
||||||
if(r <= 9)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
return -1U;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
@ -112,6 +107,47 @@ namespace {
|
|||||||
return -1U;
|
return -1U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the value of a decimal exponent of the form
|
||||||
|
[+-]ddddddd.
|
||||||
|
|
||||||
|
If the exponent overflows, returns a large exponent with the
|
||||||
|
appropriate sign. */
|
||||||
|
static int
|
||||||
|
readExponent(const char *p)
|
||||||
|
{
|
||||||
|
bool isNegative;
|
||||||
|
unsigned int absExponent;
|
||||||
|
const unsigned int overlargeExponent = 24000; /* FIXME. */
|
||||||
|
|
||||||
|
isNegative = (*p == '-');
|
||||||
|
if (*p == '-' || *p == '+')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
absExponent = decDigitValue(*p++);
|
||||||
|
assert (absExponent < 10U);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
unsigned int value;
|
||||||
|
|
||||||
|
value = decDigitValue(*p);
|
||||||
|
if (value >= 10U)
|
||||||
|
break;
|
||||||
|
|
||||||
|
p++;
|
||||||
|
value += absExponent * 10;
|
||||||
|
if (absExponent >= overlargeExponent) {
|
||||||
|
absExponent = overlargeExponent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
absExponent = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNegative)
|
||||||
|
return -(int) absExponent;
|
||||||
|
else
|
||||||
|
return (int) absExponent;
|
||||||
|
}
|
||||||
|
|
||||||
/* This is ugly and needs cleaning up, but I don't immediately see
|
/* This is ugly and needs cleaning up, but I don't immediately see
|
||||||
how whilst remaining safe. */
|
how whilst remaining safe. */
|
||||||
static int
|
static int
|
||||||
@ -132,8 +168,8 @@ namespace {
|
|||||||
for(;;) {
|
for(;;) {
|
||||||
unsigned int value;
|
unsigned int value;
|
||||||
|
|
||||||
value = digitValue(*p);
|
value = decDigitValue(*p);
|
||||||
if(value == -1U)
|
if(value >= 10U)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
@ -176,6 +212,62 @@ namespace {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Given a normal decimal floating point number of the form
|
||||||
|
|
||||||
|
dddd.dddd[eE][+-]ddd
|
||||||
|
|
||||||
|
where the decimal point and exponent are optional, fill out the
|
||||||
|
structure D. If the value is zero, V->firstSigDigit
|
||||||
|
points to a zero, and the return exponent is zero. */
|
||||||
|
struct decimalInfo {
|
||||||
|
const char *firstSigDigit;
|
||||||
|
const char *lastSigDigit;
|
||||||
|
int exponent;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
interpretDecimal(const char *p, decimalInfo *D)
|
||||||
|
{
|
||||||
|
const char *dot;
|
||||||
|
|
||||||
|
p = skipLeadingZeroesAndAnyDot (p, &dot);
|
||||||
|
|
||||||
|
D->firstSigDigit = p;
|
||||||
|
D->exponent = 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (*p == '.') {
|
||||||
|
assert(dot == 0);
|
||||||
|
dot = p++;
|
||||||
|
}
|
||||||
|
if (decDigitValue(*p) >= 10U)
|
||||||
|
break;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If number is all zerooes accept any exponent. */
|
||||||
|
if (p != D->firstSigDigit) {
|
||||||
|
if (*p == 'e' || *p == 'E')
|
||||||
|
D->exponent = readExponent(p + 1);
|
||||||
|
|
||||||
|
/* Implied decimal point? */
|
||||||
|
if (!dot)
|
||||||
|
dot = p;
|
||||||
|
|
||||||
|
/* Drop insignificant trailing zeroes. */
|
||||||
|
do
|
||||||
|
do
|
||||||
|
p--;
|
||||||
|
while (*p == '0');
|
||||||
|
while (*p == '.');
|
||||||
|
|
||||||
|
/* Adjust the specified exponent for any decimal point. */
|
||||||
|
D->exponent += (dot - p) - (dot > p);
|
||||||
|
}
|
||||||
|
|
||||||
|
D->lastSigDigit = p;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the trailing fraction of a hexadecimal number.
|
/* Return the trailing fraction of a hexadecimal number.
|
||||||
DIGITVALUE is the first hex digit of the fraction, P points to
|
DIGITVALUE is the first hex digit of the fraction, P points to
|
||||||
the next digit. */
|
the next digit. */
|
||||||
@ -1981,104 +2073,65 @@ APFloat::roundSignificandWithExponent(const integerPart *decSigParts,
|
|||||||
APFloat::opStatus
|
APFloat::opStatus
|
||||||
APFloat::convertFromDecimalString(const char *p, roundingMode rounding_mode)
|
APFloat::convertFromDecimalString(const char *p, roundingMode rounding_mode)
|
||||||
{
|
{
|
||||||
const char *dot, *firstSignificantDigit;
|
decimalInfo D;
|
||||||
integerPart val, maxVal, decValue;
|
|
||||||
opStatus fs;
|
opStatus fs;
|
||||||
|
|
||||||
/* Skip leading zeroes and any decimal point. */
|
/* Scan the text. */
|
||||||
p = skipLeadingZeroesAndAnyDot(p, &dot);
|
interpretDecimal(p, &D);
|
||||||
firstSignificantDigit = p;
|
|
||||||
|
|
||||||
/* The maximum number that can be multiplied by ten with any digit
|
if (*D.firstSigDigit == '0') {
|
||||||
added without overflowing an integerPart. */
|
|
||||||
maxVal = (~ (integerPart) 0 - 9) / 10;
|
|
||||||
|
|
||||||
val = 0;
|
|
||||||
while (val <= maxVal) {
|
|
||||||
if (*p == '.') {
|
|
||||||
assert(dot == 0);
|
|
||||||
dot = p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
decValue = digitValue(*p);
|
|
||||||
if (decValue == -1U)
|
|
||||||
break;
|
|
||||||
p++;
|
|
||||||
val = val * 10 + decValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
integerPart *decSignificand;
|
|
||||||
unsigned int partCount, maxPartCount;
|
|
||||||
|
|
||||||
partCount = 0;
|
|
||||||
maxPartCount = 4;
|
|
||||||
decSignificand = new integerPart[maxPartCount];
|
|
||||||
decSignificand[partCount++] = val;
|
|
||||||
|
|
||||||
/* Now continue to do single-part arithmetic for as long as we can.
|
|
||||||
Then do a part multiplication, and repeat. */
|
|
||||||
while (decValue != -1U) {
|
|
||||||
integerPart multiplier;
|
|
||||||
|
|
||||||
val = 0;
|
|
||||||
multiplier = 1;
|
|
||||||
|
|
||||||
while (multiplier <= maxVal) {
|
|
||||||
if (*p == '.') {
|
|
||||||
assert(dot == 0);
|
|
||||||
dot = p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
decValue = digitValue(*p);
|
|
||||||
if (decValue == -1U)
|
|
||||||
break;
|
|
||||||
p++;
|
|
||||||
multiplier *= 10;
|
|
||||||
val = val * 10 + decValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (partCount == maxPartCount) {
|
|
||||||
integerPart *newDecSignificand;
|
|
||||||
newDecSignificand = new integerPart[maxPartCount = partCount * 2];
|
|
||||||
APInt::tcAssign(newDecSignificand, decSignificand, partCount);
|
|
||||||
delete [] decSignificand;
|
|
||||||
decSignificand = newDecSignificand;
|
|
||||||
}
|
|
||||||
|
|
||||||
APInt::tcMultiplyPart(decSignificand, decSignificand, multiplier, val,
|
|
||||||
partCount, partCount + 1, false);
|
|
||||||
|
|
||||||
/* If we used another part (likely), increase the count. */
|
|
||||||
if (decSignificand[partCount] != 0)
|
|
||||||
partCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now decSignificand contains the supplied significand ignoring the
|
|
||||||
decimal point. Figure out our effective exponent, which is the
|
|
||||||
specified exponent adjusted for any decimal point. */
|
|
||||||
|
|
||||||
if (p == firstSignificantDigit) {
|
|
||||||
/* Ignore the exponent if we are zero - we cannot overflow. */
|
|
||||||
category = fcZero;
|
category = fcZero;
|
||||||
fs = opOK;
|
fs = opOK;
|
||||||
} else {
|
} else {
|
||||||
int decimalExponent;
|
integerPart *decSignificand;
|
||||||
|
unsigned int partCount;
|
||||||
|
|
||||||
if (dot)
|
/* A tight upper bound on number of bits required to hold an
|
||||||
decimalExponent = dot + 1 - p;
|
N-digit decimal integer is N * 256 / 77. Allocate enough space
|
||||||
else
|
to hold the full significand, and an extra part required by
|
||||||
decimalExponent = 0;
|
tcMultiplyPart. */
|
||||||
|
partCount = (D.lastSigDigit - D.firstSigDigit) + 1;
|
||||||
|
partCount = partCountForBits(1 + 256 * partCount / 77);
|
||||||
|
decSignificand = new integerPart[partCount + 1];
|
||||||
|
partCount = 0;
|
||||||
|
|
||||||
/* Add the given exponent. */
|
/* Convert to binary efficiently - we do almost all multiplication
|
||||||
if (*p == 'e' || *p == 'E')
|
in an integerPart. When this would overflow do we do a single
|
||||||
decimalExponent = totalExponent(p, decimalExponent);
|
bignum multiplication, and then revert again to multiplication
|
||||||
|
in an integerPart. */
|
||||||
|
do {
|
||||||
|
integerPart decValue, val, multiplier;
|
||||||
|
|
||||||
|
val = 0;
|
||||||
|
multiplier = 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (*p == '.')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
decValue = decDigitValue(*p++);
|
||||||
|
multiplier *= 10;
|
||||||
|
val = val * 10 + decValue;
|
||||||
|
/* The maximum number that can be multiplied by ten with any
|
||||||
|
digit added without overflowing an integerPart. */
|
||||||
|
} while (p <= D.lastSigDigit && multiplier <= (~ (integerPart) 0 - 9) / 10);
|
||||||
|
|
||||||
|
/* Multiply out the current part. */
|
||||||
|
APInt::tcMultiplyPart(decSignificand, decSignificand, multiplier, val,
|
||||||
|
partCount, partCount + 1, false);
|
||||||
|
|
||||||
|
/* If we used another part (likely but not guaranteed), increase
|
||||||
|
the count. */
|
||||||
|
if (decSignificand[partCount])
|
||||||
|
partCount++;
|
||||||
|
} while (p <= D.lastSigDigit);
|
||||||
|
|
||||||
category = fcNormal;
|
category = fcNormal;
|
||||||
fs = roundSignificandWithExponent(decSignificand, partCount,
|
fs = roundSignificandWithExponent(decSignificand, partCount,
|
||||||
decimalExponent, rounding_mode);
|
D.exponent, rounding_mode);
|
||||||
}
|
|
||||||
|
|
||||||
delete [] decSignificand;
|
delete [] decSignificand;
|
||||||
|
}
|
||||||
|
|
||||||
return fs;
|
return fs;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user