[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