diff options
author | John McCall <rjmccall@apple.com> | 2010-02-28 02:51:25 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-02-28 02:51:25 +0000 |
commit | e12b73816b50bbe2cc54b8005d86c95413b4f465 (patch) | |
tree | 167c037c24ea67c3d1d116f1ac9df701eb863a0e /lib/Support/APFloat.cpp | |
parent | 6281cda6737bcda0e924318ddcce28392001691e (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.cpp | 47 |
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) |