diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index d4c2f950e2d..f81109af417 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 &Str, - unsigned FormatPrecision = 8, + unsigned FormatPrecision = 0, unsigned FormatMaxPadding = 3); private: diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 5f748a2c24c..1e6d22f18ed 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 &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 &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 &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 d2a977a05cd..76cdafcf3fe 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