mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-04-01 07:11:45 +00:00
Reapply r285351 "[APFloat] Add DoubleAPFloat mode to APFloat. NFC." with
a workaround for old clang. llvm-svn: 285358
This commit is contained in:
parent
cc4c35bbfd
commit
f0b97e5679
@ -18,12 +18,15 @@
|
||||
#define LLVM_ADT_APFLOAT_H
|
||||
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
struct fltSemantics;
|
||||
class APSInt;
|
||||
class StringRef;
|
||||
class APFloat;
|
||||
|
||||
template <typename T> class SmallVectorImpl;
|
||||
|
||||
@ -206,13 +209,12 @@ struct APFloatBase {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class IEEEFloat : public APFloatBase {
|
||||
class IEEEFloat final : public APFloatBase {
|
||||
public:
|
||||
/// \name Constructors
|
||||
/// @{
|
||||
|
||||
IEEEFloat(const fltSemantics &); // Default construct to 0.0
|
||||
IEEEFloat(const fltSemantics &, StringRef);
|
||||
IEEEFloat(const fltSemantics &, integerPart);
|
||||
IEEEFloat(const fltSemantics &, uninitializedTag);
|
||||
IEEEFloat(const fltSemantics &, const APInt &);
|
||||
@ -230,74 +232,10 @@ public:
|
||||
/// \name Convenience "constructors"
|
||||
/// @{
|
||||
|
||||
/// Factory for Positive and Negative Zero.
|
||||
///
|
||||
/// \param Negative True iff the number should be negative.
|
||||
static IEEEFloat getZero(const fltSemantics &Sem, bool Negative = false) {
|
||||
IEEEFloat Val(Sem, uninitialized);
|
||||
Val.makeZero(Negative);
|
||||
return Val;
|
||||
}
|
||||
|
||||
/// Factory for Positive and Negative Infinity.
|
||||
///
|
||||
/// \param Negative True iff the number should be negative.
|
||||
static IEEEFloat getInf(const fltSemantics &Sem, bool Negative = false) {
|
||||
IEEEFloat Val(Sem, uninitialized);
|
||||
Val.makeInf(Negative);
|
||||
return Val;
|
||||
}
|
||||
|
||||
/// Factory for QNaN values.
|
||||
///
|
||||
/// \param Negative - True iff the NaN generated should be negative.
|
||||
/// \param type - The unspecified fill bits for creating the NaN, 0 by
|
||||
/// default. The value is truncated as necessary.
|
||||
static IEEEFloat getNaN(const fltSemantics &Sem, bool Negative = false,
|
||||
unsigned type = 0) {
|
||||
if (type) {
|
||||
APInt fill(64, type);
|
||||
return getQNaN(Sem, Negative, &fill);
|
||||
} else {
|
||||
return getQNaN(Sem, Negative, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
/// Factory for QNaN values.
|
||||
static IEEEFloat getQNaN(const fltSemantics &Sem, bool Negative = false,
|
||||
const APInt *payload = nullptr) {
|
||||
return makeNaN(Sem, false, Negative, payload);
|
||||
}
|
||||
|
||||
/// Factory for SNaN values.
|
||||
static IEEEFloat getSNaN(const fltSemantics &Sem, bool Negative = false,
|
||||
const APInt *payload = nullptr) {
|
||||
return makeNaN(Sem, true, Negative, payload);
|
||||
}
|
||||
|
||||
/// Returns the largest finite number in the given semantics.
|
||||
///
|
||||
/// \param Negative - True iff the number should be negative
|
||||
static IEEEFloat getLargest(const fltSemantics &Sem, bool Negative = false);
|
||||
|
||||
/// Returns the smallest (by magnitude) finite number in the given semantics.
|
||||
/// Might be denormalized, which implies a relative loss of precision.
|
||||
///
|
||||
/// \param Negative - True iff the number should be negative
|
||||
static IEEEFloat getSmallest(const fltSemantics &Sem, bool Negative = false);
|
||||
|
||||
/// Returns the smallest (by magnitude) normalized finite number in the given
|
||||
/// semantics.
|
||||
///
|
||||
/// \param Negative - True iff the number should be negative
|
||||
static IEEEFloat getSmallestNormalized(const fltSemantics &Sem,
|
||||
bool Negative = false);
|
||||
|
||||
/// Returns a float which is bitcasted from an all one value int.
|
||||
///
|
||||
/// \param BitWidth - Select float type
|
||||
/// \param isIEEE - If 128 bit number, select between PPC and IEEE
|
||||
static IEEEFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false);
|
||||
static IEEEFloat getAllOnesValue(unsigned BitWidth);
|
||||
|
||||
/// @}
|
||||
|
||||
@ -527,6 +465,25 @@ public:
|
||||
|
||||
friend IEEEFloat frexp(const IEEEFloat &X, int &Exp, roundingMode);
|
||||
|
||||
/// \name Special value setters.
|
||||
/// @{
|
||||
|
||||
void makeLargest(bool Neg = false);
|
||||
void makeSmallest(bool Neg = false);
|
||||
void makeNaN(bool SNaN = false, bool Neg = false,
|
||||
const APInt *fill = nullptr);
|
||||
void makeInf(bool Neg = false);
|
||||
void makeZero(bool Neg = false);
|
||||
void makeQuiet();
|
||||
|
||||
/// Returns the smallest (by magnitude) normalized finite number in the given
|
||||
/// semantics.
|
||||
///
|
||||
/// \param Negative - True iff the number should be negative
|
||||
void makeSmallestNormalized(bool Negative = false);
|
||||
|
||||
/// @}
|
||||
|
||||
private:
|
||||
/// \name Simple Queries
|
||||
/// @{
|
||||
@ -569,21 +526,6 @@ private:
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Special value setters.
|
||||
/// @{
|
||||
|
||||
void makeLargest(bool Neg = false);
|
||||
void makeSmallest(bool Neg = false);
|
||||
void makeNaN(bool SNaN = false, bool Neg = false,
|
||||
const APInt *fill = nullptr);
|
||||
static IEEEFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative,
|
||||
const APInt *fill);
|
||||
void makeInf(bool Neg = false);
|
||||
void makeZero(bool Neg = false);
|
||||
void makeQuiet();
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Miscellany
|
||||
/// @{
|
||||
|
||||
@ -624,6 +566,7 @@ private:
|
||||
void copySignificand(const IEEEFloat &);
|
||||
void freeSignificand();
|
||||
|
||||
/// Note: this must be the first data member.
|
||||
/// The semantics that this value obeys.
|
||||
const fltSemantics *semantics;
|
||||
|
||||
@ -653,215 +596,436 @@ int ilogb(const IEEEFloat &Arg);
|
||||
IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode);
|
||||
IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM);
|
||||
|
||||
// This mode implements more precise float in terms of two APFloats.
|
||||
// The interface and layout is designed for arbitray underlying semantics,
|
||||
// though currently only PPCDoubleDouble semantics are supported, whose
|
||||
// corresponding underlying semantics are IEEEdouble.
|
||||
class DoubleAPFloat final : public APFloatBase {
|
||||
// Note: this must be the first data member.
|
||||
const fltSemantics *Semantics;
|
||||
std::unique_ptr<APFloat[]> Floats;
|
||||
|
||||
public:
|
||||
DoubleAPFloat(const fltSemantics &S);
|
||||
DoubleAPFloat(const fltSemantics &S, uninitializedTag);
|
||||
DoubleAPFloat(const fltSemantics &S, integerPart);
|
||||
DoubleAPFloat(const fltSemantics &S, const APInt &I);
|
||||
DoubleAPFloat(const fltSemantics &S, APFloat &&First, APFloat &&Second);
|
||||
DoubleAPFloat(const DoubleAPFloat &RHS);
|
||||
DoubleAPFloat(DoubleAPFloat &&RHS);
|
||||
|
||||
DoubleAPFloat &operator=(const DoubleAPFloat &RHS);
|
||||
|
||||
DoubleAPFloat &operator=(DoubleAPFloat &&RHS) {
|
||||
if (this != &RHS) {
|
||||
this->~DoubleAPFloat();
|
||||
new (this) DoubleAPFloat(std::move(RHS));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool needsCleanup() const { return Floats != nullptr; }
|
||||
|
||||
APFloat &getFirst() { return Floats[0]; }
|
||||
const APFloat &getFirst() const { return Floats[0]; }
|
||||
};
|
||||
|
||||
} // End detail namespace
|
||||
|
||||
// This is a interface class that is currently forwarding functionalities from
|
||||
// detail::IEEEFloat.
|
||||
class APFloat : public APFloatBase {
|
||||
typedef detail::IEEEFloat IEEEFloat;
|
||||
typedef detail::DoubleAPFloat DoubleAPFloat;
|
||||
|
||||
static_assert(std::is_standard_layout<IEEEFloat>::value, "");
|
||||
|
||||
union {
|
||||
union Storage {
|
||||
const fltSemantics *semantics;
|
||||
IEEEFloat IEEE;
|
||||
};
|
||||
DoubleAPFloat Double;
|
||||
|
||||
explicit APFloat(IEEEFloat F) : IEEE(std::move(F)) {}
|
||||
explicit Storage(IEEEFloat F) : IEEE(std::move(F)) {}
|
||||
explicit Storage(DoubleAPFloat F) : Double(std::move(F)) {}
|
||||
|
||||
template <typename... ArgTypes>
|
||||
Storage(const fltSemantics &Semantics, ArgTypes &&... Args) {
|
||||
if (usesLayout<IEEEFloat>(Semantics)) {
|
||||
new (&IEEE) IEEEFloat(Semantics, std::forward<ArgTypes>(Args)...);
|
||||
} else if (usesLayout<DoubleAPFloat>(Semantics)) {
|
||||
new (&Double) DoubleAPFloat(Semantics, std::forward<ArgTypes>(Args)...);
|
||||
} else {
|
||||
llvm_unreachable("Unexpected semantics");
|
||||
}
|
||||
}
|
||||
|
||||
~Storage() {
|
||||
if (usesLayout<IEEEFloat>(*semantics)) {
|
||||
IEEE.~IEEEFloat();
|
||||
} else if (usesLayout<DoubleAPFloat>(*semantics)) {
|
||||
Double.~DoubleAPFloat();
|
||||
} else {
|
||||
llvm_unreachable("Unexpected semantics");
|
||||
}
|
||||
}
|
||||
|
||||
Storage(const Storage &RHS) {
|
||||
if (usesLayout<IEEEFloat>(*RHS.semantics)) {
|
||||
new (this) IEEEFloat(RHS.IEEE);
|
||||
} else if (usesLayout<DoubleAPFloat>(*RHS.semantics)) {
|
||||
new (this) DoubleAPFloat(RHS.Double);
|
||||
} else {
|
||||
llvm_unreachable("Unexpected semantics");
|
||||
}
|
||||
}
|
||||
|
||||
Storage(Storage &&RHS) {
|
||||
if (usesLayout<IEEEFloat>(*RHS.semantics)) {
|
||||
new (this) IEEEFloat(std::move(RHS.IEEE));
|
||||
} else if (usesLayout<DoubleAPFloat>(*RHS.semantics)) {
|
||||
new (this) DoubleAPFloat(std::move(RHS.Double));
|
||||
} else {
|
||||
llvm_unreachable("Unexpected semantics");
|
||||
}
|
||||
}
|
||||
|
||||
Storage &operator=(const Storage &RHS) {
|
||||
if (usesLayout<IEEEFloat>(*semantics) &&
|
||||
usesLayout<IEEEFloat>(*RHS.semantics)) {
|
||||
IEEE = RHS.IEEE;
|
||||
} else if (usesLayout<DoubleAPFloat>(*semantics) &&
|
||||
usesLayout<DoubleAPFloat>(*RHS.semantics)) {
|
||||
Double = RHS.Double;
|
||||
} else if (this != &RHS) {
|
||||
this->~Storage();
|
||||
new (this) Storage(RHS);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Storage &operator=(Storage &&RHS) {
|
||||
if (usesLayout<IEEEFloat>(*semantics) &&
|
||||
usesLayout<IEEEFloat>(*RHS.semantics)) {
|
||||
IEEE = std::move(RHS.IEEE);
|
||||
} else if (usesLayout<DoubleAPFloat>(*semantics) &&
|
||||
usesLayout<DoubleAPFloat>(*RHS.semantics)) {
|
||||
Double = std::move(RHS.Double);
|
||||
} else if (this != &RHS) {
|
||||
this->~Storage();
|
||||
new (this) Storage(RHS);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
} U;
|
||||
|
||||
template <typename T> static bool usesLayout(const fltSemantics &Semantics) {
|
||||
static_assert(std::is_same<T, IEEEFloat>::value ||
|
||||
std::is_same<T, DoubleAPFloat>::value, "");
|
||||
if (std::is_same<T, DoubleAPFloat>::value) {
|
||||
return &Semantics == &PPCDoubleDouble;
|
||||
}
|
||||
return &Semantics != &PPCDoubleDouble;
|
||||
}
|
||||
|
||||
IEEEFloat &getIEEE() {
|
||||
if (usesLayout<IEEEFloat>(*U.semantics)) {
|
||||
return U.IEEE;
|
||||
} else if (usesLayout<DoubleAPFloat>(*U.semantics)) {
|
||||
return U.Double.getFirst().U.IEEE;
|
||||
} else {
|
||||
llvm_unreachable("Unexpected semantics");
|
||||
}
|
||||
}
|
||||
|
||||
const IEEEFloat &getIEEE() const {
|
||||
if (usesLayout<IEEEFloat>(*U.semantics)) {
|
||||
return U.IEEE;
|
||||
} else if (usesLayout<DoubleAPFloat>(*U.semantics)) {
|
||||
return U.Double.getFirst().U.IEEE;
|
||||
} else {
|
||||
llvm_unreachable("Unexpected semantics");
|
||||
}
|
||||
}
|
||||
|
||||
void makeZero(bool Neg) { getIEEE().makeZero(Neg); }
|
||||
|
||||
void makeInf(bool Neg) { getIEEE().makeInf(Neg); }
|
||||
|
||||
void makeNaN(bool SNaN, bool Neg, const APInt *fill) {
|
||||
getIEEE().makeNaN(SNaN, Neg, fill);
|
||||
}
|
||||
|
||||
void makeLargest(bool Neg) { getIEEE().makeLargest(Neg); }
|
||||
|
||||
void makeSmallest(bool Neg) { getIEEE().makeSmallest(Neg); }
|
||||
|
||||
void makeSmallestNormalized(bool Neg) {
|
||||
getIEEE().makeSmallestNormalized(Neg);
|
||||
}
|
||||
|
||||
// FIXME: This is due to clang 3.3 (or older version) always checks for the
|
||||
// default constructor in an array aggregate initialization, even if no
|
||||
// elements in the array is default initialized.
|
||||
APFloat() : U(IEEEdouble) {
|
||||
llvm_unreachable("This is a workaround for old clang.");
|
||||
}
|
||||
|
||||
explicit APFloat(IEEEFloat F) : U(std::move(F)) {}
|
||||
explicit APFloat(DoubleAPFloat F) : U(std::move(F)) {}
|
||||
|
||||
public:
|
||||
APFloat(const fltSemantics &Semantics) : APFloat(IEEEFloat(Semantics)) {}
|
||||
APFloat(const fltSemantics &Semantics) : U(Semantics) {}
|
||||
APFloat(const fltSemantics &Semantics, StringRef S);
|
||||
APFloat(const fltSemantics &Semantics, integerPart I)
|
||||
: APFloat(IEEEFloat(Semantics, I)) {}
|
||||
APFloat(const fltSemantics &Semantics, uninitializedTag U)
|
||||
: APFloat(IEEEFloat(Semantics, U)) {}
|
||||
APFloat(const fltSemantics &Semantics, const APInt &I)
|
||||
: APFloat(IEEEFloat(Semantics, I)) {}
|
||||
explicit APFloat(double d) : APFloat(IEEEFloat(d)) {}
|
||||
explicit APFloat(float f) : APFloat(IEEEFloat(f)) {}
|
||||
APFloat(const APFloat &RHS) : APFloat(IEEEFloat(RHS.IEEE)) {}
|
||||
APFloat(APFloat &&RHS) : APFloat(IEEEFloat(std::move(RHS.IEEE))) {}
|
||||
APFloat(const fltSemantics &Semantics, integerPart I) : U(Semantics, I) {}
|
||||
APFloat(const fltSemantics &Semantics, uninitializedTag)
|
||||
: U(Semantics, uninitialized) {}
|
||||
APFloat(const fltSemantics &Semantics, const APInt &I) : U(Semantics, I) {}
|
||||
explicit APFloat(double d) : U(IEEEFloat(d)) {}
|
||||
explicit APFloat(float f) : U(IEEEFloat(f)) {}
|
||||
APFloat(const APFloat &RHS) = default;
|
||||
APFloat(APFloat &&RHS) = default;
|
||||
|
||||
~APFloat() { IEEE.~IEEEFloat(); }
|
||||
~APFloat() = default;
|
||||
|
||||
bool needsCleanup() const { return IEEE.needsCleanup(); }
|
||||
bool needsCleanup() const {
|
||||
if (usesLayout<IEEEFloat>(getSemantics())) {
|
||||
return U.IEEE.needsCleanup();
|
||||
} else if (usesLayout<DoubleAPFloat>(getSemantics())) {
|
||||
return U.Double.needsCleanup();
|
||||
} else {
|
||||
llvm_unreachable("Unexpected semantics");
|
||||
}
|
||||
}
|
||||
|
||||
/// Factory for Positive and Negative Zero.
|
||||
///
|
||||
/// \param Negative True iff the number should be negative.
|
||||
static APFloat getZero(const fltSemantics &Sem, bool Negative = false) {
|
||||
return APFloat(IEEEFloat::getZero(Sem, Negative));
|
||||
APFloat Val(Sem, uninitialized);
|
||||
Val.makeZero(Negative);
|
||||
return Val;
|
||||
}
|
||||
|
||||
/// Factory for Positive and Negative Infinity.
|
||||
///
|
||||
/// \param Negative True iff the number should be negative.
|
||||
static APFloat getInf(const fltSemantics &Sem, bool Negative = false) {
|
||||
return APFloat(IEEEFloat::getInf(Sem, Negative));
|
||||
APFloat Val(Sem, uninitialized);
|
||||
Val.makeInf(Negative);
|
||||
return Val;
|
||||
}
|
||||
|
||||
/// Factory for NaN values.
|
||||
///
|
||||
/// \param Negative - True iff the NaN generated should be negative.
|
||||
/// \param type - The unspecified fill bits for creating the NaN, 0 by
|
||||
/// default. The value is truncated as necessary.
|
||||
static APFloat getNaN(const fltSemantics &Sem, bool Negative = false,
|
||||
unsigned type = 0) {
|
||||
return APFloat(IEEEFloat::getNaN(Sem, Negative, type));
|
||||
if (type) {
|
||||
APInt fill(64, type);
|
||||
return getQNaN(Sem, Negative, &fill);
|
||||
} else {
|
||||
return getQNaN(Sem, Negative, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
/// Factory for QNaN values.
|
||||
static APFloat getQNaN(const fltSemantics &Sem, bool Negative = false,
|
||||
const APInt *payload = nullptr) {
|
||||
return APFloat(IEEEFloat::getQNaN(Sem, Negative, payload));
|
||||
APFloat Val(Sem, uninitialized);
|
||||
Val.makeNaN(false, Negative, payload);
|
||||
return Val;
|
||||
}
|
||||
|
||||
/// Factory for SNaN values.
|
||||
static APFloat getSNaN(const fltSemantics &Sem, bool Negative = false,
|
||||
const APInt *payload = nullptr) {
|
||||
return APFloat(IEEEFloat::getSNaN(Sem, Negative, payload));
|
||||
APFloat Val(Sem, uninitialized);
|
||||
Val.makeNaN(true, Negative, payload);
|
||||
return Val;
|
||||
}
|
||||
|
||||
/// Returns the largest finite number in the given semantics.
|
||||
///
|
||||
/// \param Negative - True iff the number should be negative
|
||||
static APFloat getLargest(const fltSemantics &Sem, bool Negative = false) {
|
||||
return APFloat(IEEEFloat::getLargest(Sem, Negative));
|
||||
APFloat Val(Sem, uninitialized);
|
||||
Val.makeLargest(Negative);
|
||||
return Val;
|
||||
}
|
||||
|
||||
/// Returns the smallest (by magnitude) finite number in the given semantics.
|
||||
/// Might be denormalized, which implies a relative loss of precision.
|
||||
///
|
||||
/// \param Negative - True iff the number should be negative
|
||||
static APFloat getSmallest(const fltSemantics &Sem, bool Negative = false) {
|
||||
return APFloat(IEEEFloat::getSmallest(Sem, Negative));
|
||||
APFloat Val(Sem, uninitialized);
|
||||
Val.makeSmallest(Negative);
|
||||
return Val;
|
||||
}
|
||||
|
||||
/// Returns the smallest (by magnitude) normalized finite number in the given
|
||||
/// semantics.
|
||||
///
|
||||
/// \param Negative - True iff the number should be negative
|
||||
static APFloat getSmallestNormalized(const fltSemantics &Sem,
|
||||
bool Negative = false) {
|
||||
return APFloat(IEEEFloat::getSmallestNormalized(Sem, Negative));
|
||||
APFloat Val(Sem, uninitialized);
|
||||
Val.makeSmallestNormalized(Negative);
|
||||
return Val;
|
||||
}
|
||||
|
||||
/// Returns a float which is bitcasted from an all one value int.
|
||||
///
|
||||
/// \param BitWidth - Select float type
|
||||
/// \param isIEEE - If 128 bit number, select between PPC and IEEE
|
||||
static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false) {
|
||||
return APFloat(IEEEFloat::getAllOnesValue(BitWidth, isIEEE));
|
||||
if (isIEEE) {
|
||||
return APFloat(IEEEFloat::getAllOnesValue(BitWidth));
|
||||
} else {
|
||||
assert(BitWidth == 128);
|
||||
return APFloat(PPCDoubleDouble, APInt::getAllOnesValue(BitWidth));
|
||||
}
|
||||
}
|
||||
|
||||
void Profile(FoldingSetNodeID &NID) const { IEEE.Profile(NID); }
|
||||
void Profile(FoldingSetNodeID &NID) const { getIEEE().Profile(NID); }
|
||||
|
||||
opStatus add(const APFloat &RHS, roundingMode RM) {
|
||||
return IEEE.add(RHS.IEEE, RM);
|
||||
return getIEEE().add(RHS.getIEEE(), RM);
|
||||
}
|
||||
opStatus subtract(const APFloat &RHS, roundingMode RM) {
|
||||
return IEEE.subtract(RHS.IEEE, RM);
|
||||
return getIEEE().subtract(RHS.getIEEE(), RM);
|
||||
}
|
||||
opStatus multiply(const APFloat &RHS, roundingMode RM) {
|
||||
return IEEE.multiply(RHS.IEEE, RM);
|
||||
return getIEEE().multiply(RHS.getIEEE(), RM);
|
||||
}
|
||||
opStatus divide(const APFloat &RHS, roundingMode RM) {
|
||||
return IEEE.divide(RHS.IEEE, RM);
|
||||
return getIEEE().divide(RHS.getIEEE(), RM);
|
||||
}
|
||||
opStatus remainder(const APFloat &RHS) { return IEEE.remainder(RHS.IEEE); }
|
||||
opStatus mod(const APFloat &RHS) { return IEEE.mod(RHS.IEEE); }
|
||||
opStatus remainder(const APFloat &RHS) {
|
||||
return getIEEE().remainder(RHS.getIEEE());
|
||||
}
|
||||
opStatus mod(const APFloat &RHS) { return getIEEE().mod(RHS.getIEEE()); }
|
||||
opStatus fusedMultiplyAdd(const APFloat &Multiplicand, const APFloat &Addend,
|
||||
roundingMode RM) {
|
||||
return IEEE.fusedMultiplyAdd(Multiplicand.IEEE, Addend.IEEE, RM);
|
||||
return getIEEE().fusedMultiplyAdd(Multiplicand.getIEEE(), Addend.getIEEE(),
|
||||
RM);
|
||||
}
|
||||
opStatus roundToIntegral(roundingMode RM) { return IEEE.roundToIntegral(RM); }
|
||||
opStatus next(bool nextDown) { return IEEE.next(nextDown); }
|
||||
opStatus roundToIntegral(roundingMode RM) {
|
||||
return getIEEE().roundToIntegral(RM);
|
||||
}
|
||||
opStatus next(bool nextDown) { return getIEEE().next(nextDown); }
|
||||
|
||||
APFloat operator+(const APFloat &RHS) const {
|
||||
return APFloat(IEEE + RHS.IEEE);
|
||||
return APFloat(getIEEE() + RHS.getIEEE());
|
||||
}
|
||||
|
||||
APFloat operator-(const APFloat &RHS) const {
|
||||
return APFloat(IEEE - RHS.IEEE);
|
||||
return APFloat(getIEEE() - RHS.getIEEE());
|
||||
}
|
||||
|
||||
APFloat operator*(const APFloat &RHS) const {
|
||||
return APFloat(IEEE * RHS.IEEE);
|
||||
return APFloat(getIEEE() * RHS.getIEEE());
|
||||
}
|
||||
|
||||
APFloat operator/(const APFloat &RHS) const {
|
||||
return APFloat(IEEE / RHS.IEEE);
|
||||
return APFloat(getIEEE() / RHS.getIEEE());
|
||||
}
|
||||
|
||||
void changeSign() { IEEE.changeSign(); }
|
||||
void clearSign() { IEEE.clearSign(); }
|
||||
void copySign(const APFloat &RHS) { IEEE.copySign(RHS.IEEE); }
|
||||
void changeSign() { getIEEE().changeSign(); }
|
||||
void clearSign() { getIEEE().clearSign(); }
|
||||
void copySign(const APFloat &RHS) { getIEEE().copySign(RHS.getIEEE()); }
|
||||
|
||||
static APFloat copySign(APFloat Value, const APFloat &Sign) {
|
||||
return APFloat(IEEEFloat::copySign(Value.IEEE, Sign.IEEE));
|
||||
return APFloat(IEEEFloat::copySign(Value.getIEEE(), Sign.getIEEE()));
|
||||
}
|
||||
|
||||
opStatus convert(const fltSemantics &ToSemantics, roundingMode RM,
|
||||
bool *losesInfo) {
|
||||
return IEEE.convert(ToSemantics, RM, losesInfo);
|
||||
}
|
||||
bool *losesInfo);
|
||||
opStatus convertToInteger(integerPart *Input, unsigned int Width,
|
||||
bool IsSigned, roundingMode RM,
|
||||
bool *IsExact) const {
|
||||
return IEEE.convertToInteger(Input, Width, IsSigned, RM, IsExact);
|
||||
return getIEEE().convertToInteger(Input, Width, IsSigned, RM, IsExact);
|
||||
}
|
||||
opStatus convertToInteger(APSInt &Result, roundingMode RM,
|
||||
bool *IsExact) const {
|
||||
return IEEE.convertToInteger(Result, RM, IsExact);
|
||||
return getIEEE().convertToInteger(Result, RM, IsExact);
|
||||
}
|
||||
opStatus convertFromAPInt(const APInt &Input, bool IsSigned,
|
||||
roundingMode RM) {
|
||||
return IEEE.convertFromAPInt(Input, IsSigned, RM);
|
||||
return getIEEE().convertFromAPInt(Input, IsSigned, RM);
|
||||
}
|
||||
opStatus convertFromSignExtendedInteger(const integerPart *Input,
|
||||
unsigned int InputSize, bool IsSigned,
|
||||
roundingMode RM) {
|
||||
return IEEE.convertFromSignExtendedInteger(Input, InputSize, IsSigned, RM);
|
||||
return getIEEE().convertFromSignExtendedInteger(Input, InputSize, IsSigned,
|
||||
RM);
|
||||
}
|
||||
opStatus convertFromZeroExtendedInteger(const integerPart *Input,
|
||||
unsigned int InputSize, bool IsSigned,
|
||||
roundingMode RM) {
|
||||
return IEEE.convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM);
|
||||
return getIEEE().convertFromZeroExtendedInteger(Input, InputSize, IsSigned,
|
||||
RM);
|
||||
}
|
||||
opStatus convertFromString(StringRef, roundingMode);
|
||||
APInt bitcastToAPInt() const { return IEEE.bitcastToAPInt(); }
|
||||
double convertToDouble() const { return IEEE.convertToDouble(); }
|
||||
float convertToFloat() const { return IEEE.convertToFloat(); }
|
||||
APInt bitcastToAPInt() const { return getIEEE().bitcastToAPInt(); }
|
||||
double convertToDouble() const { return getIEEE().convertToDouble(); }
|
||||
float convertToFloat() const { return getIEEE().convertToFloat(); }
|
||||
|
||||
bool operator==(const APFloat &) const = delete;
|
||||
|
||||
cmpResult compare(const APFloat &RHS) const { return IEEE.compare(RHS.IEEE); }
|
||||
cmpResult compare(const APFloat &RHS) const {
|
||||
return getIEEE().compare(RHS.getIEEE());
|
||||
}
|
||||
|
||||
bool bitwiseIsEqual(const APFloat &RHS) const {
|
||||
return IEEE.bitwiseIsEqual(RHS.IEEE);
|
||||
return getIEEE().bitwiseIsEqual(RHS.getIEEE());
|
||||
}
|
||||
|
||||
unsigned int convertToHexString(char *DST, unsigned int HexDigits,
|
||||
bool UpperCase, roundingMode RM) const {
|
||||
return IEEE.convertToHexString(DST, HexDigits, UpperCase, RM);
|
||||
return getIEEE().convertToHexString(DST, HexDigits, UpperCase, RM);
|
||||
}
|
||||
|
||||
bool isZero() const { return getCategory() == fcZero; }
|
||||
bool isInfinity() const { return getCategory() == fcInfinity; }
|
||||
bool isNaN() const { return getCategory() == fcNaN; }
|
||||
|
||||
bool isNegative() const { return IEEE.isNegative(); }
|
||||
bool isDenormal() const { return IEEE.isDenormal(); }
|
||||
bool isSignaling() const { return IEEE.isSignaling(); }
|
||||
bool isNegative() const { return getIEEE().isNegative(); }
|
||||
bool isDenormal() const { return getIEEE().isDenormal(); }
|
||||
bool isSignaling() const { return getIEEE().isSignaling(); }
|
||||
|
||||
bool isNormal() const { return !isDenormal() && isFiniteNonZero(); }
|
||||
bool isFinite() const { return !isNaN() && !isInfinity(); }
|
||||
|
||||
fltCategory getCategory() const { return IEEE.getCategory(); }
|
||||
const fltSemantics &getSemantics() const { return *semantics; }
|
||||
fltCategory getCategory() const { return getIEEE().getCategory(); }
|
||||
const fltSemantics &getSemantics() const { return *U.semantics; }
|
||||
bool isNonZero() const { return !isZero(); }
|
||||
bool isFiniteNonZero() const { return isFinite() && !isZero(); }
|
||||
bool isPosZero() const { return isZero() && !isNegative(); }
|
||||
bool isNegZero() const { return isZero() && isNegative(); }
|
||||
bool isSmallest() const { return IEEE.isSmallest(); }
|
||||
bool isLargest() const { return IEEE.isLargest(); }
|
||||
bool isInteger() const { return IEEE.isInteger(); }
|
||||
bool isSmallest() const { return getIEEE().isSmallest(); }
|
||||
bool isLargest() const { return getIEEE().isLargest(); }
|
||||
bool isInteger() const { return getIEEE().isInteger(); }
|
||||
|
||||
APFloat &operator=(const APFloat &RHS) {
|
||||
IEEE = RHS.IEEE;
|
||||
return *this;
|
||||
}
|
||||
APFloat &operator=(APFloat &&RHS) {
|
||||
IEEE = std::move(RHS.IEEE);
|
||||
return *this;
|
||||
}
|
||||
APFloat &operator=(const APFloat &RHS) = default;
|
||||
APFloat &operator=(APFloat &&RHS) = default;
|
||||
|
||||
void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0,
|
||||
unsigned FormatMaxPadding = 3) const {
|
||||
return IEEE.toString(Str, FormatPrecision, FormatMaxPadding);
|
||||
return getIEEE().toString(Str, FormatPrecision, FormatMaxPadding);
|
||||
}
|
||||
|
||||
bool getExactInverse(APFloat *inv) const {
|
||||
return IEEE.getExactInverse(inv ? &inv->IEEE : nullptr);
|
||||
return getIEEE().getExactInverse(inv ? &inv->getIEEE() : nullptr);
|
||||
}
|
||||
|
||||
friend hash_code hash_value(const APFloat &Arg);
|
||||
friend int ilogb(const APFloat &Arg) { return ilogb(Arg.IEEE); }
|
||||
friend int ilogb(const APFloat &Arg) { return ilogb(Arg.getIEEE()); }
|
||||
friend APFloat scalbn(APFloat X, int Exp, roundingMode RM);
|
||||
friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM);
|
||||
friend DoubleAPFloat;
|
||||
};
|
||||
|
||||
/// See friend declarations above.
|
||||
@ -870,7 +1034,7 @@ public:
|
||||
/// xlC compiler.
|
||||
hash_code hash_value(const APFloat &Arg);
|
||||
inline APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM) {
|
||||
return APFloat(scalbn(X.IEEE, Exp, RM));
|
||||
return APFloat(scalbn(X.getIEEE(), Exp, RM));
|
||||
}
|
||||
|
||||
/// \brief Equivalent of C standard library function.
|
||||
@ -878,7 +1042,7 @@ inline APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM) {
|
||||
/// While the C standard says Exp is an unspecified value for infinity and nan,
|
||||
/// this returns INT_MAX for infinities, and INT_MIN for NaNs.
|
||||
inline APFloat frexp(const APFloat &X, int &Exp, APFloat::roundingMode RM) {
|
||||
return APFloat(frexp(X.IEEE, Exp, RM));
|
||||
return APFloat(frexp(X.getIEEE(), Exp, RM));
|
||||
}
|
||||
/// \brief Returns the absolute value of the argument.
|
||||
inline APFloat abs(APFloat X) {
|
||||
|
@ -75,8 +75,18 @@ namespace llvm {
|
||||
to represent all possible values held by a PPC double-double number,
|
||||
for example: (long double) 1.0 + (long double) 0x1p-106
|
||||
Should this be replaced by a full emulation of PPC double-double? */
|
||||
const fltSemantics APFloatBase::PPCDoubleDouble = {1023, -1022 + 53, 53 + 53,
|
||||
128};
|
||||
const fltSemantics APFloatBase::PPCDoubleDouble = {0, 0, 0, 0};
|
||||
|
||||
/* There are temporary semantics for the real PPCDoubleDouble implementation.
|
||||
Currently, APFloat of PPCDoubleDouble holds one PPCDoubleDoubleImpl as the
|
||||
high part of double double, and one IEEEdouble as the low part, so that
|
||||
the old operations operate on PPCDoubleDoubleImpl, while the newly added
|
||||
operations also populate the IEEEdouble.
|
||||
|
||||
TODO: Once all functions support DoubleAPFloat mode, we'll change all
|
||||
PPCDoubleDoubleImpl to IEEEdouble and remove PPCDoubleDoubleImpl. */
|
||||
static const fltSemantics PPCDoubleDoubleImpl = {1023, -1022 + 53, 53 + 53,
|
||||
128};
|
||||
|
||||
/* A tight upper bound on number of parts required to hold the value
|
||||
pow(5, power) is
|
||||
@ -677,13 +687,6 @@ void IEEEFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill) {
|
||||
APInt::tcSetBit(significand, QNaNBit + 1);
|
||||
}
|
||||
|
||||
IEEEFloat IEEEFloat::makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative,
|
||||
const APInt *fill) {
|
||||
IEEEFloat value(Sem, uninitialized);
|
||||
value.makeNaN(SNaN, Negative, fill);
|
||||
return value;
|
||||
}
|
||||
|
||||
IEEEFloat &IEEEFloat::operator=(const IEEEFloat &rhs) {
|
||||
if (this != &rhs) {
|
||||
if (semantics != rhs.semantics) {
|
||||
@ -820,11 +823,6 @@ IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics, uninitializedTag tag) {
|
||||
initialize(&ourSemantics);
|
||||
}
|
||||
|
||||
IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics, StringRef text) {
|
||||
initialize(&ourSemantics);
|
||||
convertFromString(text, rmNearestTiesToEven);
|
||||
}
|
||||
|
||||
IEEEFloat::IEEEFloat(const IEEEFloat &rhs) {
|
||||
initialize(rhs.semantics);
|
||||
assign(rhs);
|
||||
@ -2366,7 +2364,8 @@ IEEEFloat::roundSignificandWithExponent(const integerPart *decSigParts,
|
||||
excessPrecision = calcSemantics.precision - semantics->precision;
|
||||
truncatedBits = excessPrecision;
|
||||
|
||||
IEEEFloat decSig = IEEEFloat::getZero(calcSemantics, sign);
|
||||
IEEEFloat decSig(calcSemantics, uninitialized);
|
||||
decSig.makeZero(sign);
|
||||
IEEEFloat pow5(calcSemantics);
|
||||
|
||||
sigStatus = decSig.convertFromUnsignedParts(decSigParts, sigPartCount,
|
||||
@ -2821,7 +2820,7 @@ APInt IEEEFloat::convertF80LongDoubleAPFloatToAPInt() const {
|
||||
}
|
||||
|
||||
APInt IEEEFloat::convertPPCDoubleDoubleAPFloatToAPInt() const {
|
||||
assert(semantics == (const llvm::fltSemantics*)&PPCDoubleDouble);
|
||||
assert(semantics == (const llvm::fltSemantics *)&PPCDoubleDoubleImpl);
|
||||
assert(partCount()==2);
|
||||
|
||||
uint64_t words[2];
|
||||
@ -3002,7 +3001,7 @@ APInt IEEEFloat::bitcastToAPInt() const {
|
||||
if (semantics == (const llvm::fltSemantics*)&IEEEquad)
|
||||
return convertQuadrupleAPFloatToAPInt();
|
||||
|
||||
if (semantics == (const llvm::fltSemantics*)&PPCDoubleDouble)
|
||||
if (semantics == (const llvm::fltSemantics *)&PPCDoubleDoubleImpl)
|
||||
return convertPPCDoubleDoubleAPFloatToAPInt();
|
||||
|
||||
assert(semantics == (const llvm::fltSemantics*)&x87DoubleExtended &&
|
||||
@ -3072,14 +3071,14 @@ void IEEEFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) {
|
||||
|
||||
// Get the first double and convert to our format.
|
||||
initFromDoubleAPInt(APInt(64, i1));
|
||||
fs = convert(PPCDoubleDouble, rmNearestTiesToEven, &losesInfo);
|
||||
fs = convert(PPCDoubleDoubleImpl, rmNearestTiesToEven, &losesInfo);
|
||||
assert(fs == opOK && !losesInfo);
|
||||
(void)fs;
|
||||
|
||||
// Unless we have a special case, add in second double.
|
||||
if (isFiniteNonZero()) {
|
||||
IEEEFloat v(IEEEdouble, APInt(64, i2));
|
||||
fs = v.convert(PPCDoubleDouble, rmNearestTiesToEven, &losesInfo);
|
||||
fs = v.convert(PPCDoubleDoubleImpl, rmNearestTiesToEven, &losesInfo);
|
||||
assert(fs == opOK && !losesInfo);
|
||||
(void)fs;
|
||||
|
||||
@ -3233,13 +3232,13 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) {
|
||||
return initFromF80LongDoubleAPInt(api);
|
||||
if (Sem == &IEEEquad)
|
||||
return initFromQuadrupleAPInt(api);
|
||||
if (Sem == &PPCDoubleDouble)
|
||||
if (Sem == &PPCDoubleDoubleImpl)
|
||||
return initFromPPCDoubleDoubleAPInt(api);
|
||||
|
||||
llvm_unreachable(nullptr);
|
||||
}
|
||||
|
||||
IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) {
|
||||
IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth) {
|
||||
switch (BitWidth) {
|
||||
case 16:
|
||||
return IEEEFloat(IEEEhalf, APInt::getAllOnesValue(BitWidth));
|
||||
@ -3250,9 +3249,7 @@ IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) {
|
||||
case 80:
|
||||
return IEEEFloat(x87DoubleExtended, APInt::getAllOnesValue(BitWidth));
|
||||
case 128:
|
||||
if (isIEEE)
|
||||
return IEEEFloat(IEEEquad, APInt::getAllOnesValue(BitWidth));
|
||||
return IEEEFloat(PPCDoubleDouble, APInt::getAllOnesValue(BitWidth));
|
||||
return IEEEFloat(IEEEquad, APInt::getAllOnesValue(BitWidth));
|
||||
default:
|
||||
llvm_unreachable("Unknown floating bit width");
|
||||
}
|
||||
@ -3296,43 +3293,18 @@ void IEEEFloat::makeSmallest(bool Negative) {
|
||||
APInt::tcSet(significandParts(), 1, partCount());
|
||||
}
|
||||
|
||||
IEEEFloat IEEEFloat::getLargest(const fltSemantics &Sem, bool Negative) {
|
||||
// We want (in interchange format):
|
||||
// sign = {Negative}
|
||||
// exponent = 1..10
|
||||
// significand = 1..1
|
||||
IEEEFloat Val(Sem, uninitialized);
|
||||
Val.makeLargest(Negative);
|
||||
return Val;
|
||||
}
|
||||
|
||||
IEEEFloat IEEEFloat::getSmallest(const fltSemantics &Sem, bool Negative) {
|
||||
// We want (in interchange format):
|
||||
// sign = {Negative}
|
||||
// exponent = 0..0
|
||||
// significand = 0..01
|
||||
IEEEFloat Val(Sem, uninitialized);
|
||||
Val.makeSmallest(Negative);
|
||||
return Val;
|
||||
}
|
||||
|
||||
IEEEFloat IEEEFloat::getSmallestNormalized(const fltSemantics &Sem,
|
||||
bool Negative) {
|
||||
IEEEFloat Val(Sem, uninitialized);
|
||||
|
||||
void IEEEFloat::makeSmallestNormalized(bool Negative) {
|
||||
// We want (in interchange format):
|
||||
// sign = {Negative}
|
||||
// exponent = 0..0
|
||||
// significand = 10..0
|
||||
|
||||
Val.category = fcNormal;
|
||||
Val.zeroSignificand();
|
||||
Val.sign = Negative;
|
||||
Val.exponent = Sem.minExponent;
|
||||
Val.significandParts()[partCountForBits(Sem.precision)-1] |=
|
||||
(((integerPart) 1) << ((Sem.precision - 1) % integerPartWidth));
|
||||
|
||||
return Val;
|
||||
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) {
|
||||
@ -3868,15 +3840,99 @@ IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM) {
|
||||
return scalbn(Val, -Exp, RM);
|
||||
}
|
||||
|
||||
DoubleAPFloat::DoubleAPFloat(const fltSemantics &S)
|
||||
: Semantics(&S), Floats(new APFloat[2]{APFloat(PPCDoubleDoubleImpl),
|
||||
APFloat(IEEEdouble)}) {
|
||||
assert(Semantics == &PPCDoubleDouble);
|
||||
}
|
||||
|
||||
DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, uninitializedTag)
|
||||
: Semantics(&S),
|
||||
Floats(new APFloat[2]{APFloat(PPCDoubleDoubleImpl, uninitialized),
|
||||
APFloat(IEEEdouble, uninitialized)}) {
|
||||
assert(Semantics == &PPCDoubleDouble);
|
||||
}
|
||||
|
||||
DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, integerPart I)
|
||||
: Semantics(&S), Floats(new APFloat[2]{APFloat(PPCDoubleDoubleImpl, I),
|
||||
APFloat(IEEEdouble)}) {
|
||||
assert(Semantics == &PPCDoubleDouble);
|
||||
}
|
||||
|
||||
DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, const APInt &I)
|
||||
: Semantics(&S), Floats(new APFloat[2]{APFloat(PPCDoubleDoubleImpl, I),
|
||||
APFloat(IEEEdouble)}) {
|
||||
assert(Semantics == &PPCDoubleDouble);
|
||||
}
|
||||
|
||||
DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, APFloat &&First,
|
||||
APFloat &&Second)
|
||||
: Semantics(&S),
|
||||
Floats(new APFloat[2]{std::move(First), std::move(Second)}) {
|
||||
assert(Semantics == &PPCDoubleDouble);
|
||||
// TODO Check for First == &IEEEdouble once the transition is done.
|
||||
assert(&Floats[0].getSemantics() == &PPCDoubleDoubleImpl);
|
||||
assert(&Floats[1].getSemantics() == &IEEEdouble);
|
||||
}
|
||||
|
||||
DoubleAPFloat::DoubleAPFloat(const DoubleAPFloat &RHS)
|
||||
: Semantics(RHS.Semantics),
|
||||
Floats(new APFloat[2]{APFloat(RHS.Floats[0]), APFloat(RHS.Floats[1])}) {
|
||||
assert(Semantics == &PPCDoubleDouble);
|
||||
}
|
||||
|
||||
DoubleAPFloat::DoubleAPFloat(DoubleAPFloat &&RHS)
|
||||
: Semantics(RHS.Semantics), Floats(std::move(RHS.Floats)) {
|
||||
RHS.Semantics = &Bogus;
|
||||
assert(Semantics == &PPCDoubleDouble);
|
||||
}
|
||||
|
||||
DoubleAPFloat &DoubleAPFloat::operator=(const DoubleAPFloat &RHS) {
|
||||
if (Semantics == RHS.Semantics) {
|
||||
Floats[0] = RHS.Floats[0];
|
||||
Floats[1] = RHS.Floats[1];
|
||||
} else if (this != &RHS) {
|
||||
this->~DoubleAPFloat();
|
||||
new (this) DoubleAPFloat(RHS);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // End detail namespace
|
||||
|
||||
APFloat::opStatus APFloat::convertFromString(StringRef Str, roundingMode RM) {
|
||||
return IEEE.convertFromString(Str, RM);
|
||||
return getIEEE().convertFromString(Str, RM);
|
||||
}
|
||||
|
||||
hash_code hash_value(const APFloat &Arg) { return hash_value(Arg.IEEE); }
|
||||
hash_code hash_value(const APFloat &Arg) { return hash_value(Arg.getIEEE()); }
|
||||
|
||||
APFloat::APFloat(const fltSemantics &Semantics, StringRef S)
|
||||
: APFloat(IEEEFloat(Semantics, S)) {}
|
||||
: APFloat(Semantics) {
|
||||
convertFromString(S, rmNearestTiesToEven);
|
||||
}
|
||||
|
||||
APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics,
|
||||
roundingMode RM, bool *losesInfo) {
|
||||
if (&getSemantics() == &ToSemantics)
|
||||
return opOK;
|
||||
if (usesLayout<IEEEFloat>(getSemantics()) &&
|
||||
usesLayout<IEEEFloat>(ToSemantics)) {
|
||||
return U.IEEE.convert(ToSemantics, RM, losesInfo);
|
||||
} else if (usesLayout<IEEEFloat>(getSemantics()) &&
|
||||
usesLayout<DoubleAPFloat>(ToSemantics)) {
|
||||
assert(&ToSemantics == &PPCDoubleDouble);
|
||||
auto Ret = U.IEEE.convert(PPCDoubleDoubleImpl, RM, losesInfo);
|
||||
*this = APFloat(
|
||||
DoubleAPFloat(PPCDoubleDouble, std::move(*this), APFloat(IEEEdouble)));
|
||||
return Ret;
|
||||
} else if (usesLayout<DoubleAPFloat>(getSemantics()) &&
|
||||
usesLayout<IEEEFloat>(ToSemantics)) {
|
||||
auto Ret = getIEEE().convert(ToSemantics, RM, losesInfo);
|
||||
*this = APFloat(std::move(getIEEE()));
|
||||
return Ret;
|
||||
} else {
|
||||
llvm_unreachable("Unexpected semantics");
|
||||
}
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
Loading…
x
Reference in New Issue
Block a user