in lib/LLVMSupport/Support/APFloat.cpp [3398:3612]
void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
unsigned FormatMaxPadding, bool TruncateZero) const {
switch (category) {
case fcInfinity:
if (isNegative())
return append(Str, "-Inf");
else
return append(Str, "+Inf");
case fcNaN: return append(Str, "NaN");
case fcZero:
if (isNegative())
Str.push_back('-');
if (!FormatMaxPadding) {
if (TruncateZero)
append(Str, "0.0E+0");
else {
append(Str, "0.0");
if (FormatPrecision > 1)
Str.append(FormatPrecision - 1, '0');
append(Str, "e+00");
}
} else
Str.push_back('0');
return;
case fcNormal:
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,
makeArrayRef(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.countTrailingZeros();
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();
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]);
}