[libcxx-commits] [libcxx] [libc++] Use libm implementations in exp for complex numbers (PR #165457)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Oct 28 11:38:22 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Aleksei Nurmukhametov (nurmukhametov)
<details>
<summary>Changes</summary>
Replace the custom implementation with calls to compiler builtins, which delegate to libm implementations. This also improves accuracy, as demonstrated by the added test.
---
Full diff: https://github.com/llvm/llvm-project/pull/165457.diff
2 Files Affected:
- (modified) libcxx/include/complex (+5-16)
- (added) libcxx/test/libcxx/numerics/complex.number/exp.pass.cpp (+40)
``````````diff
diff --git a/libcxx/include/complex b/libcxx/include/complex
index d8ec3d95c10ed..0ae2087d492f2 100644
--- a/libcxx/include/complex
+++ b/libcxx/include/complex
@@ -1074,24 +1074,13 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> sqrt(const complex<_Tp>& __x) {
// exp
+_LIBCPP_HIDE_FROM_ABI inline _Complex float __cexp(_Complex float __v) { return __builtin_cexpf(__v); }
+_LIBCPP_HIDE_FROM_ABI inline _Complex double __cexp(_Complex double __v) { return __builtin_cexp(__v); }
+_LIBCPP_HIDE_FROM_ABI inline _Complex long double __cexp(_Complex long double __v) { return __builtin_cexpl(__v); }
+
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> exp(const complex<_Tp>& __x) {
- _Tp __i = __x.imag();
- if (__i == 0) {
- return complex<_Tp>(std::exp(__x.real()), std::copysign(_Tp(0), __x.imag()));
- }
- if (std::isinf(__x.real())) {
- if (__x.real() < _Tp(0)) {
- if (!std::isfinite(__i))
- __i = _Tp(1);
- } else if (__i == 0 || !std::isfinite(__i)) {
- if (std::isinf(__i))
- __i = _Tp(NAN);
- return complex<_Tp>(__x.real(), __i);
- }
- }
- _Tp __e = std::exp(__x.real());
- return complex<_Tp>(__e * std::cos(__i), __e * std::sin(__i));
+ return complex<_Tp>(__from_builtin_tag(), std::__cexp(__x.__builtin()));
}
// pow
diff --git a/libcxx/test/libcxx/numerics/complex.number/exp.pass.cpp b/libcxx/test/libcxx/numerics/complex.number/exp.pass.cpp
new file mode 100644
index 0000000000000..ccf03cccd0a35
--- /dev/null
+++ b/libcxx/test/libcxx/numerics/complex.number/exp.pass.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <complex>
+
+// template<class T>
+// complex<T>
+// exp(const complex<T>& x);
+
+#include <complex>
+#include <cassert>
+#include <cmath>
+
+#include "test_macros.h"
+
+template <class T>
+void test_overflow_case() {
+ typedef std::complex<T> C;
+
+ // In this case, the overflow of exp(real_part) is compensated when
+ // sin(imag_part) is close to zero, resulting in a finite imaginary part.
+ C z(T(90.0238094), T(5.900613e-39));
+ C result = std::exp(z);
+
+ assert(std::isinf(result.real()));
+ assert(result.real() > 0);
+
+ assert(std::isfinite(result.imag()));
+ assert(std::abs(result.imag() - T(7.3746)) < T(1.0));
+}
+
+int main(int, char**) {
+ test_overflow_case<float>();
+ return 0;
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/165457
More information about the libcxx-commits
mailing list