You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The bug seems to be that the conversion of an APFloat to a string (using the "natural precision") and then converting that back into an APFloat can result in a different value when not using APFloat::rmNearestTiesToEven.
In the implementation of APFloat::toString(...) you can
specify FormatPrecision as 0. The method comments state that this
will use the "natural precision" of the number. In the actual
implementation the comments say that when FormatPrecision is 0 that
// 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.
Based on the above comments I expected to be able to convert an
APFloat to a string and back again when FormatPrecision is set to
zero. However this does not seem to hold. Here's some example code
that demonstrates this.
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/APFloat.h"
#include <string>
using namespace llvm;
std::string getString(APFloat f) {
SmallVector<char,10> strRep;
// FormatPrecision=0 means that the "natural precision" of the number is used
f.toString(strRep,/*FormatPrecision=*/0, /*FormatMaxPadding=*/0);
return std::string(strRep.begin(), strRep.end());
}
uint16_t getBits(APFloat f) {
APInt bits = f.bitcastToAPInt();
assert(bits.getActiveBits() <= 16);
return (uint16_t) (bits.getZExtValue() & 0xffff);
}
int main(int argc, char** argv) {
APFloat f(APFloat::IEEEhalf);
APFloat newF(APFloat::IEEEhalf);
f.convertFromString("0.3", APFloat::rmTowardZero);
outs() << "f bits: 0x";
outs().write_hex(getBits(f));
outs() << "\n";
assert(getBits(f) == 0x34cc);
// Check that if we get the string using FormatPrecision=0
// that this can be used to construct another APFloat of the
// same value.
std::string fAsString = getString(f);
outs() << "f as string: \"" << fAsString << "\"\n";
newF.convertFromString(fAsString, APFloat::rmTowardZero);
outs() << "newF as string: \"" << getString(newF) << "\"\n";
outs() << "newF bits: 0x";
outs().write_hex(getBits(newF));
outs() << "\n";
// BUG This assert fails
assert(getBits(newF) == 0x34cc);
return 0;
}
The output I see is
f bits: 0x34cc
f as string: "2.998E-1"
newF as string: "2.9956E-1"
newF bits: 0x34cb
... Assertion `getBits(newF) == 0x34cc' failed.
As you can see when we create a new APFloat from the string we get a
slightly smaller number. I have observed that if I use APFloat::rmNearestTiesToEven when creating newF that I do get
an APFloat instance which has the same value as the original APFloat.
Extended Description
This was discussed on mailing list [1].
The bug seems to be that the conversion of an APFloat to a string (using the "natural precision") and then converting that back into an APFloat can result in a different value when not using
APFloat::rmNearestTiesToEven
.In the implementation of
APFloat::toString(...)
you canspecify
FormatPrecision
as 0. The method comments state that thiswill use the "natural precision" of the number. In the actual
implementation the comments say that when FormatPrecision is 0 that
Based on the above comments I expected to be able to convert an
APFloat to a string and back again when
FormatPrecision
is set tozero. However this does not seem to hold. Here's some example code
that demonstrates this.
The output I see is
As you can see when we create a new APFloat from the string we get a
slightly smaller number. I have observed that if I use
APFloat::rmNearestTiesToEven
when creatingnewF
that I do getan APFloat instance which has the same value as the original APFloat.
[1] http://lists.llvm.org/pipermail/llvm-dev/2015-August/089085.html
The text was updated successfully, but these errors were encountered: