[libcxx-commits] [libcxx] [libc++] Use libc functions for complex calculations when available (PR #99677)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Sun Nov 17 02:21:48 PST 2024


https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/99677

>From e74324802c1d9670ba6f4572cbbadc8ed76c2af5 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Fri, 27 Jan 2023 09:41:14 +0100
Subject: [PATCH] [libc++] Forward complex math to libm

---
 libcxx/include/complex | 86 +++++++++++++++---------------------------
 1 file changed, 30 insertions(+), 56 deletions(-)

diff --git a/libcxx/include/complex b/libcxx/include/complex
index 2dc6d298e44f69..1be19eee3655e6 100644
--- a/libcxx/include/complex
+++ b/libcxx/include/complex
@@ -1125,77 +1125,51 @@ inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> __sqr(const complex<_Tp>& __x) {
 
 // asinh
 
-template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI inline _Complex float __casinh(_Complex float __v) { return __builtin_casinhf(__v); }
+_LIBCPP_HIDE_FROM_ABI inline _Complex double __casinh(_Complex double __v) { return __builtin_casinh(__v); }
+_LIBCPP_HIDE_FROM_ABI inline _Complex long double __casinh(_Complex long double __v) { return __builtin_casinhl(__v); }
+
+template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI complex<_Tp> asinh(const complex<_Tp>& __x) {
+  return complex<_Tp>(__from_builtin_tag(), std::__casinh(__x.__builtin()));
+}
+
+template <class _Tp, __enable_if_t<!is_floating_point<_Tp>::value, int> = 0>
 _LIBCPP_HIDE_FROM_ABI complex<_Tp> asinh(const complex<_Tp>& __x) {
-  const _Tp __pi(atan2(+0., -0.));
-  if (std::isinf(__x.real())) {
-    if (std::isnan(__x.imag()))
-      return __x;
-    if (std::isinf(__x.imag()))
-      return complex<_Tp>(__x.real(), std::copysign(__pi * _Tp(0.25), __x.imag()));
-    return complex<_Tp>(__x.real(), std::copysign(_Tp(0), __x.imag()));
-  }
-  if (std::isnan(__x.real())) {
-    if (std::isinf(__x.imag()))
-      return complex<_Tp>(__x.imag(), __x.real());
-    if (__x.imag() == 0)
-      return __x;
-    return complex<_Tp>(__x.real(), __x.real());
-  }
-  if (std::isinf(__x.imag()))
-    return complex<_Tp>(std::copysign(__x.imag(), __x.real()), std::copysign(__pi / _Tp(2), __x.imag()));
   complex<_Tp> __z = std::log(__x + std::sqrt(std::__sqr(__x) + _Tp(1)));
   return complex<_Tp>(std::copysign(__z.real(), __x.real()), std::copysign(__z.imag(), __x.imag()));
 }
 
 // acosh
 
-template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI inline _Complex float __cacosh(_Complex float __v) { return __builtin_cacoshf(__v); }
+_LIBCPP_HIDE_FROM_ABI inline _Complex double __cacosh(_Complex double __v) { return __builtin_cacosh(__v); }
+_LIBCPP_HIDE_FROM_ABI inline _Complex long double __cacosh(_Complex long double __v) { return __builtin_cacoshl(__v); }
+
+template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI complex<_Tp> acosh(const complex<_Tp>& __x) {
+  return complex<_Tp>(__from_builtin_tag(), std::__cacosh(__x.__builtin()));
+}
+
+template <class _Tp, __enable_if_t<!is_floating_point<_Tp>::value, int> = 0>
 _LIBCPP_HIDE_FROM_ABI complex<_Tp> acosh(const complex<_Tp>& __x) {
-  const _Tp __pi(atan2(+0., -0.));
-  if (std::isinf(__x.real())) {
-    if (std::isnan(__x.imag()))
-      return complex<_Tp>(std::abs(__x.real()), __x.imag());
-    if (std::isinf(__x.imag())) {
-      if (__x.real() > 0)
-        return complex<_Tp>(__x.real(), std::copysign(__pi * _Tp(0.25), __x.imag()));
-      else
-        return complex<_Tp>(-__x.real(), std::copysign(__pi * _Tp(0.75), __x.imag()));
-    }
-    if (__x.real() < 0)
-      return complex<_Tp>(-__x.real(), std::copysign(__pi, __x.imag()));
-    return complex<_Tp>(__x.real(), std::copysign(_Tp(0), __x.imag()));
-  }
-  if (std::isnan(__x.real())) {
-    if (std::isinf(__x.imag()))
-      return complex<_Tp>(std::abs(__x.imag()), __x.real());
-    return complex<_Tp>(__x.real(), __x.real());
-  }
-  if (std::isinf(__x.imag()))
-    return complex<_Tp>(std::abs(__x.imag()), std::copysign(__pi / _Tp(2), __x.imag()));
   complex<_Tp> __z = std::log(__x + std::sqrt(std::__sqr(__x) - _Tp(1)));
   return complex<_Tp>(std::copysign(__z.real(), _Tp(0)), std::copysign(__z.imag(), __x.imag()));
 }
 
 // atanh
 
-template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI inline _Complex float __catanh(_Complex float __v) { return __builtin_catanhf(__v); }
+_LIBCPP_HIDE_FROM_ABI inline _Complex double __catanh(_Complex double __v) { return __builtin_catanh(__v); }
+_LIBCPP_HIDE_FROM_ABI inline _Complex long double __catanh(_Complex long double __v) { return __builtin_catanhl(__v); }
+
+template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI complex<_Tp> atanh(const complex<_Tp>& __v) {
+  return complex<_Tp>(__from_builtin_tag(), std::__catanh(__v.__builtin()));
+}
+
+template <class _Tp, __enable_if_t<!is_floating_point<_Tp>::value, int> = 0>
 _LIBCPP_HIDE_FROM_ABI complex<_Tp> atanh(const complex<_Tp>& __x) {
-  const _Tp __pi(atan2(+0., -0.));
-  if (std::isinf(__x.imag())) {
-    return complex<_Tp>(std::copysign(_Tp(0), __x.real()), std::copysign(__pi / _Tp(2), __x.imag()));
-  }
-  if (std::isnan(__x.imag())) {
-    if (std::isinf(__x.real()) || __x.real() == 0)
-      return complex<_Tp>(std::copysign(_Tp(0), __x.real()), __x.imag());
-    return complex<_Tp>(__x.imag(), __x.imag());
-  }
-  if (std::isnan(__x.real())) {
-    return complex<_Tp>(__x.real(), __x.real());
-  }
-  if (std::isinf(__x.real())) {
-    return complex<_Tp>(std::copysign(_Tp(0), __x.real()), std::copysign(__pi / _Tp(2), __x.imag()));
-  }
   if (std::abs(__x.real()) == _Tp(1) && __x.imag() == _Tp(0)) {
     return complex<_Tp>(std::copysign(_Tp(INFINITY), __x.real()), std::copysign(_Tp(0), __x.imag()));
   }



More information about the libcxx-commits mailing list