[llvm-commits] [llvm] r41726 - /llvm/trunk/lib/Support/APFloat.cpp
Dale Johannesen
dalej at apple.com
Wed Sep 5 13:39:49 PDT 2007
Author: johannes
Date: Wed Sep 5 15:39:49 2007
New Revision: 41726
URL: http://llvm.org/viewvc/llvm-project?rev=41726&view=rev
Log:
Fix mod so it actually works. Fix conversions to
native types to handle denormals correctly.
Modified:
llvm/trunk/lib/Support/APFloat.cpp
Modified: llvm/trunk/lib/Support/APFloat.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APFloat.cpp?rev=41726&r1=41725&r2=41726&view=diff
==============================================================================
--- llvm/trunk/lib/Support/APFloat.cpp (original)
+++ llvm/trunk/lib/Support/APFloat.cpp Wed Sep 5 15:39:49 2007
@@ -1168,21 +1168,30 @@
{
opStatus fs;
APFloat V = *this;
+ unsigned int origSign = sign;
fs = V.divide(rhs, rmNearestTiesToEven);
if (fs == opDivByZero)
return fs;
- integerPart x;
- fs = V.convertToInteger(&x, integerPartWidth, true, rmNearestTiesToEven);
+ int parts = partCount();
+ integerPart *x = new integerPart[parts];
+ fs = V.convertToInteger(x, parts * integerPartWidth, true,
+ rmNearestTiesToEven);
if (fs==opInvalidOp)
return fs;
- fs = V.convertFromInteger(&x, integerPartWidth, true, rmNearestTiesToEven);
+ fs = V.convertFromInteger(x, parts, true, rmNearestTiesToEven);
assert(fs==opOK); // should always work
+
fs = V.multiply(rhs, rounding_mode);
- assert(fs==opOK); // should not overflow or underflow
+ assert(fs==opOK || fs==opInexact); // should not overflow or underflow
+
fs = subtract(V, rounding_mode);
- assert(fs==opOK);
+ assert(fs==opOK || fs==opInexact); // likewise
+
+ if (isZero())
+ sign = origSign; // IEEE754 requires this
+ delete[] x;
return fs;
}
@@ -1581,6 +1590,9 @@
// Current implementation requires partCount()==1, which is correct at the
// moment but could be made more general.
+// Denormals have exponent minExponent in APFloat, but minExponent-1 in
+// the actual IEEE respresentation. We compensate for that here.
+
double
APFloat::convertToDouble() const {
assert(semantics == (const llvm::fltSemantics* const)&IEEEdouble);
@@ -1589,8 +1601,10 @@
uint64_t myexponent, mysignificand;
if (category==fcNormal) {
- mysignificand = *significandParts();
myexponent = exponent+1023; //bias
+ mysignificand = *significandParts();
+ if (myexponent==1 && !(mysignificand & 0x10000000000000LL))
+ myexponent = 0; // denormal
} else if (category==fcZero) {
myexponent = 0;
mysignificand = 0;
@@ -1618,6 +1632,8 @@
if (category==fcNormal) {
myexponent = exponent+127; //bias
mysignificand = *significandParts();
+ if (myexponent == 1 && !(mysignificand & 0x400000))
+ myexponent = 0; // denormal
} else if (category==fcZero) {
myexponent = 0;
mysignificand = 0;
@@ -1625,7 +1641,7 @@
myexponent = 0xff;
mysignificand = 0;
} else if (category==fcNaN) {
- myexponent = 0x7ff;
+ myexponent = 0xff;
mysignificand = *significandParts();
} else
assert(0);
@@ -1656,7 +1672,11 @@
} else {
category = fcNormal;
exponent = myexponent - 1023;
- *significandParts() = mysignificand | 0x10000000000000LL;
+ *significandParts() = mysignificand;
+ if (myexponent==0) // denormal
+ exponent = -1022;
+ else
+ *significandParts() |= 0x10000000000000LL; // integer bit
}
}
@@ -1682,6 +1702,10 @@
} else {
category = fcNormal;
exponent = myexponent - 127; //bias
- *significandParts() = mysignificand | 0x800000; // integer bit
+ *significandParts() = mysignificand;
+ if (myexponent==0) // denormal
+ exponent = -126;
+ else
+ *significandParts() |= 0x800000; // integer bit
}
}
More information about the llvm-commits
mailing list