[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