[libc-commits] [libc] f4ba6a6 - [libc][complex] Set up headers and add documentation for complex.h. (#111659)

via libc-commits libc-commits at lists.llvm.org
Mon Oct 14 10:35:08 PDT 2024


Author: Shourya Goel
Date: 2024-10-14T13:35:04-04:00
New Revision: f4ba6a654dd962aed45710fa049539537cf1f24c

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

LOG: [libc][complex] Set up headers and add documentation for complex.h. (#111659)

Refer: 7.3.1 from [ISO
SPEC](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf)

I have added complex variants of F16 and F128 in libc doc but have
omitted support for them since we will have to first investigate how
their support matrix for clang and gcc looks like, and then add header
guards for them accordingly. Planning to add them in follow up PRs once
this gets landed.

Added: 
    libc/docs/complex.rst
    libc/include/complex.h.def
    libc/include/llvm-libc-macros/complex-macros.h
    libc/src/__support/CPP/type_traits/is_complex.h
    libc/test/include/complex_test.cpp

Modified: 
    libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
    libc/docs/index.rst
    libc/include/CMakeLists.txt
    libc/include/llvm-libc-macros/CMakeLists.txt
    libc/src/__support/CPP/type_traits.h
    libc/test/UnitTest/FPMatcher.h
    libc/test/include/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
index 8643c9bb48ad41..7af67e629471cb 100644
--- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
+++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
@@ -152,6 +152,8 @@ function(_get_common_compile_options output_var flags)
     endif()
     list(APPEND compile_options "-Wconversion")
     list(APPEND compile_options "-Wno-sign-conversion")
+    # Silence this warning because _Complex is a part of C99.
+    list(APPEND compile_options "-Wno-c99-extensions")
     list(APPEND compile_options "-Wimplicit-fallthrough")
     list(APPEND compile_options "-Wwrite-strings")
     list(APPEND compile_options "-Wextra-semi")
@@ -227,6 +229,8 @@ function(_get_common_test_compile_options output_var c_test flags)
     # list(APPEND compile_options "-Wimplicit-fallthrough")
     # list(APPEND compile_options "-Wwrite-strings")
     # list(APPEND compile_options "-Wextra-semi")
+    # Silence this warning because _Complex is a part of C99.
+    list(APPEND compile_options "-Wno-c99-extensions")
     # if(NOT CMAKE_COMPILER_IS_GNUCXX)
     #   list(APPEND compile_options "-Wnewline-eof")
     #   list(APPEND compile_options "-Wnonportable-system-include-path")

diff  --git a/libc/docs/complex.rst b/libc/docs/complex.rst
new file mode 100644
index 00000000000000..09fbdd7c6179ef
--- /dev/null
+++ b/libc/docs/complex.rst
@@ -0,0 +1,65 @@
+.. include:: check.rst
+
+=========
+complex.h
+=========
+
+Macros
+======
+
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| <Func>    | <Func_f> (float) | <Func> (double) | <Func_l> (long double) | <Func_f16> (float16) | <Func_f128> (float128) | C23 Definition Section | C23 Error Handling Section |
++===========+==================+=================+========================+======================+========================+========================+============================+
+| CMPLX     |                  |                 |                        |                      |                        | 7.3.9.3                | N/A                        |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+
+Functions
+=========
+
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| <Func>    | <Func_f> (float) | <Func> (double) | <Func_l> (long double) | <Func_f16> (float16) | <Func_f128> (float128) | C23 Definition Section | C23 Error Handling Section |
++===========+==================+=================+========================+======================+========================+========================+============================+
+| cacos     |                  |                 |                        |                      |                        | 7.3.5.1                | G.6.2.1                    |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| casin     |                  |                 |                        |                      |                        | 7.3.5.2                | N/A                        |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| catan     |                  |                 |                        |                      |                        | 7.3.5.3                | N/A                        |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| ccos      |                  |                 |                        |                      |                        | 7.3.5.4                | N/A                        |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| csin      |                  |                 |                        |                      |                        | 7.3.5.5                | N/A                        |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| ctan      |                  |                 |                        |                      |                        | 7.3.5.6                | N/A                        |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| cacosh    |                  |                 |                        |                      |                        | 7.3.6.1                | G.6.3.1                    |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| casinh    |                  |                 |                        |                      |                        | 7.3.6.2                | G.6.3.2                    |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| catanh    |                  |                 |                        |                      |                        | 7.3.6.3                | G.6.3.3                    |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| ccosh     |                  |                 |                        |                      |                        | 7.3.6.4                | G.6.3.4                    |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| csinh     |                  |                 |                        |                      |                        | 7.3.6.5                | G.6.3.5                    |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| ctanh     |                  |                 |                        |                      |                        | 7.3.6.6                | G.6.3.6                    |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| cexp      |                  |                 |                        |                      |                        | 7.3.7.1                | G.6.4.1                    |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| clog      |                  |                 |                        |                      |                        | 7.3.7.2                | G.6.4.2                    |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| cabs      |                  |                 |                        |                      |                        | 7.3.8.1                | N/A                        |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| cpow      |                  |                 |                        |                      |                        | 7.3.8.2                | G.6.5.1                    |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| csqrt     |                  |                 |                        |                      |                        | 7.3.8.3                | G.6.5.2                    |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| carg      |                  |                 |                        |                      |                        | 7.3.9.1                | N/A                        |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| cimag     |                  |                 |                        |                      |                        | 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                        |
++-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+

diff  --git a/libc/docs/index.rst b/libc/docs/index.rst
index d089a800ab90ab..6f759aa215b62c 100644
--- a/libc/docs/index.rst
+++ b/libc/docs/index.rst
@@ -73,6 +73,7 @@ stages there is no ABI stability in any form.
    libc_search
    c23
    ctype
+   complex
    signal
    threads
    setjmp

diff  --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 1f3cb59f69e96e..5deb5258d532fe 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -202,6 +202,16 @@ add_header_macro(
     .llvm-libc-macros.assert_macros
 )
 
+add_header_macro(
+  complex
+  ../libc/newhdrgen/yaml/complex.yaml
+  complex.h.def
+  complex.h
+  DEPENDS
+    .llvm_libc_common_h
+    .llvm-libc-macros.complex_macros
+)
+
 add_header_macro(
   setjmp
   ../libc/newhdrgen/yaml/setjmp.yaml

diff  --git a/libc/include/complex.h.def b/libc/include/complex.h.def
new file mode 100644
index 00000000000000..65f5765573e840
--- /dev/null
+++ b/libc/include/complex.h.def
@@ -0,0 +1,17 @@
+//===-- C standard library header complex.h -------------------------------===//
+//
+// 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_COMPLEX_H
+#define LLVM_LIBC_COMPLEX_H
+
+#include "__llvm-libc-common.h"
+#include "llvm-libc-macros/complex-macros.h"
+
+%%public_api()
+
+#endif // LLVM_LIBC_COMPLEX_H

diff  --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt
index 2ba437c8437f28..75194923a452fb 100644
--- a/libc/include/llvm-libc-macros/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/CMakeLists.txt
@@ -61,6 +61,12 @@ add_macro_header(
     fcntl-macros.h
 )
 
+add_macro_header(
+  complex_macros
+  HDR
+    complex-macros.h
+)
+
 add_macro_header(
   features_macros
   HDR

diff  --git a/libc/include/llvm-libc-macros/complex-macros.h b/libc/include/llvm-libc-macros/complex-macros.h
new file mode 100644
index 00000000000000..427c68d289e0bd
--- /dev/null
+++ b/libc/include/llvm-libc-macros/complex-macros.h
@@ -0,0 +1,24 @@
+//===-- Definition of macros to be used with complex functions ------------===//
+//
+// 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_MACROS_COMPLEX_MACROS_H
+#define __LLVM_LIBC_MACROS_COMPLEX_MACROS_H
+
+#ifndef __STDC_NO_COMPLEX__
+
+#define __STDC_VERSION_COMPLEX_H__ 202311L
+
+#define complex _Complex
+#define _Complex_I ((_Complex float)1.0fi)
+#define I _Complex_I
+
+// TODO: Add imaginary macros once GCC or Clang support _Imaginary builtin-type.
+
+#endif
+
+#endif // __LLVM_LIBC_MACROS_COMPLEX_MACROS_H

diff  --git a/libc/src/__support/CPP/type_traits.h b/libc/src/__support/CPP/type_traits.h
index d50b6612656dbb..cef4e5d1f0b139 100644
--- a/libc/src/__support/CPP/type_traits.h
+++ b/libc/src/__support/CPP/type_traits.h
@@ -25,6 +25,7 @@
 #include "src/__support/CPP/type_traits/is_array.h"
 #include "src/__support/CPP/type_traits/is_base_of.h"
 #include "src/__support/CPP/type_traits/is_class.h"
+#include "src/__support/CPP/type_traits/is_complex.h"
 #include "src/__support/CPP/type_traits/is_const.h"
 #include "src/__support/CPP/type_traits/is_constant_evaluated.h"
 #include "src/__support/CPP/type_traits/is_convertible.h"

diff  --git a/libc/src/__support/CPP/type_traits/is_complex.h b/libc/src/__support/CPP/type_traits/is_complex.h
new file mode 100644
index 00000000000000..4f5ee9abdb33a5
--- /dev/null
+++ b/libc/src/__support/CPP/type_traits/is_complex.h
@@ -0,0 +1,40 @@
+//===-- is_complex type_traits ----------------------------------*- 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_CPP_TYPE_TRAITS_IS_COMPLEX_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COMPLEX_H
+
+#include "src/__support/CPP/type_traits/is_same.h"
+#include "src/__support/CPP/type_traits/remove_cv.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// is_complex
+template <typename T> struct is_complex {
+private:
+  template <typename Head, typename... Args>
+  LIBC_INLINE_VAR static constexpr bool __is_unqualified_any_of() {
+    return (... || is_same_v<remove_cv_t<Head>, Args>);
+  }
+
+public:
+  LIBC_INLINE_VAR static constexpr bool value =
+      __is_unqualified_any_of<T, _Complex float, _Complex double,
+                              _Complex long double>();
+};
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_complex_v = is_complex<T>::value;
+template <typename T1, typename T2>
+LIBC_INLINE_VAR constexpr bool is_complex_type_same() {
+  return is_same_v<remove_cv_t<T1>, T2>;
+}
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COMPLEX_H

diff  --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h
index 3cf0b04952ec07..5220b1245bf3a5 100644
--- a/libc/test/UnitTest/FPMatcher.h
+++ b/libc/test/UnitTest/FPMatcher.h
@@ -60,10 +60,95 @@ template <typename T, TestCond Condition> class FPMatcher : public Matcher<T> {
   }
 };
 
+template <typename T, TestCond Condition> class CFPMatcher : public Matcher<T> {
+  static_assert(
+      cpp::is_complex_v<T>,
+      "CFPMatcher can only be used with complex floating point values.");
+  static_assert(Condition == TestCond::EQ || Condition == TestCond::NE,
+                "Unsupported CFPMatcher test condition.");
+
+  T expected;
+  T actual;
+
+public:
+  CFPMatcher(T expectedValue) : expected(expectedValue) {}
+
+  template <typename CFT> bool matchComplex() {
+    CFT *actualCmplxPtr = reinterpret_cast<CFT *>(&actual);
+    CFT *expectedCmplxPtr = reinterpret_cast<CFT *>(&expected);
+    CFT actualReal = actualCmplxPtr[0];
+    CFT actualImag = actualCmplxPtr[1];
+    CFT expectedReal = expectedCmplxPtr[0];
+    CFT expectedImag = expectedCmplxPtr[1];
+    fputil::FPBits<CFT> actualRealBits(actualReal),
+        expectedRealBits(expectedReal);
+    fputil::FPBits<CFT> actualImagBits(actualImag),
+        expectedImagBits(expectedImag);
+    if (Condition == TestCond::EQ)
+      return ((actualRealBits.is_nan() && expectedRealBits.is_nan()) ||
+              (actualRealBits.uintval() == expectedRealBits.uintval())) &&
+             ((actualImagBits.is_nan() && expectedImagBits.is_nan()) ||
+              (actualImagBits.uintval() == expectedImagBits.uintval()));
+
+    // If condition == TestCond::NE.
+    if (actualRealBits.is_nan() && expectedRealBits.is_nan())
+      return !expectedRealBits.is_nan() && !expectedImagBits.is_nan();
+    if (actualRealBits.is_nan())
+      return !expectedRealBits.is_nan();
+    if (actualImagBits.is_nan())
+      return !expectedImagBits.is_nan();
+    return (expectedRealBits.is_nan() ||
+            actualRealBits.uintval() != expectedRealBits.uintval()) &&
+           (expectedImagBits.is_nan() ||
+            actualImagBits.uintval() != expectedImagBits.uintval());
+  }
+
+  template <typename CFT> void explainErrorComplex() {
+    CFT *actualCmplxPtr = reinterpret_cast<CFT *>(&actual);
+    CFT *expectedCmplxPtr = reinterpret_cast<CFT *>(&expected);
+    CFT actualReal = actualCmplxPtr[0];
+    CFT actualImag = actualCmplxPtr[1];
+    CFT expectedReal = expectedCmplxPtr[0];
+    CFT expectedImag = expectedCmplxPtr[1];
+    tlog << "Expected complex floating point value: "
+         << str(fputil::FPBits<CFT>(expectedReal)) + " + " +
+                str(fputil::FPBits<CFT>(expectedImag)) + "i"
+         << '\n';
+    tlog << "Actual complex floating point value: "
+         << str(fputil::FPBits<CFT>(actualReal)) + " + " +
+                str(fputil::FPBits<CFT>(actualImag)) + "i"
+         << '\n';
+  }
+
+  bool match(T actualValue) {
+    actual = actualValue;
+    if (cpp::is_complex_type_same<T, _Complex float>())
+      return matchComplex<float>();
+    else if (cpp::is_complex_type_same<T, _Complex double>())
+      return matchComplex<double>();
+    else if (cpp::is_complex_type_same<T, _Complex long double>())
+      return matchComplex<long double>();
+  }
+
+  void explainError() override {
+    if (cpp::is_complex_type_same<T, _Complex float>())
+      return explainErrorComplex<float>();
+    else if (cpp::is_complex_type_same<T, _Complex double>())
+      return explainErrorComplex<double>();
+    else if (cpp::is_complex_type_same<T, _Complex long double>())
+      return explainErrorComplex<long double>();
+  }
+};
+
 template <TestCond C, typename T> FPMatcher<T, C> getMatcher(T expectedValue) {
   return FPMatcher<T, C>(expectedValue);
 }
 
+template <TestCond C, typename T>
+CFPMatcher<T, C> getMatcherComplex(T expectedValue) {
+  return CFPMatcher<T, C>(expectedValue);
+}
+
 template <typename T> struct FPTest : public Test {
   using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
   using StorageType = typename FPBits::StorageType;
@@ -125,6 +210,10 @@ template <typename T> struct FPTest : public Test {
   EXPECT_THAT(actual, LIBC_NAMESPACE::testing::getMatcher<                     \
                           LIBC_NAMESPACE::testing::TestCond::EQ>(expected))
 
+#define EXPECT_CFP_EQ(expected, actual)                                        \
+  EXPECT_THAT(actual, LIBC_NAMESPACE::testing::getMatcherComplex<              \
+                          LIBC_NAMESPACE::testing::TestCond::EQ>(expected))
+
 #define TEST_FP_EQ(expected, actual)                                           \
   LIBC_NAMESPACE::testing::getMatcher<LIBC_NAMESPACE::testing::TestCond::EQ>(  \
       expected)                                                                \

diff  --git a/libc/test/include/CMakeLists.txt b/libc/test/include/CMakeLists.txt
index 92185160628790..0d882eb49a7386 100644
--- a/libc/test/include/CMakeLists.txt
+++ b/libc/test/include/CMakeLists.txt
@@ -11,6 +11,16 @@ add_libc_test(
     libc.include.llvm-libc-macros.assert_macros
 )
 
+add_libc_test(
+  complex_test
+  SUITE
+    libc_include_tests
+  SRCS
+    complex_test.cpp
+  DEPENDS
+    libc.include.llvm-libc-macros.complex_macros
+)
+
 add_libc_test(
   sys_queue_test
   SUITE

diff  --git a/libc/test/include/complex_test.cpp b/libc/test/include/complex_test.cpp
new file mode 100644
index 00000000000000..f6bfe997d98dd1
--- /dev/null
+++ b/libc/test/include/complex_test.cpp
@@ -0,0 +1,19 @@
+//===-- Unittests for complex ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "include/llvm-libc-macros/complex-macros.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+TEST(LlvmLibcComplexTest, VersionMacro) {
+  EXPECT_EQ(__STDC_VERSION_COMPLEX_H__, 202311L);
+}
+
+TEST(LlvmLibcComplexTest, IMacro) { EXPECT_CFP_EQ(1.0fi, I); }
+
+TEST(LlvmLibcComplexTest, _Complex_IMacro) { EXPECT_CFP_EQ(1.0fi, _Complex_I); }


        


More information about the libc-commits mailing list