#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/MathExtras.h"
#include <cstring>
using namespace llvm;
#define convolve(lhs, rhs) ((lhs) * 4 + (rhs))
#define COMPILE_TIME_ASSERT(cond) extern int CTAssert[(cond) ? 1 : -1]
COMPILE_TIME_ASSERT(integerPartWidth % 4 == 0);
namespace llvm {
struct fltSemantics {
exponent_t maxExponent;
exponent_t minExponent;
unsigned int precision;
unsigned int arithmeticOK;
};
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, true };
const fltSemantics APFloat::Bogus = { 0, 0, 0, true };
const fltSemantics APFloat::PPCDoubleDouble = { 1023, -1022, 106, false };
const unsigned int maxExponent = 16383;
const unsigned int maxPrecision = 113;
const unsigned int maxPowerOfFiveExponent = maxExponent + maxPrecision - 1;
const unsigned int maxPowerOfFiveParts = 2 + ((maxPowerOfFiveExponent * 815)
/ (351 * integerPartWidth));
}
static inline unsigned int
partCountForBits(unsigned int bits)
{
return ((bits) + integerPartWidth - 1) / integerPartWidth;
}
static inline unsigned int
decDigitValue(unsigned int c)
{
return c - '0';
}
static 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;
}
static inline void
assertArithmeticOK(const llvm::fltSemantics &semantics) {
assert(semantics.arithmeticOK
&& "Compile-time arithmetic does not support these semantics");
}
static int
readExponent(const char *p)
{
bool isNegative;
unsigned int absExponent;
const unsigned int overlargeExponent = 24000;
isNegative = (*p == '-');
if (*p == '-' || *p == '+')
p++;
absExponent = decDigitValue(*p++);
assert (absExponent < 10U);
for (;;) {
unsigned int value;
value = decDigitValue(*p);
if (value >= 10U)
break;
p++;
value += absExponent * 10;
if (absExponent >= overlargeExponent) {
absExponent = overlargeExponent;
break;
}
absExponent = value;
}
if (isNegative)
return -(int) absExponent;
else
return (int) absExponent;
}
static int
totalExponent(const char *p, int exponentAdjustment)
{
int unsignedExponent;
bool negative, overflow;
int exponent;
p++;
negative = *p == '-';
if(*p == '-' || *p == '+')
p++;
unsignedExponent = 0;
overflow = false;
for(;;) {
unsigned int value;
value = decDigitValue(*p);
if(value >= 10U)
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;
}
static 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;
}
struct decimalInfo {
const char *firstSigDigit;
const char *lastSigDigit;
int exponent;
int normalizedExponent;
};
static void
interpretDecimal(const char *p, decimalInfo *D)
{
const char *dot;
p = skipLeadingZeroesAndAnyDot (p, &dot);
D->firstSigDigit = p;
D->exponent = 0;
D->normalizedExponent = 0;
for (;;) {
if (*p == '.') {
assert(dot == 0);
dot = p++;
}
if (decDigitValue(*p) >= 10U)
break;
p++;
}
if (p != D->firstSigDigit) {
if (*p == 'e' || *p == 'E')
D->exponent = readExponent(p + 1);
if (!dot)
dot = p;
do
do
p--;
while (*p == '0');
while (*p == '.');
D->exponent += static_cast<exponent_t>((dot - p) - (dot > p));
D->normalizedExponent = (D->exponent +
static_cast<exponent_t>((p - D->firstSigDigit)
- (dot > D->firstSigDigit && dot < p)));
}
D->lastSigDigit = p;
}
static lostFraction
trailingHexadecimalFraction(const char *p, unsigned int digitValue)
{
unsigned int hexDigit;
if(digitValue > 8)
return lfMoreThanHalf;
else if(digitValue < 8 && digitValue > 0)
return lfLessThanHalf;
while(*p == '0')
p++;
hexDigit = hexDigitValue(*p);
if(hexDigit == -1U)
return digitValue == 0 ? lfExactlyZero: lfExactlyHalf;
else
return digitValue == 0 ? lfLessThanHalf: lfMoreThanHalf;
}
static lostFraction
lostFractionThroughTruncation(const integerPart *parts,
unsigned int partCount,
unsigned int bits)
{
unsigned int lsb;
lsb = APInt::tcLSB(parts, partCount);
if(bits <= lsb)
return lfExactlyZero;
if(bits == lsb + 1)
return lfExactlyHalf;
if(bits <= partCount * integerPartWidth
&& APInt::tcExtractBit(parts, bits - 1))
return lfMoreThanHalf;
return lfLessThanHalf;
}
static 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;
}
static lostFraction
combineLostFractions(lostFraction moreSignificant,
lostFraction lessSignificant)
{
if(lessSignificant != lfExactlyZero) {
if(moreSignificant == lfExactlyZero)
moreSignificant = lfLessThanHalf;
else if(moreSignificant == lfExactlyHalf)
moreSignificant = lfMoreThanHalf;
}
return moreSignificant;
}
static unsigned int
HUerrBound(bool inexactMultiply, unsigned int HUerr1, unsigned int HUerr2)
{
assert(HUerr1 < 2 || HUerr2 < 2 || (HUerr1 + HUerr2 < 8));
if (HUerr1 + HUerr2 == 0)
return inexactMultiply * 2;
else
return inexactMultiply + 2 * (HUerr1 + HUerr2);
}
static integerPart
ulpsFromBoundary(const integerPart *parts, unsigned int bits, bool isNearest)
{
unsigned int count, partBits;
integerPart part, boundary;
assert (bits != 0);
bits--;
count = bits / integerPartWidth;
partBits = bits % integerPartWidth + 1;
part = parts[count] & (~(integerPart) 0 >> (integerPartWidth - partBits));
if (isNearest)
boundary = (integerPart) 1 << (partBits - 1);
else
boundary = 0;
if (count == 0) {
if (part - boundary <= boundary - part)
return part - boundary;
else
return boundary - part;
}
if (part == boundary) {
while (--count)
if (parts[count])
return ~(integerPart) 0;
return parts[0];
} else if (part == boundary - 1) {
while (--count)
if (~parts[count])
return ~(integerPart) 0;
return -parts[0];
}
return ~(integerPart) 0;
}
static unsigned int
powerOf5(integerPart *dst, unsigned int power)
{
static const integerPart firstEightPowers[] = { 1, 5, 25, 125, 625, 3125,
15625, 78125 };
integerPart pow5s[maxPowerOfFiveParts * 2 + 5];
pow5s[0] = 78125 * 5;
unsigned int partsCount[16] = { 1 };
integerPart scratch[maxPowerOfFiveParts], *p1, *p2, *pow5;
unsigned int result;
assert(power <= maxExponent);
p1 = dst;
p2 = scratch;
*p1 = firstEightPowers[power & 7];
power >>= 3;
result = 1;
pow5 = pow5s;
for (unsigned int n = 0; power; power >>= 1, n++) {
unsigned int pc;
pc = partsCount[n];
if (pc == 0) {
pc = partsCount[n - 1];
APInt::tcFullMultiply(pow5, pow5 - pc, pow5 - pc, pc, pc);
pc *= 2;
if (pow5[pc - 1] == 0)
pc--;
partsCount[n] = pc;
}
if (power & 1) {
integerPart *tmp;
APInt::tcFullMultiply(p2, p1, pow5, result, pc);
result += pc;
if (p2[result - 1] == 0)
result--;
tmp = p1, p1 = p2, p2 = tmp;
}
pow5 += pc;
}
if (p1 != dst)
APInt::tcAssign(dst, p1, result);
return result;
}
static const char hexDigitsLower[] = "0123456789abcdef0";
static const char hexDigitsUpper[] = "0123456789ABCDEF0";
static const char infinityL[] = "infinity";
static const char infinityU[] = "INFINITY";
static const char NaNL[] = "nan";
static const char NaNU[] = "NAN";
static unsigned int
partAsHex (char *dst, integerPart part, unsigned int count,
const char *hexDigitChars)
{
unsigned int result = count;
assert (count != 0 && count <= integerPartWidth / 4);
part >>= (integerPartWidth - 4 * count);
while (count--) {
dst[count] = hexDigitChars[part & 0xf];
part >>= 4;
}
return result;
}
static char *
writeUnsignedDecimal (char *dst, unsigned int n)
{
char buff[40], *p;
p = buff;
do
*p++ = '0' + n % 10;
while (n /= 10);
do
*dst++ = *--p;
while (p != buff);
return dst;
}
static char *
writeSignedDecimal (char *dst, int value)
{
if (value < 0) {
*dst++ = '-';
dst = writeUnsignedDecimal(dst, -(unsigned) value);
} else
dst = writeUnsignedDecimal(dst, value);
return dst;
}
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;
sign2 = rhs.sign2;
exponent2 = rhs.exponent2;
if(category == fcNormal || category == fcNaN)
copySignificand(rhs);
}
void
APFloat::copySignificand(const APFloat &rhs)
{
assert(category == fcNormal || category == fcNaN);
assert(rhs.partCount() >= partCount());
APInt::tcAssign(significandParts(), rhs.significandParts(),
partCount());
}
void
APFloat::makeNaN(void)
{
category = fcNaN;
APInt::tcSet(significandParts(), ~0U, partCount());
}
APFloat &
APFloat::operator=(const APFloat &rhs)
{
if(this != &rhs) {
if(semantics != rhs.semantics) {
freeSignificand();
initialize(rhs.semantics);
}
assign(rhs);
}
return *this;
}
bool
APFloat::bitwiseIsEqual(const APFloat &rhs) const {
if (this == &rhs)
return true;
if (semantics != rhs.semantics ||
category != rhs.category ||
sign != rhs.sign)
return false;
if (semantics==(const llvm::fltSemantics*)&PPCDoubleDouble &&
sign2 != rhs.sign2)
return false;
if (category==fcZero || category==fcInfinity)
return true;
else if (category==fcNormal && exponent!=rhs.exponent)
return false;
else if (semantics==(const llvm::fltSemantics*)&PPCDoubleDouble &&
exponent2!=rhs.exponent2)
return false;
else {
int i= partCount();
const integerPart* p=significandParts();
const integerPart* q=rhs.significandParts();
for (; i>0; i--, p++, q++) {
if (*p != *q)
return false;
}
return true;
}
}
APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value)
{
assertArithmeticOK(ourSemantics);
initialize(&ourSemantics);
sign = 0;
zeroSignificand();
exponent = ourSemantics.precision - 1;
significandParts()[0] = value;
normalize(rmNearestTiesToEven, lfExactlyZero);
}
APFloat::APFloat(const fltSemantics &ourSemantics,
fltCategory ourCategory, bool negative)
{
assertArithmeticOK(ourSemantics);
initialize(&ourSemantics);
category = ourCategory;
sign = negative;
if(category == fcNormal)
category = fcZero;
else if (ourCategory == fcNaN)
makeNaN();
}
APFloat::APFloat(const fltSemantics &ourSemantics, const char *text)
{
assertArithmeticOK(ourSemantics);
initialize(&ourSemantics);
convertFromString(text, rmNearestTiesToEven);
}
APFloat::APFloat(const APFloat &rhs)
{
initialize(rhs.semantics);
assign(rhs);
}
APFloat::~APFloat()
{
freeSignificand();
}
void APFloat::Profile(FoldingSetNodeID& ID) const {
ID.Add(bitcastToAPInt());
}
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 || category == fcNaN);
if(partCount() > 1)
return significand.parts;
else
return &significand.part;
}
void
APFloat::zeroSignificand()
{
category = fcNormal;
APInt::tcSet(significandParts(), 0, partCount());
}
void
APFloat::incrementSignificand()
{
integerPart carry;
carry = APInt::tcIncrement(significandParts(), partCount());
assert(carry == 0);
}
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());
}
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());
}
lostFraction
APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend)
{
unsigned int omsb; unsigned int partsCount, newPartsCount, precision;
integerPart *lhsSignificand;
integerPart scratch[4];
integerPart *fullSignificand;
lostFraction lost_fraction;
bool ignored;
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, 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;
extendedPrecision = precision + precision - 1;
if(omsb != extendedPrecision)
{
APInt::tcShiftLeft(fullSignificand, newPartsCount,
extendedPrecision - omsb);
exponent -= extendedPrecision - omsb;
}
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, &ignored);
assert(status == opOK);
lost_fraction = addOrSubtractSignificand(extendedAddend, false);
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;
}
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;
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;
bit = precision - APInt::tcMSB(divisor, partsCount) - 1;
if(bit) {
exponent += bit;
APInt::tcShiftLeft(divisor, partsCount, bit);
}
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);
}
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);
}
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());
}
lostFraction
APFloat::shiftSignificandRight(unsigned int bits)
{
assert((exponent_t) (exponent + bits) >= exponent);
exponent += bits;
return shiftRight(significandParts(), partCount(), bits);
}
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(compare == 0)
compare = APInt::tcCompare(significandParts(), rhs.significandParts(),
partCount());
if(compare > 0)
return cmpGreaterThan;
else if(compare < 0)
return cmpLessThan;
else
return cmpEqual;
}
APFloat::opStatus
APFloat::handleOverflow(roundingMode rounding_mode)
{
if(rounding_mode == rmNearestTiesToEven
|| rounding_mode == rmNearestTiesToAway
|| (rounding_mode == rmTowardPositive && !sign)
|| (rounding_mode == rmTowardNegative && sign))
{
category = fcInfinity;
return (opStatus) (opOverflow | opInexact);
}
category = fcNormal;
exponent = semantics->maxExponent;
APInt::tcSetLeastSignificantBits(significandParts(), partCount(),
semantics->precision);
return opInexact;
}
bool
APFloat::roundAwayFromZero(roundingMode rounding_mode,
lostFraction lost_fraction,
unsigned int bit) const
{
assert(category == fcNormal || category == fcZero);
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;
if(lost_fraction == lfExactlyHalf && category != fcZero)
return APInt::tcExtractBit(significandParts(), bit);
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;
int exponentChange;
if(category != fcNormal)
return opOK;
omsb = significandMSB() + 1;
if(omsb) {
exponentChange = omsb - semantics->precision;
if(exponent + exponentChange > semantics->maxExponent)
return handleOverflow(rounding_mode);
if(exponent + exponentChange < semantics->minExponent)
exponentChange = semantics->minExponent - exponent;
if(exponentChange < 0) {
assert(lost_fraction == lfExactlyZero);
shiftSignificandLeft(-exponentChange);
return opOK;
}
if(exponentChange > 0) {
lostFraction lf;
lf = shiftSignificandRight(exponentChange);
lost_fraction = combineLostFractions(lf, lost_fraction);
if(omsb > (unsigned) exponentChange)
omsb -= exponentChange;
else
omsb = 0;
}
}
if(lost_fraction == lfExactlyZero) {
if(omsb == 0)
category = fcZero;
return opOK;
}
if(roundAwayFromZero(rounding_mode, lost_fraction, 0)) {
if(omsb == 0)
exponent = semantics->minExponent;
incrementSignificand();
omsb = significandMSB() + 1;
if(omsb == (unsigned) semantics->precision + 1) {
if(exponent == semantics->maxExponent) {
category = fcInfinity;
return (opStatus) (opOverflow | opInexact);
}
shiftSignificandRight(1);
return opInexact;
}
}
if(omsb == semantics->precision)
return opInexact;
assert(omsb < semantics->precision);
if(omsb == 0)
category = fcZero;
return (opStatus) (opUnderflow | opInexact);
}
APFloat::opStatus
APFloat::addOrSubtractSpecials(const APFloat &rhs, bool subtract)
{
switch(convolve(category, rhs.category)) {
default:
assert(0);
case convolve(fcNaN, fcZero):
case convolve(fcNaN, fcNormal):
case convolve(fcNaN, fcInfinity):
case convolve(fcNaN, fcNaN):
case convolve(fcNormal, fcZero):
case convolve(fcInfinity, fcNormal):
case convolve(fcInfinity, fcZero):
return opOK;
case convolve(fcZero, fcNaN):
case convolve(fcNormal, fcNaN):
case convolve(fcInfinity, fcNaN):
category = fcNaN;
copySignificand(rhs);
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):
return opOK;
case convolve(fcInfinity, fcInfinity):
if(((sign ^ rhs.sign)!=0) != subtract) {
makeNaN();
return opInvalidOp;
}
return opOK;
case convolve(fcNormal, fcNormal):
return opDivByZero;
}
}
lostFraction
APFloat::addOrSubtractSignificand(const APFloat &rhs, bool subtract)
{
integerPart carry;
lostFraction lost_fraction;
int bits;
subtract ^= (sign ^ rhs.sign) ? true : false;
bits = exponent - rhs.exponent;
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 {
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);
}
if(lost_fraction == lfLessThanHalf)
lost_fraction = lfMoreThanHalf;
else if(lost_fraction == lfMoreThanHalf)
lost_fraction = lfLessThanHalf;
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);
}
assert(!carry);
}
return lost_fraction;
}
APFloat::opStatus
APFloat::multiplySpecials(const APFloat &rhs)
{
switch(convolve(category, rhs.category)) {
default:
assert(0);
case convolve(fcNaN, fcZero):
case convolve(fcNaN, fcNormal):
case convolve(fcNaN, fcInfinity):
case convolve(fcNaN, fcNaN):
return opOK;
case convolve(fcZero, fcNaN):
case convolve(fcNormal, fcNaN):
case convolve(fcInfinity, fcNaN):
category = fcNaN;
copySignificand(rhs);
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):
makeNaN();
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(fcNaN, fcZero):
case convolve(fcNaN, fcNormal):
case convolve(fcNaN, fcInfinity):
case convolve(fcNaN, fcNaN):
case convolve(fcInfinity, fcZero):
case convolve(fcInfinity, fcNormal):
case convolve(fcZero, fcInfinity):
case convolve(fcZero, fcNormal):
return opOK;
case convolve(fcZero, fcNaN):
case convolve(fcNormal, fcNaN):
case convolve(fcInfinity, fcNaN):
category = fcNaN;
copySignificand(rhs);
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):
makeNaN();
return opInvalidOp;
case convolve(fcNormal, fcNormal):
return opOK;
}
}
APFloat::opStatus
APFloat::modSpecials(const APFloat &rhs)
{
switch(convolve(category, rhs.category)) {
default:
assert(0);
case convolve(fcNaN, fcZero):
case convolve(fcNaN, fcNormal):
case convolve(fcNaN, fcInfinity):
case convolve(fcNaN, fcNaN):
case convolve(fcZero, fcInfinity):
case convolve(fcZero, fcNormal):
case convolve(fcNormal, fcInfinity):
return opOK;
case convolve(fcZero, fcNaN):
case convolve(fcNormal, fcNaN):
case convolve(fcInfinity, fcNaN):
category = fcNaN;
copySignificand(rhs);
return opOK;
case convolve(fcNormal, fcZero):
case convolve(fcInfinity, fcZero):
case convolve(fcInfinity, fcNormal):
case convolve(fcInfinity, fcInfinity):
case convolve(fcZero, fcZero):
makeNaN();
return opInvalidOp;
case convolve(fcNormal, fcNormal):
return opOK;
}
}
void
APFloat::changeSign()
{
sign = !sign;
}
void
APFloat::clearSign()
{
sign = 0;
}
void
APFloat::copySign(const APFloat &rhs)
{
sign = rhs.sign;
}
APFloat::opStatus
APFloat::addOrSubtract(const APFloat &rhs, roundingMode rounding_mode,
bool subtract)
{
opStatus fs;
assertArithmeticOK(*semantics);
fs = addOrSubtractSpecials(rhs, subtract);
if(fs == opDivByZero) {
lostFraction lost_fraction;
lost_fraction = addOrSubtractSignificand(rhs, subtract);
fs = normalize(rounding_mode, lost_fraction);
assert(category != fcZero || lost_fraction == lfExactlyZero);
}
if(category == fcZero) {
if(rhs.category != fcZero || (sign == rhs.sign) == subtract)
sign = (rounding_mode == rmTowardNegative);
}
return fs;
}
APFloat::opStatus
APFloat::add(const APFloat &rhs, roundingMode rounding_mode)
{
return addOrSubtract(rhs, rounding_mode, false);
}
APFloat::opStatus
APFloat::subtract(const APFloat &rhs, roundingMode rounding_mode)
{
return addOrSubtract(rhs, rounding_mode, true);
}
APFloat::opStatus
APFloat::multiply(const APFloat &rhs, roundingMode rounding_mode)
{
opStatus fs;
assertArithmeticOK(*semantics);
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;
}
APFloat::opStatus
APFloat::divide(const APFloat &rhs, roundingMode rounding_mode)
{
opStatus fs;
assertArithmeticOK(*semantics);
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;
}
APFloat::opStatus
APFloat::remainder(const APFloat &rhs)
{
opStatus fs;
APFloat V = *this;
unsigned int origSign = sign;
assertArithmeticOK(*semantics);
fs = V.divide(rhs, rmNearestTiesToEven);
if (fs == opDivByZero)
return fs;
int parts = partCount();
integerPart *x = new integerPart[parts];
bool ignored;
fs = V.convertToInteger(x, parts * integerPartWidth, true,
rmNearestTiesToEven, &ignored);
if (fs==opInvalidOp)
return fs;
fs = V.convertFromZeroExtendedInteger(x, parts * integerPartWidth, true,
rmNearestTiesToEven);
assert(fs==opOK);
fs = V.multiply(rhs, rmNearestTiesToEven);
assert(fs==opOK || fs==opInexact);
fs = subtract(V, rmNearestTiesToEven);
assert(fs==opOK || fs==opInexact);
if (isZero())
sign = origSign; delete[] x;
return fs;
}
APFloat::opStatus
APFloat::mod(const APFloat &rhs, roundingMode rounding_mode)
{
opStatus fs;
assertArithmeticOK(*semantics);
fs = modSpecials(rhs);
if (category == fcNormal && rhs.category == fcNormal) {
APFloat V = *this;
unsigned int origSign = sign;
fs = V.divide(rhs, rmNearestTiesToEven);
if (fs == opDivByZero)
return fs;
int parts = partCount();
integerPart *x = new integerPart[parts];
bool ignored;
fs = V.convertToInteger(x, parts * integerPartWidth, true,
rmTowardZero, &ignored);
if (fs==opInvalidOp)
return fs;
fs = V.convertFromZeroExtendedInteger(x, parts * integerPartWidth, true,
rmNearestTiesToEven);
assert(fs==opOK);
fs = V.multiply(rhs, rounding_mode);
assert(fs==opOK || fs==opInexact);
fs = subtract(V, rounding_mode);
assert(fs==opOK || fs==opInexact);
if (isZero())
sign = origSign; delete[] x;
}
return fs;
}
APFloat::opStatus
APFloat::fusedMultiplyAdd(const APFloat &multiplicand,
const APFloat &addend,
roundingMode rounding_mode)
{
opStatus fs;
assertArithmeticOK(*semantics);
sign ^= multiplicand.sign;
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(category == fcZero && sign != addend.sign)
sign = (rounding_mode == rmTowardNegative);
} else {
fs = multiplySpecials(multiplicand);
if(fs == opOK)
fs = addOrSubtract(addend, rounding_mode, false);
}
return fs;
}
APFloat::cmpResult
APFloat::compare(const APFloat &rhs) const
{
cmpResult result;
assertArithmeticOK(*semantics);
assert(semantics == rhs.semantics);
switch(convolve(category, rhs.category)) {
default:
assert(0);
case convolve(fcNaN, fcZero):
case convolve(fcNaN, fcNormal):
case convolve(fcNaN, fcInfinity):
case convolve(fcNaN, fcNaN):
case convolve(fcZero, fcNaN):
case convolve(fcNormal, fcNaN):
case convolve(fcInfinity, fcNaN):
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;
}
if(sign != rhs.sign) {
if(sign)
result = cmpLessThan;
else
result = cmpGreaterThan;
} else {
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, bool *losesInfo)
{
lostFraction lostFraction;
unsigned int newPartCount, oldPartCount;
opStatus fs;
assertArithmeticOK(*semantics);
assertArithmeticOK(toSemantics);
lostFraction = lfExactlyZero;
newPartCount = partCountForBits(toSemantics.precision + 1);
oldPartCount = partCount();
if (newPartCount > oldPartCount) {
integerPart *newParts;
newParts = new integerPart[newPartCount];
APInt::tcSet(newParts, 0, newPartCount);
if (category==fcNormal || category==fcNaN)
APInt::tcAssign(newParts, significandParts(), oldPartCount);
freeSignificand();
significand.parts = newParts;
} else if (newPartCount < oldPartCount) {
if (category==fcNormal)
lostFraction = lostFractionThroughTruncation
(significandParts(), oldPartCount, toSemantics.precision);
if (newPartCount == 1) {
integerPart newPart = 0;
if (category==fcNormal || category==fcNaN)
newPart = significandParts()[0];
freeSignificand();
significand.part = newPart;
}
}
if(category == fcNormal) {
exponent += toSemantics.precision - semantics->precision;
semantics = &toSemantics;
fs = normalize(rounding_mode, lostFraction);
*losesInfo = (fs != opOK);
} else if (category == fcNaN) {
int shift = toSemantics.precision - semantics->precision;
const fltSemantics *oldSemantics = semantics;
semantics = &toSemantics;
*losesInfo = false;
if (shift>0)
APInt::tcShiftLeft(significandParts(), newPartCount, shift);
else if (shift < 0) {
unsigned ushift = -shift;
if (APInt::tcLSB(significandParts(), newPartCount) < ushift)
*losesInfo = true;
if (oldSemantics == &APFloat::x87DoubleExtended &&
(!(*significandParts() & 0x8000000000000000ULL) ||
!(*significandParts() & 0x4000000000000000ULL)))
*losesInfo = true;
APInt::tcShiftRight(significandParts(), newPartCount, ushift);
}
fs = opOK;
} else {
semantics = &toSemantics;
fs = opOK;
*losesInfo = false;
}
return fs;
}
APFloat::opStatus
APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width,
bool isSigned,
roundingMode rounding_mode,
bool *isExact) const
{
lostFraction lost_fraction;
const integerPart *src;
unsigned int dstPartsCount, truncatedBits;
assertArithmeticOK(*semantics);
*isExact = false;
if(category == fcInfinity || category == fcNaN)
return opInvalidOp;
dstPartsCount = partCountForBits(width);
if(category == fcZero) {
APInt::tcSet(parts, 0, dstPartsCount);
*isExact = !sign;
return opOK;
}
src = significandParts();
if (exponent < 0) {
APInt::tcSet(parts, 0, dstPartsCount);
truncatedBits = semantics->precision -1U - exponent;
} else {
unsigned int bits = exponent + 1U;
if (bits > width)
return opInvalidOp;
if (bits < semantics->precision) {
truncatedBits = semantics->precision - bits;
APInt::tcExtract(parts, dstPartsCount, src, bits, truncatedBits);
} else {
APInt::tcExtract(parts, dstPartsCount, src, semantics->precision, 0);
APInt::tcShiftLeft(parts, dstPartsCount, bits - semantics->precision);
truncatedBits = 0;
}
}
if (truncatedBits) {
lost_fraction = lostFractionThroughTruncation(src, partCount(),
truncatedBits);
if (lost_fraction != lfExactlyZero
&& roundAwayFromZero(rounding_mode, lost_fraction, truncatedBits)) {
if (APInt::tcIncrement(parts, dstPartsCount))
return opInvalidOp;
}
} else {
lost_fraction = lfExactlyZero;
}
unsigned int omsb = APInt::tcMSB(parts, dstPartsCount) + 1;
if (sign) {
if (!isSigned) {
if (omsb != 0)
return opInvalidOp;
} else {
if (omsb == width && APInt::tcLSB(parts, dstPartsCount) + 1 != omsb)
return opInvalidOp;
if (omsb > width)
return opInvalidOp;
}
APInt::tcNegate (parts, dstPartsCount);
} else {
if (omsb >= width + !isSigned)
return opInvalidOp;
}
if (lost_fraction == lfExactlyZero) {
*isExact = true;
return opOK;
} else
return opInexact;
}
APFloat::opStatus
APFloat::convertToInteger(integerPart *parts, unsigned int width,
bool isSigned,
roundingMode rounding_mode, bool *isExact) const
{
opStatus fs;
fs = convertToSignExtendedInteger(parts, width, isSigned, rounding_mode,
isExact);
if (fs == opInvalidOp) {
unsigned int bits, dstPartsCount;
dstPartsCount = partCountForBits(width);
if (category == fcNaN)
bits = 0;
else if (sign)
bits = isSigned;
else
bits = width - isSigned;
APInt::tcSetLeastSignificantBits(parts, dstPartsCount, bits);
if (sign && isSigned)
APInt::tcShiftLeft(parts, dstPartsCount, width - 1);
}
return fs;
}
APFloat::opStatus
APFloat::convertFromUnsignedParts(const integerPart *src,
unsigned int srcCount,
roundingMode rounding_mode)
{
unsigned int omsb, precision, dstCount;
integerPart *dst;
lostFraction lost_fraction;
assertArithmeticOK(*semantics);
category = fcNormal;
omsb = APInt::tcMSB(src, srcCount) + 1;
dst = significandParts();
dstCount = partCount();
precision = semantics->precision;
if (precision <= omsb) {
exponent = omsb - 1;
lost_fraction = lostFractionThroughTruncation(src, srcCount,
omsb - precision);
APInt::tcExtract(dst, dstCount, src, precision, omsb - precision);
} else {
exponent = precision - 1;
lost_fraction = lfExactlyZero;
APInt::tcExtract(dst, dstCount, src, omsb, 0);
}
return normalize(rounding_mode, lost_fraction);
}
APFloat::opStatus
APFloat::convertFromAPInt(const APInt &Val,
bool isSigned,
roundingMode rounding_mode)
{
unsigned int partCount = Val.getNumWords();
APInt api = Val;
sign = false;
if (isSigned && api.isNegative()) {
sign = true;
api = -api;
}
return convertFromUnsignedParts(api.getRawData(), partCount, rounding_mode);
}
APFloat::opStatus
APFloat::convertFromSignExtendedInteger(const integerPart *src,
unsigned int srcCount,
bool isSigned,
roundingMode rounding_mode)
{
opStatus status;
assertArithmeticOK(*semantics);
if (isSigned
&& APInt::tcExtractBit(src, srcCount * integerPartWidth - 1)) {
integerPart *copy;
sign = true;
copy = new integerPart[srcCount];
APInt::tcAssign(copy, src, srcCount);
APInt::tcNegate(copy, srcCount);
status = convertFromUnsignedParts(copy, srcCount, rounding_mode);
delete [] copy;
} else {
sign = false;
status = convertFromUnsignedParts(src, srcCount, rounding_mode);
}
return status;
}
APFloat::opStatus
APFloat::convertFromZeroExtendedInteger(const integerPart *parts,
unsigned int width, bool isSigned,
roundingMode rounding_mode)
{
unsigned int partCount = partCountForBits(width);
APInt api = APInt(width, partCount, parts);
sign = false;
if(isSigned && APInt::tcExtractBit(parts, width - 1)) {
sign = true;
api = -api;
}
return convertFromUnsignedParts(api.getRawData(), partCount, rounding_mode);
}
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;
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++;
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;
}
}
assert(*p == 'p' || *p == 'P');
if(p != firstSignificantDigit) {
int expAdjustment;
if(!dot)
dot = p;
expAdjustment = static_cast<int>(dot - firstSignificantDigit);
if(expAdjustment < 0)
expAdjustment++;
expAdjustment = expAdjustment * 4 - 1;
expAdjustment += semantics->precision;
expAdjustment -= partsCount * integerPartWidth;
exponent = totalExponent(p, expAdjustment);
}
return normalize(rounding_mode, lost_fraction);
}
APFloat::opStatus
APFloat::roundSignificandWithExponent(const integerPart *decSigParts,
unsigned sigPartCount, int exp,
roundingMode rounding_mode)
{
unsigned int parts, pow5PartCount;
fltSemantics calcSemantics = { 32767, -32767, 0, true };
integerPart pow5Parts[maxPowerOfFiveParts];
bool isNearest;
isNearest = (rounding_mode == rmNearestTiesToEven
|| rounding_mode == rmNearestTiesToAway);
parts = partCountForBits(semantics->precision + 11);
pow5PartCount = powerOf5(pow5Parts, exp >= 0 ? exp: -exp);
for (;; parts *= 2) {
opStatus sigStatus, powStatus;
unsigned int excessPrecision, truncatedBits;
calcSemantics.precision = parts * integerPartWidth - 1;
excessPrecision = calcSemantics.precision - semantics->precision;
truncatedBits = excessPrecision;
APFloat decSig(calcSemantics, fcZero, sign);
APFloat pow5(calcSemantics, fcZero, false);
sigStatus = decSig.convertFromUnsignedParts(decSigParts, sigPartCount,
rmNearestTiesToEven);
powStatus = pow5.convertFromUnsignedParts(pow5Parts, pow5PartCount,
rmNearestTiesToEven);
decSig.exponent += exp;
lostFraction calcLostFraction;
integerPart HUerr, HUdistance;
unsigned int powHUerr;
if (exp >= 0) {
calcLostFraction = decSig.multiplySignificand(pow5, NULL);
powHUerr = powStatus != opOK;
} else {
calcLostFraction = decSig.divideSignificand(pow5);
if (decSig.exponent < semantics->minExponent) {
excessPrecision += (semantics->minExponent - decSig.exponent);
truncatedBits = excessPrecision;
if (excessPrecision > calcSemantics.precision)
excessPrecision = calcSemantics.precision;
}
powHUerr = (powStatus == opOK && calcLostFraction == lfExactlyZero) ? 0:2;
}
assert (APInt::tcExtractBit
(decSig.significandParts(), calcSemantics.precision - 1) == 1);
HUerr = HUerrBound(calcLostFraction != lfExactlyZero, sigStatus != opOK,
powHUerr);
HUdistance = 2 * ulpsFromBoundary(decSig.significandParts(),
excessPrecision, isNearest);
if (HUdistance >= HUerr) {
APInt::tcExtract(significandParts(), partCount(), decSig.significandParts(),
calcSemantics.precision - excessPrecision,
excessPrecision);
exponent = (decSig.exponent + semantics->precision
- (calcSemantics.precision - excessPrecision));
calcLostFraction = lostFractionThroughTruncation(decSig.significandParts(),
decSig.partCount(),
truncatedBits);
return normalize(rounding_mode, calcLostFraction);
}
}
}
APFloat::opStatus
APFloat::convertFromDecimalString(const char *p, roundingMode rounding_mode)
{
decimalInfo D;
opStatus fs;
interpretDecimal(p, &D);
if (decDigitValue(*D.firstSigDigit) >= 10U) {
category = fcZero;
fs = opOK;
} else if ((D.normalizedExponent + 1) * 28738
<= 8651 * (semantics->minExponent - (int) semantics->precision)) {
zeroSignificand();
fs = normalize(rounding_mode, lfLessThanHalf);
} else if ((D.normalizedExponent - 1) * 42039
>= 12655 * semantics->maxExponent) {
fs = handleOverflow(rounding_mode);
} else {
integerPart *decSignificand;
unsigned int partCount;
partCount = static_cast<unsigned int>(D.lastSigDigit - D.firstSigDigit) + 1;
partCount = partCountForBits(1 + 196 * partCount / 59);
decSignificand = new integerPart[partCount + 1];
partCount = 0;
do {
integerPart decValue, val, multiplier;
val = 0;
multiplier = 1;
do {
if (*p == '.')
p++;
decValue = decDigitValue(*p++);
multiplier *= 10;
val = val * 10 + decValue;
} while (p <= D.lastSigDigit && multiplier <= (~ (integerPart) 0 - 9) / 10);
APInt::tcMultiplyPart(decSignificand, decSignificand, multiplier, val,
partCount, partCount + 1, false);
if (decSignificand[partCount])
partCount++;
} while (p <= D.lastSigDigit);
category = fcNormal;
fs = roundSignificandWithExponent(decSignificand, partCount,
D.exponent, rounding_mode);
delete [] decSignificand;
}
return fs;
}
APFloat::opStatus
APFloat::convertFromString(const char *p, roundingMode rounding_mode)
{
assertArithmeticOK(*semantics);
if(*p == '-')
sign = 1, p++;
else
sign = 0;
if(p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
return convertFromHexadecimalString(p + 2, rounding_mode);
return convertFromDecimalString(p, rounding_mode);
}
unsigned int
APFloat::convertToHexString(char *dst, unsigned int hexDigits,
bool upperCase, roundingMode rounding_mode) const
{
char *p;
assertArithmeticOK(*semantics);
p = dst;
if (sign)
*dst++ = '-';
switch (category) {
case fcInfinity:
memcpy (dst, upperCase ? infinityU: infinityL, sizeof infinityU - 1);
dst += sizeof infinityL - 1;
break;
case fcNaN:
memcpy (dst, upperCase ? NaNU: NaNL, sizeof NaNU - 1);
dst += sizeof NaNU - 1;
break;
case fcZero:
*dst++ = '0';
*dst++ = upperCase ? 'X': 'x';
*dst++ = '0';
if (hexDigits > 1) {
*dst++ = '.';
memset (dst, '0', hexDigits - 1);
dst += hexDigits - 1;
}
*dst++ = upperCase ? 'P': 'p';
*dst++ = '0';
break;
case fcNormal:
dst = convertNormalToHexString (dst, hexDigits, upperCase, rounding_mode);
break;
}
*dst = 0;
return static_cast<unsigned int>(dst - p);
}
char *
APFloat::convertNormalToHexString(char *dst, unsigned int hexDigits,
bool upperCase,
roundingMode rounding_mode) const
{
unsigned int count, valueBits, shift, partsCount, outputDigits;
const char *hexDigitChars;
const integerPart *significand;
char *p;
bool roundUp;
*dst++ = '0';
*dst++ = upperCase ? 'X': 'x';
roundUp = false;
hexDigitChars = upperCase ? hexDigitsUpper: hexDigitsLower;
significand = significandParts();
partsCount = partCount();
valueBits = semantics->precision + 3;
shift = integerPartWidth - valueBits % integerPartWidth;
outputDigits = (valueBits - significandLSB () + 3) / 4;
if (hexDigits) {
if (hexDigits < outputDigits) {
unsigned int bits;
lostFraction fraction;
bits = valueBits - hexDigits * 4;
fraction = lostFractionThroughTruncation (significand, partsCount, bits);
roundUp = roundAwayFromZero(rounding_mode, fraction, bits);
}
outputDigits = hexDigits;
}
p = ++dst;
count = (valueBits + integerPartWidth - 1) / integerPartWidth;
while (outputDigits && count) {
integerPart part;
if (--count == partsCount)
part = 0;
else
part = significand[count] << shift;
if (count && shift)
part |= significand[count - 1] >> (integerPartWidth - shift);
unsigned int curDigits = integerPartWidth / 4;
if (curDigits > outputDigits)
curDigits = outputDigits;
dst += partAsHex (dst, part, curDigits, hexDigitChars);
outputDigits -= curDigits;
}
if (roundUp) {
char *q = dst;
do {
q--;
*q = hexDigitChars[hexDigitValue (*q) + 1];
} while (*q == '0');
assert (q >= p);
} else {
memset (dst, '0', outputDigits);
dst += outputDigits;
}
p[-1] = p[0];
if (dst -1 == p)
dst--;
else
p[0] = '.';
*dst++ = upperCase ? 'P': 'p';
return writeSignedDecimal (dst, exponent);
}
uint32_t
APFloat::getHashValue() const
{
if (category==fcZero) return sign<<8 | semantics->precision ;
else if (category==fcInfinity) return sign<<9 | semantics->precision;
else if (category==fcNaN) return 1<<10 | semantics->precision;
else {
uint32_t hash = sign<<11 | semantics->precision | exponent<<12;
const integerPart* p = significandParts();
for (int i=partCount(); i>0; i--, p++)
hash ^= ((uint32_t)*p) ^ (uint32_t)((*p)>>32);
return hash;
}
}
APInt
APFloat::convertF80LongDoubleAPFloatToAPInt() const
{
assert(semantics == (const llvm::fltSemantics*)&x87DoubleExtended);
assert (partCount()==2);
uint64_t myexponent, mysignificand;
if (category==fcNormal) {
myexponent = exponent+16383; mysignificand = significandParts()[0];
if (myexponent==1 && !(mysignificand & 0x8000000000000000ULL))
myexponent = 0; } else if (category==fcZero) {
myexponent = 0;
mysignificand = 0;
} else if (category==fcInfinity) {
myexponent = 0x7fff;
mysignificand = 0x8000000000000000ULL;
} else {
assert(category == fcNaN && "Unknown category");
myexponent = 0x7fff;
mysignificand = significandParts()[0];
}
uint64_t words[2];
words[0] = mysignificand;
words[1] = ((uint64_t)(sign & 1) << 15) |
(myexponent & 0x7fffLL);
return APInt(80, 2, words);
}
APInt
APFloat::convertPPCDoubleDoubleAPFloatToAPInt() const
{
assert(semantics == (const llvm::fltSemantics*)&PPCDoubleDouble);
assert (partCount()==2);
uint64_t myexponent, mysignificand, myexponent2, mysignificand2;
if (category==fcNormal) {
myexponent = exponent + 1023; myexponent2 = exponent2 + 1023;
mysignificand = significandParts()[0];
mysignificand2 = significandParts()[1];
if (myexponent==1 && !(mysignificand & 0x10000000000000LL))
myexponent = 0; if (myexponent2==1 && !(mysignificand2 & 0x10000000000000LL))
myexponent2 = 0; } else if (category==fcZero) {
myexponent = 0;
mysignificand = 0;
myexponent2 = 0;
mysignificand2 = 0;
} else if (category==fcInfinity) {
myexponent = 0x7ff;
myexponent2 = 0;
mysignificand = 0;
mysignificand2 = 0;
} else {
assert(category == fcNaN && "Unknown category");
myexponent = 0x7ff;
mysignificand = significandParts()[0];
myexponent2 = exponent2;
mysignificand2 = significandParts()[1];
}
uint64_t words[2];
words[0] = ((uint64_t)(sign & 1) << 63) |
((myexponent & 0x7ff) << 52) |
(mysignificand & 0xfffffffffffffLL);
words[1] = ((uint64_t)(sign2 & 1) << 63) |
((myexponent2 & 0x7ff) << 52) |
(mysignificand2 & 0xfffffffffffffLL);
return APInt(128, 2, words);
}
APInt
APFloat::convertDoubleAPFloatToAPInt() const
{
assert(semantics == (const llvm::fltSemantics*)&IEEEdouble);
assert (partCount()==1);
uint64_t myexponent, mysignificand;
if (category==fcNormal) {
myexponent = exponent+1023; mysignificand = *significandParts();
if (myexponent==1 && !(mysignificand & 0x10000000000000LL))
myexponent = 0; } else if (category==fcZero) {
myexponent = 0;
mysignificand = 0;
} else if (category==fcInfinity) {
myexponent = 0x7ff;
mysignificand = 0;
} else {
assert(category == fcNaN && "Unknown category!");
myexponent = 0x7ff;
mysignificand = *significandParts();
}
return APInt(64, ((((uint64_t)(sign & 1) << 63) |
((myexponent & 0x7ff) << 52) |
(mysignificand & 0xfffffffffffffLL))));
}
APInt
APFloat::convertFloatAPFloatToAPInt() const
{
assert(semantics == (const llvm::fltSemantics*)&IEEEsingle);
assert (partCount()==1);
uint32_t myexponent, mysignificand;
if (category==fcNormal) {
myexponent = exponent+127; mysignificand = (uint32_t)*significandParts();
if (myexponent == 1 && !(mysignificand & 0x800000))
myexponent = 0; } else if (category==fcZero) {
myexponent = 0;
mysignificand = 0;
} else if (category==fcInfinity) {
myexponent = 0xff;
mysignificand = 0;
} else {
assert(category == fcNaN && "Unknown category!");
myexponent = 0xff;
mysignificand = (uint32_t)*significandParts();
}
return APInt(32, (((sign&1) << 31) | ((myexponent&0xff) << 23) |
(mysignificand & 0x7fffff)));
}
APInt
APFloat::bitcastToAPInt() const
{
if (semantics == (const llvm::fltSemantics*)&IEEEsingle)
return convertFloatAPFloatToAPInt();
if (semantics == (const llvm::fltSemantics*)&IEEEdouble)
return convertDoubleAPFloatToAPInt();
if (semantics == (const llvm::fltSemantics*)&PPCDoubleDouble)
return convertPPCDoubleDoubleAPFloatToAPInt();
assert(semantics == (const llvm::fltSemantics*)&x87DoubleExtended &&
"unknown format!");
return convertF80LongDoubleAPFloatToAPInt();
}
float
APFloat::convertToFloat() const
{
assert(semantics == (const llvm::fltSemantics*)&IEEEsingle);
APInt api = bitcastToAPInt();
return api.bitsToFloat();
}
double
APFloat::convertToDouble() const
{
assert(semantics == (const llvm::fltSemantics*)&IEEEdouble);
APInt api = bitcastToAPInt();
return api.bitsToDouble();
}
void
APFloat::initFromF80LongDoubleAPInt(const APInt &api)
{
assert(api.getBitWidth()==80);
uint64_t i1 = api.getRawData()[0];
uint64_t i2 = api.getRawData()[1];
uint64_t myexponent = (i2 & 0x7fff);
uint64_t mysignificand = i1;
initialize(&APFloat::x87DoubleExtended);
assert(partCount()==2);
sign = static_cast<unsigned int>(i2>>15);
if (myexponent==0 && mysignificand==0) {
category = fcZero;
} else if (myexponent==0x7fff && mysignificand==0x8000000000000000ULL) {
category = fcInfinity;
} else if (myexponent==0x7fff && mysignificand!=0x8000000000000000ULL) {
category = fcNaN;
significandParts()[0] = mysignificand;
significandParts()[1] = 0;
} else {
category = fcNormal;
exponent = myexponent - 16383;
significandParts()[0] = mysignificand;
significandParts()[1] = 0;
if (myexponent==0) exponent = -16382;
}
}
void
APFloat::initFromPPCDoubleDoubleAPInt(const APInt &api)
{
assert(api.getBitWidth()==128);
uint64_t i1 = api.getRawData()[0];
uint64_t i2 = api.getRawData()[1];
uint64_t myexponent = (i1 >> 52) & 0x7ff;
uint64_t mysignificand = i1 & 0xfffffffffffffLL;
uint64_t myexponent2 = (i2 >> 52) & 0x7ff;
uint64_t mysignificand2 = i2 & 0xfffffffffffffLL;
initialize(&APFloat::PPCDoubleDouble);
assert(partCount()==2);
sign = static_cast<unsigned int>(i1>>63);
sign2 = static_cast<unsigned int>(i2>>63);
if (myexponent==0 && mysignificand==0) {
category = fcZero;
} else if (myexponent==0x7ff && mysignificand==0) {
category = fcInfinity;
} else if (myexponent==0x7ff && mysignificand!=0) {
category = fcNaN;
exponent2 = myexponent2;
significandParts()[0] = mysignificand;
significandParts()[1] = mysignificand2;
} else {
category = fcNormal;
exponent = myexponent - 1023;
exponent2 = myexponent2 - 1023;
significandParts()[0] = mysignificand;
significandParts()[1] = mysignificand2;
if (myexponent==0) exponent = -1022;
else
significandParts()[0] |= 0x10000000000000LL; if (myexponent2==0)
exponent2 = -1022;
else
significandParts()[1] |= 0x10000000000000LL; }
}
void
APFloat::initFromDoubleAPInt(const APInt &api)
{
assert(api.getBitWidth()==64);
uint64_t i = *api.getRawData();
uint64_t myexponent = (i >> 52) & 0x7ff;
uint64_t mysignificand = i & 0xfffffffffffffLL;
initialize(&APFloat::IEEEdouble);
assert(partCount()==1);
sign = static_cast<unsigned int>(i>>63);
if (myexponent==0 && mysignificand==0) {
category = fcZero;
} else if (myexponent==0x7ff && mysignificand==0) {
category = fcInfinity;
} else if (myexponent==0x7ff && mysignificand!=0) {
category = fcNaN;
*significandParts() = mysignificand;
} else {
category = fcNormal;
exponent = myexponent - 1023;
*significandParts() = mysignificand;
if (myexponent==0) exponent = -1022;
else
*significandParts() |= 0x10000000000000LL; }
}
void
APFloat::initFromFloatAPInt(const APInt & api)
{
assert(api.getBitWidth()==32);
uint32_t i = (uint32_t)*api.getRawData();
uint32_t myexponent = (i >> 23) & 0xff;
uint32_t mysignificand = i & 0x7fffff;
initialize(&APFloat::IEEEsingle);
assert(partCount()==1);
sign = i >> 31;
if (myexponent==0 && mysignificand==0) {
category = fcZero;
} else if (myexponent==0xff && mysignificand==0) {
category = fcInfinity;
} else if (myexponent==0xff && mysignificand!=0) {
category = fcNaN;
*significandParts() = mysignificand;
} else {
category = fcNormal;
exponent = myexponent - 127; *significandParts() = mysignificand;
if (myexponent==0) exponent = -126;
else
*significandParts() |= 0x800000; }
}
void
APFloat::initFromAPInt(const APInt& api, bool isIEEE)
{
if (api.getBitWidth() == 32)
return initFromFloatAPInt(api);
else if (api.getBitWidth()==64)
return initFromDoubleAPInt(api);
else if (api.getBitWidth()==80)
return initFromF80LongDoubleAPInt(api);
else if (api.getBitWidth()==128 && !isIEEE)
return initFromPPCDoubleDoubleAPInt(api);
else
assert(0);
}
APFloat::APFloat(const APInt& api, bool isIEEE)
{
initFromAPInt(api, isIEEE);
}
APFloat::APFloat(float f)
{
APInt api = APInt(32, 0);
initFromAPInt(api.floatToBits(f));
}
APFloat::APFloat(double d)
{
APInt api = APInt(64, 0);
initFromAPInt(api.doubleToBits(d));
}