summaryrefslogtreecommitdiff
path: root/llvm/lib/Support/APFloat.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Support/APFloat.cpp')
-rw-r--r--llvm/lib/Support/APFloat.cpp40
1 files changed, 37 insertions, 3 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 5dea98ee3993..7abca8391f70 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -66,6 +66,13 @@ namespace llvm {
/* Number of bits actually used in the semantics. */
unsigned int sizeInBits;
+
+ // Returns true if any number described by this semantics can be precisely
+ // represented by the specified semantics.
+ bool isRepresentableBy(const fltSemantics &S) const {
+ return maxExponent <= S.maxExponent && minExponent >= S.minExponent &&
+ precision <= S.precision;
+ }
};
static const fltSemantics semIEEEhalf = {15, -14, 11, 16};
@@ -3748,7 +3755,7 @@ namespace {
exp += FirstSignificant;
buffer.erase(&buffer[0], &buffer[FirstSignificant]);
}
-}
+} // namespace
void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
unsigned FormatMaxPadding, bool TruncateZero) const {
@@ -4761,7 +4768,8 @@ bool DoubleAPFloat::getExactInverse(APFloat *inv) const {
return Ret;
}
-DoubleAPFloat scalbn(DoubleAPFloat Arg, int Exp, APFloat::roundingMode RM) {
+DoubleAPFloat scalbn(const DoubleAPFloat &Arg, int Exp,
+ APFloat::roundingMode RM) {
assert(Arg.Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
return DoubleAPFloat(semPPCDoubleDouble, scalbn(Arg.Floats[0], Exp, RM),
scalbn(Arg.Floats[1], Exp, RM));
@@ -4777,7 +4785,7 @@ DoubleAPFloat frexp(const DoubleAPFloat &Arg, int &Exp,
return DoubleAPFloat(semPPCDoubleDouble, std::move(First), std::move(Second));
}
-} // End detail namespace
+} // namespace detail
APFloat::Storage::Storage(IEEEFloat F, const fltSemantics &Semantics) {
if (usesLayout<IEEEFloat>(Semantics)) {
@@ -4874,6 +4882,32 @@ APFloat::opStatus APFloat::convertToInteger(APSInt &result,
return status;
}
+double APFloat::convertToDouble() const {
+ if (&getSemantics() == (const llvm::fltSemantics *)&semIEEEdouble)
+ return getIEEE().convertToDouble();
+ assert(getSemantics().isRepresentableBy(semIEEEdouble) &&
+ "Float semantics is not representable by IEEEdouble");
+ APFloat Temp = *this;
+ bool LosesInfo;
+ opStatus St = Temp.convert(semIEEEdouble, rmNearestTiesToEven, &LosesInfo);
+ assert(!(St & opInexact) && !LosesInfo && "Unexpected imprecision");
+ (void)St;
+ return Temp.getIEEE().convertToDouble();
+}
+
+float APFloat::convertToFloat() const {
+ if (&getSemantics() == (const llvm::fltSemantics *)&semIEEEsingle)
+ return getIEEE().convertToFloat();
+ assert(getSemantics().isRepresentableBy(semIEEEsingle) &&
+ "Float semantics is not representable by IEEEsingle");
+ APFloat Temp = *this;
+ bool LosesInfo;
+ opStatus St = Temp.convert(semIEEEsingle, rmNearestTiesToEven, &LosesInfo);
+ assert(!(St & opInexact) && !LosesInfo && "Unexpected imprecision");
+ (void)St;
+ return Temp.getIEEE().convertToFloat();
+}
+
} // namespace llvm
#undef APFLOAT_DISPATCH_ON_SEMANTICS