mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-28 03:25:23 +00:00
Implement support for converting to string at "natural precision", and fix some
major bugs in long-precision conversion. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@92150 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -304,7 +304,8 @@ namespace llvm {
|
|||||||
/// precision to output. If there are fewer digits available,
|
/// precision to output. If there are fewer digits available,
|
||||||
/// zero padding will not be used unless the value is
|
/// zero padding will not be used unless the value is
|
||||||
/// integral and small enough to be expressed in
|
/// integral and small enough to be expressed in
|
||||||
/// FormatPrecision digits.
|
/// FormatPrecision digits. 0 means to use the natural
|
||||||
|
/// precision of the number.
|
||||||
/// \param FormatMaxPadding The maximum number of zeros to
|
/// \param FormatMaxPadding The maximum number of zeros to
|
||||||
/// consider inserting before falling back to scientific
|
/// consider inserting before falling back to scientific
|
||||||
/// notation. 0 means to always use scientific notation.
|
/// notation. 0 means to always use scientific notation.
|
||||||
@@ -315,10 +316,10 @@ namespace llvm {
|
|||||||
/// 1.01E+4 4 2 1.01E+4
|
/// 1.01E+4 4 2 1.01E+4
|
||||||
/// 1.01E+4 5 1 1.01E+4
|
/// 1.01E+4 5 1 1.01E+4
|
||||||
/// 1.01E-2 5 2 0.0101
|
/// 1.01E-2 5 2 0.0101
|
||||||
/// 1.01E-2 4 2 1.01E-2
|
/// 1.01E-2 4 2 0.0101
|
||||||
/// 1.01E-2 4 1 1.01E-2
|
/// 1.01E-2 4 1 1.01E-2
|
||||||
void toString(SmallVectorImpl<char> &Str,
|
void toString(SmallVectorImpl<char> &Str,
|
||||||
unsigned FormatPrecision = 8,
|
unsigned FormatPrecision = 0,
|
||||||
unsigned FormatMaxPadding = 3);
|
unsigned FormatMaxPadding = 3);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -3253,7 +3253,7 @@ namespace {
|
|||||||
|
|
||||||
// Truncate the significand down to its active bit count, but
|
// Truncate the significand down to its active bit count, but
|
||||||
// don't try to drop below 32.
|
// don't try to drop below 32.
|
||||||
unsigned newPrecision = std::min(32U, significand.getActiveBits());
|
unsigned newPrecision = std::max(32U, significand.getActiveBits());
|
||||||
significand.trunc(newPrecision);
|
significand.trunc(newPrecision);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3339,6 +3339,16 @@ void APFloat::toString(SmallVectorImpl<char> &Str,
|
|||||||
partCountForBits(semantics->precision),
|
partCountForBits(semantics->precision),
|
||||||
significandParts());
|
significandParts());
|
||||||
|
|
||||||
|
// Set FormatPrecision if zero. We want to do this before we
|
||||||
|
// truncate trailing zeros, as those are part of the precision.
|
||||||
|
if (!FormatPrecision) {
|
||||||
|
// It's an interesting question whether to use the nominal
|
||||||
|
// precision or the active precision here for denormals.
|
||||||
|
|
||||||
|
// FormatPrecision = ceil(significandBits / lg_2(10))
|
||||||
|
FormatPrecision = (semantics->precision * 59 + 195) / 196;
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore trailing binary zeros.
|
// Ignore trailing binary zeros.
|
||||||
int trailingZeros = significand.countTrailingZeros();
|
int trailingZeros = significand.countTrailingZeros();
|
||||||
exp += trailingZeros;
|
exp += trailingZeros;
|
||||||
@@ -3361,9 +3371,10 @@ void APFloat::toString(SmallVectorImpl<char> &Str,
|
|||||||
// To avoid overflow, we have to operate on numbers large
|
// To avoid overflow, we have to operate on numbers large
|
||||||
// enough to store N * 5^e:
|
// enough to store N * 5^e:
|
||||||
// log2(N * 5^e) == log2(N) + e * log2(5)
|
// log2(N * 5^e) == log2(N) + e * log2(5)
|
||||||
// <= semantics->precision + e * 2.5
|
// <= semantics->precision + e * 137 / 59
|
||||||
// (log_2(5) ~ 2.321928)
|
// (log_2(5) ~ 2.321928 < 2.322034 ~ 137/59)
|
||||||
unsigned precision = semantics->precision + 5 * texp / 2;
|
|
||||||
|
unsigned precision = semantics->precision + 137 * texp / 59;
|
||||||
|
|
||||||
// Multiply significand by 5^e.
|
// Multiply significand by 5^e.
|
||||||
// N * 5^0101 == N * 5^(1*1) * 5^(0*2) * 5^(1*4) * 5^(0*8)
|
// N * 5^0101 == N * 5^(1*1) * 5^(0*2) * 5^(1*4) * 5^(0*8)
|
||||||
@@ -3411,30 +3422,29 @@ void APFloat::toString(SmallVectorImpl<char> &Str,
|
|||||||
|
|
||||||
unsigned NDigits = buffer.size();
|
unsigned NDigits = buffer.size();
|
||||||
|
|
||||||
// Check whether we should a non-scientific format.
|
// Check whether we should use scientific notation.
|
||||||
bool FormatScientific;
|
bool FormatScientific;
|
||||||
if (!FormatMaxPadding)
|
if (!FormatMaxPadding)
|
||||||
FormatScientific = true;
|
FormatScientific = true;
|
||||||
else {
|
else {
|
||||||
unsigned Padding;
|
|
||||||
if (exp >= 0) {
|
if (exp >= 0) {
|
||||||
// 765e3 == 765000
|
// 765e3 --> 765000
|
||||||
// ^^^
|
// ^^^
|
||||||
Padding = (unsigned) exp;
|
// But we shouldn't make the number look more precise than it is.
|
||||||
|
FormatScientific = ((unsigned) exp > FormatMaxPadding ||
|
||||||
|
NDigits + (unsigned) exp > FormatPrecision);
|
||||||
} else {
|
} else {
|
||||||
unsigned Margin = (unsigned) -exp;
|
// Power of the most significant digit.
|
||||||
if (Margin < NDigits) {
|
int MSD = exp + (int) (NDigits - 1);
|
||||||
|
if (MSD >= 0) {
|
||||||
// 765e-2 == 7.65
|
// 765e-2 == 7.65
|
||||||
Padding = 0;
|
FormatScientific = false;
|
||||||
} else {
|
} else {
|
||||||
// 765e-5 == 0.00765
|
// 765e-5 == 0.00765
|
||||||
// ^ ^^
|
// ^ ^^
|
||||||
Padding = Margin + 1 - NDigits;
|
FormatScientific = ((unsigned) -MSD) > FormatMaxPadding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FormatScientific = (Padding > FormatMaxPadding ||
|
|
||||||
Padding + NDigits > FormatPrecision);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scientific formatting is pretty straightforward.
|
// Scientific formatting is pretty straightforward.
|
||||||
|
@@ -329,8 +329,10 @@ TEST(APFloatTest, toString) {
|
|||||||
ASSERT_EQ("1.01E+4", convertToString(1.01E+4, 4, 2));
|
ASSERT_EQ("1.01E+4", convertToString(1.01E+4, 4, 2));
|
||||||
ASSERT_EQ("1.01E+4", convertToString(1.01E+4, 5, 1));
|
ASSERT_EQ("1.01E+4", convertToString(1.01E+4, 5, 1));
|
||||||
ASSERT_EQ("0.0101", convertToString(1.01E-2, 5, 2));
|
ASSERT_EQ("0.0101", convertToString(1.01E-2, 5, 2));
|
||||||
ASSERT_EQ("1.01E-2", convertToString(1.01E-2, 4, 2));
|
ASSERT_EQ("0.0101", convertToString(1.01E-2, 4, 2));
|
||||||
ASSERT_EQ("1.01E-2", convertToString(1.01E-2, 5, 1));
|
ASSERT_EQ("1.01E-2", convertToString(1.01E-2, 5, 1));
|
||||||
|
ASSERT_EQ("0.7853981633974483", convertToString(0.78539816339744830961, 0, 3));
|
||||||
|
ASSERT_EQ("4.940656458412465E-324", convertToString(4.9406564584124654e-324, 0, 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GTEST_HAS_DEATH_TEST
|
#ifdef GTEST_HAS_DEATH_TEST
|
||||||
|
Reference in New Issue
Block a user