summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/ADT/APFloat.h7
-rw-r--r--lib/Support/APFloat.cpp42
-rw-r--r--unittests/ADT/APFloatTest.cpp4
3 files changed, 33 insertions, 20 deletions
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h
index d4c2f950e2..f81109af41 100644
--- a/include/llvm/ADT/APFloat.h
+++ b/include/llvm/ADT/APFloat.h
@@ -304,7 +304,8 @@ namespace llvm {
/// precision to output. If there are fewer digits available,
/// zero padding will not be used unless the value is
/// 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
/// consider inserting before falling back to scientific
/// 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 5 1 1.01E+4
/// 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
void toString(SmallVectorImpl<char> &Str,
- unsigned FormatPrecision = 8,
+ unsigned FormatPrecision = 0,
unsigned FormatMaxPadding = 3);
private:
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index 5f748a2c24..1e6d22f18e 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -3253,7 +3253,7 @@ namespace {
// Truncate the significand down to its active bit count, but
// don't try to drop below 32.
- unsigned newPrecision = std::min(32U, significand.getActiveBits());
+ unsigned newPrecision = std::max(32U, significand.getActiveBits());
significand.trunc(newPrecision);
}
@@ -3339,6 +3339,16 @@ void APFloat::toString(SmallVectorImpl<char> &Str,
partCountForBits(semantics->precision),
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.
int trailingZeros = significand.countTrailingZeros();
exp += trailingZeros;
@@ -3361,9 +3371,10 @@ void APFloat::toString(SmallVectorImpl<char> &Str,
// To avoid overflow, we have to operate on numbers large
// enough to store N * 5^e:
// log2(N * 5^e) == log2(N) + e * log2(5)
- // <= semantics->precision + e * 2.5
- // (log_2(5) ~ 2.321928)
- unsigned precision = semantics->precision + 5 * texp / 2;
+ // <= semantics->precision + e * 137 / 59
+ // (log_2(5) ~ 2.321928 < 2.322034 ~ 137/59)
+
+ unsigned precision = semantics->precision + 137 * texp / 59;
// Multiply significand by 5^e.
// 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();
- // Check whether we should a non-scientific format.
+ // Check whether we should use scientific notation.
bool FormatScientific;
if (!FormatMaxPadding)
FormatScientific = true;
else {
- unsigned Padding;
if (exp >= 0) {
- // 765e3 == 765000
- // ^^^
- Padding = (unsigned) exp;
+ // 765e3 --> 765000
+ // ^^^
+ // But we shouldn't make the number look more precise than it is.
+ FormatScientific = ((unsigned) exp > FormatMaxPadding ||
+ NDigits + (unsigned) exp > FormatPrecision);
} else {
- unsigned Margin = (unsigned) -exp;
- if (Margin < NDigits) {
+ // Power of the most significant digit.
+ int MSD = exp + (int) (NDigits - 1);
+ if (MSD >= 0) {
// 765e-2 == 7.65
- Padding = 0;
+ FormatScientific = false;
} else {
// 765e-5 == 0.00765
// ^ ^^
- Padding = Margin + 1 - NDigits;
+ FormatScientific = ((unsigned) -MSD) > FormatMaxPadding;
}
}
-
- FormatScientific = (Padding > FormatMaxPadding ||
- Padding + NDigits > FormatPrecision);
}
// Scientific formatting is pretty straightforward.
diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp
index d2a977a05c..76cdafcf3f 100644
--- a/unittests/ADT/APFloatTest.cpp
+++ b/unittests/ADT/APFloatTest.cpp
@@ -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, 5, 1));
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("0.7853981633974483", convertToString(0.78539816339744830961, 0, 3));
+ ASSERT_EQ("4.940656458412465E-324", convertToString(4.9406564584124654e-324, 0, 3));
}
#ifdef GTEST_HAS_DEATH_TEST