From b39cdde41d3c91d1fd48a038e63b78122607bb10 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 20 Aug 2007 22:49:32 +0000 Subject: [PATCH] initial checkin of Neil's APFloat work. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41203 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/APFloat.h | 258 +++++++ include/llvm/ADT/APInt.h | 7 +- lib/Support/APFloat.cpp | 1488 ++++++++++++++++++++++++++++++++++++ lib/Support/APInt.cpp | 40 +- 4 files changed, 1780 insertions(+), 13 deletions(-) create mode 100644 include/llvm/ADT/APFloat.h create mode 100644 lib/Support/APFloat.cpp diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h new file mode 100644 index 00000000000..89614d5d367 --- /dev/null +++ b/include/llvm/ADT/APFloat.h @@ -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 */ diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index ce3696fc1e6..971822f1bd4 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -19,9 +19,7 @@ #include #include -#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 @@ namespace llvm { bignum. */ typedef uint64_t integerPart; + const unsigned int host_char_bit = 8; + const unsigned int integerPartWidth = host_char_bit * sizeof(integerPart); + //===----------------------------------------------------------------------===// // APInt Class //===----------------------------------------------------------------------===// diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp new file mode 100644 index 00000000000..8ac92475db7 --- /dev/null +++ b/lib/Support/APFloat.cpp @@ -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 +#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(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(); + } +} diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index 0aec2a6d097..173f28c8d19 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -2018,19 +2018,39 @@ void APInt::dump() const /* Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe and unrestricting assumption. */ -compileTimeAssert(integerPartWidth % 2 == 0); - -#define lowBitMask(bits) (~(integerPart) 0 >> (integerPartWidth - (bits))) -#define lowHalf(part) ((part) & lowBitMask(integerPartWidth / 2)) -#define highHalf(part) ((part) >> (integerPartWidth / 2)) +COMPILE_TIME_ASSERT(integerPartWidth % 2 == 0); /* 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 @@ APInt::tcMSB(const integerPart *parts, unsigned int n) --n; if (parts[n] != 0) { - msb = PartMSB(parts[n]); + msb = partMSB(parts[n]); return msb + n * integerPartWidth; } @@ -2388,11 +2408,11 @@ APInt::tcDivide(integerPart *lhs, const integerPart *rhs, 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);