[libc-commits] [libc] [libc][math] Add initial support for C23 float128 math functions, starting with copysignf128. (PR #71731)

via libc-commits libc-commits at lists.llvm.org
Wed Nov 8 12:18:28 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: None (lntue)

<details>
<summary>Changes</summary>



---
Full diff: https://github.com/llvm/llvm-project/pull/71731.diff


18 Files Affected:

- (modified) libc/CMakeLists.txt (+1) 
- (added) libc/cmake/modules/check_compiler_features.cmake (+59) 
- (added) libc/cmake/modules/compiler_features/check_float128.cpp (+5) 
- (added) libc/cmake/modules/compiler_features/check_float16.cpp (+5) 
- (modified) libc/config/linux/x86_64/entrypoints.txt (+7) 
- (modified) libc/spec/spec.td (+3) 
- (modified) libc/spec/stdc.td (+1) 
- (modified) libc/src/__support/CPP/type_traits/is_floating_point.h (+6) 
- (modified) libc/src/__support/FPUtil/FloatProperties.h (+31) 
- (modified) libc/src/__support/macros/properties/compiler.h (+19) 
- (modified) libc/src/math/CMakeLists.txt (+1) 
- (added) libc/src/math/copysignf128.h (+20) 
- (modified) libc/src/math/generic/CMakeLists.txt (+15-3) 
- (added) libc/src/math/generic/copysignf128.cpp (+20) 
- (modified) libc/test/src/__support/FPUtil/fpbits_test.cpp (+72) 
- (modified) libc/test/src/math/smoke/CMakeLists.txt (+16) 
- (modified) libc/test/src/math/smoke/CopySignTest.h (+11-10) 
- (added) libc/test/src/math/smoke/copysignf128_test.cpp (+13) 


``````````diff
diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index 414be906336bf3f..60a68dc616c9ecb 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -245,6 +245,7 @@ option(LIBC_INCLUDE_DOCS "Build the libc documentation." ${LLVM_INCLUDE_DOCS})
 
 include(CMakeParseArguments)
 include(LLVMLibCCheckCpuFeatures)
+include(check_compiler_features)
 include(LLVMLibCRules)
 
 if(EXISTS "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}/entrypoints.txt")
diff --git a/libc/cmake/modules/check_compiler_features.cmake b/libc/cmake/modules/check_compiler_features.cmake
new file mode 100644
index 000000000000000..61db94d1b202ecb
--- /dev/null
+++ b/libc/cmake/modules/check_compiler_features.cmake
@@ -0,0 +1,59 @@
+# ------------------------------------------------------------------------------
+# Compiler features definition and flags
+# ------------------------------------------------------------------------------
+
+# Initialize ALL_COMPILER_FEATURES as empty list.
+set(ALL_COMPILER_FEATURES "float16;float128")
+
+# Making sure ALL_COMPILER_FEATURES is sorted.
+list(SORT ALL_COMPILER_FEATURES)
+
+# Function to check whether the compiler supports the provided set of features.
+# Usage:
+# compiler_supports(
+#   <output variable>
+#   <list of cpu features>
+# )
+function(compiler_supports output_var features)
+  _intersection(var "${LIBC_CPU_FEATURES}" "${features}")
+  if("${var}" STREQUAL "${features}")
+    set(${output_var} TRUE PARENT_SCOPE)
+  else()
+    unset(${output_var} PARENT_SCOPE)
+  endif()
+endfunction()
+
+# ------------------------------------------------------------------------------
+# Internal helpers and utilities.
+# ------------------------------------------------------------------------------
+
+# Computes the intersection between two lists.
+function(_intersection output_var list1 list2)
+  foreach(element IN LISTS list1)
+    if("${list2}" MATCHES "(^|;)${element}(;|$)")
+      list(APPEND tmp "${element}")
+    endif()
+  endforeach()
+  set(${output_var} ${tmp} PARENT_SCOPE)
+endfunction()
+
+set(AVAILABLE_COMPILER_FEATURES "")
+
+# Try compile a C file to check if flag is supported.
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+foreach(feature IN LISTS ALL_COMPILER_FEATURES)
+  try_compile(
+    has_feature
+    ${CMAKE_CURRENT_BINARY_DIR}/compiler_features
+    SOURCES ${LIBC_SOURCE_DIR}/cmake/modules/compiler_features/check_${feature}.cpp
+    COMPILE_DEFINITIONS -I${LIBC_SOURCE_DIR} ${LIBC_COMPILE_OPTIONS_NATIVE}
+  )
+  if(has_feature)
+    list(APPEND AVAILABLE_COMPILER_FEATURES ${feature})
+    if(${feature} STREQUAL "float128")
+      set(LIBC_COMPILER_HAS_FLOAT128 TRUE)
+    endif()
+  endif()
+endforeach()
+
+message(STATUS "Compiler features available: ${AVAILABLE_COMPILER_FEATURES}")
diff --git a/libc/cmake/modules/compiler_features/check_float128.cpp b/libc/cmake/modules/compiler_features/check_float128.cpp
new file mode 100644
index 000000000000000..1dcfe80da0a0eb1
--- /dev/null
+++ b/libc/cmake/modules/compiler_features/check_float128.cpp
@@ -0,0 +1,5 @@
+#include "src/__support/macros/properties/compiler.h"
+
+#ifndef LIBC_COMPILER_HAS_FLOAT128
+#error unsupported
+#endif
diff --git a/libc/cmake/modules/compiler_features/check_float16.cpp b/libc/cmake/modules/compiler_features/check_float16.cpp
new file mode 100644
index 000000000000000..33d0da621b18ade
--- /dev/null
+++ b/libc/cmake/modules/compiler_features/check_float16.cpp
@@ -0,0 +1,5 @@
+#include "src/__support/macros/properties/compiler.h"
+
+#ifndef LIBC_COMPILER_HAS_FLOAT16
+#error unsupported
+#endif
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 31ea282edb59126..83bc8461999ed66 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -360,6 +360,13 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.truncl
 )
 
+if(LIBC_COMPILER_HAS_FLOAT128)
+  list(APPEND TARGET_LIBM_ENTRYPOINTS
+    # math.h C23 _Float128 entrypoints
+    libc.src.math.copysignf128
+  )
+endif()
+
 if(LLVM_LIBC_FULL_BUILD)
   list(APPEND TARGET_LIBC_ENTRYPOINTS
     # assert.h entrypoints
diff --git a/libc/spec/spec.td b/libc/spec/spec.td
index ac0fba3bd0af788..981507a05412a14 100644
--- a/libc/spec/spec.td
+++ b/libc/spec/spec.td
@@ -50,6 +50,9 @@ def DoubleType : NamedType<"double">;
 def LongDoubleType : NamedType<"long double">;
 def CharType : NamedType<"char">;
 
+// TODO: Add compatibility layer to use C23 type _Float128 if possible.
+def Float128Type : NamedType<"__float128">
+
 // Common types
 def VoidPtr : PtrType<VoidType>;
 def VoidPtrPtr : PtrType<VoidPtr>;
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 239d8f9843cfc0f..4e38cb742d2844e 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -358,6 +358,7 @@ def StdC : StandardSpec<"stdc"> {
           FunctionSpec<"copysign", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
           FunctionSpec<"copysignf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
           FunctionSpec<"copysignl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
+          FunctionSpec<"copysignf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>]>,
 
           FunctionSpec<"ceil", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
           FunctionSpec<"ceilf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
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 2df75a072c3606c..bcd204102997540 100644
--- a/libc/src/__support/CPP/type_traits/is_floating_point.h
+++ b/libc/src/__support/CPP/type_traits/is_floating_point.h
@@ -11,6 +11,7 @@
 #include "src/__support/CPP/type_traits/is_same.h"
 #include "src/__support/CPP/type_traits/remove_cv.h"
 #include "src/__support/macros/attributes.h"
+#include "src/__support/macros/properties/compiler.h"
 
 namespace LIBC_NAMESPACE::cpp {
 
@@ -23,8 +24,13 @@ template <typename T> struct is_floating_point {
   }
 
 public:
+#if defined(LIBC_COMPILER_HAS_FLOAT128)
+  LIBC_INLINE_VAR static constexpr bool value =
+      __is_unqualified_any_of<T, float, double, long double, float128>();
+#else
   LIBC_INLINE_VAR static constexpr bool value =
       __is_unqualified_any_of<T, float, double, long double>();
+#endif // LIBC_COMPILER_HAS_FLOAT128
 };
 template <typename T>
 LIBC_INLINE_VAR constexpr bool is_floating_point_v =
diff --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h
index c1d58a87101afc1..8f7f985108c85c3 100644
--- a/libc/src/__support/FPUtil/FloatProperties.h
+++ b/libc/src/__support/FPUtil/FloatProperties.h
@@ -175,6 +175,37 @@ template <> struct FloatProperties<long double> {
 };
 #endif
 
+#if defined(LIBC_COMPILER_HAS_FLOAT128)
+// Properties for numbers represented in 128 bits long double on non x86
+// platform.
+template <> struct FloatProperties<float128> {
+  typedef UInt128 BitsType;
+  static_assert(sizeof(BitsType) == sizeof(float128),
+                "Unexpected size of 'float128' type.");
+
+  static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3;
+
+  static constexpr uint32_t MANTISSA_WIDTH = 112;
+  static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
+  static constexpr uint32_t EXPONENT_WIDTH = 15;
+  static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
+  static constexpr BitsType SIGN_MASK = BitsType(1)
+                                        << (EXPONENT_WIDTH + MANTISSA_WIDTH);
+  static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
+  static constexpr uint32_t EXPONENT_BIAS = 16383;
+
+  static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK | EXPONENT_MASK;
+  static_assert(EXP_MANT_MASK == ~SIGN_MASK,
+                "Exponent and mantissa masks are not as expected.");
+
+  // If a number x is a NAN, then it is a quiet NAN if:
+  //   QuietNaNMask & bits(x) != 0
+  // Else, it is a signalling NAN.
+  static constexpr BitsType QUIET_NAN_MASK = BitsType(1)
+                                             << (MANTISSA_WIDTH - 1);
+};
+#endif // LIBC_COMPILER_HAS_FLOAT128
+
 // Define the float type corresponding to the BitsType.
 template <typename BitsType> struct FloatType;
 
diff --git a/libc/src/__support/macros/properties/compiler.h b/libc/src/__support/macros/properties/compiler.h
index a7a2822bf6a14a6..eb3c28693a50623 100644
--- a/libc/src/__support/macros/properties/compiler.h
+++ b/libc/src/__support/macros/properties/compiler.h
@@ -21,4 +21,23 @@
 #define LIBC_COMPILER_IS_MSC
 #endif
 
+// Check compiler features
+#if defined(FLT128_MANT_DIG)
+// C23 _Float128 type is available.
+#define LIBC_COMPILER_HAS_FLOAT128
+#define LIBC_FLOAT128_IS_C23
+using float128 = _Float128;
+
+#elif defined(__SIZEOF_FLOAT128__)
+// Builtin __float128 is available.
+#define LIBC_COMPILER_HAS_FLOAT128
+#define LIBC_FLOAT128_IS_BUILTIN
+using float128 = __float128;
+
+#endif
+
+#if defined(FLT16_MANT_DIG)
+#define LIBC_COMPILER_HAS_FLOAT16
+#endif
+
 #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_COMPILER_H
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index f1f72714981a9e5..4aea54c7a457547 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -80,6 +80,7 @@ add_math_entrypoint_object(ceill)
 add_math_entrypoint_object(copysign)
 add_math_entrypoint_object(copysignf)
 add_math_entrypoint_object(copysignl)
+add_math_entrypoint_object(copysignf128)
 
 add_math_entrypoint_object(cos)
 add_math_entrypoint_object(cosf)
diff --git a/libc/src/math/copysignf128.h b/libc/src/math/copysignf128.h
new file mode 100644
index 000000000000000..9448d8205dd7523
--- /dev/null
+++ b/libc/src/math/copysignf128.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for copysignf128 ------------------*- 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_MATH_COPYSIGNF128_H
+#define LLVM_LIBC_SRC_MATH_COPYSIGNF128_H
+
+#include "src/__support/macros/properties/compiler.h"
+
+namespace LIBC_NAMESPACE {
+
+float128 copysignf128(float128 x, float128 y);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_COPYSIGN_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 693887c165ce98c..7ac365f55bb6f83 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -806,7 +806,7 @@ add_entrypoint_object(
   DEPENDS
     libc.src.__support.FPUtil.manipulation_functions
   COMPILE_OPTIONS
-    -O2
+    -O3
 )
 
 add_entrypoint_object(
@@ -818,7 +818,7 @@ add_entrypoint_object(
   DEPENDS
     libc.src.__support.FPUtil.manipulation_functions
   COMPILE_OPTIONS
-    -O2
+    -O3
 )
 
 add_entrypoint_object(
@@ -830,7 +830,19 @@ add_entrypoint_object(
   DEPENDS
     libc.src.__support.FPUtil.manipulation_functions
   COMPILE_OPTIONS
-    -O2
+    -O3
+)
+
+add_entrypoint_object(
+  copysignf128
+  SRCS
+    copysignf128.cpp
+  HDRS
+    ../copysignf128.h
+  DEPENDS
+    libc.src.__support.FPUtil.manipulation_functions
+  COMPILE_OPTIONS
+    -O3
 )
 
 add_entrypoint_object(
diff --git a/libc/src/math/generic/copysignf128.cpp b/libc/src/math/generic/copysignf128.cpp
new file mode 100644
index 000000000000000..07e5caa223a5345
--- /dev/null
+++ b/libc/src/math/generic/copysignf128.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of copysignf128 function ---------------------------===//
+//
+// 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/math/copysignf128.h"
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/properties/compiler.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float128, copysignf128, (float128 x, float128 y)) {
+  return fputil::copysign(x, y);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/test/src/__support/FPUtil/fpbits_test.cpp b/libc/test/src/__support/FPUtil/fpbits_test.cpp
index 5c97ba3a70ca795..027db8807ab226a 100644
--- a/libc/test/src/__support/FPUtil/fpbits_test.cpp
+++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp
@@ -287,3 +287,75 @@ TEST(LlvmLibcFPBitsTest, LongDoubleType) {
 #endif
 }
 #endif
+
+#if defined(LIBC_COMPILER_HAS_FLOAT128)
+TEST(LlvmLibcFPBitsTest, Float128Type) {
+  using Float128Bits = FPBits<float128>;
+
+  EXPECT_STREQ(LIBC_NAMESPACE::str(Float128Bits(Float128Bits::inf())).c_str(),
+               "(+Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(Float128Bits(Float128Bits::neg_inf())).c_str(),
+      "(-Infinity)");
+  EXPECT_STREQ(
+      LIBC_NAMESPACE::str(Float128Bits(Float128Bits::build_nan(1))).c_str(),
+      "(NaN)");
+
+  Float128Bits zero(Float128Bits::zero());
+  EXPECT_EQ(zero.get_sign(), false);
+  EXPECT_EQ(zero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
+  EXPECT_EQ(zero.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
+                                     << 64);
+  EXPECT_EQ(zero.uintval(), static_cast<UInt128>(0x0000000000000000) << 64);
+  EXPECT_STREQ(LIBC_NAMESPACE::str(zero).c_str(),
+               "0x00000000000000000000000000000000 = "
+               "(S: 0, E: 0x0000, M: 0x00000000000000000000000000000000)");
+
+  Float128Bits negzero(Float128Bits::neg_zero());
+  EXPECT_EQ(negzero.get_sign(), true);
+  EXPECT_EQ(negzero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
+  EXPECT_EQ(negzero.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
+                                        << 64);
+  EXPECT_EQ(negzero.uintval(), static_cast<UInt128>(0x1) << 127);
+  EXPECT_STREQ(LIBC_NAMESPACE::str(negzero).c_str(),
+               "0x80000000000000000000000000000000 = "
+               "(S: 1, E: 0x0000, M: 0x00000000000000000000000000000000)");
+
+  Float128Bits one(float128(1.0));
+  EXPECT_EQ(one.get_sign(), false);
+  EXPECT_EQ(one.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(one.get_mantissa(), static_cast<UInt128>(0x0000000000000000) << 64);
+  EXPECT_EQ(one.uintval(), static_cast<UInt128>(0x3FFF) << 112);
+  EXPECT_STREQ(LIBC_NAMESPACE::str(one).c_str(),
+               "0x3FFF0000000000000000000000000000 = "
+               "(S: 0, E: 0x3FFF, M: 0x00000000000000000000000000000000)");
+
+  Float128Bits negone(float128(-1.0));
+  EXPECT_EQ(negone.get_sign(), true);
+  EXPECT_EQ(negone.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(negone.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
+                                       << 64);
+  EXPECT_EQ(negone.uintval(), static_cast<UInt128>(0xBFFF) << 112);
+  EXPECT_STREQ(LIBC_NAMESPACE::str(negone).c_str(),
+               "0xBFFF0000000000000000000000000000 = "
+               "(S: 1, E: 0x3FFF, M: 0x00000000000000000000000000000000)");
+
+  Float128Bits num(float128(1.125));
+  EXPECT_EQ(num.get_sign(), false);
+  EXPECT_EQ(num.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(num.get_mantissa(), static_cast<UInt128>(0x2) << 108);
+  EXPECT_EQ(num.uintval(), static_cast<UInt128>(0x3FFF2) << 108);
+  EXPECT_STREQ(LIBC_NAMESPACE::str(num).c_str(),
+               "0x3FFF2000000000000000000000000000 = "
+               "(S: 0, E: 0x3FFF, M: 0x00002000000000000000000000000000)");
+
+  Float128Bits negnum(float128(-1.125));
+  EXPECT_EQ(negnum.get_sign(), true);
+  EXPECT_EQ(negnum.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(negnum.get_mantissa(), static_cast<UInt128>(0x2) << 108);
+  EXPECT_EQ(negnum.uintval(), static_cast<UInt128>(0xBFFF2) << 108);
+  EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(),
+               "0xBFFF2000000000000000000000000000 = "
+               "(S: 1, E: 0x3FFF, M: 0x00002000000000000000000000000000)");
+}
+#endif // LIBC_COMPILER_HAS_FLOAT128
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 995dee7b0b54829..101bdac995355de 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -674,6 +674,22 @@ add_fp_unittest(
   UNIT_TEST_ONLY
 )
 
+add_fp_unittest(
+  copysignf128_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    copysignf128_test.cpp
+  HDRS
+    CopySignTest.h
+  DEPENDS
+    libc.include.math
+    libc.src.math.copysignf128
+    libc.src.__support.FPUtil.fp_bits
+  # FIXME: Currently fails on the GPU build.
+  UNIT_TEST_ONLY
+)
+
 add_fp_unittest(
   frexp_test
   SUITE
diff --git a/libc/test/src/math/smoke/CopySignTest.h b/libc/test/src/math/smoke/CopySignTest.h
index c33f78038a3cff9..5e748bb8fd8ed58 100644
--- a/libc/test/src/math/smoke/CopySignTest.h
+++ b/libc/test/src/math/smoke/CopySignTest.h
@@ -20,28 +20,29 @@ class CopySignTest : public LIBC_NAMESPACE::testing::Test {
   typedef T (*CopySignFunc)(T, T);
 
   void testSpecialNumbers(CopySignFunc func) {
-    EXPECT_FP_EQ(aNaN, func(aNaN, -1.0));
-    EXPECT_FP_EQ(aNaN, func(aNaN, 1.0));
+    EXPECT_FP_EQ(aNaN, func(aNaN, T(-1.0)));
+    EXPECT_FP_EQ(aNaN, func(aNaN, T(1.0)));
 
-    EXPECT_FP_EQ(neg_inf, func(inf, -1.0));
-    EXPECT_FP_EQ(inf, func(neg_inf, 1.0));
+    EXPECT_FP_EQ(neg_inf, func(inf, T(-1.0)));
+    EXPECT_FP_EQ(inf, func(neg_inf, T(1.0)));
 
-    EXPECT_FP_EQ(neg_zero, func(zero, -1.0));
-    EXPECT_FP_EQ(zero, func(neg_zero, 1.0));
+    EXPECT_FP_EQ(neg_zero, func(zero, T(-1.0)));
+    EXPECT_FP_EQ(zero, func(neg_zero, T(1.0)));
   }
 
   void testRange(CopySignFunc func) {
     constexpr UIntType COUNT = 100'000;
     constexpr UIntType STEP = UIntType(-1) / COUNT;
     for (UIntType i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
-      T x = T(FPBits(v));
-      if (isnan(x) || isinf(x))
+      FPBits x_bits = FPBits(v);
+      T x = T(v);
+      if (x_bits.is_nan() || x_bits.is_inf())
         continue;
 
-      double res1 = func(x, -x);
+      T res1 = func(x, -x);
       ASSERT_FP_EQ(res1, -x);
 
-      double res2 = func(x, x);
+      T res2 = func(x, x);
       ASSERT_FP_EQ(res2, x);
     }
   }
diff --git a/libc/test/src/math/smoke/copysignf128_test.cpp b/libc/test/src/math/smoke/copysignf128_test.cpp
new file mode 100644
index 000000000000000..48b41deb71d53eb
--- /dev/null
+++ b/libc/test/src/math/smoke/copysignf128_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for copysignf128 ----------------------------------------===//
+//
+// 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 "CopySignTest.h"
+
+#include "src/math/copysignf128.h"
+
+LIST_COPYSIGN_TESTS(float128, LIBC_NAMESPACE::copysignf128)

``````````

</details>


https://github.com/llvm/llvm-project/pull/71731


More information about the libc-commits mailing list