Skip to content

Commit e421740

Browse files
Sh0g0-1758DanielCChen
authored andcommitted
[libc][complex] Set up headers and add documentation for complex.h. (llvm#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.
1 parent f2251e2 commit e421740

File tree

12 files changed

+286
-0
lines changed

12 files changed

+286
-0
lines changed

libc/cmake/modules/LLVMLibCCompileOptionRules.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ function(_get_common_compile_options output_var flags)
152152
endif()
153153
list(APPEND compile_options "-Wconversion")
154154
list(APPEND compile_options "-Wno-sign-conversion")
155+
# Silence this warning because _Complex is a part of C99.
156+
list(APPEND compile_options "-Wno-c99-extensions")
155157
list(APPEND compile_options "-Wimplicit-fallthrough")
156158
list(APPEND compile_options "-Wwrite-strings")
157159
list(APPEND compile_options "-Wextra-semi")
@@ -227,6 +229,8 @@ function(_get_common_test_compile_options output_var c_test flags)
227229
# list(APPEND compile_options "-Wimplicit-fallthrough")
228230
# list(APPEND compile_options "-Wwrite-strings")
229231
# list(APPEND compile_options "-Wextra-semi")
232+
# Silence this warning because _Complex is a part of C99.
233+
list(APPEND compile_options "-Wno-c99-extensions")
230234
# if(NOT CMAKE_COMPILER_IS_GNUCXX)
231235
# list(APPEND compile_options "-Wnewline-eof")
232236
# list(APPEND compile_options "-Wnonportable-system-include-path")

libc/docs/complex.rst

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
.. include:: check.rst
2+
3+
=========
4+
complex.h
5+
=========
6+
7+
Macros
8+
======
9+
10+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
11+
| <Func> | <Func_f> (float) | <Func> (double) | <Func_l> (long double) | <Func_f16> (float16) | <Func_f128> (float128) | C23 Definition Section | C23 Error Handling Section |
12+
+===========+==================+=================+========================+======================+========================+========================+============================+
13+
| CMPLX | | | | | | 7.3.9.3 | N/A |
14+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
15+
16+
Functions
17+
=========
18+
19+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
20+
| <Func> | <Func_f> (float) | <Func> (double) | <Func_l> (long double) | <Func_f16> (float16) | <Func_f128> (float128) | C23 Definition Section | C23 Error Handling Section |
21+
+===========+==================+=================+========================+======================+========================+========================+============================+
22+
| cacos | | | | | | 7.3.5.1 | G.6.2.1 |
23+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
24+
| casin | | | | | | 7.3.5.2 | N/A |
25+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
26+
| catan | | | | | | 7.3.5.3 | N/A |
27+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
28+
| ccos | | | | | | 7.3.5.4 | N/A |
29+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
30+
| csin | | | | | | 7.3.5.5 | N/A |
31+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
32+
| ctan | | | | | | 7.3.5.6 | N/A |
33+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
34+
| cacosh | | | | | | 7.3.6.1 | G.6.3.1 |
35+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
36+
| casinh | | | | | | 7.3.6.2 | G.6.3.2 |
37+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
38+
| catanh | | | | | | 7.3.6.3 | G.6.3.3 |
39+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
40+
| ccosh | | | | | | 7.3.6.4 | G.6.3.4 |
41+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
42+
| csinh | | | | | | 7.3.6.5 | G.6.3.5 |
43+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
44+
| ctanh | | | | | | 7.3.6.6 | G.6.3.6 |
45+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
46+
| cexp | | | | | | 7.3.7.1 | G.6.4.1 |
47+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
48+
| clog | | | | | | 7.3.7.2 | G.6.4.2 |
49+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
50+
| cabs | | | | | | 7.3.8.1 | N/A |
51+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
52+
| cpow | | | | | | 7.3.8.2 | G.6.5.1 |
53+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
54+
| csqrt | | | | | | 7.3.8.3 | G.6.5.2 |
55+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
56+
| carg | | | | | | 7.3.9.1 | N/A |
57+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
58+
| cimag | | | | | | 7.3.9.2 | N/A |
59+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
60+
| conj | | | | | | 7.3.9.4 | N/A |
61+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
62+
| cproj | | | | | | 7.3.9.5 | N/A |
63+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
64+
| creal | | | | | | 7.3.9.6 | N/A |
65+
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+

libc/docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ stages there is no ABI stability in any form.
7373
libc_search
7474
c23
7575
ctype
76+
complex
7677
signal
7778
threads
7879
setjmp

libc/include/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,16 @@ add_header_macro(
202202
.llvm-libc-macros.assert_macros
203203
)
204204

205+
add_header_macro(
206+
complex
207+
../libc/newhdrgen/yaml/complex.yaml
208+
complex.h.def
209+
complex.h
210+
DEPENDS
211+
.llvm_libc_common_h
212+
.llvm-libc-macros.complex_macros
213+
)
214+
205215
add_header_macro(
206216
setjmp
207217
../libc/newhdrgen/yaml/setjmp.yaml

libc/include/complex.h.def

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//===-- C standard library header complex.h -------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_COMPLEX_H
10+
#define LLVM_LIBC_COMPLEX_H
11+
12+
#include "__llvm-libc-common.h"
13+
#include "llvm-libc-macros/complex-macros.h"
14+
15+
%%public_api()
16+
17+
#endif // LLVM_LIBC_COMPLEX_H

libc/include/llvm-libc-macros/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ add_macro_header(
6161
fcntl-macros.h
6262
)
6363

64+
add_macro_header(
65+
complex_macros
66+
HDR
67+
complex-macros.h
68+
)
69+
6470
add_macro_header(
6571
features_macros
6672
HDR
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//===-- Definition of macros to be used with complex functions ------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef __LLVM_LIBC_MACROS_COMPLEX_MACROS_H
10+
#define __LLVM_LIBC_MACROS_COMPLEX_MACROS_H
11+
12+
#ifndef __STDC_NO_COMPLEX__
13+
14+
#define __STDC_VERSION_COMPLEX_H__ 202311L
15+
16+
#define complex _Complex
17+
#define _Complex_I ((_Complex float)1.0fi)
18+
#define I _Complex_I
19+
20+
// TODO: Add imaginary macros once GCC or Clang support _Imaginary builtin-type.
21+
22+
#endif
23+
24+
#endif // __LLVM_LIBC_MACROS_COMPLEX_MACROS_H

libc/src/__support/CPP/type_traits.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "src/__support/CPP/type_traits/is_array.h"
2626
#include "src/__support/CPP/type_traits/is_base_of.h"
2727
#include "src/__support/CPP/type_traits/is_class.h"
28+
#include "src/__support/CPP/type_traits/is_complex.h"
2829
#include "src/__support/CPP/type_traits/is_const.h"
2930
#include "src/__support/CPP/type_traits/is_constant_evaluated.h"
3031
#include "src/__support/CPP/type_traits/is_convertible.h"
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===-- is_complex type_traits ----------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COMPLEX_H
9+
#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COMPLEX_H
10+
11+
#include "src/__support/CPP/type_traits/is_same.h"
12+
#include "src/__support/CPP/type_traits/remove_cv.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
namespace cpp {
16+
17+
// is_complex
18+
template <typename T> struct is_complex {
19+
private:
20+
template <typename Head, typename... Args>
21+
LIBC_INLINE_VAR static constexpr bool __is_unqualified_any_of() {
22+
return (... || is_same_v<remove_cv_t<Head>, Args>);
23+
}
24+
25+
public:
26+
LIBC_INLINE_VAR static constexpr bool value =
27+
__is_unqualified_any_of<T, _Complex float, _Complex double,
28+
_Complex long double>();
29+
};
30+
template <typename T>
31+
LIBC_INLINE_VAR constexpr bool is_complex_v = is_complex<T>::value;
32+
template <typename T1, typename T2>
33+
LIBC_INLINE_VAR constexpr bool is_complex_type_same() {
34+
return is_same_v<remove_cv_t<T1>, T2>;
35+
}
36+
37+
} // namespace cpp
38+
} // namespace LIBC_NAMESPACE_DECL
39+
40+
#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COMPLEX_H

libc/test/UnitTest/FPMatcher.h

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,95 @@ template <typename T, TestCond Condition> class FPMatcher : public Matcher<T> {
6060
}
6161
};
6262

63+
template <typename T, TestCond Condition> class CFPMatcher : public Matcher<T> {
64+
static_assert(
65+
cpp::is_complex_v<T>,
66+
"CFPMatcher can only be used with complex floating point values.");
67+
static_assert(Condition == TestCond::EQ || Condition == TestCond::NE,
68+
"Unsupported CFPMatcher test condition.");
69+
70+
T expected;
71+
T actual;
72+
73+
public:
74+
CFPMatcher(T expectedValue) : expected(expectedValue) {}
75+
76+
template <typename CFT> bool matchComplex() {
77+
CFT *actualCmplxPtr = reinterpret_cast<CFT *>(&actual);
78+
CFT *expectedCmplxPtr = reinterpret_cast<CFT *>(&expected);
79+
CFT actualReal = actualCmplxPtr[0];
80+
CFT actualImag = actualCmplxPtr[1];
81+
CFT expectedReal = expectedCmplxPtr[0];
82+
CFT expectedImag = expectedCmplxPtr[1];
83+
fputil::FPBits<CFT> actualRealBits(actualReal),
84+
expectedRealBits(expectedReal);
85+
fputil::FPBits<CFT> actualImagBits(actualImag),
86+
expectedImagBits(expectedImag);
87+
if (Condition == TestCond::EQ)
88+
return ((actualRealBits.is_nan() && expectedRealBits.is_nan()) ||
89+
(actualRealBits.uintval() == expectedRealBits.uintval())) &&
90+
((actualImagBits.is_nan() && expectedImagBits.is_nan()) ||
91+
(actualImagBits.uintval() == expectedImagBits.uintval()));
92+
93+
// If condition == TestCond::NE.
94+
if (actualRealBits.is_nan() && expectedRealBits.is_nan())
95+
return !expectedRealBits.is_nan() && !expectedImagBits.is_nan();
96+
if (actualRealBits.is_nan())
97+
return !expectedRealBits.is_nan();
98+
if (actualImagBits.is_nan())
99+
return !expectedImagBits.is_nan();
100+
return (expectedRealBits.is_nan() ||
101+
actualRealBits.uintval() != expectedRealBits.uintval()) &&
102+
(expectedImagBits.is_nan() ||
103+
actualImagBits.uintval() != expectedImagBits.uintval());
104+
}
105+
106+
template <typename CFT> void explainErrorComplex() {
107+
CFT *actualCmplxPtr = reinterpret_cast<CFT *>(&actual);
108+
CFT *expectedCmplxPtr = reinterpret_cast<CFT *>(&expected);
109+
CFT actualReal = actualCmplxPtr[0];
110+
CFT actualImag = actualCmplxPtr[1];
111+
CFT expectedReal = expectedCmplxPtr[0];
112+
CFT expectedImag = expectedCmplxPtr[1];
113+
tlog << "Expected complex floating point value: "
114+
<< str(fputil::FPBits<CFT>(expectedReal)) + " + " +
115+
str(fputil::FPBits<CFT>(expectedImag)) + "i"
116+
<< '\n';
117+
tlog << "Actual complex floating point value: "
118+
<< str(fputil::FPBits<CFT>(actualReal)) + " + " +
119+
str(fputil::FPBits<CFT>(actualImag)) + "i"
120+
<< '\n';
121+
}
122+
123+
bool match(T actualValue) {
124+
actual = actualValue;
125+
if (cpp::is_complex_type_same<T, _Complex float>())
126+
return matchComplex<float>();
127+
else if (cpp::is_complex_type_same<T, _Complex double>())
128+
return matchComplex<double>();
129+
else if (cpp::is_complex_type_same<T, _Complex long double>())
130+
return matchComplex<long double>();
131+
}
132+
133+
void explainError() override {
134+
if (cpp::is_complex_type_same<T, _Complex float>())
135+
return explainErrorComplex<float>();
136+
else if (cpp::is_complex_type_same<T, _Complex double>())
137+
return explainErrorComplex<double>();
138+
else if (cpp::is_complex_type_same<T, _Complex long double>())
139+
return explainErrorComplex<long double>();
140+
}
141+
};
142+
63143
template <TestCond C, typename T> FPMatcher<T, C> getMatcher(T expectedValue) {
64144
return FPMatcher<T, C>(expectedValue);
65145
}
66146

147+
template <TestCond C, typename T>
148+
CFPMatcher<T, C> getMatcherComplex(T expectedValue) {
149+
return CFPMatcher<T, C>(expectedValue);
150+
}
151+
67152
template <typename T> struct FPTest : public Test {
68153
using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
69154
using StorageType = typename FPBits::StorageType;
@@ -125,6 +210,10 @@ template <typename T> struct FPTest : public Test {
125210
EXPECT_THAT(actual, LIBC_NAMESPACE::testing::getMatcher< \
126211
LIBC_NAMESPACE::testing::TestCond::EQ>(expected))
127212

213+
#define EXPECT_CFP_EQ(expected, actual) \
214+
EXPECT_THAT(actual, LIBC_NAMESPACE::testing::getMatcherComplex< \
215+
LIBC_NAMESPACE::testing::TestCond::EQ>(expected))
216+
128217
#define TEST_FP_EQ(expected, actual) \
129218
LIBC_NAMESPACE::testing::getMatcher<LIBC_NAMESPACE::testing::TestCond::EQ>( \
130219
expected) \

libc/test/include/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ add_libc_test(
1111
libc.include.llvm-libc-macros.assert_macros
1212
)
1313

14+
add_libc_test(
15+
complex_test
16+
SUITE
17+
libc_include_tests
18+
SRCS
19+
complex_test.cpp
20+
DEPENDS
21+
libc.include.llvm-libc-macros.complex_macros
22+
)
23+
1424
add_libc_test(
1525
sys_queue_test
1626
SUITE

libc/test/include/complex_test.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Unittests for complex ---------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "include/llvm-libc-macros/complex-macros.h"
10+
#include "test/UnitTest/FPMatcher.h"
11+
#include "test/UnitTest/Test.h"
12+
13+
TEST(LlvmLibcComplexTest, VersionMacro) {
14+
EXPECT_EQ(__STDC_VERSION_COMPLEX_H__, 202311L);
15+
}
16+
17+
TEST(LlvmLibcComplexTest, IMacro) { EXPECT_CFP_EQ(1.0fi, I); }
18+
19+
TEST(LlvmLibcComplexTest, _Complex_IMacro) { EXPECT_CFP_EQ(1.0fi, _Complex_I); }

0 commit comments

Comments
 (0)