Neil Booth wrote:-
> This patch supplies software IEEE floating point support.
Ahem.
-------------- next part --------------
Index: include/llvm/ADT/APInt.h
==================================================================---
include/llvm/ADT/APInt.h (revision 41166)
+++ include/llvm/ADT/APInt.h (working copy)
@@ -19,9 +19,7 @@
#include <cassert>
#include <string>
-#define HOST_CHAR_BIT 8
-#define compileTimeAssert(cond) extern int CTAssert[(cond) ? 1 : -1]
-#define integerPartWidth (HOST_CHAR_BIT * sizeof(llvm::integerPart))
+#define COMPILE_TIME_ASSERT(cond) extern int CTAssert[(cond) ? 1 : -1]
namespace llvm {
@@ -29,6 +27,9 @@
bignum. */
typedef uint64_t integerPart;
+ const unsigned int host_char_bit = 8;
+ const unsigned int integerPartWidth = host_char_bit * sizeof(integerPart);
+
//===----------------------------------------------------------------------===//
// APInt Class
//===----------------------------------------------------------------------===//
Index: include/llvm/ADT/APFloat.h
==================================================================---
include/llvm/ADT/APFloat.h (revision 0)
+++ include/llvm/ADT/APFloat.h (revision 0)
@@ -0,0 +1,258 @@
+//== llvm/Support/APFloat.h - Arbitrary Precision Floating Point -*- C++
-*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by Neil Booth and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares a class to represent arbitrary precision floating
+// point values and provide a variety of arithmetic operations on them.
+//
+//===----------------------------------------------------------------------===//
+
+/* A self-contained host- and target-independent arbitrary-precision
+ floating-point software implementation using bignum integer
+ arithmetic, as provided by static functions in the APInt class.
+ The library will work with bignum integers whose parts are any
+ unsigned type at least 16 bits wide. 64 bits is recommended.
+
+ Written for clarity rather than speed, in particular with a view
+ to use in the front-end of a cross compiler so that target
+ arithmetic can be correctly performed on the host. Performance
+ should nonetheless be reasonable, particularly for its intended
+ use. It may be useful as a base implementation for a run-time
+ library during development of a faster target-specific one.
+
+ All 5 rounding modes in the IEEE-754R draft are handled correctly
+ for all implemented operations. Currently implemented operations
+ are add, subtract, multiply, divide, fused-multiply-add,
+ conversion-to-float, conversion-to-integer and
+ conversion-from-integer. New rounding modes (e.g. away from zero)
+ can be added with three or four lines of code. The library reads
+ and correctly rounds hexadecimal floating point numbers as per
+ C99; syntax is required to have been validated by the caller.
+ Conversion from decimal is not currently implemented.
+
+ Four formats are built-in: IEEE single precision, double
+ precision, quadruple precision, and x87 80-bit extended double
+ (when operating with full extended precision). Adding a new
+ format that obeys IEEE semantics only requires adding two lines of
+ code: a declaration and definition of the format.
+
+ All operations return the status of that operation as an exception
+ bit-mask, so multiple operations can be done consecutively with
+ their results or-ed together. The returned status can be useful
+ for compiler diagnostics; e.g., inexact, underflow and overflow
+ can be easily diagnosed on constant folding, and compiler
+ optimizers can determine what exceptions would be raised by
+ folding operations and optimize, or perhaps not optimize,
+ accordingly.
+
+ At present, underflow tininess is detected after rounding; it
+ should be straight forward to add support for the before-rounding
+ case too.
+
+ Non-zero finite numbers are represented internally as a sign bit,
+ a 16-bit signed exponent, and the significand as an array of
+ integer parts. After normalization of a number of precision P the
+ exponent is within the range of the format, and if the number is
+ not denormal the P-th bit of the significand is set as an explicit
+ integer bit. For denormals the most significant bit is shifted
+ right so that the exponent is maintained at the format's minimum,
+ so that the smallest denormal has just the least significant bit
+ of the significand set. The sign of zeroes and infinities is
+ significant; the exponent and significand of such numbers is
+ indeterminate and meaningless. For QNaNs the sign bit, as well as
+ the exponent and significand are indeterminate and meaningless.
+
+ TODO
+ ===+
+ Some features that may or may not be worth adding:
+
+ Conversions to and from decimal strings (hard).
+
+ Conversions to hexadecimal string.
+
+ Read and write IEEE-format in-memory representations.
+
+ Optional ability to detect underflow tininess before rounding.
+
+ New formats: x87 in single and double precision mode (IEEE apart
+ from extended exponent range) and IBM two-double extended
+ precision (hard).
+
+ New operations: sqrt, copysign, nextafter, nexttoward.
+*/
+
+#ifndef LLVM_FLOAT_H
+#define LLVM_FLOAT_H
+
+// APInt contains static functions implementing bignum arithmetic.
+#include "llvm/ADT/APInt.h"
+
+namespace llvm {
+
+ /* Exponents are stored as signed numbers. */
+ typedef signed short exponent_t;
+
+ struct fltSemantics;
+
+ /* When bits of a floating point number are truncated, this enum is
+ used to indicate what fraction of the LSB those bits represented.
+ It essentially combines the roles of guard and sticky bits. */
+ enum lostFraction { // Example of truncated bits:
+ lfExactlyZero, // 000000
+ lfLessThanHalf, // 0xxxxx x's not all zero
+ lfExactlyHalf, // 100000
+ lfMoreThanHalf // 1xxxxx x's not all zero
+ };
+
+ class APFloat {
+ public:
+
+ /* We support the following floating point semantics. */
+ static const fltSemantics IEEEsingle;
+ static const fltSemantics IEEEdouble;
+ static const fltSemantics IEEEquad;
+ static const fltSemantics x87DoubleExtended;
+
+ static unsigned int semanticsPrecision(const fltSemantics &);
+
+ /* Floating point numbers have a four-state comparison relation. */
+ enum cmpResult {
+ cmpLessThan,
+ cmpEqual,
+ cmpGreaterThan,
+ cmpUnordered
+ };
+
+ /* IEEE-754R gives five rounding modes. */
+ enum roundingMode {
+ rmNearestTiesToEven,
+ rmTowardPositive,
+ rmTowardNegative,
+ rmTowardZero,
+ rmNearestTiesToAway
+ };
+
+ /* Operation status. opUnderflow or opOverflow are always returned
+ or-ed with opInexact. */
+ enum opStatus {
+ opOK = 0x00,
+ opInvalidOp = 0x01,
+ opDivByZero = 0x02,
+ opOverflow = 0x04,
+ opUnderflow = 0x08,
+ opInexact = 0x10
+ };
+
+ /* Category of internally-represented number. */
+ enum fltCategory {
+ fcInfinity,
+ fcQNaN,
+ fcNormal,
+ fcZero
+ };
+
+ /* Constructors. */
+ APFloat(const fltSemantics &, const char *);
+ APFloat(const fltSemantics &, integerPart);
+ APFloat(const fltSemantics &, fltCategory, bool negative);
+ APFloat(const APFloat &);
+ ~APFloat();
+
+ /* Arithmetic. */
+ opStatus add(const APFloat &, roundingMode);
+ opStatus subtract(const APFloat &, roundingMode);
+ opStatus multiply(const APFloat &, roundingMode);
+ opStatus divide(const APFloat &, roundingMode);
+ opStatus fusedMultiplyAdd(const APFloat &, const APFloat &,
roundingMode);
+ void changeSign();
+
+ /* Conversions. */
+ opStatus convert(const fltSemantics &, roundingMode);
+ opStatus convertToInteger(integerPart *, unsigned int, bool,
+ roundingMode) const;
+ opStatus convertFromInteger(const integerPart *, unsigned int, bool,
+ roundingMode);
+ opStatus convertFromString(const char *, roundingMode);
+
+ /* Comparison with another floating point number. */
+ cmpResult compare(const APFloat &) const;
+
+ /* Simple queries. */
+ fltCategory getCategory() const { return category; }
+ const fltSemantics &getSemantics() const { return *semantics; }
+ bool isZero() const { return category == fcZero; }
+ bool isNonZero() const { return category != fcZero; }
+ bool isNegative() const { return sign; }
+
+ APFloat& operator=(const APFloat &);
+
+ private:
+
+ /* Trivial queries. */
+ integerPart *significandParts();
+ const integerPart *significandParts() const;
+ unsigned int partCount() const;
+
+ /* Significand operations. */
+ integerPart addSignificand(const APFloat &);
+ integerPart subtractSignificand(const APFloat &, integerPart);
+ lostFraction addOrSubtractSignificand(const APFloat &, bool subtract);
+ lostFraction multiplySignificand(const APFloat &, const APFloat *);
+ lostFraction divideSignificand(const APFloat &);
+ void incrementSignificand();
+ void initialize(const fltSemantics *);
+ void shiftSignificandLeft(unsigned int);
+ lostFraction shiftSignificandRight(unsigned int);
+ unsigned int significandLSB() const;
+ unsigned int significandMSB() const;
+ void zeroSignificand();
+
+ /* Arithmetic on special values. */
+ opStatus addOrSubtractSpecials(const APFloat &, bool subtract);
+ opStatus divideSpecials(const APFloat &);
+ opStatus multiplySpecials(const APFloat &);
+
+ /* Miscellany. */
+ opStatus normalize(roundingMode, lostFraction);
+ opStatus addOrSubtract(const APFloat &, roundingMode, bool subtract);
+ cmpResult compareAbsoluteValue(const APFloat &) const;
+ opStatus handleOverflow(roundingMode);
+ bool roundAwayFromZero(roundingMode, lostFraction);
+ opStatus convertFromUnsignedInteger(integerPart *, unsigned int,
+ roundingMode);
+ lostFraction combineLostFractions(lostFraction, lostFraction);
+ opStatus convertFromHexadecimalString(const char *, roundingMode);
+
+ void assign(const APFloat &);
+ void copySignificand(const APFloat &);
+ void freeSignificand();
+
+ /* What kind of semantics does this value obey? */
+ const fltSemantics *semantics;
+
+ /* Significand - the fraction with an explicit integer bit. Must be
+ at least one bit wider than the target precision. */
+ union Significand
+ {
+ integerPart part;
+ integerPart *parts;
+ } significand;
+
+ /* The exponent - a signed number. */
+ exponent_t exponent;
+
+ /* What kind of floating point number this is. */
+ fltCategory category: 2;
+
+ /* The sign bit of this number. */
+ unsigned int sign: 1;
+ };
+} /* namespace llvm */
+
+#endif /* LLVM_FLOAT_H */
Index: lib/Support/APInt.cpp
==================================================================---
lib/Support/APInt.cpp (revision 41166)
+++ lib/Support/APInt.cpp (working copy)
@@ -2018,19 +2018,39 @@
/* Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe
and unrestricting assumption. */
-compileTimeAssert(integerPartWidth % 2 == 0);
+COMPILE_TIME_ASSERT(integerPartWidth % 2 == 0);
-#define lowBitMask(bits) (~(integerPart) 0 >> (integerPartWidth -
(bits)))
-#define lowHalf(part) ((part) & lowBitMask(integerPartWidth / 2))
-#define highHalf(part) ((part) >> (integerPartWidth / 2))
-
/* Some handy functions local to this file. */
namespace {
+ /* Returns the integer part with the least significant BITS set.
+ BITS cannot be zero. */
+ inline integerPart
+ lowBitMask(unsigned int bits)
+ {
+ assert (bits != 0 && bits <= integerPartWidth);
+
+ return ~(integerPart) 0 >> (integerPartWidth - bits);
+ }
+
+ /* Returns the value of the lower nibble of PART. */
+ inline integerPart
+ lowHalf(integerPart part)
+ {
+ return part & lowBitMask(integerPartWidth / 2);
+ }
+
+ /* Returns the value of the upper nibble of PART. */
+ inline integerPart
+ highHalf(integerPart part)
+ {
+ return part >> (integerPartWidth / 2);
+ }
+
/* Returns the bit number of the most significant bit of a part. If
the input number has no bits set -1U is returned. */
unsigned int
- PartMSB(integerPart value)
+ partMSB(integerPart value)
{
unsigned int n, msb;
@@ -2157,7 +2177,7 @@
--n;
if (parts[n] != 0) {
- msb = PartMSB(parts[n]);
+ msb = partMSB(parts[n]);
return msb + n * integerPartWidth;
}
@@ -2388,11 +2408,11 @@
assert(lhs != remainder && lhs != srhs && remainder != srhs);
- shiftCount = tcMSB(rhs, parts);
- if (shiftCount == -1U)
+ shiftCount = tcMSB(rhs, parts) + 1;
+ if (shiftCount == 0)
return true;
- shiftCount = parts * integerPartWidth - shiftCount - 1;
+ shiftCount = parts * integerPartWidth - shiftCount;
n = shiftCount / integerPartWidth;
mask = (integerPart) 1 << (shiftCount % integerPartWidth);
Index: lib/Support/APFloat.cpp
==================================================================---
lib/Support/APFloat.cpp (revision 0)
+++ lib/Support/APFloat.cpp (revision 0)
@@ -0,0 +1,1488 @@
+//===-- APFloat.cpp - Implement APFloat class
-----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by Neil Booth and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a class to represent arbitrary precision floating
+// point values and provide a variety of arithmetic operations on them.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cassert>
+#include "llvm/ADT/APFloat.h"
+
+using namespace llvm;
+
+#define convolve(lhs, rhs) ((lhs) * 4 + (rhs))
+
+/* Assumed in hexadecimal significand parsing. */
+COMPILE_TIME_ASSERT(integerPartWidth % 4 == 0);
+
+namespace llvm {
+
+ /* Represents floating point arithmetic semantics. */
+ struct fltSemantics {
+ /* The largest E such that 2^E is representable; this matches the
+ definition of IEEE 754. */
+ exponent_t maxExponent;
+
+ /* The smallest E such that 2^E is a normalized number; this
+ matches the definition of IEEE 754. */
+ exponent_t minExponent;
+
+ /* Number of bits in the significand. This includes the integer
+ bit. */
+ unsigned char precision;
+
+ /* If the target format has an implicit integer bit. */
+ bool implicitIntegerBit;
+ };
+
+ const fltSemantics APFloat::IEEEsingle = { 127, -126, 24, true };
+ const fltSemantics APFloat::IEEEdouble = { 1023, -1022, 53, true };
+ const fltSemantics APFloat::IEEEquad = { 16383, -16382, 113, true };
+ const fltSemantics APFloat::x87DoubleExtended = { 16383, -16382, 64, false };
+}
+
+/* Put a bunch of private, handy routines in an anonymous namespace. */
+namespace {
+
+ inline unsigned int
+ partCountForBits(unsigned int bits)
+ {
+ return ((bits) + integerPartWidth - 1) / integerPartWidth;
+ }
+
+ unsigned int
+ digitValue(unsigned int c)
+ {
+ unsigned int r;
+
+ r = c - '0';
+ if(r <= 9)
+ return r;
+
+ return -1U;
+ }
+
+ unsigned int
+ hexDigitValue (unsigned int c)
+ {
+ unsigned int r;
+
+ r = c - '0';
+ if(r <= 9)
+ return r;
+
+ r = c - 'A';
+ if(r <= 5)
+ return r + 10;
+
+ r = c - 'a';
+ if(r <= 5)
+ return r + 10;
+
+ return -1U;
+ }
+
+ /* This is ugly and needs cleaning up, but I don't immediately see
+ how whilst remaining safe. */
+ static int
+ totalExponent(const char *p, int exponentAdjustment)
+ {
+ integerPart unsignedExponent;
+ bool negative, overflow;
+ long exponent;
+
+ /* Move past the exponent letter and sign to the digits. */
+ p++;
+ negative = *p == '-';
+ if(*p == '-' || *p == '+')
+ p++;
+
+ unsignedExponent = 0;
+ overflow = false;
+ for(;;) {
+ unsigned int value;
+
+ value = digitValue(*p);
+ if(value == -1U)
+ break;
+
+ p++;
+ unsignedExponent = unsignedExponent * 10 + value;
+ if(unsignedExponent > 65535)
+ overflow = true;
+ }
+
+ if(exponentAdjustment > 65535 || exponentAdjustment < -65536)
+ overflow = true;
+
+ if(!overflow) {
+ exponent = unsignedExponent;
+ if(negative)
+ exponent = -exponent;
+ exponent += exponentAdjustment;
+ if(exponent > 65535 || exponent < -65536)
+ overflow = true;
+ }
+
+ if(overflow)
+ exponent = negative ? -65536: 65535;
+
+ return exponent;
+ }
+
+ const char *
+ skipLeadingZeroesAndAnyDot(const char *p, const char **dot)
+ {
+ *dot = 0;
+ while(*p == '0')
+ p++;
+
+ if(*p == '.') {
+ *dot = p++;
+ while(*p == '0')
+ p++;
+ }
+
+ return p;
+ }
+
+ /* Return the trailing fraction of a hexadecimal number.
+ DIGITVALUE is the first hex digit of the fraction, P points to
+ the next digit. */
+ lostFraction
+ trailingHexadecimalFraction(const char *p, unsigned int digitValue)
+ {
+ unsigned int hexDigit;
+
+ /* If the first trailing digit isn't 0 or 8 we can work out the
+ fraction immediately. */
+ if(digitValue > 8)
+ return lfMoreThanHalf;
+ else if(digitValue < 8 && digitValue > 0)
+ return lfLessThanHalf;
+
+ /* Otherwise we need to find the first non-zero digit. */
+ while(*p == '0')
+ p++;
+
+ hexDigit = hexDigitValue(*p);
+
+ /* If we ran off the end it is exactly zero or one-half, otherwise
+ a little more. */
+ if(hexDigit == -1U)
+ return digitValue == 0 ? lfExactlyZero: lfExactlyHalf;
+ else
+ return digitValue == 0 ? lfLessThanHalf: lfMoreThanHalf;
+ }
+
+ /* Return the fraction lost were a bignum truncated. */
+ lostFraction
+ lostFractionThroughTruncation(integerPart *parts,
+ unsigned int partCount,
+ unsigned int bits)
+ {
+ unsigned int lsb;
+
+ lsb = APInt::tcLSB(parts, partCount);
+
+ /* Note this is guaranteed true if bits == 0, or LSB == -1U. */
+ if(bits <= lsb)
+ return lfExactlyZero;
+ if(bits == lsb + 1)
+ return lfExactlyHalf;
+ if(bits <= partCount * integerPartWidth
+ && APInt::tcExtractBit(parts, bits - 1))
+ return lfMoreThanHalf;
+
+ return lfLessThanHalf;
+ }
+
+ /* Shift DST right BITS bits noting lost fraction. */
+ lostFraction
+ shiftRight(integerPart *dst, unsigned int parts, unsigned int bits)
+ {
+ lostFraction lost_fraction;
+
+ lost_fraction = lostFractionThroughTruncation(dst, parts, bits);
+
+ APInt::tcShiftRight(dst, parts, bits);
+
+ return lost_fraction;
+ }
+}
+
+/* Constructors. */
+void
+APFloat::initialize(const fltSemantics *ourSemantics)
+{
+ unsigned int count;
+
+ semantics = ourSemantics;
+ count = partCount();
+ if(count > 1)
+ significand.parts = new integerPart[count];
+}
+
+void
+APFloat::freeSignificand()
+{
+ if(partCount() > 1)
+ delete [] significand.parts;
+}
+
+void
+APFloat::assign(const APFloat &rhs)
+{
+ assert(semantics == rhs.semantics);
+
+ sign = rhs.sign;
+ category = rhs.category;
+ exponent = rhs.exponent;
+ if(category == fcNormal)
+ copySignificand(rhs);
+}
+
+void
+APFloat::copySignificand(const APFloat &rhs)
+{
+ assert(category == fcNormal);
+ assert(rhs.partCount() >= partCount());
+
+ APInt::tcAssign(significandParts(), rhs.significandParts(),
+ partCount());
+}
+
+APFloat &
+APFloat::operator=(const APFloat &rhs)
+{
+ if(this != &rhs) {
+ if(semantics != rhs.semantics) {
+ freeSignificand();
+ initialize(rhs.semantics);
+ }
+ assign(rhs);
+ }
+
+ return *this;
+}
+
+APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value)
+{
+ initialize(&ourSemantics);
+ sign = 0;
+ zeroSignificand();
+ exponent = ourSemantics.precision - 1;
+ significandParts()[0] = value;
+ normalize(rmNearestTiesToEven, lfExactlyZero);
+}
+
+APFloat::APFloat(const fltSemantics &ourSemantics,
+ fltCategory ourCategory, bool negative)
+{
+ initialize(&ourSemantics);
+ category = ourCategory;
+ sign = negative;
+ if(category == fcNormal)
+ category = fcZero;
+}
+
+APFloat::APFloat(const fltSemantics &ourSemantics, const char *text)
+{
+ initialize(&ourSemantics);
+ convertFromString(text, rmNearestTiesToEven);
+}
+
+APFloat::APFloat(const APFloat &rhs)
+{
+ initialize(rhs.semantics);
+ assign(rhs);
+}
+
+APFloat::~APFloat()
+{
+ freeSignificand();
+}
+
+unsigned int
+APFloat::partCount() const
+{
+ return partCountForBits(semantics->precision + 1);
+}
+
+unsigned int
+APFloat::semanticsPrecision(const fltSemantics &semantics)
+{
+ return semantics.precision;
+}
+
+const integerPart *
+APFloat::significandParts() const
+{
+ return const_cast<APFloat *>(this)->significandParts();
+}
+
+integerPart *
+APFloat::significandParts()
+{
+ assert(category == fcNormal);
+
+ if(partCount() > 1)
+ return significand.parts;
+ else
+ return &significand.part;
+}
+
+/* Combine the effect of two lost fractions. */
+lostFraction
+APFloat::combineLostFractions(lostFraction moreSignificant,
+ lostFraction lessSignificant)
+{
+ if(lessSignificant != lfExactlyZero) {
+ if(moreSignificant == lfExactlyZero)
+ moreSignificant = lfLessThanHalf;
+ else if(moreSignificant == lfExactlyHalf)
+ moreSignificant = lfMoreThanHalf;
+ }
+
+ return moreSignificant;
+}
+
+void
+APFloat::zeroSignificand()
+{
+ category = fcNormal;
+ APInt::tcSet(significandParts(), 0, partCount());
+}
+
+/* Increment an fcNormal floating point number's significand. */
+void
+APFloat::incrementSignificand()
+{
+ integerPart carry;
+
+ carry = APInt::tcIncrement(significandParts(), partCount());
+
+ /* Our callers should never cause us to overflow. */
+ assert(carry == 0);
+}
+
+/* Add the significand of the RHS. Returns the carry flag. */
+integerPart
+APFloat::addSignificand(const APFloat &rhs)
+{
+ integerPart *parts;
+
+ parts = significandParts();
+
+ assert(semantics == rhs.semantics);
+ assert(exponent == rhs.exponent);
+
+ return APInt::tcAdd(parts, rhs.significandParts(), 0, partCount());
+}
+
+/* Subtract the significand of the RHS with a borrow flag. Returns
+ the borrow flag. */
+integerPart
+APFloat::subtractSignificand(const APFloat &rhs, integerPart borrow)
+{
+ integerPart *parts;
+
+ parts = significandParts();
+
+ assert(semantics == rhs.semantics);
+ assert(exponent == rhs.exponent);
+
+ return APInt::tcSubtract(parts, rhs.significandParts(), borrow,
+ partCount());
+}
+
+/* Multiply the significand of the RHS. If ADDEND is non-NULL, add it
+ on to the full-precision result of the multiplication. Returns the
+ lost fraction. */
+lostFraction
+APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend)
+{
+ unsigned int omsb; // One, not zero, based MSB.
+ unsigned int partsCount, newPartsCount, precision;
+ integerPart *lhsSignificand;
+ integerPart scratch[4];
+ integerPart *fullSignificand;
+ lostFraction lost_fraction;
+
+ assert(semantics == rhs.semantics);
+
+ precision = semantics->precision;
+ newPartsCount = partCountForBits(precision * 2);
+
+ if(newPartsCount > 4)
+ fullSignificand = new integerPart[newPartsCount];
+ else
+ fullSignificand = scratch;
+
+ lhsSignificand = significandParts();
+ partsCount = partCount();
+
+ APInt::tcFullMultiply(fullSignificand, lhsSignificand,
+ rhs.significandParts(), partsCount);
+
+ lost_fraction = lfExactlyZero;
+ omsb = APInt::tcMSB(fullSignificand, newPartsCount) + 1;
+ exponent += rhs.exponent;
+
+ if(addend) {
+ Significand savedSignificand = significand;
+ const fltSemantics *savedSemantics = semantics;
+ fltSemantics extendedSemantics;
+ opStatus status;
+ unsigned int extendedPrecision;
+
+ /* Normalize our MSB. */
+ extendedPrecision = precision + precision - 1;
+ if(omsb != extendedPrecision)
+ {
+ APInt::tcShiftLeft(fullSignificand, newPartsCount,
+ extendedPrecision - omsb);
+ exponent -= extendedPrecision - omsb;
+ }
+
+ /* Create new semantics. */
+ extendedSemantics = *semantics;
+ extendedSemantics.precision = extendedPrecision;
+
+ if(newPartsCount == 1)
+ significand.part = fullSignificand[0];
+ else
+ significand.parts = fullSignificand;
+ semantics = &extendedSemantics;
+
+ APFloat extendedAddend(*addend);
+ status = extendedAddend.convert(extendedSemantics, rmTowardZero);
+ assert(status == opOK);
+ lost_fraction = addOrSubtractSignificand(extendedAddend, false);
+
+ /* Restore our state. */
+ if(newPartsCount == 1)
+ fullSignificand[0] = significand.part;
+ significand = savedSignificand;
+ semantics = savedSemantics;
+
+ omsb = APInt::tcMSB(fullSignificand, newPartsCount) + 1;
+ }
+
+ exponent -= (precision - 1);
+
+ if(omsb > precision) {
+ unsigned int bits, significantParts;
+ lostFraction lf;
+
+ bits = omsb - precision;
+ significantParts = partCountForBits(omsb);
+ lf = shiftRight(fullSignificand, significantParts, bits);
+ lost_fraction = combineLostFractions(lf, lost_fraction);
+ exponent += bits;
+ }
+
+ APInt::tcAssign(lhsSignificand, fullSignificand, partsCount);
+
+ if(newPartsCount > 4)
+ delete [] fullSignificand;
+
+ return lost_fraction;
+}
+
+/* Multiply the significands of LHS and RHS to DST. */
+lostFraction
+APFloat::divideSignificand(const APFloat &rhs)
+{
+ unsigned int bit, i, partsCount;
+ const integerPart *rhsSignificand;
+ integerPart *lhsSignificand, *dividend, *divisor;
+ integerPart scratch[4];
+ lostFraction lost_fraction;
+
+ assert(semantics == rhs.semantics);
+
+ lhsSignificand = significandParts();
+ rhsSignificand = rhs.significandParts();
+ partsCount = partCount();
+
+ if(partsCount > 2)
+ dividend = new integerPart[partsCount * 2];
+ else
+ dividend = scratch;
+
+ divisor = dividend + partsCount;
+
+ /* Copy the dividend and divisor as they will be modified in-place. */
+ for(i = 0; i < partsCount; i++) {
+ dividend[i] = lhsSignificand[i];
+ divisor[i] = rhsSignificand[i];
+ lhsSignificand[i] = 0;
+ }
+
+ exponent -= rhs.exponent;
+
+ unsigned int precision = semantics->precision;
+
+ /* Normalize the divisor. */
+ bit = precision - APInt::tcMSB(divisor, partsCount) - 1;
+ if(bit) {
+ exponent += bit;
+ APInt::tcShiftLeft(divisor, partsCount, bit);
+ }
+
+ /* Normalize the dividend. */
+ bit = precision - APInt::tcMSB(dividend, partsCount) - 1;
+ if(bit) {
+ exponent -= bit;
+ APInt::tcShiftLeft(dividend, partsCount, bit);
+ }
+
+ if(APInt::tcCompare(dividend, divisor, partsCount) < 0) {
+ exponent--;
+ APInt::tcShiftLeft(dividend, partsCount, 1);
+ assert(APInt::tcCompare(dividend, divisor, partsCount) >= 0);
+ }
+
+ /* Long division. */
+ for(bit = precision; bit; bit -= 1) {
+ if(APInt::tcCompare(dividend, divisor, partsCount) >= 0) {
+ APInt::tcSubtract(dividend, divisor, 0, partsCount);
+ APInt::tcSetBit(lhsSignificand, bit - 1);
+ }
+
+ APInt::tcShiftLeft(dividend, partsCount, 1);
+ }
+
+ /* Figure out the lost fraction. */
+ int cmp = APInt::tcCompare(dividend, divisor, partsCount);
+
+ if(cmp > 0)
+ lost_fraction = lfMoreThanHalf;
+ else if(cmp == 0)
+ lost_fraction = lfExactlyHalf;
+ else if(APInt::tcIsZero(dividend, partsCount))
+ lost_fraction = lfExactlyZero;
+ else
+ lost_fraction = lfLessThanHalf;
+
+ if(partsCount > 2)
+ delete [] dividend;
+
+ return lost_fraction;
+}
+
+unsigned int
+APFloat::significandMSB() const
+{
+ return APInt::tcMSB(significandParts(), partCount());
+}
+
+unsigned int
+APFloat::significandLSB() const
+{
+ return APInt::tcLSB(significandParts(), partCount());
+}
+
+/* Note that a zero result is NOT normalized to fcZero. */
+lostFraction
+APFloat::shiftSignificandRight(unsigned int bits)
+{
+ /* Our exponent should not overflow. */
+ assert((exponent_t) (exponent + bits) >= exponent);
+
+ exponent += bits;
+
+ return shiftRight(significandParts(), partCount(), bits);
+}
+
+/* Shift the significand left BITS bits, subtract BITS from its exponent. */
+void
+APFloat::shiftSignificandLeft(unsigned int bits)
+{
+ assert(bits < semantics->precision);
+
+ if(bits) {
+ unsigned int partsCount = partCount();
+
+ APInt::tcShiftLeft(significandParts(), partsCount, bits);
+ exponent -= bits;
+
+ assert(!APInt::tcIsZero(significandParts(), partsCount));
+ }
+}
+
+APFloat::cmpResult
+APFloat::compareAbsoluteValue(const APFloat &rhs) const
+{
+ int compare;
+
+ assert(semantics == rhs.semantics);
+ assert(category == fcNormal);
+ assert(rhs.category == fcNormal);
+
+ compare = exponent - rhs.exponent;
+
+ /* If exponents are equal, do an unsigned bignum comparison of the
+ significands. */
+ if(compare == 0)
+ compare = APInt::tcCompare(significandParts(), rhs.significandParts(),
+ partCount());
+
+ if(compare > 0)
+ return cmpGreaterThan;
+ else if(compare < 0)
+ return cmpLessThan;
+ else
+ return cmpEqual;
+}
+
+/* Handle overflow. Sign is preserved. We either become infinity or
+ the largest finite number. */
+APFloat::opStatus
+APFloat::handleOverflow(roundingMode rounding_mode)
+{
+ /* Infinity? */
+ if(rounding_mode == rmNearestTiesToEven
+ || rounding_mode == rmNearestTiesToAway
+ || (rounding_mode == rmTowardPositive && !sign)
+ || (rounding_mode == rmTowardNegative && sign))
+ {
+ category = fcInfinity;
+ return (opStatus) (opOverflow | opInexact);
+ }
+
+ /* Otherwise we become the largest finite number. */
+ category = fcNormal;
+ exponent = semantics->maxExponent;
+ APInt::tcSetLeastSignificantBits(significandParts(), partCount(),
+ semantics->precision);
+
+ return opInexact;
+}
+
+/* This routine must work for fcZero of both signs, and fcNormal
+ numbers. */
+bool
+APFloat::roundAwayFromZero(roundingMode rounding_mode,
+ lostFraction lost_fraction)
+{
+ /* QNaNs and infinities should not have lost fractions. */
+ assert(category == fcNormal || category == fcZero);
+
+ /* Our caller has already handled this case. */
+ assert(lost_fraction != lfExactlyZero);
+
+ switch(rounding_mode) {
+ default:
+ assert(0);
+
+ case rmNearestTiesToAway:
+ return lost_fraction == lfExactlyHalf || lost_fraction == lfMoreThanHalf;
+
+ case rmNearestTiesToEven:
+ if(lost_fraction == lfMoreThanHalf)
+ return true;
+
+ /* Our zeroes don't have a significand to test. */
+ if(lost_fraction == lfExactlyHalf && category != fcZero)
+ return significandParts()[0] & 1;
+
+ return false;
+
+ case rmTowardZero:
+ return false;
+
+ case rmTowardPositive:
+ return sign == false;
+
+ case rmTowardNegative:
+ return sign == true;
+ }
+}
+
+APFloat::opStatus
+APFloat::normalize(roundingMode rounding_mode,
+ lostFraction lost_fraction)
+{
+ unsigned int omsb; /* One, not zero, based MSB. */
+ int exponentChange;
+
+ if(category != fcNormal)
+ return opOK;
+
+ /* Before rounding normalize the exponent of fcNormal numbers. */
+ omsb = significandMSB() + 1;
+
+ if(omsb) {
+ /* OMSB is numbered from 1. We want to place it in the integer
+ bit numbered PRECISON if possible, with a compensating change in
+ the exponent. */
+ exponentChange = omsb - semantics->precision;
+
+ /* If the resulting exponent is too high, overflow according to
+ the rounding mode. */
+ if(exponent + exponentChange > semantics->maxExponent)
+ return handleOverflow(rounding_mode);
+
+ /* Subnormal numbers have exponent minExponent, and their MSB
+ is forced based on that. */
+ if(exponent + exponentChange < semantics->minExponent)
+ exponentChange = semantics->minExponent - exponent;
+
+ /* Shifting left is easy as we don't lose precision. */
+ if(exponentChange < 0) {
+ assert(lost_fraction == lfExactlyZero);
+
+ shiftSignificandLeft(-exponentChange);
+
+ return opOK;
+ }
+
+ if(exponentChange > 0) {
+ lostFraction lf;
+
+ /* Shift right and capture any new lost fraction. */
+ lf = shiftSignificandRight(exponentChange);
+
+ lost_fraction = combineLostFractions(lf, lost_fraction);
+
+ /* Keep OMSB up-to-date. */
+ if(omsb > (unsigned) exponentChange)
+ omsb -= (unsigned) exponentChange;
+ else
+ omsb = 0;
+ }
+ }
+
+ /* Now round the number according to rounding_mode given the lost
+ fraction. */
+
+ /* As specified in IEEE 754, since we do not trap we do not report
+ underflow for exact results. */
+ if(lost_fraction == lfExactlyZero) {
+ /* Canonicalize zeroes. */
+ if(omsb == 0)
+ category = fcZero;
+
+ return opOK;
+ }
+
+ /* Increment the significand if we're rounding away from zero. */
+ if(roundAwayFromZero(rounding_mode, lost_fraction)) {
+ if(omsb == 0)
+ exponent = semantics->minExponent;
+
+ incrementSignificand();
+ omsb = significandMSB() + 1;
+
+ /* Did the significand increment overflow? */
+ if(omsb == (unsigned) semantics->precision + 1) {
+ /* Renormalize by incrementing the exponent and shifting our
+ significand right one. However if we already have the
+ maximum exponent we overflow to infinity. */
+ if(exponent == semantics->maxExponent) {
+ category = fcInfinity;
+
+ return (opStatus) (opOverflow | opInexact);
+ }
+
+ shiftSignificandRight(1);
+
+ return opInexact;
+ }
+ }
+
+ /* The normal case - we were and are not denormal, and any
+ significand increment above didn't overflow. */
+ if(omsb == semantics->precision)
+ return opInexact;
+
+ /* We have a non-zero denormal. */
+ assert(omsb < semantics->precision);
+ assert(exponent == semantics->minExponent);
+
+ /* Canonicalize zeroes. */
+ if(omsb == 0)
+ category = fcZero;
+
+ /* The fcZero case is a denormal that underflowed to zero. */
+ return (opStatus) (opUnderflow | opInexact);
+}
+
+APFloat::opStatus
+APFloat::addOrSubtractSpecials(const APFloat &rhs, bool subtract)
+{
+ switch(convolve(category, rhs.category)) {
+ default:
+ assert(0);
+
+ case convolve(fcQNaN, fcZero):
+ case convolve(fcQNaN, fcNormal):
+ case convolve(fcQNaN, fcInfinity):
+ case convolve(fcQNaN, fcQNaN):
+ case convolve(fcNormal, fcZero):
+ case convolve(fcInfinity, fcNormal):
+ case convolve(fcInfinity, fcZero):
+ return opOK;
+
+ case convolve(fcZero, fcQNaN):
+ case convolve(fcNormal, fcQNaN):
+ case convolve(fcInfinity, fcQNaN):
+ category = fcQNaN;
+ return opOK;
+
+ case convolve(fcNormal, fcInfinity):
+ case convolve(fcZero, fcInfinity):
+ category = fcInfinity;
+ sign = rhs.sign ^ subtract;
+ return opOK;
+
+ case convolve(fcZero, fcNormal):
+ assign(rhs);
+ sign = rhs.sign ^ subtract;
+ return opOK;
+
+ case convolve(fcZero, fcZero):
+ /* Sign depends on rounding mode; handled by caller. */
+ return opOK;
+
+ case convolve(fcInfinity, fcInfinity):
+ /* Differently signed infinities can only be validly
+ subtracted. */
+ if(sign ^ rhs.sign != subtract) {
+ category = fcQNaN;
+ return opInvalidOp;
+ }
+
+ return opOK;
+
+ case convolve(fcNormal, fcNormal):
+ return opDivByZero;
+ }
+}
+
+/* Add or subtract two normal numbers. */
+lostFraction
+APFloat::addOrSubtractSignificand(const APFloat &rhs, bool subtract)
+{
+ integerPart carry;
+ lostFraction lost_fraction;
+ int bits;
+
+ /* Determine if the operation on the absolute values is effectively
+ an addition or subtraction. */
+ subtract ^= (sign ^ rhs.sign);
+
+ /* Are we bigger exponent-wise than the RHS? */
+ bits = exponent - rhs.exponent;
+
+ /* Subtraction is more subtle than one might naively expect. */
+ if(subtract) {
+ APFloat temp_rhs(rhs);
+ bool reverse;
+
+ if(bits == 0) {
+ reverse = compareAbsoluteValue(temp_rhs) == cmpLessThan;
+ lost_fraction = lfExactlyZero;
+ } else if(bits > 0) {
+ lost_fraction = temp_rhs.shiftSignificandRight(bits - 1);
+ shiftSignificandLeft(1);
+ reverse = false;
+ } else if(bits < 0) {
+ lost_fraction = shiftSignificandRight(-bits - 1);
+ temp_rhs.shiftSignificandLeft(1);
+ reverse = true;
+ }
+
+ if(reverse) {
+ carry = temp_rhs.subtractSignificand
+ (*this, lost_fraction != lfExactlyZero);
+ copySignificand(temp_rhs);
+ sign = !sign;
+ } else {
+ carry = subtractSignificand
+ (temp_rhs, lost_fraction != lfExactlyZero);
+ }
+
+ /* Invert the lost fraction - it was on the RHS and
+ subtracted. */
+ if(lost_fraction == lfLessThanHalf)
+ lost_fraction = lfMoreThanHalf;
+ else if(lost_fraction == lfMoreThanHalf)
+ lost_fraction = lfLessThanHalf;
+
+ /* The code above is intended to ensure that no borrow is
+ necessary. */
+ assert(!carry);
+ } else {
+ if(bits > 0) {
+ APFloat temp_rhs(rhs);
+
+ lost_fraction = temp_rhs.shiftSignificandRight(bits);
+ carry = addSignificand(temp_rhs);
+ } else {
+ lost_fraction = shiftSignificandRight(-bits);
+ carry = addSignificand(rhs);
+ }
+
+ /* We have a guard bit; generating a carry cannot happen. */
+ assert(!carry);
+ }
+
+ return lost_fraction;
+}
+
+APFloat::opStatus
+APFloat::multiplySpecials(const APFloat &rhs)
+{
+ switch(convolve(category, rhs.category)) {
+ default:
+ assert(0);
+
+ case convolve(fcQNaN, fcZero):
+ case convolve(fcQNaN, fcNormal):
+ case convolve(fcQNaN, fcInfinity):
+ case convolve(fcQNaN, fcQNaN):
+ case convolve(fcZero, fcQNaN):
+ case convolve(fcNormal, fcQNaN):
+ case convolve(fcInfinity, fcQNaN):
+ category = fcQNaN;
+ return opOK;
+
+ case convolve(fcNormal, fcInfinity):
+ case convolve(fcInfinity, fcNormal):
+ case convolve(fcInfinity, fcInfinity):
+ category = fcInfinity;
+ return opOK;
+
+ case convolve(fcZero, fcNormal):
+ case convolve(fcNormal, fcZero):
+ case convolve(fcZero, fcZero):
+ category = fcZero;
+ return opOK;
+
+ case convolve(fcZero, fcInfinity):
+ case convolve(fcInfinity, fcZero):
+ category = fcQNaN;
+ return opInvalidOp;
+
+ case convolve(fcNormal, fcNormal):
+ return opOK;
+ }
+}
+
+APFloat::opStatus
+APFloat::divideSpecials(const APFloat &rhs)
+{
+ switch(convolve(category, rhs.category)) {
+ default:
+ assert(0);
+
+ case convolve(fcQNaN, fcZero):
+ case convolve(fcQNaN, fcNormal):
+ case convolve(fcQNaN, fcInfinity):
+ case convolve(fcQNaN, fcQNaN):
+ case convolve(fcInfinity, fcZero):
+ case convolve(fcInfinity, fcNormal):
+ case convolve(fcZero, fcInfinity):
+ case convolve(fcZero, fcNormal):
+ return opOK;
+
+ case convolve(fcZero, fcQNaN):
+ case convolve(fcNormal, fcQNaN):
+ case convolve(fcInfinity, fcQNaN):
+ category = fcQNaN;
+ return opOK;
+
+ case convolve(fcNormal, fcInfinity):
+ category = fcZero;
+ return opOK;
+
+ case convolve(fcNormal, fcZero):
+ category = fcInfinity;
+ return opDivByZero;
+
+ case convolve(fcInfinity, fcInfinity):
+ case convolve(fcZero, fcZero):
+ category = fcQNaN;
+ return opInvalidOp;
+
+ case convolve(fcNormal, fcNormal):
+ return opOK;
+ }
+}
+
+/* Change sign. */
+void
+APFloat::changeSign()
+{
+ /* Look mummy, this one's easy. */
+ sign = !sign;
+}
+
+/* Normalized addition or subtraction. */
+APFloat::opStatus
+APFloat::addOrSubtract(const APFloat &rhs, roundingMode rounding_mode,
+ bool subtract)
+{
+ opStatus fs;
+
+ fs = addOrSubtractSpecials(rhs, subtract);
+
+ /* This return code means it was not a simple case. */
+ if(fs == opDivByZero) {
+ lostFraction lost_fraction;
+
+ lost_fraction = addOrSubtractSignificand(rhs, subtract);
+ fs = normalize(rounding_mode, lost_fraction);
+
+ /* Can only be zero if we lost no fraction. */
+ assert(category != fcZero || lost_fraction == lfExactlyZero);
+ }
+
+ /* If two numbers add (exactly) to zero, IEEE 754 decrees it is a
+ positive zero unless rounding to minus infinity, except that
+ adding two like-signed zeroes gives that zero. */
+ if(category == fcZero) {
+ if(rhs.category != fcZero || (sign == rhs.sign) == subtract)
+ sign = (rounding_mode == rmTowardNegative);
+ }
+
+ return fs;
+}
+
+/* Normalized addition. */
+APFloat::opStatus
+APFloat::add(const APFloat &rhs, roundingMode rounding_mode)
+{
+ return addOrSubtract(rhs, rounding_mode, false);
+}
+
+/* Normalized subtraction. */
+APFloat::opStatus
+APFloat::subtract(const APFloat &rhs, roundingMode rounding_mode)
+{
+ return addOrSubtract(rhs, rounding_mode, true);
+}
+
+/* Normalized multiply. */
+APFloat::opStatus
+APFloat::multiply(const APFloat &rhs, roundingMode rounding_mode)
+{
+ opStatus fs;
+
+ sign ^= rhs.sign;
+ fs = multiplySpecials(rhs);
+
+ if(category == fcNormal) {
+ lostFraction lost_fraction = multiplySignificand(rhs, 0);
+ fs = normalize(rounding_mode, lost_fraction);
+ if(lost_fraction != lfExactlyZero)
+ fs = (opStatus) (fs | opInexact);
+ }
+
+ return fs;
+}
+
+/* Normalized divide. */
+APFloat::opStatus
+APFloat::divide(const APFloat &rhs, roundingMode rounding_mode)
+{
+ opStatus fs;
+
+ sign ^= rhs.sign;
+ fs = divideSpecials(rhs);
+
+ if(category == fcNormal) {
+ lostFraction lost_fraction = divideSignificand(rhs);
+ fs = normalize(rounding_mode, lost_fraction);
+ if(lost_fraction != lfExactlyZero)
+ fs = (opStatus) (fs | opInexact);
+ }
+
+ return fs;
+}
+
+/* Normalized fused-multiply-add. */
+APFloat::opStatus
+APFloat::fusedMultiplyAdd(const APFloat &multiplicand,
+ const APFloat &addend,
+ roundingMode rounding_mode)
+{
+ opStatus fs;
+
+ /* Post-multiplication sign, before addition. */
+ sign ^= multiplicand.sign;
+
+ /* If and only if all arguments are normal do we need to do an
+ extended-precision calculation. */
+ if(category == fcNormal
+ && multiplicand.category == fcNormal
+ && addend.category == fcNormal) {
+ lostFraction lost_fraction;
+
+ lost_fraction = multiplySignificand(multiplicand, &addend);
+ fs = normalize(rounding_mode, lost_fraction);
+ if(lost_fraction != lfExactlyZero)
+ fs = (opStatus) (fs | opInexact);
+
+ /* If two numbers add (exactly) to zero, IEEE 754 decrees it is a
+ positive zero unless rounding to minus infinity, except that
+ adding two like-signed zeroes gives that zero. */
+ if(category == fcZero && sign != addend.sign)
+ sign = (rounding_mode == rmTowardNegative);
+ } else {
+ fs = multiplySpecials(multiplicand);
+
+ /* FS can only be opOK or opInvalidOp. There is no more work
+ to do in the latter case. The IEEE-754R standard says it is
+ implementation-defined in this case whether, if ADDEND is a
+ quiet QNaN, we raise invalid op; this implementation does so.
+
+ If we need to do the addition we can do so with normal
+ precision. */
+ if(fs == opOK)
+ fs = addOrSubtract(addend, rounding_mode, false);
+ }
+
+ return fs;
+}
+
+/* Comparison requires normalized numbers. */
+APFloat::cmpResult
+APFloat::compare(const APFloat &rhs) const
+{
+ cmpResult result;
+
+ assert(semantics == rhs.semantics);
+
+ switch(convolve(category, rhs.category)) {
+ default:
+ assert(0);
+
+ case convolve(fcQNaN, fcZero):
+ case convolve(fcQNaN, fcNormal):
+ case convolve(fcQNaN, fcInfinity):
+ case convolve(fcQNaN, fcQNaN):
+ case convolve(fcZero, fcQNaN):
+ case convolve(fcNormal, fcQNaN):
+ case convolve(fcInfinity, fcQNaN):
+ return cmpUnordered;
+
+ case convolve(fcInfinity, fcNormal):
+ case convolve(fcInfinity, fcZero):
+ case convolve(fcNormal, fcZero):
+ if(sign)
+ return cmpLessThan;
+ else
+ return cmpGreaterThan;
+
+ case convolve(fcNormal, fcInfinity):
+ case convolve(fcZero, fcInfinity):
+ case convolve(fcZero, fcNormal):
+ if(rhs.sign)
+ return cmpGreaterThan;
+ else
+ return cmpLessThan;
+
+ case convolve(fcInfinity, fcInfinity):
+ if(sign == rhs.sign)
+ return cmpEqual;
+ else if(sign)
+ return cmpLessThan;
+ else
+ return cmpGreaterThan;
+
+ case convolve(fcZero, fcZero):
+ return cmpEqual;
+
+ case convolve(fcNormal, fcNormal):
+ break;
+ }
+
+ /* Two normal numbers. Do they have the same sign? */
+ if(sign != rhs.sign) {
+ if(sign)
+ result = cmpLessThan;
+ else
+ result = cmpGreaterThan;
+ } else {
+ /* Compare absolute values; invert result if negative. */
+ result = compareAbsoluteValue(rhs);
+
+ if(sign) {
+ if(result == cmpLessThan)
+ result = cmpGreaterThan;
+ else if(result == cmpGreaterThan)
+ result = cmpLessThan;
+ }
+ }
+
+ return result;
+}
+
+APFloat::opStatus
+APFloat::convert(const fltSemantics &toSemantics,
+ roundingMode rounding_mode)
+{
+ unsigned int newPartCount;
+ opStatus fs;
+
+ newPartCount = partCountForBits(toSemantics.precision + 1);
+
+ /* If our new form is wider, re-allocate our bit pattern into wider
+ storage. */
+ if(newPartCount > partCount()) {
+ integerPart *newParts;
+
+ newParts = new integerPart[newPartCount];
+ APInt::tcSet(newParts, 0, newPartCount);
+ APInt::tcAssign(newParts, significandParts(), partCount());
+ freeSignificand();
+ significand.parts = newParts;
+ }
+
+ if(category == fcNormal) {
+ /* Re-interpret our bit-pattern. */
+ exponent += toSemantics.precision - semantics->precision;
+ semantics = &toSemantics;
+ fs = normalize(rounding_mode, lfExactlyZero);
+ } else {
+ semantics = &toSemantics;
+ fs = opOK;
+ }
+
+ return fs;
+}
+
+/* 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
+ 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.
+
+ 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
+{
+ lostFraction lost_fraction;
+ unsigned int msb, partsCount;
+ int bits;
+
+ /* Handle the three special cases first. */
+ if(category == fcInfinity || category == fcQNaN)
+ return opInvalidOp;
+
+ partsCount = partCountForBits(width);
+
+ if(category == fcZero) {
+ APInt::tcSet(parts, 0, partsCount);
+ return opOK;
+ }
+
+ /* Shift the bit pattern so the fraction is lost. */
+ APFloat tmp(*this);
+
+ bits = (int) semantics->precision - 1 - exponent;
+
+ if(bits > 0) {
+ lost_fraction = tmp.shiftSignificandRight(bits);
+ } else {
+ tmp.shiftSignificandLeft(-bits);
+ lost_fraction = lfExactlyZero;
+ }
+
+ if(lost_fraction != lfExactlyZero
+ && tmp.roundAwayFromZero(rounding_mode, lost_fraction))
+ tmp.incrementSignificand();
+
+ msb = tmp.significandMSB();
+
+ /* Negative numbers cannot be represented as unsigned. */
+ if(!isSigned && tmp.sign && msb != -1U)
+ 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(isSigned && msb + 1 == width
+ && (!tmp.sign || tmp.significandLSB() != msb))
+ return opInvalidOp;
+
+ APInt::tcAssign(parts, tmp.significandParts(), partsCount);
+
+ if(tmp.sign)
+ APInt::tcNegate(parts, partsCount);
+
+ if(lost_fraction == lfExactlyZero)
+ return opOK;
+ else
+ return opInexact;
+}
+
+APFloat::opStatus
+APFloat::convertFromUnsignedInteger(integerPart *parts,
+ unsigned int partCount,
+ roundingMode rounding_mode)
+{
+ unsigned int msb, precision;
+ lostFraction lost_fraction;
+
+ msb = APInt::tcMSB(parts, partCount) + 1;
+ precision = semantics->precision;
+
+ category = fcNormal;
+ exponent = precision - 1;
+
+ if(msb > precision) {
+ exponent += (msb - precision);
+ lost_fraction = shiftRight(parts, partCount, msb - precision);
+ msb = precision;
+ } else
+ lost_fraction = lfExactlyZero;
+
+ /* Copy the bit image. */
+ zeroSignificand();
+ APInt::tcAssign(significandParts(), parts, partCountForBits(msb));
+
+ return normalize(rounding_mode, lost_fraction);
+}
+
+APFloat::opStatus
+APFloat::convertFromInteger(const integerPart *parts,
+ unsigned int partCount, bool isSigned,
+ roundingMode rounding_mode)
+{
+ unsigned int width;
+ opStatus status;
+ integerPart *copy;
+
+ copy = new integerPart[partCount];
+ APInt::tcAssign(copy, parts, partCount);
+
+ width = partCount * integerPartWidth;
+
+ sign = false;
+ if(isSigned && APInt::tcExtractBit(parts, width - 1)) {
+ sign = true;
+ APInt::tcNegate(copy, partCount);
+ }
+
+ status = convertFromUnsignedInteger(copy, partCount, rounding_mode);
+ delete [] copy;
+
+ return status;
+}
+
+APFloat::opStatus
+APFloat::convertFromHexadecimalString(const char *p,
+ roundingMode rounding_mode)
+{
+ lostFraction lost_fraction;
+ integerPart *significand;
+ unsigned int bitPos, partsCount;
+ const char *dot, *firstSignificantDigit;
+
+ zeroSignificand();
+ exponent = 0;
+ category = fcNormal;
+
+ significand = significandParts();
+ partsCount = partCount();
+ bitPos = partsCount * integerPartWidth;
+
+ /* Skip leading zeroes and any(hexa)decimal point. */
+ p = skipLeadingZeroesAndAnyDot(p, &dot);
+ firstSignificantDigit = p;
+
+ for(;;) {
+ integerPart hex_value;
+
+ if(*p == '.') {
+ assert(dot == 0);
+ dot = p++;
+ }
+
+ hex_value = hexDigitValue(*p);
+ if(hex_value == -1U) {
+ lost_fraction = lfExactlyZero;
+ break;
+ }
+
+ p++;
+
+ /* Store the number whilst 4-bit nibbles remain. */
+ if(bitPos) {
+ bitPos -= 4;
+ hex_value <<= bitPos % integerPartWidth;
+ significand[bitPos / integerPartWidth] |= hex_value;
+ } else {
+ lost_fraction = trailingHexadecimalFraction(p, hex_value);
+ while(hexDigitValue(*p) != -1U)
+ p++;
+ break;
+ }
+ }
+
+ /* Hex floats require an exponent but not a hexadecimal point. */
+ assert(*p == 'p' || *p == 'P');
+
+ /* Ignore the exponent if we are zero. */
+ if(p != firstSignificantDigit) {
+ int expAdjustment;
+
+ /* Implicit hexadecimal point? */
+ if(!dot)
+ dot = p;
+
+ /* Calculate the exponent adjustment implicit in the number of
+ significant digits. */
+ expAdjustment = dot - firstSignificantDigit;
+ if(expAdjustment < 0)
+ expAdjustment++;
+ expAdjustment = expAdjustment * 4 - 1;
+
+ /* Adjust for writing the significand starting at the most
+ significant nibble. */
+ expAdjustment += semantics->precision;
+ expAdjustment -= partsCount * integerPartWidth;
+
+ /* Adjust for the given exponent. */
+ exponent = totalExponent(p, expAdjustment);
+ }
+
+ return normalize(rounding_mode, lost_fraction);
+}
+
+APFloat::opStatus
+APFloat::convertFromString(const char *p, roundingMode rounding_mode)
+{
+ /* Handle a leading minus sign. */
+ if(*p == '-')
+ sign = 1, p++;
+ else
+ sign = 0;
+
+ if(p[0] == '0' && (p[1] == 'x' || p[1] ==
'X'))
+ return convertFromHexadecimalString(p + 2, rounding_mode);
+ else
+ {
+ assert(0 && "Decimal to binary conversions not yet
imlemented");
+ abort();
+ }
+}