[llvm] [APFloat] add power (PR #122889)

Iman Hosseini via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 15 10:36:35 PST 2025


https://github.com/ImanHosseini updated https://github.com/llvm/llvm-project/pull/122889

>From 10da74e43550f58760ed899282cb4d1002ff6070 Mon Sep 17 00:00:00 2001
From: ImanHosseini <imanhosseini.17 at gmail.com>
Date: Tue, 14 Jan 2025 11:35:31 +0000
Subject: [PATCH 1/6] add apfloat power

---
 llvm/include/llvm/ADT/APFloat.h    | 21 +++++++++++++++++++++
 llvm/unittests/ADT/APFloatTest.cpp | 15 +++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index 9792749230cbf9..803949cf9abcbf 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -1536,6 +1536,27 @@ inline APFloat abs(APFloat X) {
   return X;
 }
 
+/// Returns X^N for N >= 0.
+/// Returns X^N for N >= 0.
+inline APFloat pow(const APFloat &X, const int &N) {
+  assert(N >= 0 && "negative exponents not supported.");
+  APFloat Acc = APFloat::getOne(X.getSemantics());
+  if (N == 0) {
+    return APFloat::getOne(X.getSemantics());
+  }
+  APFloat Base = X;
+  int64_t RemainingExponent = N;
+  while (RemainingExponent > 0) {
+    while (RemainingExponent % 2 == 0) {
+      Base = Base * Base;
+      RemainingExponent /= 2;
+    }
+    --RemainingExponent;
+    Acc = Acc * Base;
+  }
+  return Acc;
+};
+
 /// Returns the negated value of the argument.
 inline APFloat neg(APFloat X) {
   X.changeSign();
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index f291c814886d35..0e4fe151af10af 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -3793,6 +3793,21 @@ TEST(APFloatTest, abs) {
   EXPECT_TRUE(PSmallestNormalized.bitwiseIsEqual(abs(MSmallestNormalized)));
 }
 
+TEST(APFloatTest, pow) {
+  APFloat One = APFloat(APFloat::IEEEsingle(), "1.0");
+  APFloat Two = APFloat(APFloat::IEEEsingle(), "2.0");
+  APFloat Four = APFloat(APFloat::IEEEsingle(), "4.0");
+  APFloat Eight = APFloat(APFloat::IEEEsingle(), "8.0");
+  APFloat NegTwo = APFloat(APFloat::IEEEsingle(), "-2.0");
+  APFloat NegEight = APFloat(APFloat::IEEEsingle(), "-8.0");
+
+  EXPECT_TRUE(One.bitwiseIsEqual(pow(One, 0)));
+  EXPECT_TRUE(One.bitwiseIsEqual(pow(One, 3)));
+  EXPECT_TRUE(Four.bitwiseIsEqual(pow(Two, 2)));
+  EXPECT_TRUE(Eight.bitwiseIsEqual(pow(Two, 3)));
+  EXPECT_TRUE(NegEight.bitwiseIsEqual(pow(NegTwo, 3)));
+}
+
 TEST(APFloatTest, neg) {
   APFloat One = APFloat(APFloat::IEEEsingle(), "1.0");
   APFloat NegOne = APFloat(APFloat::IEEEsingle(), "-1.0");

>From eb093a1b06402fbdfe89769aa7ea1caee7c9a4e9 Mon Sep 17 00:00:00 2001
From: ImanHosseini <imanhosseini.17 at gmail.com>
Date: Tue, 14 Jan 2025 12:58:19 +0000
Subject: [PATCH 2/6] rmv extra ;

---
 llvm/include/llvm/ADT/APFloat.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index 803949cf9abcbf..eeace70dfad29f 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -1555,7 +1555,7 @@ inline APFloat pow(const APFloat &X, const int &N) {
     Acc = Acc * Base;
   }
   return Acc;
-};
+}
 
 /// Returns the negated value of the argument.
 inline APFloat neg(APFloat X) {

>From 38468c983bbd6047dd842dc3d5d5550a198e736d Mon Sep 17 00:00:00 2001
From: ImanHosseini <imanhosseini.17 at gmail.com>
Date: Tue, 14 Jan 2025 15:34:38 +0000
Subject: [PATCH 3/6] N -> int64_t to be similar to APInt pow

---
 llvm/include/llvm/ADT/APFloat.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index eeace70dfad29f..6b669eca6f82b5 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -1537,8 +1537,7 @@ inline APFloat abs(APFloat X) {
 }
 
 /// Returns X^N for N >= 0.
-/// Returns X^N for N >= 0.
-inline APFloat pow(const APFloat &X, const int &N) {
+inline APFloat pow(const APFloat &X, int64_t N) {
   assert(N >= 0 && "negative exponents not supported.");
   APFloat Acc = APFloat::getOne(X.getSemantics());
   if (N == 0) {

>From eb07e2aa0d3f95d2c7fce624df597a62d0c61721 Mon Sep 17 00:00:00 2001
From: ImanHosseini <imanhosseini.17 at gmail.com>
Date: Tue, 14 Jan 2025 22:13:26 +0000
Subject: [PATCH 4/6] rename to `powi`.

---
 llvm/include/llvm/ADT/APFloat.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index 6b669eca6f82b5..ad1e37b1c0c22d 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -1537,11 +1537,11 @@ inline APFloat abs(APFloat X) {
 }
 
 /// Returns X^N for N >= 0.
-inline APFloat pow(const APFloat &X, int64_t N) {
+inline APFloat powi(const APFloat &X, int64_t N) {
   assert(N >= 0 && "negative exponents not supported.");
   APFloat Acc = APFloat::getOne(X.getSemantics());
   if (N == 0) {
-    return APFloat::getOne(X.getSemantics());
+    return Acc;
   }
   APFloat Base = X;
   int64_t RemainingExponent = N;

>From 09ad4eb4a40a69b8b1d3dec6f1b0bc92bdcf95d8 Mon Sep 17 00:00:00 2001
From: ImanHosseini <imanhosseini.17 at gmail.com>
Date: Wed, 15 Jan 2025 18:32:25 +0000
Subject: [PATCH 5/6] add more tests

---
 llvm/unittests/ADT/APFloatTest.cpp | 39 ++++++++++++++++++++++++------
 1 file changed, 31 insertions(+), 8 deletions(-)

diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index 0e4fe151af10af..b85ba0eb88df6c 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -3793,19 +3793,42 @@ TEST(APFloatTest, abs) {
   EXPECT_TRUE(PSmallestNormalized.bitwiseIsEqual(abs(MSmallestNormalized)));
 }
 
-TEST(APFloatTest, pow) {
-  APFloat One = APFloat(APFloat::IEEEsingle(), "1.0");
+TEST(APFloatTest, powi) {
+  APFloat One = APFloat::getOne(APFloat::IEEEsingle(), false);
   APFloat Two = APFloat(APFloat::IEEEsingle(), "2.0");
   APFloat Four = APFloat(APFloat::IEEEsingle(), "4.0");
   APFloat Eight = APFloat(APFloat::IEEEsingle(), "8.0");
   APFloat NegTwo = APFloat(APFloat::IEEEsingle(), "-2.0");
   APFloat NegEight = APFloat(APFloat::IEEEsingle(), "-8.0");
-
-  EXPECT_TRUE(One.bitwiseIsEqual(pow(One, 0)));
-  EXPECT_TRUE(One.bitwiseIsEqual(pow(One, 3)));
-  EXPECT_TRUE(Four.bitwiseIsEqual(pow(Two, 2)));
-  EXPECT_TRUE(Eight.bitwiseIsEqual(pow(Two, 3)));
-  EXPECT_TRUE(NegEight.bitwiseIsEqual(pow(NegTwo, 3)));
+  APFloat PosInf = APFloat::getInf(APFloat::IEEEsingle(), false);
+  APFloat NegInf = APFloat::getInf(APFloat::IEEEsingle(), true);
+  APFloat PosZero = APFloat::getZero(APFloat::IEEEsingle(), false);
+  APFloat NegZero = APFloat::getZero(APFloat::IEEEsingle(), true);
+  APFloat PosQNaN = APFloat::getNaN(APFloat::IEEEsingle(), false);
+  APFloat NegQNaN = APFloat::getNaN(APFloat::IEEEsingle(), true);
+  APFloat PosSNaN = APFloat::getSNaN(APFloat::IEEEsingle(), false);
+  APFloat NegSNaN = APFloat::getSNaN(APFloat::IEEEsingle(), true);
+  
+  EXPECT_TRUE(One.bitwiseIsEqual(powi(One, 0)));
+  EXPECT_TRUE(One.bitwiseIsEqual(powi(One, 3)));
+  EXPECT_TRUE(Four.bitwiseIsEqual(powi(Two, 2)));
+  EXPECT_TRUE(Eight.bitwiseIsEqual(powi(Two, 3)));
+  
+  // See page 63 of IEEE 754-2019.
+  EXPECT_TRUE(One.bitwiseIsEqual(powi(PosInf, 0)));
+  EXPECT_TRUE(NegEight.bitwiseIsEqual(powi(NegTwo, 3)));
+  EXPECT_TRUE(PosZero.bitwiseIsEqual(powi(PosZero, 3)));
+  EXPECT_TRUE(NegZero.bitwiseIsEqual(powi(NegZero, 5)));
+  EXPECT_TRUE(PosZero.bitwiseIsEqual(powi(NegZero, 6)));
+  EXPECT_TRUE(NegInf.bitwiseIsEqual(powi(NegInf, 3)));
+  EXPECT_TRUE(PosInf.bitwiseIsEqual(powi(NegInf, 4)));
+  EXPECT_TRUE(PosInf.bitwiseIsEqual(powi(PosInf, 3)));
+  
+  EXPECT_TRUE(PosQNaN.bitwiseIsEqual(powi(PosQNaN, 1)));
+  EXPECT_TRUE(NegQNaN.bitwiseIsEqual(powi(NegQNaN, 1)));
+  // Check signaling NaN is quieted for n == 1.
+  EXPECT_TRUE(PosQNaN.bitwiseIsEqual(powi(PosSNaN, 1)));
+  EXPECT_TRUE(NegSNaN.bitwiseIsEqual(powi(NegSNaN, 1)));
 }
 
 TEST(APFloatTest, neg) {

>From 8f6da4e6352e4416d53c334f228225cf22ef7b6d Mon Sep 17 00:00:00 2001
From: ImanHosseini <imanhosseini.17 at gmail.com>
Date: Wed, 15 Jan 2025 18:35:59 +0000
Subject: [PATCH 6/6] sink.

---
 llvm/include/llvm/ADT/APFloat.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index ad1e37b1c0c22d..a07f637b384a8b 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -1538,11 +1538,11 @@ inline APFloat abs(APFloat X) {
 
 /// Returns X^N for N >= 0.
 inline APFloat powi(const APFloat &X, int64_t N) {
-  assert(N >= 0 && "negative exponents not supported.");
   APFloat Acc = APFloat::getOne(X.getSemantics());
   if (N == 0) {
     return Acc;
   }
+  assert(N >= 0 && "negative exponents not supported.");
   APFloat Base = X;
   int64_t RemainingExponent = N;
   while (RemainingExponent > 0) {



More information about the llvm-commits mailing list