[libc-commits] [libc] [libc] Float128 Emulation in LLVM libc (PR #200565)

via libc-commits libc-commits at lists.llvm.org
Thu Jun 25 09:16:02 PDT 2026


https://github.com/Sukumarsawant updated https://github.com/llvm/llvm-project/pull/200565

>From 8a47cf7d898cc79e8cc749cad2663032012ff2d1 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 30 May 2026 02:08:42 +0530
Subject: [PATCH 01/28] test: float128 skeleton

---
 libc/src/__support/FPUtil/CMakeLists.txt | 11 ++++++
 libc/src/__support/FPUtil/float128.h     | 45 ++++++++++++++++++++++++
 2 files changed, 56 insertions(+)
 create mode 100644 libc/src/__support/FPUtil/float128.h

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index d45dd82560788..a88986b4992f8 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -294,4 +294,15 @@ add_header_library(
     libc.src.__support.macros.properties.types
 )
 
+add_header_library(
+  float128
+  HDRS
+    float128.h
+  DEPENDS
+    .fp_bits
+    libc.hdr.fenv_macros
+    libc.src.__support.CPP.bit
+    libc.src.__support.uint128
+)
+
 add_subdirectory(generic)
diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
new file mode 100644
index 0000000000000..73f450f1d41a8
--- /dev/null
+++ b/libc/src/__support/FPUtil/float128.h
@@ -0,0 +1,45 @@
+//===-- Utilities for Float128 data type  -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
+#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
+
+#include "FPBits.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/CPP/bit.h"
+#include "src/__support/uint128.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace fputil {
+
+struct Float128 {
+  UInt128 bits;
+  // Testing
+  constexpr Float128() = default;
+  /* TODO: precision
+     TODO: explicit so it does not convert without warn ( Done )
+     VERIFY :   template <cpp::enable_if_t<fputil::get_fp_type<Double>() ==
+                                 fputil::FPType::IEEE754_Binary64,
+                             int> = 0>
+  */
+  constexpr explicit Float128(double x) {
+    FPBits<double> x_bits(x);
+    uint64_t val = x_bits.uintval();
+    bits = static_cast<UInt128>(val) << 64;
+  }
+
+  constexpr explicit operator double() const {
+    uint64_t val = static_cast<uint64_t>(bits >> 64U);
+    return cpp::bit_cast<double>(val);
+  }
+};
+
+} // namespace fputil
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H

>From dd5cdbd4910bdbabdd83f5eb0e78da2328a1929b Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 2 Jun 2026 14:00:26 +0530
Subject: [PATCH 02/28] Add small smoke test

---
 .../CPP/type_traits/is_floating_point.h       |  2 +-
 libc/src/__support/FPUtil/CMakeLists.txt      |  4 +-
 libc/src/__support/FPUtil/FPBits.h            | 13 +++++-
 libc/src/__support/FPUtil/float128.h          | 41 +++++++++++--------
 libc/src/__support/macros/properties/types.h  |  8 ++++
 libc/test/src/math/smoke/CMakeLists.txt       | 10 +++++
 libc/test/src/math/smoke/float128_test.cpp    | 25 +++++++++++
 7 files changed, 81 insertions(+), 22 deletions(-)
 create mode 100644 libc/test/src/math/smoke/float128_test.cpp

diff --git a/libc/src/__support/CPP/type_traits/is_floating_point.h b/libc/src/__support/CPP/type_traits/is_floating_point.h
index 9dc77ad7ee0ea..ab4191868517e 100644
--- a/libc/src/__support/CPP/type_traits/is_floating_point.h
+++ b/libc/src/__support/CPP/type_traits/is_floating_point.h
@@ -37,7 +37,7 @@ template <typename T> struct is_floating_point {
                               float128
 #endif
                               ,
-                              bfloat16>();
+                              bfloat16, fputil::Float128>();
 };
 template <typename T>
 LIBC_INLINE_VAR constexpr bool is_floating_point_v =
diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index a88986b4992f8..20e1c01bb8ca1 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -299,9 +299,9 @@ add_header_library(
   HDRS
     float128.h
   DEPENDS
-    .fp_bits
-    libc.hdr.fenv_macros
     libc.src.__support.CPP.bit
+    libc.src.__support.macros.attributes
+    libc.src.__support.macros.config
     libc.src.__support.uint128
 )
 
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index c52699e17e225..5b7461a44cff5 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -37,7 +37,8 @@ enum class FPType {
   IEEE754_Binary64,
   IEEE754_Binary128,
   X86_Binary80,
-  BFloat16
+  BFloat16,
+  Float128
 };
 
 // The classes hierarchy is as follows:
@@ -146,6 +147,14 @@ template <> struct FPLayout<FPType::BFloat16> {
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
 };
 
+template <> struct FPLayout<FPType::Float128> {
+  using StorageType = UInt128;
+  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 = 112;
+  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
+};
+
 // FPStorage derives useful constants from the FPLayout above.
 template <FPType fp_type> struct FPStorage : public FPLayout<fp_type> {
   using UP = FPLayout<fp_type>;
@@ -813,6 +822,8 @@ template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
 #endif
   else if constexpr (cpp::is_same_v<UnqualT, bfloat16>)
     return FPType::BFloat16;
+  else if constexpr (cpp::is_same_v<UnqualT, Float128>)
+    return FPType::Float128;
   else
     static_assert(cpp::always_false<UnqualT>, "Unsupported type");
 }
diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index 73f450f1d41a8..ca5c49ddf11d7 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -1,4 +1,8 @@
+<<<<<<< HEAD
 //===-- Utilities for Float128 data type  -----------------------*- C++ -*-===//
+=======
+//===-- Definition for Float128 data type -----------------------*- C++ -*-===//
+>>>>>>> f128-test
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -9,33 +13,34 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
 #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
 
-#include "FPBits.h"
-#include "hdr/fenv_macros.h"
-#include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/bit.h" // cpp::bit_cast
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
 #include "src/__support/uint128.h"
+#include <stdint.h>
 
 namespace LIBC_NAMESPACE_DECL {
 namespace fputil {
 
 struct Float128 {
   UInt128 bits;
-  // Testing
-  constexpr Float128() = default;
-  /* TODO: precision
-     TODO: explicit so it does not convert without warn ( Done )
-     VERIFY :   template <cpp::enable_if_t<fputil::get_fp_type<Double>() ==
-                                 fputil::FPType::IEEE754_Binary64,
-                             int> = 0>
-  */
-  constexpr explicit Float128(double x) {
-    FPBits<double> x_bits(x);
-    uint64_t val = x_bits.uintval();
-    bits = static_cast<UInt128>(val) << 64;
+
+  LIBC_INLINE Float128() = default;
+
+  LIBC_INLINE constexpr explicit Float128(double x) : bits(0) {
+    uint64_t d = cpp::bit_cast<uint64_t>(x);
+    bits = static_cast<UInt128>(d) << 64U;
   }
 
-  constexpr explicit operator double() const {
-    uint64_t val = static_cast<uint64_t>(bits >> 64U);
-    return cpp::bit_cast<double>(val);
+  LIBC_INLINE constexpr explicit operator double() const {
+    return cpp::bit_cast<double>(static_cast<uint64_t>(bits >> 64U));
+  }
+
+  LIBC_INLINE constexpr bool operator==(Float128 other) const {
+    return bits == other.bits;
+  }
+  LIBC_INLINE constexpr bool operator!=(Float128 other) const {
+    return bits != other.bits;
   }
 };
 
diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h
index 3259c8a6a1d12..d94f6068984df 100644
--- a/libc/src/__support/macros/properties/types.h
+++ b/libc/src/__support/macros/properties/types.h
@@ -58,6 +58,14 @@ using float16 = _Float16;
 // LIBC_TYPES_HAS_FLOAT128 and 'float128' type are provided by
 // "include/llvm-libc-types/float128.h"
 
+// -- Emulated float128 support ------------------------------------------------
+// Float128 is always available regardless of native __float128 support.
+namespace LIBC_NAMESPACE_DECL {
+namespace fputil {
+struct Float128;
+}
+} // namespace LIBC_NAMESPACE_DECL
+
 // -- bfloat16 support ---------------------------------------------------------
 
 namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index b763cdb43b31c..89b131f0a79b5 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -1,6 +1,16 @@
 add_custom_target(libc-math-smoke-tests)
 add_dependencies(libc-math-unittests libc-math-smoke-tests)
 
+add_libc_unittest(
+  float128_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    float128_test.cpp
+  DEPENDS
+    libc.src.__support.FPUtil.float128
+)
+
 add_fp_unittest(
   cosf_test
   SUITE
diff --git a/libc/test/src/math/smoke/float128_test.cpp b/libc/test/src/math/smoke/float128_test.cpp
new file mode 100644
index 0000000000000..738e5ec703f00
--- /dev/null
+++ b/libc/test/src/math/smoke/float128_test.cpp
@@ -0,0 +1,25 @@
+//===-- Unittests for Float128 emulated type -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/FPUtil/float128.h"
+#include "src/__support/uint128.h"
+#include "test/UnitTest/Test.h"
+
+using LIBC_NAMESPACE::fputil::Float128;
+
+TEST(LlvmLibcFloat128Test, DefaultConstructor) {
+  Float128 x;
+  (void)x;
+}
+
+TEST(LlvmLibcFloat128Test, Equality) {
+  Float128 a(1.0), b(1.0), c(2.0);
+  ASSERT_TRUE(a == b);
+  ASSERT_TRUE(a != c);
+  ASSERT_TRUE(b != c);
+}

>From 006c184990d37da5580facb66dc7a6226abac021 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 2 Jun 2026 14:06:05 +0530
Subject: [PATCH 03/28] nit

---
 libc/src/__support/FPUtil/float128.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index ca5c49ddf11d7..c7835d7376853 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -1,8 +1,4 @@
-<<<<<<< HEAD
-//===-- Utilities for Float128 data type  -----------------------*- C++ -*-===//
-=======
 //===-- Definition for Float128 data type -----------------------*- C++ -*-===//
->>>>>>> f128-test
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.

>From d1d786ac7954bdf68ee615d48d6410d0c262d40c Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 2 Jun 2026 15:13:25 +0530
Subject: [PATCH 04/28] nit

---
 libc/src/__support/FPUtil/float128.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index c7835d7376853..cc72692e8a22f 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -9,7 +9,7 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
 #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
 
-#include "src/__support/CPP/bit.h" // cpp::bit_cast
+#include "src/__support/CPP/bit.h"
 #include "src/__support/macros/attributes.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/uint128.h"
@@ -24,8 +24,8 @@ struct Float128 {
   LIBC_INLINE Float128() = default;
 
   LIBC_INLINE constexpr explicit Float128(double x) : bits(0) {
-    uint64_t d = cpp::bit_cast<uint64_t>(x);
-    bits = static_cast<UInt128>(d) << 64U;
+    uint64_t x_bits = cpp::bit_cast<uint64_t>(x);
+    bits = static_cast<UInt128>(x_bits) << 64U;
   }
 
   LIBC_INLINE constexpr explicit operator double() const {

>From 86ab3c80688f1219d89f3eaba8b9fe4d9f67a3e6 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 2 Jun 2026 20:52:36 +0530
Subject: [PATCH 05/28] temp commit for rebase

---
 libc/src/__support/CPP/type_traits/is_floating_point.h | 5 ++++-
 libc/src/__support/FPUtil/cast.h                       | 4 +++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/libc/src/__support/CPP/type_traits/is_floating_point.h b/libc/src/__support/CPP/type_traits/is_floating_point.h
index ab4191868517e..d53dcd4961ab6 100644
--- a/libc/src/__support/CPP/type_traits/is_floating_point.h
+++ b/libc/src/__support/CPP/type_traits/is_floating_point.h
@@ -37,7 +37,10 @@ template <typename T> struct is_floating_point {
                               float128
 #endif
                               ,
-                              bfloat16, fputil::Float128>();
+                              bfloat16
+
+                              ,
+                              fputil::Float128>();
 };
 template <typename T>
 LIBC_INLINE_VAR constexpr bool is_floating_point_v =
diff --git a/libc/src/__support/FPUtil/cast.h b/libc/src/__support/FPUtil/cast.h
index 54c80e862523a..4fc5ea0893ebe 100644
--- a/libc/src/__support/FPUtil/cast.h
+++ b/libc/src/__support/FPUtil/cast.h
@@ -31,7 +31,9 @@ cast(InType x) {
     return x;
   } else {
     if constexpr (cpp::is_same_v<OutType, bfloat16> ||
-                  cpp::is_same_v<InType, bfloat16>
+                  cpp::is_same_v<InType, bfloat16> ||
+                  cpp::is_same_v<OutType, Float128> ||
+                  cpp::is_same_v<InType, Float128>
 #if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
                   || cpp::is_same_v<OutType, float16> ||
                   cpp::is_same_v<InType, float16>

>From b409aaf9a19785d4553b1af43f20965a66477cc0 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 2 Jun 2026 22:24:48 +0530
Subject: [PATCH 06/28] feat: comparison operator overload

---
 libc/src/__support/FPUtil/CMakeLists.txt     |  2 ++
 libc/src/__support/FPUtil/cast.h             |  4 ++--
 libc/src/__support/FPUtil/dyadic_float.h     |  2 +-
 libc/src/__support/FPUtil/float128.h         | 23 ++++++++++++++++++--
 libc/src/__support/macros/properties/types.h |  3 +++
 libc/test/src/math/smoke/float128_test.cpp   |  8 ++++++-
 6 files changed, 36 insertions(+), 6 deletions(-)

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 20e1c01bb8ca1..c49d873b026e2 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -303,6 +303,8 @@ add_header_library(
     libc.src.__support.macros.attributes
     libc.src.__support.macros.config
     libc.src.__support.uint128
+    libc.src.__support.CPP.type_traits
+    .comparison_operations
 )
 
 add_subdirectory(generic)
diff --git a/libc/src/__support/FPUtil/cast.h b/libc/src/__support/FPUtil/cast.h
index 4fc5ea0893ebe..e7b2caf92fe4a 100644
--- a/libc/src/__support/FPUtil/cast.h
+++ b/libc/src/__support/FPUtil/cast.h
@@ -32,8 +32,8 @@ cast(InType x) {
   } else {
     if constexpr (cpp::is_same_v<OutType, bfloat16> ||
                   cpp::is_same_v<InType, bfloat16> ||
-                  cpp::is_same_v<OutType, Float128> ||
-                  cpp::is_same_v<InType, Float128>
+                  cpp::is_same_v<OutType, float128> ||
+                  cpp::is_same_v<InType, float128>
 #if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
                   || cpp::is_same_v<OutType, float16> ||
                   cpp::is_same_v<InType, float16>
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 2c065e48e7632..0e56b48d92ad5 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -438,7 +438,7 @@ template <size_t Bits> struct DyadicFloat {
                                             (FPBits<T>::FRACTION_LEN < Bits),
                                         void>>
   LIBC_INLINE LIBC_CONSTEXPR_DEFAULT T as() const {
-    if constexpr (cpp::is_same_v<T, bfloat16>
+    if constexpr (cpp::is_same_v<T, bfloat16> || cpp::is_same_v<T, float128>
 #if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
                   || cpp::is_same_v<T, float16>
 #endif
diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index cc72692e8a22f..d887153f58afb 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -10,6 +10,8 @@
 #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
 
 #include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/FPUtil/comparison_operations.h"
 #include "src/__support/macros/attributes.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/uint128.h"
@@ -33,10 +35,27 @@ struct Float128 {
   }
 
   LIBC_INLINE constexpr bool operator==(Float128 other) const {
-    return bits == other.bits;
+    return fputil::equals(*this, other);
   }
+
   LIBC_INLINE constexpr bool operator!=(Float128 other) const {
-    return bits != other.bits;
+    return !fputil::equals(*this, other);
+  }
+
+  LIBC_INLINE constexpr bool operator<(Float128 other) const {
+    return fputil::less_than(*this, other);
+  }
+
+  LIBC_INLINE constexpr bool operator<=(Float128 other) const {
+    return fputil::less_than_or_equals(*this, other);
+  }
+
+  LIBC_INLINE constexpr bool operator>(Float128 other) const {
+    return fputil::greater_than(*this, other);
+  }
+
+  LIBC_INLINE constexpr bool operator>=(Float128 other) const {
+    return fputil::greater_than_or_equals(*this, other);
   }
 };
 
diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h
index d94f6068984df..02d08867a4c9f 100644
--- a/libc/src/__support/macros/properties/types.h
+++ b/libc/src/__support/macros/properties/types.h
@@ -66,6 +66,9 @@ struct Float128;
 }
 } // namespace LIBC_NAMESPACE_DECL
 
+#ifndef LIBC_TYPES_HAS_FLOAT128
+using float128 = LIBC_NAMESPACE::fputil::Float128;
+#endif // LIBC_TYPES_HAS_FLOAT128
 // -- bfloat16 support ---------------------------------------------------------
 
 namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/test/src/math/smoke/float128_test.cpp b/libc/test/src/math/smoke/float128_test.cpp
index 738e5ec703f00..29fcc73384fd5 100644
--- a/libc/test/src/math/smoke/float128_test.cpp
+++ b/libc/test/src/math/smoke/float128_test.cpp
@@ -17,9 +17,15 @@ TEST(LlvmLibcFloat128Test, DefaultConstructor) {
   (void)x;
 }
 
-TEST(LlvmLibcFloat128Test, Equality) {
+TEST(LlvmLibcFloat128Test, operators) {
   Float128 a(1.0), b(1.0), c(2.0);
+
+  // comparison operators
   ASSERT_TRUE(a == b);
   ASSERT_TRUE(a != c);
   ASSERT_TRUE(b != c);
+  ASSERT_TRUE(c > b);
+  ASSERT_TRUE(a >= b);
+  ASSERT_TRUE(b <= c);
+  ASSERT_TRUE(a < c);
 }

>From f7618045fd67e5e2f82624c7ecfc2c46a1dc3049 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Wed, 3 Jun 2026 00:02:22 +0530
Subject: [PATCH 07/28] marking default const , constexpr

---
 libc/src/__support/FPUtil/float128.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index d887153f58afb..c9db7fd683bd1 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -23,7 +23,7 @@ namespace fputil {
 struct Float128 {
   UInt128 bits;
 
-  LIBC_INLINE Float128() = default;
+  LIBC_INLINE constexpr Float128() = default;
 
   LIBC_INLINE constexpr explicit Float128(double x) : bits(0) {
     uint64_t x_bits = cpp::bit_cast<uint64_t>(x);

>From a860a9c931ac2dde9c5b6d2ab68c0daacabf456f Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Wed, 3 Jun 2026 01:02:42 +0530
Subject: [PATCH 08/28] testing alias + removed constexpr for def const

---
 libc/src/__support/FPUtil/cast.h             | 4 ++--
 libc/src/__support/FPUtil/dyadic_float.h     | 2 +-
 libc/src/__support/FPUtil/float128.h         | 2 +-
 libc/src/__support/macros/properties/types.h | 6 +++---
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/libc/src/__support/FPUtil/cast.h b/libc/src/__support/FPUtil/cast.h
index e7b2caf92fe4a..4fc5ea0893ebe 100644
--- a/libc/src/__support/FPUtil/cast.h
+++ b/libc/src/__support/FPUtil/cast.h
@@ -32,8 +32,8 @@ cast(InType x) {
   } else {
     if constexpr (cpp::is_same_v<OutType, bfloat16> ||
                   cpp::is_same_v<InType, bfloat16> ||
-                  cpp::is_same_v<OutType, float128> ||
-                  cpp::is_same_v<InType, float128>
+                  cpp::is_same_v<OutType, Float128> ||
+                  cpp::is_same_v<InType, Float128>
 #if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
                   || cpp::is_same_v<OutType, float16> ||
                   cpp::is_same_v<InType, float16>
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 0e56b48d92ad5..d3f11e1a35320 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -438,7 +438,7 @@ template <size_t Bits> struct DyadicFloat {
                                             (FPBits<T>::FRACTION_LEN < Bits),
                                         void>>
   LIBC_INLINE LIBC_CONSTEXPR_DEFAULT T as() const {
-    if constexpr (cpp::is_same_v<T, bfloat16> || cpp::is_same_v<T, float128>
+    if constexpr (cpp::is_same_v<T, bfloat16> || cpp::is_same_v<T, Float128>
 #if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
                   || cpp::is_same_v<T, float16>
 #endif
diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index c9db7fd683bd1..d887153f58afb 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -23,7 +23,7 @@ namespace fputil {
 struct Float128 {
   UInt128 bits;
 
-  LIBC_INLINE constexpr Float128() = default;
+  LIBC_INLINE Float128() = default;
 
   LIBC_INLINE constexpr explicit Float128(double x) : bits(0) {
     uint64_t x_bits = cpp::bit_cast<uint64_t>(x);
diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h
index 02d08867a4c9f..7b861640c785d 100644
--- a/libc/src/__support/macros/properties/types.h
+++ b/libc/src/__support/macros/properties/types.h
@@ -66,9 +66,9 @@ struct Float128;
 }
 } // namespace LIBC_NAMESPACE_DECL
 
-#ifndef LIBC_TYPES_HAS_FLOAT128
-using float128 = LIBC_NAMESPACE::fputil::Float128;
-#endif // LIBC_TYPES_HAS_FLOAT128
+// #ifndef LIBC_TYPES_HAS_FLOAT128
+// using float128 = LIBC_NAMESPACE::fputil::Float128;
+// #endif // LIBC_TYPES_HAS_FLOAT128
 // -- bfloat16 support ---------------------------------------------------------
 
 namespace LIBC_NAMESPACE_DECL {

>From 91e9a520c6c21177732a5268e39034e11b39571d Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Wed, 3 Jun 2026 13:40:43 +0530
Subject: [PATCH 09/28] template + LIBC_CONSTEXPR_DEFAULT

---
 libc/src/__support/FPUtil/float128.h | 30 ++++++++++++++++------------
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index d887153f58afb..97c0daf79c546 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -9,8 +9,8 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
 #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
 
-#include "src/__support/CPP/bit.h"
 #include "src/__support/CPP/type_traits.h"
+#include "src/__support/FPUtil/cast.h"
 #include "src/__support/FPUtil/comparison_operations.h"
 #include "src/__support/macros/attributes.h"
 #include "src/__support/macros/config.h"
@@ -25,36 +25,40 @@ struct Float128 {
 
   LIBC_INLINE Float128() = default;
 
-  LIBC_INLINE constexpr explicit Float128(double x) : bits(0) {
-    uint64_t x_bits = cpp::bit_cast<uint64_t>(x);
-    bits = static_cast<UInt128>(x_bits) << 64U;
+  template <typename T> LIBC_INLINE constexpr explicit Float128(T x) : bits(0) {
+    if constexpr (cpp::is_floating_point_v<T>) {
+      bits = fputil::cast<Float128>(x).bits;
+    }
+    // TODO: add rem after testing
   }
 
-  LIBC_INLINE constexpr explicit operator double() const {
-    return cpp::bit_cast<double>(static_cast<uint64_t>(bits >> 64U));
+  template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T> &&
+                                             !cpp::is_same_v<T, Float128>,
+                                         int> = 0>
+  LIBC_INLINE LIBC_CONSTEXPR_DEFAULT operator T() const {
+    return fputil::cast<T>(*this);
   }
-
-  LIBC_INLINE constexpr bool operator==(Float128 other) const {
+  LIBC_INLINE constexpr bool operator==(Float128 &other) const {
     return fputil::equals(*this, other);
   }
 
-  LIBC_INLINE constexpr bool operator!=(Float128 other) const {
+  LIBC_INLINE constexpr bool operator!=(Float128 &other) const {
     return !fputil::equals(*this, other);
   }
 
-  LIBC_INLINE constexpr bool operator<(Float128 other) const {
+  LIBC_INLINE constexpr bool operator<(Float128 &other) const {
     return fputil::less_than(*this, other);
   }
 
-  LIBC_INLINE constexpr bool operator<=(Float128 other) const {
+  LIBC_INLINE constexpr bool operator<=(Float128 &other) const {
     return fputil::less_than_or_equals(*this, other);
   }
 
-  LIBC_INLINE constexpr bool operator>(Float128 other) const {
+  LIBC_INLINE constexpr bool operator>(Float128 &other) const {
     return fputil::greater_than(*this, other);
   }
 
-  LIBC_INLINE constexpr bool operator>=(Float128 other) const {
+  LIBC_INLINE constexpr bool operator>=(Float128 &other) const {
     return fputil::greater_than_or_equals(*this, other);
   }
 };

>From 2de71f3528723dda452aad564f7aa40c35198f83 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 4 Jun 2026 20:34:00 +0530
Subject: [PATCH 10/28] testing double?

---
 libc/test/src/math/smoke/float128_test.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/test/src/math/smoke/float128_test.cpp b/libc/test/src/math/smoke/float128_test.cpp
index 29fcc73384fd5..f2f6d31007754 100644
--- a/libc/test/src/math/smoke/float128_test.cpp
+++ b/libc/test/src/math/smoke/float128_test.cpp
@@ -18,7 +18,7 @@ TEST(LlvmLibcFloat128Test, DefaultConstructor) {
 }
 
 TEST(LlvmLibcFloat128Test, operators) {
-  Float128 a(1.0), b(1.0), c(2.0);
+  Float128 a(1.0f), b(1.0f), c(2.0f);
 
   // comparison operators
   ASSERT_TRUE(a == b);

>From 0098b2eebbc7d59276623a581a80efae1993eac8 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 4 Jun 2026 21:49:40 +0530
Subject: [PATCH 11/28] test static assert

---
 libc/src/__support/FPUtil/bfloat16.h | 7 +++++++
 libc/src/__support/FPUtil/float128.h | 7 +++++++
 2 files changed, 14 insertions(+)

diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index ce4e3160a0963..cf3fefe75bff3 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -135,4 +135,11 @@ struct BFloat16 {
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 
+static_assert(
+    LIBC_NAMESPACE::cpp::is_trivially_constructible<
+        LIBC_NAMESPACE::fputil::BFloat16>::value);
+static_assert(
+    LIBC_NAMESPACE::cpp::is_trivially_copyable<
+        LIBC_NAMESPACE::fputil::BFloat16>::value);
+
 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_BFLOAT16_H
diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index 97c0daf79c546..184cc802d094d 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -66,4 +66,11 @@ struct Float128 {
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 
+static_assert(
+    LIBC_NAMESPACE::cpp::is_trivially_constructible<
+        LIBC_NAMESPACE::fputil::Float128>::value);
+static_assert(
+    LIBC_NAMESPACE::cpp::is_trivially_copyable<
+        LIBC_NAMESPACE::fputil::Float128>::value);
+
 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H

>From b145f3e198bf9a8640e0832d9cbf8ba71e343dea Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 4 Jun 2026 22:16:53 +0530
Subject: [PATCH 12/28] testing with all types of constructor

---
 libc/src/__support/FPUtil/float128.h | 31 ++++++++++++++++++++++++----
 1 file changed, 27 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index 184cc802d094d..cf1a1d2f59199 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -23,13 +23,36 @@ namespace fputil {
 struct Float128 {
   UInt128 bits;
 
-  LIBC_INLINE Float128() = default;
+  LIBC_INLINE constexpr Float128() = default;
+  LIBC_INLINE constexpr Float128(const Float128 &) = default;
+  LIBC_INLINE constexpr Float128(Float128 &&) = default;
+  LIBC_INLINE constexpr Float128 &operator=(const Float128 &) = default;
+  LIBC_INLINE constexpr Float128 &operator=(Float128 &&) = default;
 
-  template <typename T> LIBC_INLINE constexpr explicit Float128(T x) : bits(0) {
+  template <typename T>
+  LIBC_INLINE constexpr explicit Float128(T value)
+      : bits(static_cast<UInt128>(0U)) {
     if constexpr (cpp::is_floating_point_v<T>) {
-      bits = fputil::cast<Float128>(x).bits;
+      bits = fputil::cast<Float128>(value).bits;
+    } else if constexpr (cpp::is_integral_v<T>) {
+      Sign sign = Sign::POS;
+
+      if constexpr (cpp::is_signed_v<T>) {
+        if (value < 0) {
+          sign = Sign::NEG;
+          value = -value;
+        }
+      }
+
+      fputil::DyadicFloat<cpp::numeric_limits<cpp::make_unsigned_t<T>>::digits>
+          xd(sign, 0, value);
+      bits = xd.template as<Float128, /*ShouldSignalExceptions=*/true>().bits;
+
+    } else if constexpr (cpp::is_convertible_v<T, Float128>) {
+      bits = value.operator Float128().bits;
+    } else {
+      bits = fputil::cast<Float128>(static_cast<float>(value)).bits;
     }
-    // TODO: add rem after testing
   }
 
   template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T> &&

>From 8ca5777ac87d966f27ed1fbaf125e8eb829f0e04 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 4 Jun 2026 22:24:42 +0530
Subject: [PATCH 13/28] removing constexpr

---
 libc/src/__support/FPUtil/float128.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index cf1a1d2f59199..e8cccd019d0ea 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -23,7 +23,7 @@ namespace fputil {
 struct Float128 {
   UInt128 bits;
 
-  LIBC_INLINE constexpr Float128() = default;
+  LIBC_INLINE Float128() = default;
   LIBC_INLINE constexpr Float128(const Float128 &) = default;
   LIBC_INLINE constexpr Float128(Float128 &&) = default;
   LIBC_INLINE constexpr Float128 &operator=(const Float128 &) = default;

>From f3db979cc95bdc11471655b76ab60ac8ce9e7716 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 11 Jun 2026 18:11:24 +0530
Subject: [PATCH 14/28] nits before final (Win fail)

---
 libc/src/__support/CPP/type_traits/is_floating_point.h | 2 ++
 libc/src/__support/FPUtil/bfloat16.h                   | 2 ++
 libc/src/__support/FPUtil/float128.h                   | 3 ++-
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/libc/src/__support/CPP/type_traits/is_floating_point.h b/libc/src/__support/CPP/type_traits/is_floating_point.h
index d53dcd4961ab6..b7fa71bde2f93 100644
--- a/libc/src/__support/CPP/type_traits/is_floating_point.h
+++ b/libc/src/__support/CPP/type_traits/is_floating_point.h
@@ -40,6 +40,8 @@ template <typename T> struct is_floating_point {
                               bfloat16
 
                               ,
+                              // TODO: Replace as float128 once the alias is
+                              // fixed
                               fputil::Float128>();
 };
 template <typename T>
diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index cf3fefe75bff3..8a3f3c9894aad 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -135,11 +135,13 @@ struct BFloat16 {
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 
+// <--To be removed------------------------------------>
 static_assert(
     LIBC_NAMESPACE::cpp::is_trivially_constructible<
         LIBC_NAMESPACE::fputil::BFloat16>::value);
 static_assert(
     LIBC_NAMESPACE::cpp::is_trivially_copyable<
         LIBC_NAMESPACE::fputil::BFloat16>::value);
+// ----------------------------------------------------
 
 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_BFLOAT16_H
diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index e8cccd019d0ea..df1e3e5e884a7 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -89,11 +89,12 @@ struct Float128 {
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 
+// <--To be removed------------------------------------>
 static_assert(
     LIBC_NAMESPACE::cpp::is_trivially_constructible<
         LIBC_NAMESPACE::fputil::Float128>::value);
 static_assert(
     LIBC_NAMESPACE::cpp::is_trivially_copyable<
         LIBC_NAMESPACE::fputil::Float128>::value);
-
+// ----------------------------------------------------
 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H

>From 301006a6dc0682986d8afa14094cfe8bf25828c9 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 11 Jun 2026 20:16:12 +0530
Subject: [PATCH 15/28] testing CI for more operators and conversions (
 floating-type)

---
 libc/src/__support/FPUtil/float128.h       | 42 ++++++++++++++++++----
 libc/test/src/math/smoke/float128_test.cpp | 16 ++++++++-
 2 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index df1e3e5e884a7..663d54a8de01e 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -16,6 +16,11 @@
 #include "src/__support/macros/config.h"
 #include "src/__support/uint128.h"
 #include <stdint.h>
+#include "hdr/stdint_proxy.h"
+#include "src/__support/FPUtil/dyadic_float.h"
+#include "src/__support/FPUtil/generic/add_sub.h"
+#include "src/__support/FPUtil/generic/div.h"
+#include "src/__support/FPUtil/generic/mul.h"
 
 namespace LIBC_NAMESPACE_DECL {
 namespace fputil {
@@ -29,6 +34,7 @@ struct Float128 {
   LIBC_INLINE constexpr Float128 &operator=(const Float128 &) = default;
   LIBC_INLINE constexpr Float128 &operator=(Float128 &&) = default;
 
+  // Floating point type and integer type 
   template <typename T>
   LIBC_INLINE constexpr explicit Float128(T value)
       : bits(static_cast<UInt128>(0U)) {
@@ -61,27 +67,51 @@ struct Float128 {
   LIBC_INLINE LIBC_CONSTEXPR_DEFAULT operator T() const {
     return fputil::cast<T>(*this);
   }
-  LIBC_INLINE constexpr bool operator==(Float128 &other) const {
+// TODO: Integer conversion
+  // unary
+  LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR Float128 operator-() const {
+    fputil::FPBits<Float128> result(*this);
+    result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
+    return result.get_val();
+  }
+  // operator overloads
+    LIBC_INLINE constexpr Float128 operator+(const Float128 &other) const {
+    return fputil::generic::add<Float128>(*this, other);
+  }
+
+  LIBC_INLINE constexpr Float128 operator-(const Float128 &other) const {
+    return fputil::generic::sub<Float128>(*this, other);
+  }
+
+  LIBC_INLINE constexpr Float128 operator*(const Float128 &other) const {
+    return fputil::generic::mul<Float128>(*this, other);
+  }
+
+  LIBC_INLINE constexpr Float128 operator/(const Float128 &other) const {
+    return fputil::generic::div<Float128>(*this, other);
+  }
+
+  LIBC_INLINE constexpr bool operator==(const Float128 &other) const {
     return fputil::equals(*this, other);
   }
 
-  LIBC_INLINE constexpr bool operator!=(Float128 &other) const {
+  LIBC_INLINE constexpr bool operator!=(const Float128 &other) const {
     return !fputil::equals(*this, other);
   }
 
-  LIBC_INLINE constexpr bool operator<(Float128 &other) const {
+  LIBC_INLINE constexpr bool operator<(const Float128 &other) const {
     return fputil::less_than(*this, other);
   }
 
-  LIBC_INLINE constexpr bool operator<=(Float128 &other) const {
+  LIBC_INLINE constexpr bool operator<=(const Float128 &other) const {
     return fputil::less_than_or_equals(*this, other);
   }
 
-  LIBC_INLINE constexpr bool operator>(Float128 &other) const {
+  LIBC_INLINE constexpr bool operator>(const Float128 &other) const {
     return fputil::greater_than(*this, other);
   }
 
-  LIBC_INLINE constexpr bool operator>=(Float128 &other) const {
+  LIBC_INLINE constexpr bool operator>=(const Float128 &other) const {
     return fputil::greater_than_or_equals(*this, other);
   }
 };
diff --git a/libc/test/src/math/smoke/float128_test.cpp b/libc/test/src/math/smoke/float128_test.cpp
index f2f6d31007754..1a3a9a6c45726 100644
--- a/libc/test/src/math/smoke/float128_test.cpp
+++ b/libc/test/src/math/smoke/float128_test.cpp
@@ -17,15 +17,29 @@ TEST(LlvmLibcFloat128Test, DefaultConstructor) {
   (void)x;
 }
 
-TEST(LlvmLibcFloat128Test, operators) {
+TEST(LlvmLibcFloat128Test, UnaryOperators) {
   Float128 a(1.0f), b(1.0f), c(2.0f);
 
   // comparison operators
   ASSERT_TRUE(a == b);
+  ASSERT_TRUE(a == Float128(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);
+
+  //negation 
+  Float128 pa(1.0),na(-1.0f);
+  ASSERT_TRUE(-pa == na);
+  ASSERT_TRUE(-(-pa)== -na);
+}
+
+TEST(LlvmLibcFloat128Test, BinaryOperators) {
+  Float128 a(1.0f), b(1.0f), c(2.0f), d(3.0);
+  ASSERT_TRUE((a + b) == c);
+  ASSERT_TRUE((a - b) == Float128(0.0));
+  ASSERT_TRUE((c * d) == Float128(6.0));
+  ASSERT_TRUE((Float128(6.0) / d) == Float128(2.0));
 }

>From 21ad86d1e714d728e6bd0469d6abb590beecff99 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 11 Jun 2026 20:57:53 +0530
Subject: [PATCH 16/28] testing float128 add_sub addition

---
 libc/src/__support/FPUtil/generic/add_sub.h | 10 +++++++++-
 libc/test/src/math/smoke/float128_test.cpp  | 18 +++++++++---------
 2 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/libc/src/__support/FPUtil/generic/add_sub.h b/libc/src/__support/FPUtil/generic/add_sub.h
index cf662d051c162..0a2208f43cf05 100644
--- a/libc/src/__support/FPUtil/generic/add_sub.h
+++ b/libc/src/__support/FPUtil/generic/add_sub.h
@@ -116,7 +116,15 @@ add_or_sub(InType x, InType y) {
         if constexpr (IsSub)
           out_y_bits.set_sign(out_y_bits.sign().negate());
         return out_y_bits.get_val();
-      } else {
+      }
+      else if constexpr (cpp::is_same_v<InType, Float128> &&
+                    cpp::is_same_v<OutType, Float128>) {
+        OutFPBits out_y_bits(y);
+        if constexpr (IsSub)
+          out_y_bits.set_sign(out_y_bits.sign().negate());
+        return out_y_bits.get_val();
+      }
+      else {
 
 #ifdef LIBC_USE_CONSTEXPR
         InType tmp = y;
diff --git a/libc/test/src/math/smoke/float128_test.cpp b/libc/test/src/math/smoke/float128_test.cpp
index 1a3a9a6c45726..41323bccb3467 100644
--- a/libc/test/src/math/smoke/float128_test.cpp
+++ b/libc/test/src/math/smoke/float128_test.cpp
@@ -22,7 +22,7 @@ TEST(LlvmLibcFloat128Test, UnaryOperators) {
 
   // comparison operators
   ASSERT_TRUE(a == b);
-  ASSERT_TRUE(a == Float128(1.0));
+  // ASSERT_TRUE(a == Float128(1.0));
   ASSERT_TRUE(a != c);
   ASSERT_TRUE(b != c);
   ASSERT_TRUE(c > b);
@@ -30,16 +30,16 @@ TEST(LlvmLibcFloat128Test, UnaryOperators) {
   ASSERT_TRUE(b <= c);
   ASSERT_TRUE(a < c);
 
-  //negation 
-  Float128 pa(1.0),na(-1.0f);
-  ASSERT_TRUE(-pa == na);
-  ASSERT_TRUE(-(-pa)== -na);
+  // //negation 
+  // Float128 pa(1.0),na(-1.0f);
+  // ASSERT_TRUE(-pa == na);
+  // ASSERT_TRUE(-(-pa)== -na);
 }
 
 TEST(LlvmLibcFloat128Test, BinaryOperators) {
-  Float128 a(1.0f), b(1.0f), c(2.0f), d(3.0);
+  Float128 a(1.0f), b(1.0f), c(2.0f), d(3.0f);
   ASSERT_TRUE((a + b) == c);
-  ASSERT_TRUE((a - b) == Float128(0.0));
-  ASSERT_TRUE((c * d) == Float128(6.0));
-  ASSERT_TRUE((Float128(6.0) / d) == Float128(2.0));
+  ASSERT_TRUE((a - b) == Float128(0.0f));
+  ASSERT_TRUE((c * d) == Float128(6.0f));
+  ASSERT_TRUE((Float128(6.0f) / d) == Float128(2.0f));
 }

>From 5f68af7d0f24da1c44a1f3ec2a71f509bff3ee3b Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 11 Jun 2026 20:59:53 +0530
Subject: [PATCH 17/28] testing intype = outType

---
 libc/src/__support/FPUtil/generic/add_sub.h | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/libc/src/__support/FPUtil/generic/add_sub.h b/libc/src/__support/FPUtil/generic/add_sub.h
index 0a2208f43cf05..729b4afc9afca 100644
--- a/libc/src/__support/FPUtil/generic/add_sub.h
+++ b/libc/src/__support/FPUtil/generic/add_sub.h
@@ -110,15 +110,7 @@ add_or_sub(InType x, InType y) {
 #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
       }
 
-      if constexpr (cpp::is_same_v<InType, bfloat16> &&
-                    cpp::is_same_v<OutType, bfloat16>) {
-        OutFPBits out_y_bits(y);
-        if constexpr (IsSub)
-          out_y_bits.set_sign(out_y_bits.sign().negate());
-        return out_y_bits.get_val();
-      }
-      else if constexpr (cpp::is_same_v<InType, Float128> &&
-                    cpp::is_same_v<OutType, Float128>) {
+      if constexpr (cpp::is_same_v<InType, OutType>) {
         OutFPBits out_y_bits(y);
         if constexpr (IsSub)
           out_y_bits.set_sign(out_y_bits.sign().negate());

>From ce5183af3108151496a53aa44569afba99a01b3b Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 11 Jun 2026 21:08:11 +0530
Subject: [PATCH 18/28] removed checker for LIBC_USE_CONSTEXPR

---
 libc/src/__support/FPUtil/generic/add_sub.h | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/libc/src/__support/FPUtil/generic/add_sub.h b/libc/src/__support/FPUtil/generic/add_sub.h
index 729b4afc9afca..bdec242f4a591 100644
--- a/libc/src/__support/FPUtil/generic/add_sub.h
+++ b/libc/src/__support/FPUtil/generic/add_sub.h
@@ -115,17 +115,11 @@ add_or_sub(InType x, InType y) {
         if constexpr (IsSub)
           out_y_bits.set_sign(out_y_bits.sign().negate());
         return out_y_bits.get_val();
-      }
-      else {
-
-#ifdef LIBC_USE_CONSTEXPR
-        InType tmp = y;
-#else
+      } else {
         // volatile prevents Clang from converting tmp to OutType and then
         // immediately back to InType before negating it, resulting in double
         // rounding.
         volatile InType tmp = y;
-#endif // LIBC_USE_CONSTEXPR
         if constexpr (IsSub)
           tmp = -tmp;
         return cast<OutType>(tmp);

>From 227f09acfb323475a4d0c39561dff7431a4f7ca2 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 18 Jun 2026 18:39:29 +0530
Subject: [PATCH 19/28] int conversion + tests

temporary tests

clang-format

int conversion testing
---
 libc/src/__support/FPUtil/bfloat16.h       | 10 ++--
 libc/src/__support/FPUtil/float128.h       | 57 ++++++++++++++++------
 libc/test/src/math/smoke/float128_test.cpp | 36 +++++++++++++-
 3 files changed, 82 insertions(+), 21 deletions(-)

diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index 8a3f3c9894aad..d7889843ac736 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -136,12 +136,10 @@ struct BFloat16 {
 } // namespace LIBC_NAMESPACE_DECL
 
 // <--To be removed------------------------------------>
-static_assert(
-    LIBC_NAMESPACE::cpp::is_trivially_constructible<
-        LIBC_NAMESPACE::fputil::BFloat16>::value);
-static_assert(
-    LIBC_NAMESPACE::cpp::is_trivially_copyable<
-        LIBC_NAMESPACE::fputil::BFloat16>::value);
+static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible<
+              LIBC_NAMESPACE::fputil::BFloat16>::value);
+static_assert(LIBC_NAMESPACE::cpp::is_trivially_copyable<
+              LIBC_NAMESPACE::fputil::BFloat16>::value);
 // ----------------------------------------------------
 
 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_BFLOAT16_H
diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index 663d54a8de01e..642e348220a29 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -9,18 +9,18 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
 #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
 
+#include "hdr/stdint_proxy.h"
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/FPUtil/cast.h"
 #include "src/__support/FPUtil/comparison_operations.h"
-#include "src/__support/macros/attributes.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/uint128.h"
-#include <stdint.h>
-#include "hdr/stdint_proxy.h"
 #include "src/__support/FPUtil/dyadic_float.h"
 #include "src/__support/FPUtil/generic/add_sub.h"
 #include "src/__support/FPUtil/generic/div.h"
 #include "src/__support/FPUtil/generic/mul.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/uint128.h"
+#include <stdint.h>
 
 namespace LIBC_NAMESPACE_DECL {
 namespace fputil {
@@ -34,7 +34,7 @@ struct Float128 {
   LIBC_INLINE constexpr Float128 &operator=(const Float128 &) = default;
   LIBC_INLINE constexpr Float128 &operator=(Float128 &&) = default;
 
-  // Floating point type and integer type 
+  // Floating point type and integer type
   template <typename T>
   LIBC_INLINE constexpr explicit Float128(T value)
       : bits(static_cast<UInt128>(0U)) {
@@ -67,7 +67,21 @@ struct Float128 {
   LIBC_INLINE LIBC_CONSTEXPR_DEFAULT operator T() const {
     return fputil::cast<T>(*this);
   }
-// TODO: Integer conversion
+
+  // Integer conversion (Incomplete + not verified with tests)
+  template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
+  LIBC_INLINE constexpr explicit operator T() const {
+    fputil::FPBits<Float128> x_bits(*this);
+    if (x_bits.is_zero())
+      return static_cast<T>(0);
+
+    fputil::DyadicFloat<fputil::FPBits<Float128>::STORAGE_LEN> xd(
+        x_bits.sign(),
+        x_bits.get_explicit_exponent() - fputil::FPBits<Float128>::FRACTION_LEN,
+        x_bits.get_explicit_mantissa());
+    return static_cast<T>(xd.as_mantissa_type_rounded());
+  }
+
   // unary
   LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR Float128 operator-() const {
     fputil::FPBits<Float128> result(*this);
@@ -75,7 +89,7 @@ struct Float128 {
     return result.get_val();
   }
   // operator overloads
-    LIBC_INLINE constexpr Float128 operator+(const Float128 &other) const {
+  LIBC_INLINE constexpr Float128 operator+(const Float128 &other) const {
     return fputil::generic::add<Float128>(*this, other);
   }
 
@@ -114,17 +128,32 @@ struct Float128 {
   LIBC_INLINE constexpr bool operator>=(const Float128 &other) const {
     return fputil::greater_than_or_equals(*this, other);
   }
+
+  LIBC_INLINE constexpr Float128 &operator*=(const Float128 &other) {
+    *this = *this * other;
+    return *this;
+  }
+  LIBC_INLINE constexpr Float128 &operator+=(const Float128 &other) {
+    *this = *this + other;
+    return *this;
+  }
+  LIBC_INLINE constexpr Float128 &operator-=(const Float128 &other) {
+    *this = *this - other;
+    return *this;
+  }
+  LIBC_INLINE constexpr Float128 &operator/=(const Float128 &other) {
+    *this = *this / other;
+    return *this;
+  }
 };
 
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 
 // <--To be removed------------------------------------>
-static_assert(
-    LIBC_NAMESPACE::cpp::is_trivially_constructible<
-        LIBC_NAMESPACE::fputil::Float128>::value);
-static_assert(
-    LIBC_NAMESPACE::cpp::is_trivially_copyable<
-        LIBC_NAMESPACE::fputil::Float128>::value);
+static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible<
+              LIBC_NAMESPACE::fputil::Float128>::value);
+static_assert(LIBC_NAMESPACE::cpp::is_trivially_copyable<
+              LIBC_NAMESPACE::fputil::Float128>::value);
 // ----------------------------------------------------
 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
diff --git a/libc/test/src/math/smoke/float128_test.cpp b/libc/test/src/math/smoke/float128_test.cpp
index 41323bccb3467..0e4126edd91be 100644
--- a/libc/test/src/math/smoke/float128_test.cpp
+++ b/libc/test/src/math/smoke/float128_test.cpp
@@ -30,7 +30,7 @@ TEST(LlvmLibcFloat128Test, UnaryOperators) {
   ASSERT_TRUE(b <= c);
   ASSERT_TRUE(a < c);
 
-  // //negation 
+  // //negation
   // Float128 pa(1.0),na(-1.0f);
   // ASSERT_TRUE(-pa == na);
   // ASSERT_TRUE(-(-pa)== -na);
@@ -43,3 +43,37 @@ TEST(LlvmLibcFloat128Test, BinaryOperators) {
   ASSERT_TRUE((c * d) == Float128(6.0f));
   ASSERT_TRUE((Float128(6.0f) / d) == Float128(2.0f));
 }
+
+TEST(LlvmLibcFloat128Test, Negation) {
+  Float128 pa(1.0f), na(-1.0f);
+  ASSERT_TRUE(-pa == na);
+  ASSERT_TRUE(-(-pa) == pa);
+  ASSERT_TRUE(-na == pa);
+}
+
+TEST(LlvmLibcFloat128Test, CompoundAssignment) {
+  Float128 a(1.0f), b(2.0f), c(3.0f), d(4.0f);
+
+  a += Float128(2.0f);
+  ASSERT_TRUE(a == c);
+
+  b -= Float128(1.0f);
+  ASSERT_TRUE(b == Float128(1.0f));
+
+  c *= Float128(2.0f);
+  ASSERT_TRUE(c == Float128(6.0f));
+
+  d /= Float128(2.0f);
+  ASSERT_TRUE(d == Float128(2.0f));
+}
+
+TEST(LlvmLibcFloat128Test, IntegerConversion) {
+  ASSERT_EQ(static_cast<int>(Float128(0.0f)), 0);
+  ASSERT_EQ(static_cast<int>(Float128(1.0f)), 1);
+  ASSERT_EQ(static_cast<int>(Float128(-1.0f)), -1);
+  ASSERT_EQ(static_cast<int>(Float128(42.0f)), 42);
+  ASSERT_EQ(static_cast<int>(Float128(-42.0f)), -42);
+  ASSERT_EQ(static_cast<long long>(Float128(123456789.0)),
+            static_cast<long long>(123456789));
+  ASSERT_EQ(static_cast<unsigned>(Float128(7.0f)), 7U);
+}

>From cda4043e3ac32668cccefab9ce5358f8eb589046 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 18 Jun 2026 19:41:55 +0530
Subject: [PATCH 20/28] int conversion

---
 libc/src/__support/FPUtil/float128.h       | 11 +++++------
 libc/test/src/math/smoke/float128_test.cpp |  2 +-
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index 642e348220a29..8f50df91f2486 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -71,13 +71,12 @@ struct Float128 {
   // Integer conversion (Incomplete + not verified with tests)
   template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
   LIBC_INLINE constexpr explicit operator T() const {
-    fputil::FPBits<Float128> x_bits(*this);
-    if (x_bits.is_zero())
-      return static_cast<T>(0);
-
-    fputil::DyadicFloat<fputil::FPBits<Float128>::STORAGE_LEN> xd(
+    FPBits<Float128> x_bits(*this);
+    int  x_bits_exp = x_bits.get_explicit_exponent() - FPBits<Float128>::FRACTION_LEN;
+    // sign * mantissa * 2(exp-bias)
+    DyadicFloat<FPBits<Float128>::STORAGE_LEN> xd(
         x_bits.sign(),
-        x_bits.get_explicit_exponent() - fputil::FPBits<Float128>::FRACTION_LEN,
+       x_bits_exp,
         x_bits.get_explicit_mantissa());
     return static_cast<T>(xd.as_mantissa_type_rounded());
   }
diff --git a/libc/test/src/math/smoke/float128_test.cpp b/libc/test/src/math/smoke/float128_test.cpp
index 0e4126edd91be..0ebcce3248c1f 100644
--- a/libc/test/src/math/smoke/float128_test.cpp
+++ b/libc/test/src/math/smoke/float128_test.cpp
@@ -18,7 +18,7 @@ TEST(LlvmLibcFloat128Test, DefaultConstructor) {
 }
 
 TEST(LlvmLibcFloat128Test, UnaryOperators) {
-  Float128 a(1.0f), b(1.0f), c(2.0f);
+  Float128 a(1.0), b(1.0f), c(2.0f);
 
   // comparison operators
   ASSERT_TRUE(a == b);

>From 287f92ffcab70878b77817e82a97d0ca57f9be56 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Fri, 19 Jun 2026 03:22:56 +0530
Subject: [PATCH 21/28] cleanup and tests

fix for test fails

clang format

cleanup for test
---
 libc/src/__support/FPUtil/bfloat16.h          |  7 --
 libc/src/__support/FPUtil/float128.h          | 12 +--
 libc/src/__support/FPUtil/generic/add_sub.h   |  6 ++
 libc/test/src/__support/FPUtil/CMakeLists.txt | 11 +++
 .../src/__support/FPUtil/float128_test.cpp    | 91 +++++++++++++++++++
 libc/test/src/math/smoke/CMakeLists.txt       | 10 --
 libc/test/src/math/smoke/float128_test.cpp    | 79 ----------------
 7 files changed, 110 insertions(+), 106 deletions(-)
 create mode 100644 libc/test/src/__support/FPUtil/float128_test.cpp
 delete mode 100644 libc/test/src/math/smoke/float128_test.cpp

diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index d7889843ac736..ce4e3160a0963 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -135,11 +135,4 @@ struct BFloat16 {
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 
-// <--To be removed------------------------------------>
-static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible<
-              LIBC_NAMESPACE::fputil::BFloat16>::value);
-static_assert(LIBC_NAMESPACE::cpp::is_trivially_copyable<
-              LIBC_NAMESPACE::fputil::BFloat16>::value);
-// ----------------------------------------------------
-
 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_BFLOAT16_H
diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index 8f50df91f2486..9fdd47bb48597 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -50,8 +50,7 @@ struct Float128 {
         }
       }
 
-      fputil::DyadicFloat<cpp::numeric_limits<cpp::make_unsigned_t<T>>::digits>
-          xd(sign, 0, value);
+      fputil::DyadicFloat<FPBits<Float128>::STORAGE_LEN> xd(sign, 0, value);
       bits = xd.template as<Float128, /*ShouldSignalExceptions=*/true>().bits;
 
     } else if constexpr (cpp::is_convertible_v<T, Float128>) {
@@ -68,7 +67,6 @@ struct Float128 {
     return fputil::cast<T>(*this);
   }
 
-  // Integer conversion (Incomplete + not verified with tests)
   template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
   LIBC_INLINE constexpr explicit operator T() const {
     FPBits<Float128> x_bits(*this);
@@ -78,7 +76,7 @@ struct Float128 {
         x_bits.sign(),
        x_bits_exp,
         x_bits.get_explicit_mantissa());
-    return static_cast<T>(xd.as_mantissa_type_rounded());
+    return static_cast<T>(xd.as_mantissa_type());
   }
 
   // unary
@@ -149,10 +147,4 @@ struct Float128 {
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 
-// <--To be removed------------------------------------>
-static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible<
-              LIBC_NAMESPACE::fputil::Float128>::value);
-static_assert(LIBC_NAMESPACE::cpp::is_trivially_copyable<
-              LIBC_NAMESPACE::fputil::Float128>::value);
-// ----------------------------------------------------
 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOAT128_H
diff --git a/libc/src/__support/FPUtil/generic/add_sub.h b/libc/src/__support/FPUtil/generic/add_sub.h
index bdec242f4a591..71e50daa9a996 100644
--- a/libc/src/__support/FPUtil/generic/add_sub.h
+++ b/libc/src/__support/FPUtil/generic/add_sub.h
@@ -116,10 +116,16 @@ add_or_sub(InType x, InType y) {
           out_y_bits.set_sign(out_y_bits.sign().negate());
         return out_y_bits.get_val();
       } else {
+
+#ifdef LIBC_USE_CONSTEXPR
+        InType tmp = y;
+#else
         // volatile prevents Clang from converting tmp to OutType and then
         // immediately back to InType before negating it, resulting in double
         // rounding.
         volatile InType tmp = y;
+#endif // LIBC_USE_CONSTEXPR
+
         if constexpr (IsSub)
           tmp = -tmp;
         return cast<OutType>(tmp);
diff --git a/libc/test/src/__support/FPUtil/CMakeLists.txt b/libc/test/src/__support/FPUtil/CMakeLists.txt
index 81db4ccae44c6..e38c9bcdc9fcd 100644
--- a/libc/test/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/test/src/__support/FPUtil/CMakeLists.txt
@@ -39,6 +39,17 @@ add_fp_unittest(
     libc.src.__support.FPUtil.rounding_mode
 )
 
+add_libc_test(
+  float128_test
+  SUITE
+    libc-fputil-tests
+  SRCS
+    float128_test.cpp
+  DEPENDS
+    libc.src.__support.FPUtil.float128
+    libc.src.__support.uint128
+)
+
 # TODO: Temporally disable bfloat16 test until MPCommon target is updated
 # https://github.com/llvm/llvm-project/pull/149678
 if(LLVM_LIBC_FULL_BUILD)
diff --git a/libc/test/src/__support/FPUtil/float128_test.cpp b/libc/test/src/__support/FPUtil/float128_test.cpp
new file mode 100644
index 0000000000000..31d852c0c9bab
--- /dev/null
+++ b/libc/test/src/__support/FPUtil/float128_test.cpp
@@ -0,0 +1,91 @@
+//===-- Unittests for Float128 emulated type -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/FPUtil/float128.h"
+#include "test/UnitTest/Test.h"
+
+using LIBC_NAMESPACE::Sign;
+using LIBC_NAMESPACE::fputil::Float128;
+
+TEST(LlvmLibcFloat128Test, Operators) {
+  Float128 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 == Float128(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(-pa == na);
+  ASSERT_TRUE(-(-pa) == pa);
+
+  // Binary operators
+  ASSERT_TRUE((a + b) == c);
+  ASSERT_TRUE((a - b) == Float128(0.0f));
+  ASSERT_TRUE((c * d) == Float128(6.0f));
+  ASSERT_TRUE((Float128(6.0f) / d) == Float128(2.0f));
+
+  // Compound assignment operators
+  a += Float128(1.0f);
+  ASSERT_TRUE(a == c);
+  b -= Float128(1.0f);
+  ASSERT_TRUE(b == Float128(0.0f));
+  c *= Float128(2.0f);
+  ASSERT_TRUE(c == Float128(4.0f));
+  d /= Float128(3.0f);
+  ASSERT_TRUE(d == Float128(1.0f));
+}
+
+TEST(LlvmLibcFloat128Test, SpecialValues) {
+  using FPBits = LIBC_NAMESPACE::fputil::FPBits<Float128>;
+
+  Float128 zero = FPBits::zero(Sign::POS).get_val();
+  Float128 neg_zero = FPBits::zero(Sign::NEG).get_val();
+  Float128 inf = FPBits::inf(Sign::POS).get_val();
+  Float128 neg_inf = FPBits::inf(Sign::NEG).get_val();
+  Float128 nan = FPBits::quiet_nan().get_val();
+
+  // checking operators with special values
+  ASSERT_TRUE(zero == neg_zero); // +0.0 == -0.0 is true
+  ASSERT_TRUE(zero == Float128(0.0f));
+  ASSERT_TRUE(inf == inf);
+  ASSERT_TRUE(-inf == neg_inf);
+  ASSERT_TRUE((inf + Float128(1.0f)) == inf);
+  ASSERT_TRUE(inf + inf == inf);
+  ASSERT_TRUE(nan != nan);
+  ASSERT_TRUE(!(nan == nan));
+  ASSERT_TRUE(nan != zero);
+}
+
+TEST(LlvmLibcFloat128Test, IntegerConversion) {
+  // Float128 to Integer conversion test
+  ASSERT_EQ(static_cast<int>(Float128(0.0f)), 0);
+  ASSERT_EQ(static_cast<int>(Float128(1.0f)), 1);
+  ASSERT_EQ(static_cast<int>(Float128(-1.0)), -1);
+  ASSERT_EQ(static_cast<long long>(Float128(1000000000.0)),
+            static_cast<long long>(1000000000));
+  ASSERT_EQ(static_cast<unsigned>(Float128(7.0f)), 7U);
+  ASSERT_EQ(static_cast<int>(Float128(-1.5)), -1);
+  ASSERT_EQ(static_cast<int>(Float128(-1.9)), -1);
+  ASSERT_EQ(static_cast<int>(Float128(1.9f)), 1);
+}
+
+TEST(LlvmLibcFloat128Test, FromIntegralTypes) {
+  // Integer to float128 conversion test
+  ASSERT_TRUE(Float128(42) == Float128(42.0f));
+  ASSERT_TRUE(Float128(-42) == Float128(-42.0f));
+  ASSERT_TRUE(Float128(0) == Float128(0.0f));
+  ASSERT_TRUE(Float128(7U) == Float128(7.0f));
+  ASSERT_TRUE(Float128(-7LL) == Float128(-7.0));
+  ASSERT_TRUE(Float128(123456789LL) == Float128(123456789.0));
+}
\ No newline at end of file
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 89b131f0a79b5..b763cdb43b31c 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -1,16 +1,6 @@
 add_custom_target(libc-math-smoke-tests)
 add_dependencies(libc-math-unittests libc-math-smoke-tests)
 
-add_libc_unittest(
-  float128_test
-  SUITE
-    libc-math-smoke-tests
-  SRCS
-    float128_test.cpp
-  DEPENDS
-    libc.src.__support.FPUtil.float128
-)
-
 add_fp_unittest(
   cosf_test
   SUITE
diff --git a/libc/test/src/math/smoke/float128_test.cpp b/libc/test/src/math/smoke/float128_test.cpp
deleted file mode 100644
index 0ebcce3248c1f..0000000000000
--- a/libc/test/src/math/smoke/float128_test.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-//===-- Unittests for Float128 emulated type -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "src/__support/FPUtil/float128.h"
-#include "src/__support/uint128.h"
-#include "test/UnitTest/Test.h"
-
-using LIBC_NAMESPACE::fputil::Float128;
-
-TEST(LlvmLibcFloat128Test, DefaultConstructor) {
-  Float128 x;
-  (void)x;
-}
-
-TEST(LlvmLibcFloat128Test, UnaryOperators) {
-  Float128 a(1.0), b(1.0f), c(2.0f);
-
-  // comparison operators
-  ASSERT_TRUE(a == b);
-  // ASSERT_TRUE(a == Float128(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);
-
-  // //negation
-  // Float128 pa(1.0),na(-1.0f);
-  // ASSERT_TRUE(-pa == na);
-  // ASSERT_TRUE(-(-pa)== -na);
-}
-
-TEST(LlvmLibcFloat128Test, BinaryOperators) {
-  Float128 a(1.0f), b(1.0f), c(2.0f), d(3.0f);
-  ASSERT_TRUE((a + b) == c);
-  ASSERT_TRUE((a - b) == Float128(0.0f));
-  ASSERT_TRUE((c * d) == Float128(6.0f));
-  ASSERT_TRUE((Float128(6.0f) / d) == Float128(2.0f));
-}
-
-TEST(LlvmLibcFloat128Test, Negation) {
-  Float128 pa(1.0f), na(-1.0f);
-  ASSERT_TRUE(-pa == na);
-  ASSERT_TRUE(-(-pa) == pa);
-  ASSERT_TRUE(-na == pa);
-}
-
-TEST(LlvmLibcFloat128Test, CompoundAssignment) {
-  Float128 a(1.0f), b(2.0f), c(3.0f), d(4.0f);
-
-  a += Float128(2.0f);
-  ASSERT_TRUE(a == c);
-
-  b -= Float128(1.0f);
-  ASSERT_TRUE(b == Float128(1.0f));
-
-  c *= Float128(2.0f);
-  ASSERT_TRUE(c == Float128(6.0f));
-
-  d /= Float128(2.0f);
-  ASSERT_TRUE(d == Float128(2.0f));
-}
-
-TEST(LlvmLibcFloat128Test, IntegerConversion) {
-  ASSERT_EQ(static_cast<int>(Float128(0.0f)), 0);
-  ASSERT_EQ(static_cast<int>(Float128(1.0f)), 1);
-  ASSERT_EQ(static_cast<int>(Float128(-1.0f)), -1);
-  ASSERT_EQ(static_cast<int>(Float128(42.0f)), 42);
-  ASSERT_EQ(static_cast<int>(Float128(-42.0f)), -42);
-  ASSERT_EQ(static_cast<long long>(Float128(123456789.0)),
-            static_cast<long long>(123456789));
-  ASSERT_EQ(static_cast<unsigned>(Float128(7.0f)), 7U);
-}

>From c579bb07a7ea33e5dd09ead356ece9f1780b2c00 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Wed, 24 Jun 2026 20:54:08 +0530
Subject: [PATCH 22/28] use IEEE754_Binary128 as the container

---
 libc/src/__support/FPUtil/FPBits.h               | 13 ++-----------
 libc/test/src/__support/FPUtil/float128_test.cpp |  2 +-
 2 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 5b7461a44cff5..83219b7573f46 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -37,8 +37,7 @@ enum class FPType {
   IEEE754_Binary64,
   IEEE754_Binary128,
   X86_Binary80,
-  BFloat16,
-  Float128
+  BFloat16
 };
 
 // The classes hierarchy is as follows:
@@ -147,14 +146,6 @@ template <> struct FPLayout<FPType::BFloat16> {
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
 };
 
-template <> struct FPLayout<FPType::Float128> {
-  using StorageType = UInt128;
-  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 = 112;
-  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
-};
-
 // FPStorage derives useful constants from the FPLayout above.
 template <FPType fp_type> struct FPStorage : public FPLayout<fp_type> {
   using UP = FPLayout<fp_type>;
@@ -823,7 +814,7 @@ template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
   else if constexpr (cpp::is_same_v<UnqualT, bfloat16>)
     return FPType::BFloat16;
   else if constexpr (cpp::is_same_v<UnqualT, Float128>)
-    return FPType::Float128;
+    return FPType::IEEE754_Binary128;
   else
     static_assert(cpp::always_false<UnqualT>, "Unsupported type");
 }
diff --git a/libc/test/src/__support/FPUtil/float128_test.cpp b/libc/test/src/__support/FPUtil/float128_test.cpp
index 31d852c0c9bab..de37226034ddd 100644
--- a/libc/test/src/__support/FPUtil/float128_test.cpp
+++ b/libc/test/src/__support/FPUtil/float128_test.cpp
@@ -88,4 +88,4 @@ TEST(LlvmLibcFloat128Test, FromIntegralTypes) {
   ASSERT_TRUE(Float128(7U) == Float128(7.0f));
   ASSERT_TRUE(Float128(-7LL) == Float128(-7.0));
   ASSERT_TRUE(Float128(123456789LL) == Float128(123456789.0));
-}
\ No newline at end of file
+}

>From 5cb3e19d8de617effca834652ca19a75fb3f679f Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Wed, 24 Jun 2026 21:13:01 +0530
Subject: [PATCH 23/28] clang-format

---
 libc/src/__support/FPUtil/float128.h | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index 9fdd47bb48597..50a0f93cbd297 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -70,12 +70,11 @@ struct Float128 {
   template <typename T, cpp::enable_if_t<cpp::is_integral_v<T>, int> = 0>
   LIBC_INLINE constexpr explicit operator T() const {
     FPBits<Float128> x_bits(*this);
-    int  x_bits_exp = x_bits.get_explicit_exponent() - FPBits<Float128>::FRACTION_LEN;
+    int x_bits_exp =
+        x_bits.get_explicit_exponent() - FPBits<Float128>::FRACTION_LEN;
     // sign * mantissa * 2(exp-bias)
     DyadicFloat<FPBits<Float128>::STORAGE_LEN> xd(
-        x_bits.sign(),
-       x_bits_exp,
-        x_bits.get_explicit_mantissa());
+        x_bits.sign(), x_bits_exp, x_bits.get_explicit_mantissa());
     return static_cast<T>(xd.as_mantissa_type());
   }
 

>From a17ceb592a481a381482d7c71d51d453ebe988f7 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Wed, 24 Jun 2026 21:18:43 +0530
Subject: [PATCH 24/28] 1:1 dependency

---
 libc/src/__support/FPUtil/CMakeLists.txt | 11 ++++++++---
 libc/src/__support/FPUtil/float128.h     |  1 -
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index c49d873b026e2..8b6ac8027b52d 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -299,12 +299,17 @@ add_header_library(
   HDRS
     float128.h
   DEPENDS
-    libc.src.__support.CPP.bit
+    .cast
+    .comparison_operations
+    .dyadic_float
+    libc.hdr.stdint_proxy
+    libc.src.__support.CPP.type_traits
+    libc.src.__support.FPUtil.generic.add_sub
+    libc.src.__support.FPUtil.generic.div
+    libc.src.__support.FPUtil.generic.mul
     libc.src.__support.macros.attributes
     libc.src.__support.macros.config
     libc.src.__support.uint128
-    libc.src.__support.CPP.type_traits
-    .comparison_operations
 )
 
 add_subdirectory(generic)
diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index 50a0f93cbd297..cbb113567dc05 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -20,7 +20,6 @@
 #include "src/__support/macros/attributes.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/uint128.h"
-#include <stdint.h>
 
 namespace LIBC_NAMESPACE_DECL {
 namespace fputil {

>From 26cbb5e0c6c98fd302adb4b0001cfa2c42ad2bb9 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 25 Jun 2026 21:02:20 +0530
Subject: [PATCH 25/28]  test: bigInt

---
 libc/src/__support/FPUtil/float128.h | 7 ++++++-
 libc/src/__support/big_int.h         | 7 +++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/libc/src/__support/FPUtil/float128.h b/libc/src/__support/FPUtil/float128.h
index cbb113567dc05..025c8d2170256 100644
--- a/libc/src/__support/FPUtil/float128.h
+++ b/libc/src/__support/FPUtil/float128.h
@@ -141,7 +141,12 @@ struct Float128 {
     return *this;
   }
 };
-
+static_assert(
+    LIBC_NAMESPACE::cpp::is_trivially_constructible<
+        LIBC_NAMESPACE::fputil::Float128>::value);
+static_assert(
+    LIBC_NAMESPACE::cpp::is_trivially_copyable<
+        LIBC_NAMESPACE::fputil::Float128>::value);
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 
diff --git a/libc/src/__support/big_int.h b/libc/src/__support/big_int.h
index 0e5c038ec356e..2fe3c36034b11 100644
--- a/libc/src/__support/big_int.h
+++ b/libc/src/__support/big_int.h
@@ -1389,6 +1389,13 @@ first_trailing_one(T value) {
   return value == 0 ? 0 : cpp::countr_zero(value) + 1;
 }
 
+static_assert(
+    LIBC_NAMESPACE::cpp::is_trivially_constructible<
+        LIBC_NAMESPACE::BigInt<128>>::value);
+static_assert(
+    LIBC_NAMESPACE::cpp::is_trivially_copyable<
+        LIBC_NAMESPACE::BigInt<128>>::value);
+
 } // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC_SRC___SUPPORT_BIG_INT_H

>From 83dd62795328911fd8e08107ea3336057a4f4485 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 25 Jun 2026 21:09:50 +0530
Subject: [PATCH 26/28] arg bit_int

---
 libc/src/__support/big_int.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libc/src/__support/big_int.h b/libc/src/__support/big_int.h
index 2fe3c36034b11..5be9d678c5594 100644
--- a/libc/src/__support/big_int.h
+++ b/libc/src/__support/big_int.h
@@ -1391,10 +1391,10 @@ first_trailing_one(T value) {
 
 static_assert(
     LIBC_NAMESPACE::cpp::is_trivially_constructible<
-        LIBC_NAMESPACE::BigInt<128>>::value);
+        LIBC_NAMESPACE::BigInt<128, false>>::value);
 static_assert(
     LIBC_NAMESPACE::cpp::is_trivially_copyable<
-        LIBC_NAMESPACE::BigInt<128>>::value);
+        LIBC_NAMESPACE::BigInt<128, false>>::value);
 
 } // namespace LIBC_NAMESPACE_DECL
 

>From 92ee15d5eda0b316dec1d6b1bcbbe5442b4b199f Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 25 Jun 2026 21:19:04 +0530
Subject: [PATCH 27/28] force win

---
 libc/src/__support/big_int.h                 | 12 ++++++------
 libc/src/__support/macros/properties/types.h |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/libc/src/__support/big_int.h b/libc/src/__support/big_int.h
index 5be9d678c5594..6c3ce97a93eda 100644
--- a/libc/src/__support/big_int.h
+++ b/libc/src/__support/big_int.h
@@ -1389,12 +1389,12 @@ first_trailing_one(T value) {
   return value == 0 ? 0 : cpp::countr_zero(value) + 1;
 }
 
-static_assert(
-    LIBC_NAMESPACE::cpp::is_trivially_constructible<
-        LIBC_NAMESPACE::BigInt<128, false>>::value);
-static_assert(
-    LIBC_NAMESPACE::cpp::is_trivially_copyable<
-        LIBC_NAMESPACE::BigInt<128, false>>::value);
+// static_assert(
+//     LIBC_NAMESPACE::cpp::is_trivially_constructible<
+//         LIBC_NAMESPACE::BigInt<128, false>>::value);
+// static_assert(
+//     LIBC_NAMESPACE::cpp::is_trivially_copyable<
+//         LIBC_NAMESPACE::BigInt<128, false>>::value);
 
 } // namespace LIBC_NAMESPACE_DECL
 
diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h
index 7b861640c785d..43a8c43b596b1 100644
--- a/libc/src/__support/macros/properties/types.h
+++ b/libc/src/__support/macros/properties/types.h
@@ -42,7 +42,7 @@
 #endif // UINT64_MAX
 
 // int128 / uint128 support
-#if defined(__SIZEOF_INT128__) && !defined(LIBC_TARGET_OS_IS_WINDOWS)
+#if defined(__SIZEOF_INT128__)
 #define LIBC_TYPES_HAS_INT128
 #endif // defined(__SIZEOF_INT128__)
 

>From 21f42497a82f54829753f11ff9c6772129083514 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Thu, 25 Jun 2026 21:45:31 +0530
Subject: [PATCH 28/28] test: big_int Trivially const

---
 libc/src/__support/big_int.h                 | 2 +-
 libc/src/__support/macros/properties/types.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/libc/src/__support/big_int.h b/libc/src/__support/big_int.h
index 6c3ce97a93eda..abf46e4c9f48c 100644
--- a/libc/src/__support/big_int.h
+++ b/libc/src/__support/big_int.h
@@ -358,7 +358,7 @@ struct BigInt {
 
   LIBC_INLINE_VAR static constexpr size_t WORD_COUNT = Bits / WORD_SIZE;
 
-  cpp::array<WordType, WORD_COUNT> val{}; // zero initialized.
+  cpp::array<WordType, WORD_COUNT> val; // zero initialized.
 
   LIBC_INLINE constexpr BigInt() = default;
 
diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h
index 43a8c43b596b1..7b861640c785d 100644
--- a/libc/src/__support/macros/properties/types.h
+++ b/libc/src/__support/macros/properties/types.h
@@ -42,7 +42,7 @@
 #endif // UINT64_MAX
 
 // int128 / uint128 support
-#if defined(__SIZEOF_INT128__)
+#if defined(__SIZEOF_INT128__) && !defined(LIBC_TARGET_OS_IS_WINDOWS)
 #define LIBC_TYPES_HAS_INT128
 #endif // defined(__SIZEOF_INT128__)
 



More information about the libc-commits mailing list