diff options
Diffstat (limited to 'llvm/lib/Support/APFloat.cpp')
-rw-r--r-- | llvm/lib/Support/APFloat.cpp | 375 |
1 files changed, 195 insertions, 180 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 3017a9b..3664de7 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -4118,6 +4118,199 @@ namespace { exp += FirstSignificant; buffer.erase(&buffer[0], &buffer[FirstSignificant]); } + + void toStringImpl(SmallVectorImpl<char> &Str, const bool isNeg, int exp, + APInt significand, unsigned FormatPrecision, + unsigned FormatMaxPadding, bool TruncateZero) { + const int semanticsPrecision = significand.getBitWidth(); + + if (isNeg) + Str.push_back('-'); + + // Set FormatPrecision if zero. We want to do this before we + // truncate trailing zeros, as those are part of the precision. + if (!FormatPrecision) { + // We use enough digits so the number can be round-tripped back to an + // APFloat. The formula comes from "How to Print Floating-Point Numbers + // Accurately" by Steele and White. + // FIXME: Using a formula based purely on the precision is conservative; + // we can print fewer digits depending on the actual value being printed. + + // FormatPrecision = 2 + floor(significandBits / lg_2(10)) + FormatPrecision = 2 + semanticsPrecision * 59 / 196; + } + + // Ignore trailing binary zeros. + int trailingZeros = significand.countr_zero(); + exp += trailingZeros; + significand.lshrInPlace(trailingZeros); + + // Change the exponent from 2^e to 10^e. + if (exp == 0) { + // Nothing to do. + } else if (exp > 0) { + // Just shift left. + significand = significand.zext(semanticsPrecision + exp); + significand <<= exp; + exp = 0; + } else { /* exp < 0 */ + int texp = -exp; + + // We transform this using the identity: + // (N)(2^-e) == (N)(5^e)(10^-e) + // This means we have to multiply N (the significand) by 5^e. + // 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 * 137 / 59 + // (log_2(5) ~ 2.321928 < 2.322034 ~ 137/59) + + unsigned precision = semanticsPrecision + (137 * texp + 136) / 59; + + // Multiply significand by 5^e. + // N * 5^0101 == N * 5^(1*1) * 5^(0*2) * 5^(1*4) * 5^(0*8) + significand = significand.zext(precision); + APInt five_to_the_i(precision, 5); + while (true) { + if (texp & 1) + significand *= five_to_the_i; + + texp >>= 1; + if (!texp) + break; + five_to_the_i *= five_to_the_i; + } + } + + AdjustToPrecision(significand, exp, FormatPrecision); + + SmallVector<char, 256> buffer; + + // Fill the buffer. + unsigned precision = significand.getBitWidth(); + if (precision < 4) { + // We need enough precision to store the value 10. + precision = 4; + significand = significand.zext(precision); + } + APInt ten(precision, 10); + APInt digit(precision, 0); + + bool inTrail = true; + while (significand != 0) { + // digit <- significand % 10 + // significand <- significand / 10 + APInt::udivrem(significand, ten, significand, digit); + + unsigned d = digit.getZExtValue(); + + // Drop trailing zeros. + if (inTrail && !d) + exp++; + else { + buffer.push_back((char) ('0' + d)); + inTrail = false; + } + } + + assert(!buffer.empty() && "no characters in buffer!"); + + // Drop down to FormatPrecision. + // TODO: don't do more precise calculations above than are required. + AdjustToPrecision(buffer, exp, FormatPrecision); + + unsigned NDigits = buffer.size(); + + // Check whether we should use scientific notation. + bool FormatScientific; + if (!FormatMaxPadding) + FormatScientific = true; + else { + if (exp >= 0) { + // 765e3 --> 765000 + // ^^^ + // But we shouldn't make the number look more precise than it is. + FormatScientific = ((unsigned) exp > FormatMaxPadding || + NDigits + (unsigned) exp > FormatPrecision); + } else { + // Power of the most significant digit. + int MSD = exp + (int) (NDigits - 1); + if (MSD >= 0) { + // 765e-2 == 7.65 + FormatScientific = false; + } else { + // 765e-5 == 0.00765 + // ^ ^^ + FormatScientific = ((unsigned) -MSD) > FormatMaxPadding; + } + } + } + + // Scientific formatting is pretty straightforward. + if (FormatScientific) { + exp += (NDigits - 1); + + Str.push_back(buffer[NDigits-1]); + Str.push_back('.'); + if (NDigits == 1 && TruncateZero) + Str.push_back('0'); + else + for (unsigned I = 1; I != NDigits; ++I) + Str.push_back(buffer[NDigits-1-I]); + // Fill with zeros up to FormatPrecision. + if (!TruncateZero && FormatPrecision > NDigits - 1) + Str.append(FormatPrecision - NDigits + 1, '0'); + // For !TruncateZero we use lower 'e'. + Str.push_back(TruncateZero ? 'E' : 'e'); + + Str.push_back(exp >= 0 ? '+' : '-'); + if (exp < 0) + exp = -exp; + SmallVector<char, 6> expbuf; + do { + expbuf.push_back((char) ('0' + (exp % 10))); + exp /= 10; + } while (exp); + // Exponent always at least two digits if we do not truncate zeros. + if (!TruncateZero && expbuf.size() < 2) + expbuf.push_back('0'); + for (unsigned I = 0, E = expbuf.size(); I != E; ++I) + Str.push_back(expbuf[E-1-I]); + return; + } + + // Non-scientific, positive exponents. + if (exp >= 0) { + for (unsigned I = 0; I != NDigits; ++I) + Str.push_back(buffer[NDigits-1-I]); + for (unsigned I = 0; I != (unsigned) exp; ++I) + Str.push_back('0'); + return; + } + + // Non-scientific, negative exponents. + + // The number of digits to the left of the decimal point. + int NWholeDigits = exp + (int) NDigits; + + unsigned I = 0; + if (NWholeDigits > 0) { + for (; I != (unsigned) NWholeDigits; ++I) + Str.push_back(buffer[NDigits-I-1]); + Str.push_back('.'); + } else { + unsigned NZeros = 1 + (unsigned) -NWholeDigits; + + Str.push_back('0'); + Str.push_back('.'); + for (unsigned Z = 1; Z != NZeros; ++Z) + Str.push_back('0'); + } + + for (; I != NDigits; ++I) + Str.push_back(buffer[NDigits-I-1]); + + } } // namespace void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision, @@ -4152,193 +4345,15 @@ void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision, break; } - if (isNegative()) - Str.push_back('-'); - // Decompose the number into an APInt and an exponent. int exp = exponent - ((int) semantics->precision - 1); APInt significand( semantics->precision, ArrayRef(significandParts(), partCountForBits(semantics->precision))); - // Set FormatPrecision if zero. We want to do this before we - // truncate trailing zeros, as those are part of the precision. - if (!FormatPrecision) { - // We use enough digits so the number can be round-tripped back to an - // APFloat. The formula comes from "How to Print Floating-Point Numbers - // Accurately" by Steele and White. - // FIXME: Using a formula based purely on the precision is conservative; - // we can print fewer digits depending on the actual value being printed. - - // FormatPrecision = 2 + floor(significandBits / lg_2(10)) - FormatPrecision = 2 + semantics->precision * 59 / 196; - } - - // Ignore trailing binary zeros. - int trailingZeros = significand.countr_zero(); - exp += trailingZeros; - significand.lshrInPlace(trailingZeros); - - // Change the exponent from 2^e to 10^e. - if (exp == 0) { - // Nothing to do. - } else if (exp > 0) { - // Just shift left. - significand = significand.zext(semantics->precision + exp); - significand <<= exp; - exp = 0; - } else { /* exp < 0 */ - int texp = -exp; - - // We transform this using the identity: - // (N)(2^-e) == (N)(5^e)(10^-e) - // This means we have to multiply N (the significand) by 5^e. - // 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 * 137 / 59 - // (log_2(5) ~ 2.321928 < 2.322034 ~ 137/59) - - unsigned precision = semantics->precision + (137 * texp + 136) / 59; - - // Multiply significand by 5^e. - // N * 5^0101 == N * 5^(1*1) * 5^(0*2) * 5^(1*4) * 5^(0*8) - significand = significand.zext(precision); - APInt five_to_the_i(precision, 5); - while (true) { - if (texp & 1) significand *= five_to_the_i; - - texp >>= 1; - if (!texp) break; - five_to_the_i *= five_to_the_i; - } - } - - AdjustToPrecision(significand, exp, FormatPrecision); - - SmallVector<char, 256> buffer; - - // Fill the buffer. - unsigned precision = significand.getBitWidth(); - if (precision < 4) { - // We need enough precision to store the value 10. - precision = 4; - significand = significand.zext(precision); - } - APInt ten(precision, 10); - APInt digit(precision, 0); - - bool inTrail = true; - while (significand != 0) { - // digit <- significand % 10 - // significand <- significand / 10 - APInt::udivrem(significand, ten, significand, digit); - - unsigned d = digit.getZExtValue(); - - // Drop trailing zeros. - if (inTrail && !d) exp++; - else { - buffer.push_back((char) ('0' + d)); - inTrail = false; - } - } - - assert(!buffer.empty() && "no characters in buffer!"); - - // Drop down to FormatPrecision. - // TODO: don't do more precise calculations above than are required. - AdjustToPrecision(buffer, exp, FormatPrecision); - - unsigned NDigits = buffer.size(); - - // Check whether we should use scientific notation. - bool FormatScientific; - if (!FormatMaxPadding) - FormatScientific = true; - else { - if (exp >= 0) { - // 765e3 --> 765000 - // ^^^ - // But we shouldn't make the number look more precise than it is. - FormatScientific = ((unsigned) exp > FormatMaxPadding || - NDigits + (unsigned) exp > FormatPrecision); - } else { - // Power of the most significant digit. - int MSD = exp + (int) (NDigits - 1); - if (MSD >= 0) { - // 765e-2 == 7.65 - FormatScientific = false; - } else { - // 765e-5 == 0.00765 - // ^ ^^ - FormatScientific = ((unsigned) -MSD) > FormatMaxPadding; - } - } - } - - // Scientific formatting is pretty straightforward. - if (FormatScientific) { - exp += (NDigits - 1); - - Str.push_back(buffer[NDigits-1]); - Str.push_back('.'); - if (NDigits == 1 && TruncateZero) - Str.push_back('0'); - else - for (unsigned I = 1; I != NDigits; ++I) - Str.push_back(buffer[NDigits-1-I]); - // Fill with zeros up to FormatPrecision. - if (!TruncateZero && FormatPrecision > NDigits - 1) - Str.append(FormatPrecision - NDigits + 1, '0'); - // For !TruncateZero we use lower 'e'. - Str.push_back(TruncateZero ? 'E' : 'e'); - - Str.push_back(exp >= 0 ? '+' : '-'); - if (exp < 0) exp = -exp; - SmallVector<char, 6> expbuf; - do { - expbuf.push_back((char) ('0' + (exp % 10))); - exp /= 10; - } while (exp); - // Exponent always at least two digits if we do not truncate zeros. - if (!TruncateZero && expbuf.size() < 2) - expbuf.push_back('0'); - for (unsigned I = 0, E = expbuf.size(); I != E; ++I) - Str.push_back(expbuf[E-1-I]); - return; - } - - // Non-scientific, positive exponents. - if (exp >= 0) { - for (unsigned I = 0; I != NDigits; ++I) - Str.push_back(buffer[NDigits-1-I]); - for (unsigned I = 0; I != (unsigned) exp; ++I) - Str.push_back('0'); - return; - } - - // Non-scientific, negative exponents. - - // The number of digits to the left of the decimal point. - int NWholeDigits = exp + (int) NDigits; - - unsigned I = 0; - if (NWholeDigits > 0) { - for (; I != (unsigned) NWholeDigits; ++I) - Str.push_back(buffer[NDigits-I-1]); - Str.push_back('.'); - } else { - unsigned NZeros = 1 + (unsigned) -NWholeDigits; - - Str.push_back('0'); - Str.push_back('.'); - for (unsigned Z = 1; Z != NZeros; ++Z) - Str.push_back('0'); - } + toStringImpl(Str, isNegative(), exp, significand, FormatPrecision, + FormatMaxPadding, TruncateZero); - for (; I != NDigits; ++I) - Str.push_back(buffer[NDigits-I-1]); } bool IEEEFloat::getExactInverse(APFloat *inv) const { |