Skip to content

[libc][complex] Set up headers and add documentation for complex.h. #111659

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down
65 changes: 65 additions & 0 deletions libc/docs/complex.rst
Original file line number Diff line number Diff line change
@@ -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 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
1 change: 1 addition & 0 deletions libc/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ stages there is no ABI stability in any form.
libc_search
c23
ctype
complex
signal
threads
setjmp
Expand Down
10 changes: 10 additions & 0 deletions libc/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions libc/include/complex.h.def
Original file line number Diff line number Diff line change
@@ -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
6 changes: 6 additions & 0 deletions libc/include/llvm-libc-macros/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 24 additions & 0 deletions libc/include/llvm-libc-macros/complex-macros.h
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions libc/src/__support/CPP/type_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
40 changes: 40 additions & 0 deletions libc/src/__support/CPP/type_traits/is_complex.h
Original file line number Diff line number Diff line change
@@ -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
89 changes: 89 additions & 0 deletions libc/test/UnitTest/FPMatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) \
Expand Down
10 changes: 10 additions & 0 deletions libc/test/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 19 additions & 0 deletions libc/test/include/complex_test.cpp
Original file line number Diff line number Diff line change
@@ -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); }