Skip to content

Commit bda7bce

Browse files
committed
WIP: preserve original implementation in case when libm can't provide cexp functions
1 parent 11c9295 commit bda7bce

File tree

4 files changed

+53
-0
lines changed

4 files changed

+53
-0
lines changed

libcxx/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,7 @@ config_define(${LIBCXX_ENABLE_UNICODE} _LIBCPP_HAS_UNICODE)
749749
config_define(${LIBCXX_ENABLE_WIDE_CHARACTERS} _LIBCPP_HAS_WIDE_CHARACTERS)
750750
config_define(${LIBCXX_ENABLE_TIME_ZONE_DATABASE} _LIBCPP_HAS_TIME_ZONE_DATABASE)
751751
config_define(${LIBCXX_ENABLE_VENDOR_AVAILABILITY_ANNOTATIONS} _LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS)
752+
config_define_if(C_SUPPORTS_C99_COMPLEX _LIBCPP_HAS_C99_COMPLEX)
752753

753754
# TODO: Remove in LLVM 21. We're leaving an error to make this fail explicitly.
754755
if (LIBCXX_ENABLE_ASSERTIONS)

libcxx/cmake/config-ix.cmake

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,31 @@ endif()
103103

104104
check_symbol_exists(__PICOLIBC__ "string.h" PICOLIBC)
105105

106+
# Check for the existence of <complex.h> complex math functions.
107+
# This is necessary even though libcxx uses the builtin versions
108+
# of these functions, because if the builtin cannot be used, a reference
109+
# to the library function is emitted. Using compiler builtins for these
110+
# functions requires corresponding C99 library functions to be present.
111+
112+
cmake_push_check_state()
113+
list(APPEND CMAKE_REQUIRED_LIBRARIES m)
114+
check_c_source_compiles("
115+
#include <complex.h>
116+
typedef __complex__ float float_type;
117+
typedef __complex__ double double_type;
118+
typedef __complex__ long double ld_type;
119+
volatile float_type tmpf;
120+
volatile double_type tmpd;
121+
volatile ld_type tmpld;
122+
int main(void) {
123+
tmpf = cexpf(tmpf);
124+
tmpd = cexp(tmpd);
125+
tmpld = cexpl(tmpld);
126+
return 0;
127+
}
128+
" C_SUPPORTS_C99_COMPLEX)
129+
cmake_pop_check_state()
130+
106131
# Check libraries
107132
if(WIN32 AND NOT MINGW)
108133
# TODO(compnerd) do we want to support an emulation layer that allows for the

libcxx/include/__config_site.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#cmakedefine01 _LIBCPP_HAS_WIDE_CHARACTERS
3333
#cmakedefine01 _LIBCPP_HAS_TIME_ZONE_DATABASE
3434
#cmakedefine01 _LIBCPP_INSTRUMENTED_WITH_ASAN
35+
#cmakedefine01 _LIBCPP_HAS_C99_COMPLEX
3536

3637
// PSTL backends
3738
#cmakedefine _LIBCPP_PSTL_BACKEND_SERIAL

libcxx/include/complex

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,7 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> sqrt(const complex<_Tp>& __x) {
10741074

10751075
// exp
10761076

1077+
#if _LIBCPP_HAS_C99_COMPLEX
10771078
_LIBCPP_HIDE_FROM_ABI inline _Complex float __cexp(_Complex float __v) { return __builtin_cexpf(__v); }
10781079
_LIBCPP_HIDE_FROM_ABI inline _Complex double __cexp(_Complex double __v) { return __builtin_cexp(__v); }
10791080
_LIBCPP_HIDE_FROM_ABI inline _Complex long double __cexp(_Complex long double __v) { return __builtin_cexpl(__v); }
@@ -1082,6 +1083,31 @@ template <class _Tp>
10821083
_LIBCPP_HIDE_FROM_ABI complex<_Tp> exp(const complex<_Tp>& __x) {
10831084
return complex<_Tp>(__from_builtin_tag(), std::__cexp(__x.__builtin()));
10841085
}
1086+
#else
1087+
template <class _Tp>
1088+
_LIBCPP_HIDE_FROM_ABI complex<_Tp> exp(const complex<_Tp>& __x) {
1089+
_Tp __i = __x.imag();
1090+
if (__i == 0) {
1091+
return complex<_Tp>(std::exp(__x.real()), std::copysign(_Tp(0), __x.imag()));
1092+
}
1093+
if (std::isinf(__x.real())) {
1094+
if (__x.real() < _Tp(0)) {
1095+
if (!std::isfinite(__i))
1096+
__i = _Tp(1);
1097+
} else if (__i == 0 || !std::isfinite(__i)) {
1098+
if (std::isinf(__i))
1099+
__i = _Tp(NAN);
1100+
return complex<_Tp>(__x.real(), __i);
1101+
}
1102+
}
1103+
if (std::isinf(__e)) {
1104+
_Tp __e2 = std::exp(__x.real() * _Tp(0.5));
1105+
return complex<_Tp>(__e2 * std::cos(__i) * __e2, __e2 * std::sin(__i) * __e2);
1106+
}
1107+
_Tp __e = std::exp(__x.real());
1108+
return complex<_Tp>(__e * std::cos(__i), __e * std::sin(__i));
1109+
}
1110+
#endif
10851111

10861112
// pow
10871113

0 commit comments

Comments
 (0)