[libc-commits] [libc] [libc] Add `next_toward_inf` fo `FPBits` (PR #80654)

Guillaume Chatelet via libc-commits libc-commits at lists.llvm.org
Mon Feb 5 01:47:44 PST 2024


https://github.com/gchatelet created https://github.com/llvm/llvm-project/pull/80654

It is needed to provide correct rounding when building FPRep from greater precision representations.


>From 734466d9e83cb1ef92ee5da6e45646cd1b6cd8d9 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Mon, 5 Feb 2024 09:47:12 +0000
Subject: [PATCH] [libc] Add `next_toward_inf` fo `FPBits`

It is needed to provide correct rounding when building FPRep from greater precision representations.
---
 libc/src/__support/FPUtil/FPBits.h            | 34 +++++++++++++++++++
 .../test/src/__support/FPUtil/fpbits_test.cpp | 22 ++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 7bfdfc1691a2d..271fc7c2c968d 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -266,6 +266,16 @@ template <FPType fp_type> struct FPStorage : public FPLayout<fp_type> {
     LIBC_INLINE constexpr operator Exponent() const {
       return Exponent(UP::value - EXP_BIAS);
     }
+
+    LIBC_INLINE constexpr BiasedExponent &operator++() {
+      ++UP::value;
+      return *this;
+    }
+
+    LIBC_INLINE constexpr BiasedExponent &operator--() {
+      --UP::value;
+      return *this;
+    }
   };
 
   // An opaque type to store a floating point significand.
@@ -435,6 +445,13 @@ struct FPRepSem : public FPStorage<fp_type> {
   LIBC_INLINE constexpr bool is_normal() const {
     return is_finite() && !is_subnormal();
   }
+
+  // Modifiers
+  LIBC_INLINE constexpr void next_toward_inf() {
+    if (is_finite())
+      ++UP::bits;
+  }
+
   // Returns the mantissa with the implicit bit set iff the current
   // value is a valid normal number.
   LIBC_INLINE constexpr StorageType get_explicit_mantissa() const {
@@ -551,6 +568,22 @@ struct FPRepSem<FPType::X86_Binary80, RetT>
       return false;
     return get_implicit_bit();
   }
+  
+  // Modifiers
+  LIBC_INLINE constexpr void next_toward_inf() {
+    if (is_finite()) {
+      if (exp_sig_bits() == max_normal().uintval()) {
+        bits = inf(sign()).uintval();
+      } else if (exp_sig_bits() == max_subnormal().uintval()) {
+        bits = min_normal(sign()).uintval();
+      } else if (sig_bits() == SIG_MASK) {
+        bits = encode(sign(), ++biased_exponent(), Significand::ZERO());
+      } else {
+        ++bits;
+      }
+    }
+  }
+
   LIBC_INLINE constexpr StorageType get_explicit_mantissa() const {
     return sig_bits();
   }
@@ -633,6 +666,7 @@ struct FPRepImpl : public FPRepSem<fp_type, RetT> {
   using UP::max_subnormal;
   using UP::min_normal;
   using UP::min_subnormal;
+  using UP::next_toward_inf;
   using UP::one;
   using UP::quiet_nan;
   using UP::signaling_nan;
diff --git a/libc/test/src/__support/FPUtil/fpbits_test.cpp b/libc/test/src/__support/FPUtil/fpbits_test.cpp
index 65823511e82f5..c0dedc08780cf 100644
--- a/libc/test/src/__support/FPUtil/fpbits_test.cpp
+++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp
@@ -306,6 +306,28 @@ TYPED_TEST(LlvmLibcFPBitsTest, Properties, FPTypes) {
   }
 }
 
+#define ASSERT_SAME_REP(A, B) ASSERT_EQ(A.uintval(), B.uintval());
+
+TYPED_TEST(LlvmLibcFPBitsTest, NextTowardInf, FPTypes) {
+  struct {
+    FP before, after;
+  } TEST_CASES[] = {
+      {FP::ZERO, FP::MIN_SUBNORMAL},          //
+      {FP::MAX_SUBNORMAL, FP::MIN_NORMAL},    //
+      {FP::MAX_NORMAL, FP::INF},              //
+      {FP::INF, FP::INF},                     //
+      {FP::QUIET_NAN, FP::QUIET_NAN},         //
+      {FP::SIGNALING_NAN, FP::SIGNALING_NAN}, //
+  };
+  for (Sign sign : all_signs) {
+    for (auto tc : TEST_CASES) {
+      T val = make<T>(sign, tc.before);
+      val.next_toward_inf();
+      ASSERT_SAME_REP(val, make<T>(sign, tc.after));
+    }
+  }
+}
+
 TEST(LlvmLibcFPBitsTest, FloatType) {
   using FloatBits = FPBits<float>;
 



More information about the libc-commits mailing list