[flang] Fix folding of EXPONENT() intrinsic function
authorPeter Klausler <pklausler@nvidia.com>
Thu, 2 Dec 2021 20:34:37 +0000 (12:34 -0800)
committerPeter Klausler <pklausler@nvidia.com>
Sat, 4 Dec 2021 19:23:09 +0000 (11:23 -0800)
The definition of the EXPONENT() intrinsic function differs by one
from the real arithmetic folding templates concept of an unbiased
exponent, and also needs special handling for zero.  Fix, and add
more tests.

Differential Revision: https://reviews.llvm.org/D115084

flang/include/flang/Evaluate/real.h
flang/test/Evaluate/folding07.f90

index 80e6777..8f49740 100644 (file)
@@ -125,8 +125,10 @@ public:
   template <typename INT> constexpr INT EXPONENT() const {
     if (Exponent() == maxExponent) {
       return INT::HUGE();
+    } else if (IsZero()) {
+      return {0};
     } else {
-      return {UnbiasedExponent()};
+      return {UnbiasedExponent() + 1};
     }
   }
 
@@ -308,6 +310,8 @@ public:
 
   // Extracts unbiased exponent value.
   // Corrects the exponent value of a subnormal number.
+  // Note that the result is one less than the EXPONENT intrinsic;
+  // UnbiasedExponent(1.0) is 0, not 1.
   constexpr int UnbiasedExponent() const {
     int exponent{Exponent() - exponentBias};
     if (IsSubnormal()) {
index e79dfaf..b8eca95 100644 (file)
@@ -197,6 +197,14 @@ module m
   logical, parameter :: test_tiny10 = tiny10 == ztiny10
   logical, parameter :: test_tiny16 = tiny16 == ztiny16
 
+  logical, parameter :: test_exponent_0 = exponent(0.0) == 0
+  logical, parameter :: test_exponent_r8 = exponent(0.125) == -2
+  logical, parameter :: test_exponent_r4 = exponent(0.25) == -1
+  logical, parameter :: test_exponent_r2 = exponent(0.5) == 0
+  logical, parameter :: test_exponent_1 = exponent(1.0) == 1
+  logical, parameter :: test_exponent_4 = exponent(4.1) == 3
+  logical, parameter :: test_exponent_12 = exponent(12.9) == 4
+
   integer, parameter :: &
     max2 = maxexponent(0._2), &
     max3 = maxexponent(0._3), &