diff options
author | Dale Johannesen <dalej@apple.com> | 2007-09-25 17:25:00 +0000 |
---|---|---|
committer | Dale Johannesen <dalej@apple.com> | 2007-09-25 17:25:00 +0000 |
commit | 902ff94aff34acb2b11f4651f4a4006cb788301a (patch) | |
tree | 18f981dcd3b8deaea4728a4551c6fe8b7b8d2c8c /lib/Support/APFloat.cpp | |
parent | c3b0b5ca1d5772cf90c0c66e03412da33a0d7cdb (diff) |
Fix long double<->shorter FP type conversions
of zero, infinity, and NaNs.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42298 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Support/APFloat.cpp')
-rw-r--r-- | lib/Support/APFloat.cpp | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 2b9930cad6..b3705f5058 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -1329,26 +1329,30 @@ APFloat::convert(const fltSemantics &toSemantics, /* 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. */ + single part we need to free the old storage. + Be careful not to reference significandParts for zeroes + and infinities, since it aborts. */ if (newPartCount > oldPartCount) { integerPart *newParts; - newParts = new integerPart[newPartCount]; APInt::tcSet(newParts, 0, newPartCount); - APInt::tcAssign(newParts, significandParts(), oldPartCount); + if (category==fcNormal || category==fcNaN) + APInt::tcAssign(newParts, significandParts(), oldPartCount); freeSignificand(); significand.parts = newParts; } else if (newPartCount < oldPartCount) { /* Capture any lost fraction through truncation of parts so we get correct rounding whilst normalizing. */ - lostFraction = lostFractionThroughTruncation - (significandParts(), oldPartCount, toSemantics.precision); - if (newPartCount == 1) - { - integerPart newPart = significandParts()[0]; - freeSignificand(); - significand.part = newPart; - } + if (category==fcNormal) + lostFraction = lostFractionThroughTruncation + (significandParts(), oldPartCount, toSemantics.precision); + if (newPartCount == 1) { + integerPart newPart = 0; + if (category==fcNormal || category==fcNaN) + newPart = significandParts()[0]; + freeSignificand(); + significand.part = newPart; + } } if(category == fcNormal) { @@ -1356,6 +1360,19 @@ APFloat::convert(const fltSemantics &toSemantics, exponent += toSemantics.precision - semantics->precision; semantics = &toSemantics; fs = normalize(rounding_mode, lostFraction); + } else if (category == fcNaN) { + int shift = toSemantics.precision - semantics->precision; + // No normalization here, just truncate + if (shift>0) + APInt::tcShiftLeft(significandParts(), newPartCount, shift); + else if (shift < 0) + APInt::tcShiftRight(significandParts(), newPartCount, -shift); + // gcc forces the Quiet bit on, which means (float)(double)(float_sNan) + // does not give you back the same bits. This is dubious, and we + // don't currently do it. You're really supposed to get + // an invalid operation signal at runtime, but nobody does that. + semantics = &toSemantics; + fs = opOK; } else { semantics = &toSemantics; fs = opOK; @@ -1818,7 +1835,7 @@ APFloat::initFromFloatAPInt(const APInt & api) { } else if (myexponent==0xff && mysignificand==0) { // exponent, significand meaningless category = fcInfinity; - } else if (myexponent==0xff && (mysignificand & 0x400000)) { + } else if (myexponent==0xff && mysignificand!=0) { // sign, exponent, significand meaningless category = fcNaN; *significandParts() = mysignificand; |