#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <cstring>
#include <limits.h>
#define APFLOAT_DISPATCH_ON_SEMANTICS(METHOD_CALL) \
do { \
if (usesLayout<IEEEFloat>(getSemantics())) \
return U.IEEE.METHOD_CALL; \
if (usesLayout<DoubleAPFloat>(getSemantics())) \
return U.Double.METHOD_CALL; \
llvm_unreachable("Unexpected semantics"); \
} while (false)
using namespace llvm;
#define PackCategoriesIntoKey(_lhs, _rhs) ((_lhs) * 4 + (_rhs))
static_assert(APFloatBase::integerPartWidth % 4 == 0, "Part width must be divisible by 4!");
namespace llvm {
struct fltSemantics {
APFloatBase::ExponentType maxExponent;
APFloatBase::ExponentType minExponent;
unsigned int precision;
unsigned int sizeInBits;
bool isRepresentableBy(const fltSemantics &S) const {
return maxExponent <= S.maxExponent && minExponent >= S.minExponent &&
precision <= S.precision;
}
};
static const fltSemantics semIEEEhalf = {15, -14, 11, 16};
static const fltSemantics semBFloat = {127, -126, 8, 16};
static const fltSemantics semIEEEsingle = {127, -126, 24, 32};
static const fltSemantics semIEEEdouble = {1023, -1022, 53, 64};
static const fltSemantics semIEEEquad = {16383, -16382, 113, 128};
static const fltSemantics semX87DoubleExtended = {16383, -16382, 64, 80};
static const fltSemantics semBogus = {0, 0, 0, 0};
static const fltSemantics semPPCDoubleDouble = {-1, 0, 0, 128};
static const fltSemantics semPPCDoubleDoubleLegacy = {1023, -1022 + 53,
53 + 53, 128};
const llvm::fltSemantics &APFloatBase::EnumToSemantics(Semantics S) {
switch (S) {
case S_IEEEhalf:
return IEEEhalf();
case S_BFloat:
return BFloat();
case S_IEEEsingle:
return IEEEsingle();
case S_IEEEdouble:
return IEEEdouble();
case S_x87DoubleExtended:
return x87DoubleExtended();
case S_IEEEquad:
return IEEEquad();
case S_PPCDoubleDouble:
return PPCDoubleDouble();
}
llvm_unreachable("Unrecognised floating semantics");
}
APFloatBase::Semantics
APFloatBase::SemanticsToEnum(const llvm::fltSemantics &Sem) {
if (&Sem == &llvm::APFloat::IEEEhalf())
return S_IEEEhalf;
else if (&Sem == &llvm::APFloat::BFloat())
return S_BFloat;
else if (&Sem == &llvm::APFloat::IEEEsingle())
return S_IEEEsingle;
else if (&Sem == &llvm::APFloat::IEEEdouble())
return S_IEEEdouble;
else if (&Sem == &llvm::APFloat::x87DoubleExtended())
return S_x87DoubleExtended;
else if (&Sem == &llvm::APFloat::IEEEquad())
return S_IEEEquad;
else if (&Sem == &llvm::APFloat::PPCDoubleDouble())
return S_PPCDoubleDouble;
else
llvm_unreachable("Unknown floating semantics");
}
const fltSemantics &APFloatBase::IEEEhalf() {
return semIEEEhalf;
}
const fltSemantics &APFloatBase::BFloat() {
return semBFloat;
}
const fltSemantics &APFloatBase::IEEEsingle() {
return semIEEEsingle;
}
const fltSemantics &APFloatBase::IEEEdouble() {
return semIEEEdouble;
}
const fltSemantics &APFloatBase::IEEEquad() {
return semIEEEquad;
}
const fltSemantics &APFloatBase::x87DoubleExtended() {
return semX87DoubleExtended;
}
const fltSemantics &APFloatBase::Bogus() {
return semBogus;
}
const fltSemantics &APFloatBase::PPCDoubleDouble() {
return semPPCDoubleDouble;
}
constexpr RoundingMode APFloatBase::rmNearestTiesToEven;
constexpr RoundingMode APFloatBase::rmTowardPositive;
constexpr RoundingMode APFloatBase::rmTowardNegative;
constexpr RoundingMode APFloatBase::rmTowardZero;
constexpr RoundingMode APFloatBase::rmNearestTiesToAway;
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 * APFloatBase::integerPartWidth));
unsigned int APFloatBase::semanticsPrecision(const fltSemantics &semantics) {
return semantics.precision;
}
APFloatBase::ExponentType
APFloatBase::semanticsMaxExponent(const fltSemantics &semantics) {
return semantics.maxExponent;
}
APFloatBase::ExponentType
APFloatBase::semanticsMinExponent(const fltSemantics &semantics) {
return semantics.minExponent;
}
unsigned int APFloatBase::semanticsSizeInBits(const fltSemantics &semantics) {
return semantics.sizeInBits;
}
unsigned APFloatBase::getSizeInBits(const fltSemantics &Sem) {
return Sem.sizeInBits;
}
static inline Error createError(const Twine &Err) {
return make_error<StringError>(Err, inconvertibleErrorCode());
}
static inline unsigned int
partCountForBits(unsigned int bits)
{
return ((bits) + APFloatBase::integerPartWidth - 1) / APFloatBase::integerPartWidth;
}
static inline unsigned int
decDigitValue(unsigned int c)
{
return c - '0';
}
static Expected<int> readExponent(StringRef::iterator begin,
StringRef::iterator end) {
bool isNegative;
unsigned int absExponent;
const unsigned int overlargeExponent = 24000;
StringRef::iterator p = begin;
if (p == end || ((*p == '-' || *p == '+') && (p + 1) == end)) {
return 0;
}
isNegative = (*p == '-');
if (*p == '-' || *p == '+') {
p++;
if (p == end)
return createError("Exponent has no digits");
}
absExponent = decDigitValue(*p++);
if (absExponent >= 10U)
return createError("Invalid character in exponent");
for (; p != end; ++p) {
unsigned int value;
value = decDigitValue(*p);
if (value >= 10U)
return createError("Invalid character in exponent");
absExponent = absExponent * 10U + value;
if (absExponent >= overlargeExponent) {
absExponent = overlargeExponent;
break;
}
}
if (isNegative)
return -(int) absExponent;
else
return (int) absExponent;
}
static Expected<int> totalExponent(StringRef::iterator p,
StringRef::iterator end,
int exponentAdjustment) {
int unsignedExponent;
bool negative, overflow;
int exponent = 0;
if (p == end)
return createError("Exponent has no digits");
negative = *p == '-';
if (*p == '-' || *p == '+') {
p++;
if (p == end)
return createError("Exponent has no digits");
}
unsignedExponent = 0;
overflow = false;
for (; p != end; ++p) {
unsigned int value;
value = decDigitValue(*p);
if (value >= 10U)
return createError("Invalid character in exponent");
unsignedExponent = unsignedExponent * 10 + value;
if (unsignedExponent > 32767) {
overflow = true;
break;
}
}
if (exponentAdjustment > 32767 || exponentAdjustment < -32768)
overflow = true;
if (!overflow) {
exponent = unsignedExponent;
if (negative)
exponent = -exponent;
exponent += exponentAdjustment;
if (exponent > 32767 || exponent < -32768)
overflow = true;
}
if (overflow)
exponent = negative ? -32768: 32767;
return exponent;
}
static Expected<StringRef::iterator>
skipLeadingZeroesAndAnyDot(StringRef::iterator begin, StringRef::iterator end,
StringRef::iterator *dot) {
StringRef::iterator p = begin;
*dot = end;
while (p != end && *p == '0')
p++;
if (p != end && *p == '.') {
*dot = p++;
if (end - begin == 1)
return createError("Significand has no digits");
while (p != end && *p == '0')
p++;
}
return p;
}
struct decimalInfo {
const char *firstSigDigit;
const char *lastSigDigit;
int exponent;
int normalizedExponent;
};
static Error interpretDecimal(StringRef::iterator begin,
StringRef::iterator end, decimalInfo *D) {
StringRef::iterator dot = end;
auto PtrOrErr = skipLeadingZeroesAndAnyDot(begin, end, &dot);
if (!PtrOrErr)
return PtrOrErr.takeError();
StringRef::iterator p = *PtrOrErr;
D->firstSigDigit = p;
D->exponent = 0;
D->normalizedExponent = 0;
for (; p != end; ++p) {
if (*p == '.') {
if (dot != end)
return createError("String contains multiple dots");
dot = p++;
if (p == end)
break;
}
if (decDigitValue(*p) >= 10U)
break;
}
if (p != end) {
if (*p != 'e' && *p != 'E')
return createError("Invalid character in significand");
if (p == begin)
return createError("Significand has no digits");
if (dot != end && p - begin == 1)
return createError("Significand has no digits");
auto ExpOrErr = readExponent(p + 1, end);
if (!ExpOrErr)
return ExpOrErr.takeError();
D->exponent = *ExpOrErr;
if (dot == end)
dot = p;
}
if (p != D->firstSigDigit) {
if (p != begin) {
do
do
p--;
while (p != begin && *p == '0');
while (p != begin && *p == '.');
}
D->exponent += static_cast<APFloat::ExponentType>((dot - p) - (dot > p));
D->normalizedExponent = (D->exponent +
static_cast<APFloat::ExponentType>((p - D->firstSigDigit)
- (dot > D->firstSigDigit && dot < p)));
}
D->lastSigDigit = p;
return Error::success();
}
static Expected<lostFraction>
trailingHexadecimalFraction(StringRef::iterator p, StringRef::iterator end,
unsigned int digitValue) {
unsigned int hexDigit;
if (digitValue > 8)
return lfMoreThanHalf;
else if (digitValue < 8 && digitValue > 0)
return lfLessThanHalf;
while (p != end && (*p == '0' || *p == '.'))
p++;
if (p == end)
return createError("Invalid trailing hexadecimal fraction!");
hexDigit = hexDigitValue(*p);
if (hexDigit == -1U)
return digitValue == 0 ? lfExactlyZero: lfExactlyHalf;
else
return digitValue == 0 ? lfLessThanHalf: lfMoreThanHalf;
}
static lostFraction
lostFractionThroughTruncation(const APFloatBase::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 * APFloatBase::integerPartWidth &&
APInt::tcExtractBit(parts, bits - 1))
return lfMoreThanHalf;
return lfLessThanHalf;
}
static lostFraction
shiftRight(APFloatBase::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 APFloatBase::integerPart
ulpsFromBoundary(const APFloatBase::integerPart *parts, unsigned int bits,
bool isNearest) {
unsigned int count, partBits;
APFloatBase::integerPart part, boundary;
assert(bits != 0);
bits--;
count = bits / APFloatBase::integerPartWidth;
partBits = bits % APFloatBase::integerPartWidth + 1;
part = parts[count] & (~(APFloatBase::integerPart) 0 >> (APFloatBase::integerPartWidth - partBits));
if (isNearest)
boundary = (APFloatBase::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 ~(APFloatBase::integerPart) 0;
return parts[0];
} else if (part == boundary - 1) {
while (--count)
if (~parts[count])
return ~(APFloatBase::integerPart) 0;
return -parts[0];
}
return ~(APFloatBase::integerPart) 0;
}
static unsigned int
powerOf5(APFloatBase::integerPart *dst, unsigned int power) {
static const APFloatBase::integerPart firstEightPowers[] = { 1, 5, 25, 125, 625, 3125, 15625, 78125 };
APFloatBase::integerPart pow5s[maxPowerOfFiveParts * 2 + 5];
pow5s[0] = 78125 * 5;
unsigned int partsCount[16] = { 1 };
APFloatBase::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) {
APFloatBase::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, APFloatBase::integerPart part, unsigned int count,
const char *hexDigitChars)
{
unsigned int result = count;
assert(count != 0 && count <= APFloatBase::integerPartWidth / 4);
part >>= (APFloatBase::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;
}
namespace detail {
void IEEEFloat::initialize(const fltSemantics *ourSemantics) {
unsigned int count;
semantics = ourSemantics;
count = partCount();
if (count > 1)
significand.parts = new integerPart[count];
}
void IEEEFloat::freeSignificand() {
if (needsCleanup())
delete [] significand.parts;
}
void IEEEFloat::assign(const IEEEFloat &rhs) {
assert(semantics == rhs.semantics);
sign = rhs.sign;
category = rhs.category;
exponent = rhs.exponent;
if (isFiniteNonZero() || category == fcNaN)
copySignificand(rhs);
}
void IEEEFloat::copySignificand(const IEEEFloat &rhs) {
assert(isFiniteNonZero() || category == fcNaN);
assert(rhs.partCount() >= partCount());
APInt::tcAssign(significandParts(), rhs.significandParts(),
partCount());
}
void IEEEFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill) {
category = fcNaN;
sign = Negative;
exponent = exponentNaN();
integerPart *significand = significandParts();
unsigned numParts = partCount();
if (!fill || fill->getNumWords() < numParts)
APInt::tcSet(significand, 0, numParts);
if (fill) {
APInt::tcAssign(significand, fill->getRawData(),
std::min(fill->getNumWords(), numParts));
unsigned bitsToPreserve = semantics->precision - 1;
unsigned part = bitsToPreserve / 64;
bitsToPreserve %= 64;
significand[part] &= ((1ULL << bitsToPreserve) - 1);
for (part++; part != numParts; ++part)
significand[part] = 0;
}
unsigned QNaNBit = semantics->precision - 2;
if (SNaN) {
APInt::tcClearBit(significand, QNaNBit);
if (APInt::tcIsZero(significand, numParts))
APInt::tcSetBit(significand, QNaNBit - 1);
} else {
APInt::tcSetBit(significand, QNaNBit);
}
if (semantics == &semX87DoubleExtended)
APInt::tcSetBit(significand, QNaNBit + 1);
}
IEEEFloat &IEEEFloat::operator=(const IEEEFloat &rhs) {
if (this != &rhs) {
if (semantics != rhs.semantics) {
freeSignificand();
initialize(rhs.semantics);
}
assign(rhs);
}
return *this;
}
IEEEFloat &IEEEFloat::operator=(IEEEFloat &&rhs) {
freeSignificand();
semantics = rhs.semantics;
significand = rhs.significand;
exponent = rhs.exponent;
category = rhs.category;
sign = rhs.sign;
rhs.semantics = &semBogus;
return *this;
}
bool IEEEFloat::isDenormal() const {
return isFiniteNonZero() && (exponent == semantics->minExponent) &&
(APInt::tcExtractBit(significandParts(),
semantics->precision - 1) == 0);
}
bool IEEEFloat::isSmallest() const {
return isFiniteNonZero() && exponent == semantics->minExponent &&
significandMSB() == 0;
}
bool IEEEFloat::isSignificandAllOnes() const {
const integerPart *Parts = significandParts();
const unsigned PartCount = partCountForBits(semantics->precision);
for (unsigned i = 0; i < PartCount - 1; i++)
if (~Parts[i])
return false;
const unsigned NumHighBits =
PartCount*integerPartWidth - semantics->precision + 1;
assert(NumHighBits <= integerPartWidth && NumHighBits > 0 &&
"Can not have more high bits to fill than integerPartWidth");
const integerPart HighBitFill =
~integerPart(0) << (integerPartWidth - NumHighBits);
if (~(Parts[PartCount - 1] | HighBitFill))
return false;
return true;
}
bool IEEEFloat::isSignificandAllZeros() const {
const integerPart *Parts = significandParts();
const unsigned PartCount = partCountForBits(semantics->precision);
for (unsigned i = 0; i < PartCount - 1; i++)
if (Parts[i])
return false;
const unsigned NumHighBits =
PartCount*integerPartWidth - semantics->precision + 1;
assert(NumHighBits < integerPartWidth && "Can not have more high bits to "
"clear than integerPartWidth");
const integerPart HighBitMask = ~integerPart(0) >> NumHighBits;
if (Parts[PartCount - 1] & HighBitMask)
return false;
return true;
}
bool IEEEFloat::isLargest() const {
return isFiniteNonZero() && exponent == semantics->maxExponent
&& isSignificandAllOnes();
}
bool IEEEFloat::isInteger() const {
if (!isFinite()) return false;
IEEEFloat truncated = *this;
truncated.roundToIntegral(rmTowardZero);
return compare(truncated) == cmpEqual;
}
bool IEEEFloat::bitwiseIsEqual(const IEEEFloat &rhs) const {
if (this == &rhs)
return true;
if (semantics != rhs.semantics ||
category != rhs.category ||
sign != rhs.sign)
return false;
if (category==fcZero || category==fcInfinity)
return true;
if (isFiniteNonZero() && exponent != rhs.exponent)
return false;
return std::equal(significandParts(), significandParts() + partCount(),
rhs.significandParts());
}
IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics, integerPart value) {
initialize(&ourSemantics);
sign = 0;
category = fcNormal;
zeroSignificand();
exponent = ourSemantics.precision - 1;
significandParts()[0] = value;
normalize(rmNearestTiesToEven, lfExactlyZero);
}
IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics) {
initialize(&ourSemantics);
makeZero(false);
}
IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics, uninitializedTag tag)
: IEEEFloat(ourSemantics) {}
IEEEFloat::IEEEFloat(const IEEEFloat &rhs) {
initialize(rhs.semantics);
assign(rhs);
}
IEEEFloat::IEEEFloat(IEEEFloat &&rhs) : semantics(&semBogus) {
*this = std::move(rhs);
}
IEEEFloat::~IEEEFloat() { freeSignificand(); }
unsigned int IEEEFloat::partCount() const {
return partCountForBits(semantics->precision + 1);
}
const IEEEFloat::integerPart *IEEEFloat::significandParts() const {
return const_cast<IEEEFloat *>(this)->significandParts();
}
IEEEFloat::integerPart *IEEEFloat::significandParts() {
if (partCount() > 1)
return significand.parts;
else
return &significand.part;
}
void IEEEFloat::zeroSignificand() {
APInt::tcSet(significandParts(), 0, partCount());
}
void IEEEFloat::incrementSignificand() {
integerPart carry;
carry = APInt::tcIncrement(significandParts(), partCount());
assert(carry == 0);
(void)carry;
}
IEEEFloat::integerPart IEEEFloat::addSignificand(const IEEEFloat &rhs) {
integerPart *parts;
parts = significandParts();
assert(semantics == rhs.semantics);
assert(exponent == rhs.exponent);
return APInt::tcAdd(parts, rhs.significandParts(), 0, partCount());
}
IEEEFloat::integerPart IEEEFloat::subtractSignificand(const IEEEFloat &rhs,
integerPart borrow) {
integerPart *parts;
parts = significandParts();
assert(semantics == rhs.semantics);
assert(exponent == rhs.exponent);
return APInt::tcSubtract(parts, rhs.significandParts(), borrow,
partCount());
}
lostFraction IEEEFloat::multiplySignificand(const IEEEFloat &rhs,
IEEEFloat 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 + 1);
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;
exponent += 2;
if (addend.isNonZero()) {
Significand savedSignificand = significand;
const fltSemantics *savedSemantics = semantics;
fltSemantics extendedSemantics;
opStatus status;
unsigned int extendedPrecision;
extendedPrecision = 2 * precision + 1;
if (omsb != extendedPrecision - 1) {
assert(extendedPrecision > omsb);
APInt::tcShiftLeft(fullSignificand, newPartsCount,
(extendedPrecision - 1) - omsb);
exponent -= (extendedPrecision - 1) - omsb;
}
extendedSemantics = *semantics;
extendedSemantics.precision = extendedPrecision;
if (newPartsCount == 1)
significand.part = fullSignificand[0];
else
significand.parts = fullSignificand;
semantics = &extendedSemantics;
IEEEFloat extendedAddend(addend);
status = extendedAddend.convert(extendedSemantics, rmTowardZero, &ignored);
assert(status == opOK);
(void)status;
lost_fraction = extendedAddend.shiftSignificandRight(1);
assert(lost_fraction == lfExactlyZero &&
"Lost precision while shifting addend for fused-multiply-add.");
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 IEEEFloat::multiplySignificand(const IEEEFloat &rhs) {
return multiplySignificand(rhs, IEEEFloat(*semantics));
}
lostFraction IEEEFloat::divideSignificand(const IEEEFloat &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 IEEEFloat::significandMSB() const {
return APInt::tcMSB(significandParts(), partCount());
}
unsigned int IEEEFloat::significandLSB() const {
return APInt::tcLSB(significandParts(), partCount());
}
lostFraction IEEEFloat::shiftSignificandRight(unsigned int bits) {
assert((ExponentType) (exponent + bits) >= exponent);
exponent += bits;
return shiftRight(significandParts(), partCount(), bits);
}
void IEEEFloat::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));
}
}
IEEEFloat::cmpResult
IEEEFloat::compareAbsoluteValue(const IEEEFloat &rhs) const {
int compare;
assert(semantics == rhs.semantics);
assert(isFiniteNonZero());
assert(rhs.isFiniteNonZero());
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;
}
static void tcSetLeastSignificantBits(APInt::WordType *dst, unsigned parts,
unsigned bits) {
unsigned i = 0;
while (bits > APInt::APINT_BITS_PER_WORD) {
dst[i++] = ~(APInt::WordType)0;
bits -= APInt::APINT_BITS_PER_WORD;
}
if (bits)
dst[i++] = ~(APInt::WordType)0 >> (APInt::APINT_BITS_PER_WORD - bits);
while (i < parts)
dst[i++] = 0;
}
IEEEFloat::opStatus IEEEFloat::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;
tcSetLeastSignificantBits(significandParts(), partCount(),
semantics->precision);
return opInexact;
}
bool IEEEFloat::roundAwayFromZero(roundingMode rounding_mode,
lostFraction lost_fraction,
unsigned int bit) const {
assert(isFiniteNonZero() || category == fcZero);
assert(lost_fraction != lfExactlyZero);
switch (rounding_mode) {
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;
case rmTowardNegative:
return sign;
default:
break;
}
llvm_unreachable("Invalid rounding mode found");
}
IEEEFloat::opStatus IEEEFloat::normalize(roundingMode rounding_mode,
lostFraction lost_fraction) {
unsigned int omsb;
int exponentChange;
if (!isFiniteNonZero())
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);
}
IEEEFloat::opStatus IEEEFloat::addOrSubtractSpecials(const IEEEFloat &rhs,
bool subtract) {
switch (PackCategoriesIntoKey(category, rhs.category)) {
default:
llvm_unreachable(nullptr);
case PackCategoriesIntoKey(fcZero, fcNaN):
case PackCategoriesIntoKey(fcNormal, fcNaN):
case PackCategoriesIntoKey(fcInfinity, fcNaN):
assign(rhs);
LLVM_FALLTHROUGH;
case PackCategoriesIntoKey(fcNaN, fcZero):
case PackCategoriesIntoKey(fcNaN, fcNormal):
case PackCategoriesIntoKey(fcNaN, fcInfinity):
case PackCategoriesIntoKey(fcNaN, fcNaN):
if (isSignaling()) {
makeQuiet();
return opInvalidOp;
}
return rhs.isSignaling() ? opInvalidOp : opOK;
case PackCategoriesIntoKey(fcNormal, fcZero):
case PackCategoriesIntoKey(fcInfinity, fcNormal):
case PackCategoriesIntoKey(fcInfinity, fcZero):
return opOK;
case PackCategoriesIntoKey(fcNormal, fcInfinity):
case PackCategoriesIntoKey(fcZero, fcInfinity):
category = fcInfinity;
sign = rhs.sign ^ subtract;
return opOK;
case PackCategoriesIntoKey(fcZero, fcNormal):
assign(rhs);
sign = rhs.sign ^ subtract;
return opOK;
case PackCategoriesIntoKey(fcZero, fcZero):
return opOK;
case PackCategoriesIntoKey(fcInfinity, fcInfinity):
if (((sign ^ rhs.sign)!=0) != subtract) {
makeNaN();
return opInvalidOp;
}
return opOK;
case PackCategoriesIntoKey(fcNormal, fcNormal):
return opDivByZero;
}
}
lostFraction IEEEFloat::addOrSubtractSignificand(const IEEEFloat &rhs,
bool subtract) {
integerPart carry;
lostFraction lost_fraction;
int bits;
subtract ^= static_cast<bool>(sign ^ rhs.sign);
bits = exponent - rhs.exponent;
if (subtract) {
IEEEFloat temp_rhs(rhs);
if (bits == 0)
lost_fraction = lfExactlyZero;
else if (bits > 0) {
lost_fraction = temp_rhs.shiftSignificandRight(bits - 1);
shiftSignificandLeft(1);
} else {
lost_fraction = shiftSignificandRight(-bits - 1);
temp_rhs.shiftSignificandLeft(1);
}
if (compareAbsoluteValue(temp_rhs) == cmpLessThan) {
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);
(void)carry;
} else {
if (bits > 0) {
IEEEFloat temp_rhs(rhs);
lost_fraction = temp_rhs.shiftSignificandRight(bits);
carry = addSignificand(temp_rhs);
} else {
lost_fraction = shiftSignificandRight(-bits);
carry = addSignificand(rhs);
}
assert(!carry);
(void)carry;
}
return lost_fraction;
}
IEEEFloat::opStatus IEEEFloat::multiplySpecials(const IEEEFloat &rhs) {
switch (PackCategoriesIntoKey(category, rhs.category)) {
default:
llvm_unreachable(nullptr);
case PackCategoriesIntoKey(fcZero, fcNaN):
case PackCategoriesIntoKey(fcNormal, fcNaN):
case PackCategoriesIntoKey(fcInfinity, fcNaN):
assign(rhs);
sign = false;
LLVM_FALLTHROUGH;
case PackCategoriesIntoKey(fcNaN, fcZero):
case PackCategoriesIntoKey(fcNaN, fcNormal):
case PackCategoriesIntoKey(fcNaN, fcInfinity):
case PackCategoriesIntoKey(fcNaN, fcNaN):
sign ^= rhs.sign; if (isSignaling()) {
makeQuiet();
return opInvalidOp;
}
return rhs.isSignaling() ? opInvalidOp : opOK;
case PackCategoriesIntoKey(fcNormal, fcInfinity):
case PackCategoriesIntoKey(fcInfinity, fcNormal):
case PackCategoriesIntoKey(fcInfinity, fcInfinity):
category = fcInfinity;
return opOK;
case PackCategoriesIntoKey(fcZero, fcNormal):
case PackCategoriesIntoKey(fcNormal, fcZero):
case PackCategoriesIntoKey(fcZero, fcZero):
category = fcZero;
return opOK;
case PackCategoriesIntoKey(fcZero, fcInfinity):
case PackCategoriesIntoKey(fcInfinity, fcZero):
makeNaN();
return opInvalidOp;
case PackCategoriesIntoKey(fcNormal, fcNormal):
return opOK;
}
}
IEEEFloat::opStatus IEEEFloat::divideSpecials(const IEEEFloat &rhs) {
switch (PackCategoriesIntoKey(category, rhs.category)) {
default:
llvm_unreachable(nullptr);
case PackCategoriesIntoKey(fcZero, fcNaN):
case PackCategoriesIntoKey(fcNormal, fcNaN):
case PackCategoriesIntoKey(fcInfinity, fcNaN):
assign(rhs);
sign = false;
LLVM_FALLTHROUGH;
case PackCategoriesIntoKey(fcNaN, fcZero):
case PackCategoriesIntoKey(fcNaN, fcNormal):
case PackCategoriesIntoKey(fcNaN, fcInfinity):
case PackCategoriesIntoKey(fcNaN, fcNaN):
sign ^= rhs.sign; if (isSignaling()) {
makeQuiet();
return opInvalidOp;
}
return rhs.isSignaling() ? opInvalidOp : opOK;
case PackCategoriesIntoKey(fcInfinity, fcZero):
case PackCategoriesIntoKey(fcInfinity, fcNormal):
case PackCategoriesIntoKey(fcZero, fcInfinity):
case PackCategoriesIntoKey(fcZero, fcNormal):
return opOK;
case PackCategoriesIntoKey(fcNormal, fcInfinity):
category = fcZero;
return opOK;
case PackCategoriesIntoKey(fcNormal, fcZero):
category = fcInfinity;
return opDivByZero;
case PackCategoriesIntoKey(fcInfinity, fcInfinity):
case PackCategoriesIntoKey(fcZero, fcZero):
makeNaN();
return opInvalidOp;
case PackCategoriesIntoKey(fcNormal, fcNormal):
return opOK;
}
}
IEEEFloat::opStatus IEEEFloat::modSpecials(const IEEEFloat &rhs) {
switch (PackCategoriesIntoKey(category, rhs.category)) {
default:
llvm_unreachable(nullptr);
case PackCategoriesIntoKey(fcZero, fcNaN):
case PackCategoriesIntoKey(fcNormal, fcNaN):
case PackCategoriesIntoKey(fcInfinity, fcNaN):
assign(rhs);
LLVM_FALLTHROUGH;
case PackCategoriesIntoKey(fcNaN, fcZero):
case PackCategoriesIntoKey(fcNaN, fcNormal):
case PackCategoriesIntoKey(fcNaN, fcInfinity):
case PackCategoriesIntoKey(fcNaN, fcNaN):
if (isSignaling()) {
makeQuiet();
return opInvalidOp;
}
return rhs.isSignaling() ? opInvalidOp : opOK;
case PackCategoriesIntoKey(fcZero, fcInfinity):
case PackCategoriesIntoKey(fcZero, fcNormal):
case PackCategoriesIntoKey(fcNormal, fcInfinity):
return opOK;
case PackCategoriesIntoKey(fcNormal, fcZero):
case PackCategoriesIntoKey(fcInfinity, fcZero):
case PackCategoriesIntoKey(fcInfinity, fcNormal):
case PackCategoriesIntoKey(fcInfinity, fcInfinity):
case PackCategoriesIntoKey(fcZero, fcZero):
makeNaN();
return opInvalidOp;
case PackCategoriesIntoKey(fcNormal, fcNormal):
return opOK;
}
}
IEEEFloat::opStatus IEEEFloat::remainderSpecials(const IEEEFloat &rhs) {
switch (PackCategoriesIntoKey(category, rhs.category)) {
default:
llvm_unreachable(nullptr);
case PackCategoriesIntoKey(fcZero, fcNaN):
case PackCategoriesIntoKey(fcNormal, fcNaN):
case PackCategoriesIntoKey(fcInfinity, fcNaN):
assign(rhs);
LLVM_FALLTHROUGH;
case PackCategoriesIntoKey(fcNaN, fcZero):
case PackCategoriesIntoKey(fcNaN, fcNormal):
case PackCategoriesIntoKey(fcNaN, fcInfinity):
case PackCategoriesIntoKey(fcNaN, fcNaN):
if (isSignaling()) {
makeQuiet();
return opInvalidOp;
}
return rhs.isSignaling() ? opInvalidOp : opOK;
case PackCategoriesIntoKey(fcZero, fcInfinity):
case PackCategoriesIntoKey(fcZero, fcNormal):
case PackCategoriesIntoKey(fcNormal, fcInfinity):
return opOK;
case PackCategoriesIntoKey(fcNormal, fcZero):
case PackCategoriesIntoKey(fcInfinity, fcZero):
case PackCategoriesIntoKey(fcInfinity, fcNormal):
case PackCategoriesIntoKey(fcInfinity, fcInfinity):
case PackCategoriesIntoKey(fcZero, fcZero):
makeNaN();
return opInvalidOp;
case PackCategoriesIntoKey(fcNormal, fcNormal):
return opDivByZero; }
}
void IEEEFloat::changeSign() {
sign = !sign;
}
IEEEFloat::opStatus IEEEFloat::addOrSubtract(const IEEEFloat &rhs,
roundingMode rounding_mode,
bool subtract) {
opStatus fs;
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;
}
IEEEFloat::opStatus IEEEFloat::add(const IEEEFloat &rhs,
roundingMode rounding_mode) {
return addOrSubtract(rhs, rounding_mode, false);
}
IEEEFloat::opStatus IEEEFloat::subtract(const IEEEFloat &rhs,
roundingMode rounding_mode) {
return addOrSubtract(rhs, rounding_mode, true);
}
IEEEFloat::opStatus IEEEFloat::multiply(const IEEEFloat &rhs,
roundingMode rounding_mode) {
opStatus fs;
sign ^= rhs.sign;
fs = multiplySpecials(rhs);
if (isFiniteNonZero()) {
lostFraction lost_fraction = multiplySignificand(rhs);
fs = normalize(rounding_mode, lost_fraction);
if (lost_fraction != lfExactlyZero)
fs = (opStatus) (fs | opInexact);
}
return fs;
}
IEEEFloat::opStatus IEEEFloat::divide(const IEEEFloat &rhs,
roundingMode rounding_mode) {
opStatus fs;
sign ^= rhs.sign;
fs = divideSpecials(rhs);
if (isFiniteNonZero()) {
lostFraction lost_fraction = divideSignificand(rhs);
fs = normalize(rounding_mode, lost_fraction);
if (lost_fraction != lfExactlyZero)
fs = (opStatus) (fs | opInexact);
}
return fs;
}
IEEEFloat::opStatus IEEEFloat::remainder(const IEEEFloat &rhs) {
opStatus fs;
unsigned int origSign = sign;
fs = remainderSpecials(rhs);
if (fs != opDivByZero)
return fs;
fs = opOK;
IEEEFloat P2 = rhs;
if (P2.add(rhs, rmNearestTiesToEven) == opOK) {
fs = mod(P2);
assert(fs == opOK);
}
IEEEFloat P = rhs;
P.sign = false;
sign = false;
bool losesInfo;
fltSemantics extendedSemantics = *semantics;
extendedSemantics.maxExponent++;
extendedSemantics.minExponent--;
extendedSemantics.precision += 2;
IEEEFloat VEx = *this;
fs = VEx.convert(extendedSemantics, rmNearestTiesToEven, &losesInfo);
assert(fs == opOK && !losesInfo);
IEEEFloat PEx = P;
fs = PEx.convert(extendedSemantics, rmNearestTiesToEven, &losesInfo);
assert(fs == opOK && !losesInfo);
fs = VEx.add(VEx, rmNearestTiesToEven);
assert(fs == opOK);
if (VEx.compare(PEx) == cmpGreaterThan) {
fs = subtract(P, rmNearestTiesToEven);
assert(fs == opOK);
fs = VEx.subtract(PEx, rmNearestTiesToEven);
assert(fs == opOK);
fs = VEx.subtract(PEx, rmNearestTiesToEven);
assert(fs == opOK);
cmpResult result = VEx.compare(PEx);
if (result == cmpGreaterThan || result == cmpEqual) {
fs = subtract(P, rmNearestTiesToEven);
assert(fs == opOK);
}
}
if (isZero())
sign = origSign; else
sign ^= origSign;
return fs;
}
IEEEFloat::opStatus IEEEFloat::mod(const IEEEFloat &rhs) {
opStatus fs;
fs = modSpecials(rhs);
unsigned int origSign = sign;
while (isFiniteNonZero() && rhs.isFiniteNonZero() &&
compareAbsoluteValue(rhs) != cmpLessThan) {
IEEEFloat V = scalbn(rhs, ilogb(*this) - ilogb(rhs), rmNearestTiesToEven);
if (compareAbsoluteValue(V) == cmpLessThan)
V = scalbn(V, -1, rmNearestTiesToEven);
V.sign = sign;
fs = subtract(V, rmNearestTiesToEven);
assert(fs==opOK);
}
if (isZero())
sign = origSign; return fs;
}
IEEEFloat::opStatus IEEEFloat::fusedMultiplyAdd(const IEEEFloat &multiplicand,
const IEEEFloat &addend,
roundingMode rounding_mode) {
opStatus fs;
sign ^= multiplicand.sign;
if (isFiniteNonZero() &&
multiplicand.isFiniteNonZero() &&
addend.isFinite()) {
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 && !(fs & opUnderflow) && sign != addend.sign)
sign = (rounding_mode == rmTowardNegative);
} else {
fs = multiplySpecials(multiplicand);
if (fs == opOK)
fs = addOrSubtract(addend, rounding_mode, false);
}
return fs;
}
IEEEFloat::opStatus IEEEFloat::roundToIntegral(roundingMode rounding_mode) {
opStatus fs;
if (isInfinity())
return opOK;
if (isNaN()) {
if (isSignaling()) {
makeQuiet();
return opInvalidOp;
} else {
return opOK;
}
}
if (isZero()) {
return opOK;
}
if (exponent+1 >= (int)semanticsPrecision(*semantics))
return opOK;
APInt IntegerConstant(NextPowerOf2(semanticsPrecision(*semantics)), 1);
IntegerConstant <<= semanticsPrecision(*semantics)-1;
IEEEFloat MagicConstant(*semantics);
fs = MagicConstant.convertFromAPInt(IntegerConstant, false,
rmNearestTiesToEven);
assert(fs == opOK);
MagicConstant.sign = sign;
bool inputSign = isNegative();
fs = add(MagicConstant, rounding_mode);
subtract(MagicConstant, rounding_mode);
if (inputSign != isNegative())
changeSign();
return fs;
}
IEEEFloat::cmpResult IEEEFloat::compare(const IEEEFloat &rhs) const {
cmpResult result;
assert(semantics == rhs.semantics);
switch (PackCategoriesIntoKey(category, rhs.category)) {
default:
llvm_unreachable(nullptr);
case PackCategoriesIntoKey(fcNaN, fcZero):
case PackCategoriesIntoKey(fcNaN, fcNormal):
case PackCategoriesIntoKey(fcNaN, fcInfinity):
case PackCategoriesIntoKey(fcNaN, fcNaN):
case PackCategoriesIntoKey(fcZero, fcNaN):
case PackCategoriesIntoKey(fcNormal, fcNaN):
case PackCategoriesIntoKey(fcInfinity, fcNaN):
return cmpUnordered;
case PackCategoriesIntoKey(fcInfinity, fcNormal):
case PackCategoriesIntoKey(fcInfinity, fcZero):
case PackCategoriesIntoKey(fcNormal, fcZero):
if (sign)
return cmpLessThan;
else
return cmpGreaterThan;
case PackCategoriesIntoKey(fcNormal, fcInfinity):
case PackCategoriesIntoKey(fcZero, fcInfinity):
case PackCategoriesIntoKey(fcZero, fcNormal):
if (rhs.sign)
return cmpGreaterThan;
else
return cmpLessThan;
case PackCategoriesIntoKey(fcInfinity, fcInfinity):
if (sign == rhs.sign)
return cmpEqual;
else if (sign)
return cmpLessThan;
else
return cmpGreaterThan;
case PackCategoriesIntoKey(fcZero, fcZero):
return cmpEqual;
case PackCategoriesIntoKey(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;
}
IEEEFloat::opStatus IEEEFloat::convert(const fltSemantics &toSemantics,
roundingMode rounding_mode,
bool *losesInfo) {
lostFraction lostFraction;
unsigned int newPartCount, oldPartCount;
opStatus fs;
int shift;
const fltSemantics &fromSemantics = *semantics;
lostFraction = lfExactlyZero;
newPartCount = partCountForBits(toSemantics.precision + 1);
oldPartCount = partCount();
shift = toSemantics.precision - fromSemantics.precision;
bool X86SpecialNan = false;
if (&fromSemantics == &semX87DoubleExtended &&
&toSemantics != &semX87DoubleExtended && category == fcNaN &&
(!(*significandParts() & 0x8000000000000000ULL) ||
!(*significandParts() & 0x4000000000000000ULL))) {
X86SpecialNan = true;
}
if (shift < 0 && isFiniteNonZero()) {
int omsb = significandMSB() + 1;
int exponentChange = omsb - fromSemantics.precision;
if (exponent + exponentChange < toSemantics.minExponent)
exponentChange = toSemantics.minExponent - exponent;
if (exponentChange < shift)
exponentChange = shift;
if (exponentChange < 0) {
shift -= exponentChange;
exponent += exponentChange;
} else if (omsb <= -shift) {
exponentChange = omsb + shift - 1; shift -= exponentChange;
exponent += exponentChange;
}
}
if (shift < 0 && (isFiniteNonZero() || category==fcNaN))
lostFraction = shiftRight(significandParts(), oldPartCount, -shift);
if (newPartCount > oldPartCount) {
integerPart *newParts;
newParts = new integerPart[newPartCount];
APInt::tcSet(newParts, 0, newPartCount);
if (isFiniteNonZero() || category==fcNaN)
APInt::tcAssign(newParts, significandParts(), oldPartCount);
freeSignificand();
significand.parts = newParts;
} else if (newPartCount == 1 && oldPartCount != 1) {
integerPart newPart = 0;
if (isFiniteNonZero() || category==fcNaN)
newPart = significandParts()[0];
freeSignificand();
significand.part = newPart;
}
semantics = &toSemantics;
if (shift > 0 && (isFiniteNonZero() || category==fcNaN))
APInt::tcShiftLeft(significandParts(), newPartCount, shift);
if (isFiniteNonZero()) {
fs = normalize(rounding_mode, lostFraction);
*losesInfo = (fs != opOK);
} else if (category == fcNaN) {
*losesInfo = lostFraction != lfExactlyZero || X86SpecialNan;
if (!X86SpecialNan && semantics == &semX87DoubleExtended)
APInt::tcSetBit(significandParts(), semantics->precision - 1);
if (isSignaling()) {
makeQuiet();
fs = opInvalidOp;
} else {
fs = opOK;
}
} else {
*losesInfo = false;
fs = opOK;
}
return fs;
}
IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger(
MutableArrayRef<integerPart> parts, unsigned int width, bool isSigned,
roundingMode rounding_mode, bool *isExact) const {
lostFraction lost_fraction;
const integerPart *src;
unsigned int dstPartsCount, truncatedBits;
*isExact = false;
if (category == fcInfinity || category == fcNaN)
return opInvalidOp;
dstPartsCount = partCountForBits(width);
assert(dstPartsCount <= parts.size() && "Integer too big");
if (category == fcZero) {
APInt::tcSet(parts.data(), 0, dstPartsCount);
*isExact = !sign;
return opOK;
}
src = significandParts();
if (exponent < 0) {
APInt::tcSet(parts.data(), 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.data(), dstPartsCount, src, bits, truncatedBits);
} else {
APInt::tcExtract(parts.data(), dstPartsCount, src, semantics->precision,
0);
APInt::tcShiftLeft(parts.data(), 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.data(), dstPartsCount))
return opInvalidOp;
}
} else {
lost_fraction = lfExactlyZero;
}
unsigned int omsb = APInt::tcMSB(parts.data(), dstPartsCount) + 1;
if (sign) {
if (!isSigned) {
if (omsb != 0)
return opInvalidOp;
} else {
if (omsb == width &&
APInt::tcLSB(parts.data(), dstPartsCount) + 1 != omsb)
return opInvalidOp;
if (omsb > width)
return opInvalidOp;
}
APInt::tcNegate (parts.data(), dstPartsCount);
} else {
if (omsb >= width + !isSigned)
return opInvalidOp;
}
if (lost_fraction == lfExactlyZero) {
*isExact = true;
return opOK;
} else
return opInexact;
}
IEEEFloat::opStatus
IEEEFloat::convertToInteger(MutableArrayRef<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);
assert(dstPartsCount <= parts.size() && "Integer too big");
if (category == fcNaN)
bits = 0;
else if (sign)
bits = isSigned;
else
bits = width - isSigned;
tcSetLeastSignificantBits(parts.data(), dstPartsCount, bits);
if (sign && isSigned)
APInt::tcShiftLeft(parts.data(), dstPartsCount, width - 1);
}
return fs;
}
IEEEFloat::opStatus IEEEFloat::convertFromUnsignedParts(
const integerPart *src, unsigned int srcCount, roundingMode rounding_mode) {
unsigned int omsb, precision, dstCount;
integerPart *dst;
lostFraction lost_fraction;
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);
}
IEEEFloat::opStatus IEEEFloat::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);
}
IEEEFloat::opStatus
IEEEFloat::convertFromSignExtendedInteger(const integerPart *src,
unsigned int srcCount, bool isSigned,
roundingMode rounding_mode) {
opStatus status;
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;
}
IEEEFloat::opStatus
IEEEFloat::convertFromZeroExtendedInteger(const integerPart *parts,
unsigned int width, bool isSigned,
roundingMode rounding_mode) {
unsigned int partCount = partCountForBits(width);
APInt api = APInt(width, makeArrayRef(parts, partCount));
sign = false;
if (isSigned && APInt::tcExtractBit(parts, width - 1)) {
sign = true;
api = -api;
}
return convertFromUnsignedParts(api.getRawData(), partCount, rounding_mode);
}
Expected<IEEEFloat::opStatus>
IEEEFloat::convertFromHexadecimalString(StringRef s,
roundingMode rounding_mode) {
lostFraction lost_fraction = lfExactlyZero;
category = fcNormal;
zeroSignificand();
exponent = 0;
integerPart *significand = significandParts();
unsigned partsCount = partCount();
unsigned bitPos = partsCount * integerPartWidth;
bool computedTrailingFraction = false;
StringRef::iterator begin = s.begin();
StringRef::iterator end = s.end();
StringRef::iterator dot;
auto PtrOrErr = skipLeadingZeroesAndAnyDot(begin, end, &dot);
if (!PtrOrErr)
return PtrOrErr.takeError();
StringRef::iterator p = *PtrOrErr;
StringRef::iterator firstSignificantDigit = p;
while (p != end) {
integerPart hex_value;
if (*p == '.') {
if (dot != end)
return createError("String contains multiple dots");
dot = p++;
continue;
}
hex_value = hexDigitValue(*p);
if (hex_value == -1U)
break;
p++;
if (bitPos) {
bitPos -= 4;
hex_value <<= bitPos % integerPartWidth;
significand[bitPos / integerPartWidth] |= hex_value;
} else if (!computedTrailingFraction) {
auto FractOrErr = trailingHexadecimalFraction(p, end, hex_value);
if (!FractOrErr)
return FractOrErr.takeError();
lost_fraction = *FractOrErr;
computedTrailingFraction = true;
}
}
if (p == end)
return createError("Hex strings require an exponent");
if (*p != 'p' && *p != 'P')
return createError("Invalid character in significand");
if (p == begin)
return createError("Significand has no digits");
if (dot != end && p - begin == 1)
return createError("Significand has no digits");
if (p != firstSignificantDigit) {
int expAdjustment;
if (dot == end)
dot = p;
expAdjustment = static_cast<int>(dot - firstSignificantDigit);
if (expAdjustment < 0)
expAdjustment++;
expAdjustment = expAdjustment * 4 - 1;
expAdjustment += semantics->precision;
expAdjustment -= partsCount * integerPartWidth;
auto ExpOrErr = totalExponent(p + 1, end, expAdjustment);
if (!ExpOrErr)
return ExpOrErr.takeError();
exponent = *ExpOrErr;
}
return normalize(rounding_mode, lost_fraction);
}
IEEEFloat::opStatus
IEEEFloat::roundSignificandWithExponent(const integerPart *decSigParts,
unsigned sigPartCount, int exp,
roundingMode rounding_mode) {
unsigned int parts, pow5PartCount;
fltSemantics calcSemantics = { 32767, -32767, 0, 0 };
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;
IEEEFloat decSig(calcSemantics, uninitialized);
decSig.makeZero(sign);
IEEEFloat pow5(calcSemantics);
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);
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);
}
}
}
Expected<IEEEFloat::opStatus>
IEEEFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) {
decimalInfo D;
opStatus fs;
StringRef::iterator p = str.begin();
if (Error Err = interpretDecimal(p, str.end(), &D))
return std::move(Err);
if (D.firstSigDigit == str.end() || decDigitValue(*D.firstSigDigit) >= 10U) {
category = fcZero;
fs = opOK;
} else if (D.normalizedExponent - 1 > INT_MAX / 42039) {
fs = handleOverflow(rounding_mode);
} else if (D.normalizedExponent - 1 < INT_MIN / 42039 ||
(D.normalizedExponent + 1) * 28738 <=
8651 * (semantics->minExponent - (int) semantics->precision)) {
category = fcNormal;
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++;
if (p == str.end()) {
break;
}
}
decValue = decDigitValue(*p++);
if (decValue >= 10U) {
delete[] decSignificand;
return createError("Invalid character in significand");
}
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;
}
bool IEEEFloat::convertFromStringSpecials(StringRef str) {
const size_t MIN_NAME_SIZE = 3;
if (str.size() < MIN_NAME_SIZE)
return false;
if (str.equals("inf") || str.equals("INFINITY") || str.equals("+Inf")) {
makeInf(false);
return true;
}
bool IsNegative = str.front() == '-';
if (IsNegative) {
str = str.drop_front();
if (str.size() < MIN_NAME_SIZE)
return false;
if (str.equals("inf") || str.equals("INFINITY") || str.equals("Inf")) {
makeInf(true);
return true;
}
}
bool IsSignaling = str.front() == 's' || str.front() == 'S';
if (IsSignaling) {
str = str.drop_front();
if (str.size() < MIN_NAME_SIZE)
return false;
}
if (str.startswith("nan") || str.startswith("NaN")) {
str = str.drop_front(3);
if (str.empty()) {
makeNaN(IsSignaling, IsNegative);
return true;
}
if (str.front() == '(') {
if (str.size() <= 2 || str.back() != ')')
return false;
str = str.slice(1, str.size() - 1);
}
unsigned Radix = 10;
if (str[0] == '0') {
if (str.size() > 1 && tolower(str[1]) == 'x') {
str = str.drop_front(2);
Radix = 16;
} else
Radix = 8;
}
APInt Payload;
if (!str.getAsInteger(Radix, Payload)) {
makeNaN(IsSignaling, IsNegative, &Payload);
return true;
}
}
return false;
}
Expected<IEEEFloat::opStatus>
IEEEFloat::convertFromString(StringRef str, roundingMode rounding_mode) {
if (str.empty())
return createError("Invalid string length");
if (convertFromStringSpecials(str))
return opOK;
StringRef::iterator p = str.begin();
size_t slen = str.size();
sign = *p == '-' ? 1 : 0;
if (*p == '-' || *p == '+') {
p++;
slen--;
if (!slen)
return createError("String has no digits");
}
if (slen >= 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
if (slen == 2)
return createError("Invalid string");
return convertFromHexadecimalString(StringRef(p + 2, slen - 2),
rounding_mode);
}
return convertFromDecimalString(StringRef(p, slen), rounding_mode);
}
unsigned int IEEEFloat::convertToHexString(char *dst, unsigned int hexDigits,
bool upperCase,
roundingMode rounding_mode) const {
char *p;
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 *IEEEFloat::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);
}
hash_code hash_value(const IEEEFloat &Arg) {
if (!Arg.isFiniteNonZero())
return hash_combine((uint8_t)Arg.category,
Arg.isNaN() ? (uint8_t)0 : (uint8_t)Arg.sign,
Arg.semantics->precision);
return hash_combine((uint8_t)Arg.category, (uint8_t)Arg.sign,
Arg.semantics->precision, Arg.exponent,
hash_combine_range(
Arg.significandParts(),
Arg.significandParts() + Arg.partCount()));
}
APInt IEEEFloat::convertF80LongDoubleAPFloatToAPInt() const {
assert(semantics == (const llvm::fltSemantics*)&semX87DoubleExtended);
assert(partCount()==2);
uint64_t myexponent, mysignificand;
if (isFiniteNonZero()) {
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, words);
}
APInt IEEEFloat::convertPPCDoubleDoubleAPFloatToAPInt() const {
assert(semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleLegacy);
assert(partCount()==2);
uint64_t words[2];
opStatus fs;
bool losesInfo;
fltSemantics extendedSemantics = *semantics;
extendedSemantics.minExponent = semIEEEdouble.minExponent;
IEEEFloat extended(*this);
fs = extended.convert(extendedSemantics, rmNearestTiesToEven, &losesInfo);
assert(fs == opOK && !losesInfo);
(void)fs;
IEEEFloat u(extended);
fs = u.convert(semIEEEdouble, rmNearestTiesToEven, &losesInfo);
assert(fs == opOK || fs == opInexact);
(void)fs;
words[0] = *u.convertDoubleAPFloatToAPInt().getRawData();
if (u.isFiniteNonZero() && losesInfo) {
fs = u.convert(extendedSemantics, rmNearestTiesToEven, &losesInfo);
assert(fs == opOK && !losesInfo);
(void)fs;
IEEEFloat v(extended);
v.subtract(u, rmNearestTiesToEven);
fs = v.convert(semIEEEdouble, rmNearestTiesToEven, &losesInfo);
assert(fs == opOK && !losesInfo);
(void)fs;
words[1] = *v.convertDoubleAPFloatToAPInt().getRawData();
} else {
words[1] = 0;
}
return APInt(128, words);
}
APInt IEEEFloat::convertQuadrupleAPFloatToAPInt() const {
assert(semantics == (const llvm::fltSemantics*)&semIEEEquad);
assert(partCount()==2);
uint64_t myexponent, mysignificand, mysignificand2;
if (isFiniteNonZero()) {
myexponent = exponent+16383; mysignificand = significandParts()[0];
mysignificand2 = significandParts()[1];
if (myexponent==1 && !(mysignificand2 & 0x1000000000000LL))
myexponent = 0; } else if (category==fcZero) {
myexponent = 0;
mysignificand = mysignificand2 = 0;
} else if (category==fcInfinity) {
myexponent = 0x7fff;
mysignificand = mysignificand2 = 0;
} else {
assert(category == fcNaN && "Unknown category!");
myexponent = 0x7fff;
mysignificand = significandParts()[0];
mysignificand2 = significandParts()[1];
}
uint64_t words[2];
words[0] = mysignificand;
words[1] = ((uint64_t)(sign & 1) << 63) |
((myexponent & 0x7fff) << 48) |
(mysignificand2 & 0xffffffffffffLL);
return APInt(128, words);
}
APInt IEEEFloat::convertDoubleAPFloatToAPInt() const {
assert(semantics == (const llvm::fltSemantics*)&semIEEEdouble);
assert(partCount()==1);
uint64_t myexponent, mysignificand;
if (isFiniteNonZero()) {
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 IEEEFloat::convertFloatAPFloatToAPInt() const {
assert(semantics == (const llvm::fltSemantics*)&semIEEEsingle);
assert(partCount()==1);
uint32_t myexponent, mysignificand;
if (isFiniteNonZero()) {
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 IEEEFloat::convertBFloatAPFloatToAPInt() const {
assert(semantics == (const llvm::fltSemantics *)&semBFloat);
assert(partCount() == 1);
uint32_t myexponent, mysignificand;
if (isFiniteNonZero()) {
myexponent = exponent + 127; mysignificand = (uint32_t)*significandParts();
if (myexponent == 1 && !(mysignificand & 0x80))
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(16, (((sign & 1) << 15) | ((myexponent & 0xff) << 7) |
(mysignificand & 0x7f)));
}
APInt IEEEFloat::convertHalfAPFloatToAPInt() const {
assert(semantics == (const llvm::fltSemantics*)&semIEEEhalf);
assert(partCount()==1);
uint32_t myexponent, mysignificand;
if (isFiniteNonZero()) {
myexponent = exponent+15; mysignificand = (uint32_t)*significandParts();
if (myexponent == 1 && !(mysignificand & 0x400))
myexponent = 0; } else if (category==fcZero) {
myexponent = 0;
mysignificand = 0;
} else if (category==fcInfinity) {
myexponent = 0x1f;
mysignificand = 0;
} else {
assert(category == fcNaN && "Unknown category!");
myexponent = 0x1f;
mysignificand = (uint32_t)*significandParts();
}
return APInt(16, (((sign&1) << 15) | ((myexponent&0x1f) << 10) |
(mysignificand & 0x3ff)));
}
APInt IEEEFloat::bitcastToAPInt() const {
if (semantics == (const llvm::fltSemantics*)&semIEEEhalf)
return convertHalfAPFloatToAPInt();
if (semantics == (const llvm::fltSemantics *)&semBFloat)
return convertBFloatAPFloatToAPInt();
if (semantics == (const llvm::fltSemantics*)&semIEEEsingle)
return convertFloatAPFloatToAPInt();
if (semantics == (const llvm::fltSemantics*)&semIEEEdouble)
return convertDoubleAPFloatToAPInt();
if (semantics == (const llvm::fltSemantics*)&semIEEEquad)
return convertQuadrupleAPFloatToAPInt();
if (semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleLegacy)
return convertPPCDoubleDoubleAPFloatToAPInt();
assert(semantics == (const llvm::fltSemantics*)&semX87DoubleExtended &&
"unknown format!");
return convertF80LongDoubleAPFloatToAPInt();
}
float IEEEFloat::convertToFloat() const {
assert(semantics == (const llvm::fltSemantics*)&semIEEEsingle &&
"Float semantics are not IEEEsingle");
APInt api = bitcastToAPInt();
return api.bitsToFloat();
}
double IEEEFloat::convertToDouble() const {
assert(semantics == (const llvm::fltSemantics*)&semIEEEdouble &&
"Float semantics are not IEEEdouble");
APInt api = bitcastToAPInt();
return api.bitsToDouble();
}
void IEEEFloat::initFromF80LongDoubleAPInt(const APInt &api) {
uint64_t i1 = api.getRawData()[0];
uint64_t i2 = api.getRawData()[1];
uint64_t myexponent = (i2 & 0x7fff);
uint64_t mysignificand = i1;
uint8_t myintegerbit = mysignificand >> 63;
initialize(&semX87DoubleExtended);
assert(partCount()==2);
sign = static_cast<unsigned int>(i2>>15);
if (myexponent == 0 && mysignificand == 0) {
makeZero(sign);
} else if (myexponent==0x7fff && mysignificand==0x8000000000000000ULL) {
makeInf(sign);
} else if ((myexponent == 0x7fff && mysignificand != 0x8000000000000000ULL) ||
(myexponent != 0x7fff && myexponent != 0 && myintegerbit == 0)) {
category = fcNaN;
exponent = exponentNaN();
significandParts()[0] = mysignificand;
significandParts()[1] = 0;
} else {
category = fcNormal;
exponent = myexponent - 16383;
significandParts()[0] = mysignificand;
significandParts()[1] = 0;
if (myexponent==0) exponent = -16382;
}
}
void IEEEFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) {
uint64_t i1 = api.getRawData()[0];
uint64_t i2 = api.getRawData()[1];
opStatus fs;
bool losesInfo;
initFromDoubleAPInt(APInt(64, i1));
fs = convert(semPPCDoubleDoubleLegacy, rmNearestTiesToEven, &losesInfo);
assert(fs == opOK && !losesInfo);
(void)fs;
if (isFiniteNonZero()) {
IEEEFloat v(semIEEEdouble, APInt(64, i2));
fs = v.convert(semPPCDoubleDoubleLegacy, rmNearestTiesToEven, &losesInfo);
assert(fs == opOK && !losesInfo);
(void)fs;
add(v, rmNearestTiesToEven);
}
}
void IEEEFloat::initFromQuadrupleAPInt(const APInt &api) {
uint64_t i1 = api.getRawData()[0];
uint64_t i2 = api.getRawData()[1];
uint64_t myexponent = (i2 >> 48) & 0x7fff;
uint64_t mysignificand = i1;
uint64_t mysignificand2 = i2 & 0xffffffffffffLL;
initialize(&semIEEEquad);
assert(partCount()==2);
sign = static_cast<unsigned int>(i2>>63);
if (myexponent==0 &&
(mysignificand==0 && mysignificand2==0)) {
makeZero(sign);
} else if (myexponent==0x7fff &&
(mysignificand==0 && mysignificand2==0)) {
makeInf(sign);
} else if (myexponent==0x7fff &&
(mysignificand!=0 || mysignificand2 !=0)) {
category = fcNaN;
exponent = exponentNaN();
significandParts()[0] = mysignificand;
significandParts()[1] = mysignificand2;
} else {
category = fcNormal;
exponent = myexponent - 16383;
significandParts()[0] = mysignificand;
significandParts()[1] = mysignificand2;
if (myexponent==0) exponent = -16382;
else
significandParts()[1] |= 0x1000000000000LL; }
}
void IEEEFloat::initFromDoubleAPInt(const APInt &api) {
uint64_t i = *api.getRawData();
uint64_t myexponent = (i >> 52) & 0x7ff;
uint64_t mysignificand = i & 0xfffffffffffffLL;
initialize(&semIEEEdouble);
assert(partCount()==1);
sign = static_cast<unsigned int>(i>>63);
if (myexponent==0 && mysignificand==0) {
makeZero(sign);
} else if (myexponent==0x7ff && mysignificand==0) {
makeInf(sign);
} else if (myexponent==0x7ff && mysignificand!=0) {
category = fcNaN;
exponent = exponentNaN();
*significandParts() = mysignificand;
} else {
category = fcNormal;
exponent = myexponent - 1023;
*significandParts() = mysignificand;
if (myexponent==0) exponent = -1022;
else
*significandParts() |= 0x10000000000000LL; }
}
void IEEEFloat::initFromFloatAPInt(const APInt &api) {
uint32_t i = (uint32_t)*api.getRawData();
uint32_t myexponent = (i >> 23) & 0xff;
uint32_t mysignificand = i & 0x7fffff;
initialize(&semIEEEsingle);
assert(partCount()==1);
sign = i >> 31;
if (myexponent==0 && mysignificand==0) {
makeZero(sign);
} else if (myexponent==0xff && mysignificand==0) {
makeInf(sign);
} else if (myexponent==0xff && mysignificand!=0) {
category = fcNaN;
exponent = exponentNaN();
*significandParts() = mysignificand;
} else {
category = fcNormal;
exponent = myexponent - 127; *significandParts() = mysignificand;
if (myexponent==0) exponent = -126;
else
*significandParts() |= 0x800000; }
}
void IEEEFloat::initFromBFloatAPInt(const APInt &api) {
uint32_t i = (uint32_t)*api.getRawData();
uint32_t myexponent = (i >> 7) & 0xff;
uint32_t mysignificand = i & 0x7f;
initialize(&semBFloat);
assert(partCount() == 1);
sign = i >> 15;
if (myexponent == 0 && mysignificand == 0) {
makeZero(sign);
} else if (myexponent == 0xff && mysignificand == 0) {
makeInf(sign);
} else if (myexponent == 0xff && mysignificand != 0) {
category = fcNaN;
exponent = exponentNaN();
*significandParts() = mysignificand;
} else {
category = fcNormal;
exponent = myexponent - 127; *significandParts() = mysignificand;
if (myexponent == 0) exponent = -126;
else
*significandParts() |= 0x80; }
}
void IEEEFloat::initFromHalfAPInt(const APInt &api) {
uint32_t i = (uint32_t)*api.getRawData();
uint32_t myexponent = (i >> 10) & 0x1f;
uint32_t mysignificand = i & 0x3ff;
initialize(&semIEEEhalf);
assert(partCount()==1);
sign = i >> 15;
if (myexponent==0 && mysignificand==0) {
makeZero(sign);
} else if (myexponent==0x1f && mysignificand==0) {
makeInf(sign);
} else if (myexponent==0x1f && mysignificand!=0) {
category = fcNaN;
exponent = exponentNaN();
*significandParts() = mysignificand;
} else {
category = fcNormal;
exponent = myexponent - 15; *significandParts() = mysignificand;
if (myexponent==0) exponent = -14;
else
*significandParts() |= 0x400; }
}
void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) {
assert(api.getBitWidth() == Sem->sizeInBits);
if (Sem == &semIEEEhalf)
return initFromHalfAPInt(api);
if (Sem == &semBFloat)
return initFromBFloatAPInt(api);
if (Sem == &semIEEEsingle)
return initFromFloatAPInt(api);
if (Sem == &semIEEEdouble)
return initFromDoubleAPInt(api);
if (Sem == &semX87DoubleExtended)
return initFromF80LongDoubleAPInt(api);
if (Sem == &semIEEEquad)
return initFromQuadrupleAPInt(api);
if (Sem == &semPPCDoubleDoubleLegacy)
return initFromPPCDoubleDoubleAPInt(api);
llvm_unreachable(nullptr);
}
void IEEEFloat::makeLargest(bool Negative) {
category = fcNormal;
sign = Negative;
exponent = semantics->maxExponent;
integerPart *significand = significandParts();
unsigned PartCount = partCount();
memset(significand, 0xFF, sizeof(integerPart)*(PartCount - 1));
const unsigned NumUnusedHighBits =
PartCount*integerPartWidth - semantics->precision;
significand[PartCount - 1] = (NumUnusedHighBits < integerPartWidth)
? (~integerPart(0) >> NumUnusedHighBits)
: 0;
}
void IEEEFloat::makeSmallest(bool Negative) {
category = fcNormal;
sign = Negative;
exponent = semantics->minExponent;
APInt::tcSet(significandParts(), 1, partCount());
}
void IEEEFloat::makeSmallestNormalized(bool Negative) {
category = fcNormal;
zeroSignificand();
sign = Negative;
exponent = semantics->minExponent;
significandParts()[partCountForBits(semantics->precision) - 1] |=
(((integerPart)1) << ((semantics->precision - 1) % integerPartWidth));
}
IEEEFloat::IEEEFloat(const fltSemantics &Sem, const APInt &API) {
initFromAPInt(&Sem, API);
}
IEEEFloat::IEEEFloat(float f) {
initFromAPInt(&semIEEEsingle, APInt::floatToBits(f));
}
IEEEFloat::IEEEFloat(double d) {
initFromAPInt(&semIEEEdouble, APInt::doubleToBits(d));
}
namespace {
void append(SmallVectorImpl<char> &Buffer, StringRef Str) {
Buffer.append(Str.begin(), Str.end());
}
void AdjustToPrecision(APInt &significand,
int &exp, unsigned FormatPrecision) {
unsigned bits = significand.getActiveBits();
unsigned bitsRequired = (FormatPrecision * 196 + 58) / 59;
if (bits <= bitsRequired) return;
unsigned tensRemovable = (bits - bitsRequired) * 59 / 196;
if (!tensRemovable) return;
exp += tensRemovable;
APInt divisor(significand.getBitWidth(), 1);
APInt powten(significand.getBitWidth(), 10);
while (true) {
if (tensRemovable & 1)
divisor *= powten;
tensRemovable >>= 1;
if (!tensRemovable) break;
powten *= powten;
}
significand = significand.udiv(divisor);
significand = significand.trunc(significand.getActiveBits());
}
void AdjustToPrecision(SmallVectorImpl<char> &buffer,
int &exp, unsigned FormatPrecision) {
unsigned N = buffer.size();
if (N <= FormatPrecision) return;
unsigned FirstSignificant = N - FormatPrecision;
if (buffer[FirstSignificant - 1] < '5') {
while (FirstSignificant < N && buffer[FirstSignificant] == '0')
FirstSignificant++;
exp += FirstSignificant;
buffer.erase(&buffer[0], &buffer[FirstSignificant]);
return;
}
for (unsigned I = FirstSignificant; I != N; ++I) {
if (buffer[I] == '9') {
FirstSignificant++;
} else {
buffer[I]++;
break;
}
}
if (FirstSignificant == N) {
exp += FirstSignificant;
buffer.clear();
buffer.push_back('1');
return;
}
exp += FirstSignificant;
buffer.erase(&buffer[0], &buffer[FirstSignificant]);
}
}
void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
unsigned FormatMaxPadding, bool TruncateZero) const {
switch (category) {
case fcInfinity:
if (isNegative())
return append(Str, "-Inf");
else
return append(Str, "+Inf");
case fcNaN: return append(Str, "NaN");
case fcZero:
if (isNegative())
Str.push_back('-');
if (!FormatMaxPadding) {
if (TruncateZero)
append(Str, "0.0E+0");
else {
append(Str, "0.0");
if (FormatPrecision > 1)
Str.append(FormatPrecision - 1, '0');
append(Str, "e+00");
}
} else
Str.push_back('0');
return;
case fcNormal:
break;
}
if (isNegative())
Str.push_back('-');
int exp = exponent - ((int) semantics->precision - 1);
APInt significand(semantics->precision,
makeArrayRef(significandParts(),
partCountForBits(semantics->precision)));
if (!FormatPrecision) {
FormatPrecision = 2 + semantics->precision * 59 / 196;
}
int trailingZeros = significand.countTrailingZeros();
exp += trailingZeros;
significand.lshrInPlace(trailingZeros);
if (exp == 0) {
} else if (exp > 0) {
significand = significand.zext(semantics->precision + exp);
significand <<= exp;
exp = 0;
} else {
int texp = -exp;
unsigned precision = semantics->precision + (137 * texp + 136) / 59;
significand = significand.zext(precision);
APInt five_to_the_i(precision, 5);
while (true) {
if (texp & 1) significand *= five_to_the_i;
texp >>= 1;
if (!texp) break;
five_to_the_i *= five_to_the_i;
}
}
AdjustToPrecision(significand, exp, FormatPrecision);
SmallVector<char, 256> buffer;
unsigned precision = significand.getBitWidth();
APInt ten(precision, 10);
APInt digit(precision, 0);
bool inTrail = true;
while (significand != 0) {
APInt::udivrem(significand, ten, significand, digit);
unsigned d = digit.getZExtValue();
if (inTrail && !d) exp++;
else {
buffer.push_back((char) ('0' + d));
inTrail = false;
}
}
assert(!buffer.empty() && "no characters in buffer!");
AdjustToPrecision(buffer, exp, FormatPrecision);
unsigned NDigits = buffer.size();
bool FormatScientific;
if (!FormatMaxPadding)
FormatScientific = true;
else {
if (exp >= 0) {
FormatScientific = ((unsigned) exp > FormatMaxPadding ||
NDigits + (unsigned) exp > FormatPrecision);
} else {
int MSD = exp + (int) (NDigits - 1);
if (MSD >= 0) {
FormatScientific = false;
} else {
FormatScientific = ((unsigned) -MSD) > FormatMaxPadding;
}
}
}
if (FormatScientific) {
exp += (NDigits - 1);
Str.push_back(buffer[NDigits-1]);
Str.push_back('.');
if (NDigits == 1 && TruncateZero)
Str.push_back('0');
else
for (unsigned I = 1; I != NDigits; ++I)
Str.push_back(buffer[NDigits-1-I]);
if (!TruncateZero && FormatPrecision > NDigits - 1)
Str.append(FormatPrecision - NDigits + 1, '0');
Str.push_back(TruncateZero ? 'E' : 'e');
Str.push_back(exp >= 0 ? '+' : '-');
if (exp < 0) exp = -exp;
SmallVector<char, 6> expbuf;
do {
expbuf.push_back((char) ('0' + (exp % 10)));
exp /= 10;
} while (exp);
if (!TruncateZero && expbuf.size() < 2)
expbuf.push_back('0');
for (unsigned I = 0, E = expbuf.size(); I != E; ++I)
Str.push_back(expbuf[E-1-I]);
return;
}
if (exp >= 0) {
for (unsigned I = 0; I != NDigits; ++I)
Str.push_back(buffer[NDigits-1-I]);
for (unsigned I = 0; I != (unsigned) exp; ++I)
Str.push_back('0');
return;
}
int NWholeDigits = exp + (int) NDigits;
unsigned I = 0;
if (NWholeDigits > 0) {
for (; I != (unsigned) NWholeDigits; ++I)
Str.push_back(buffer[NDigits-I-1]);
Str.push_back('.');
} else {
unsigned NZeros = 1 + (unsigned) -NWholeDigits;
Str.push_back('0');
Str.push_back('.');
for (unsigned Z = 1; Z != NZeros; ++Z)
Str.push_back('0');
}
for (; I != NDigits; ++I)
Str.push_back(buffer[NDigits-I-1]);
}
bool IEEEFloat::getExactInverse(APFloat *inv) const {
if (!isFiniteNonZero())
return false;
if (significandLSB() != semantics->precision - 1)
return false;
IEEEFloat reciprocal(*semantics, 1ULL);
if (reciprocal.divide(*this, rmNearestTiesToEven) != opOK)
return false;
if (reciprocal.isDenormal())
return false;
assert(reciprocal.isFiniteNonZero() &&
reciprocal.significandLSB() == reciprocal.semantics->precision - 1);
if (inv)
*inv = APFloat(reciprocal, *semantics);
return true;
}
bool IEEEFloat::isSignaling() const {
if (!isNaN())
return false;
return !APInt::tcExtractBit(significandParts(), semantics->precision - 2);
}
IEEEFloat::opStatus IEEEFloat::next(bool nextDown) {
if (nextDown)
changeSign();
opStatus result = opOK;
switch (category) {
case fcInfinity:
if (!isNegative())
break;
makeLargest(true);
break;
case fcNaN:
if (isSignaling()) {
result = opInvalidOp;
makeNaN(false, isNegative(), nullptr);
}
break;
case fcZero:
makeSmallest(false);
break;
case fcNormal:
if (isSmallest() && isNegative()) {
APInt::tcSet(significandParts(), 0, partCount());
category = fcZero;
exponent = 0;
break;
}
if (isLargest() && !isNegative()) {
APInt::tcSet(significandParts(), 0, partCount());
category = fcInfinity;
exponent = semantics->maxExponent + 1;
break;
}
if (isNegative()) {
bool WillCrossBinadeBoundary =
exponent != semantics->minExponent && isSignificandAllZeros();
integerPart *Parts = significandParts();
APInt::tcDecrement(Parts, partCount());
if (WillCrossBinadeBoundary) {
APInt::tcSetBit(Parts, semantics->precision - 1);
exponent--;
}
} else {
bool WillCrossBinadeBoundary = !isDenormal() && isSignificandAllOnes();
if (WillCrossBinadeBoundary) {
integerPart *Parts = significandParts();
APInt::tcSet(Parts, 0, partCount());
APInt::tcSetBit(Parts, semantics->precision - 1);
assert(exponent != semantics->maxExponent &&
"We can not increment an exponent beyond the maxExponent allowed"
" by the given floating point semantics.");
exponent++;
} else {
incrementSignificand();
}
}
break;
}
if (nextDown)
changeSign();
return result;
}
APFloatBase::ExponentType IEEEFloat::exponentNaN() const {
return semantics->maxExponent + 1;
}
APFloatBase::ExponentType IEEEFloat::exponentInf() const {
return semantics->maxExponent + 1;
}
APFloatBase::ExponentType IEEEFloat::exponentZero() const {
return semantics->minExponent - 1;
}
void IEEEFloat::makeInf(bool Negative) {
category = fcInfinity;
sign = Negative;
exponent = exponentInf();
APInt::tcSet(significandParts(), 0, partCount());
}
void IEEEFloat::makeZero(bool Negative) {
category = fcZero;
sign = Negative;
exponent = exponentZero();
APInt::tcSet(significandParts(), 0, partCount());
}
void IEEEFloat::makeQuiet() {
assert(isNaN());
APInt::tcSetBit(significandParts(), semantics->precision - 2);
}
int ilogb(const IEEEFloat &Arg) {
if (Arg.isNaN())
return IEEEFloat::IEK_NaN;
if (Arg.isZero())
return IEEEFloat::IEK_Zero;
if (Arg.isInfinity())
return IEEEFloat::IEK_Inf;
if (!Arg.isDenormal())
return Arg.exponent;
IEEEFloat Normalized(Arg);
int SignificandBits = Arg.getSemantics().precision - 1;
Normalized.exponent += SignificandBits;
Normalized.normalize(IEEEFloat::rmNearestTiesToEven, lfExactlyZero);
return Normalized.exponent - SignificandBits;
}
IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode RoundingMode) {
auto MaxExp = X.getSemantics().maxExponent;
auto MinExp = X.getSemantics().minExponent;
int SignificandBits = X.getSemantics().precision - 1;
int MaxIncrement = MaxExp - (MinExp - SignificandBits) + 1;
X.exponent += std::min(std::max(Exp, -MaxIncrement - 1), MaxIncrement);
X.normalize(RoundingMode, lfExactlyZero);
if (X.isNaN())
X.makeQuiet();
return X;
}
IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM) {
Exp = ilogb(Val);
if (Exp == IEEEFloat::IEK_NaN) {
IEEEFloat Quiet(Val);
Quiet.makeQuiet();
return Quiet;
}
if (Exp == IEEEFloat::IEK_Inf)
return Val;
Exp = Exp == IEEEFloat::IEK_Zero ? 0 : Exp + 1;
return scalbn(Val, -Exp, RM);
}
DoubleAPFloat::DoubleAPFloat(const fltSemantics &S)
: Semantics(&S),
Floats(new APFloat[2]{APFloat(semIEEEdouble), APFloat(semIEEEdouble)}) {
assert(Semantics == &semPPCDoubleDouble);
}
DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, uninitializedTag)
: Semantics(&S),
Floats(new APFloat[2]{APFloat(semIEEEdouble, uninitialized),
APFloat(semIEEEdouble, uninitialized)}) {
assert(Semantics == &semPPCDoubleDouble);
}
DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, integerPart I)
: Semantics(&S), Floats(new APFloat[2]{APFloat(semIEEEdouble, I),
APFloat(semIEEEdouble)}) {
assert(Semantics == &semPPCDoubleDouble);
}
DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, const APInt &I)
: Semantics(&S),
Floats(new APFloat[2]{
APFloat(semIEEEdouble, APInt(64, I.getRawData()[0])),
APFloat(semIEEEdouble, APInt(64, I.getRawData()[1]))}) {
assert(Semantics == &semPPCDoubleDouble);
}
DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, APFloat &&First,
APFloat &&Second)
: Semantics(&S),
Floats(new APFloat[2]{std::move(First), std::move(Second)}) {
assert(Semantics == &semPPCDoubleDouble);
assert(&Floats[0].getSemantics() == &semIEEEdouble);
assert(&Floats[1].getSemantics() == &semIEEEdouble);
}
DoubleAPFloat::DoubleAPFloat(const DoubleAPFloat &RHS)
: Semantics(RHS.Semantics),
Floats(RHS.Floats ? new APFloat[2]{APFloat(RHS.Floats[0]),
APFloat(RHS.Floats[1])}
: nullptr) {
assert(Semantics == &semPPCDoubleDouble);
}
DoubleAPFloat::DoubleAPFloat(DoubleAPFloat &&RHS)
: Semantics(RHS.Semantics), Floats(std::move(RHS.Floats)) {
RHS.Semantics = &semBogus;
assert(Semantics == &semPPCDoubleDouble);
}
DoubleAPFloat &DoubleAPFloat::operator=(const DoubleAPFloat &RHS) {
if (Semantics == RHS.Semantics && RHS.Floats) {
Floats[0] = RHS.Floats[0];
Floats[1] = RHS.Floats[1];
} else if (this != &RHS) {
this->~DoubleAPFloat();
new (this) DoubleAPFloat(RHS);
}
return *this;
}
APFloat::opStatus DoubleAPFloat::addImpl(const APFloat &a, const APFloat &aa,
const APFloat &c, const APFloat &cc,
roundingMode RM) {
int Status = opOK;
APFloat z = a;
Status |= z.add(c, RM);
if (!z.isFinite()) {
if (!z.isInfinity()) {
Floats[0] = std::move(z);
Floats[1].makeZero( false);
return (opStatus)Status;
}
Status = opOK;
auto AComparedToC = a.compareAbsoluteValue(c);
z = cc;
Status |= z.add(aa, RM);
if (AComparedToC == APFloat::cmpGreaterThan) {
Status |= z.add(c, RM);
Status |= z.add(a, RM);
} else {
Status |= z.add(a, RM);
Status |= z.add(c, RM);
}
if (!z.isFinite()) {
Floats[0] = std::move(z);
Floats[1].makeZero( false);
return (opStatus)Status;
}
Floats[0] = z;
APFloat zz = aa;
Status |= zz.add(cc, RM);
if (AComparedToC == APFloat::cmpGreaterThan) {
Floats[1] = a;
Status |= Floats[1].subtract(z, RM);
Status |= Floats[1].add(c, RM);
Status |= Floats[1].add(zz, RM);
} else {
Floats[1] = c;
Status |= Floats[1].subtract(z, RM);
Status |= Floats[1].add(a, RM);
Status |= Floats[1].add(zz, RM);
}
} else {
APFloat q = a;
Status |= q.subtract(z, RM);
auto zz = q;
Status |= zz.add(c, RM);
Status |= q.add(z, RM);
Status |= q.subtract(a, RM);
q.changeSign();
Status |= zz.add(q, RM);
Status |= zz.add(aa, RM);
Status |= zz.add(cc, RM);
if (zz.isZero() && !zz.isNegative()) {
Floats[0] = std::move(z);
Floats[1].makeZero( false);
return opOK;
}
Floats[0] = z;
Status |= Floats[0].add(zz, RM);
if (!Floats[0].isFinite()) {
Floats[1].makeZero( false);
return (opStatus)Status;
}
Floats[1] = std::move(z);
Status |= Floats[1].subtract(Floats[0], RM);
Status |= Floats[1].add(zz, RM);
}
return (opStatus)Status;
}
APFloat::opStatus DoubleAPFloat::addWithSpecial(const DoubleAPFloat &LHS,
const DoubleAPFloat &RHS,
DoubleAPFloat &Out,
roundingMode RM) {
if (LHS.getCategory() == fcNaN) {
Out = LHS;
return opOK;
}
if (RHS.getCategory() == fcNaN) {
Out = RHS;
return opOK;
}
if (LHS.getCategory() == fcZero) {
Out = RHS;
return opOK;
}
if (RHS.getCategory() == fcZero) {
Out = LHS;
return opOK;
}
if (LHS.getCategory() == fcInfinity && RHS.getCategory() == fcInfinity &&
LHS.isNegative() != RHS.isNegative()) {
Out.makeNaN(false, Out.isNegative(), nullptr);
return opInvalidOp;
}
if (LHS.getCategory() == fcInfinity) {
Out = LHS;
return opOK;
}
if (RHS.getCategory() == fcInfinity) {
Out = RHS;
return opOK;
}
assert(LHS.getCategory() == fcNormal && RHS.getCategory() == fcNormal);
APFloat A(LHS.Floats[0]), AA(LHS.Floats[1]), C(RHS.Floats[0]),
CC(RHS.Floats[1]);
assert(&A.getSemantics() == &semIEEEdouble);
assert(&AA.getSemantics() == &semIEEEdouble);
assert(&C.getSemantics() == &semIEEEdouble);
assert(&CC.getSemantics() == &semIEEEdouble);
assert(&Out.Floats[0].getSemantics() == &semIEEEdouble);
assert(&Out.Floats[1].getSemantics() == &semIEEEdouble);
return Out.addImpl(A, AA, C, CC, RM);
}
APFloat::opStatus DoubleAPFloat::add(const DoubleAPFloat &RHS,
roundingMode RM) {
return addWithSpecial(*this, RHS, *this, RM);
}
APFloat::opStatus DoubleAPFloat::subtract(const DoubleAPFloat &RHS,
roundingMode RM) {
changeSign();
auto Ret = add(RHS, RM);
changeSign();
return Ret;
}
APFloat::opStatus DoubleAPFloat::multiply(const DoubleAPFloat &RHS,
APFloat::roundingMode RM) {
const auto &LHS = *this;
auto &Out = *this;
if (LHS.getCategory() == fcNaN) {
Out = LHS;
return opOK;
}
if (RHS.getCategory() == fcNaN) {
Out = RHS;
return opOK;
}
if ((LHS.getCategory() == fcZero && RHS.getCategory() == fcInfinity) ||
(LHS.getCategory() == fcInfinity && RHS.getCategory() == fcZero)) {
Out.makeNaN(false, false, nullptr);
return opOK;
}
if (LHS.getCategory() == fcZero || LHS.getCategory() == fcInfinity) {
Out = LHS;
return opOK;
}
if (RHS.getCategory() == fcZero || RHS.getCategory() == fcInfinity) {
Out = RHS;
return opOK;
}
assert(LHS.getCategory() == fcNormal && RHS.getCategory() == fcNormal &&
"Special cases not handled exhaustively");
int Status = opOK;
APFloat A = Floats[0], B = Floats[1], C = RHS.Floats[0], D = RHS.Floats[1];
APFloat T = A;
Status |= T.multiply(C, RM);
if (!T.isFiniteNonZero()) {
Floats[0] = T;
Floats[1].makeZero( false);
return (opStatus)Status;
}
APFloat Tau = A;
T.changeSign();
Status |= Tau.fusedMultiplyAdd(C, T, RM);
T.changeSign();
{
APFloat V = A;
Status |= V.multiply(D, RM);
APFloat W = B;
Status |= W.multiply(C, RM);
Status |= V.add(W, RM);
Status |= Tau.add(V, RM);
}
APFloat U = T;
Status |= U.add(Tau, RM);
Floats[0] = U;
if (!U.isFinite()) {
Floats[1].makeZero( false);
} else {
Status |= T.subtract(U, RM);
Status |= T.add(Tau, RM);
Floats[1] = T;
}
return (opStatus)Status;
}
APFloat::opStatus DoubleAPFloat::divide(const DoubleAPFloat &RHS,
APFloat::roundingMode RM) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
auto Ret =
Tmp.divide(APFloat(semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt()), RM);
*this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
return Ret;
}
APFloat::opStatus DoubleAPFloat::remainder(const DoubleAPFloat &RHS) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
auto Ret =
Tmp.remainder(APFloat(semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt()));
*this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
return Ret;
}
APFloat::opStatus DoubleAPFloat::mod(const DoubleAPFloat &RHS) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
auto Ret = Tmp.mod(APFloat(semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt()));
*this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
return Ret;
}
APFloat::opStatus
DoubleAPFloat::fusedMultiplyAdd(const DoubleAPFloat &Multiplicand,
const DoubleAPFloat &Addend,
APFloat::roundingMode RM) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
auto Ret = Tmp.fusedMultiplyAdd(
APFloat(semPPCDoubleDoubleLegacy, Multiplicand.bitcastToAPInt()),
APFloat(semPPCDoubleDoubleLegacy, Addend.bitcastToAPInt()), RM);
*this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
return Ret;
}
APFloat::opStatus DoubleAPFloat::roundToIntegral(APFloat::roundingMode RM) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
auto Ret = Tmp.roundToIntegral(RM);
*this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
return Ret;
}
void DoubleAPFloat::changeSign() {
Floats[0].changeSign();
Floats[1].changeSign();
}
APFloat::cmpResult
DoubleAPFloat::compareAbsoluteValue(const DoubleAPFloat &RHS) const {
auto Result = Floats[0].compareAbsoluteValue(RHS.Floats[0]);
if (Result != cmpEqual)
return Result;
Result = Floats[1].compareAbsoluteValue(RHS.Floats[1]);
if (Result == cmpLessThan || Result == cmpGreaterThan) {
auto Against = Floats[0].isNegative() ^ Floats[1].isNegative();
auto RHSAgainst = RHS.Floats[0].isNegative() ^ RHS.Floats[1].isNegative();
if (Against && !RHSAgainst)
return cmpLessThan;
if (!Against && RHSAgainst)
return cmpGreaterThan;
if (!Against && !RHSAgainst)
return Result;
if (Against && RHSAgainst)
return (cmpResult)(cmpLessThan + cmpGreaterThan - Result);
}
return Result;
}
APFloat::fltCategory DoubleAPFloat::getCategory() const {
return Floats[0].getCategory();
}
bool DoubleAPFloat::isNegative() const { return Floats[0].isNegative(); }
void DoubleAPFloat::makeInf(bool Neg) {
Floats[0].makeInf(Neg);
Floats[1].makeZero( false);
}
void DoubleAPFloat::makeZero(bool Neg) {
Floats[0].makeZero(Neg);
Floats[1].makeZero( false);
}
void DoubleAPFloat::makeLargest(bool Neg) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
Floats[0] = APFloat(semIEEEdouble, APInt(64, 0x7fefffffffffffffull));
Floats[1] = APFloat(semIEEEdouble, APInt(64, 0x7c8ffffffffffffeull));
if (Neg)
changeSign();
}
void DoubleAPFloat::makeSmallest(bool Neg) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
Floats[0].makeSmallest(Neg);
Floats[1].makeZero( false);
}
void DoubleAPFloat::makeSmallestNormalized(bool Neg) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
Floats[0] = APFloat(semIEEEdouble, APInt(64, 0x0360000000000000ull));
if (Neg)
Floats[0].changeSign();
Floats[1].makeZero( false);
}
void DoubleAPFloat::makeNaN(bool SNaN, bool Neg, const APInt *fill) {
Floats[0].makeNaN(SNaN, Neg, fill);
Floats[1].makeZero( false);
}
APFloat::cmpResult DoubleAPFloat::compare(const DoubleAPFloat &RHS) const {
auto Result = Floats[0].compare(RHS.Floats[0]);
if (Result == APFloat::cmpEqual)
return Floats[1].compare(RHS.Floats[1]);
return Result;
}
bool DoubleAPFloat::bitwiseIsEqual(const DoubleAPFloat &RHS) const {
return Floats[0].bitwiseIsEqual(RHS.Floats[0]) &&
Floats[1].bitwiseIsEqual(RHS.Floats[1]);
}
hash_code hash_value(const DoubleAPFloat &Arg) {
if (Arg.Floats)
return hash_combine(hash_value(Arg.Floats[0]), hash_value(Arg.Floats[1]));
return hash_combine(Arg.Semantics);
}
APInt DoubleAPFloat::bitcastToAPInt() const {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
uint64_t Data[] = {
Floats[0].bitcastToAPInt().getRawData()[0],
Floats[1].bitcastToAPInt().getRawData()[0],
};
return APInt(128, 2, Data);
}
Expected<APFloat::opStatus> DoubleAPFloat::convertFromString(StringRef S,
roundingMode RM) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat Tmp(semPPCDoubleDoubleLegacy);
auto Ret = Tmp.convertFromString(S, RM);
*this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
return Ret;
}
APFloat::opStatus DoubleAPFloat::next(bool nextDown) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
auto Ret = Tmp.next(nextDown);
*this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
return Ret;
}
APFloat::opStatus
DoubleAPFloat::convertToInteger(MutableArrayRef<integerPart> Input,
unsigned int Width, bool IsSigned,
roundingMode RM, bool *IsExact) const {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
return APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt())
.convertToInteger(Input, Width, IsSigned, RM, IsExact);
}
APFloat::opStatus DoubleAPFloat::convertFromAPInt(const APInt &Input,
bool IsSigned,
roundingMode RM) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat Tmp(semPPCDoubleDoubleLegacy);
auto Ret = Tmp.convertFromAPInt(Input, IsSigned, RM);
*this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
return Ret;
}
APFloat::opStatus
DoubleAPFloat::convertFromSignExtendedInteger(const integerPart *Input,
unsigned int InputSize,
bool IsSigned, roundingMode RM) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat Tmp(semPPCDoubleDoubleLegacy);
auto Ret = Tmp.convertFromSignExtendedInteger(Input, InputSize, IsSigned, RM);
*this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
return Ret;
}
APFloat::opStatus
DoubleAPFloat::convertFromZeroExtendedInteger(const integerPart *Input,
unsigned int InputSize,
bool IsSigned, roundingMode RM) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat Tmp(semPPCDoubleDoubleLegacy);
auto Ret = Tmp.convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM);
*this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
return Ret;
}
unsigned int DoubleAPFloat::convertToHexString(char *DST,
unsigned int HexDigits,
bool UpperCase,
roundingMode RM) const {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
return APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt())
.convertToHexString(DST, HexDigits, UpperCase, RM);
}
bool DoubleAPFloat::isDenormal() const {
return getCategory() == fcNormal &&
(Floats[0].isDenormal() || Floats[1].isDenormal() ||
Floats[0] != Floats[0] + Floats[1]);
}
bool DoubleAPFloat::isSmallest() const {
if (getCategory() != fcNormal)
return false;
DoubleAPFloat Tmp(*this);
Tmp.makeSmallest(this->isNegative());
return Tmp.compare(*this) == cmpEqual;
}
bool DoubleAPFloat::isLargest() const {
if (getCategory() != fcNormal)
return false;
DoubleAPFloat Tmp(*this);
Tmp.makeLargest(this->isNegative());
return Tmp.compare(*this) == cmpEqual;
}
bool DoubleAPFloat::isInteger() const {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
return Floats[0].isInteger() && Floats[1].isInteger();
}
void DoubleAPFloat::toString(SmallVectorImpl<char> &Str,
unsigned FormatPrecision,
unsigned FormatMaxPadding,
bool TruncateZero) const {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt())
.toString(Str, FormatPrecision, FormatMaxPadding, TruncateZero);
}
bool DoubleAPFloat::getExactInverse(APFloat *inv) const {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
if (!inv)
return Tmp.getExactInverse(nullptr);
APFloat Inv(semPPCDoubleDoubleLegacy);
auto Ret = Tmp.getExactInverse(&Inv);
*inv = APFloat(semPPCDoubleDouble, Inv.bitcastToAPInt());
return Ret;
}
DoubleAPFloat scalbn(const DoubleAPFloat &Arg, int Exp,
APFloat::roundingMode RM) {
assert(Arg.Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
return DoubleAPFloat(semPPCDoubleDouble, scalbn(Arg.Floats[0], Exp, RM),
scalbn(Arg.Floats[1], Exp, RM));
}
DoubleAPFloat frexp(const DoubleAPFloat &Arg, int &Exp,
APFloat::roundingMode RM) {
assert(Arg.Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
APFloat First = frexp(Arg.Floats[0], Exp, RM);
APFloat Second = Arg.Floats[1];
if (Arg.getCategory() == APFloat::fcNormal)
Second = scalbn(Second, -Exp, RM);
return DoubleAPFloat(semPPCDoubleDouble, std::move(First), std::move(Second));
}
}
APFloat::Storage::Storage(IEEEFloat F, const fltSemantics &Semantics) {
if (usesLayout<IEEEFloat>(Semantics)) {
new (&IEEE) IEEEFloat(std::move(F));
return;
}
if (usesLayout<DoubleAPFloat>(Semantics)) {
const fltSemantics& S = F.getSemantics();
new (&Double)
DoubleAPFloat(Semantics, APFloat(std::move(F), S),
APFloat(semIEEEdouble));
return;
}
llvm_unreachable("Unexpected semantics");
}
Expected<APFloat::opStatus> APFloat::convertFromString(StringRef Str,
roundingMode RM) {
APFLOAT_DISPATCH_ON_SEMANTICS(convertFromString(Str, RM));
}
hash_code hash_value(const APFloat &Arg) {
if (APFloat::usesLayout<detail::IEEEFloat>(Arg.getSemantics()))
return hash_value(Arg.U.IEEE);
if (APFloat::usesLayout<detail::DoubleAPFloat>(Arg.getSemantics()))
return hash_value(Arg.U.Double);
llvm_unreachable("Unexpected semantics");
}
APFloat::APFloat(const fltSemantics &Semantics, StringRef S)
: APFloat(Semantics) {
auto StatusOrErr = convertFromString(S, rmNearestTiesToEven);
assert(StatusOrErr && "Invalid floating point representation");
consumeError(StatusOrErr.takeError());
}
APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics,
roundingMode RM, bool *losesInfo) {
if (&getSemantics() == &ToSemantics) {
*losesInfo = false;
return opOK;
}
if (usesLayout<IEEEFloat>(getSemantics()) &&
usesLayout<IEEEFloat>(ToSemantics))
return U.IEEE.convert(ToSemantics, RM, losesInfo);
if (usesLayout<IEEEFloat>(getSemantics()) &&
usesLayout<DoubleAPFloat>(ToSemantics)) {
assert(&ToSemantics == &semPPCDoubleDouble);
auto Ret = U.IEEE.convert(semPPCDoubleDoubleLegacy, RM, losesInfo);
*this = APFloat(ToSemantics, U.IEEE.bitcastToAPInt());
return Ret;
}
if (usesLayout<DoubleAPFloat>(getSemantics()) &&
usesLayout<IEEEFloat>(ToSemantics)) {
auto Ret = getIEEE().convert(ToSemantics, RM, losesInfo);
*this = APFloat(std::move(getIEEE()), ToSemantics);
return Ret;
}
llvm_unreachable("Unexpected semantics");
}
APFloat APFloat::getAllOnesValue(const fltSemantics &Semantics) {
return APFloat(Semantics, APInt::getAllOnes(Semantics.sizeInBits));
}
void APFloat::print(raw_ostream &OS) const {
SmallVector<char, 16> Buffer;
toString(Buffer);
OS << Buffer << "\n";
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void APFloat::dump() const { print(dbgs()); }
#endif
void APFloat::Profile(FoldingSetNodeID &NID) const {
NID.Add(bitcastToAPInt());
}
APFloat::opStatus APFloat::convertToInteger(APSInt &result,
roundingMode rounding_mode,
bool *isExact) const {
unsigned bitWidth = result.getBitWidth();
SmallVector<uint64_t, 4> parts(result.getNumWords());
opStatus status = convertToInteger(parts, bitWidth, result.isSigned(),
rounding_mode, isExact);
result = APInt(bitWidth, parts);
return status;
}
double APFloat::convertToDouble() const {
if (&getSemantics() == (const llvm::fltSemantics *)&semIEEEdouble)
return getIEEE().convertToDouble();
assert(getSemantics().isRepresentableBy(semIEEEdouble) &&
"Float semantics is not representable by IEEEdouble");
APFloat Temp = *this;
bool LosesInfo;
opStatus St = Temp.convert(semIEEEdouble, rmNearestTiesToEven, &LosesInfo);
assert(!(St & opInexact) && !LosesInfo && "Unexpected imprecision");
(void)St;
return Temp.getIEEE().convertToDouble();
}
float APFloat::convertToFloat() const {
if (&getSemantics() == (const llvm::fltSemantics *)&semIEEEsingle)
return getIEEE().convertToFloat();
assert(getSemantics().isRepresentableBy(semIEEEsingle) &&
"Float semantics is not representable by IEEEsingle");
APFloat Temp = *this;
bool LosesInfo;
opStatus St = Temp.convert(semIEEEsingle, rmNearestTiesToEven, &LosesInfo);
assert(!(St & opInexact) && !LosesInfo && "Unexpected imprecision");
(void)St;
return Temp.getIEEE().convertToFloat();
}
}
#undef APFLOAT_DISPATCH_ON_SEMANTICS