[libc-commits] [libc] ffe04e0 - [libc][complex] implement different flavors of `creal` and `cimag` functions (#113300)

via libc-commits libc-commits at lists.llvm.org
Sat Nov 2 21:08:13 PDT 2024


Author: Shourya Goel
Date: 2024-11-03T09:38:09+05:30
New Revision: ffe04e0351203524b212f850b48edf54dc5dbeb5

URL: https://github.com/llvm/llvm-project/commit/ffe04e0351203524b212f850b48edf54dc5dbeb5
DIFF: https://github.com/llvm/llvm-project/commit/ffe04e0351203524b212f850b48edf54dc5dbeb5.diff

LOG: [libc][complex] implement different flavors of `creal` and `cimag` functions (#113300)

I have commented out the test for `neg_zero`(creal) because : 

1. real(neg_zero + 0.0i) equals zero. 
2. real(neg_zero - 0.0i) equals neg_zero.

I am not sure if this is the intended behaviour. 

[EDIT]
I have updated tests for `neg_zero` (creal) to be : 

```
    EXPECT_FP_EQ(func(CFPT(neg_zero - zero * 1.0i)), neg_zero);
    EXPECT_FP_EQ(func(CFPT(neg_zero + zero * 1.0i)), zero);
```

because all three [gcc, clang and GNU MPC] also give the same result. 
https://godbolt.org/z/hxhcn6aof
and it seems that it is indeed the correct behaviour since Imaginary
types are not supported yet, refer #113671

Added: 
    libc/src/__support/complex_type.h
    libc/src/complex/CMakeLists.txt
    libc/src/complex/cimag.h
    libc/src/complex/cimagf.h
    libc/src/complex/cimagf128.h
    libc/src/complex/cimagf16.h
    libc/src/complex/cimagl.h
    libc/src/complex/creal.h
    libc/src/complex/crealf.h
    libc/src/complex/crealf128.h
    libc/src/complex/crealf16.h
    libc/src/complex/creall.h
    libc/src/complex/generic/CMakeLists.txt
    libc/src/complex/generic/cimag.cpp
    libc/src/complex/generic/cimagf.cpp
    libc/src/complex/generic/cimagf128.cpp
    libc/src/complex/generic/cimagf16.cpp
    libc/src/complex/generic/cimagl.cpp
    libc/src/complex/generic/creal.cpp
    libc/src/complex/generic/crealf.cpp
    libc/src/complex/generic/crealf128.cpp
    libc/src/complex/generic/crealf16.cpp
    libc/src/complex/generic/creall.cpp
    libc/test/src/complex/CImagTest.h
    libc/test/src/complex/CMakeLists.txt
    libc/test/src/complex/CRealTest.h
    libc/test/src/complex/cimag_test.cpp
    libc/test/src/complex/cimagf128_test.cpp
    libc/test/src/complex/cimagf16_test.cpp
    libc/test/src/complex/cimagf_test.cpp
    libc/test/src/complex/cimagl_test.cpp
    libc/test/src/complex/creal_test.cpp
    libc/test/src/complex/crealf128_test.cpp
    libc/test/src/complex/crealf16_test.cpp
    libc/test/src/complex/crealf_test.cpp
    libc/test/src/complex/creall_test.cpp

Modified: 
    libc/config/linux/aarch64/entrypoints.txt
    libc/config/linux/arm/entrypoints.txt
    libc/config/linux/riscv/entrypoints.txt
    libc/config/linux/x86_64/entrypoints.txt
    libc/docs/complex.rst
    libc/src/CMakeLists.txt
    libc/src/__support/CMakeLists.txt
    libc/test/src/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index b3f94a581c8ad9..9f076ddedb5c67 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -356,6 +356,14 @@ if(LLVM_LIBC_INCLUDE_SCUDO)
 endif()
 
 set(TARGET_LIBM_ENTRYPOINTS
+    # complex.h entrypoints
+    libc.src.complex.creal
+    libc.src.complex.crealf
+    libc.src.complex.creall
+    libc.src.complex.cimag
+    libc.src.complex.cimagf
+    libc.src.complex.cimagl
+
     # fenv.h entrypoints
     libc.src.fenv.feclearexcept
     libc.src.fenv.fedisableexcept
@@ -603,6 +611,10 @@ set(TARGET_LIBM_ENTRYPOINTS
 
 if(LIBC_TYPES_HAS_FLOAT16)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
+    # complex.h C23 _Complex _Float16 entrypoints
+    libc.src.complex.crealf16
+    libc.src.complex.cimagf16
+    
     # math.h C23 _Float16 entrypoints
     libc.src.math.canonicalizef16
     libc.src.math.ceilf16
@@ -704,6 +716,10 @@ endif()
 
 if(LIBC_TYPES_HAS_FLOAT128)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
+    # complex.h C23 _Complex _Float128 entrypoints
+    libc.src.complex.crealf128
+    libc.src.complex.cimagf128
+
     # math.h C23 _Float128 entrypoints
     libc.src.math.canonicalizef128
     libc.src.math.ceilf128

diff  --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 2ddb7aeefe48ec..383bf8c8e52801 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -197,6 +197,14 @@ if(LLVM_LIBC_INCLUDE_SCUDO)
 endif()
 
 set(TARGET_LIBM_ENTRYPOINTS
+    # complex.h entrypoints
+    libc.src.complex.creal
+    libc.src.complex.crealf
+    libc.src.complex.creall
+    libc.src.complex.cimag
+    libc.src.complex.cimagf
+    libc.src.complex.cimagl
+    
     # fenv.h entrypoints
     libc.src.fenv.feclearexcept
     libc.src.fenv.fedisableexcept

diff  --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 5c09edf7cfb266..c47a4662d1ac79 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -355,6 +355,14 @@ if(LLVM_LIBC_INCLUDE_SCUDO)
 endif()
 
 set(TARGET_LIBM_ENTRYPOINTS
+    # complex.h entrypoints
+    libc.src.complex.creal
+    libc.src.complex.crealf
+    libc.src.complex.creall
+    libc.src.complex.cimag
+    libc.src.complex.cimagf
+    libc.src.complex.cimagl
+
     # fenv.h entrypoints
     libc.src.fenv.feclearexcept
     libc.src.fenv.fedisableexcept
@@ -606,6 +614,10 @@ set(TARGET_LIBM_ENTRYPOINTS
 
 if(LIBC_TYPES_HAS_FLOAT128)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
+    # complex.h C23 _Complex _Float128 entrypoints
+    libc.src.complex.crealf128
+    libc.src.complex.cimagf128
+    
     # math.h C23 _Float128 entrypoints
     libc.src.math.canonicalizef128
     libc.src.math.ceilf128

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index a2fb97d04584d5..af9b41eb40e32d 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -355,6 +355,14 @@ if(LLVM_LIBC_INCLUDE_SCUDO)
 endif()
 
 set(TARGET_LIBM_ENTRYPOINTS
+    # complex.h entrypoints
+    libc.src.complex.creal
+    libc.src.complex.crealf
+    libc.src.complex.creall
+    libc.src.complex.cimag
+    libc.src.complex.cimagf
+    libc.src.complex.cimagl
+    
     # fenv.h entrypoints
     libc.src.fenv.feclearexcept
     libc.src.fenv.fedisableexcept
@@ -606,6 +614,10 @@ set(TARGET_LIBM_ENTRYPOINTS
 
 if(LIBC_TYPES_HAS_FLOAT16)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
+    # complex.h C23 _Complex _Float16 entrypoints
+    libc.src.complex.crealf16
+    libc.src.complex.cimagf16
+
     # math.h C23 _Float16 entrypoints
     libc.src.math.canonicalizef16
     libc.src.math.ceilf16
@@ -709,6 +721,10 @@ endif()
 
 if(LIBC_TYPES_HAS_FLOAT128)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
+    # complex.h C23 _Complex _Float128 entrypoints
+    libc.src.complex.crealf128
+    libc.src.complex.cimagf128
+    
     # math.h C23 _Float128 entrypoints
     libc.src.math.canonicalizef128
     libc.src.math.ceilf128

diff  --git a/libc/docs/complex.rst b/libc/docs/complex.rst
index 09fbdd7c6179ef..1e74f16b60e660 100644
--- a/libc/docs/complex.rst
+++ b/libc/docs/complex.rst
@@ -55,11 +55,11 @@ Functions
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
 | carg      |                  |                 |                        |                      |                        | 7.3.9.1                | N/A                        |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
-| cimag     |                  |                 |                        |                      |                        | 7.3.9.2                | N/A                        |
+| cimag     | |check|          | |check|         | |check|                | |check|              | |check|                | 7.3.9.2                | N/A                        |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
 | conj      |                  |                 |                        |                      |                        | 7.3.9.4                | N/A                        |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
 | cproj     |                  |                 |                        |                      |                        | 7.3.9.5                | N/A                        |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
-| creal     |                  |                 |                        |                      |                        | 7.3.9.6                | N/A                        |
+| creal     | |check|          | |check|         | |check|                | |check|              | |check|                | 7.3.9.6                | N/A                        |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+

diff  --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index d554c12fb1ec89..02c193e635362e 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_subdirectory(__support)
 
+add_subdirectory(complex)
 add_subdirectory(ctype)
 add_subdirectory(dlfcn)
 add_subdirectory(errno)

diff  --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt
index 14a3acff8fae93..bdf839e7622d5f 100644
--- a/libc/src/__support/CMakeLists.txt
+++ b/libc/src/__support/CMakeLists.txt
@@ -209,6 +209,12 @@ add_header_library(
     libc.src.__support.CPP.limits
 )
 
+add_header_library(
+  complex_type
+  HDRS
+    complex_type.h
+)
+
 add_header_library(
   integer_operations
   HDRS

diff  --git a/libc/src/__support/complex_type.h b/libc/src/__support/complex_type.h
new file mode 100644
index 00000000000000..d6b5eec8fd6b24
--- /dev/null
+++ b/libc/src/__support/complex_type.h
@@ -0,0 +1,20 @@
+//===-- complex 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_COMPLEX_TYPE_H
+#define LLVM_LIBC_SRC___SUPPORT_COMPLEX_TYPE_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+template <typename T> struct Complex {
+  T real;
+  T imag;
+};
+} // 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
new file mode 100644
index 00000000000000..289cce5455af78
--- /dev/null
+++ b/libc/src/complex/CMakeLists.txt
@@ -0,0 +1,26 @@
+add_subdirectory(generic)
+
+function(add_complex_entrypoint_object name)
+  get_fq_target_name("generic.${name}" fq_generic_target_name)
+  if(TARGET ${fq_generic_target_name})
+    add_entrypoint_object(
+      ${name}
+      ALIAS
+      DEPENDS
+        .generic.${name}
+    )
+    return()
+  endif()
+endfunction()
+
+add_complex_entrypoint_object(creal)
+add_complex_entrypoint_object(crealf)
+add_complex_entrypoint_object(creall)
+add_complex_entrypoint_object(crealf16)
+add_complex_entrypoint_object(crealf128)
+
+add_complex_entrypoint_object(cimag)
+add_complex_entrypoint_object(cimagf)
+add_complex_entrypoint_object(cimagl)
+add_complex_entrypoint_object(cimagf16)
+add_complex_entrypoint_object(cimagf128)

diff  --git a/libc/src/complex/cimag.h b/libc/src/complex/cimag.h
new file mode 100644
index 00000000000000..29c9b22a78b053
--- /dev/null
+++ b/libc/src/complex/cimag.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for cimag -------------------------*- 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_CIMAG_H
+#define LLVM_LIBC_SRC_COMPLEX_CIMAG_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+double cimag(_Complex double x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_COMPLEX_CIMAG_H

diff  --git a/libc/src/complex/cimagf.h b/libc/src/complex/cimagf.h
new file mode 100644
index 00000000000000..577b6ca1145595
--- /dev/null
+++ b/libc/src/complex/cimagf.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for cimagf ------------------------*- 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_CIMAGF_H
+#define LLVM_LIBC_SRC_COMPLEX_CIMAGF_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float cimagf(_Complex float x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_COMPLEX_CIMAGF_H

diff  --git a/libc/src/complex/cimagf128.h b/libc/src/complex/cimagf128.h
new file mode 100644
index 00000000000000..ab8f9ac7da58c5
--- /dev/null
+++ b/libc/src/complex/cimagf128.h
@@ -0,0 +1,27 @@
+//===-- Implementation header for cimagf128 ---------------------*- 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_CIMAGF128_H
+#define LLVM_LIBC_SRC_COMPLEX_CIMAGF128_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float128 cimagf128(cfloat128 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_COMPLEX_CIMAGF128_H
+
+#endif // LIBC_TYPES_HAS_CFLOAT128

diff  --git a/libc/src/complex/cimagf16.h b/libc/src/complex/cimagf16.h
new file mode 100644
index 00000000000000..5c5de2eb1bcf2e
--- /dev/null
+++ b/libc/src/complex/cimagf16.h
@@ -0,0 +1,27 @@
+//===-- Implementation header for cimagf16 ----------------------*- 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_CIMAGF16_H
+#define LLVM_LIBC_SRC_COMPLEX_CIMAGF16_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float16 cimagf16(cfloat16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_COMPLEX_CIMAGF16_H
+
+#endif // LIBC_TYPES_HAS_CFLOAT16

diff  --git a/libc/src/complex/cimagl.h b/libc/src/complex/cimagl.h
new file mode 100644
index 00000000000000..966aee0ef3f74f
--- /dev/null
+++ b/libc/src/complex/cimagl.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for cimagl ------------------------*- 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_CIMAGL_H
+#define LLVM_LIBC_SRC_COMPLEX_CIMAGL_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+long double cimagl(_Complex long double x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_COMPLEX_CIMAGL_H

diff  --git a/libc/src/complex/creal.h b/libc/src/complex/creal.h
new file mode 100644
index 00000000000000..3ec5dd049b975d
--- /dev/null
+++ b/libc/src/complex/creal.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for creal -------------------------*- 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_CREAL_H
+#define LLVM_LIBC_SRC_COMPLEX_CREAL_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+double creal(_Complex double x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_COMPLEX_CREAL_H

diff  --git a/libc/src/complex/crealf.h b/libc/src/complex/crealf.h
new file mode 100644
index 00000000000000..79dafc1c3758d5
--- /dev/null
+++ b/libc/src/complex/crealf.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for crealf ------------------------*- 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_CREALF_H
+#define LLVM_LIBC_SRC_COMPLEX_CREALF_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float crealf(_Complex float x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_COMPLEX_CREALF_H

diff  --git a/libc/src/complex/crealf128.h b/libc/src/complex/crealf128.h
new file mode 100644
index 00000000000000..4922ae78cb2386
--- /dev/null
+++ b/libc/src/complex/crealf128.h
@@ -0,0 +1,27 @@
+//===-- Implementation header for crealf128 ---------------------*- 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_CREALF128_H
+#define LLVM_LIBC_SRC_COMPLEX_CREALF128_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float128 crealf128(cfloat128 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_COMPLEX_CREALF128_H
+
+#endif // LIBC_TYPES_HAS_CFLOAT128

diff  --git a/libc/src/complex/crealf16.h b/libc/src/complex/crealf16.h
new file mode 100644
index 00000000000000..e6098a218d092d
--- /dev/null
+++ b/libc/src/complex/crealf16.h
@@ -0,0 +1,27 @@
+//===-- Implementation header for crealf16 ----------------------*- 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_CREALF16_H
+#define LLVM_LIBC_SRC_COMPLEX_CREALF16_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float16 crealf16(cfloat16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_COMPLEX_CREALF16_H
+
+#endif // LIBC_TYPES_HAS_CFLOAT16

diff  --git a/libc/src/complex/creall.h b/libc/src/complex/creall.h
new file mode 100644
index 00000000000000..2a8245f63d6710
--- /dev/null
+++ b/libc/src/complex/creall.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for creall ------------------------*- 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_CREALL_H
+#define LLVM_LIBC_SRC_COMPLEX_CREALL_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+long double creall(_Complex long double x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_COMPLEX_CREALL_H

diff  --git a/libc/src/complex/generic/CMakeLists.txt b/libc/src/complex/generic/CMakeLists.txt
new file mode 100644
index 00000000000000..a63871b32afbf1
--- /dev/null
+++ b/libc/src/complex/generic/CMakeLists.txt
@@ -0,0 +1,137 @@
+add_entrypoint_object(
+  creal
+  SRCS
+    creal.cpp
+  HDRS
+    ../creal.h
+  COMPILE_OPTIONS
+    -O3
+  DEPENDS
+    libc.src.__support.CPP.bit
+    libc.src.__support.complex_type
+)
+
+add_entrypoint_object(
+  crealf
+  SRCS
+    crealf.cpp
+  HDRS
+    ../crealf.h
+  COMPILE_OPTIONS
+    -O3
+  DEPENDS
+    libc.src.__support.CPP.bit
+    libc.src.__support.complex_type
+)
+
+add_entrypoint_object(
+  creall
+  SRCS
+    creall.cpp
+  HDRS
+    ../creall.h
+  COMPILE_OPTIONS
+    -O3
+  DEPENDS
+    libc.src.__support.CPP.bit
+    libc.src.__support.complex_type
+)
+
+add_entrypoint_object(
+  crealf16
+  SRCS
+    crealf16.cpp
+  HDRS
+    ../crealf16.h
+  COMPILE_OPTIONS
+    -O3
+  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(
+  crealf128
+  SRCS
+    crealf128.cpp
+  HDRS
+    ../crealf128.h
+  COMPILE_OPTIONS
+    -O3
+  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(
+  cimag
+  SRCS
+    cimag.cpp
+  HDRS
+    ../cimag.h
+  COMPILE_OPTIONS
+    -O3
+  DEPENDS
+    libc.src.__support.CPP.bit
+    libc.src.__support.complex_type
+)
+
+add_entrypoint_object(
+  cimagf
+  SRCS
+    cimagf.cpp
+  HDRS
+    ../cimagf.h
+  COMPILE_OPTIONS
+    -O3
+  DEPENDS
+    libc.src.__support.CPP.bit
+    libc.src.__support.complex_type
+)
+
+add_entrypoint_object(
+  cimagl
+  SRCS
+    cimagl.cpp
+  HDRS
+    ../cimagl.h
+  COMPILE_OPTIONS
+    -O3
+  DEPENDS
+    libc.src.__support.CPP.bit
+    libc.src.__support.complex_type
+)
+
+add_entrypoint_object(
+  cimagf16
+  SRCS
+    cimagf16.cpp
+  HDRS
+    ../cimagf16.h
+  COMPILE_OPTIONS
+    -O3
+  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(
+  cimagf128
+  SRCS
+    cimagf128.cpp
+  HDRS
+    ../cimagf128.h
+  COMPILE_OPTIONS
+    -O3
+  DEPENDS
+    libc.src.__support.CPP.bit
+    libc.src.__support.complex_type
+    libc.src.__support.macros.properties.types
+    libc.src.__support.macros.properties.complex_types
+)

diff  --git a/libc/src/complex/generic/cimag.cpp b/libc/src/complex/generic/cimag.cpp
new file mode 100644
index 00000000000000..6aa5de4c2e78a8
--- /dev/null
+++ b/libc/src/complex/generic/cimag.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of cimag 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/cimag.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(double, cimag, (_Complex double x)) {
+  Complex<double> x_c = cpp::bit_cast<Complex<double>>(x);
+  return x_c.imag;
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/complex/generic/cimagf.cpp b/libc/src/complex/generic/cimagf.cpp
new file mode 100644
index 00000000000000..f61808c8120773
--- /dev/null
+++ b/libc/src/complex/generic/cimagf.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of cimagf 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/cimagf.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(float, cimagf, (_Complex float x)) {
+  Complex<float> x_c = cpp::bit_cast<Complex<float>>(x);
+  return x_c.imag;
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/complex/generic/cimagf128.cpp b/libc/src/complex/generic/cimagf128.cpp
new file mode 100644
index 00000000000000..c21bd7f4602cc1
--- /dev/null
+++ b/libc/src/complex/generic/cimagf128.cpp
@@ -0,0 +1,25 @@
+//===-- Implementation of cimagf128 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/cimagf128.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(float128, cimagf128, (cfloat128 x)) {
+  Complex<float128> x_c = cpp::bit_cast<Complex<float128>>(x);
+  return x_c.imag;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_CFLOAT128

diff  --git a/libc/src/complex/generic/cimagf16.cpp b/libc/src/complex/generic/cimagf16.cpp
new file mode 100644
index 00000000000000..361687984067b3
--- /dev/null
+++ b/libc/src/complex/generic/cimagf16.cpp
@@ -0,0 +1,25 @@
+//===-- Implementation of cimagf16 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/cimagf16.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(float16, cimagf16, (cfloat16 x)) {
+  Complex<float16> x_c = cpp::bit_cast<Complex<float16>>(x);
+  return x_c.imag;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_CFLOAT16

diff  --git a/libc/src/complex/generic/cimagl.cpp b/libc/src/complex/generic/cimagl.cpp
new file mode 100644
index 00000000000000..1f63ad3a957363
--- /dev/null
+++ b/libc/src/complex/generic/cimagl.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of cimagl 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/cimagl.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(long double, cimagl, (_Complex long double x)) {
+  Complex<long double> x_c = cpp::bit_cast<Complex<long double>>(x);
+  return x_c.imag;
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/complex/generic/creal.cpp b/libc/src/complex/generic/creal.cpp
new file mode 100644
index 00000000000000..e97e1dac2473d8
--- /dev/null
+++ b/libc/src/complex/generic/creal.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of creal 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/creal.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(double, creal, (_Complex double x)) {
+  Complex<double> x_c = cpp::bit_cast<Complex<double>>(x);
+  return x_c.real;
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/complex/generic/crealf.cpp b/libc/src/complex/generic/crealf.cpp
new file mode 100644
index 00000000000000..304c743d5922aa
--- /dev/null
+++ b/libc/src/complex/generic/crealf.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of crealf 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/crealf.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(float, crealf, (_Complex float x)) {
+  Complex<float> x_c = cpp::bit_cast<Complex<float>>(x);
+  return x_c.real;
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/complex/generic/crealf128.cpp b/libc/src/complex/generic/crealf128.cpp
new file mode 100644
index 00000000000000..e72a7782160109
--- /dev/null
+++ b/libc/src/complex/generic/crealf128.cpp
@@ -0,0 +1,25 @@
+//===-- Implementation of crealf128 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/crealf128.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(float128, crealf128, (cfloat128 x)) {
+  Complex<float128> x_c = cpp::bit_cast<Complex<float128>>(x);
+  return x_c.real;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_CFLOAT128

diff  --git a/libc/src/complex/generic/crealf16.cpp b/libc/src/complex/generic/crealf16.cpp
new file mode 100644
index 00000000000000..35142071f0536d
--- /dev/null
+++ b/libc/src/complex/generic/crealf16.cpp
@@ -0,0 +1,25 @@
+//===-- Implementation of crealf16 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/crealf16.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(float16, crealf16, (cfloat16 x)) {
+  Complex<float16> x_c = cpp::bit_cast<Complex<float16>>(x);
+  return x_c.real;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_CFLOAT16

diff  --git a/libc/src/complex/generic/creall.cpp b/libc/src/complex/generic/creall.cpp
new file mode 100644
index 00000000000000..9d43f977cf300e
--- /dev/null
+++ b/libc/src/complex/generic/creall.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of creall 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/creall.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(long double, creall, (_Complex long double x)) {
+  Complex<long double> x_c = cpp::bit_cast<Complex<long double>>(x);
+  return x_c.real;
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt
index ddc6a5c7f6965f..e121555bd60a9f 100644
--- a/libc/test/src/CMakeLists.txt
+++ b/libc/test/src/CMakeLists.txt
@@ -47,6 +47,7 @@ function(add_fp_unittest name)
 endfunction(add_fp_unittest)
 
 add_subdirectory(__support)
+add_subdirectory(complex)
 add_subdirectory(ctype)
 add_subdirectory(errno)
 add_subdirectory(fenv)

diff  --git a/libc/test/src/complex/CImagTest.h b/libc/test/src/complex/CImagTest.h
new file mode 100644
index 00000000000000..6d2f9350026691
--- /dev/null
+++ b/libc/test/src/complex/CImagTest.h
@@ -0,0 +1,74 @@
+//===-- Utility class to test 
diff erent flavors of cimag --------*- 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_CIMAGTEST_H
+#define LLVM_LIBC_TEST_SRC_COMPLEX_CIMAGTEST_H
+
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+#include "hdr/math_macros.h"
+
+template <typename CFPT, typename FPT>
+class CImagTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+
+  DECLARE_SPECIAL_CONSTANTS(FPT)
+
+public:
+  typedef FPT (*CImagFunc)(CFPT);
+
+  void testSpecialNumbers(CImagFunc func) {
+    EXPECT_FP_EQ(func(CFPT(67.123 + aNaN * 1.0i)), aNaN);
+    EXPECT_FP_EQ(func(CFPT(78.319 + neg_aNaN * 1.0i)), neg_aNaN);
+    EXPECT_FP_EQ(func(CFPT(7813.131 + sNaN * 1.0i)), sNaN);
+    EXPECT_FP_EQ(func(CFPT(7824.152 + neg_sNaN * 1.0i)), neg_sNaN);
+    EXPECT_FP_EQ(func(CFPT(9024.2442 + inf * 1.0i)), inf);
+    EXPECT_FP_EQ(func(CFPT(8923.124 + neg_inf * 1.0i)), neg_inf);
+    EXPECT_FP_EQ(func(CFPT(782.124 + min_normal * 1.0i)), min_normal);
+    EXPECT_FP_EQ(func(CFPT(2141.2352 + max_normal * 1.0i)), max_normal);
+    EXPECT_FP_EQ(func(CFPT(341.134 + neg_max_normal * 1.0i)), neg_max_normal);
+    EXPECT_FP_EQ(func(CFPT(781.142 + min_denormal * 1.0i)), min_denormal);
+    EXPECT_FP_EQ(func(CFPT(781.134 + neg_min_denormal * 1.0i)),
+                 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);
+  }
+
+  void testRoundedNumbers(CImagFunc func) {
+    EXPECT_FP_EQ(func((CFPT)(4523.1413 + 12413.1414i)), (FPT)(12413.1414));
+    EXPECT_FP_EQ(func((CFPT)(-4523.1413 + 12413.1414i)), (FPT)(12413.1414));
+    EXPECT_FP_EQ(func((CFPT)(4523.1413 - 12413.1414i)), (FPT)(-12413.1414));
+    EXPECT_FP_EQ(func((CFPT)(-4523.1413 - 12413.1414i)), (FPT)(-12413.1414));
+
+    EXPECT_FP_EQ(func((CFPT)(3210.5678 + 9876.5432i)), (FPT)(9876.5432));
+    EXPECT_FP_EQ(func((CFPT)(-3210.5678 + 9876.5432i)), (FPT)(9876.5432));
+    EXPECT_FP_EQ(func((CFPT)(3210.5678 - 9876.5432i)), (FPT)(-9876.5432));
+    EXPECT_FP_EQ(func((CFPT)(-3210.5678 - 9876.5432i)), (FPT)(-9876.5432));
+
+    EXPECT_FP_EQ(func((CFPT)(1234.4321 + 4321.1234i)), (FPT)(4321.1234));
+    EXPECT_FP_EQ(func((CFPT)(-1234.4321 + 4321.1234i)), (FPT)(4321.1234));
+    EXPECT_FP_EQ(func((CFPT)(1234.4321 - 4321.1234i)), (FPT)(-4321.1234));
+    EXPECT_FP_EQ(func((CFPT)(-1234.4321 - 4321.1234i)), (FPT)(-4321.1234));
+
+    EXPECT_FP_EQ(func((CFPT)(6789.1234 + 8765.6789i)), (FPT)(8765.6789));
+    EXPECT_FP_EQ(func((CFPT)(-6789.1234 + 8765.6789i)), (FPT)(8765.6789));
+    EXPECT_FP_EQ(func((CFPT)(6789.1234 - 8765.6789i)), (FPT)(-8765.6789));
+    EXPECT_FP_EQ(func((CFPT)(-6789.1234 - 8765.6789i)), (FPT)(-8765.6789));
+  }
+};
+
+#define LIST_CIMAG_TESTS(U, T, func)                                           \
+  using LlvmLibcCImagTest = CImagTest<U, T>;                                   \
+  TEST_F(LlvmLibcCImagTest, SpecialNumbers) { testSpecialNumbers(&func); }     \
+  TEST_F(LlvmLibcCImagTest, RoundedNumbers) { testRoundedNumbers(&func); }
+
+#endif // LLVM_LIBC_TEST_SRC_COMPLEX_CIMAGTEST_H

diff  --git a/libc/test/src/complex/CMakeLists.txt b/libc/test/src/complex/CMakeLists.txt
new file mode 100644
index 00000000000000..8f49e6d79e1796
--- /dev/null
+++ b/libc/test/src/complex/CMakeLists.txt
@@ -0,0 +1,121 @@
+add_custom_target(libc-complex-unittests)
+
+add_libc_test(
+  creal_test
+  SUITE
+    libc-complex-unittests
+  SRCS
+    creal_test.cpp
+  DEPENDS
+    libc.src.complex.creal
+  LINK_LIBRARIES
+      LibcFPTestHelpers
+)
+
+add_libc_test(
+  crealf_test
+  SUITE
+    libc-complex-unittests
+  SRCS
+    crealf_test.cpp
+  DEPENDS
+    libc.src.complex.crealf
+  LINK_LIBRARIES
+    LibcFPTestHelpers
+)
+
+add_libc_test(
+  creall_test
+  SUITE
+    libc-complex-unittests
+  SRCS
+    creall_test.cpp
+  DEPENDS
+    libc.src.complex.creall
+  LINK_LIBRARIES
+    LibcFPTestHelpers
+)
+
+add_libc_test(
+  crealf16_test
+  SUITE
+    libc-complex-unittests
+  SRCS
+    crealf16_test.cpp
+  DEPENDS
+    libc.src.complex.crealf16
+  LINK_LIBRARIES
+    LibcFPTestHelpers
+)
+
+add_libc_test(
+  crealf128_test
+  SUITE
+    libc-complex-unittests
+  SRCS
+    crealf128_test.cpp
+  DEPENDS
+    libc.src.complex.crealf128
+  LINK_LIBRARIES
+    LibcFPTestHelpers
+)
+
+add_libc_test(
+  cimag_test
+  SUITE
+    libc-complex-unittests
+  SRCS
+    cimag_test.cpp
+  DEPENDS
+    libc.src.complex.cimag
+  LINK_LIBRARIES
+    LibcFPTestHelpers
+)
+
+add_libc_test(
+  cimagf_test
+  SUITE
+    libc-complex-unittests
+  SRCS
+    cimagf_test.cpp
+  DEPENDS
+    libc.src.complex.cimagf
+  LINK_LIBRARIES
+    LibcFPTestHelpers
+)
+
+add_libc_test(
+  cimagl_test
+  SUITE
+    libc-complex-unittests
+  SRCS
+    cimagl_test.cpp
+  DEPENDS
+    libc.src.complex.cimagl
+  LINK_LIBRARIES
+    LibcFPTestHelpers
+)
+
+add_libc_test(
+  cimagf16_test
+  SUITE
+    libc-complex-unittests
+  SRCS
+    cimagf16_test.cpp
+  DEPENDS
+    libc.src.complex.cimagf16
+  LINK_LIBRARIES
+    LibcFPTestHelpers
+)
+
+add_libc_test(
+  cimagf128_test
+  SUITE
+    libc-complex-unittests
+  SRCS
+    cimagf128_test.cpp
+  DEPENDS
+    libc.src.complex.cimagf128
+  LINK_LIBRARIES
+    LibcFPTestHelpers
+)

diff  --git a/libc/test/src/complex/CRealTest.h b/libc/test/src/complex/CRealTest.h
new file mode 100644
index 00000000000000..a25555b506e225
--- /dev/null
+++ b/libc/test/src/complex/CRealTest.h
@@ -0,0 +1,72 @@
+//===-- Utility class to test 
diff erent flavors of creal --------*- 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_CREALTEST_H
+#define LLVM_LIBC_TEST_SRC_COMPLEX_CREALTEST_H
+
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+#include "hdr/math_macros.h"
+
+template <typename CFPT, typename FPT>
+class CRealTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+
+  DECLARE_SPECIAL_CONSTANTS(FPT)
+
+public:
+  typedef FPT (*CRealFunc)(CFPT);
+
+  void testSpecialNumbers(CRealFunc func) {
+    EXPECT_FP_EQ(func(CFPT(aNaN + 67.123i)), aNaN);
+    EXPECT_FP_EQ(func(CFPT(neg_aNaN + 78.319i)), neg_aNaN);
+    EXPECT_FP_EQ(func(CFPT(sNaN + 7813.131i)), sNaN);
+    EXPECT_FP_EQ(func(CFPT(neg_sNaN + 7824.152i)), neg_sNaN);
+    EXPECT_FP_EQ(func(CFPT(inf + 9024.2442i)), inf);
+    EXPECT_FP_EQ(func(CFPT(neg_inf + 8923.124i)), neg_inf);
+    EXPECT_FP_EQ(func(CFPT(min_normal + 782.124i)), min_normal);
+    EXPECT_FP_EQ(func(CFPT(max_normal + 2141.2352i)), max_normal);
+    EXPECT_FP_EQ(func(CFPT(neg_max_normal + 341.134i)), neg_max_normal);
+    EXPECT_FP_EQ(func(CFPT(min_denormal + 781.142i)), min_denormal);
+    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);
+  }
+
+  void testRoundedNumbers(CRealFunc func) {
+    EXPECT_FP_EQ(func((CFPT)(4523.1413 + 12413.1414i)), (FPT)(4523.1413));
+    EXPECT_FP_EQ(func((CFPT)(-4523.1413 + 12413.1414i)), (FPT)(-4523.1413));
+    EXPECT_FP_EQ(func((CFPT)(4523.1413 - 12413.1414i)), (FPT)(4523.1413));
+    EXPECT_FP_EQ(func((CFPT)(-4523.1413 - 12413.1414i)), (FPT)(-4523.1413));
+
+    EXPECT_FP_EQ(func((CFPT)(3210.5678 + 9876.5432i)), (FPT)(3210.5678));
+    EXPECT_FP_EQ(func((CFPT)(-3210.5678 + 9876.5432i)), (FPT)(-3210.5678));
+    EXPECT_FP_EQ(func((CFPT)(3210.5678 - 9876.5432i)), (FPT)(3210.5678));
+    EXPECT_FP_EQ(func((CFPT)(-3210.5678 - 9876.5432i)), (FPT)(-3210.5678));
+
+    EXPECT_FP_EQ(func((CFPT)(1234.4321 + 4321.1234i)), (FPT)(1234.4321));
+    EXPECT_FP_EQ(func((CFPT)(-1234.4321 + 4321.1234i)), (FPT)(-1234.4321));
+    EXPECT_FP_EQ(func((CFPT)(1234.4321 - 4321.1234i)), (FPT)(1234.4321));
+    EXPECT_FP_EQ(func((CFPT)(-1234.4321 - 4321.1234i)), (FPT)(-1234.4321));
+
+    EXPECT_FP_EQ(func((CFPT)(6789.1234 + 8765.6789i)), (FPT)(6789.1234));
+    EXPECT_FP_EQ(func((CFPT)(-6789.1234 + 8765.6789i)), (FPT)(-6789.1234));
+    EXPECT_FP_EQ(func((CFPT)(6789.1234 - 8765.6789i)), (FPT)(6789.1234));
+    EXPECT_FP_EQ(func((CFPT)(-6789.1234 - 8765.6789i)), (FPT)(-6789.1234));
+  }
+};
+
+#define LIST_CREAL_TESTS(U, T, func)                                           \
+  using LlvmLibcCRealTest = CRealTest<U, T>;                                   \
+  TEST_F(LlvmLibcCRealTest, SpecialNumbers) { testSpecialNumbers(&func); }     \
+  TEST_F(LlvmLibcCRealTest, RoundedNumbers) { testRoundedNumbers(&func); }
+
+#endif // LLVM_LIBC_TEST_SRC_COMPLEX_CREALTEST_H

diff  --git a/libc/test/src/complex/cimag_test.cpp b/libc/test/src/complex/cimag_test.cpp
new file mode 100644
index 00000000000000..706f54422b3cf8
--- /dev/null
+++ b/libc/test/src/complex/cimag_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for cimag -----------------------------------------------===//
+//
+// 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 "CImagTest.h"
+
+#include "src/complex/cimag.h"
+
+LIST_CIMAG_TESTS(_Complex double, double, LIBC_NAMESPACE::cimag)

diff  --git a/libc/test/src/complex/cimagf128_test.cpp b/libc/test/src/complex/cimagf128_test.cpp
new file mode 100644
index 00000000000000..50ddc0ab061663
--- /dev/null
+++ b/libc/test/src/complex/cimagf128_test.cpp
@@ -0,0 +1,17 @@
+//===-- Unittests for cimagf128 -------------------------------------------===//
+//
+// 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 "CImagTest.h"
+
+#include "src/complex/cimagf128.h"
+
+#if defined(LIBC_TYPES_HAS_CFLOAT128)
+
+LIST_CIMAG_TESTS(cfloat128, float128, LIBC_NAMESPACE::cimagf128)
+
+#endif // LIBC_TYPES_HAS_CFLOAT128

diff  --git a/libc/test/src/complex/cimagf16_test.cpp b/libc/test/src/complex/cimagf16_test.cpp
new file mode 100644
index 00000000000000..65a69787ddbd66
--- /dev/null
+++ b/libc/test/src/complex/cimagf16_test.cpp
@@ -0,0 +1,17 @@
+//===-- Unittests for cimagf16 --------------------------------------------===//
+//
+// 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 "CImagTest.h"
+
+#include "src/complex/cimagf16.h"
+
+#if defined(LIBC_TYPES_HAS_CFLOAT16)
+
+LIST_CIMAG_TESTS(cfloat16, float16, LIBC_NAMESPACE::cimagf16)
+
+#endif // LIBC_TYPES_HAS_CFLOAT16

diff  --git a/libc/test/src/complex/cimagf_test.cpp b/libc/test/src/complex/cimagf_test.cpp
new file mode 100644
index 00000000000000..abc9225031e134
--- /dev/null
+++ b/libc/test/src/complex/cimagf_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for cimagf ----------------------------------------------===//
+//
+// 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 "CImagTest.h"
+
+#include "src/complex/cimagf.h"
+
+LIST_CIMAG_TESTS(_Complex float, float, LIBC_NAMESPACE::cimagf)

diff  --git a/libc/test/src/complex/cimagl_test.cpp b/libc/test/src/complex/cimagl_test.cpp
new file mode 100644
index 00000000000000..156e4c6bc852d4
--- /dev/null
+++ b/libc/test/src/complex/cimagl_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for cimagl ----------------------------------------------===//
+//
+// 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 "CImagTest.h"
+
+#include "src/complex/cimagl.h"
+
+LIST_CIMAG_TESTS(_Complex long double, long double, LIBC_NAMESPACE::cimagl)

diff  --git a/libc/test/src/complex/creal_test.cpp b/libc/test/src/complex/creal_test.cpp
new file mode 100644
index 00000000000000..14dc550932d7d5
--- /dev/null
+++ b/libc/test/src/complex/creal_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for creal -----------------------------------------------===//
+//
+// 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 "CRealTest.h"
+
+#include "src/complex/creal.h"
+
+LIST_CREAL_TESTS(_Complex double, double, LIBC_NAMESPACE::creal)

diff  --git a/libc/test/src/complex/crealf128_test.cpp b/libc/test/src/complex/crealf128_test.cpp
new file mode 100644
index 00000000000000..7626eeebca2783
--- /dev/null
+++ b/libc/test/src/complex/crealf128_test.cpp
@@ -0,0 +1,17 @@
+//===-- Unittests for crealf128 -------------------------------------------===//
+//
+// 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 "CRealTest.h"
+
+#include "src/complex/crealf128.h"
+
+#if defined(LIBC_TYPES_HAS_CFLOAT128)
+
+LIST_CREAL_TESTS(cfloat128, float128, LIBC_NAMESPACE::crealf128)
+
+#endif // LIBC_TYPES_HAS_CFLOAT128

diff  --git a/libc/test/src/complex/crealf16_test.cpp b/libc/test/src/complex/crealf16_test.cpp
new file mode 100644
index 00000000000000..97346aad615f7e
--- /dev/null
+++ b/libc/test/src/complex/crealf16_test.cpp
@@ -0,0 +1,17 @@
+//===-- Unittests for crealf16 --------------------------------------------===//
+//
+// 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 "CRealTest.h"
+
+#include "src/complex/crealf16.h"
+
+#if defined(LIBC_TYPES_HAS_CFLOAT16)
+
+LIST_CREAL_TESTS(cfloat16, float16, LIBC_NAMESPACE::crealf16)
+
+#endif // LIBC_TYPES_HAS_CFLOAT16

diff  --git a/libc/test/src/complex/crealf_test.cpp b/libc/test/src/complex/crealf_test.cpp
new file mode 100644
index 00000000000000..aa54f54793e2a6
--- /dev/null
+++ b/libc/test/src/complex/crealf_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for crealf ----------------------------------------------===//
+//
+// 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 "CRealTest.h"
+
+#include "src/complex/crealf.h"
+
+LIST_CREAL_TESTS(_Complex float, float, LIBC_NAMESPACE::crealf)

diff  --git a/libc/test/src/complex/creall_test.cpp b/libc/test/src/complex/creall_test.cpp
new file mode 100644
index 00000000000000..6985dbc2590a77
--- /dev/null
+++ b/libc/test/src/complex/creall_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for creall ----------------------------------------------===//
+//
+// 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 "CRealTest.h"
+
+#include "src/complex/creall.h"
+
+LIST_CREAL_TESTS(_Complex long double, long double, LIBC_NAMESPACE::creall)


        


More information about the libc-commits mailing list