aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Support/APFloat.cpp178
1 files changed, 107 insertions, 71 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index 8cc916e..1e1c5ff 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -1733,7 +1733,8 @@ APFloat::convert(const fltSemantics &toSemantics,
/* Convert a floating point number to an integer according to the
rounding mode. If the rounded integer value is out of range this
- returns an invalid operation exception. If the rounded value is in
+ returns an invalid operation exception and the contents of the
+ destination parts are unspecified. If the rounded value is in
range but the floating point number is not the exact integer, the C
standard doesn't require an inexact exception to be raised. IEEE
854 does require it so we do that.
@@ -1741,95 +1742,131 @@ APFloat::convert(const fltSemantics &toSemantics,
Note that for conversions to integer type the C standard requires
round-to-zero to always be used. */
APFloat::opStatus
-APFloat::convertToInteger(integerPart *parts, unsigned int width,
- bool isSigned,
- roundingMode rounding_mode) const
+APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width,
+ bool isSigned,
+ roundingMode rounding_mode) const
{
lostFraction lost_fraction;
- unsigned int msb, partsCount;
- int bits;
+ const integerPart *src;
+ unsigned int dstPartsCount, truncatedBits;
- assertArithmeticOK(*semantics);
- partsCount = partCountForBits(width);
-
- /* Handle the three special cases first. We produce
- a deterministic result even for the Invalid cases. */
- if (category == fcNaN) {
- // Neither sign nor isSigned affects this.
- APInt::tcSet(parts, 0, partsCount);
+ /* Handle the three special cases first. */
+ if(category == fcInfinity || category == fcNaN)
return opInvalidOp;
- }
- if (category == fcInfinity) {
- if (!sign && isSigned)
- APInt::tcSetLeastSignificantBits(parts, partsCount, width-1);
- else if (!sign && !isSigned)
- APInt::tcSetLeastSignificantBits(parts, partsCount, width);
- else if (sign && isSigned) {
- APInt::tcSetLeastSignificantBits(parts, partsCount, 1);
- APInt::tcShiftLeft(parts, partsCount, width-1);
- } else // sign && !isSigned
- APInt::tcSet(parts, 0, partsCount);
- return opInvalidOp;
- }
- if (category == fcZero) {
- APInt::tcSet(parts, 0, partsCount);
+
+ dstPartsCount = partCountForBits(width);
+
+ if(category == fcZero) {
+ APInt::tcSet(parts, 0, dstPartsCount);
return opOK;
}
- /* Shift the bit pattern so the fraction is lost. */
- APFloat tmp(*this);
-
- bits = (int) semantics->precision - 1 - exponent;
+ src = significandParts();
- if(bits > 0) {
- lost_fraction = tmp.shiftSignificandRight(bits);
+ /* Step 1: place our absolute value, with any fraction truncated, in
+ the destination. */
+ if (exponent < 0) {
+ /* Our absolute value is less than one; truncate everything. */
+ APInt::tcSet(parts, 0, dstPartsCount);
+ truncatedBits = semantics->precision;
} else {
- if ((unsigned) -bits >= semantics->precision) {
- // Unrepresentably large.
- if (!sign && isSigned)
- APInt::tcSetLeastSignificantBits(parts, partsCount, width-1);
- else if (!sign && !isSigned)
- APInt::tcSetLeastSignificantBits(parts, partsCount, width);
- else if (sign && isSigned) {
- APInt::tcSetLeastSignificantBits(parts, partsCount, 1);
- APInt::tcShiftLeft(parts, partsCount, width-1);
- } else // sign && !isSigned
- APInt::tcSet(parts, 0, partsCount);
- return (opStatus)(opOverflow | opInexact);
+ /* We want the most significant (exponent + 1) bits; the rest are
+ truncated. */
+ unsigned int bits = exponent + 1U;
+
+ /* Hopelessly large in magnitude? */
+ if (bits > width)
+ return opInvalidOp;
+
+ if (bits < semantics->precision) {
+ /* We truncate (semantics->precision - bits) bits. */
+ truncatedBits = semantics->precision - bits;
+ APInt::tcExtract(parts, dstPartsCount, src, bits, truncatedBits);
+ } else {
+ /* We want at least as many bits as are available. */
+ APInt::tcExtract(parts, dstPartsCount, src, semantics->precision, 0);
+ APInt::tcShiftLeft(parts, dstPartsCount, bits - semantics->precision);
+ truncatedBits = 0;
+ }
+ }
+
+ /* Step 2: work out any lost fraction, and increment the absolute
+ value if we would round away from zero. */
+ if (truncatedBits) {
+ lost_fraction = lostFractionThroughTruncation(src, partCount(),
+ truncatedBits);
+ if (lost_fraction != lfExactlyZero
+ && roundAwayFromZero(rounding_mode, lost_fraction, truncatedBits)) {
+ if (APInt::tcIncrement(parts, dstPartsCount))
+ return opInvalidOp; /* Overflow. */
}
- tmp.shiftSignificandLeft(-bits);
+ } else {
lost_fraction = lfExactlyZero;
}
- if(lost_fraction != lfExactlyZero
- && tmp.roundAwayFromZero(rounding_mode, lost_fraction, 0))
- tmp.incrementSignificand();
+ /* Step 3: check if we fit in the destination. */
+ unsigned int omsb = APInt::tcMSB(parts, dstPartsCount) + 1;
- msb = tmp.significandMSB();
+ if (sign) {
+ if (!isSigned) {
+ /* Negative numbers cannot be represented as unsigned. */
+ if (omsb != 0)
+ return opInvalidOp;
+ } else {
+ /* It takes omsb bits to represent the unsigned integer value.
+ We lose a bit for the sign, but care is needed as the
+ maximally negative integer is a special case. */
+ if (omsb == width && APInt::tcLSB(parts, dstPartsCount) + 1 != omsb)
+ return opInvalidOp;
+
+ /* This case can happen because of rounding. */
+ if (omsb > width)
+ return opInvalidOp;
+ }
- /* Negative numbers cannot be represented as unsigned. */
- if(!isSigned && tmp.sign && msb != -1U)
- return opInvalidOp;
+ APInt::tcNegate (parts, dstPartsCount);
+ } else {
+ if (omsb >= width + !isSigned)
+ return opInvalidOp;
+ }
- /* It takes exponent + 1 bits to represent the truncated floating
- point number without its sign. We lose a bit for the sign, but
- the maximally negative integer is a special case. */
- if(msb + 1 > width) /* !! Not same as msb >= width !! */
- return opInvalidOp;
+ if (lost_fraction == lfExactlyZero)
+ return opOK;
+ else
+ return opInexact;
+}
- if(isSigned && msb + 1 == width
- && (!tmp.sign || tmp.significandLSB() != msb))
- return opInvalidOp;
+/* Same as convertToSignExtendedInteger, except we provide
+ deterministic values in case of an invalid operation exception,
+ namely zero for NaNs and the minimal or maximal value respectively
+ for underflow or overflow. */
+APFloat::opStatus
+APFloat::convertToInteger(integerPart *parts, unsigned int width,
+ bool isSigned,
+ roundingMode rounding_mode) const
+{
+ opStatus fs;
- APInt::tcAssign(parts, tmp.significandParts(), partsCount);
+ fs = convertToSignExtendedInteger(parts, width, isSigned, rounding_mode);
- if(tmp.sign)
- APInt::tcNegate(parts, partsCount);
+ if (fs == opInvalidOp) {
+ unsigned int bits, dstPartsCount;
- if(lost_fraction == lfExactlyZero)
- return opOK;
- else
- return opInexact;
+ dstPartsCount = partCountForBits(width);
+
+ if (category == fcNaN)
+ bits = 0;
+ else if (sign)
+ bits = isSigned;
+ else
+ bits = width - isSigned;
+
+ APInt::tcSetLeastSignificantBits(parts, dstPartsCount, bits);
+ if (sign && isSigned)
+ APInt::tcShiftLeft(parts, dstPartsCount, width - 1);
+ }
+
+ return fs;
}
/* Convert an unsigned integer SRC to a floating point number,
@@ -2162,7 +2199,6 @@ APFloat::convertFromDecimalString(const char *p, roundingMode rounding_mode)
partCount++;
} while (p <= D.lastSigDigit);
- category = fcNormal;
fs = roundSignificandWithExponent(decSignificand, partCount,
D.exponent, rounding_mode);