diff --git a/flang/include/flang/Evaluate/real.h b/flang/include/flang/Evaluate/real.h --- a/flang/include/flang/Evaluate/real.h +++ b/flang/include/flang/Evaluate/real.h @@ -177,17 +177,21 @@ template ValueWithRealFlags SCALE(const INT &by, Rounding rounding = TargetCharacteristics::defaultRounding) const { - auto expo{exponentBias + by.ToInt64()}; + // Normalize a fraction with just its LSB set and then multiply. + // (Set the LSB, not the MSB, in case the scale factor needs to + // be subnormal.) + auto adjust{exponentBias + binaryPrecision - 1}; + auto expo{adjust + by.ToInt64()}; if (IsZero()) { expo = exponentBias; // ignore by, don't overflow } else if (by > INT{maxExponent}) { - expo = maxExponent; - } else if (by < INT{-exponentBias}) { + expo = maxExponent + binaryPrecision - 1; + } else if (by < INT{-adjust}) { expo = -1; } Real twoPow; RealFlags flags{ - twoPow.Normalize(false, static_cast(expo), Fraction::MASKL(1))}; + twoPow.Normalize(false, static_cast(expo), Fraction::MASKR(1))}; ValueWithRealFlags result{Multiply(twoPow, rounding)}; result.flags |= flags; return result; diff --git a/flang/lib/Evaluate/real.cpp b/flang/lib/Evaluate/real.cpp --- a/flang/lib/Evaluate/real.cpp +++ b/flang/lib/Evaluate/real.cpp @@ -765,9 +765,7 @@ } else if (IsZero()) { return *this; } else { - Real result; - result.Normalize(IsNegative(), expo + exponentBias - 1, GetFraction()); - return result; + return SCALE(Integer<32>(expo - UnbiasedExponent() - 1)).value; } } diff --git a/flang/test/Evaluate/folding07.f90 b/flang/test/Evaluate/folding07.f90 --- a/flang/test/Evaluate/folding07.f90 +++ b/flang/test/Evaluate/folding07.f90 @@ -280,5 +280,6 @@ logical, parameter :: test_set_exponent_0 = set_exponent(1., 0) == 0.5 logical, parameter :: test_set_exponent_1 = set_exponent(1., 1) == 1. logical, parameter :: test_set_exponent_2 = set_exponent(1., 2) == 2. + logical, parameter :: test_set_exponent_min = set_exponent(1., -149) == 1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125e-45_4 end module