[llvm-branch-commits] [libc] [libc] Make atan2f128 use the emulated float128 type (PR #214980)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Aug 8 12:10:52 PDT 2026


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

>From aaa5f191702c1af37e83f3472f53a4994770fbd3 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 8 Aug 2026 21:22:52 +0530
Subject: [PATCH 1/3] atan2f128

---
 libc/shared/math/atan2f128.h           |  9 +++------
 libc/src/__support/math/CMakeLists.txt |  1 +
 libc/src/__support/math/atan2f128.h    | 19 ++++++++-----------
 libc/src/math/atan2f128.h              |  5 +++++
 libc/src/math/generic/atan2f128.cpp    |  6 +++++-
 libc/src/math/hypotbf16.h              |  2 +-
 libc/test/shared/shared_math_test.cpp  |  4 ++--
 7 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/libc/shared/math/atan2f128.h b/libc/shared/math/atan2f128.h
index d7aee40c69527..19c008e33bde4 100644
--- a/libc/shared/math/atan2f128.h
+++ b/libc/shared/math/atan2f128.h
@@ -9,13 +9,12 @@
 #ifndef LLVM_LIBC_SHARED_MATH_ATAN2F128_H
 #define LLVM_LIBC_SHARED_MATH_ATAN2F128_H
 
-#include "include/llvm-libc-types/float128.h"
-
-#ifdef LIBC_TYPES_HAS_FLOAT128
-
 #include "shared/libc_common.h"
+#include "src/__support/FPUtil/float128.h"
 #include "src/__support/math/atan2f128.h"
 
+using LIBC_NAMESPACE::fputil::Float128;
+
 namespace LIBC_NAMESPACE_DECL {
 namespace shared {
 
@@ -24,6 +23,4 @@ using math::atan2f128;
 } // namespace shared
 } // namespace LIBC_NAMESPACE_DECL
 
-#endif // LIBC_TYPES_HAS_FLOAT128
-
 #endif // LLVM_LIBC_SHARED_MATH_ATAN2F128_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 93d226b807a67..146ef7c4a195e 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -314,6 +314,7 @@ add_header_library(
     atan2f128.h
   DEPENDS
     .atan_utils
+    libc.src.__support.FPUtil.float128
     libc.src.__support.integer_literals
     libc.src.__support.uint128
     libc.src.__support.FPUtil.dyadic_float
diff --git a/libc/src/__support/math/atan2f128.h b/libc/src/__support/math/atan2f128.h
index f99de5be3472c..58e6038d33cf2 100644
--- a/libc/src/__support/math/atan2f128.h
+++ b/libc/src/__support/math/atan2f128.h
@@ -9,19 +9,18 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_MATH_ATAN2F128_H
 #define LLVM_LIBC_SRC___SUPPORT_MATH_ATAN2F128_H
 
-#include "include/llvm-libc-types/float128.h"
-
-#ifdef LIBC_TYPES_HAS_FLOAT128
-
 #include "atan_utils.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/dyadic_float.h"
+#include "src/__support/FPUtil/float128.h"
 #include "src/__support/FPUtil/nearest_integer.h"
 #include "src/__support/integer_literals.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 #include "src/__support/uint128.h"
 
+using LIBC_NAMESPACE::fputil::Float128;
+
 namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
@@ -81,7 +80,7 @@ namespace math {
 // and relative errors bounded by:
 //   |(atan(u) - P(u)) / P(u)| < 2^-114.
 
-LIBC_INLINE float128 atan2f128(float128 y, float128 x) {
+LIBC_INLINE Float128 atan2f128(Float128 y, Float128 x) {
   using DFloat128 = fputil::DyadicFloat<128>;
 
   constexpr DFloat128 ZERO = {Sign::POS, 0, 0_u128};
@@ -106,7 +105,7 @@ LIBC_INLINE float128 atan2f128(float128 y, float128 x) {
       {{MPI, PI_OVER_2}, {MPI, PI_OVER_2}}};
 
   using namespace atan_internal;
-  using FPBits = fputil::FPBits<float128>;
+  using FPBits = fputil::FPBits<Float128>;
   using DFloat128 = fputil::DyadicFloat<128>;
 
   FPBits x_bits(x), y_bits(y);
@@ -151,7 +150,7 @@ LIBC_INLINE float128 atan2f128(float128 y, float128 x) {
       DFloat128 r = EXCEPTS[y_except][x_except][x_sign];
       if (y_sign)
         r.sign = r.sign.negate();
-      return static_cast<float128>(r);
+      return static_cast<Float128>(r);
     }
   }
 
@@ -165,7 +164,7 @@ LIBC_INLINE float128 atan2f128(float128 y, float128 x) {
     DFloat128 result = quick_add(const_term, quotient);
     if (final_sign)
       result.sign = result.sign.negate();
-    return static_cast<float128>(result);
+    return static_cast<Float128>(result);
   }
 
   // Take 24 leading bits of num and den to convert to float for fast division.
@@ -203,13 +202,11 @@ LIBC_INLINE float128 atan2f128(float128 y, float128 x) {
   if (final_sign)
     r.sign = r.sign.negate();
 
-  return static_cast<float128>(r);
+  return static_cast<Float128>(r);
 }
 
 } // namespace math
 
 } // namespace LIBC_NAMESPACE_DECL
 
-#endif // LIBC_TYPES_HAS_FLOAT128
-
 #endif // LLVM_LIBC_SRC___SUPPORT_MATH_ATAN2F128_H
diff --git a/libc/src/math/atan2f128.h b/libc/src/math/atan2f128.h
index 26f7ec624940c..57baca529405e 100644
--- a/libc/src/math/atan2f128.h
+++ b/libc/src/math/atan2f128.h
@@ -9,9 +9,14 @@
 #ifndef LLVM_LIBC_SRC_MATH_ATAN2F128_H
 #define LLVM_LIBC_SRC_MATH_ATAN2F128_H
 
+#include "src/__support/FPUtil/float128.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/properties/types.h"
 
+#ifndef LIBC_TYPES_HAS_FLOAT128
+using float128 = LIBC_NAMESPACE::fputil::Float128;
+#endif // LIBC_TYPES_HAS_FLOAT128
+
 namespace LIBC_NAMESPACE_DECL {
 
 float128 atan2f128(float128 x, float128 y);
diff --git a/libc/src/math/generic/atan2f128.cpp b/libc/src/math/generic/atan2f128.cpp
index ec051ddd4e00b..c3b7d6c0fe178 100644
--- a/libc/src/math/generic/atan2f128.cpp
+++ b/libc/src/math/generic/atan2f128.cpp
@@ -9,10 +9,14 @@
 #include "src/math/atan2f128.h"
 #include "src/__support/math/atan2f128.h"
 
+#ifndef LIBC_TYPES_HAS_FLOAT128
+using float128 = LIBC_NAMESPACE::fputil::Float128;
+#endif // LIBC_TYPES_HAS_FLOAT128
+
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(float128, atan2f128, (float128 y, float128 x)) {
-  return math::atan2f128(y, x);
+  return fputil::cast<float128>(math::atan2f128(Float128(y), Float128(x)));
 }
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/hypotbf16.h b/libc/src/math/hypotbf16.h
index db1365d791dba..d8623ceb3283e 100644
--- a/libc/src/math/hypotbf16.h
+++ b/libc/src/math/hypotbf16.h
@@ -14,7 +14,7 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-bfloat16 hypotbf16(bfloat16 x, bfloat16 y);
+bfloat16 hypotbf16(bfloat16 x, bfloata16 y);
 
 } // namespace LIBC_NAMESPACE_DECL
 
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index 3d52f190f55c1..f0879f83f2b85 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -584,6 +584,8 @@ using LIBC_NAMESPACE::fputil::Float128;
 
 TEST(LlvmLibcSharedMathTest, AllEmuFloat128) {
   EXPECT_FP_EQ(Float128(0.0), LIBC_NAMESPACE::shared::ceilf128(Float128(0.0)));
+  EXPECT_FP_EQ(float128(0.0),
+               LIBC_NAMESPACE::shared::atan2f128(float128(0.0), float128(0.0)));
 }
 
 #ifdef LIBC_TYPES_HAS_FLOAT128
@@ -592,8 +594,6 @@ TEST(LlvmLibcSharedMathTest, AllFloat128) {
   using FPBits = LIBC_NAMESPACE::fputil::FPBits<float128>;
   int exponent;
 
-  EXPECT_FP_EQ(float128(0.0),
-               LIBC_NAMESPACE::shared::atan2f128(float128(0.0), float128(0.0)));
   EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::shared::ffmaf128(
                          float128(0.0), float128(0.0), float128(0.0)));
   EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::shared::fsqrtf128(float128(1.0f)));

>From f0b97df711b7ea83c9fb1901df85a8392eaecc09 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 8 Aug 2026 21:24:59 +0530
Subject: [PATCH 2/3] nit

---
 libc/src/math/hypotbf16.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/math/hypotbf16.h b/libc/src/math/hypotbf16.h
index d8623ceb3283e..db1365d791dba 100644
--- a/libc/src/math/hypotbf16.h
+++ b/libc/src/math/hypotbf16.h
@@ -14,7 +14,7 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-bfloat16 hypotbf16(bfloat16 x, bfloata16 y);
+bfloat16 hypotbf16(bfloat16 x, bfloat16 y);
 
 } // namespace LIBC_NAMESPACE_DECL
 

>From 738bcc6264eae1247b41e9f3b771dbc4661eddcf Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sun, 9 Aug 2026 00:40:36 +0530
Subject: [PATCH 3/3] initial commit

---
 libc/src/__support/math/atan2f128.h         |  6 ++-
 libc/src/math/generic/atan2f128.cpp         |  4 +-
 libc/test/shared/shared_math_test.cpp       |  4 +-
 libc/test/src/math/atan2f128_test.cpp       | 23 ++++----
 libc/test/src/math/smoke/atan2f128_test.cpp | 60 ++++++++++++++-------
 5 files changed, 63 insertions(+), 34 deletions(-)

diff --git a/libc/src/__support/math/atan2f128.h b/libc/src/__support/math/atan2f128.h
index 58e6038d33cf2..662692d876e9c 100644
--- a/libc/src/__support/math/atan2f128.h
+++ b/libc/src/__support/math/atan2f128.h
@@ -129,8 +129,10 @@ LIBC_INLINE Float128 atan2f128(Float128 y, Float128 x) {
   if (LIBC_UNLIKELY(max_exp >= 0x7fffU || min_exp == 0U)) {
     if (x_bits.is_nan() || y_bits.is_nan())
       return FPBits::quiet_nan().get_val();
-    unsigned x_except = x == 0 ? 0 : (FPBits(x_abs).is_inf() ? 2 : 1);
-    unsigned y_except = y == 0 ? 0 : (FPBits(y_abs).is_inf() ? 2 : 1);
+    unsigned x_except =
+        (x == Float128(0)) ? 0 : (FPBits(x_abs).is_inf() ? 2 : 1);
+    unsigned y_except =
+        (y == Float128(0)) ? 0 : (FPBits(y_abs).is_inf() ? 2 : 1);
 
     // Exceptional cases:
     //   EXCEPT[y_except][x_except][x_is_neg]
diff --git a/libc/src/math/generic/atan2f128.cpp b/libc/src/math/generic/atan2f128.cpp
index c3b7d6c0fe178..90d354bf3eac6 100644
--- a/libc/src/math/generic/atan2f128.cpp
+++ b/libc/src/math/generic/atan2f128.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/math/atan2f128.h"
+#include "src/__support/CPP/bit.h"
 #include "src/__support/math/atan2f128.h"
 
 #ifndef LIBC_TYPES_HAS_FLOAT128
@@ -16,7 +17,8 @@ using float128 = LIBC_NAMESPACE::fputil::Float128;
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(float128, atan2f128, (float128 y, float128 x)) {
-  return fputil::cast<float128>(math::atan2f128(Float128(y), Float128(x)));
+  return cpp::bit_cast<float128>(
+      math::atan2f128(Float128(y), Float128(x)).bits);
 }
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index f0879f83f2b85..2aed15338fdf2 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -584,8 +584,8 @@ using LIBC_NAMESPACE::fputil::Float128;
 
 TEST(LlvmLibcSharedMathTest, AllEmuFloat128) {
   EXPECT_FP_EQ(Float128(0.0), LIBC_NAMESPACE::shared::ceilf128(Float128(0.0)));
-  EXPECT_FP_EQ(float128(0.0),
-               LIBC_NAMESPACE::shared::atan2f128(float128(0.0), float128(0.0)));
+  EXPECT_FP_EQ(Float128(0.0),
+               LIBC_NAMESPACE::shared::atan2f128(Float128(0.0), Float128(0.0)));
 }
 
 #ifdef LIBC_TYPES_HAS_FLOAT128
diff --git a/libc/test/src/math/atan2f128_test.cpp b/libc/test/src/math/atan2f128_test.cpp
index 0bfec1bd276ed..0f2bc76b8eaaf 100644
--- a/libc/test/src/math/atan2f128_test.cpp
+++ b/libc/test/src/math/atan2f128_test.cpp
@@ -11,7 +11,8 @@
 #include "test/UnitTest/Test.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-using LlvmLibcAtan2f128Test = LIBC_NAMESPACE::testing::FPTest<float128>;
+using LIBC_NAMESPACE::fputil::Float128;
+using LlvmLibcAtan2f128Test = LIBC_NAMESPACE::testing::FPTest<Float128>;
 using LIBC_NAMESPACE::testing::tlog;
 
 namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
@@ -19,14 +20,14 @@ namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
 TEST_F(LlvmLibcAtan2f128Test, InQuadRange) {
   constexpr StorageType X_COUNT = 123;
   constexpr StorageType X_START =
-      FPBits(static_cast<float128>(0.25q)).uintval();
-  constexpr StorageType X_STOP = FPBits(static_cast<float128>(4.0q)).uintval();
+      FPBits(static_cast<Float128>(0.25q)).uintval();
+  constexpr StorageType X_STOP = FPBits(static_cast<Float128>(4.0q)).uintval();
   constexpr StorageType X_STEP = (X_STOP - X_START) / X_COUNT;
 
   constexpr StorageType Y_COUNT = 137;
   constexpr StorageType Y_START =
-      FPBits(static_cast<float128>(0.25q)).uintval();
-  constexpr StorageType Y_STOP = FPBits(static_cast<float128>(4.0q)).uintval();
+      FPBits(static_cast<Float128>(0.25q)).uintval();
+  constexpr StorageType Y_STOP = FPBits(static_cast<Float128>(4.0q)).uintval();
   constexpr StorageType Y_STEP = (Y_STOP - Y_START) / Y_COUNT;
 
   auto test = [&](mpfr::RoundingMode rounding_mode) {
@@ -37,26 +38,26 @@ TEST_F(LlvmLibcAtan2f128Test, InQuadRange) {
     uint64_t fails = 0;
     uint64_t finite_count = 0;
     uint64_t total_count = 0;
-    float128 failed_x = 0.0, failed_y = 0.0, failed_r = 0.0;
+    Float128 failed_x = 0.0, failed_y = 0.0, failed_r = 0.0;
     double tol = 0.5;
 
     for (StorageType i = 0, v = X_START; i <= X_COUNT; ++i, v += X_STEP) {
-      float128 x = FPBits(v).get_val();
+      Float128 x = FPBits(v).get_val();
       if (FPBits(x).is_inf_or_nan() || x < 0.0q)
         continue;
 
       for (StorageType j = 0, w = Y_START; j <= Y_COUNT; ++j, w += Y_STEP) {
-        float128 y = FPBits(w).get_val();
+        Float128 y = FPBits(w).get_val();
         if (FPBits(y).is_inf_or_nan())
           continue;
 
-        float128 result = LIBC_NAMESPACE::atan2f128(x, y);
+        Float128 result = LIBC_NAMESPACE::atan2f128(x, y);
         ++total_count;
         if (FPBits(result).is_inf_or_nan())
           continue;
 
         ++finite_count;
-        mpfr::BinaryInput<float128> inputs{x, y};
+        mpfr::BinaryInput<Float128> inputs{x, y};
 
         if (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Atan2, inputs,
                                                result, 2.0, rounding_mode)) {
@@ -81,7 +82,7 @@ TEST_F(LlvmLibcAtan2f128Test, InQuadRange) {
            << "   Max ULPs is at most: " << static_cast<uint64_t>(tol) << ".\n";
     }
     if (fails) {
-      mpfr::BinaryInput<float128> inputs{failed_x, failed_y};
+      mpfr::BinaryInput<Float128> inputs{failed_x, failed_y};
       EXPECT_MPFR_MATCH(mpfr::Operation::Atan2, inputs, failed_r, 0.5,
                         rounding_mode);
     }
diff --git a/libc/test/src/math/smoke/atan2f128_test.cpp b/libc/test/src/math/smoke/atan2f128_test.cpp
index 28b15ae71cac8..fc5414ed80637 100644
--- a/libc/test/src/math/smoke/atan2f128_test.cpp
+++ b/libc/test/src/math/smoke/atan2f128_test.cpp
@@ -6,28 +6,52 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/integer_literals.h"
 #include "src/math/atan2f128.h"
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 
-using LlvmLibcAtan2f128Test = LIBC_NAMESPACE::testing::FPTest<float128>;
+using LIBC_NAMESPACE::fputil::Float128;
+using LIBC_NAMESPACE::operator""_u128;
+
+// The public atan2f128 returns the native float128; reinterpret its bits
+// directly so the comparison never goes through a value conversion.
+using NativeFPBits = LIBC_NAMESPACE::fputil::FPBits<float128>;
+
+using LlvmLibcAtan2f128Test = LIBC_NAMESPACE::testing::FPTest<Float128>;
 
 TEST_F(LlvmLibcAtan2f128Test, SpecialNumbers) {
-  EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atan2f128(aNaN, zero));
-  EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atan2f128(1.0, aNaN));
-  EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::atan2f128(zero, zero));
-  EXPECT_FP_EQ_ALL_ROUNDING(neg_zero,
-                            LIBC_NAMESPACE::atan2f128(neg_zero, zero));
-  EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::atan2f128(1.0, inf));
-  EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, LIBC_NAMESPACE::atan2f128(-1.0, inf));
-
-  float128 x = 0x1.ffffffffffffffffffffffffffe7p1q;
-  float128 y = 0x1.fffffffffffffffffffffffffff2p1q;
-  float128 r = 0x1.921fb54442d18469898cc51701b3p-1q;
-  EXPECT_FP_EQ(r, LIBC_NAMESPACE::atan2f128(x, y));
-
-  x = -0x1.f122e07fff556143p+3524q;
-  y = 0x1.f122e07fff55615b75p+6316q;
-  r = -0x1.ffffffffffffffe6cfcdc604fc99p-2793q;
-  EXPECT_FP_EQ(r, LIBC_NAMESPACE::atan2f128(x, y));
+  EXPECT_FP_EQ_ALL_ROUNDING(aNaN,
+                            Float128(LIBC_NAMESPACE::atan2f128(aNaN, zero)));
+  EXPECT_FP_EQ_ALL_ROUNDING(
+      aNaN, Float128(LIBC_NAMESPACE::atan2f128(Float128(1.0), aNaN)));
+  EXPECT_FP_EQ_ALL_ROUNDING(zero,
+                            Float128(LIBC_NAMESPACE::atan2f128(zero, zero)));
+  EXPECT_FP_EQ_ALL_ROUNDING(
+      neg_zero, Float128(LIBC_NAMESPACE::atan2f128(neg_zero, zero)));
+  EXPECT_FP_EQ_ALL_ROUNDING(
+      zero, Float128(LIBC_NAMESPACE::atan2f128(Float128(1.0), inf)));
+  EXPECT_FP_EQ_ALL_ROUNDING(
+      neg_zero, Float128(LIBC_NAMESPACE::atan2f128(Float128(-1.0), inf)));
+
+  Float128 x, y, r, actual;
+
+  // 0x1.ffffffffffffffffffffffffffe7p1
+  x.bits = 0x4000FFFFFFFFFFFFFFFFFFFFFFFFFFE7_u128;
+  // 0x1.fffffffffffffffffffffffffff2p1
+  y.bits = 0x4000FFFFFFFFFFFFFFFFFFFFFFFFFFF2_u128;
+  // 0x1.921fb54442d18469898cc51701b3p-1
+  r.bits = 0x3FFE921FB54442D18469898CC51701B3_u128;
+  actual.bits = NativeFPBits(LIBC_NAMESPACE::atan2f128(x, y)).uintval();
+  EXPECT_FP_EQ(r, actual);
+
+  // -0x1.f122e07fff556143p+3524
+  x.bits = 0xCDC3F122E07FFF556143000000000000_u128;
+  // 0x1.f122e07fff55615b75p+6316
+  y.bits = 0x58ABF122E07FFF55615B750000000000_u128;
+  // -0x1.ffffffffffffffe6cfcdc604fc99p-2793
+  r.bits = 0xB516FFFFFFFFFFFFFFE6CFCDC604FC99_u128;
+  actual.bits = NativeFPBits(LIBC_NAMESPACE::atan2f128(x, y)).uintval();
+  EXPECT_FP_EQ(r, actual);
 }



More information about the llvm-branch-commits mailing list