diff options
Diffstat (limited to 'include/llvm/ADT/APFloat.h')
-rw-r--r-- | include/llvm/ADT/APFloat.h | 370 |
1 files changed, 235 insertions, 135 deletions
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 00304230a991a..e7e5036e69307 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -18,9 +18,19 @@ #define LLVM_ADT_APFLOAT_H #include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/ErrorHandling.h" #include <memory> +#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) + namespace llvm { struct fltSemantics; @@ -42,7 +52,7 @@ enum lostFraction { // Example of truncated bits: lfMoreThanHalf // 1xxxxx x's not all zero }; -/// \brief A self-contained host- and target-independent arbitrary-precision +/// A self-contained host- and target-independent arbitrary-precision /// floating-point software implementation. /// /// APFloat uses bignum integer arithmetic as provided by static functions in @@ -130,22 +140,25 @@ enum lostFraction { // Example of truncated bits: // implementation classes. This struct should not define any non-static data // members. struct APFloatBase { + // TODO remove this and use APInt typedef directly. + typedef APInt::WordType integerPart; + /// A signed type to represent a floating point numbers unbiased exponent. typedef signed short ExponentType; /// \name Floating Point Semantics. /// @{ - static const fltSemantics &IEEEhalf(); - static const fltSemantics &IEEEsingle(); - static const fltSemantics &IEEEdouble(); - static const fltSemantics &IEEEquad(); - static const fltSemantics &PPCDoubleDouble(); - static const fltSemantics &x87DoubleExtended(); + static const fltSemantics &IEEEhalf() LLVM_READNONE; + static const fltSemantics &IEEEsingle() LLVM_READNONE; + static const fltSemantics &IEEEdouble() LLVM_READNONE; + static const fltSemantics &IEEEquad() LLVM_READNONE; + static const fltSemantics &PPCDoubleDouble() LLVM_READNONE; + static const fltSemantics &x87DoubleExtended() LLVM_READNONE; /// A Pseudo fltsemantic used to construct APFloats that cannot conflict with /// anything real. - static const fltSemantics &Bogus(); + static const fltSemantics &Bogus() LLVM_READNONE; /// @} @@ -191,7 +204,7 @@ struct APFloatBase { uninitialized }; - /// \brief Enumeration of \c ilogb error results. + /// Enumeration of \c ilogb error results. enum IlogbErrorKinds { IEK_Zero = INT_MIN + 1, IEK_NaN = INT_MIN, @@ -227,7 +240,7 @@ public: /// @} - /// \brief Returns whether this instance allocated memory. + /// Returns whether this instance allocated memory. bool needsCleanup() const { return partCount() > 1; } /// \name Convenience "constructors" @@ -235,10 +248,6 @@ public: /// @} - /// Used to insert APFloat objects, or objects that contain APFloat objects, - /// into FoldingSets. - void Profile(FoldingSetNodeID &NID) const; - /// \name Arithmetic /// @{ @@ -255,53 +264,12 @@ public: /// IEEE-754R 5.3.1: nextUp/nextDown. opStatus next(bool nextDown); - /// \brief Operator+ overload which provides the default - /// \c nmNearestTiesToEven rounding mode and *no* error checking. - IEEEFloat operator+(const IEEEFloat &RHS) const { - IEEEFloat Result = *this; - Result.add(RHS, rmNearestTiesToEven); - return Result; - } - - /// \brief Operator- overload which provides the default - /// \c nmNearestTiesToEven rounding mode and *no* error checking. - IEEEFloat operator-(const IEEEFloat &RHS) const { - IEEEFloat Result = *this; - Result.subtract(RHS, rmNearestTiesToEven); - return Result; - } - - /// \brief Operator* overload which provides the default - /// \c nmNearestTiesToEven rounding mode and *no* error checking. - IEEEFloat operator*(const IEEEFloat &RHS) const { - IEEEFloat Result = *this; - Result.multiply(RHS, rmNearestTiesToEven); - return Result; - } - - /// \brief Operator/ overload which provides the default - /// \c nmNearestTiesToEven rounding mode and *no* error checking. - IEEEFloat operator/(const IEEEFloat &RHS) const { - IEEEFloat Result = *this; - Result.divide(RHS, rmNearestTiesToEven); - return Result; - } - /// @} /// \name Sign operations. /// @{ void changeSign(); - void clearSign(); - void copySign(const IEEEFloat &); - - /// \brief A static helper to produce a copy of an APFloat value with its sign - /// copied from some other APFloat. - static IEEEFloat copySign(IEEEFloat Value, const IEEEFloat &Sign) { - Value.copySign(Sign); - return Value; - } /// @} @@ -309,9 +277,8 @@ public: /// @{ opStatus convert(const fltSemantics &, roundingMode, bool *); - opStatus convertToInteger(integerPart *, unsigned int, bool, roundingMode, - bool *) const; - opStatus convertToInteger(APSInt &, roundingMode, bool *) const; + opStatus convertToInteger(MutableArrayRef<integerPart>, unsigned int, bool, + roundingMode, bool *) const; opStatus convertFromAPInt(const APInt &, bool, roundingMode); opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int, bool, roundingMode); @@ -398,7 +365,7 @@ public: /// Returns true if and only if the number has the largest possible finite /// magnitude in the current semantics. bool isLargest() const; - + /// Returns true if and only if the number is an exact integer. bool isInteger() const; @@ -407,7 +374,7 @@ public: IEEEFloat &operator=(const IEEEFloat &); IEEEFloat &operator=(IEEEFloat &&); - /// \brief Overload to compute a hash code for an APFloat value. + /// Overload to compute a hash code for an APFloat value. /// /// Note that the use of hash codes for floating point values is in general /// frought with peril. Equality is hard to define for these values. For @@ -443,9 +410,9 @@ public: /// If this value has an exact multiplicative inverse, store it in inv and /// return true. - bool getExactInverse(IEEEFloat *inv) const; + bool getExactInverse(APFloat *inv) const; - /// \brief Returns the exponent of the internal representation of the APFloat. + /// Returns the exponent of the internal representation of the APFloat. /// /// Because the radix of APFloat is 2, this is equivalent to floor(log2(x)). /// For special APFloat values, this returns special error codes: @@ -456,7 +423,7 @@ public: /// friend int ilogb(const IEEEFloat &Arg); - /// \brief Returns: X * 2^Exp for integral exponents. + /// Returns: X * 2^Exp for integral exponents. friend IEEEFloat scalbn(IEEEFloat X, int Exp, roundingMode); friend IEEEFloat frexp(const IEEEFloat &X, int &Exp, roundingMode); @@ -532,8 +499,9 @@ private: opStatus addOrSubtract(const IEEEFloat &, roundingMode, bool subtract); opStatus handleOverflow(roundingMode); bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const; - opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool, - roundingMode, bool *) const; + opStatus convertToSignExtendedInteger(MutableArrayRef<integerPart>, + unsigned int, bool, roundingMode, + bool *) const; opStatus convertFromUnsignedParts(const integerPart *, unsigned int, roundingMode); opStatus convertFromHexadecimalString(StringRef, roundingMode); @@ -636,6 +604,13 @@ public: opStatus add(const DoubleAPFloat &RHS, roundingMode RM); opStatus subtract(const DoubleAPFloat &RHS, roundingMode RM); + opStatus multiply(const DoubleAPFloat &RHS, roundingMode RM); + opStatus divide(const DoubleAPFloat &RHS, roundingMode RM); + opStatus remainder(const DoubleAPFloat &RHS); + opStatus mod(const DoubleAPFloat &RHS); + opStatus fusedMultiplyAdd(const DoubleAPFloat &Multiplicand, + const DoubleAPFloat &Addend, roundingMode RM); + opStatus roundToIntegral(roundingMode RM); void changeSign(); cmpResult compareAbsoluteValue(const DoubleAPFloat &RHS) const; @@ -643,9 +618,49 @@ public: bool isNegative() const; void makeInf(bool Neg); + void makeZero(bool Neg); + void makeLargest(bool Neg); + void makeSmallest(bool Neg); + void makeSmallestNormalized(bool Neg); void makeNaN(bool SNaN, bool Neg, const APInt *fill); + + cmpResult compare(const DoubleAPFloat &RHS) const; + bool bitwiseIsEqual(const DoubleAPFloat &RHS) const; + APInt bitcastToAPInt() const; + opStatus convertFromString(StringRef, roundingMode); + opStatus next(bool nextDown); + + opStatus convertToInteger(MutableArrayRef<integerPart> Input, + unsigned int Width, bool IsSigned, roundingMode RM, + bool *IsExact) const; + opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM); + opStatus convertFromSignExtendedInteger(const integerPart *Input, + unsigned int InputSize, bool IsSigned, + roundingMode RM); + opStatus convertFromZeroExtendedInteger(const integerPart *Input, + unsigned int InputSize, bool IsSigned, + roundingMode RM); + unsigned int convertToHexString(char *DST, unsigned int HexDigits, + bool UpperCase, roundingMode RM) const; + + bool isDenormal() const; + bool isSmallest() const; + bool isLargest() const; + bool isInteger() const; + + void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision, + unsigned FormatMaxPadding) const; + + bool getExactInverse(APFloat *inv) const; + + friend int ilogb(const DoubleAPFloat &Arg); + friend DoubleAPFloat scalbn(DoubleAPFloat X, int Exp, roundingMode); + friend DoubleAPFloat frexp(const DoubleAPFloat &X, int &Exp, roundingMode); + friend hash_code hash_value(const DoubleAPFloat &Arg); }; +hash_code hash_value(const DoubleAPFloat &Arg); + } // End detail namespace // This is a interface class that is currently forwarding functionalities from @@ -770,26 +785,24 @@ class APFloat : public APFloatBase { llvm_unreachable("Unexpected semantics"); } - void makeZero(bool Neg) { getIEEE().makeZero(Neg); } + void makeZero(bool Neg) { APFLOAT_DISPATCH_ON_SEMANTICS(makeZero(Neg)); } - void makeInf(bool Neg) { - if (usesLayout<IEEEFloat>(*U.semantics)) - return U.IEEE.makeInf(Neg); - if (usesLayout<DoubleAPFloat>(*U.semantics)) - return U.Double.makeInf(Neg); - llvm_unreachable("Unexpected semantics"); - } + void makeInf(bool Neg) { APFLOAT_DISPATCH_ON_SEMANTICS(makeInf(Neg)); } void makeNaN(bool SNaN, bool Neg, const APInt *fill) { - getIEEE().makeNaN(SNaN, Neg, fill); + APFLOAT_DISPATCH_ON_SEMANTICS(makeNaN(SNaN, Neg, fill)); } - void makeLargest(bool Neg) { getIEEE().makeLargest(Neg); } + void makeLargest(bool Neg) { + APFLOAT_DISPATCH_ON_SEMANTICS(makeLargest(Neg)); + } - void makeSmallest(bool Neg) { getIEEE().makeSmallest(Neg); } + void makeSmallest(bool Neg) { + APFLOAT_DISPATCH_ON_SEMANTICS(makeSmallest(Neg)); + } void makeSmallestNormalized(bool Neg) { - getIEEE().makeSmallestNormalized(Neg); + APFLOAT_DISPATCH_ON_SEMANTICS(makeSmallestNormalized(Neg)); } // FIXME: This is due to clang 3.3 (or older version) always checks for the @@ -804,7 +817,8 @@ class APFloat : public APFloatBase { : U(std::move(F), S) {} cmpResult compareAbsoluteValue(const APFloat &RHS) const { - assert(&getSemantics() == &RHS.getSemantics()); + assert(&getSemantics() == &RHS.getSemantics() && + "Should only compare APFloats with the same semantics"); if (usesLayout<IEEEFloat>(getSemantics())) return U.IEEE.compareAbsoluteValue(RHS.U.IEEE); if (usesLayout<DoubleAPFloat>(getSemantics())) @@ -827,13 +841,7 @@ public: ~APFloat() = default; - bool needsCleanup() const { - if (usesLayout<IEEEFloat>(getSemantics())) - return U.IEEE.needsCleanup(); - if (usesLayout<DoubleAPFloat>(getSemantics())) - return U.Double.needsCleanup(); - llvm_unreachable("Unexpected semantics"); - } + bool needsCleanup() const { APFLOAT_DISPATCH_ON_SEMANTICS(needsCleanup()); } /// Factory for Positive and Negative Zero. /// @@ -920,9 +928,13 @@ public: /// \param isIEEE - If 128 bit number, select between PPC and IEEE static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false); - void Profile(FoldingSetNodeID &NID) const { getIEEE().Profile(NID); } + /// Used to insert APFloat objects, or objects that contain APFloat objects, + /// into FoldingSets. + void Profile(FoldingSetNodeID &NID) const; opStatus add(const APFloat &RHS, roundingMode RM) { + assert(&getSemantics() == &RHS.getSemantics() && + "Should only call on two APFloats with the same semantics"); if (usesLayout<IEEEFloat>(getSemantics())) return U.IEEE.add(RHS.U.IEEE, RM); if (usesLayout<DoubleAPFloat>(getSemantics())) @@ -930,6 +942,8 @@ public: llvm_unreachable("Unexpected semantics"); } opStatus subtract(const APFloat &RHS, roundingMode RM) { + assert(&getSemantics() == &RHS.getSemantics() && + "Should only call on two APFloats with the same semantics"); if (usesLayout<IEEEFloat>(getSemantics())) return U.IEEE.subtract(RHS.U.IEEE, RM); if (usesLayout<DoubleAPFloat>(getSemantics())) @@ -937,95 +951,172 @@ public: llvm_unreachable("Unexpected semantics"); } opStatus multiply(const APFloat &RHS, roundingMode RM) { - return getIEEE().multiply(RHS.getIEEE(), RM); + assert(&getSemantics() == &RHS.getSemantics() && + "Should only call on two APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.multiply(RHS.U.IEEE, RM); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.multiply(RHS.U.Double, RM); + llvm_unreachable("Unexpected semantics"); } opStatus divide(const APFloat &RHS, roundingMode RM) { - return getIEEE().divide(RHS.getIEEE(), RM); + assert(&getSemantics() == &RHS.getSemantics() && + "Should only call on two APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.divide(RHS.U.IEEE, RM); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.divide(RHS.U.Double, RM); + llvm_unreachable("Unexpected semantics"); } opStatus remainder(const APFloat &RHS) { - return getIEEE().remainder(RHS.getIEEE()); + assert(&getSemantics() == &RHS.getSemantics() && + "Should only call on two APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.remainder(RHS.U.IEEE); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.remainder(RHS.U.Double); + llvm_unreachable("Unexpected semantics"); + } + opStatus mod(const APFloat &RHS) { + assert(&getSemantics() == &RHS.getSemantics() && + "Should only call on two APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.mod(RHS.U.IEEE); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.mod(RHS.U.Double); + llvm_unreachable("Unexpected semantics"); } - opStatus mod(const APFloat &RHS) { return getIEEE().mod(RHS.getIEEE()); } opStatus fusedMultiplyAdd(const APFloat &Multiplicand, const APFloat &Addend, roundingMode RM) { - return getIEEE().fusedMultiplyAdd(Multiplicand.getIEEE(), Addend.getIEEE(), - RM); + assert(&getSemantics() == &Multiplicand.getSemantics() && + "Should only call on APFloats with the same semantics"); + assert(&getSemantics() == &Addend.getSemantics() && + "Should only call on APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.fusedMultiplyAdd(Multiplicand.U.IEEE, Addend.U.IEEE, RM); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.fusedMultiplyAdd(Multiplicand.U.Double, Addend.U.Double, + RM); + llvm_unreachable("Unexpected semantics"); } opStatus roundToIntegral(roundingMode RM) { - return getIEEE().roundToIntegral(RM); + APFLOAT_DISPATCH_ON_SEMANTICS(roundToIntegral(RM)); + } + + // TODO: bool parameters are not readable and a source of bugs. + // Do something. + opStatus next(bool nextDown) { + APFLOAT_DISPATCH_ON_SEMANTICS(next(nextDown)); } - opStatus next(bool nextDown) { return getIEEE().next(nextDown); } + /// Add two APFloats, rounding ties to the nearest even. + /// No error checking. APFloat operator+(const APFloat &RHS) const { - return APFloat(getIEEE() + RHS.getIEEE(), getSemantics()); + APFloat Result(*this); + (void)Result.add(RHS, rmNearestTiesToEven); + return Result; } + /// Subtract two APFloats, rounding ties to the nearest even. + /// No error checking. APFloat operator-(const APFloat &RHS) const { - return APFloat(getIEEE() - RHS.getIEEE(), getSemantics()); + APFloat Result(*this); + (void)Result.subtract(RHS, rmNearestTiesToEven); + return Result; } + /// Multiply two APFloats, rounding ties to the nearest even. + /// No error checking. APFloat operator*(const APFloat &RHS) const { - return APFloat(getIEEE() * RHS.getIEEE(), getSemantics()); + APFloat Result(*this); + (void)Result.multiply(RHS, rmNearestTiesToEven); + return Result; } + /// Divide the first APFloat by the second, rounding ties to the nearest even. + /// No error checking. APFloat operator/(const APFloat &RHS) const { - return APFloat(getIEEE() / RHS.getIEEE(), getSemantics()); + APFloat Result(*this); + (void)Result.divide(RHS, rmNearestTiesToEven); + return Result; } - void changeSign() { getIEEE().changeSign(); } - void clearSign() { getIEEE().clearSign(); } - void copySign(const APFloat &RHS) { getIEEE().copySign(RHS.getIEEE()); } + void changeSign() { APFLOAT_DISPATCH_ON_SEMANTICS(changeSign()); } + void clearSign() { + if (isNegative()) + changeSign(); + } + void copySign(const APFloat &RHS) { + if (isNegative() != RHS.isNegative()) + changeSign(); + } + /// A static helper to produce a copy of an APFloat value with its sign + /// copied from some other APFloat. static APFloat copySign(APFloat Value, const APFloat &Sign) { - return APFloat(IEEEFloat::copySign(Value.getIEEE(), Sign.getIEEE()), - Value.getSemantics()); + Value.copySign(Sign); + return Value; } opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo); - opStatus convertToInteger(integerPart *Input, unsigned int Width, - bool IsSigned, roundingMode RM, + opStatus convertToInteger(MutableArrayRef<integerPart> Input, + unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const { - return getIEEE().convertToInteger(Input, Width, IsSigned, RM, IsExact); + APFLOAT_DISPATCH_ON_SEMANTICS( + convertToInteger(Input, Width, IsSigned, RM, IsExact)); } opStatus convertToInteger(APSInt &Result, roundingMode RM, - bool *IsExact) const { - return getIEEE().convertToInteger(Result, RM, IsExact); - } + bool *IsExact) const; opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM) { - return getIEEE().convertFromAPInt(Input, IsSigned, RM); + APFLOAT_DISPATCH_ON_SEMANTICS(convertFromAPInt(Input, IsSigned, RM)); } opStatus convertFromSignExtendedInteger(const integerPart *Input, unsigned int InputSize, bool IsSigned, roundingMode RM) { - return getIEEE().convertFromSignExtendedInteger(Input, InputSize, IsSigned, - RM); + APFLOAT_DISPATCH_ON_SEMANTICS( + convertFromSignExtendedInteger(Input, InputSize, IsSigned, RM)); } opStatus convertFromZeroExtendedInteger(const integerPart *Input, unsigned int InputSize, bool IsSigned, roundingMode RM) { - return getIEEE().convertFromZeroExtendedInteger(Input, InputSize, IsSigned, - RM); + APFLOAT_DISPATCH_ON_SEMANTICS( + convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM)); } opStatus convertFromString(StringRef, roundingMode); - APInt bitcastToAPInt() const { return getIEEE().bitcastToAPInt(); } + APInt bitcastToAPInt() const { + APFLOAT_DISPATCH_ON_SEMANTICS(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 getIEEE().compare(RHS.getIEEE()); + assert(&getSemantics() == &RHS.getSemantics() && + "Should only compare APFloats with the same semantics"); + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.compare(RHS.U.IEEE); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.compare(RHS.U.Double); + llvm_unreachable("Unexpected semantics"); } bool bitwiseIsEqual(const APFloat &RHS) const { - return getIEEE().bitwiseIsEqual(RHS.getIEEE()); + if (&getSemantics() != &RHS.getSemantics()) + return false; + if (usesLayout<IEEEFloat>(getSemantics())) + return U.IEEE.bitwiseIsEqual(RHS.U.IEEE); + if (usesLayout<DoubleAPFloat>(getSemantics())) + return U.Double.bitwiseIsEqual(RHS.U.Double); + llvm_unreachable("Unexpected semantics"); } unsigned int convertToHexString(char *DST, unsigned int HexDigits, bool UpperCase, roundingMode RM) const { - return getIEEE().convertToHexString(DST, HexDigits, UpperCase, RM); + APFLOAT_DISPATCH_ON_SEMANTICS( + convertToHexString(DST, HexDigits, UpperCase, RM)); } bool isZero() const { return getCategory() == fcZero; } @@ -1033,7 +1124,7 @@ public: bool isNaN() const { return getCategory() == fcNaN; } bool isNegative() const { return getIEEE().isNegative(); } - bool isDenormal() const { return getIEEE().isDenormal(); } + bool isDenormal() const { APFLOAT_DISPATCH_ON_SEMANTICS(isDenormal()); } bool isSignaling() const { return getIEEE().isSignaling(); } bool isNormal() const { return !isDenormal() && isFiniteNonZero(); } @@ -1045,30 +1136,24 @@ public: bool isFiniteNonZero() const { return isFinite() && !isZero(); } bool isPosZero() const { return isZero() && !isNegative(); } bool isNegZero() const { return isZero() && isNegative(); } - bool isSmallest() const { return getIEEE().isSmallest(); } - bool isLargest() const { return getIEEE().isLargest(); } - bool isInteger() const { return getIEEE().isInteger(); } + bool isSmallest() const { APFLOAT_DISPATCH_ON_SEMANTICS(isSmallest()); } + bool isLargest() const { APFLOAT_DISPATCH_ON_SEMANTICS(isLargest()); } + bool isInteger() const { APFLOAT_DISPATCH_ON_SEMANTICS(isInteger()); } APFloat &operator=(const APFloat &RHS) = default; APFloat &operator=(APFloat &&RHS) = default; void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0, unsigned FormatMaxPadding = 3) const { - return getIEEE().toString(Str, FormatPrecision, FormatMaxPadding); + APFLOAT_DISPATCH_ON_SEMANTICS( + toString(Str, FormatPrecision, FormatMaxPadding)); } void print(raw_ostream &) const; void dump() const; bool getExactInverse(APFloat *inv) const { - return getIEEE().getExactInverse(inv ? &inv->getIEEE() : nullptr); - } - - // This is for internal test only. - // TODO: Remove it after the PPCDoubleDouble transition. - const APFloat &getSecondFloat() const { - assert(&getSemantics() == &PPCDoubleDouble()); - return U.Double.getSecond(); + APFLOAT_DISPATCH_ON_SEMANTICS(getExactInverse(inv)); } friend hash_code hash_value(const APFloat &Arg); @@ -1085,22 +1170,36 @@ public: /// xlC compiler. hash_code hash_value(const APFloat &Arg); inline APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM) { - return APFloat(scalbn(X.getIEEE(), Exp, RM), X.getSemantics()); + if (APFloat::usesLayout<detail::IEEEFloat>(X.getSemantics())) + return APFloat(scalbn(X.U.IEEE, Exp, RM), X.getSemantics()); + if (APFloat::usesLayout<detail::DoubleAPFloat>(X.getSemantics())) + return APFloat(scalbn(X.U.Double, Exp, RM), X.getSemantics()); + llvm_unreachable("Unexpected semantics"); } -/// \brief Equivalent of C standard library function. +/// Equivalent of C standard library function. /// /// 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.getIEEE(), Exp, RM), X.getSemantics()); + if (APFloat::usesLayout<detail::IEEEFloat>(X.getSemantics())) + return APFloat(frexp(X.U.IEEE, Exp, RM), X.getSemantics()); + if (APFloat::usesLayout<detail::DoubleAPFloat>(X.getSemantics())) + return APFloat(frexp(X.U.Double, Exp, RM), X.getSemantics()); + llvm_unreachable("Unexpected semantics"); } -/// \brief Returns the absolute value of the argument. +/// Returns the absolute value of the argument. inline APFloat abs(APFloat X) { X.clearSign(); return X; } +/// \brief Returns the negated value of the argument. +inline APFloat neg(APFloat X) { + X.changeSign(); + return X; +} + /// Implements IEEE minNum semantics. Returns the smaller of the 2 arguments if /// both are not NaN. If either argument is a NaN, returns the other argument. LLVM_READONLY @@ -1125,4 +1224,5 @@ inline APFloat maxnum(const APFloat &A, const APFloat &B) { } // namespace llvm +#undef APFLOAT_DISPATCH_ON_SEMANTICS #endif // LLVM_ADT_APFLOAT_H |