mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-04-02 15:51:54 +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
|
#define LLVM_ADT_APFLOAT_H
|
||||||
|
|
||||||
#include "llvm/ADT/APInt.h"
|
#include "llvm/ADT/APInt.h"
|
||||||
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
struct fltSemantics;
|
struct fltSemantics;
|
||||||
class APSInt;
|
class APSInt;
|
||||||
class StringRef;
|
class StringRef;
|
||||||
|
class APFloat;
|
||||||
|
|
||||||
template <typename T> class SmallVectorImpl;
|
template <typename T> class SmallVectorImpl;
|
||||||
|
|
||||||
@ -206,13 +209,12 @@ struct APFloatBase {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
class IEEEFloat : public APFloatBase {
|
class IEEEFloat final : public APFloatBase {
|
||||||
public:
|
public:
|
||||||
/// \name Constructors
|
/// \name Constructors
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
IEEEFloat(const fltSemantics &); // Default construct to 0.0
|
IEEEFloat(const fltSemantics &); // Default construct to 0.0
|
||||||
IEEEFloat(const fltSemantics &, StringRef);
|
|
||||||
IEEEFloat(const fltSemantics &, integerPart);
|
IEEEFloat(const fltSemantics &, integerPart);
|
||||||
IEEEFloat(const fltSemantics &, uninitializedTag);
|
IEEEFloat(const fltSemantics &, uninitializedTag);
|
||||||
IEEEFloat(const fltSemantics &, const APInt &);
|
IEEEFloat(const fltSemantics &, const APInt &);
|
||||||
@ -230,74 +232,10 @@ public:
|
|||||||
/// \name Convenience "constructors"
|
/// \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.
|
/// Returns a float which is bitcasted from an all one value int.
|
||||||
///
|
///
|
||||||
/// \param BitWidth - Select float type
|
/// \param BitWidth - Select float type
|
||||||
/// \param isIEEE - If 128 bit number, select between PPC and IEEE
|
static IEEEFloat getAllOnesValue(unsigned BitWidth);
|
||||||
static IEEEFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false);
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
@ -527,6 +465,25 @@ public:
|
|||||||
|
|
||||||
friend IEEEFloat frexp(const IEEEFloat &X, int &Exp, roundingMode);
|
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:
|
private:
|
||||||
/// \name Simple Queries
|
/// \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
|
/// \name Miscellany
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
@ -624,6 +566,7 @@ private:
|
|||||||
void copySignificand(const IEEEFloat &);
|
void copySignificand(const IEEEFloat &);
|
||||||
void freeSignificand();
|
void freeSignificand();
|
||||||
|
|
||||||
|
/// Note: this must be the first data member.
|
||||||
/// The semantics that this value obeys.
|
/// The semantics that this value obeys.
|
||||||
const fltSemantics *semantics;
|
const fltSemantics *semantics;
|
||||||
|
|
||||||
@ -653,215 +596,436 @@ int ilogb(const IEEEFloat &Arg);
|
|||||||
IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode);
|
IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode);
|
||||||
IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM);
|
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
|
} // End detail namespace
|
||||||
|
|
||||||
// This is a interface class that is currently forwarding functionalities from
|
// This is a interface class that is currently forwarding functionalities from
|
||||||
// detail::IEEEFloat.
|
// detail::IEEEFloat.
|
||||||
class APFloat : public APFloatBase {
|
class APFloat : public APFloatBase {
|
||||||
typedef detail::IEEEFloat IEEEFloat;
|
typedef detail::IEEEFloat IEEEFloat;
|
||||||
|
typedef detail::DoubleAPFloat DoubleAPFloat;
|
||||||
|
|
||||||
static_assert(std::is_standard_layout<IEEEFloat>::value, "");
|
static_assert(std::is_standard_layout<IEEEFloat>::value, "");
|
||||||
|
|
||||||
union {
|
union Storage {
|
||||||
const fltSemantics *semantics;
|
const fltSemantics *semantics;
|
||||||
IEEEFloat IEEE;
|
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:
|
public:
|
||||||
APFloat(const fltSemantics &Semantics) : APFloat(IEEEFloat(Semantics)) {}
|
APFloat(const fltSemantics &Semantics) : U(Semantics) {}
|
||||||
APFloat(const fltSemantics &Semantics, StringRef S);
|
APFloat(const fltSemantics &Semantics, StringRef S);
|
||||||
APFloat(const fltSemantics &Semantics, integerPart I)
|
APFloat(const fltSemantics &Semantics, integerPart I) : U(Semantics, I) {}
|
||||||
: APFloat(IEEEFloat(Semantics, I)) {}
|
APFloat(const fltSemantics &Semantics, uninitializedTag)
|
||||||
APFloat(const fltSemantics &Semantics, uninitializedTag U)
|
: U(Semantics, uninitialized) {}
|
||||||
: APFloat(IEEEFloat(Semantics, U)) {}
|
APFloat(const fltSemantics &Semantics, const APInt &I) : U(Semantics, I) {}
|
||||||
APFloat(const fltSemantics &Semantics, const APInt &I)
|
explicit APFloat(double d) : U(IEEEFloat(d)) {}
|
||||||
: APFloat(IEEEFloat(Semantics, I)) {}
|
explicit APFloat(float f) : U(IEEEFloat(f)) {}
|
||||||
explicit APFloat(double d) : APFloat(IEEEFloat(d)) {}
|
APFloat(const APFloat &RHS) = default;
|
||||||
explicit APFloat(float f) : APFloat(IEEEFloat(f)) {}
|
APFloat(APFloat &&RHS) = default;
|
||||||
APFloat(const APFloat &RHS) : APFloat(IEEEFloat(RHS.IEEE)) {}
|
|
||||||
APFloat(APFloat &&RHS) : APFloat(IEEEFloat(std::move(RHS.IEEE))) {}
|
|
||||||
|
|
||||||
~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) {
|
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) {
|
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,
|
static APFloat getNaN(const fltSemantics &Sem, bool Negative = false,
|
||||||
unsigned type = 0) {
|
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,
|
static APFloat getQNaN(const fltSemantics &Sem, bool Negative = false,
|
||||||
const APInt *payload = nullptr) {
|
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,
|
static APFloat getSNaN(const fltSemantics &Sem, bool Negative = false,
|
||||||
const APInt *payload = nullptr) {
|
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) {
|
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) {
|
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,
|
static APFloat getSmallestNormalized(const fltSemantics &Sem,
|
||||||
bool Negative = false) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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 remainder(const APFloat &RHS) {
|
||||||
opStatus mod(const APFloat &RHS) { return IEEE.mod(RHS.IEEE); }
|
return getIEEE().remainder(RHS.getIEEE());
|
||||||
|
}
|
||||||
|
opStatus mod(const APFloat &RHS) { return getIEEE().mod(RHS.getIEEE()); }
|
||||||
opStatus fusedMultiplyAdd(const APFloat &Multiplicand, const APFloat &Addend,
|
opStatus fusedMultiplyAdd(const APFloat &Multiplicand, const APFloat &Addend,
|
||||||
roundingMode RM) {
|
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 roundToIntegral(roundingMode RM) {
|
||||||
opStatus next(bool nextDown) { return IEEE.next(nextDown); }
|
return getIEEE().roundToIntegral(RM);
|
||||||
|
}
|
||||||
|
opStatus next(bool nextDown) { return getIEEE().next(nextDown); }
|
||||||
|
|
||||||
APFloat operator+(const APFloat &RHS) const {
|
APFloat operator+(const APFloat &RHS) const {
|
||||||
return APFloat(IEEE + RHS.IEEE);
|
return APFloat(getIEEE() + RHS.getIEEE());
|
||||||
}
|
}
|
||||||
|
|
||||||
APFloat operator-(const APFloat &RHS) const {
|
APFloat operator-(const APFloat &RHS) const {
|
||||||
return APFloat(IEEE - RHS.IEEE);
|
return APFloat(getIEEE() - RHS.getIEEE());
|
||||||
}
|
}
|
||||||
|
|
||||||
APFloat operator*(const APFloat &RHS) const {
|
APFloat operator*(const APFloat &RHS) const {
|
||||||
return APFloat(IEEE * RHS.IEEE);
|
return APFloat(getIEEE() * RHS.getIEEE());
|
||||||
}
|
}
|
||||||
|
|
||||||
APFloat operator/(const APFloat &RHS) const {
|
APFloat operator/(const APFloat &RHS) const {
|
||||||
return APFloat(IEEE / RHS.IEEE);
|
return APFloat(getIEEE() / RHS.getIEEE());
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeSign() { IEEE.changeSign(); }
|
void changeSign() { getIEEE().changeSign(); }
|
||||||
void clearSign() { IEEE.clearSign(); }
|
void clearSign() { getIEEE().clearSign(); }
|
||||||
void copySign(const APFloat &RHS) { IEEE.copySign(RHS.IEEE); }
|
void copySign(const APFloat &RHS) { getIEEE().copySign(RHS.getIEEE()); }
|
||||||
|
|
||||||
static APFloat copySign(APFloat Value, const APFloat &Sign) {
|
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,
|
opStatus convert(const fltSemantics &ToSemantics, roundingMode RM,
|
||||||
bool *losesInfo) {
|
bool *losesInfo);
|
||||||
return IEEE.convert(ToSemantics, RM, losesInfo);
|
|
||||||
}
|
|
||||||
opStatus convertToInteger(integerPart *Input, unsigned int Width,
|
opStatus convertToInteger(integerPart *Input, unsigned int Width,
|
||||||
bool IsSigned, roundingMode RM,
|
bool IsSigned, roundingMode RM,
|
||||||
bool *IsExact) const {
|
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,
|
opStatus convertToInteger(APSInt &Result, roundingMode RM,
|
||||||
bool *IsExact) const {
|
bool *IsExact) const {
|
||||||
return IEEE.convertToInteger(Result, RM, IsExact);
|
return getIEEE().convertToInteger(Result, RM, IsExact);
|
||||||
}
|
}
|
||||||
opStatus convertFromAPInt(const APInt &Input, bool IsSigned,
|
opStatus convertFromAPInt(const APInt &Input, bool IsSigned,
|
||||||
roundingMode RM) {
|
roundingMode RM) {
|
||||||
return IEEE.convertFromAPInt(Input, IsSigned, RM);
|
return getIEEE().convertFromAPInt(Input, IsSigned, RM);
|
||||||
}
|
}
|
||||||
opStatus convertFromSignExtendedInteger(const integerPart *Input,
|
opStatus convertFromSignExtendedInteger(const integerPart *Input,
|
||||||
unsigned int InputSize, bool IsSigned,
|
unsigned int InputSize, bool IsSigned,
|
||||||
roundingMode RM) {
|
roundingMode RM) {
|
||||||
return IEEE.convertFromSignExtendedInteger(Input, InputSize, IsSigned, RM);
|
return getIEEE().convertFromSignExtendedInteger(Input, InputSize, IsSigned,
|
||||||
|
RM);
|
||||||
}
|
}
|
||||||
opStatus convertFromZeroExtendedInteger(const integerPart *Input,
|
opStatus convertFromZeroExtendedInteger(const integerPart *Input,
|
||||||
unsigned int InputSize, bool IsSigned,
|
unsigned int InputSize, bool IsSigned,
|
||||||
roundingMode RM) {
|
roundingMode RM) {
|
||||||
return IEEE.convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM);
|
return getIEEE().convertFromZeroExtendedInteger(Input, InputSize, IsSigned,
|
||||||
|
RM);
|
||||||
}
|
}
|
||||||
opStatus convertFromString(StringRef, roundingMode);
|
opStatus convertFromString(StringRef, roundingMode);
|
||||||
APInt bitcastToAPInt() const { return IEEE.bitcastToAPInt(); }
|
APInt bitcastToAPInt() const { return getIEEE().bitcastToAPInt(); }
|
||||||
double convertToDouble() const { return IEEE.convertToDouble(); }
|
double convertToDouble() const { return getIEEE().convertToDouble(); }
|
||||||
float convertToFloat() const { return IEEE.convertToFloat(); }
|
float convertToFloat() const { return getIEEE().convertToFloat(); }
|
||||||
|
|
||||||
bool operator==(const APFloat &) const = delete;
|
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 {
|
bool bitwiseIsEqual(const APFloat &RHS) const {
|
||||||
return IEEE.bitwiseIsEqual(RHS.IEEE);
|
return getIEEE().bitwiseIsEqual(RHS.getIEEE());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int convertToHexString(char *DST, unsigned int HexDigits,
|
unsigned int convertToHexString(char *DST, unsigned int HexDigits,
|
||||||
bool UpperCase, roundingMode RM) const {
|
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 isZero() const { return getCategory() == fcZero; }
|
||||||
bool isInfinity() const { return getCategory() == fcInfinity; }
|
bool isInfinity() const { return getCategory() == fcInfinity; }
|
||||||
bool isNaN() const { return getCategory() == fcNaN; }
|
bool isNaN() const { return getCategory() == fcNaN; }
|
||||||
|
|
||||||
bool isNegative() const { return IEEE.isNegative(); }
|
bool isNegative() const { return getIEEE().isNegative(); }
|
||||||
bool isDenormal() const { return IEEE.isDenormal(); }
|
bool isDenormal() const { return getIEEE().isDenormal(); }
|
||||||
bool isSignaling() const { return IEEE.isSignaling(); }
|
bool isSignaling() const { return getIEEE().isSignaling(); }
|
||||||
|
|
||||||
bool isNormal() const { return !isDenormal() && isFiniteNonZero(); }
|
bool isNormal() const { return !isDenormal() && isFiniteNonZero(); }
|
||||||
bool isFinite() const { return !isNaN() && !isInfinity(); }
|
bool isFinite() const { return !isNaN() && !isInfinity(); }
|
||||||
|
|
||||||
fltCategory getCategory() const { return IEEE.getCategory(); }
|
fltCategory getCategory() const { return getIEEE().getCategory(); }
|
||||||
const fltSemantics &getSemantics() const { return *semantics; }
|
const fltSemantics &getSemantics() const { return *U.semantics; }
|
||||||
bool isNonZero() const { return !isZero(); }
|
bool isNonZero() const { return !isZero(); }
|
||||||
bool isFiniteNonZero() const { return isFinite() && !isZero(); }
|
bool isFiniteNonZero() const { return isFinite() && !isZero(); }
|
||||||
bool isPosZero() const { return isZero() && !isNegative(); }
|
bool isPosZero() const { return isZero() && !isNegative(); }
|
||||||
bool isNegZero() const { return isZero() && isNegative(); }
|
bool isNegZero() const { return isZero() && isNegative(); }
|
||||||
bool isSmallest() const { return IEEE.isSmallest(); }
|
bool isSmallest() const { return getIEEE().isSmallest(); }
|
||||||
bool isLargest() const { return IEEE.isLargest(); }
|
bool isLargest() const { return getIEEE().isLargest(); }
|
||||||
bool isInteger() const { return IEEE.isInteger(); }
|
bool isInteger() const { return getIEEE().isInteger(); }
|
||||||
|
|
||||||
APFloat &operator=(const APFloat &RHS) {
|
APFloat &operator=(const APFloat &RHS) = default;
|
||||||
IEEE = RHS.IEEE;
|
APFloat &operator=(APFloat &&RHS) = default;
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
APFloat &operator=(APFloat &&RHS) {
|
|
||||||
IEEE = std::move(RHS.IEEE);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0,
|
void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0,
|
||||||
unsigned FormatMaxPadding = 3) const {
|
unsigned FormatMaxPadding = 3) const {
|
||||||
return IEEE.toString(Str, FormatPrecision, FormatMaxPadding);
|
return getIEEE().toString(Str, FormatPrecision, FormatMaxPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getExactInverse(APFloat *inv) const {
|
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 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 scalbn(APFloat X, int Exp, roundingMode RM);
|
||||||
friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM);
|
friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM);
|
||||||
|
friend DoubleAPFloat;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// See friend declarations above.
|
/// See friend declarations above.
|
||||||
@ -870,7 +1034,7 @@ public:
|
|||||||
/// xlC compiler.
|
/// xlC compiler.
|
||||||
hash_code hash_value(const APFloat &Arg);
|
hash_code hash_value(const APFloat &Arg);
|
||||||
inline APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM) {
|
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.
|
/// \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,
|
/// 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.
|
/// this returns INT_MAX for infinities, and INT_MIN for NaNs.
|
||||||
inline APFloat frexp(const APFloat &X, int &Exp, APFloat::roundingMode RM) {
|
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.
|
/// \brief Returns the absolute value of the argument.
|
||||||
inline APFloat abs(APFloat X) {
|
inline APFloat abs(APFloat X) {
|
||||||
|
@ -75,8 +75,18 @@ namespace llvm {
|
|||||||
to represent all possible values held by a PPC double-double number,
|
to represent all possible values held by a PPC double-double number,
|
||||||
for example: (long double) 1.0 + (long double) 0x1p-106
|
for example: (long double) 1.0 + (long double) 0x1p-106
|
||||||
Should this be replaced by a full emulation of PPC double-double? */
|
Should this be replaced by a full emulation of PPC double-double? */
|
||||||
const fltSemantics APFloatBase::PPCDoubleDouble = {1023, -1022 + 53, 53 + 53,
|
const fltSemantics APFloatBase::PPCDoubleDouble = {0, 0, 0, 0};
|
||||||
128};
|
|
||||||
|
/* 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
|
/* A tight upper bound on number of parts required to hold the value
|
||||||
pow(5, power) is
|
pow(5, power) is
|
||||||
@ -677,13 +687,6 @@ void IEEEFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill) {
|
|||||||
APInt::tcSetBit(significand, QNaNBit + 1);
|
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) {
|
IEEEFloat &IEEEFloat::operator=(const IEEEFloat &rhs) {
|
||||||
if (this != &rhs) {
|
if (this != &rhs) {
|
||||||
if (semantics != rhs.semantics) {
|
if (semantics != rhs.semantics) {
|
||||||
@ -820,11 +823,6 @@ IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics, uninitializedTag tag) {
|
|||||||
initialize(&ourSemantics);
|
initialize(&ourSemantics);
|
||||||
}
|
}
|
||||||
|
|
||||||
IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics, StringRef text) {
|
|
||||||
initialize(&ourSemantics);
|
|
||||||
convertFromString(text, rmNearestTiesToEven);
|
|
||||||
}
|
|
||||||
|
|
||||||
IEEEFloat::IEEEFloat(const IEEEFloat &rhs) {
|
IEEEFloat::IEEEFloat(const IEEEFloat &rhs) {
|
||||||
initialize(rhs.semantics);
|
initialize(rhs.semantics);
|
||||||
assign(rhs);
|
assign(rhs);
|
||||||
@ -2366,7 +2364,8 @@ IEEEFloat::roundSignificandWithExponent(const integerPart *decSigParts,
|
|||||||
excessPrecision = calcSemantics.precision - semantics->precision;
|
excessPrecision = calcSemantics.precision - semantics->precision;
|
||||||
truncatedBits = excessPrecision;
|
truncatedBits = excessPrecision;
|
||||||
|
|
||||||
IEEEFloat decSig = IEEEFloat::getZero(calcSemantics, sign);
|
IEEEFloat decSig(calcSemantics, uninitialized);
|
||||||
|
decSig.makeZero(sign);
|
||||||
IEEEFloat pow5(calcSemantics);
|
IEEEFloat pow5(calcSemantics);
|
||||||
|
|
||||||
sigStatus = decSig.convertFromUnsignedParts(decSigParts, sigPartCount,
|
sigStatus = decSig.convertFromUnsignedParts(decSigParts, sigPartCount,
|
||||||
@ -2821,7 +2820,7 @@ APInt IEEEFloat::convertF80LongDoubleAPFloatToAPInt() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
APInt IEEEFloat::convertPPCDoubleDoubleAPFloatToAPInt() const {
|
APInt IEEEFloat::convertPPCDoubleDoubleAPFloatToAPInt() const {
|
||||||
assert(semantics == (const llvm::fltSemantics*)&PPCDoubleDouble);
|
assert(semantics == (const llvm::fltSemantics *)&PPCDoubleDoubleImpl);
|
||||||
assert(partCount()==2);
|
assert(partCount()==2);
|
||||||
|
|
||||||
uint64_t words[2];
|
uint64_t words[2];
|
||||||
@ -3002,7 +3001,7 @@ APInt IEEEFloat::bitcastToAPInt() const {
|
|||||||
if (semantics == (const llvm::fltSemantics*)&IEEEquad)
|
if (semantics == (const llvm::fltSemantics*)&IEEEquad)
|
||||||
return convertQuadrupleAPFloatToAPInt();
|
return convertQuadrupleAPFloatToAPInt();
|
||||||
|
|
||||||
if (semantics == (const llvm::fltSemantics*)&PPCDoubleDouble)
|
if (semantics == (const llvm::fltSemantics *)&PPCDoubleDoubleImpl)
|
||||||
return convertPPCDoubleDoubleAPFloatToAPInt();
|
return convertPPCDoubleDoubleAPFloatToAPInt();
|
||||||
|
|
||||||
assert(semantics == (const llvm::fltSemantics*)&x87DoubleExtended &&
|
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.
|
// Get the first double and convert to our format.
|
||||||
initFromDoubleAPInt(APInt(64, i1));
|
initFromDoubleAPInt(APInt(64, i1));
|
||||||
fs = convert(PPCDoubleDouble, rmNearestTiesToEven, &losesInfo);
|
fs = convert(PPCDoubleDoubleImpl, rmNearestTiesToEven, &losesInfo);
|
||||||
assert(fs == opOK && !losesInfo);
|
assert(fs == opOK && !losesInfo);
|
||||||
(void)fs;
|
(void)fs;
|
||||||
|
|
||||||
// Unless we have a special case, add in second double.
|
// Unless we have a special case, add in second double.
|
||||||
if (isFiniteNonZero()) {
|
if (isFiniteNonZero()) {
|
||||||
IEEEFloat v(IEEEdouble, APInt(64, i2));
|
IEEEFloat v(IEEEdouble, APInt(64, i2));
|
||||||
fs = v.convert(PPCDoubleDouble, rmNearestTiesToEven, &losesInfo);
|
fs = v.convert(PPCDoubleDoubleImpl, rmNearestTiesToEven, &losesInfo);
|
||||||
assert(fs == opOK && !losesInfo);
|
assert(fs == opOK && !losesInfo);
|
||||||
(void)fs;
|
(void)fs;
|
||||||
|
|
||||||
@ -3233,13 +3232,13 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) {
|
|||||||
return initFromF80LongDoubleAPInt(api);
|
return initFromF80LongDoubleAPInt(api);
|
||||||
if (Sem == &IEEEquad)
|
if (Sem == &IEEEquad)
|
||||||
return initFromQuadrupleAPInt(api);
|
return initFromQuadrupleAPInt(api);
|
||||||
if (Sem == &PPCDoubleDouble)
|
if (Sem == &PPCDoubleDoubleImpl)
|
||||||
return initFromPPCDoubleDoubleAPInt(api);
|
return initFromPPCDoubleDoubleAPInt(api);
|
||||||
|
|
||||||
llvm_unreachable(nullptr);
|
llvm_unreachable(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) {
|
IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth) {
|
||||||
switch (BitWidth) {
|
switch (BitWidth) {
|
||||||
case 16:
|
case 16:
|
||||||
return IEEEFloat(IEEEhalf, APInt::getAllOnesValue(BitWidth));
|
return IEEEFloat(IEEEhalf, APInt::getAllOnesValue(BitWidth));
|
||||||
@ -3250,9 +3249,7 @@ IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) {
|
|||||||
case 80:
|
case 80:
|
||||||
return IEEEFloat(x87DoubleExtended, APInt::getAllOnesValue(BitWidth));
|
return IEEEFloat(x87DoubleExtended, APInt::getAllOnesValue(BitWidth));
|
||||||
case 128:
|
case 128:
|
||||||
if (isIEEE)
|
return IEEEFloat(IEEEquad, APInt::getAllOnesValue(BitWidth));
|
||||||
return IEEEFloat(IEEEquad, APInt::getAllOnesValue(BitWidth));
|
|
||||||
return IEEEFloat(PPCDoubleDouble, APInt::getAllOnesValue(BitWidth));
|
|
||||||
default:
|
default:
|
||||||
llvm_unreachable("Unknown floating bit width");
|
llvm_unreachable("Unknown floating bit width");
|
||||||
}
|
}
|
||||||
@ -3296,43 +3293,18 @@ void IEEEFloat::makeSmallest(bool Negative) {
|
|||||||
APInt::tcSet(significandParts(), 1, partCount());
|
APInt::tcSet(significandParts(), 1, partCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
IEEEFloat IEEEFloat::getLargest(const fltSemantics &Sem, bool Negative) {
|
void IEEEFloat::makeSmallestNormalized(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);
|
|
||||||
|
|
||||||
// We want (in interchange format):
|
// We want (in interchange format):
|
||||||
// sign = {Negative}
|
// sign = {Negative}
|
||||||
// exponent = 0..0
|
// exponent = 0..0
|
||||||
// significand = 10..0
|
// significand = 10..0
|
||||||
|
|
||||||
Val.category = fcNormal;
|
category = fcNormal;
|
||||||
Val.zeroSignificand();
|
zeroSignificand();
|
||||||
Val.sign = Negative;
|
sign = Negative;
|
||||||
Val.exponent = Sem.minExponent;
|
exponent = semantics->minExponent;
|
||||||
Val.significandParts()[partCountForBits(Sem.precision)-1] |=
|
significandParts()[partCountForBits(semantics->precision) - 1] |=
|
||||||
(((integerPart) 1) << ((Sem.precision - 1) % integerPartWidth));
|
(((integerPart)1) << ((semantics->precision - 1) % integerPartWidth));
|
||||||
|
|
||||||
return Val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IEEEFloat::IEEEFloat(const fltSemantics &Sem, const APInt &API) {
|
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);
|
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
|
} // End detail namespace
|
||||||
|
|
||||||
APFloat::opStatus APFloat::convertFromString(StringRef Str, roundingMode RM) {
|
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::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
|
} // End llvm namespace
|
||||||
|
Loading…
x
Reference in New Issue
Block a user