summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Support/APFloat.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Support/APFloat.cpp')
-rw-r--r--contrib/llvm/lib/Support/APFloat.cpp75
1 files changed, 62 insertions, 13 deletions
diff --git a/contrib/llvm/lib/Support/APFloat.cpp b/contrib/llvm/lib/Support/APFloat.cpp
index 19b8221..f9370b8 100644
--- a/contrib/llvm/lib/Support/APFloat.cpp
+++ b/contrib/llvm/lib/Support/APFloat.cpp
@@ -14,6 +14,7 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringExtras.h"
@@ -501,7 +502,9 @@ powerOf5(integerPart *dst, unsigned int power)
/* Now result is in p1 with partsCount parts and p2 is scratch
space. */
- tmp = p1, p1 = p2, p2 = tmp;
+ tmp = p1;
+ p1 = p2;
+ p2 = tmp;
}
pow5 += pc;
@@ -3940,22 +3943,68 @@ APFloat::makeZero(bool Negative) {
category = fcZero;
sign = Negative;
exponent = semantics->minExponent-1;
- APInt::tcSet(significandParts(), 0, partCount());
+ APInt::tcSet(significandParts(), 0, partCount());
+}
+
+void APFloat::makeQuiet() {
+ assert(isNaN());
+ APInt::tcSetBit(significandParts(), semantics->precision - 2);
}
-APFloat llvm::scalbn(APFloat X, int Exp) {
- if (X.isInfinity() || X.isZero() || X.isNaN())
- return X;
+int llvm::ilogb(const APFloat &Arg) {
+ if (Arg.isNaN())
+ return APFloat::IEK_NaN;
+ if (Arg.isZero())
+ return APFloat::IEK_Zero;
+ if (Arg.isInfinity())
+ return APFloat::IEK_Inf;
+ if (!Arg.isDenormal())
+ return Arg.exponent;
+
+ APFloat Normalized(Arg);
+ int SignificandBits = Arg.getSemantics().precision - 1;
+ Normalized.exponent += SignificandBits;
+ Normalized.normalize(APFloat::rmNearestTiesToEven, lfExactlyZero);
+ return Normalized.exponent - SignificandBits;
+}
+
+APFloat llvm::scalbn(APFloat X, int Exp, APFloat::roundingMode RoundingMode) {
auto MaxExp = X.getSemantics().maxExponent;
auto MinExp = X.getSemantics().minExponent;
- if (Exp > (MaxExp - X.exponent))
- // Overflow saturates to infinity.
- return APFloat::getInf(X.getSemantics(), X.isNegative());
- if (Exp < (MinExp - X.exponent))
- // Underflow saturates to zero.
- return APFloat::getZero(X.getSemantics(), X.isNegative());
-
- X.exponent += Exp;
+
+ // If Exp is wildly out-of-scale, simply adding it to X.exponent will
+ // overflow; clamp it to a safe range before adding, but ensure that the range
+ // is large enough that the clamp does not change the result. The range we
+ // need to support is the difference between the largest possible exponent and
+ // the normalized exponent of half the smallest denormal.
+
+ int SignificandBits = X.getSemantics().precision - 1;
+ int MaxIncrement = MaxExp - (MinExp - SignificandBits) + 1;
+
+ // Clamp to one past the range ends to let normalize handle overlflow.
+ X.exponent += std::min(std::max(Exp, -MaxIncrement - 1), MaxIncrement);
+ X.normalize(RoundingMode, lfExactlyZero);
+ if (X.isNaN())
+ X.makeQuiet();
return X;
}
+
+APFloat llvm::frexp(const APFloat &Val, int &Exp, APFloat::roundingMode RM) {
+ Exp = ilogb(Val);
+
+ // Quiet signalling nans.
+ if (Exp == APFloat::IEK_NaN) {
+ APFloat Quiet(Val);
+ Quiet.makeQuiet();
+ return Quiet;
+ }
+
+ if (Exp == APFloat::IEK_Inf)
+ return Val;
+
+ // 1 is added because frexp is defined to return a normalized fraction in
+ // +/-[0.5, 1.0), rather than the usual +/-[1.0, 2.0).
+ Exp = Exp == APFloat::IEK_Zero ? 0 : Exp + 1;
+ return scalbn(Val, -Exp, RM);
+}
OpenPOWER on IntegriCloud