diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index effa5b12d87ac..7d23129f4b85a 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -365,6 +365,9 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.complex.cimag libc.src.complex.cimagf libc.src.complex.cimagl + libc.src.complex.conj + libc.src.complex.conjf + libc.src.complex.conjl # fenv.h entrypoints libc.src.fenv.feclearexcept @@ -616,6 +619,7 @@ if(LIBC_TYPES_HAS_FLOAT16) # complex.h C23 _Complex _Float16 entrypoints # libc.src.complex.crealf16 # libc.src.complex.cimagf16 + # libc.src.complex.conjf16 # math.h C23 _Float16 entrypoints libc.src.math.canonicalizef16 @@ -721,6 +725,7 @@ if(LIBC_TYPES_HAS_FLOAT128) # complex.h C23 _Complex _Float128 entrypoints libc.src.complex.crealf128 libc.src.complex.cimagf128 + libc.src.complex.conjf128 # math.h C23 _Float128 entrypoints libc.src.math.canonicalizef128 diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index 31d81de06fb6b..babdf92bb5676 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -207,6 +207,9 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.complex.cimag libc.src.complex.cimagf libc.src.complex.cimagl + libc.src.complex.conj + libc.src.complex.conjf + libc.src.complex.conjl # fenv.h entrypoints libc.src.fenv.feclearexcept diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 5a48baf104159..59a5a1168f5dd 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -363,6 +363,9 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.complex.cimag libc.src.complex.cimagf libc.src.complex.cimagl + libc.src.complex.conj + libc.src.complex.conjf + libc.src.complex.conjl # fenv.h entrypoints libc.src.fenv.feclearexcept @@ -618,6 +621,7 @@ if(LIBC_TYPES_HAS_FLOAT128) # complex.h C23 _Complex _Float128 entrypoints libc.src.complex.crealf128 libc.src.complex.cimagf128 + libc.src.complex.conjf128 # math.h C23 _Float128 entrypoints libc.src.math.canonicalizef128 diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 1bedc25a9d029..21dd7e9a1d9da 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -365,6 +365,9 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.complex.cimag libc.src.complex.cimagf libc.src.complex.cimagl + libc.src.complex.conj + libc.src.complex.conjf + libc.src.complex.conjl # fenv.h entrypoints libc.src.fenv.feclearexcept @@ -621,6 +624,7 @@ if(LIBC_TYPES_HAS_FLOAT16) # complex.h C23 _Complex _Float16 entrypoints libc.src.complex.crealf16 libc.src.complex.cimagf16 + libc.src.complex.conjf16 # math.h C23 _Float16 entrypoints libc.src.math.canonicalizef16 @@ -730,6 +734,7 @@ if(LIBC_TYPES_HAS_FLOAT128) # complex.h C23 _Complex _Float128 entrypoints # libc.src.complex.crealf128 # libc.src.complex.cimagf128 + # libc.src.complex.conjf128 # math.h C23 _Float128 entrypoints libc.src.math.canonicalizef128 diff --git a/libc/docs/headers/complex.rst b/libc/docs/headers/complex.rst index 2e81aba97b0ef..b6a340543fad1 100644 --- a/libc/docs/headers/complex.rst +++ b/libc/docs/headers/complex.rst @@ -57,7 +57,7 @@ Functions +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | cimag | |check| | |check| | |check| | |check| | |check| | 7.3.9.2 | N/A | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ -| conj | | | | | | 7.3.9.4 | N/A | +| conj | |check| | |check| | |check| | |check| | |check| | 7.3.9.4 | N/A | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | cproj | | | | | | 7.3.9.5 | N/A | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ diff --git a/libc/src/__support/complex_type.h b/libc/src/__support/complex_type.h index d6b5eec8fd6b2..4c861b05bc752 100644 --- a/libc/src/__support/complex_type.h +++ b/libc/src/__support/complex_type.h @@ -10,11 +10,70 @@ #define LLVM_LIBC_SRC___SUPPORT_COMPLEX_TYPE_H #include "src/__support/macros/config.h" +#include "src/__support/macros/properties/complex_types.h" +#include "src/__support/macros/properties/types.h" namespace LIBC_NAMESPACE_DECL { template struct Complex { T real; T imag; }; + +template struct make_complex; + +template <> struct make_complex { + using type = _Complex float; +}; +template <> struct make_complex { + using type = _Complex double; +}; +template <> struct make_complex { + using type = _Complex long double; +}; + +#if defined(LIBC_TYPES_HAS_CFLOAT16) +template <> struct make_complex { + using type = cfloat16; +}; +#endif +#if defined(LIBC_TYPES_HAS_CFLOAT128) +template <> struct make_complex { + using type = cfloat128; +}; +#endif + +template using make_complex_t = typename make_complex::type; + +template struct make_real; + +template <> struct make_real<_Complex float> { + using type = float; +}; +template <> struct make_real<_Complex double> { + using type = double; +}; +template <> struct make_real<_Complex long double> { + using type = long double; +}; + +#if defined(LIBC_TYPES_HAS_CFLOAT16) +template <> struct make_real { + using type = float16; +}; +#endif +#if defined(LIBC_TYPES_HAS_CFLOAT128) +template <> struct make_real { + using type = float128; +}; +#endif + +template using make_real_t = typename make_real::type; + +template LIBC_INLINE constexpr T conjugate(T c) { + Complex> c_c = cpp::bit_cast>>(c); + c_c.imag = -c_c.imag; + return cpp::bit_cast(c_c); +} + } // namespace LIBC_NAMESPACE_DECL #endif // LLVM_LIBC_SRC___SUPPORT_COMPLEX_TYPE_H diff --git a/libc/src/complex/CMakeLists.txt b/libc/src/complex/CMakeLists.txt index 289cce5455af7..7306e2fe925e3 100644 --- a/libc/src/complex/CMakeLists.txt +++ b/libc/src/complex/CMakeLists.txt @@ -24,3 +24,9 @@ add_complex_entrypoint_object(cimagf) add_complex_entrypoint_object(cimagl) add_complex_entrypoint_object(cimagf16) add_complex_entrypoint_object(cimagf128) + +add_complex_entrypoint_object(conj) +add_complex_entrypoint_object(conjf) +add_complex_entrypoint_object(conjl) +add_complex_entrypoint_object(conjf16) +add_complex_entrypoint_object(conjf128) diff --git a/libc/src/complex/conj.h b/libc/src/complex/conj.h new file mode 100644 index 0000000000000..2ff82d2758620 --- /dev/null +++ b/libc/src/complex/conj.h @@ -0,0 +1,20 @@ +//===-- Implementation header for conj --------------------------*- 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_COMPLEX_CONJ_H +#define LLVM_LIBC_SRC_COMPLEX_CONJ_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +_Complex double conj(_Complex double x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CONJ_H diff --git a/libc/src/complex/conjf.h b/libc/src/complex/conjf.h new file mode 100644 index 0000000000000..6b3bd612e5bf7 --- /dev/null +++ b/libc/src/complex/conjf.h @@ -0,0 +1,20 @@ +//===-- Implementation header for conjf -------------------------*- 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_COMPLEX_CONJF_H +#define LLVM_LIBC_SRC_COMPLEX_CONJF_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +_Complex float conjf(_Complex float x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CONJF_H diff --git a/libc/src/complex/conjf128.h b/libc/src/complex/conjf128.h new file mode 100644 index 0000000000000..587c979d315ef --- /dev/null +++ b/libc/src/complex/conjf128.h @@ -0,0 +1,27 @@ +//===-- Implementation header for conjf128 ----------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/macros/properties/complex_types.h" +#include "src/__support/macros/properties/types.h" + +#if defined(LIBC_TYPES_HAS_CFLOAT128) + +#ifndef LLVM_LIBC_SRC_COMPLEX_CONJF128_H +#define LLVM_LIBC_SRC_COMPLEX_CONJF128_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +cfloat128 conjf128(cfloat128 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CONJF128_H + +#endif // LIBC_TYPES_HAS_CFLOAT128 diff --git a/libc/src/complex/conjf16.h b/libc/src/complex/conjf16.h new file mode 100644 index 0000000000000..b15c5b3f61f4a --- /dev/null +++ b/libc/src/complex/conjf16.h @@ -0,0 +1,27 @@ +//===-- Implementation header for conjf16 -----------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/macros/properties/complex_types.h" +#include "src/__support/macros/properties/types.h" + +#if defined(LIBC_TYPES_HAS_CFLOAT16) + +#ifndef LLVM_LIBC_SRC_COMPLEX_CONJF16_H +#define LLVM_LIBC_SRC_COMPLEX_CONJF16_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +cfloat16 conjf16(cfloat16 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CONJF16_H + +#endif // LIBC_TYPES_HAS_CFLOAT16 diff --git a/libc/src/complex/conjl.h b/libc/src/complex/conjl.h new file mode 100644 index 0000000000000..aec640f9433ac --- /dev/null +++ b/libc/src/complex/conjl.h @@ -0,0 +1,20 @@ +//===-- Implementation header for conjl -------------------------*- 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_COMPLEX_CONJL_H +#define LLVM_LIBC_SRC_COMPLEX_CONJL_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +_Complex long double conjl(_Complex long double x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CONJL_H diff --git a/libc/src/complex/generic/CMakeLists.txt b/libc/src/complex/generic/CMakeLists.txt index a3da781c60237..cc14f89122edd 100644 --- a/libc/src/complex/generic/CMakeLists.txt +++ b/libc/src/complex/generic/CMakeLists.txt @@ -1,3 +1,72 @@ +add_entrypoint_object( + conj + SRCS + conj.cpp + HDRS + ../conj.h + COMPILE_OPTIONS + ${libc_opt_high_flag} + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type +) + +add_entrypoint_object( + conjf + SRCS + conjf.cpp + HDRS + ../conjf.h + COMPILE_OPTIONS + ${libc_opt_high_flag} + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type +) + +add_entrypoint_object( + conjl + SRCS + conjl.cpp + HDRS + ../conjl.h + COMPILE_OPTIONS + ${libc_opt_high_flag} + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type +) + +add_entrypoint_object( + conjf16 + SRCS + conjf16.cpp + HDRS + ../conjf16.h + COMPILE_OPTIONS + ${libc_opt_high_flag} + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type + libc.src.__support.macros.properties.types + libc.src.__support.macros.properties.complex_types +) + +add_entrypoint_object( + conjf128 + SRCS + conjf128.cpp + HDRS + ../conjf128.h + COMPILE_OPTIONS + ${libc_opt_high_flag} + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type + libc.src.__support.macros.properties.types + libc.src.__support.macros.properties.complex_types +) + add_entrypoint_object( creal SRCS diff --git a/libc/src/complex/generic/conj.cpp b/libc/src/complex/generic/conj.cpp new file mode 100644 index 0000000000000..1a93bc25dc3c4 --- /dev/null +++ b/libc/src/complex/generic/conj.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of conj 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/complex/conj.h" +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(_Complex double, conj, (_Complex double x)) { + return conjugate<_Complex double>(x); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/complex/generic/conjf.cpp b/libc/src/complex/generic/conjf.cpp new file mode 100644 index 0000000000000..33cb34340a04e --- /dev/null +++ b/libc/src/complex/generic/conjf.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of conjf 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/complex/conjf.h" +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(_Complex float, conjf, (_Complex float x)) { + return conjugate<_Complex float>(x); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/complex/generic/conjf128.cpp b/libc/src/complex/generic/conjf128.cpp new file mode 100644 index 0000000000000..4e35b3d5a97b7 --- /dev/null +++ b/libc/src/complex/generic/conjf128.cpp @@ -0,0 +1,24 @@ +//===-- Implementation of conjf128 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/complex/conjf128.h" +#if defined(LIBC_TYPES_HAS_CFLOAT128) + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(cfloat128, conjf128, (cfloat128 x)) { + return conjugate(x); +} + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_CFLOAT128 diff --git a/libc/src/complex/generic/conjf16.cpp b/libc/src/complex/generic/conjf16.cpp new file mode 100644 index 0000000000000..2564fe252027a --- /dev/null +++ b/libc/src/complex/generic/conjf16.cpp @@ -0,0 +1,24 @@ +//===-- Implementation of conjf16 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/complex/conjf16.h" +#if defined(LIBC_TYPES_HAS_CFLOAT16) + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(cfloat16, conjf16, (cfloat16 x)) { + return conjugate(x); +} + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_CFLOAT16 diff --git a/libc/src/complex/generic/conjl.cpp b/libc/src/complex/generic/conjl.cpp new file mode 100644 index 0000000000000..dc071ab1ec51b --- /dev/null +++ b/libc/src/complex/generic/conjl.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of conjl 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/complex/conjl.h" +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(_Complex long double, conjl, (_Complex long double x)) { + return conjugate<_Complex long double>(x); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/src/complex/CImagTest.h b/libc/test/src/complex/CImagTest.h index 6d2f935002669..408460d97dfc6 100644 --- a/libc/test/src/complex/CImagTest.h +++ b/libc/test/src/complex/CImagTest.h @@ -38,9 +38,14 @@ class CImagTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { neg_min_denormal); EXPECT_FP_EQ(func(CFPT(1241.112 + max_denormal * 1.0i)), max_denormal); EXPECT_FP_EQ(func(CFPT(121.121 + zero * 1.0i)), zero); - EXPECT_FP_EQ(func(CFPT(neg_zero + zero * 1.0i)), zero); - EXPECT_FP_EQ(func(CFPT(neg_zero + neg_zero * 1.0i)), neg_zero); - EXPECT_FP_EQ(func(CFPT(zero + neg_zero * 1.0i)), neg_zero); + EXPECT_FP_EQ(func(CFPT(0.0 + 0.0i)), 0.0); + EXPECT_FP_EQ(func(CFPT(-0.0 + 0.0i)), 0.0); + EXPECT_FP_EQ(func(CFPT(0.0 - 0.0i)), -0.0); + EXPECT_FP_EQ(func(CFPT(-0.0 - 0.0i)), -0.0); + EXPECT_FP_EQ(func(CFPT(0.0)), 0.0); + EXPECT_FP_EQ(func(CFPT(-0.0)), 0.0); + EXPECT_FP_EQ(func(CFPT(0.0i)), 0.0); + EXPECT_FP_EQ(func(CFPT(-0.0i)), -0.0); } void testRoundedNumbers(CImagFunc func) { diff --git a/libc/test/src/complex/CMakeLists.txt b/libc/test/src/complex/CMakeLists.txt index 8f49e6d79e179..0c668d9e1e8b9 100644 --- a/libc/test/src/complex/CMakeLists.txt +++ b/libc/test/src/complex/CMakeLists.txt @@ -1,5 +1,65 @@ add_custom_target(libc-complex-unittests) +add_libc_test( + conj_test + SUITE + libc-complex-unittests + SRCS + conj_test.cpp + DEPENDS + libc.src.complex.conj + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + conjf_test + SUITE + libc-complex-unittests + SRCS + conjf_test.cpp + DEPENDS + libc.src.complex.conjf + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + conjl_test + SUITE + libc-complex-unittests + SRCS + conjl_test.cpp + DEPENDS + libc.src.complex.conjl + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + conjf16_test + SUITE + libc-complex-unittests + SRCS + conjf16_test.cpp + DEPENDS + libc.src.complex.conjf16 + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + conjf128_test + SUITE + libc-complex-unittests + SRCS + conjf128_test.cpp + DEPENDS + libc.src.complex.conjf128 + LINK_LIBRARIES + LibcFPTestHelpers +) + add_libc_test( creal_test SUITE diff --git a/libc/test/src/complex/CRealTest.h b/libc/test/src/complex/CRealTest.h index a25555b506e22..80eafc9975f4c 100644 --- a/libc/test/src/complex/CRealTest.h +++ b/libc/test/src/complex/CRealTest.h @@ -37,8 +37,14 @@ class CRealTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { EXPECT_FP_EQ(func(CFPT(neg_min_denormal + 781.134i)), neg_min_denormal); EXPECT_FP_EQ(func(CFPT(max_denormal + 1241.112i)), max_denormal); EXPECT_FP_EQ(func(CFPT(zero + 121.121i)), zero); - EXPECT_FP_EQ(func(CFPT(neg_zero + neg_zero * 1.0i)), neg_zero); - EXPECT_FP_EQ(func(CFPT(neg_zero + zero * 1.0i)), zero); + EXPECT_FP_EQ(func(CFPT(0.0 + 0.0i)), 0.0); + EXPECT_FP_EQ(func(CFPT(-0.0 + 0.0i)), 0.0); + EXPECT_FP_EQ(func(CFPT(0.0 - 0.0i)), 0.0); + EXPECT_FP_EQ(func(CFPT(-0.0 - 0.0i)), -0.0); + EXPECT_FP_EQ(func(CFPT(0.0)), 0.0); + EXPECT_FP_EQ(func(CFPT(-0.0)), -0.0); + EXPECT_FP_EQ(func(CFPT(0.0i)), 0.0); + EXPECT_FP_EQ(func(CFPT(-0.0i)), -0.0); } void testRoundedNumbers(CRealFunc func) { diff --git a/libc/test/src/complex/ConjTest.h b/libc/test/src/complex/ConjTest.h new file mode 100644 index 0000000000000..da4fb4fd137c8 --- /dev/null +++ b/libc/test/src/complex/ConjTest.h @@ -0,0 +1,131 @@ +//===-- Utility class to test different flavors of conj ---------*- 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_TEST_SRC_COMPLEX_CONJTEST_H +#define LLVM_LIBC_TEST_SRC_COMPLEX_CONJTEST_H + +#include "test/UnitTest/FEnvSafeTest.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +#include "hdr/math_macros.h" + +template +class ConjTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { + + DECLARE_SPECIAL_CONSTANTS(FPT) + +public: + typedef CFPT (*ConjFunc)(CFPT); + + void testSpecialNumbers(ConjFunc func) { + EXPECT_CFP_EQ(func(CFPT(aNaN + 67.123i)), CFPT(aNaN - 67.123i)); + EXPECT_CFP_EQ(func(CFPT(neg_aNaN + 78.319i)), CFPT(neg_aNaN - 78.319i)); + EXPECT_CFP_EQ(func(CFPT(sNaN + 7813.131i)), CFPT(sNaN - 7813.131i)); + EXPECT_CFP_EQ(func(CFPT(neg_sNaN + 7824.152i)), CFPT(neg_sNaN - 7824.152i)); + EXPECT_CFP_EQ(func(CFPT(inf + 9024.2442i)), CFPT(inf - 9024.2442i)); + EXPECT_CFP_EQ(func(CFPT(neg_inf + 8923.124i)), CFPT(neg_inf - 8923.124i)); + EXPECT_CFP_EQ(func(CFPT(min_normal + 782.124i)), + CFPT(min_normal - 782.124i)); + EXPECT_CFP_EQ(func(CFPT(max_normal + 2141.2352i)), + CFPT(max_normal - 2141.2352i)); + EXPECT_CFP_EQ(func(CFPT(neg_max_normal + 341.134i)), + CFPT(neg_max_normal - 341.134i)); + EXPECT_CFP_EQ(func(CFPT(min_denormal + 781.142i)), + CFPT(min_denormal - 781.142i)); + EXPECT_CFP_EQ(func(CFPT(neg_min_denormal + 781.134i)), + CFPT(neg_min_denormal - 781.134i)); + EXPECT_CFP_EQ(func(CFPT(max_denormal + 1241.112i)), + CFPT(max_denormal - 1241.112i)); + EXPECT_CFP_EQ(func(CFPT(zero + 121.121i)), CFPT(zero - 121.121i)); + EXPECT_CFP_EQ(func(CFPT(67.123 + aNaN * 1.0i)), CFPT(67.123 - aNaN * 1.0i)); + EXPECT_CFP_EQ(func(CFPT(78.319 + neg_aNaN * 1.0i)), + CFPT(78.319 - neg_aNaN * 1.0i)); + EXPECT_CFP_EQ(func(CFPT(7813.131 + sNaN * 1.0i)), + CFPT(7813.131 - sNaN * 1.0i)); + EXPECT_CFP_EQ(func(CFPT(7824.152 + neg_sNaN * 1.0i)), + CFPT(7824.152 - neg_sNaN * 1.0i)); + EXPECT_CFP_EQ(func(CFPT(9024.2442 + inf * 1.0i)), + CFPT(9024.2442 - inf * 1.0i)); + EXPECT_CFP_EQ(func(CFPT(8923.124 + neg_inf * 1.0i)), + CFPT(8923.124 - neg_inf * 1.0i)); + EXPECT_CFP_EQ(func(CFPT(782.124 + min_normal * 1.0i)), + CFPT(782.124 - min_normal * 1.0i)); + EXPECT_CFP_EQ(func(CFPT(2141.2352 + max_normal * 1.0i)), + CFPT(2141.2352 - max_normal * 1.0i)); + EXPECT_CFP_EQ(func(CFPT(341.134 + neg_max_normal * 1.0i)), + CFPT(341.134 - neg_max_normal * 1.0i)); + EXPECT_CFP_EQ(func(CFPT(781.142 + min_denormal * 1.0i)), + CFPT(781.142 - min_denormal * 1.0i)); + EXPECT_CFP_EQ(func(CFPT(781.134 + neg_min_denormal * 1.0i)), + CFPT(781.134 - neg_min_denormal * 1.0i)); + EXPECT_CFP_EQ(func(CFPT(1241.112 + max_denormal * 1.0i)), + CFPT(1241.112 - max_denormal * 1.0i)); + EXPECT_CFP_EQ(func(CFPT(121.121 + zero * 1.0i)), + CFPT(121.121 - zero * 1.0i)); + EXPECT_CFP_EQ(func(CFPT(0.0 - 0.0i)), CFPT(0.0 + 0.0i)); + EXPECT_CFP_EQ(func(CFPT(0.0 + 0.0i)), CFPT(0.0 - 0.0i)); + // This test passes because the conjugate of -0.0 - 0.0i is CMPLX(-0.0, 0.0) + // which cannot be represented as -0.0 + 0.0i because -0.0 + 0.0i is + // actually CMPLX(-0.0, 0.0) + CMPLX(0.0, 0.0) = 0.0 + 0.0i so to represent + // CMPLX(-0.0, 0.0), we use -0.0 + EXPECT_CFP_EQ(func(CFPT(-0.0 - 0.0i)), CFPT(-0.0)); + // This test passes because -0.0 + 0.0i is actually + // CMPLX(-0.0, 0.0) + CMPLX(0.0, 0.0) = CMPLX(-0.0 + 0.0, 0.0) = 0.0 + 0.0i + EXPECT_CFP_EQ(func(CFPT(-0.0 + 0.0i)), CFPT(0.0 - 0.0i)); + EXPECT_CFP_EQ(func(CFPT(0.0)), CFPT(0.0 - 0.0i)); + EXPECT_CFP_EQ(func(CFPT(-0.0)), CFPT(-0.0 - 0.0i)); + EXPECT_CFP_EQ(func(CFPT(0.0i)), CFPT(0.0 - 0.0i)); + EXPECT_CFP_EQ(func(CFPT(-0.0i)), CFPT(-0.0)); + } + + void testRoundedNumbers(ConjFunc func) { + EXPECT_CFP_EQ(func((CFPT)(4523.1413 + 12413.1414i)), + CFPT(4523.1413 - 12413.1414i)); + EXPECT_CFP_EQ(func((CFPT)(-4523.1413 + 12413.1414i)), + CFPT(-4523.1413 - 12413.1414i)); + EXPECT_CFP_EQ(func((CFPT)(4523.1413 - 12413.1414i)), + CFPT(4523.1413 + 12413.1414i)); + EXPECT_CFP_EQ(func((CFPT)(-4523.1413 - 12413.1414i)), + CFPT(-4523.1413 + 12413.1414i)); + + EXPECT_CFP_EQ(func((CFPT)(3210.5678 + 9876.5432i)), + CFPT(3210.5678 - 9876.5432i)); + EXPECT_CFP_EQ(func((CFPT)(-3210.5678 + 9876.5432i)), + CFPT(-3210.5678 - 9876.5432i)); + EXPECT_CFP_EQ(func((CFPT)(3210.5678 - 9876.5432i)), + CFPT(3210.5678 + 9876.5432i)); + EXPECT_CFP_EQ(func((CFPT)(-3210.5678 - 9876.5432i)), + CFPT(-3210.5678 + 9876.5432i)); + + EXPECT_CFP_EQ(func((CFPT)(1234.4321 + 4321.1234i)), + CFPT(1234.4321 - 4321.1234i)); + EXPECT_CFP_EQ(func((CFPT)(-1234.4321 + 4321.1234i)), + CFPT(-1234.4321 - 4321.1234i)); + EXPECT_CFP_EQ(func((CFPT)(1234.4321 - 4321.1234i)), + CFPT(1234.4321 + 4321.1234i)); + EXPECT_CFP_EQ(func((CFPT)(-1234.4321 - 4321.1234i)), + CFPT(-1234.4321 + 4321.1234i)); + + EXPECT_CFP_EQ(func((CFPT)(6789.1234 + 8765.6789i)), + CFPT(6789.1234 - 8765.6789i)); + EXPECT_CFP_EQ(func((CFPT)(-6789.1234 + 8765.6789i)), + CFPT(-6789.1234 - 8765.6789i)); + EXPECT_CFP_EQ(func((CFPT)(6789.1234 - 8765.6789i)), + CFPT(6789.1234 + 8765.6789i)); + EXPECT_CFP_EQ(func((CFPT)(-6789.1234 - 8765.6789i)), + CFPT(-6789.1234 + 8765.6789i)); + } +}; + +#define LIST_CONJ_TESTS(U, T, func) \ + using LlvmLibcConjTest = ConjTest; \ + TEST_F(LlvmLibcConjTest, SpecialNumbers) { testSpecialNumbers(&func); } \ + TEST_F(LlvmLibcConjTest, RoundedNumbers) { testRoundedNumbers(&func); } + +#endif // LLVM_LIBC_TEST_SRC_COMPLEX_CONJTEST_H diff --git a/libc/test/src/complex/conj_test.cpp b/libc/test/src/complex/conj_test.cpp new file mode 100644 index 0000000000000..97445fa065088 --- /dev/null +++ b/libc/test/src/complex/conj_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for conj ------------------------------------------------===// +// +// 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 "ConjTest.h" + +#include "src/complex/conj.h" + +LIST_CONJ_TESTS(_Complex double, double, LIBC_NAMESPACE::conj) diff --git a/libc/test/src/complex/conjf128_test.cpp b/libc/test/src/complex/conjf128_test.cpp new file mode 100644 index 0000000000000..a1feb9ff31fdc --- /dev/null +++ b/libc/test/src/complex/conjf128_test.cpp @@ -0,0 +1,17 @@ +//===-- Unittests for conjf128 --------------------------------------------===// +// +// 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 "ConjTest.h" + +#include "src/complex/conjf128.h" + +#if defined(LIBC_TYPES_HAS_CFLOAT128) + +LIST_CONJ_TESTS(cfloat128, float128, LIBC_NAMESPACE::conjf128) + +#endif // LIBC_TYPES_HAS_CFLOAT128 diff --git a/libc/test/src/complex/conjf16_test.cpp b/libc/test/src/complex/conjf16_test.cpp new file mode 100644 index 0000000000000..0de9f448e8681 --- /dev/null +++ b/libc/test/src/complex/conjf16_test.cpp @@ -0,0 +1,17 @@ +//===-- Unittests for conjf16 ---------------------------------------------===// +// +// 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 "ConjTest.h" + +#include "src/complex/conjf16.h" + +#if defined(LIBC_TYPES_HAS_CFLOAT16) + +LIST_CONJ_TESTS(cfloat16, float16, LIBC_NAMESPACE::conjf16) + +#endif // LIBC_TYPES_HAS_CFLOAT16 diff --git a/libc/test/src/complex/conjf_test.cpp b/libc/test/src/complex/conjf_test.cpp new file mode 100644 index 0000000000000..34b00b37996c3 --- /dev/null +++ b/libc/test/src/complex/conjf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for conjf -----------------------------------------------===// +// +// 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 "ConjTest.h" + +#include "src/complex/conjf.h" + +LIST_CONJ_TESTS(_Complex float, float, LIBC_NAMESPACE::conjf) diff --git a/libc/test/src/complex/conjl_test.cpp b/libc/test/src/complex/conjl_test.cpp new file mode 100644 index 0000000000000..ec299f9631547 --- /dev/null +++ b/libc/test/src/complex/conjl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for conjl -----------------------------------------------===// +// +// 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 "ConjTest.h" + +#include "src/complex/conjl.h" + +LIST_CONJ_TESTS(_Complex long double, long double, LIBC_NAMESPACE::conjl)