#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/ErrorHandling.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))
hexadecimal strings. */
static_assert(APFloatBase::integerPartWidth % 4 == 0, "Part width must be divisible by 4!");
namespace llvm {
struct fltSemantics {
definition of IEEE 754. */
APFloatBase::ExponentType maxExponent;
matches the definition of IEEE 754. */
APFloatBase::ExponentType minExponent;
bit. */
unsigned int precision;
unsigned int sizeInBits;
};
static const fltSemantics semIEEEhalf = {15, -14, 11, 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};
64-bit doubles (Hi, Lo), where |Hi| > |Lo|, and if normal,
(double)(Hi + Lo) == Hi. The numeric value it's modeling is Hi + Lo.
Therefore it has two 53-bit mantissa parts that aren't necessarily adjacent
to each other, and two 11-bit exponents.
Note: we need to make the value different from semBogus as otherwise
an unsafe optimization may collapse both values to a single address,
and we heavily rely on them having distinct addresses. */
static const fltSemantics semPPCDoubleDouble = {-1, 0, 0, 0};
IBM double-double, if the accurate semPPCDoubleDouble doesn't handle the
operation. It's equivalent to having an IEEE number with consecutive 106
bits of mantissa and 11 bits of exponent.
It's not equivalent to IBM double-double. For example, a legit IBM
double-double, 1 + epsilon:
1 + epsilon = 1 + (1 >> 1076)
is not representable by a consecutive 106 bits of mantissa.
Currently, these semantics are used in the following way:
semPPCDoubleDouble -> (IEEEdouble, IEEEdouble) ->
(64-bit APInt, 64-bit APInt) -> (128-bit APInt) ->
semPPCDoubleDoubleLegacy -> IEEE operations
We use bitcastToAPInt() to get the bit representation (in APInt) of the
underlying IEEEdouble, then use the APInt constructor to construct the
legacy IEEE float.
TODO: Implement all operations in semPPCDoubleDouble, and delete these
semantics. */
static const fltSemantics semPPCDoubleDoubleLegacy = {1023, -1022 + 53,
53 + 53, 128};
const fltSemantics &APFloatBase::IEEEhalf() {
return semIEEEhalf;
}
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;
}
pow(5, power) is
power * 815 / (351 * integerPartWidth) + 1
However, whilst the result may require only this many parts,
because we are multiplying two values to get it, the
multiplication may require an extra part with the excess part
being zero (consider the trivial case of 1 * 1, tcFullMultiply
requires two parts to hold the single-part result). So we add an
extra one to guarantee enough space whilst multiplying. */
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 unsigned int
partCountForBits(unsigned int bits)
{
return ((bits) + APFloatBase::integerPartWidth - 1) / APFloatBase::integerPartWidth;
}
static inline unsigned int
decDigitValue(unsigned int c)
{
return c - '0';
}
[+-]ddddddd.
If the exponent overflows, returns a large exponent with the
appropriate sign. */
static int
readExponent(StringRef::iterator begin, StringRef::iterator end)
{
bool isNegative;
unsigned int absExponent;
const unsigned int overlargeExponent = 24000;
StringRef::iterator p = begin;
assert(p != end && "Exponent has no digits");
isNegative = (*p == '-');
if (*p == '-' || *p == '+') {
p++;
assert(p != end && "Exponent has no digits");
}
absExponent = decDigitValue(*p++);
assert(absExponent < 10U && "Invalid character in exponent");
for (; p != end; ++p) {
unsigned int value;
value = decDigitValue(*p);
assert(value < 10U && "Invalid character in exponent");
value += absExponent * 10;
if (absExponent >= overlargeExponent) {
absExponent = overlargeExponent;
p = end;
break;
}
absExponent = value;
}
assert(p == end && "Invalid exponent in exponent");
if (isNegative)
return -(int) absExponent;
else
return (int) absExponent;
}
how whilst remaining safe. */
static int
totalExponent(StringRef::iterator p, StringRef::iterator end,
int exponentAdjustment)
{
int unsignedExponent;
bool negative, overflow;
int exponent = 0;
assert(p != end && "Exponent has no digits");
negative = *p == '-';
if (*p == '-' || *p == '+') {
p++;
assert(p != end && "Exponent has no digits");
}
unsignedExponent = 0;
overflow = false;
for (; p != end; ++p) {
unsigned int value;
value = decDigitValue(*p);
assert(value < 10U && "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 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++;
assert(end - begin != 1 && "Significand has no digits");
while (p != end && *p == '0')
p++;
}
return p;
}
dddd.dddd[eE][+-]ddd
where the decimal point and exponent are optional, fill out the
structure D. Exponent is appropriate if the significand is
treated as an integer, and normalizedExponent if the significand
is taken to have the decimal point after a single leading
non-zero digit.
If the value is zero, V->firstSigDigit points to a non-digit, and
the return exponent is zero.
*/
struct decimalInfo {
const char *firstSigDigit;
const char *lastSigDigit;
int exponent;
int normalizedExponent;
};
static void
interpretDecimal(StringRef::iterator begin, StringRef::iterator end,
decimalInfo *D)
{
StringRef::iterator dot = end;
StringRef::iterator p = skipLeadingZeroesAndAnyDot (begin, end, &dot);
D->firstSigDigit = p;
D->exponent = 0;
D->normalizedExponent = 0;
for (; p != end; ++p) {
if (*p == '.') {
assert(dot == end && "String contains multiple dots");
dot = p++;
if (p == end)
break;
}
if (decDigitValue(*p) >= 10U)
break;
}
if (p != end) {
assert((*p == 'e' || *p == 'E') && "Invalid character in significand");
assert(p != begin && "Significand has no digits");
assert((dot == end || p - begin != 1) && "Significand has no digits");
D->exponent = readExponent(p + 1, end);
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;
}
DIGITVALUE is the first hex digit of the fraction, P points to
the next digit. */
static lostFraction
trailingHexadecimalFraction(StringRef::iterator p, StringRef::iterator end,
unsigned int digitValue)
{
unsigned int hexDigit;
fraction immediately. */
if (digitValue > 8)
return lfMoreThanHalf;
else if (digitValue < 8 && digitValue > 0)
return lfLessThanHalf;
while (p != end && (*p == '0' || *p == '.'))
p++;
assert(p != end && "Invalid trailing hexadecimal fraction!");
hexDigit = hexDigitValue(*p);
a little more. */
if (hexDigit == -1U)
return digitValue == 0 ? lfExactlyZero: lfExactlyHalf;
else
return digitValue == 0 ? lfLessThanHalf: lfMoreThanHalf;
}
significant BITS bits. */
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;
}
floating point numbers, which differ from the value they
approximate by at most HUE1 and HUE2 half-ulps, is strictly less
than the returned value.
See "How to Read Floating Point Numbers Accurately" by William D
Clinger. */
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);
}
when the least significant BITS are truncated. BITS cannot be
zero. */
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;
}
DST must be at least one part larger than size of the answer. */
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--;
space. */
tmp = p1;
p1 = p2;
p2 = tmp;
}
pow5 += pc;
}
if (p1 != dst)
APInt::tcAssign(dst, p1, result);
return result;
}
when rounding up during hexadecimal output. */
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";
significant nibble. Write out exactly COUNT hexdigits, return
COUNT. */
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());
}
for the significand. If double or longer, this is a signalling NaN,
which may not be ideal. If float, this is QNaN(0). */
void IEEEFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill) {
category = fcNaN;
sign = Negative;
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 = partCount();
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 "
"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 = partCount();
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);
category = fcZero;
sign = 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());
}
the borrow flag. */
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());
}
on to the full-precision result of the multiplication. Returns the
lost fraction. */
lostFraction IEEEFloat::multiplySignificand(const IEEEFloat &rhs,
const 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 && 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::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);
}
Incidentally, this means that the division loop below is
guaranteed to set the integer bit to one. */
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;
significands. */
if (compare == 0)
compare = APInt::tcCompare(significandParts(), rhs.significandParts(),
partCount());
if (compare > 0)
return cmpGreaterThan;
else if (compare < 0)
return cmpLessThan;
else
return cmpEqual;
}
the largest finite number. */
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;
APInt::tcSetLeastSignificantBits(significandParts(), partCount(),
semantics->precision);
return opInexact;
}
new LSB, with the given lost fraction and rounding mode, the result
would need to be rounded away from zero (i.e., by increasing the
signficand). This routine must work for fcZero of both signs, and
fcNormal numbers. */
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;
}
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) {
bit numbered PRECISION if possible, with a compensating change in
the exponent. */
exponentChange = omsb - semantics->precision;
the rounding mode. */
if (exponent + exponentChange > semantics->maxExponent)
return handleOverflow(rounding_mode);
is forced based on that. */
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;
}
}
fraction. */
underflow for exact results. */
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) {
significand right one. However if we already have the
maximum exponent we overflow to infinity. */
if (exponent == semantics->maxExponent) {
category = fcInfinity;
return (opStatus) (opOverflow | opInexact);
}
shiftSignificandRight(1);
return opInexact;
}
}
significand increment above didn't overflow. */
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(fcNaN, fcZero):
case PackCategoriesIntoKey(fcNaN, fcNormal):
case PackCategoriesIntoKey(fcNaN, fcInfinity):
case PackCategoriesIntoKey(fcNaN, fcNaN):
case PackCategoriesIntoKey(fcNormal, fcZero):
case PackCategoriesIntoKey(fcInfinity, fcNormal):
case PackCategoriesIntoKey(fcInfinity, fcZero):
return opOK;
case PackCategoriesIntoKey(fcZero, fcNaN):
case PackCategoriesIntoKey(fcNormal, fcNaN):
case PackCategoriesIntoKey(fcInfinity, fcNaN):
// We need to be sure to flip the sign here for subtraction because we
// don't have a separate negate operation so -NaN becomes 0 - NaN here.
sign = rhs.sign ^ subtract;
category = fcNaN;
copySignificand(rhs);
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):
/* Sign depends on rounding mode; handled by caller. */
return opOK;
case PackCategoriesIntoKey(fcInfinity, fcInfinity):
/* Differently signed infinities can only be validly
subtracted. */
if (((sign ^ rhs.sign)!=0) != subtract) {
makeNaN();
return opInvalidOp;
}
return opOK;
case PackCategoriesIntoKey(fcNormal, fcNormal):
return opDivByZero;
}
}
/* Add or subtract two normal numbers. */
lostFraction IEEEFloat::addOrSubtractSignificand(const IEEEFloat &rhs,
bool subtract) {
integerPart carry;
lostFraction lost_fraction;
int bits;
/* Determine if the operation on the absolute values is effectively
an addition or subtraction. */
subtract ^= static_cast<bool>(sign ^ rhs.sign);
/* Are we bigger exponent-wise than the RHS? */
bits = exponent - rhs.exponent;
/* Subtraction is more subtle than one might naively expect. */
if (subtract) {
IEEEFloat temp_rhs(rhs);
bool reverse;
if (bits == 0) {
reverse = compareAbsoluteValue(temp_rhs) == cmpLessThan;
lost_fraction = lfExactlyZero;
} else if (bits > 0) {
lost_fraction = temp_rhs.shiftSignificandRight(bits - 1);
shiftSignificandLeft(1);
reverse = false;
} else {
lost_fraction = shiftSignificandRight(-bits - 1);
temp_rhs.shiftSignificandLeft(1);
reverse = true;
}
if (reverse) {
carry = temp_rhs.subtractSignificand
(*this, lost_fraction != lfExactlyZero);
copySignificand(temp_rhs);
sign = !sign;
} else {
carry = subtractSignificand
(temp_rhs, lost_fraction != lfExactlyZero);
}
/* Invert the lost fraction - it was on the RHS and
subtracted. */
if (lost_fraction == lfLessThanHalf)
lost_fraction = lfMoreThanHalf;
else if (lost_fraction == lfMoreThanHalf)
lost_fraction = lfLessThanHalf;
/* The code above is intended to ensure that no borrow is
necessary. */
assert(!carry);
(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);
}
/* We have a guard bit; generating a carry cannot happen. */
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(fcNaN, fcZero):
case PackCategoriesIntoKey(fcNaN, fcNormal):
case PackCategoriesIntoKey(fcNaN, fcInfinity):
case PackCategoriesIntoKey(fcNaN, fcNaN):
sign = false;
return opOK;
case PackCategoriesIntoKey(fcZero, fcNaN):
case PackCategoriesIntoKey(fcNormal, fcNaN):
case PackCategoriesIntoKey(fcInfinity, fcNaN):
sign = false;
category = fcNaN;
copySignificand(rhs);
return 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):
category = fcNaN;
copySignificand(rhs);
LLVM_FALLTHROUGH;
case PackCategoriesIntoKey(fcNaN, fcZero):
case PackCategoriesIntoKey(fcNaN, fcNormal):
case PackCategoriesIntoKey(fcNaN, fcInfinity):
case PackCategoriesIntoKey(fcNaN, fcNaN):
sign = false;
LLVM_FALLTHROUGH;
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(fcNaN, fcZero):
case PackCategoriesIntoKey(fcNaN, fcNormal):
case PackCategoriesIntoKey(fcNaN, fcInfinity):
case PackCategoriesIntoKey(fcNaN, fcNaN):
case PackCategoriesIntoKey(fcZero, fcInfinity):
case PackCategoriesIntoKey(fcZero, fcNormal):
case PackCategoriesIntoKey(fcNormal, fcInfinity):
return opOK;
case PackCategoriesIntoKey(fcZero, fcNaN):
case PackCategoriesIntoKey(fcNormal, fcNaN):
case PackCategoriesIntoKey(fcInfinity, fcNaN):
sign = false;
category = fcNaN;
copySignificand(rhs);
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;
}
}
/* Change sign. */
void IEEEFloat::changeSign() {
/* Look mummy, this one's easy. */
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);
}
positive zero unless rounding to minus infinity, except that
adding two like-signed zeroes gives that zero. */
if (category == fcZero) {
if (rhs.category != fcZero || (sign == rhs.sign) == subtract)
sign = (rounding_mode == rmTowardNegative);
}
return fs;
}
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, nullptr);
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;
IEEEFloat V = *this;
unsigned int origSign = sign;
fs = V.divide(rhs, rmNearestTiesToEven);
if (fs == opDivByZero)
return fs;
int parts = partCount();
integerPart *x = new integerPart[parts];
bool ignored;
fs = V.convertToInteger(makeMutableArrayRef(x, parts),
parts * integerPartWidth, true, rmNearestTiesToEven,
&ignored);
if (fs == opInvalidOp) {
delete[] x;
return fs;
}
fs = V.convertFromZeroExtendedInteger(x, parts * integerPartWidth, true,
rmNearestTiesToEven);
assert(fs==opOK);
fs = V.multiply(rhs, rmNearestTiesToEven);
assert(fs==opOK || fs==opInexact);
fs = subtract(V, rmNearestTiesToEven);
assert(fs==opOK || fs==opInexact);
if (isZero())
sign = origSign;
delete[] x;
return fs;
}
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;
extended-precision calculation. */
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);
positive zero unless rounding to minus infinity, except that
adding two like-signed zeroes gives that zero. */
if (category == fcZero && !(fs & opUnderflow) && sign != addend.sign)
sign = (rounding_mode == rmTowardNegative);
} else {
fs = multiplySpecials(multiplicand);
to do in the latter case. The IEEE-754R standard says it is
implementation-defined in this case whether, if ADDEND is a
quiet NaN, we raise invalid op; this implementation does so.
If we need to do the addition we can do so with normal
precision. */
if (fs == opOK)
fs = addOrSubtract(addend, rounding_mode, false);
}
return fs;
}
IEEEFloat::opStatus IEEEFloat::roundToIntegral(roundingMode rounding_mode) {
opStatus fs;
if (isFiniteNonZero() && 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);
MagicConstant.sign = sign;
if (fs != opOK)
return fs;
bool inputSign = isNegative();
fs = add(MagicConstant, rounding_mode);
if (fs != opOK && fs != opInexact)
return fs;
fs = 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 exponentChange = significandMSB() + 1 - fromSemantics.precision;
if (exponent + exponentChange < toSemantics.minExponent)
exponentChange = toSemantics.minExponent - exponent;
if (exponentChange < shift)
exponentChange = shift;
if (exponentChange < 0) {
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);
fs = opOK;
} else {
*losesInfo = false;
fs = opOK;
}
return fs;
}
rounding mode. If the rounded integer value is out of range this
returns an invalid operation exception and the contents of the
destination parts are unspecified. If the rounded value is in
range but the floating point number is not the exact integer, the C
standard doesn't require an inexact exception to be raised. IEEE
854 does require it so we do that.
Note that for conversions to integer type the C standard requires
round-to-zero to always be used. */
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();
the destination. */
if (exponent < 0) {
APInt::tcSet(parts.data(), 0, dstPartsCount);
For smaller exponents leftmost truncated bit is 0. */
truncatedBits = semantics->precision -1U - exponent;
} else {
truncated. */
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;
}
}
value if we would round away from zero. */
if (truncatedBits) {
lost_fraction = lostFractionThroughTruncation(src, partCount(),
truncatedBits);
if (lost_fraction != lfExactlyZero &&
roundAwayFromZero(rounding_mode, lost_fraction, truncatedBits)) {
if (APInt::tcIncrement(parts.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 {
We lose a bit for the sign, but care is needed as the
maximally negative integer is a special case. */
if (omsb == width &&
APInt::tcLSB(parts.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;
}
deterministic values in case of an invalid operation exception,
namely zero for NaNs and the minimal or maximal value respectively
for underflow or overflow.
The *isExact output tells whether the result is exact, in the sense
that converting it back to the original floating point type produces
the original value. This is almost equivalent to result==opOK,
except for negative zeroes.
*/
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;
APInt::tcSetLeastSignificantBits(parts.data(), dstPartsCount, bits);
if (sign && isSigned)
APInt::tcShiftLeft(parts.data(), dstPartsCount, width - 1);
}
return fs;
}
rounding according to ROUNDING_MODE. The sign of the floating
point number is not modified. */
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;
be that many; extract what we can. */
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);
}
rounding according to ROUNDING_MODE. ISSIGNED is true if the
integer is signed, in which case it must be sign-extended. */
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);
}
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;
StringRef::iterator p = skipLeadingZeroesAndAnyDot(begin, end, &dot);
StringRef::iterator firstSignificantDigit = p;
while (p != end) {
integerPart hex_value;
if (*p == '.') {
assert(dot == end && "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) {
lost_fraction = trailingHexadecimalFraction(p, end, hex_value);
computedTrailingFraction = true;
}
}
assert(p != end && "Hex strings require an exponent");
assert((*p == 'p' || *p == 'P') && "Invalid character in significand");
assert(p != begin && "Significand has no digits");
assert((dot == end || p - begin != 1) && "Significand has no digits");
if (p != firstSignificantDigit) {
int expAdjustment;
if (dot == end)
dot = p;
significant digits. */
expAdjustment = static_cast<int>(dot - firstSignificantDigit);
if (expAdjustment < 0)
expAdjustment++;
expAdjustment = expAdjustment * 4 - 1;
significant nibble. */
expAdjustment += semantics->precision;
expAdjustment -= partsCount * integerPartWidth;
exponent = totalExponent(p + 1, end, expAdjustment);
}
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, nullptr);
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;
}
result with the integer bit set. */
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);
above we must adjust our exponent to compensate for the
implicit right shift. */
exponent = (decSig.exponent + semantics->precision
- (calcSemantics.precision - excessPrecision));
calcLostFraction = lostFractionThroughTruncation(decSig.significandParts(),
decSig.partCount(),
truncatedBits);
return normalize(rounding_mode, calcLostFraction);
}
}
}
IEEEFloat::opStatus
IEEEFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) {
decimalInfo D;
opStatus fs;
StringRef::iterator p = str.begin();
interpretDecimal(p, str.end(), &D);
i.e. zero, and then exponents that are obviously too large or too
small. Writing L for log 10 / log 2, a number d.ddddd*10^exp
definitely overflows if
(exp - 1) * L >= maxExponent
and definitely underflows to zero where
(exp + 1) * L <= minExponent - precision
With integer arithmetic the tightest bounds for L are
93/28 < L < 196/59 [ numerator <= 256 ]
42039/12655 < L < 28738/8651 [ numerator <= 65536 ]
*/
if (D.firstSigDigit == str.end() || decDigitValue(*D.firstSigDigit) >= 10U) {
category = fcZero;
fs = opOK;
max during the log-rebasing in the max-exponent check below. */
} else if (D.normalizedExponent - 1 > INT_MAX / 42039) {
fs = handleOverflow(rounding_mode);
during the log-rebasing in the min-exponent check. Check that it
won't overflow min in either check, then perform the min-exponent
check. */
} 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;
N-digit decimal integer is N * 196 / 59. Allocate enough space
to hold the full significand, and an extra part required by
tcMultiplyPart. */
partCount = static_cast<unsigned int>(D.lastSigDigit - D.firstSigDigit) + 1;
partCount = partCountForBits(1 + 196 * partCount / 59);
decSignificand = new integerPart[partCount + 1];
partCount = 0;
in an integerPart. When this would overflow do we do a single
bignum multiplication, and then revert again to multiplication
in an integerPart. */
do {
integerPart decValue, val, multiplier;
val = 0;
multiplier = 1;
do {
if (*p == '.') {
p++;
if (p == str.end()) {
break;
}
}
decValue = decDigitValue(*p++);
assert(decValue < 10U && "Invalid character in significand");
multiplier *= 10;
val = val * 10 + decValue;
digit added without overflowing an integerPart. */
} while (p <= D.lastSigDigit && multiplier <= (~ (integerPart) 0 - 9) / 10);
APInt::tcMultiplyPart(decSignificand, decSignificand, multiplier, val,
partCount, partCount + 1, false);
the count. */
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) {
if (str.equals("inf") || str.equals("INFINITY") || str.equals("+Inf")) {
makeInf(false);
return true;
}
if (str.equals("-inf") || str.equals("-INFINITY") || str.equals("-Inf")) {
makeInf(true);
return true;
}
if (str.equals("nan") || str.equals("NaN")) {
makeNaN(false, false);
return true;
}
if (str.equals("-nan") || str.equals("-NaN")) {
makeNaN(false, true);
return true;
}
return false;
}
IEEEFloat::opStatus IEEEFloat::convertFromString(StringRef str,
roundingMode rounding_mode) {
assert(!str.empty() && "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--;
assert(slen && "String has no digits");
}
if (slen >= 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
assert(slen - 2 && "Invalid string");
return convertFromHexadecimalString(StringRef(p + 2, slen - 2),
rounding_mode);
}
return convertFromDecimalString(StringRef(p, slen), rounding_mode);
}
to DST, which must be of sufficient size, in the C99 form
[-]0xh.hhhhp[+-]d. Return the number of characters written,
excluding the terminating NUL.
If UPPERCASE, the output is in upper case, otherwise in lower case.
HEXDIGITS digits appear altogether, rounding the value if
necessary. If HEXDIGITS is 0, the minimal precision to display the
number precisely is used instead. If nothing would appear after
the decimal point it is suppressed.
The decimal exponent is always printed and has at least one digit.
Zero values display an exponent of zero. Infinities and NaNs
appear as "infinity" or "nan" respectively.
The above rules are as specified by C99. There is ambiguity about
what the leading hexadecimal digit should be. This implementation
uses whatever is necessary so that the exponent is displayed as
stored. This implies the exponent will fall within the IEEE format
range, and the leading hexadecimal digit will be 0 (for denormals),
1 (normal numbers) or 2 (normal numbers rounded-away-from-zero with
any other digits zero).
*/
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);
}
form of a normal floating point number with the specified number of
hexadecimal digits. If HEXDIGITS is zero the minimum number of
digits necessary to print the value precisely is output. */
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();
we have 3 virtual zero most-significant-bits. */
valueBits = semantics->precision + 3;
shift = integerPartWidth - valueBits % integerPartWidth;
insignificant zeroes. */
outputDigits = (valueBits - significandLSB () + 3) / 4;
precision. Otherwise, see if we are truncating. If we are,
find out if we need to round away from zero. */
if (hexDigits) {
if (hexDigits < outputDigits) {
"bits" is the number of dropped bits. */
unsigned int bits;
lostFraction fraction;
bits = valueBits - hexDigits * 4;
fraction = lostFractionThroughTruncation (significand, partsCount, bits);
roundUp = roundAwayFromZero(rounding_mode, fraction, bits);
}
outputDigits = hexDigits;
}
of the hexadecimal point. We move the most significant digit
left and add the hexadecimal point later. */
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;
}
is something after the decimal point add it. This must come
after rounding above. */
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::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*)&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) {
assert(api.getBitWidth()==80);
uint64_t i1 = api.getRawData()[0];
uint64_t i2 = api.getRawData()[1];
uint64_t myexponent = (i2 & 0x7fff);
uint64_t mysignificand = i1;
uint8_t myintegerbit = mysignificand >> 63;
initialize(&semX87DoubleExtended);
assert(partCount()==2);
sign = static_cast<unsigned int>(i2>>15);
if (myexponent == 0 && mysignificand == 0) {
category = fcZero;
} else if (myexponent==0x7fff && mysignificand==0x8000000000000000ULL) {
category = fcInfinity;
} else if ((myexponent == 0x7fff && mysignificand != 0x8000000000000000ULL) ||
(myexponent != 0x7fff && myexponent != 0 && myintegerbit == 0)) {
category = fcNaN;
significandParts()[0] = mysignificand;
significandParts()[1] = 0;
} else {
category = fcNormal;
exponent = myexponent - 16383;
significandParts()[0] = mysignificand;
significandParts()[1] = 0;
if (myexponent==0)
exponent = -16382;
}
}
void IEEEFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) {
assert(api.getBitWidth()==128);
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) {
assert(api.getBitWidth()==128);
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)) {
category = fcZero;
} else if (myexponent==0x7fff &&
(mysignificand==0 && mysignificand2==0)) {
category = fcInfinity;
} else if (myexponent==0x7fff &&
(mysignificand!=0 || mysignificand2 !=0)) {
category = fcNaN;
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) {
assert(api.getBitWidth()==64);
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) {
category = fcZero;
} else if (myexponent==0x7ff && mysignificand==0) {
category = fcInfinity;
} else if (myexponent==0x7ff && mysignificand!=0) {
category = fcNaN;
*significandParts() = mysignificand;
} else {
category = fcNormal;
exponent = myexponent - 1023;
*significandParts() = mysignificand;
if (myexponent==0)
exponent = -1022;
else
*significandParts() |= 0x10000000000000LL;
}
}
void IEEEFloat::initFromFloatAPInt(const APInt &api) {
assert(api.getBitWidth()==32);
uint32_t i = (uint32_t)*api.getRawData();
uint32_t myexponent = (i >> 23) & 0xff;
uint32_t mysignificand = i & 0x7fffff;
initialize(&semIEEEsingle);
assert(partCount()==1);
sign = i >> 31;
if (myexponent==0 && mysignificand==0) {
category = fcZero;
} else if (myexponent==0xff && mysignificand==0) {
category = fcInfinity;
} else if (myexponent==0xff && mysignificand!=0) {
category = fcNaN;
*significandParts() = mysignificand;
} else {
category = fcNormal;
exponent = myexponent - 127;
*significandParts() = mysignificand;
if (myexponent==0)
exponent = -126;
else
*significandParts() |= 0x800000;
}
}
void IEEEFloat::initFromHalfAPInt(const APInt &api) {
assert(api.getBitWidth()==16);
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) {
category = fcZero;
} else if (myexponent==0x1f && mysignificand==0) {
category = fcInfinity;
} else if (myexponent==0x1f && mysignificand!=0) {
category = fcNaN;
*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) {
if (Sem == &semIEEEhalf)
return initFromHalfAPInt(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;
}
void IEEEFloat::makeInf(bool Negative) {
category = fcInfinity;
sign = Negative;
exponent = semantics->maxExponent + 1;
APInt::tcSet(significandParts(), 0, partCount());
}
void IEEEFloat::makeZero(bool Negative) {
category = fcZero;
sign = Negative;
exponent = semantics->minExponent-1;
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;
common ancestor of the following layered graph gives the correct
return category:
NaN
/ \
Zero Inf
\ /
Normal
e.g. NaN * NaN = NaN
Zero * Inf = NaN
Normal * Zero = Zero
Normal * Inf = Inf
*/
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);
}
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].compare(Floats[0] + Floats[1]) != cmpEqual);
}
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(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)) {
new (&Double)
DoubleAPFloat(Semantics, APFloat(std::move(F), F.getSemantics()),
APFloat(semIEEEdouble));
return;
}
llvm_unreachable("Unexpected semantics");
}
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) {
convertFromString(S, rmNearestTiesToEven);
}
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(unsigned BitWidth, bool isIEEE) {
if (isIEEE) {
switch (BitWidth) {
case 16:
return APFloat(semIEEEhalf, APInt::getAllOnesValue(BitWidth));
case 32:
return APFloat(semIEEEsingle, APInt::getAllOnesValue(BitWidth));
case 64:
return APFloat(semIEEEdouble, APInt::getAllOnesValue(BitWidth));
case 80:
return APFloat(semX87DoubleExtended, APInt::getAllOnesValue(BitWidth));
case 128:
return APFloat(semIEEEquad, APInt::getAllOnesValue(BitWidth));
default:
llvm_unreachable("Unknown floating bit width");
}
} else {
assert(BitWidth == 128);
return APFloat(semPPCDoubleDouble, APInt::getAllOnesValue(BitWidth));
}
}
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());
}
an APSInt, whose initial bit-width and signed-ness are used to determine the
precision of the conversion.
*/
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;
}
}
#undef APFLOAT_DISPATCH_ON_SEMANTICS