File tree Expand file tree Collapse file tree 4 files changed +53
-0
lines changed Expand file tree Collapse file tree 4 files changed +53
-0
lines changed Original file line number Diff line number Diff line change @@ -749,6 +749,7 @@ config_define(${LIBCXX_ENABLE_UNICODE} _LIBCPP_HAS_UNICODE)
749749config_define(${LIBCXX_ENABLE_WIDE_CHARACTERS} _LIBCPP_HAS_WIDE_CHARACTERS)
750750config_define(${LIBCXX_ENABLE_TIME_ZONE_DATABASE} _LIBCPP_HAS_TIME_ZONE_DATABASE)
751751config_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.
754755if (LIBCXX_ENABLE_ASSERTIONS)
Original file line number Diff line number Diff line change @@ -103,6 +103,31 @@ endif()
103103
104104check_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
107132if (WIN32 AND NOT MINGW)
108133 # TODO(compnerd) do we want to support an emulation layer that allows for the
Original file line number Diff line number Diff line change 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
Original file line number Diff line number Diff 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
You can’t perform that action at this time.
0 commit comments