mirror of
https://github.com/intel/llvm.git
synced 2026-01-20 10:58:11 +08:00
[libc][math] Add initial support for C23 float128 math functions, starting with copysignf128. (#71731)
This commit is contained in:
@@ -245,6 +245,7 @@ option(LIBC_INCLUDE_DOCS "Build the libc documentation." ${LLVM_INCLUDE_DOCS})
|
||||
|
||||
include(CMakeParseArguments)
|
||||
include(LLVMLibCCheckCpuFeatures)
|
||||
include(CheckCompilerFeatures)
|
||||
include(LLVMLibCRules)
|
||||
|
||||
if(EXISTS "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}/entrypoints.txt")
|
||||
|
||||
59
libc/cmake/modules/CheckCompilerFeatures.cmake
Normal file
59
libc/cmake/modules/CheckCompilerFeatures.cmake
Normal file
@@ -0,0 +1,59 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Compiler features definition and flags
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Initialize ALL_COMPILER_FEATURES as empty list.
|
||||
set(ALL_COMPILER_FEATURES "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}")
|
||||
5
libc/cmake/modules/compiler_features/check_float128.cpp
Normal file
5
libc/cmake/modules/compiler_features/check_float128.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "src/__support/macros/properties/compiler.h"
|
||||
|
||||
#ifndef LIBC_COMPILER_HAS_FLOAT128
|
||||
#error unsupported
|
||||
#endif
|
||||
@@ -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
|
||||
|
||||
@@ -96,9 +96,9 @@ Implementation Status
|
||||
|
||||
* To check math functions enabled for embedded system:
|
||||
|
||||
- `barebone-aarch32 <https://github.com/llvm/llvm-project/tree/main/libc/config/baremetal/arm/entrypoints.txt>`_
|
||||
- `baremetal-aarch32 <https://github.com/llvm/llvm-project/tree/main/libc/config/baremetal/arm/entrypoints.txt>`_
|
||||
|
||||
- barebone-riscv32 - to be added
|
||||
- baremetal-riscv32 - to be added
|
||||
|
||||
Basic Operations
|
||||
----------------
|
||||
@@ -120,6 +120,8 @@ Basic Operations
|
||||
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
|
||||
| copysignl | |check| | |check| | | |check| | |check| | | | |check| | | | | |
|
||||
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
|
||||
| copysignf128 | |check| | |check| | | | | | | | | | | |
|
||||
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
|
||||
| fabs | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | | | |
|
||||
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
|
||||
| fabsf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | | | |
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>]>,
|
||||
|
||||
@@ -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 @@ private:
|
||||
}
|
||||
|
||||
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 =
|
||||
|
||||
@@ -175,6 +175,38 @@ template <> struct FloatProperties<long double> {
|
||||
};
|
||||
#endif
|
||||
|
||||
#if (defined(LIBC_COMPILER_HAS_FLOAT128) && \
|
||||
!defined(LIBC_FLOAT128_IS_LONG_DOUBLE))
|
||||
// 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;
|
||||
|
||||
|
||||
@@ -21,4 +21,25 @@
|
||||
#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;
|
||||
|
||||
#elif (defined(__linux__) && defined(__aarch64__))
|
||||
// long double on Linux aarch64 is 128-bit floating point.
|
||||
#define LIBC_COMPILER_HAS_FLOAT128
|
||||
#define LIBC_FLOAT128_IS_LONG_DOUBLE
|
||||
using float128 = long double;
|
||||
|
||||
#endif
|
||||
|
||||
#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_COMPILER_H
|
||||
|
||||
@@ -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)
|
||||
|
||||
20
libc/src/math/copysignf128.h
Normal file
20
libc/src/math/copysignf128.h
Normal file
@@ -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
|
||||
@@ -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(
|
||||
|
||||
20
libc/src/math/generic/copysignf128.cpp
Normal file
20
libc/src/math/generic/copysignf128.cpp
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -20,28 +20,29 @@ public:
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
13
libc/test/src/math/smoke/copysignf128_test.cpp
Normal file
13
libc/test/src/math/smoke/copysignf128_test.cpp
Normal file
@@ -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)
|
||||
@@ -308,6 +308,7 @@ libc_support_library(
|
||||
deps = [
|
||||
":__support_macros_attributes",
|
||||
":__support_macros_config",
|
||||
":__support_macros_properties_compiler",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1821,6 +1822,8 @@ libc_math_function(name = "copysignf")
|
||||
|
||||
libc_math_function(name = "copysignl")
|
||||
|
||||
libc_math_function(name = "copysignf128")
|
||||
|
||||
libc_math_function(name = "ilogb")
|
||||
|
||||
libc_math_function(name = "ilogbf")
|
||||
|
||||
Reference in New Issue
Block a user