[libcxx-commits] [libcxx] [libc++] Use libm implementations in exp for complex numbers (PR #165457)
Aleksei Nurmukhametov via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Oct 28 11:37:49 PDT 2025
https://github.com/nurmukhametov created https://github.com/llvm/llvm-project/pull/165457
Replace the custom implementation with calls to compiler builtins, which delegate to libm implementations. This also improves accuracy, as demonstrated by the added test.
>From 11c9295ceb1da6e18df4324f85a3e5417bc83625 Mon Sep 17 00:00:00 2001
From: Aleksei Nurmukhametov <anurmukh at amd.com>
Date: Tue, 28 Oct 2025 18:18:51 +0000
Subject: [PATCH] [libc++] Use libm implementations in exp for complex numbers
Replace the custom implementation with calls to compiler builtins, which
delegate to libm implementations. This also improves accuracy, as
demonstrated by the added test.
---
libcxx/include/complex | 21 +++-------
.../numerics/complex.number/exp.pass.cpp | 40 +++++++++++++++++++
2 files changed, 45 insertions(+), 16 deletions(-)
create mode 100644 libcxx/test/libcxx/numerics/complex.number/exp.pass.cpp
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;
+}
More information about the libcxx-commits
mailing list