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
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,
/// @}
- /// \brief Returns whether this instance allocated memory.
+ /// Returns whether this instance allocated memory.
bool needsCleanup() const { return partCount() > 1; }
/// \name Convenience "constructors"
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
/// return true.
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:
///
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);
llvm_unreachable("Unexpected semantics");
}
+ // TODO: bool parameters are not readable and a source of bugs.
+ // Do something.
opStatus next(bool nextDown) {
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.next(nextDown);
llvm_unreachable("Unexpected semantics");
}
- /// \brief Operator+ overload which provides the default
- /// \c rmNearestTiesToEven rounding mode and *no* error checking.
+ /// Add two APFloats, rounding ties to the nearest even.
+ /// No error checking.
APFloat operator+(const APFloat &RHS) const {
APFloat Result(*this);
(void)Result.add(RHS, rmNearestTiesToEven);
return Result;
}
- /// \brief Operator- overload which provides the default
- /// \c rmNearestTiesToEven rounding mode and *no* error checking.
+ /// Subtract two APFloats, rounding ties to the nearest even.
+ /// No error checking.
APFloat operator-(const APFloat &RHS) const {
APFloat Result(*this);
(void)Result.subtract(RHS, rmNearestTiesToEven);
return Result;
}
- /// \brief Operator* overload which provides the default
- /// \c rmNearestTiesToEven rounding mode and *no* error checking.
+ /// Multiply two APFloats, rounding ties to the nearest even.
+ /// No error checking.
APFloat operator*(const APFloat &RHS) const {
APFloat Result(*this);
(void)Result.multiply(RHS, rmNearestTiesToEven);
return Result;
}
- /// \brief Operator/ overload which provides the default
- /// \c rmNearestTiesToEven rounding mode and *no* error checking.
+ /// Divide the first APFloat by the second, rounding ties to the nearest even.
+ /// No error checking.
APFloat operator/(const APFloat &RHS) const {
APFloat Result(*this);
(void)Result.divide(RHS, rmNearestTiesToEven);
changeSign();
}
- /// \brief A static helper to produce a copy of an APFloat value with its sign
+ /// 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) {
Value.copySign(Sign);
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.
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;
static const fltSemantics semX87DoubleExtended = {16383, -16382, 64, 80};
static const fltSemantics semBogus = {0, 0, 0, 0};
- /* The PowerPC format consists of two doubles. It does not map cleanly
- onto the usual format above. It is approximated using twice the
- mantissa bits. Note that for exponents near the double minimum,
- we no longer can represent the full 106 mantissa bits, so those
- will be treated as denormal numbers.
-
- FIXME: While this approximation is equivalent to what GCC uses for
- compile-time arithmetic on PPC double-double numbers, it is not able
- 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?
+ /* The IBM double-double semantics. Such a number consists of a pair of IEEE
+ 64-bit doubles (Hi, Lo), where |Hi| > |Lo|, and if normal,
+ (double)(Hi + Lo) == Hi. The numeric value it's modeling is Hi + Lo.
+ Therefore it has two 53-bit mantissa parts that aren't necessarily adjacent
+ to each other, and two 11-bit exponents.
Note: we need to make the value different from semBogus as otherwise
an unsafe optimization may collapse both values to a single address,
/* These are legacy semantics for the fallback, inaccrurate implementation of
IBM double-double, if the accurate semPPCDoubleDouble doesn't handle the
- case. It's equivalent to have an IEEE number with consecutive 106 bits of
- mantissa, and 11 bits of exponent. It's not accurate, becuase the two
- 53-bit mantissa parts don't actually have to be consecutive,
- e.g. 1 + epsilon.
+ operation. It's equivalent to having an IEEE number with consecutive 106
+ bits of mantissa and 11 bits of exponent.
+
+ It's not equivalent to IBM double-double. For example, a legit IBM
+ double-double, 1 + epsilon:
+
+ 1 + epsilon = 1 + (1 >> 1076)
+
+ is not representable by a consecutive 106 bits of mantissa.
Currently, these semantics are used in the following way:
- (IEEEdouble, IEEEdouble) -> (64-bit APInt, 64-bit APInt) ->
- (128-bit APInt) -> semPPCDoubleDoubleLegacy -> IEEE operations
+ semPPCDoubleDouble -> (IEEEdouble, IEEEdouble) ->
+ (64-bit APInt, 64-bit APInt) -> (128-bit APInt) ->
+ semPPCDoubleDoubleLegacy -> IEEE operations
We use bitcastToAPInt() to get the bit representation (in APInt) of the
underlying IEEEdouble, then use the APInt constructor to construct the
if (!z.isFinite()) {
if (!z.isInfinity()) {
Floats[0] = std::move(z);
- Floats[1].makeZero(false);
+ Floats[1].makeZero(/* Neg = */ false);
return (opStatus)Status;
}
Status = opOK;
}
if (!z.isFinite()) {
Floats[0] = std::move(z);
- Floats[1].makeZero(false);
+ Floats[1].makeZero(/* Neg = */ false);
return (opStatus)Status;
}
Floats[0] = z;
Status |= zz.add(cc, RM);
if (zz.isZero() && !zz.isNegative()) {
Floats[0] = std::move(z);
- Floats[1].makeZero(false);
+ Floats[1].makeZero(/* Neg = */ false);
return opOK;
}
Floats[0] = z;
Status |= Floats[0].add(zz, RM);
if (!Floats[0].isFinite()) {
- Floats[1].makeZero(false);
+ Floats[1].makeZero(/* Neg = */ false);
return (opStatus)Status;
}
Floats[1] = std::move(z);
Status |= T.multiply(C, RM);
if (!T.isFiniteNonZero()) {
Floats[0] = T;
- Floats[1].makeZero(false);
+ Floats[1].makeZero(/* Neg = */ false);
return (opStatus)Status;
}
Floats[0] = U;
if (!U.isFinite()) {
- Floats[1].makeZero(false);
+ Floats[1].makeZero(/* Neg = */ false);
} else {
// Floats[1] = (t - u) + tau
Status |= T.subtract(U, RM);
void DoubleAPFloat::makeInf(bool Neg) {
Floats[0].makeInf(Neg);
- Floats[1].makeZero(false);
+ Floats[1].makeZero(/* Neg = */ false);
}
void DoubleAPFloat::makeZero(bool Neg) {
Floats[0].makeZero(Neg);
- Floats[1].makeZero(false);
+ Floats[1].makeZero(/* Neg = */ false);
}
void DoubleAPFloat::makeLargest(bool Neg) {
void DoubleAPFloat::makeSmallest(bool Neg) {
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
Floats[0].makeSmallest(Neg);
- Floats[1].makeZero(false);
+ Floats[1].makeZero(/* Neg = */ false);
}
void DoubleAPFloat::makeSmallestNormalized(bool Neg) {
Floats[0] = APFloat(semIEEEdouble, APInt(64, 0x0360000000000000ull));
if (Neg)
Floats[0].changeSign();
- Floats[1].makeZero(false);
+ Floats[1].makeZero(/* Neg = */ false);
}
void DoubleAPFloat::makeNaN(bool SNaN, bool Neg, const APInt *fill) {
Floats[0].makeNaN(SNaN, Neg, fill);
- Floats[1].makeZero(false);
+ Floats[1].makeZero(/* Neg = */ false);
}
APFloat::cmpResult DoubleAPFloat::compare(const DoubleAPFloat &RHS) const {
auto Result = Floats[0].compare(RHS.Floats[0]);
+ // |Float[0]| > |Float[1]|
if (Result == APFloat::cmpEqual)
return Floats[1].compare(RHS.Floats[1]);
return Result;
bool DoubleAPFloat::isDenormal() const {
return getCategory() == fcNormal &&
(Floats[0].isDenormal() || Floats[1].isDenormal() ||
+ // (double)(Hi + Lo) == Hi defines a normal number.
Floats[0].compare(Floats[0] + Floats[1]) != cmpEqual);
}