aboutsummaryrefslogtreecommitdiff
path: root/lib/Support/APFloat.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-02-28 02:51:25 +0000
committerJohn McCall <rjmccall@apple.com>2010-02-28 02:51:25 +0000
commite12b73816b50bbe2cc54b8005d86c95413b4f465 (patch)
tree167c037c24ea67c3d1d116f1ac9df701eb863a0e /lib/Support/APFloat.cpp
parent6281cda6737bcda0e924318ddcce28392001691e (diff)
Teach APFloat how to create both QNaNs and SNaNs and with arbitrary-width
payloads. APFloat's internal folding routines always make QNaNs now, instead of sometimes making QNaNs and sometimes SNaNs depending on the type. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97364 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Support/APFloat.cpp')
-rw-r--r--lib/Support/APFloat.cpp47
1 files changed, 36 insertions, 11 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index f90973feab..4f1b85431c 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -626,17 +626,37 @@ APFloat::copySignificand(const APFloat &rhs)
/* Make this number a NaN, with an arbitrary but deterministic value
for the significand. If double or longer, this is a signalling NaN,
which may not be ideal. If float, this is QNaN(0). */
-void
-APFloat::makeNaN(unsigned type)
+void APFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill)
{
category = fcNaN;
- // FIXME: Add double and long double support for QNaN(0).
- if (semantics->precision == 24 && semantics->maxExponent == 127) {
- type |= 0x7fc00000U;
- type &= ~0x80000000U;
- } else
- type = ~0U;
- APInt::tcSet(significandParts(), type, partCount());
+ sign = Negative;
+
+ // Set the significand bits to the fill.
+ if (!fill || fill->getNumWords() < partCount())
+ APInt::tcSet(significandParts(), 0, partCount());
+ if (fill)
+ APInt::tcAssign(significandParts(), fill->getRawData(), partCount());
+
+ if (SNaN) {
+ // We always have to clear the QNaN bit to make it an SNaN.
+ APInt::tcClearBit(significandParts(), semantics->precision - 2);
+
+ // If there are no bits set in the payload, we have to set
+ // *something* to make it a NaN instead of an infinity;
+ // conventionally, this is the next bit down from the QNaN bit.
+ if (APInt::tcIsZero(significandParts(), partCount()))
+ APInt::tcSetBit(significandParts(), semantics->precision - 3);
+ } else {
+ // We always have to set the QNaN bit to make it a QNaN.
+ APInt::tcSetBit(significandParts(), semantics->precision - 2);
+ }
+}
+
+APFloat APFloat::makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative,
+ const APInt *fill) {
+ APFloat value(Sem, uninitialized);
+ value.makeNaN(SNaN, Negative, fill);
+ return value;
}
APFloat &
@@ -701,9 +721,14 @@ APFloat::APFloat(const fltSemantics &ourSemantics) {
sign = false;
}
+APFloat::APFloat(const fltSemantics &ourSemantics, uninitializedTag tag) {
+ assertArithmeticOK(ourSemantics);
+ // Allocates storage if necessary but does not initialize it.
+ initialize(&ourSemantics);
+}
APFloat::APFloat(const fltSemantics &ourSemantics,
- fltCategory ourCategory, bool negative, unsigned type)
+ fltCategory ourCategory, bool negative)
{
assertArithmeticOK(ourSemantics);
initialize(&ourSemantics);
@@ -712,7 +737,7 @@ APFloat::APFloat(const fltSemantics &ourSemantics,
if (category == fcNormal)
category = fcZero;
else if (ourCategory == fcNaN)
- makeNaN(type);
+ makeNaN();
}
APFloat::APFloat(const fltSemantics &ourSemantics, const StringRef& text)