Skip to content

Conversation

@moar55
Copy link
Contributor

@moar55 moar55 commented Feb 25, 2025

This addresses #127866.
This is just a first attempt, as I am not sure about a few things...
Should I add a test in libcxx as well?
I also added this logic to pow(complex<T>, complex<U>), because the amendment of the proposal talks about this as well. Does that make sense to you?

@moar55 moar55 requested a review from a team as a code owner February 25, 2025 22:10
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Feb 25, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 25, 2025

@llvm/pr-subscribers-libcxx

Author: Omar Hossam (moar55)

Changes

This addresses #127866.
This is just a first attempt, as I am not sure about a few things...
Should I add a test in libcxx as well?
I also added this logic to pow(complex&lt;T&gt;, complex&lt;U&gt;), because the amendment of the proposal talks about this as well. Does that make sense to you?


Full diff: https://github.com/llvm/llvm-project/pull/128779.diff

3 Files Affected:

  • (modified) libcxx/include/complex (+20)
  • (modified) libcxx/test/libcxx/numerics/complex.number/cmplx.over.pow.pass.cpp (+3)
  • (modified) libcxx/test/std/numerics/complex.number/cmplx.over/pow.pass.cpp (+3)
diff --git a/libcxx/include/complex b/libcxx/include/complex
index df18159595b34..0871ded7f5707 100644
--- a/libcxx/include/complex
+++ b/libcxx/include/complex
@@ -1100,18 +1100,38 @@ inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> pow(const complex<_Tp>& __x, const com
   return std::exp(__y * std::log(__x));
 }
 
+#  if _LIBCPP_STD_VER >= 26
+template <class _Tp, class _Up, __enable_if_t<is_floating_point<_Tp>::value && is_floating_point<_Up>::value, int> = 0>
+inline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, conditional_t<is_integral_v<_Up>, double, _Up>>::type>
+pow(const complex<_Tp>& __x, const complex<_Up>& __y) {
+  using _Yp = conditional_t<is_integral_v<_Up>, double, _Up>;
+  typedef complex<typename __promote<_Tp, _Yp>::type> result_type;
+  return std::pow(result_type(__x), result_type(__y));
+}
+#  else
 template <class _Tp, class _Up, __enable_if_t<is_floating_point<_Tp>::value && is_floating_point<_Up>::value, int> = 0>
 inline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, _Up>::type>
 pow(const complex<_Tp>& __x, const complex<_Up>& __y) {
   typedef complex<typename __promote<_Tp, _Up>::type> result_type;
   return std::pow(result_type(__x), result_type(__y));
 }
+#  endif
 
+#  if _LIBCPP_STD_VER >= 26
+template <class _Tp, class _Up, __enable_if_t<is_floating_point<_Tp>::value && is_arithmetic<_Up>::value, int> = 0>
+inline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, conditional_t<is_integral_v<_Up>, double, _Up>>::type>
+pow(const complex<_Tp>& __x, const _Up& __y) {
+  using _Yp = conditional_t<is_integral_v<_Up>, double, _Up>;
+  typedef complex<typename __promote<_Tp, _Yp>::type> result_type;
+  return std::pow(result_type(__x), result_type(__y));
+}
+#  else
 template <class _Tp, class _Up, __enable_if_t<is_floating_point<_Tp>::value && is_arithmetic<_Up>::value, int> = 0>
 inline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, _Up>::type> pow(const complex<_Tp>& __x, const _Up& __y) {
   typedef complex<typename __promote<_Tp, _Up>::type> result_type;
   return std::pow(result_type(__x), result_type(__y));
 }
+#  endif
 
 template <class _Tp, class _Up, __enable_if_t<is_arithmetic<_Tp>::value && is_floating_point<_Up>::value, int> = 0>
 inline _LIBCPP_HIDE_FROM_ABI complex<typename __promote<_Tp, _Up>::type> pow(const _Tp& __x, const complex<_Up>& __y) {
diff --git a/libcxx/test/libcxx/numerics/complex.number/cmplx.over.pow.pass.cpp b/libcxx/test/libcxx/numerics/complex.number/cmplx.over.pow.pass.cpp
index 8c1b3a17c669f..76f2224be37e0 100644
--- a/libcxx/test/libcxx/numerics/complex.number/cmplx.over.pow.pass.cpp
+++ b/libcxx/test/libcxx/numerics/complex.number/cmplx.over.pow.pass.cpp
@@ -82,5 +82,8 @@ int main(int, char**) {
   assert(pow(ctag, std::complex<long double>(1.0l)) == 4);
   assert(pow(std::complex<long double>(1.0l), ctag) == 5);
 
+  // Make sure LWG4191: P1467 is respected.
+  static_assert(std::is_same_v<decltype(std::pow(std::complex<float>(), int())), std::complex<double>>, "");
+
   return 0;
 }
diff --git a/libcxx/test/std/numerics/complex.number/cmplx.over/pow.pass.cpp b/libcxx/test/std/numerics/complex.number/cmplx.over/pow.pass.cpp
index 54a6cba9c0011..7a9ca6719a20c 100644
--- a/libcxx/test/std/numerics/complex.number/cmplx.over/pow.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/cmplx.over/pow.pass.cpp
@@ -101,6 +101,9 @@ int main(int, char**)
 
     test<long double, float>();
     test<long double, double>();
+    
+    // Make sure LWG4191: P1467 is respected.
+    static_assert(std::is_same_v<decltype(std::pow(std::complex<float>(), int())), std::complex<double>>, "");
 
   return 0;
 }

@github-actions
Copy link

github-actions bot commented Feb 25, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Contributor

@frederick-vs-ja frederick-vs-ja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to change test files, because LWG4191 just reverts a mistaken change in C++23. The current pre-C++23 test coverages are sufficient.

However, I have no idea how to continue as we haven't implemented P1467R9.

assert(pow(ctag, std::complex<long double>(1.0l)) == 4);
assert(pow(std::complex<long double>(1.0l), ctag) == 5);

// Make sure LWG4191: P1467 is respected.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC the libcxx/test/libcxx subdirectory is intendedly used for libc++-specific implementation details and extensions. As we're testing implementation of standard requirements, I think it's better not to add cases here.

test<long double, double>();

return 0;
// Make sure LWG4191: P1467 is respected.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to change this file either. test<int, float>(), test<unsigned, float>(), and test<long long, float>() should have been sufficient.

@moar55
Copy link
Contributor Author

moar55 commented Feb 26, 2025

However, I have no idea how to continue as we haven't implemented P1467R9
You mean because we don't have this common_type_t?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants