[llvm-branch-commits] [libc] [libc] Add Operator Overloads for Float80 (PR #214493)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Aug 22 04:55:26 PDT 2026
https://github.com/Sukumarsawant updated https://github.com/llvm/llvm-project/pull/214493
>From 997bdbc6021942be40a689c249fb1d981488a4ff Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 23 Jul 2026 00:10:21 +0530
Subject: [PATCH 01/15] initial temp skeleton
---
libc/src/__support/FPUtil/float80.h | 90 ++++++++++++++++++++++++-----
1 file changed, 74 insertions(+), 16 deletions(-)
diff --git a/libc/src/__support/FPUtil/float80.h b/libc/src/__support/FPUtil/float80.h
index 7cbb1300ca12a..edd63aab47ba7 100644
--- a/libc/src/__support/FPUtil/float80.h
+++ b/libc/src/__support/FPUtil/float80.h
@@ -69,34 +69,92 @@ struct Float80 {
template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
LIBC_INLINE constexpr explicit operator T() const {
- constexpr T MIN_T = cpp::numeric_limits<T>::min();
- constexpr T MAX_T = cpp::numeric_limits<T>::max();
FPBits<Float80> x_bits(*this);
// Raise FE_INVALID for inf and NaN
if (x_bits.is_inf_or_nan()) {
raise_except_if_required(FE_INVALID);
- return x_bits.is_neg() ? MIN_T : MAX_T;
}
- int exponent = x_bits.get_explicit_exponent();
- constexpr int EXPONENT_LIMIT = cpp::numeric_limits<T>::digits;
- if (exponent > EXPONENT_LIMIT) {
- raise_except_if_required(FE_INVALID);
- return x_bits.is_neg() ? MIN_T : MAX_T;
- } else if (exponent == EXPONENT_LIMIT) {
- if (x_bits.is_pos() || x_bits.get_mantissa() != 0) {
- raise_except_if_required(FE_INVALID);
- return x_bits.is_neg() ? MIN_T : MAX_T;
- }
- }
-
- int x_bits_exp = exponent - FPBits<Float80>::FRACTION_LEN;
+ int x_bits_exp =
+ x_bits.get_explicit_exponent() - FPBits<Float80>::FRACTION_LEN;
// sign * 2^(exp-bias) * mantissa
DyadicFloat<FPBits<Float80>::STORAGE_LEN> xd(
x_bits.sign(), x_bits_exp, x_bits.get_explicit_mantissa());
return static_cast<T>(xd.as_mantissa_type());
}
+
+ // unary
+ LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR Float80 operator-() const {
+ fputil::FPBits<Float80> result(*this);
+ result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
+ return result.get_val();
+ }
+ // operator overloads
+ LIBC_INLINE constexpr Float80 operator+(const Float80 &other) const {
+ return fputil::generic::add<Float80>(*this, other);
+ }
+
+ LIBC_INLINE constexpr Float80 operator-(const Float80 &other) const {
+ return fputil::generic::sub<Float80>(*this, other);
+ }
+
+ LIBC_INLINE constexpr Float80 operator*(const Float80 &other) const {
+ return fputil::generic::mul<Float80>(*this, other);
+ }
+
+ LIBC_INLINE constexpr Float80 operator/(const Float80 &other) const {
+ return fputil::generic::div<Float80>(*this, other);
+ }
+
+ LIBC_INLINE constexpr Float80 &operator*=(const Float80 &other) {
+ *this = *this * other;
+ return *this;
+ }
+
+ LIBC_INLINE constexpr Float80 &operator+=(const Float80 &other) {
+ *this = *this + other;
+ return *this;
+ }
+
+ LIBC_INLINE constexpr Float80 &operator-=(const Float80 &other) {
+ *this = *this - other;
+ return *this;
+ }
+
+ LIBC_INLINE constexpr Float80 &operator/=(const Float80 &other) {
+ *this = *this / other;
+ return *this;
+ }
+
+ LIBC_INLINE constexpr bool operator==(const Float80 &other) const {
+ return fputil::equals(*this, other);
+ }
+
+ LIBC_INLINE constexpr bool operator!=(const Float80 &other) const {
+ return !fputil::equals(*this, other);
+ }
+
+ LIBC_INLINE constexpr bool operator<(const Float80 &other) const {
+ return fputil::less_than(*this, other);
+ }
+
+ LIBC_INLINE constexpr bool operator<=(const Float80 &other) const {
+ return fputil::less_than_or_equals(*this, other);
+ }
+
+ LIBC_INLINE constexpr bool operator>(const Float80 &other) const {
+ return fputil::greater_than(*this, other);
+ }
+
+ LIBC_INLINE constexpr bool operator>=(const Float80 &other) const {
+ return fputil::greater_than_or_equals(*this, other);
+ }
};
+static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible<
+ LIBC_NAMESPACE::fputil::Float80>::value);
+static_assert(LIBC_NAMESPACE::cpp::is_trivially_copyable<
+ LIBC_NAMESPACE::fputil::Float80>::value);
+
} // namespace fputil
} // namespace LIBC_NAMESPACE_DECL
>From 19c92b5fb0024d12bdd979a9bedd5c10f264ad82 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 30 Jul 2026 20:30:14 +0530
Subject: [PATCH 02/15] Removed temporarliy for 128bit container only
---
libc/src/__support/FPUtil/FPBits.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 6127dede03f4a..e251b7f15e9a3 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -127,11 +127,11 @@ template <> struct FPLayout<FPType::IEEE754_Binary128> {
};
template <> struct FPLayout<FPType::X86_Binary80> {
-#if __SIZEOF_LONG_DOUBLE__ == 12
- using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
-#else
+// #if __SIZEOF_LONG_DOUBLE__ == 12
+// using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
+// #else
using StorageType = UInt128;
-#endif
+// #endif
LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
LIBC_INLINE_VAR static constexpr int EXP_LEN = 15;
LIBC_INLINE_VAR static constexpr int SIG_LEN = 64;
>From 80b6720d9c699f0caf57244d2adc7b79ad18e2f7 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 30 Jul 2026 20:36:32 +0530
Subject: [PATCH 03/15] test
---
libc/src/__support/FPUtil/FPBits.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index e251b7f15e9a3..59d3ca28c7dc4 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -127,11 +127,11 @@ template <> struct FPLayout<FPType::IEEE754_Binary128> {
};
template <> struct FPLayout<FPType::X86_Binary80> {
-// #if __SIZEOF_LONG_DOUBLE__ == 12
-// using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
-// #else
+ // #if __SIZEOF_LONG_DOUBLE__ == 12
+ // using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
+ // #else
using StorageType = UInt128;
-// #endif
+ // #endif
LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
LIBC_INLINE_VAR static constexpr int EXP_LEN = 15;
LIBC_INLINE_VAR static constexpr int SIG_LEN = 64;
>From 0773125f62cee3b72c9d9afe9dc00f364be9ca58 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 13:10:13 +0530
Subject: [PATCH 04/15] nit
---
libc/src/__support/FPUtil/FPBits.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 59d3ca28c7dc4..1b5f76b3f1d17 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -127,11 +127,11 @@ template <> struct FPLayout<FPType::IEEE754_Binary128> {
};
template <> struct FPLayout<FPType::X86_Binary80> {
- // #if __SIZEOF_LONG_DOUBLE__ == 12
- // using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
- // #else
+ #if __SIZEOF_LONG_DOUBLE__ == 12
+ using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
+ #else
using StorageType = UInt128;
- // #endif
+ #endif
LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
LIBC_INLINE_VAR static constexpr int EXP_LEN = 15;
LIBC_INLINE_VAR static constexpr int SIG_LEN = 64;
>From 9c439126e71c3f1e2aeae8ec9903e9f1b9db12c7 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 13:15:10 +0530
Subject: [PATCH 05/15] formatting
---
libc/src/__support/FPUtil/FPBits.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 1b5f76b3f1d17..6127dede03f4a 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -127,11 +127,11 @@ template <> struct FPLayout<FPType::IEEE754_Binary128> {
};
template <> struct FPLayout<FPType::X86_Binary80> {
- #if __SIZEOF_LONG_DOUBLE__ == 12
- using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
- #else
+#if __SIZEOF_LONG_DOUBLE__ == 12
+ using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>;
+#else
using StorageType = UInt128;
- #endif
+#endif
LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
LIBC_INLINE_VAR static constexpr int EXP_LEN = 15;
LIBC_INLINE_VAR static constexpr int SIG_LEN = 64;
>From 3414cedf92c3f1f18142000637241abe1ef625be Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 15:50:02 +0530
Subject: [PATCH 06/15] feat: add tests
---
libc/src/__support/FPUtil/float80.h | 85 ++++++-----------------------
1 file changed, 16 insertions(+), 69 deletions(-)
diff --git a/libc/src/__support/FPUtil/float80.h b/libc/src/__support/FPUtil/float80.h
index edd63aab47ba7..d6823f7bedb76 100644
--- a/libc/src/__support/FPUtil/float80.h
+++ b/libc/src/__support/FPUtil/float80.h
@@ -69,85 +69,32 @@ struct Float80 {
template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
LIBC_INLINE constexpr explicit operator T() const {
+ constexpr T MIN_T = cpp::numeric_limits<T>::min();
+ constexpr T MAX_T = cpp::numeric_limits<T>::max();
FPBits<Float80> x_bits(*this);
// Raise FE_INVALID for inf and NaN
if (x_bits.is_inf_or_nan()) {
raise_except_if_required(FE_INVALID);
+ return x_bits.is_neg() ? MIN_T : MAX_T;
}
- int x_bits_exp =
- x_bits.get_explicit_exponent() - FPBits<Float80>::FRACTION_LEN;
+ int exponent = x_bits.get_explicit_exponent();
+ constexpr int EXPONENT_LIMIT = cpp::numeric_limits<T>::digits;
+ if (exponent > EXPONENT_LIMIT) {
+ raise_except_if_required(FE_INVALID);
+ return x_bits.is_neg() ? MIN_T : MAX_T;
+ } else if (exponent == EXPONENT_LIMIT) {
+ if (x_bits.is_pos() || x_bits.get_mantissa() != 0) {
+ raise_except_if_required(FE_INVALID);
+ return x_bits.is_neg() ? MIN_T : MAX_T;
+ }
+ }
+
+ int x_bits_exp = exponent - FPBits<Float80>::FRACTION_LEN;
// sign * 2^(exp-bias) * mantissa
DyadicFloat<FPBits<Float80>::STORAGE_LEN> xd(
x_bits.sign(), x_bits_exp, x_bits.get_explicit_mantissa());
return static_cast<T>(xd.as_mantissa_type());
}
-
- // unary
- LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR Float80 operator-() const {
- fputil::FPBits<Float80> result(*this);
- result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
- return result.get_val();
- }
- // operator overloads
- LIBC_INLINE constexpr Float80 operator+(const Float80 &other) const {
- return fputil::generic::add<Float80>(*this, other);
- }
-
- LIBC_INLINE constexpr Float80 operator-(const Float80 &other) const {
- return fputil::generic::sub<Float80>(*this, other);
- }
-
- LIBC_INLINE constexpr Float80 operator*(const Float80 &other) const {
- return fputil::generic::mul<Float80>(*this, other);
- }
-
- LIBC_INLINE constexpr Float80 operator/(const Float80 &other) const {
- return fputil::generic::div<Float80>(*this, other);
- }
-
- LIBC_INLINE constexpr Float80 &operator*=(const Float80 &other) {
- *this = *this * other;
- return *this;
- }
-
- LIBC_INLINE constexpr Float80 &operator+=(const Float80 &other) {
- *this = *this + other;
- return *this;
- }
-
- LIBC_INLINE constexpr Float80 &operator-=(const Float80 &other) {
- *this = *this - other;
- return *this;
- }
-
- LIBC_INLINE constexpr Float80 &operator/=(const Float80 &other) {
- *this = *this / other;
- return *this;
- }
-
- LIBC_INLINE constexpr bool operator==(const Float80 &other) const {
- return fputil::equals(*this, other);
- }
-
- LIBC_INLINE constexpr bool operator!=(const Float80 &other) const {
- return !fputil::equals(*this, other);
- }
-
- LIBC_INLINE constexpr bool operator<(const Float80 &other) const {
- return fputil::less_than(*this, other);
- }
-
- LIBC_INLINE constexpr bool operator<=(const Float80 &other) const {
- return fputil::less_than_or_equals(*this, other);
- }
-
- LIBC_INLINE constexpr bool operator>(const Float80 &other) const {
- return fputil::greater_than(*this, other);
- }
-
- LIBC_INLINE constexpr bool operator>=(const Float80 &other) const {
- return fputil::greater_than_or_equals(*this, other);
- }
};
static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible<
>From 7e7f5961f7517fbfb9d0ffbce951a037ee6023fe Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 16:56:36 +0530
Subject: [PATCH 07/15] add explicit bit handling for dyadic_float as per
FPBits
---
libc/src/__support/FPUtil/dyadic_float.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index e32906e3cf9cf..855c2d1499216 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -264,6 +264,8 @@ template <size_t Bits> struct DyadicFloat {
}
out_mantissa = static_cast<StorageType>(mantissa >> extra_fraction_len);
+ if constexpr (get_fp_type<T>() == FPType::X86_Binary80)
+ out_mantissa |= FPBits::EXPLICIT_BIT_MASK;
}
bool lsb = (out_mantissa & 1) != 0;
>From 3feba51a031c640fa76c403c5fe4c5add49a76eb Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 16:58:38 +0530
Subject: [PATCH 08/15] nit
---
libc/src/__support/FPUtil/dyadic_float.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 855c2d1499216..86a3e409a17d6 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -264,6 +264,7 @@ template <size_t Bits> struct DyadicFloat {
}
out_mantissa = static_cast<StorageType>(mantissa >> extra_fraction_len);
+ // Takes into consideration the explicit bit for number for types like float 80
if constexpr (get_fp_type<T>() == FPType::X86_Binary80)
out_mantissa |= FPBits::EXPLICIT_BIT_MASK;
}
>From 185aa8cf08eb28559d1dfe1e4806faed92e1cdb6 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 17:03:13 +0530
Subject: [PATCH 09/15] nit
---
libc/src/__support/FPUtil/dyadic_float.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 86a3e409a17d6..432409e6a8501 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -264,7 +264,8 @@ template <size_t Bits> struct DyadicFloat {
}
out_mantissa = static_cast<StorageType>(mantissa >> extra_fraction_len);
- // Takes into consideration the explicit bit for number for types like float 80
+ // Takes into consideration the explicit bit for number for types like
+ // float 80
if constexpr (get_fp_type<T>() == FPType::X86_Binary80)
out_mantissa |= FPBits::EXPLICIT_BIT_MASK;
}
>From c15cc4653e69b2ab60119099efd20ceef6626942 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 17:25:32 +0530
Subject: [PATCH 10/15] test: limit EXTRA_FRAC_LEN to be non-negative
test
test
nit
revert
revert
only add >0 condition
format
---
libc/src/__support/FPUtil/dyadic_float.h | 4 ----
1 file changed, 4 deletions(-)
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 432409e6a8501..e32906e3cf9cf 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -264,10 +264,6 @@ template <size_t Bits> struct DyadicFloat {
}
out_mantissa = static_cast<StorageType>(mantissa >> extra_fraction_len);
- // Takes into consideration the explicit bit for number for types like
- // float 80
- if constexpr (get_fp_type<T>() == FPType::X86_Binary80)
- out_mantissa |= FPBits::EXPLICIT_BIT_MASK;
}
bool lsb = (out_mantissa & 1) != 0;
>From eea571b9e394f96caa9a6352481cc8822b4d91b6 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 19:11:47 +0530
Subject: [PATCH 11/15] feat: add negation and a test for it
---
libc/src/__support/FPUtil/float80.h | 7 +++++++
libc/test/src/__support/FPUtil/float80_test.cpp | 2 ++
2 files changed, 9 insertions(+)
diff --git a/libc/src/__support/FPUtil/float80.h b/libc/src/__support/FPUtil/float80.h
index d6823f7bedb76..98d2a579c4f3d 100644
--- a/libc/src/__support/FPUtil/float80.h
+++ b/libc/src/__support/FPUtil/float80.h
@@ -95,6 +95,13 @@ struct Float80 {
x_bits.sign(), x_bits_exp, x_bits.get_explicit_mantissa());
return static_cast<T>(xd.as_mantissa_type());
}
+
+ // unary operators
+ LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR Float80 operator-() const {
+ fputil::FPBits<Float80> result(*this);
+ result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
+ return result.get_val();
+ }
};
static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible<
diff --git a/libc/test/src/__support/FPUtil/float80_test.cpp b/libc/test/src/__support/FPUtil/float80_test.cpp
index 549c414cea811..76a52f1dcfbfc 100644
--- a/libc/test/src/__support/FPUtil/float80_test.cpp
+++ b/libc/test/src/__support/FPUtil/float80_test.cpp
@@ -19,7 +19,9 @@ using FPBits = LIBC_NAMESPACE::fputil::FPBits<Float80>;
TEST(LlvmLibcFloat80Test, IntegerConversion) {
// Float80 to Integer conversion test
ASSERT_EQ(static_cast<int>(Float80(0.0f)), 0);
+ ASSERT_EQ(static_cast<int>(Float80(-0.0f)), 0);
ASSERT_EQ(static_cast<int>(Float80(1.0f)), 1);
+ ASSERT_EQ(static_cast<int>(Float80(-1.0f)), -1);
ASSERT_EQ(static_cast<long long>(Float80(1000000000.0)),
static_cast<long long>(1000000000));
ASSERT_EQ(static_cast<unsigned>(Float80(7.0f)), 7U);
>From 01aa9e0c91daed08cfce310f651eb7dbdb83cc73 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 6 Aug 2026 21:03:12 +0530
Subject: [PATCH 12/15] add tests
---
libc/src/__support/FPUtil/float80.h | 21 +++++++++++++++++++
.../src/__support/FPUtil/float80_test.cpp | 15 +++++++++++++
2 files changed, 36 insertions(+)
diff --git a/libc/src/__support/FPUtil/float80.h b/libc/src/__support/FPUtil/float80.h
index 98d2a579c4f3d..726f15a06520a 100644
--- a/libc/src/__support/FPUtil/float80.h
+++ b/libc/src/__support/FPUtil/float80.h
@@ -101,6 +101,27 @@ struct Float80 {
fputil::FPBits<Float80> result(*this);
result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
return result.get_val();
+
+ // operator overloads
+ LIBC_INLINE constexpr Float80 operator+(const Float80 &other) const {
+ return fputil::generic::add<Float80>(*this, other);
+ }
+
+ LIBC_INLINE constexpr Float80 operator-(const Float80 &other) const {
+ return fputil::generic::sub<Float80>(*this, other);
+ }
+
+ LIBC_INLINE constexpr Float80 operator*(const Float80 &other) const {
+ return fputil::generic::mul<Float80>(*this, other);
+ }
+
+ LIBC_INLINE constexpr Float80 operator/(const Float80 &other) const {
+ return fputil::generic::div<Float80>(*this, other);
+ }
+
+ LIBC_INLINE constexpr bool operator==(const Float128 &other) const {
+ return fputil::equals(*this, other);
+ }
}
};
diff --git a/libc/test/src/__support/FPUtil/float80_test.cpp b/libc/test/src/__support/FPUtil/float80_test.cpp
index 76a52f1dcfbfc..7ad02731843a1 100644
--- a/libc/test/src/__support/FPUtil/float80_test.cpp
+++ b/libc/test/src/__support/FPUtil/float80_test.cpp
@@ -16,6 +16,21 @@ using LIBC_NAMESPACE::Sign;
using LIBC_NAMESPACE::fputil::Float80;
using FPBits = LIBC_NAMESPACE::fputil::FPBits<Float80>;
+TEST(LlvmLibcFloat80Test, temp) { Float80 a(1.0f); }
+
+TEST(LlvmLibcFloat80Test, Operators) {
+ Float80 a(1.0f), b(1.0f), c(2.0f), d(3.0f), pa(1.0f), na(-1.0f);
+
+ // Unary operators
+ ASSERT_TRUE(FPBits(-pa) == FPBits(na));
+
+ // Binary operators
+ ASSERT_TRUE(a + b == c);
+ ASSERT_TRUE(a - b == Float128(0.0));
+ ASSERT_TRUE(c * d == Float128(6.0));
+ ASSERT_TRUE(Float80(6.0f) / d) == Float80(2.0f);
+}
+
TEST(LlvmLibcFloat80Test, IntegerConversion) {
// Float80 to Integer conversion test
ASSERT_EQ(static_cast<int>(Float80(0.0f)), 0);
>From 07ec1cb08498f51d6fe2d06072163c8f96b3d3c9 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 13 Aug 2026 20:25:20 +0530
Subject: [PATCH 13/15] suggestions and add more operators
---
libc/src/__support/FPUtil/float80.h | 56 +++++++++++++------
.../src/__support/FPUtil/float80_test.cpp | 39 +++++++++++--
2 files changed, 74 insertions(+), 21 deletions(-)
diff --git a/libc/src/__support/FPUtil/float80.h b/libc/src/__support/FPUtil/float80.h
index 726f15a06520a..cb8dc618c9280 100644
--- a/libc/src/__support/FPUtil/float80.h
+++ b/libc/src/__support/FPUtil/float80.h
@@ -14,6 +14,7 @@
#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/comparison_operations.h"
#include "src/__support/FPUtil/dyadic_float.h"
+#include "src/__support/FPUtil/float128.h"
#include "src/__support/FPUtil/generic/add_sub.h"
#include "src/__support/FPUtil/generic/div.h"
#include "src/__support/FPUtil/generic/mul.h"
@@ -101,27 +102,50 @@ struct Float80 {
fputil::FPBits<Float80> result(*this);
result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
return result.get_val();
+ }
+ LIBC_INLINE constexpr Float80 operator+(const Float80 &other) const {
+ return fputil::generic::add<Float80>(fputil::cast<Float128>(*this),
+ fputil::cast<Float128>(other));
+ }
- // operator overloads
- LIBC_INLINE constexpr Float80 operator+(const Float80 &other) const {
- return fputil::generic::add<Float80>(*this, other);
- }
+ LIBC_INLINE constexpr Float80 operator-(const Float80 &other) const {
+ return fputil::generic::sub<Float80>(fputil::cast<Float128>(*this),
+ fputil::cast<Float128>(other));
+ }
- LIBC_INLINE constexpr Float80 operator-(const Float80 &other) const {
- return fputil::generic::sub<Float80>(*this, other);
- }
+ LIBC_INLINE constexpr Float80 operator*(const Float80 &other) const {
+ return fputil::generic::mul<Float80>(fputil::cast<Float128>(*this),
+ fputil::cast<Float128>(other));
+ }
- LIBC_INLINE constexpr Float80 operator*(const Float80 &other) const {
- return fputil::generic::mul<Float80>(*this, other);
- }
+ LIBC_INLINE constexpr Float80 operator/(const Float80 &other) const {
+ return fputil::generic::div<Float80>(fputil::cast<Float128>(*this),
+ fputil::cast<Float128>(other));
+ }
- LIBC_INLINE constexpr Float80 operator/(const Float80 &other) const {
- return fputil::generic::div<Float80>(*this, other);
- }
+ // Comparison operators
+ LIBC_INLINE constexpr bool operator==(const Float80 &other) const {
+ return fputil::equals(*this, other);
+ }
- LIBC_INLINE constexpr bool operator==(const Float128 &other) const {
- return fputil::equals(*this, other);
- }
+ LIBC_INLINE constexpr bool operator!=(const Float80 &other) const {
+ return !fputil::equals(*this, other);
+ }
+
+ LIBC_INLINE constexpr bool operator<(const Float80 &other) const {
+ return fputil::less_than(*this, other);
+ }
+
+ LIBC_INLINE constexpr bool operator<=(const Float80 &other) const {
+ return fputil::less_than_or_equals(*this, other);
+ }
+
+ LIBC_INLINE constexpr bool operator>(const Float80 &other) const {
+ return fputil::greater_than(*this, other);
+ }
+
+ LIBC_INLINE constexpr bool operator>=(const Float80 &other) const {
+ return fputil::greater_than_or_equals(*this, other);
}
};
diff --git a/libc/test/src/__support/FPUtil/float80_test.cpp b/libc/test/src/__support/FPUtil/float80_test.cpp
index 7ad02731843a1..7344e60f86d08 100644
--- a/libc/test/src/__support/FPUtil/float80_test.cpp
+++ b/libc/test/src/__support/FPUtil/float80_test.cpp
@@ -16,19 +16,48 @@ using LIBC_NAMESPACE::Sign;
using LIBC_NAMESPACE::fputil::Float80;
using FPBits = LIBC_NAMESPACE::fputil::FPBits<Float80>;
+// will be removed
TEST(LlvmLibcFloat80Test, temp) { Float80 a(1.0f); }
TEST(LlvmLibcFloat80Test, Operators) {
Float80 a(1.0f), b(1.0f), c(2.0f), d(3.0f), pa(1.0f), na(-1.0f);
+ // comparison operators
+ ASSERT_TRUE(a == b);
+ ASSERT_TRUE(a == Float80(1.0));
+ ASSERT_TRUE(a != c);
+ ASSERT_TRUE(b != c);
+ ASSERT_TRUE(c > b);
+ ASSERT_TRUE(a >= b);
+ ASSERT_TRUE(b <= c);
+ ASSERT_TRUE(a < c);
+
// Unary operators
- ASSERT_TRUE(FPBits(-pa) == FPBits(na));
+ ASSERT_TRUE(-pa == na);
+ ASSERT_TRUE(-(-pa) == pa);
// Binary operators
- ASSERT_TRUE(a + b == c);
- ASSERT_TRUE(a - b == Float128(0.0));
- ASSERT_TRUE(c * d == Float128(6.0));
- ASSERT_TRUE(Float80(6.0f) / d) == Float80(2.0f);
+ ASSERT_TRUE((a + b) == c);
+ ASSERT_TRUE((a - b) == Float80(0.0f));
+ ASSERT_TRUE((c * d) == Float80(6.0f));
+ ASSERT_TRUE((Float80(6.0f) / d) == Float80(2.0f));
+}
+
+TEST(LlvmLibcFloat80Test, SpecialValues) {
+ Float80 inf = FPBits::inf(Sign::POS).get_val();
+ Float80 neg_inf = FPBits::inf(Sign::NEG).get_val();
+ Float80 nan = FPBits::quiet_nan().get_val();
+
+ // checking operators with special values
+ ASSERT_TRUE(Float80(0.0f) == Float80(-0.0f)); // +0.0 == -0.0 is true
+ ASSERT_TRUE(Float80(0.0f) == Float80(0.0f));
+ ASSERT_TRUE(inf == inf);
+ ASSERT_TRUE(-inf == neg_inf);
+ ASSERT_TRUE((inf + Float80(1.0f)) == inf);
+ ASSERT_TRUE(inf + inf == inf);
+ ASSERT_TRUE(nan != nan);
+ ASSERT_TRUE(!(nan == nan));
+ ASSERT_TRUE(nan != Float80(0.0f));
}
TEST(LlvmLibcFloat80Test, IntegerConversion) {
>From 04630ba08b72e147b2f5392a6e875cec7938344b Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Fri, 21 Aug 2026 01:47:22 +0530
Subject: [PATCH 14/15] nit
---
libc/test/src/__support/FPUtil/float80_test.cpp | 3 ---
1 file changed, 3 deletions(-)
diff --git a/libc/test/src/__support/FPUtil/float80_test.cpp b/libc/test/src/__support/FPUtil/float80_test.cpp
index 7344e60f86d08..c761dd74c6fb8 100644
--- a/libc/test/src/__support/FPUtil/float80_test.cpp
+++ b/libc/test/src/__support/FPUtil/float80_test.cpp
@@ -16,9 +16,6 @@ using LIBC_NAMESPACE::Sign;
using LIBC_NAMESPACE::fputil::Float80;
using FPBits = LIBC_NAMESPACE::fputil::FPBits<Float80>;
-// will be removed
-TEST(LlvmLibcFloat80Test, temp) { Float80 a(1.0f); }
-
TEST(LlvmLibcFloat80Test, Operators) {
Float80 a(1.0f), b(1.0f), c(2.0f), d(3.0f), pa(1.0f), na(-1.0f);
>From 0dd9607ef40c9896c8c052556e69ec2c2fa2a1db Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Fri, 21 Aug 2026 01:51:46 +0530
Subject: [PATCH 15/15] apply suggestion
---
libc/src/__support/FPUtil/CMakeLists.txt | 1 +
libc/src/__support/FPUtil/float80.h | 8 ++------
2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 96fbb6d80a669..19934a6f00783 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -323,6 +323,7 @@ add_header_library(
.dyadic_float
libc.hdr.stdint_proxy
libc.src.__support.CPP.type_traits
+ libc.src.__support.FPUtil.float80
libc.src.__support.FPUtil.generic.add_sub
libc.src.__support.FPUtil.generic.div
libc.src.__support.FPUtil.generic.mul
diff --git a/libc/src/__support/FPUtil/float80.h b/libc/src/__support/FPUtil/float80.h
index cb8dc618c9280..8264212546fc5 100644
--- a/libc/src/__support/FPUtil/float80.h
+++ b/libc/src/__support/FPUtil/float80.h
@@ -97,12 +97,13 @@ struct Float80 {
return static_cast<T>(xd.as_mantissa_type());
}
- // unary operators
+ // unary operator
LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR Float80 operator-() const {
fputil::FPBits<Float80> result(*this);
result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
return result.get_val();
}
+
LIBC_INLINE constexpr Float80 operator+(const Float80 &other) const {
return fputil::generic::add<Float80>(fputil::cast<Float128>(*this),
fputil::cast<Float128>(other));
@@ -149,11 +150,6 @@ struct Float80 {
}
};
-static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible<
- LIBC_NAMESPACE::fputil::Float80>::value);
-static_assert(LIBC_NAMESPACE::cpp::is_trivially_copyable<
- LIBC_NAMESPACE::fputil::Float80>::value);
-
} // namespace fputil
} // namespace LIBC_NAMESPACE_DECL
More information about the llvm-branch-commits
mailing list