[LLVMdev] APFloat storage complications
Neil Booth
neil at daikokuya.co.uk
Fri Sep 21 19:39:55 PDT 2007
APFloat is derived from C code using fixed width storage for
the matntissa. When converting to C++ I changed it to variable-
width storage for space efficiency and generality reasons.
Unfortunately this leads to a complication during float->float
conversions that I missed that isn't present when using fixed
width storage.
Dale - I think this solves the issue correctly whilst preserving
correct rounding. Does it fix the problem case you had?
Neil.
-------------- next part --------------
Index: lib/Support/APFloat.cpp
===================================================================
--- lib/Support/APFloat.cpp (revision 42219)
+++ lib/Support/APFloat.cpp (working copy)
@@ -1318,39 +1318,44 @@
APFloat::convert(const fltSemantics &toSemantics,
roundingMode rounding_mode)
{
- unsigned int newPartCount;
+ lostFraction lostFraction;
+ unsigned int newPartCount, oldPartCount;
opStatus fs;
-
+
+ lostFraction = lfExactlyZero;
newPartCount = partCountForBits(toSemantics.precision + 1);
+ oldPartCount = partCount();
- /* If our new form is wider, re-allocate our bit pattern into wider
- storage.
- If we're narrowing from multiple words to 1 words, copy to the single
- word. If we are losing information by doing this, we would have to
- worry about rounding; right now the only case is f80 -> shorter
- conversion, and we are keeping all 64 significant bits, so it's OK. */
- if(newPartCount > partCount()) {
+ /* Handle storage complications. If our new form is wider,
+ re-allocate our bit pattern into wider storage. If it is
+ narrower, we ignore the excess parts, but if narrowing to a
+ single part we need to free the old storage. */
+ if (newPartCount > oldPartCount) {
integerPart *newParts;
newParts = new integerPart[newPartCount];
APInt::tcSet(newParts, 0, newPartCount);
- APInt::tcAssign(newParts, significandParts(), partCount());
+ APInt::tcAssign(newParts, significandParts(), oldPartCount);
freeSignificand();
significand.parts = newParts;
- } else if (newPartCount==1 && newPartCount < partCount()) {
- integerPart newPart;
-
- APInt::tcSet(&newPart, 0, newPartCount);
- APInt::tcAssign(&newPart, significandParts(), partCount());
- freeSignificand();
- significand.part = newPart;
+ } else if (newPartCount < oldPartCount) {
+ /* Capture any lost fraction through truncation of parts so we get
+ correct rounding whilst normalizing. */
+ lostFraction = lostFractionThroughTruncation
+ (significandParts(), oldPartCount, newPartCount * integerPartWidth);
+ if (newPartCount == 1)
+ {
+ integerPart newPart = significandParts()[0];
+ freeSignificand();
+ significand.part = newPart;
+ }
}
if(category == fcNormal) {
/* Re-interpret our bit-pattern. */
exponent += toSemantics.precision - semantics->precision;
semantics = &toSemantics;
- fs = normalize(rounding_mode, lfExactlyZero);
+ fs = normalize(rounding_mode, lostFraction);
} else {
semantics = &toSemantics;
fs = opOK;
More information about the llvm-dev
mailing list