[libcxx-commits] [libcxx] [libcxx] makes `tanh(complex<float>)` work for large values (PR #122194)
via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jan 8 15:49:23 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Christopher Di Bella (cjdb)
<details>
<summary>Changes</summary>
By attempting to compute `sin(2x)` and `cos(2x)`, we were inadvertently producing `complex<float>(NaN, NaN)` for any `|x| > 2^127`, since `2x` would be computed as `inf`, and `sin(inf) == cos(inf) == NaN`.
This commit relies on trig identities to sidestep this issue and always produce a valid answer for large values of `tanh`. The test cases only handled `double`, so they have been expanded to test `float` and `long double` as well.
---
Patch is 117.15 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/122194.diff
28 Files Affected:
- (modified) libcxx/include/complex (+34-6)
- (modified) libcxx/test/std/numerics/complex.number/cases.h (+198-172)
- (modified) libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp (+31-6)
- (modified) libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp (+26-6)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/acos.pass.cpp (+39-29)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/acosh.pass.cpp (+33-30)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/asin.pass.cpp (+29-26)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/asinh.pass.cpp (+32-29)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/atan.pass.cpp (+9-6)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/atanh.pass.cpp (+34-31)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/cos.pass.cpp (+8-5)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/cosh.pass.cpp (+29-19)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/exp.pass.cpp (+24-21)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/log.pass.cpp (+27-24)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/log10.pass.cpp (+7-4)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/pow_complex_complex.pass.cpp (+7-4)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/pow_complex_scalar.pass.cpp (+7-4)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/pow_scalar_complex.pass.cpp (+7-4)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/sin.pass.cpp (+9-6)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/sinh.pass.cpp (+32-22)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/sqrt.pass.cpp (+53-19)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/tan.pass.cpp (+9-6)
- (modified) libcxx/test/std/numerics/complex.number/complex.transcendentals/tanh.pass.cpp (+28-19)
- (modified) libcxx/test/std/numerics/complex.number/complex.value.ops/abs.pass.cpp (+21-4)
- (modified) libcxx/test/std/numerics/complex.number/complex.value.ops/arg.pass.cpp (+34-29)
- (modified) libcxx/test/std/numerics/complex.number/complex.value.ops/norm.pass.cpp (+9-4)
- (modified) libcxx/test/std/numerics/complex.number/complex.value.ops/polar.pass.cpp (+11-6)
- (modified) libcxx/test/std/numerics/complex.number/complex.value.ops/proj.pass.cpp (+14-9)
``````````diff
diff --git a/libcxx/include/complex b/libcxx/include/complex
index df18159595b34d..5f425206100ce2 100644
--- a/libcxx/include/complex
+++ b/libcxx/include/complex
@@ -1236,6 +1236,36 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> cosh(const complex<_Tp>& __x) {
// tanh
+template<class _Tp>
+_LIBCPP_HIDE_FROM_ABI _Tp __sin2(const _Tp __x) noexcept
+{
+ static_assert(std::is_arithmetic<_Tp>::value, "requires an arithmetic type");
+ return 2 * std::sin(__x) * std::cos(__x);
+}
+
+template<class _Tp>
+_LIBCPP_HIDE_FROM_ABI _Tp __sinh2(const _Tp __x) noexcept
+{
+ static_assert(std::is_arithmetic<_Tp>::value, "requires an arithmetic type");
+ return 2 * std::sinh(__x) * std::cosh(__x);
+}
+
+template<class _Tp>
+_LIBCPP_HIDE_FROM_ABI _Tp __cos2(const _Tp __x) noexcept
+{
+ static_assert(std::is_arithmetic<_Tp>::value, "requires an arithmetic type");
+ const _Tp __cos = std::cos(__x);
+ return 2 * __cos * __cos - 1;
+}
+
+template<class _Tp>
+_LIBCPP_HIDE_FROM_ABI _Tp __cosh2(const _Tp __x) noexcept
+{
+ static_assert(std::is_arithmetic<_Tp>::value, "requires an arithmetic type");
+ const _Tp __cosh = std::cosh(__x);
+ return 2 * __cosh * __cosh - 1;
+}
+
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI complex<_Tp> tanh(const complex<_Tp>& __x) {
if (std::isinf(__x.real())) {
@@ -1245,13 +1275,11 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> tanh(const complex<_Tp>& __x) {
}
if (std::isnan(__x.real()) && __x.imag() == 0)
return __x;
- _Tp __2r(_Tp(2) * __x.real());
- _Tp __2i(_Tp(2) * __x.imag());
- _Tp __d(std::cosh(__2r) + std::cos(__2i));
- _Tp __2rsh(std::sinh(__2r));
+ _Tp __d(std::__cosh2(__x.real()) + std::__cos2(__x.imag()));
+ _Tp __2rsh(std::__sinh2(__x.real()));
if (std::isinf(__2rsh) && std::isinf(__d))
- return complex<_Tp>(__2rsh > _Tp(0) ? _Tp(1) : _Tp(-1), __2i > _Tp(0) ? _Tp(0) : _Tp(-0.));
- return complex<_Tp>(__2rsh / __d, std::sin(__2i) / __d);
+ return complex<_Tp>(__2rsh > _Tp(0) ? _Tp(1) : _Tp(-1), __x.imag() > _Tp(0) ? _Tp(0) : _Tp(-0.));
+ return complex<_Tp>(__2rsh / __d, std::__sin2(__x.imag()) / __d);
}
// asin
diff --git a/libcxx/test/std/numerics/complex.number/cases.h b/libcxx/test/std/numerics/complex.number/cases.h
index b360e1423ff576..37d327450311ae 100644
--- a/libcxx/test/std/numerics/complex.number/cases.h
+++ b/libcxx/test/std/numerics/complex.number/cases.h
@@ -15,184 +15,201 @@
#include <cassert>
#include <complex>
+#include <limits>
#include <type_traits>
#include "test_macros.h"
-TEST_CONSTEXPR_CXX20 const std::complex<double> testcases[] =
+template<class T>
+TEST_CONSTEXPR_CXX20 const std::complex<T> testcases[] =
{
- std::complex<double>( 1.e-6, 1.e-6),
- std::complex<double>(-1.e-6, 1.e-6),
- std::complex<double>(-1.e-6, -1.e-6),
- std::complex<double>( 1.e-6, -1.e-6),
-
- std::complex<double>( 1.e+6, 1.e-6),
- std::complex<double>(-1.e+6, 1.e-6),
- std::complex<double>(-1.e+6, -1.e-6),
- std::complex<double>( 1.e+6, -1.e-6),
-
- std::complex<double>( 1.e-6, 1.e+6),
- std::complex<double>(-1.e-6, 1.e+6),
- std::complex<double>(-1.e-6, -1.e+6),
- std::complex<double>( 1.e-6, -1.e+6),
-
- std::complex<double>( 1.e+6, 1.e+6),
- std::complex<double>(-1.e+6, 1.e+6),
- std::complex<double>(-1.e+6, -1.e+6),
- std::complex<double>( 1.e+6, -1.e+6),
-
- std::complex<double>(-0, -1.e-6),
- std::complex<double>(-0, 1.e-6),
- std::complex<double>(-0, 1.e+6),
- std::complex<double>(-0, -1.e+6),
- std::complex<double>( 0, -1.e-6),
- std::complex<double>( 0, 1.e-6),
- std::complex<double>( 0, 1.e+6),
- std::complex<double>( 0, -1.e+6),
-
- std::complex<double>(-1.e-6, -0),
- std::complex<double>( 1.e-6, -0),
- std::complex<double>( 1.e+6, -0),
- std::complex<double>(-1.e+6, -0),
- std::complex<double>(-1.e-6, 0),
- std::complex<double>( 1.e-6, 0),
- std::complex<double>( 1.e+6, 0),
- std::complex<double>(-1.e+6, 0),
-
- std::complex<double>(std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN()),
- std::complex<double>(-std::numeric_limits<double>::infinity(), std::numeric_limits<double>::quiet_NaN()),
- std::complex<double>(-2, std::numeric_limits<double>::quiet_NaN()),
- std::complex<double>(-1, std::numeric_limits<double>::quiet_NaN()),
- std::complex<double>(-0.5, std::numeric_limits<double>::quiet_NaN()),
- std::complex<double>(-0., std::numeric_limits<double>::quiet_NaN()),
- std::complex<double>(+0., std::numeric_limits<double>::quiet_NaN()),
- std::complex<double>(0.5, std::numeric_limits<double>::quiet_NaN()),
- std::complex<double>(1, std::numeric_limits<double>::quiet_NaN()),
- std::complex<double>(2, std::numeric_limits<double>::quiet_NaN()),
- std::complex<double>(std::numeric_limits<double>::infinity(), std::numeric_limits<double>::quiet_NaN()),
-
- std::complex<double>(std::numeric_limits<double>::quiet_NaN(), -std::numeric_limits<double>::infinity()),
- std::complex<double>(-std::numeric_limits<double>::infinity(), -std::numeric_limits<double>::infinity()),
- std::complex<double>(-2, -std::numeric_limits<double>::infinity()),
- std::complex<double>(-1, -std::numeric_limits<double>::infinity()),
- std::complex<double>(-0.5, -std::numeric_limits<double>::infinity()),
- std::complex<double>(-0., -std::numeric_limits<double>::infinity()),
- std::complex<double>(+0., -std::numeric_limits<double>::infinity()),
- std::complex<double>(0.5, -std::numeric_limits<double>::infinity()),
- std::complex<double>(1, -std::numeric_limits<double>::infinity()),
- std::complex<double>(2, -std::numeric_limits<double>::infinity()),
- std::complex<double>(std::numeric_limits<double>::infinity(), -std::numeric_limits<double>::infinity()),
-
- std::complex<double>(std::numeric_limits<double>::quiet_NaN(), -2),
- std::complex<double>(-std::numeric_limits<double>::infinity(), -2),
- std::complex<double>(-2, -2),
- std::complex<double>(-1, -2),
- std::complex<double>(-0.5, -2),
- std::complex<double>(-0., -2),
- std::complex<double>(+0., -2),
- std::complex<double>(0.5, -2),
- std::complex<double>(1, -2),
- std::complex<double>(2, -2),
- std::complex<double>(std::numeric_limits<double>::infinity(), -2),
-
- std::complex<double>(std::numeric_limits<double>::quiet_NaN(), -1),
- std::complex<double>(-std::numeric_limits<double>::infinity(), -1),
- std::complex<double>(-2, -1),
- std::complex<double>(-1, -1),
- std::complex<double>(-0.5, -1),
- std::complex<double>(-0., -1),
- std::complex<double>(+0., -1),
- std::complex<double>(0.5, -1),
- std::complex<double>(1, -1),
- std::complex<double>(2, -1),
- std::complex<double>(std::numeric_limits<double>::infinity(), -1),
-
- std::complex<double>(std::numeric_limits<double>::quiet_NaN(), -0.5),
- std::complex<double>(-std::numeric_limits<double>::infinity(), -0.5),
- std::complex<double>(-2, -0.5),
- std::complex<double>(-1, -0.5),
- std::complex<double>(-0.5, -0.5),
- std::complex<double>(-0., -0.5),
- std::complex<double>(+0., -0.5),
- std::complex<double>(0.5, -0.5),
- std::complex<double>(1, -0.5),
- std::complex<double>(2, -0.5),
- std::complex<double>(std::numeric_limits<double>::infinity(), -0.5),
-
- std::complex<double>(std::numeric_limits<double>::quiet_NaN(), -0.),
- std::complex<double>(-std::numeric_limits<double>::infinity(), -0.),
- std::complex<double>(-2, -0.),
- std::complex<double>(-1, -0.),
- std::complex<double>(-0.5, -0.),
- std::complex<double>(-0., -0.),
- std::complex<double>(+0., -0.),
- std::complex<double>(0.5, -0.),
- std::complex<double>(1, -0.),
- std::complex<double>(2, -0.),
- std::complex<double>(std::numeric_limits<double>::infinity(), -0.),
-
- std::complex<double>(std::numeric_limits<double>::quiet_NaN(), +0.),
- std::complex<double>(-std::numeric_limits<double>::infinity(), +0.),
- std::complex<double>(-2, +0.),
- std::complex<double>(-1, +0.),
- std::complex<double>(-0.5, +0.),
- std::complex<double>(-0., +0.),
- std::complex<double>(+0., +0.),
- std::complex<double>(0.5, +0.),
- std::complex<double>(1, +0.),
- std::complex<double>(2, +0.),
- std::complex<double>(std::numeric_limits<double>::infinity(), +0.),
-
- std::complex<double>(std::numeric_limits<double>::quiet_NaN(), 0.5),
- std::complex<double>(-std::numeric_limits<double>::infinity(), 0.5),
- std::complex<double>(-2, 0.5),
- std::complex<double>(-1, 0.5),
- std::complex<double>(-0.5, 0.5),
- std::complex<double>(-0., 0.5),
- std::complex<double>(+0., 0.5),
- std::complex<double>(0.5, 0.5),
- std::complex<double>(1, 0.5),
- std::complex<double>(2, 0.5),
- std::complex<double>(std::numeric_limits<double>::infinity(), 0.5),
-
- std::complex<double>(std::numeric_limits<double>::quiet_NaN(), 1),
- std::complex<double>(-std::numeric_limits<double>::infinity(), 1),
- std::complex<double>(-2, 1),
- std::complex<double>(-1, 1),
- std::complex<double>(-0.5, 1),
- std::complex<double>(-0., 1),
- std::complex<double>(+0., 1),
- std::complex<double>(0.5, 1),
- std::complex<double>(1, 1),
- std::complex<double>(2, 1),
- std::complex<double>(std::numeric_limits<double>::infinity(), 1),
-
- std::complex<double>(std::numeric_limits<double>::quiet_NaN(), 2),
- std::complex<double>(-std::numeric_limits<double>::infinity(), 2),
- std::complex<double>(-2, 2),
- std::complex<double>(-1, 2),
- std::complex<double>(-0.5, 2),
- std::complex<double>(-0., 2),
- std::complex<double>(+0., 2),
- std::complex<double>(0.5, 2),
- std::complex<double>(1, 2),
- std::complex<double>(2, 2),
- std::complex<double>(std::numeric_limits<double>::infinity(), 2),
-
- std::complex<double>(std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::infinity()),
- std::complex<double>(-std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity()),
- std::complex<double>(-2, std::numeric_limits<double>::infinity()),
- std::complex<double>(-1, std::numeric_limits<double>::infinity()),
- std::complex<double>(-0.5, std::numeric_limits<double>::infinity()),
- std::complex<double>(-0., std::numeric_limits<double>::infinity()),
- std::complex<double>(+0., std::numeric_limits<double>::infinity()),
- std::complex<double>(0.5, std::numeric_limits<double>::infinity()),
- std::complex<double>(1, std::numeric_limits<double>::infinity()),
- std::complex<double>(2, std::numeric_limits<double>::infinity()),
- std::complex<double>(std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity())
+ std::complex<T>( 1.e-6, 1.e-6),
+ std::complex<T>(-1.e-6, 1.e-6),
+ std::complex<T>(-1.e-6, -1.e-6),
+ std::complex<T>( 1.e-6, -1.e-6),
+
+ std::complex<T>( 1.e+6, 1.e-6),
+ std::complex<T>(-1.e+6, 1.e-6),
+ std::complex<T>(-1.e+6, -1.e-6),
+ std::complex<T>( 1.e+6, -1.e-6),
+
+ std::complex<T>( 1.e-6, 1.e+6),
+ std::complex<T>(-1.e-6, 1.e+6),
+ std::complex<T>(-1.e-6, -1.e+6),
+ std::complex<T>( 1.e-6, -1.e+6),
+
+ std::complex<T>( 1.e+6, 1.e+6),
+ std::complex<T>(-1.e+6, 1.e+6),
+ std::complex<T>(-1.e+6, -1.e+6),
+ std::complex<T>( 1.e+6, -1.e+6),
+
+ std::complex<T>(-0, -1.e-6),
+ std::complex<T>(-0, 1.e-6),
+ std::complex<T>(-0, 1.e+6),
+ std::complex<T>(-0, -1.e+6),
+ std::complex<T>( 0, -1.e-6),
+ std::complex<T>( 0, 1.e-6),
+ std::complex<T>( 0, 1.e+6),
+ std::complex<T>( 0, -1.e+6),
+
+ std::complex<T>(-1.e-6, -0),
+ std::complex<T>( 1.e-6, -0),
+ std::complex<T>( 1.e+6, -0),
+ std::complex<T>(-1.e+6, -0),
+ std::complex<T>(-1.e-6, 0),
+ std::complex<T>( 1.e-6, 0),
+ std::complex<T>( 1.e+6, 0),
+ std::complex<T>(-1.e+6, 0),
+
+ std::complex<T>(std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN()),
+ std::complex<T>(-std::numeric_limits<T>::infinity(), std::numeric_limits<T>::quiet_NaN()),
+ std::complex<T>(-2, std::numeric_limits<T>::quiet_NaN()),
+ std::complex<T>(-1, std::numeric_limits<T>::quiet_NaN()),
+ std::complex<T>(-0.5, std::numeric_limits<T>::quiet_NaN()),
+ std::complex<T>(-0., std::numeric_limits<T>::quiet_NaN()),
+ std::complex<T>(+0., std::numeric_limits<T>::quiet_NaN()),
+ std::complex<T>(0.5, std::numeric_limits<T>::quiet_NaN()),
+ std::complex<T>(1, std::numeric_limits<T>::quiet_NaN()),
+ std::complex<T>(2, std::numeric_limits<T>::quiet_NaN()),
+ std::complex<T>(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::quiet_NaN()),
+
+ std::complex<T>(std::numeric_limits<T>::quiet_NaN(), -std::numeric_limits<T>::infinity()),
+ std::complex<T>(-std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity()),
+ std::complex<T>(-2, -std::numeric_limits<T>::infinity()),
+ std::complex<T>(-1, -std::numeric_limits<T>::infinity()),
+ std::complex<T>(-0.5, -std::numeric_limits<T>::infinity()),
+ std::complex<T>(-0., -std::numeric_limits<T>::infinity()),
+ std::complex<T>(+0., -std::numeric_limits<T>::infinity()),
+ std::complex<T>(0.5, -std::numeric_limits<T>::infinity()),
+ std::complex<T>(1, -std::numeric_limits<T>::infinity()),
+ std::complex<T>(2, -std::numeric_limits<T>::infinity()),
+ std::complex<T>(std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity()),
+
+ std::complex<T>(std::numeric_limits<T>::quiet_NaN(), -2),
+ std::complex<T>(-std::numeric_limits<T>::infinity(), -2),
+ std::complex<T>(-2, -2),
+ std::complex<T>(-1, -2),
+ std::complex<T>(-0.5, -2),
+ std::complex<T>(-0., -2),
+ std::complex<T>(+0., -2),
+ std::complex<T>(0.5, -2),
+ std::complex<T>(1, -2),
+ std::complex<T>(2, -2),
+ std::complex<T>(std::numeric_limits<T>::infinity(), -2),
+
+ std::complex<T>(std::numeric_limits<T>::quiet_NaN(), -1),
+ std::complex<T>(-std::numeric_limits<T>::infinity(), -1),
+ std::complex<T>(-2, -1),
+ std::complex<T>(-1, -1),
+ std::complex<T>(-0.5, -1),
+ std::complex<T>(-0., -1),
+ std::complex<T>(+0., -1),
+ std::complex<T>(0.5, -1),
+ std::complex<T>(1, -1),
+ std::complex<T>(2, -1),
+ std::complex<T>(std::numeric_limits<T>::infinity(), -1),
+
+ std::complex<T>(std::numeric_limits<T>::quiet_NaN(), -0.5),
+ std::complex<T>(-std::numeric_limits<T>::infinity(), -0.5),
+ std::complex<T>(-2, -0.5),
+ std::complex<T>(-1, -0.5),
+ std::complex<T>(-0.5, -0.5),
+ std::complex<T>(-0., -0.5),
+ std::complex<T>(+0., -0.5),
+ std::complex<T>(0.5, -0.5),
+ std::complex<T>(1, -0.5),
+ std::complex<T>(2, -0.5),
+ std::complex<T>(std::numeric_limits<T>::infinity(), -0.5),
+
+ std::complex<T>(std::numeric_limits<T>::quiet_NaN(), -0.),
+ std::complex<T>(-std::numeric_limits<T>::infinity(), -0.),
+ std::complex<T>(-2, -0.),
+ std::complex<T>(-1, -0.),
+ std::complex<T>(-0.5, -0.),
+ std::complex<T>(-0., -0.),
+ std::complex<T>(+0., -0.),
+ std::complex<T>(0.5, -0.),
+ std::complex<T>(1, -0.),
+ std::complex<T>(2, -0.),
+ std::complex<T>(std::numeric_limits<T>::infinity(), -0.),
+
+ std::complex<T>(std::numeric_limits<T>::quiet_NaN(), +0.),
+ std::complex<T>(-std::numeric_limits<T>::infinity(), +0.),
+ std::complex<T>(-2, +0.),
+ std::complex<T>(-1, +0.),
+ std::complex<T>(-0.5, +0.),
+ std::complex<T>(-0., +0.),
+ std::complex<T>(+0., +0.),
+ std::complex<T>(0.5, +0.),
+ std::complex<T>(1, +0.),
+ std::complex<T>(2, +0.),
+ std::complex<T>(std::numeric_limits<T>::infinity(), +0.),
+
+ std::complex<T>(std::numeric_limits<T>::quiet_NaN(), 0.5),
+ std::complex<T>(-std::numeric_limits<T>::infinity(), 0.5),
+ std::complex<T>(-2, 0.5),
+ std::complex<T>(-1, 0.5),
+ std::complex<T>(-0.5, 0.5),
+ std::complex<T>(-0., 0.5),
+ std::complex<T>(+0., 0.5),
+ std::complex<T>(0.5, 0.5),
+ std::complex<T>(1, 0.5),
+ std::complex<T>(2, 0.5),
+ std::complex<T>(std::numeric_limits<T>::infinity(), 0.5),
+
+ std::complex<T>(std::numeric_limits<T>::quiet_NaN(), 1),
+ std::complex<T>(-std::numeric_limits<T>::infinity(), 1),
+ std::complex<T>(-2, 1),
+ std::complex<T>(-1, 1),
+ std::complex<T>(-0.5, 1),
+ std::complex<T>(-0., 1),
+ std::complex<T>(+0., 1),
+ std::complex<T>(0.5, 1),
+ std::complex<T>(1, 1),
+ std::complex<T>(2, 1),
+ std::complex<T>(std::numeric_limits<T>::infinity(), 1),
+
+ std::complex<T>(std::numeric_limits<T>::quiet_NaN(), 2),
+ std::complex<T>(-std::numeric_limits<T>::infinity(), 2),
+ std::complex<T>(-2, 2),
+ std::complex<T>(-1, 2),
+ std::complex<T>(-0.5, 2),
+ std::complex<T>(-0., 2),
+ std::complex<T>(+0., 2),
+ std::complex<T>(0.5, 2),
+ std::complex<T>(1, 2),
+ std::complex<T>(2, 2),
+ std::complex<T>(std::numeric_limits<T>::infinity(), 2),
+
+ std::complex<T>(std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::infinity()),
+ std::complex<T>(-std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()),
+ std::complex<T>(-2, std::numeric_limits<T>::infinity()),
+ std::complex<T>(-1, std::numeric_limits<T>::infinity()),
+ std::complex<T>(-0.5, std::numeric_limits<T>::infinity()),
+ std::complex<T>(-0., std::numeric_limits<T>::infinity()),
+ std::complex<T>(+0., std::numeric_limits<T>::infinity()),
+ std::complex<T>(0.5, std::numeric_limits<T>::infinity()),
+ std::complex<T>(1, std::numeric_limits<T>::infinity()),
+ std::complex<T>(2, std::numeric_limits<T>::infinity()),
+ std::complex<T>(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()),
+
+ std::complex<T>(std::numeric_limits<T>::max(), 1),
+ std::complex<T>(std::numeric_limits<T>::max(), -1),
+ std::complex<T>(std::numeric_limits<T>::lowest(), 1),
+ std::complex<T>(std::numeric_limits<T>::lowest(), -1),
+
+ std::complex<T>(1, std::numeric_limits<T>::max()),
+ std::complex<T>(1, std::numeric_limits<T>::lowest()),
+ std::complex<T>(-1, std::numeric_limits<T>::max()),
+ std::complex<T>(-1, std::numeric_limits<T>::lowest()),
+
+ std::complex<T>(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()),
+ std::complex<T>(std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest()),
+ std::complex<T>(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max()),
+ std::complex<T>(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::lowest()),
};
-enum {zero, non_zero, inf, NaN, non_zero_nan};
+enum {zero, non_zero, lowest_value, maximum_value, inf, NaN, non_zero_nan};
template <class T, typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0>
TEST_CONSTEXPR_CXX20 bool test_isinf(T v) {
@@ -227,12 +244,17 @@ classify(const std::complex<T>& x)
return NaN;
return non_zero_nan;
}
+ if (x.real() == std::numeric_limits<T>::max() || x.imag() == std::numeric_limits<T>::max())
+ return maximum_value;
+ if (x.real() == std::numeric_limits<T>::lowest() || x.imag() == std::numeric_limits<T>::lowest())
+ return lowest_value;
return non_zero;
}
+template<class T>
inline
int
-classify(double x)
+classify(T x)
{
if (x == 0)
return zero;
@@ -240,6 +262,10 @@ classify(double x)
return inf;
if (std::isnan(x))
return NaN;
+ if (x == std::numeric_limits<T>::max())
+ return maximum_value;
+ if (x == std::numeric_limits<T>::lowest())
+ return lowest_value;
return non_zero;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp
index d12dfd994b0ae9..bc0bdd0ec261dd 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp
@@ -12,7 +12,7 @@
// complex<T>
// operator/(const complex<T>& lhs, const complex<T>& rhs); // constexpr in C++20
-// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2131685
#include <cassert>
#include <complex>
@@ -34,24 +34,30 @@ test()
return true;
}
+...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/122194
More information about the libcxx-commits
mailing list