mirror of
https://github.com/RPCS3/llvm.git
synced 2026-07-19 15:13:49 -04:00
APFloat: Fix scalbn handling of denormals
This was incorrect for denormals, and also failed on longer exponent ranges. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@263369 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
+13
-11
@@ -3945,19 +3945,21 @@ APFloat::makeZero(bool Negative) {
|
||||
APInt::tcSet(significandParts(), 0, partCount());
|
||||
}
|
||||
|
||||
APFloat llvm::scalbn(APFloat X, int Exp) {
|
||||
if (X.isInfinity() || X.isZero() || X.isNaN())
|
||||
return X;
|
||||
|
||||
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);
|
||||
return X;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user