[libcxx-commits] [libcxx] 7223bcf - [libc++] [C++20] [P0415] Constexpr for std::complex.
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Jan 8 06:46:58 PST 2023
Author: Marek Kurdej
Date: 2023-01-08T15:46:51+01:00
New Revision: 7223bcf04c4ce3c1585df9408c6a6663cc8364ea
URL: https://github.com/llvm/llvm-project/commit/7223bcf04c4ce3c1585df9408c6a6663cc8364ea
DIFF: https://github.com/llvm/llvm-project/commit/7223bcf04c4ce3c1585df9408c6a6663cc8364ea.diff
LOG: [libc++] [C++20] [P0415] Constexpr for std::complex.
This patch adds constexpr to <complex> header: operators, member operators, and member functions (real, imag, norm, conj).
https://eel.is/c++draft/complex.numbers
https://wg21.link/p0415
Reviewed By: ldionne, #libc
Spies: philnik, danilaml, Quuxplusone, wmaxey, arichardson, libcxx-commits
Differential Revision: https://reviews.llvm.org/D79555
Added:
Modified:
libcxx/docs/FeatureTestMacroTable.rst
libcxx/docs/ReleaseNotes.rst
libcxx/docs/Status/Cxx20Papers.csv
libcxx/include/__config
libcxx/include/cmath
libcxx/include/complex
libcxx/include/math.h
libcxx/include/version
libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.compile.pass.cpp
libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
libcxx/test/std/numerics/complex.number/cases.h
libcxx/test/std/numerics/complex.number/cmplx.over/conj.pass.cpp
libcxx/test/std/numerics/complex.number/cmplx.over/norm.pass.cpp
libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_scalar.pass.cpp
libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_scalar.pass.cpp
libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_scalar.pass.cpp
libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_scalar.pass.cpp
libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_scalar.pass.cpp
libcxx/test/std/numerics/complex.number/complex.members/real_imag.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_scalar.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_scalar.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_scalar.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_scalar.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_scalar.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/complex_times_scalar.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/scalar_equals_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/scalar_minus_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/scalar_not_equals_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/scalar_plus_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/scalar_times_complex.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/unary_minus.pass.cpp
libcxx/test/std/numerics/complex.number/complex.ops/unary_plus.pass.cpp
libcxx/utils/generate_feature_test_macro_components.py
Removed:
################################################################################
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index c4ecbd6279924..34e28a31d9e12 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -202,7 +202,7 @@ Status
------------------------------------------------- -----------------
``__cpp_lib_constexpr_algorithms`` ``201806L``
------------------------------------------------- -----------------
- ``__cpp_lib_constexpr_complex`` *unimplemented*
+ ``__cpp_lib_constexpr_complex`` ``201711L``
------------------------------------------------- -----------------
``__cpp_lib_constexpr_dynamic_alloc`` ``201907L``
------------------------------------------------- -----------------
diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst
index ba710c04e1af8..df0646e330157 100644
--- a/libcxx/docs/ReleaseNotes.rst
+++ b/libcxx/docs/ReleaseNotes.rst
@@ -50,6 +50,7 @@ Implemented Papers
- P0600R1 - ``nodiscard`` in the library
- P0339R6 - ``polymorphic_allocator<>`` as a vocabulary type
- P1169R4 - ``static operator()``
+- P0415R1 - ``constexpr`` for ``std::complex``
Improvements and New Features
-----------------------------
diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv
index 95e3c4cc51493..9ce8af1dea7aa 100644
--- a/libcxx/docs/Status/Cxx20Papers.csv
+++ b/libcxx/docs/Status/Cxx20Papers.csv
@@ -5,7 +5,7 @@
"`P0020R6 <https://wg21.link/P0020R6>`__","LWG","Floating Point Atomic","Albuquerque","",""
"`P0053R7 <https://wg21.link/P0053R7>`__","LWG","C++ Synchronized Buffered Ostream","Albuquerque","",""
"`P0202R3 <https://wg21.link/P0202R3>`__","LWG","Add constexpr modifiers to functions in <algorithm> and <utility> Headers","Albuquerque","|Complete|","12.0"
-"`P0415R1 <https://wg21.link/P0415R1>`__","LWG","Constexpr for ``std::complex``\ ","Albuquerque","|In Progress|","7.0"
+"`P0415R1 <https://wg21.link/P0415R1>`__","LWG","Constexpr for ``std::complex``\ ","Albuquerque","|Complete|","16.0"
"`P0439R0 <https://wg21.link/P0439R0>`__","LWG","Make ``std::memory_order``\ a scoped enumeration","Albuquerque","|Complete|",""
"`P0457R2 <https://wg21.link/P0457R2>`__","LWG","String Prefix and Suffix Checking","Albuquerque","|Complete|","6.0"
"`P0550R2 <https://wg21.link/P0550R2>`__","LWG","Transformation Trait ``remove_cvref``\ ","Albuquerque","|Complete|","6.0"
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 8f69db2270ba0..9f7aaddc3ad92 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -196,6 +196,10 @@
# define __has_cpp_attribute(__x) 0
# endif
+# ifndef __has_constexpr_builtin
+# define __has_constexpr_builtin(x) 0
+# endif
+
// '__is_identifier' returns '0' if '__x' is a reserved identifier provided by
// the compiler and '1' otherwise.
# ifndef __is_identifier
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index 29eb0fee57ee4..d106f63231729 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -308,6 +308,7 @@ constexpr long double lerp(long double a, long double b, long double t) noexcept
#include <__config>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_arithmetic.h>
+#include <__type_traits/is_constant_evaluated.h>
#include <__type_traits/is_floating_point.h>
#include <__type_traits/is_same.h>
#include <__type_traits/remove_cv.h>
@@ -623,7 +624,162 @@ _LIBCPP_INLINE_VISIBILITY
_LIBCPP_CONSTEXPR typename enable_if<!is_floating_point<_A1>::value, bool>::type
__constexpr_isfinite(_A1 __lcpp_x) _NOEXCEPT
{
- return std::isfinite(__lcpp_x);
+ return __builtin_isfinite(__lcpp_x);
+}
+
+_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI float __constexpr_copysign(float __x, float __y) _NOEXCEPT {
+ return __builtin_copysignf(__x, __y);
+}
+
+_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI double __constexpr_copysign(double __x, double __y) _NOEXCEPT {
+ return __builtin_copysign(__x, __y);
+}
+
+_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI long double
+__constexpr_copysign(long double __x, long double __y) _NOEXCEPT {
+ return __builtin_copysignl(__x, __y);
+}
+
+template <class _A1, class _A2>
+_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI
+ typename std::__enable_if_t<std::is_arithmetic<_A1>::value && std::is_arithmetic<_A2>::value,
+ std::__promote<_A1, _A2> >::type
+ __constexpr_copysign(_A1 __x, _A2 __y) _NOEXCEPT {
+ typedef typename std::__promote<_A1, _A2>::type __result_type;
+ static_assert((!(std::_IsSame<_A1, __result_type>::value && std::_IsSame<_A2, __result_type>::value)), "");
+ return __builtin_copysign((__result_type)__x, (__result_type)__y);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR float __constexpr_fabs(float __x) _NOEXCEPT {
+ return __builtin_fabsf(__x);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double __constexpr_fabs(double __x) _NOEXCEPT {
+ return __builtin_fabs(__x);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR long double __constexpr_fabs(long double __x) _NOEXCEPT {
+ return __builtin_fabsl(__x);
+}
+
+template <class _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double __constexpr_fabs(_Tp __x) _NOEXCEPT {
+ return __builtin_fabs(static_cast<double>(__x));
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 float __constexpr_fmax(float __x, float __y) _NOEXCEPT {
+#if !__has_constexpr_builtin(__builtin_fmaxf)
+ if (__libcpp_is_constant_evaluated()) {
+ if (std::__constexpr_isnan(__x))
+ return __y;
+ if (std::__constexpr_isnan(__y))
+ return __x;
+ return __x < __y ? __y : __x;
+ }
+#endif
+ return __builtin_fmaxf(__x, __y);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 double __constexpr_fmax(double __x, double __y) _NOEXCEPT {
+#if !__has_constexpr_builtin(__builtin_fmax)
+ if (__libcpp_is_constant_evaluated()) {
+ if (std::__constexpr_isnan(__x))
+ return __y;
+ if (std::__constexpr_isnan(__y))
+ return __x;
+ return __x < __y ? __y : __x;
+ }
+#endif
+ return __builtin_fmax(__x, __y);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 long double
+__constexpr_fmax(long double __x, long double __y) _NOEXCEPT {
+#if !__has_constexpr_builtin(__builtin_fmaxl)
+ if (__libcpp_is_constant_evaluated()) {
+ if (std::__constexpr_isnan(__x))
+ return __y;
+ if (std::__constexpr_isnan(__y))
+ return __x;
+ return __x < __y ? __y : __x;
+ }
+#endif
+ return __builtin_fmaxl(__x, __y);
+}
+
+template <class _Tp, class _Up, __enable_if_t<is_arithmetic<_Tp>::value && is_arithmetic<_Up>::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename __promote<_Tp, _Up>::type
+__constexpr_fmax(_Tp __x, _Up __y) _NOEXCEPT {
+ using __result_type = typename __promote<_Tp, _Up>::type;
+ return std::__constexpr_fmax(static_cast<__result_type>(__x), static_cast<__result_type>(__y));
+}
+
+template <class _Tp>
+_LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __constexpr_logb(_Tp __x) {
+#if !__has_constexpr_builtin(__builtin_logb)
+ if (__libcpp_is_constant_evaluated()) {
+ if (__x == _Tp(0)) {
+ // raise FE_DIVBYZERO
+ return -numeric_limits<_Tp>::infinity();
+ }
+
+ if (std::__constexpr_isinf(__x))
+ return numeric_limits<_Tp>::infinity();
+
+ if (std::__constexpr_isnan(__x))
+ return numeric_limits<_Tp>::quiet_NaN();
+
+ __x = std::__constexpr_fabs(__x);
+ unsigned long long __exp = 0;
+ while (__x >= numeric_limits<_Tp>::radix) {
+ __x /= numeric_limits<_Tp>::radix;
+ __exp += 1;
+ }
+ return _Tp(__exp);
+ }
+#endif // _LIBCPP_STD_VER > 17
+ return __builtin_logb(__x);
+}
+
+template <class _Tp>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp __constexpr_scalbn(_Tp __x, int __exp) {
+#if !__has_constexpr_builtin(__builtin_scalbln)
+ if (__libcpp_is_constant_evaluated()) {
+ if (__x == _Tp(0))
+ return __x;
+
+ if (std::__constexpr_isinf(__x))
+ return __x;
+
+ if (__exp == _Tp(0))
+ return __x;
+
+ if (std::__constexpr_isnan(__x))
+ return numeric_limits<_Tp>::quiet_NaN();
+
+ _Tp __mult(1);
+ if (__exp > 0) {
+ __mult = numeric_limits<_Tp>::radix;
+ --__exp;
+ } else {
+ ++__exp;
+ __exp = -__exp;
+ __mult /= numeric_limits<_Tp>::radix;
+ }
+
+ while (__exp > 0) {
+ if (!(__exp & 1)) {
+ __mult *= __mult;
+ __exp >>= 1;
+ } else {
+ __x *= __mult;
+ --__exp;
+ }
+ }
+ return __x;
+ }
+#endif // _LIBCPP_STD_VER > 17
+ return __builtin_scalbn(__x, __exp);
}
#if _LIBCPP_STD_VER > 17
diff --git a/libcxx/include/complex b/libcxx/include/complex
index 1117dda257a34..760fbaa81128e 100644
--- a/libcxx/include/complex
+++ b/libcxx/include/complex
@@ -29,21 +29,21 @@ public:
T real() const; // constexpr in C++14
T imag() const; // constexpr in C++14
- void real(T);
- void imag(T);
-
- complex<T>& operator= (const T&);
- complex<T>& operator+=(const T&);
- complex<T>& operator-=(const T&);
- complex<T>& operator*=(const T&);
- complex<T>& operator/=(const T&);
-
- complex& operator=(const complex&);
- template<class X> complex<T>& operator= (const complex<X>&);
- template<class X> complex<T>& operator+=(const complex<X>&);
- template<class X> complex<T>& operator-=(const complex<X>&);
- template<class X> complex<T>& operator*=(const complex<X>&);
- template<class X> complex<T>& operator/=(const complex<X>&);
+ void real(T); // constexpr in C++20
+ void imag(T); // constexpr in C++20
+
+ complex<T>& operator= (const T&); // constexpr in C++20
+ complex<T>& operator+=(const T&); // constexpr in C++20
+ complex<T>& operator-=(const T&); // constexpr in C++20
+ complex<T>& operator*=(const T&); // constexpr in C++20
+ complex<T>& operator/=(const T&); // constexpr in C++20
+
+ complex& operator=(const complex&); // constexpr in C++20
+ template<class X> complex<T>& operator= (const complex<X>&); // constexpr in C++20
+ template<class X> complex<T>& operator+=(const complex<X>&); // constexpr in C++20
+ template<class X> complex<T>& operator-=(const complex<X>&); // constexpr in C++20
+ template<class X> complex<T>& operator*=(const complex<X>&); // constexpr in C++20
+ template<class X> complex<T>& operator/=(const complex<X>&); // constexpr in C++20
};
template<>
@@ -57,22 +57,22 @@ public:
explicit constexpr complex(const complex<long double>&);
constexpr float real() const;
- void real(float);
+ void real(float); // constexpr in C++20
constexpr float imag() const;
- void imag(float);
-
- complex<float>& operator= (float);
- complex<float>& operator+=(float);
- complex<float>& operator-=(float);
- complex<float>& operator*=(float);
- complex<float>& operator/=(float);
-
- complex<float>& operator=(const complex<float>&);
- template<class X> complex<float>& operator= (const complex<X>&);
- template<class X> complex<float>& operator+=(const complex<X>&);
- template<class X> complex<float>& operator-=(const complex<X>&);
- template<class X> complex<float>& operator*=(const complex<X>&);
- template<class X> complex<float>& operator/=(const complex<X>&);
+ void imag(float); // constexpr in C++20
+
+ complex<float>& operator= (float); // constexpr in C++20
+ complex<float>& operator+=(float); // constexpr in C++20
+ complex<float>& operator-=(float); // constexpr in C++20
+ complex<float>& operator*=(float); // constexpr in C++20
+ complex<float>& operator/=(float); // constexpr in C++20
+
+ complex<float>& operator=(const complex<float>&); // constexpr in C++20
+ template<class X> complex<float>& operator= (const complex<X>&); // constexpr in C++20
+ template<class X> complex<float>& operator+=(const complex<X>&); // constexpr in C++20
+ template<class X> complex<float>& operator-=(const complex<X>&); // constexpr in C++20
+ template<class X> complex<float>& operator*=(const complex<X>&); // constexpr in C++20
+ template<class X> complex<float>& operator/=(const complex<X>&); // constexpr in C++20
};
template<>
@@ -86,22 +86,22 @@ public:
explicit constexpr complex(const complex<long double>&);
constexpr double real() const;
- void real(double);
+ void real(double); // constexpr in C++20
constexpr double imag() const;
- void imag(double);
-
- complex<double>& operator= (double);
- complex<double>& operator+=(double);
- complex<double>& operator-=(double);
- complex<double>& operator*=(double);
- complex<double>& operator/=(double);
- complex<double>& operator=(const complex<double>&);
-
- template<class X> complex<double>& operator= (const complex<X>&);
- template<class X> complex<double>& operator+=(const complex<X>&);
- template<class X> complex<double>& operator-=(const complex<X>&);
- template<class X> complex<double>& operator*=(const complex<X>&);
- template<class X> complex<double>& operator/=(const complex<X>&);
+ void imag(double); // constexpr in C++20
+
+ complex<double>& operator= (double); // constexpr in C++20
+ complex<double>& operator+=(double); // constexpr in C++20
+ complex<double>& operator-=(double); // constexpr in C++20
+ complex<double>& operator*=(double); // constexpr in C++20
+ complex<double>& operator/=(double); // constexpr in C++20
+ complex<double>& operator=(const complex<double>&); // constexpr in C++20
+
+ template<class X> complex<double>& operator= (const complex<X>&); // constexpr in C++20
+ template<class X> complex<double>& operator+=(const complex<X>&); // constexpr in C++20
+ template<class X> complex<double>& operator-=(const complex<X>&); // constexpr in C++20
+ template<class X> complex<double>& operator*=(const complex<X>&); // constexpr in C++20
+ template<class X> complex<double>& operator/=(const complex<X>&); // constexpr in C++20
};
template<>
@@ -115,39 +115,39 @@ public:
constexpr complex(const complex<double>&);
constexpr long double real() const;
- void real(long double);
+ void real(long double); // constexpr in C++20
constexpr long double imag() const;
- void imag(long double);
-
- complex<long double>& operator=(const complex<long double>&);
- complex<long double>& operator= (long double);
- complex<long double>& operator+=(long double);
- complex<long double>& operator-=(long double);
- complex<long double>& operator*=(long double);
- complex<long double>& operator/=(long double);
-
- template<class X> complex<long double>& operator= (const complex<X>&);
- template<class X> complex<long double>& operator+=(const complex<X>&);
- template<class X> complex<long double>& operator-=(const complex<X>&);
- template<class X> complex<long double>& operator*=(const complex<X>&);
- template<class X> complex<long double>& operator/=(const complex<X>&);
+ void imag(long double); // constexpr in C++20
+
+ complex<long double>& operator=(const complex<long double>&); // constexpr in C++20
+ complex<long double>& operator= (long double); // constexpr in C++20
+ complex<long double>& operator+=(long double); // constexpr in C++20
+ complex<long double>& operator-=(long double); // constexpr in C++20
+ complex<long double>& operator*=(long double); // constexpr in C++20
+ complex<long double>& operator/=(long double); // constexpr in C++20
+
+ template<class X> complex<long double>& operator= (const complex<X>&); // constexpr in C++20
+ template<class X> complex<long double>& operator+=(const complex<X>&); // constexpr in C++20
+ template<class X> complex<long double>& operator-=(const complex<X>&); // constexpr in C++20
+ template<class X> complex<long double>& operator*=(const complex<X>&); // constexpr in C++20
+ template<class X> complex<long double>& operator/=(const complex<X>&); // constexpr in C++20
};
// 26.3.6 operators:
-template<class T> complex<T> operator+(const complex<T>&, const complex<T>&);
-template<class T> complex<T> operator+(const complex<T>&, const T&);
-template<class T> complex<T> operator+(const T&, const complex<T>&);
-template<class T> complex<T> operator-(const complex<T>&, const complex<T>&);
-template<class T> complex<T> operator-(const complex<T>&, const T&);
-template<class T> complex<T> operator-(const T&, const complex<T>&);
-template<class T> complex<T> operator*(const complex<T>&, const complex<T>&);
-template<class T> complex<T> operator*(const complex<T>&, const T&);
-template<class T> complex<T> operator*(const T&, const complex<T>&);
-template<class T> complex<T> operator/(const complex<T>&, const complex<T>&);
-template<class T> complex<T> operator/(const complex<T>&, const T&);
-template<class T> complex<T> operator/(const T&, const complex<T>&);
-template<class T> complex<T> operator+(const complex<T>&);
-template<class T> complex<T> operator-(const complex<T>&);
+template<class T> complex<T> operator+(const complex<T>&, const complex<T>&); // constexpr in C++20
+template<class T> complex<T> operator+(const complex<T>&, const T&); // constexpr in C++20
+template<class T> complex<T> operator+(const T&, const complex<T>&); // constexpr in C++20
+template<class T> complex<T> operator-(const complex<T>&, const complex<T>&); // constexpr in C++20
+template<class T> complex<T> operator-(const complex<T>&, const T&); // constexpr in C++20
+template<class T> complex<T> operator-(const T&, const complex<T>&); // constexpr in C++20
+template<class T> complex<T> operator*(const complex<T>&, const complex<T>&); // constexpr in C++20
+template<class T> complex<T> operator*(const complex<T>&, const T&); // constexpr in C++20
+template<class T> complex<T> operator*(const T&, const complex<T>&); // constexpr in C++20
+template<class T> complex<T> operator/(const complex<T>&, const complex<T>&); // constexpr in C++20
+template<class T> complex<T> operator/(const complex<T>&, const T&); // constexpr in C++20
+template<class T> complex<T> operator/(const T&, const complex<T>&); // constexpr in C++20
+template<class T> complex<T> operator+(const complex<T>&); // constexpr in C++20
+template<class T> complex<T> operator-(const complex<T>&); // constexpr in C++20
template<class T> bool operator==(const complex<T>&, const complex<T>&); // constexpr in C++14
template<class T> bool operator==(const complex<T>&, const T&); // constexpr in C++14
template<class T> bool operator==(const T&, const complex<T>&); // constexpr in C++14
@@ -184,17 +184,17 @@ template<class T> T arg(const complex<T>&);
template<Integral T> double arg(T);
float arg(float);
-template<class T> T norm(const complex<T>&);
- long double norm(long double);
- double norm(double);
-template<Integral T> double norm(T);
- float norm(float);
+template<class T> T norm(const complex<T>&); // constexpr in C++20
+ long double norm(long double); // constexpr in C++20
+ double norm(double); // constexpr in C++20
+template<Integral T> double norm(T); // constexpr in C++20
+ float norm(float); // constexpr in C++20
-template<class T> complex<T> conj(const complex<T>&);
- complex<long double> conj(long double);
- complex<double> conj(double);
-template<Integral T> complex<double> conj(T);
- complex<float> conj(float);
+template<class T> complex<T> conj(const complex<T>&); // constexpr in C++20
+ complex<long double> conj(long double); // constexpr in C++20
+ complex<double> conj(double); // constexpr in C++20
+template<Integral T> complex<double> conj(T); // constexpr in C++20
+ complex<float> conj(float); // constexpr in C++20
template<class T> complex<T> proj(const complex<T>&);
complex<long double> proj(long double);
@@ -251,8 +251,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template<class _Tp> class _LIBCPP_TEMPLATE_VIS complex;
-template<class _Tp> _LIBCPP_HIDE_FROM_ABI complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w);
-template<class _Tp> _LIBCPP_HIDE_FROM_ABI complex<_Tp> operator/(const complex<_Tp>& __x, const complex<_Tp>& __y);
+template<class _Tp> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w);
+template<class _Tp> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator/(const complex<_Tp>& __x, const complex<_Tp>& __y);
template<class _Tp>
class _LIBCPP_TEMPLATE_VIS complex
@@ -273,40 +273,40 @@ public:
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 value_type real() const {return __re_;}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 value_type imag() const {return __im_;}
- _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;}
- _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;}
- _LIBCPP_INLINE_VISIBILITY complex& operator= (const value_type& __re)
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const value_type& __re)
{__re_ = __re; __im_ = value_type(); return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator+=(const value_type& __re) {__re_ += __re; return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator-=(const value_type& __re) {__re_ -= __re; return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator*=(const value_type& __re) {__re_ *= __re; __im_ *= __re; return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator/=(const value_type& __re) {__re_ /= __re; __im_ /= __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const value_type& __re) {__re_ += __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const value_type& __re) {__re_ -= __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const value_type& __re) {__re_ *= __re; __im_ *= __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const value_type& __re) {__re_ /= __re; __im_ /= __re; return *this;}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const complex<_Xp>& __c)
{
__re_ = __c.real();
__im_ = __c.imag();
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c)
{
__re_ += __c.real();
__im_ += __c.imag();
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c)
{
__re_ -= __c.real();
__im_ -= __c.imag();
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c)
{
*this = *this * complex(__c.real(), __c.imag());
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c)
{
*this = *this / complex(__c.real(), __c.imag());
return *this;
@@ -334,40 +334,40 @@ public:
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR float real() const {return __re_;}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR float imag() const {return __im_;}
- _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;}
- _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;}
- _LIBCPP_INLINE_VISIBILITY complex& operator= (float __re)
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (float __re)
{__re_ = __re; __im_ = value_type(); return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator+=(float __re) {__re_ += __re; return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator-=(float __re) {__re_ -= __re; return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator*=(float __re) {__re_ *= __re; __im_ *= __re; return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator/=(float __re) {__re_ /= __re; __im_ /= __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(float __re) {__re_ += __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(float __re) {__re_ -= __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(float __re) {__re_ *= __re; __im_ *= __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(float __re) {__re_ /= __re; __im_ /= __re; return *this;}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const complex<_Xp>& __c)
{
__re_ = __c.real();
__im_ = __c.imag();
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c)
{
__re_ += __c.real();
__im_ += __c.imag();
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c)
{
__re_ -= __c.real();
__im_ -= __c.imag();
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c)
{
*this = *this * complex(__c.real(), __c.imag());
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c)
{
*this = *this / complex(__c.real(), __c.imag());
return *this;
@@ -392,40 +392,40 @@ public:
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR double real() const {return __re_;}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR double imag() const {return __im_;}
- _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;}
- _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;}
- _LIBCPP_INLINE_VISIBILITY complex& operator= (double __re)
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (double __re)
{__re_ = __re; __im_ = value_type(); return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator+=(double __re) {__re_ += __re; return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator-=(double __re) {__re_ -= __re; return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator*=(double __re) {__re_ *= __re; __im_ *= __re; return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator/=(double __re) {__re_ /= __re; __im_ /= __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(double __re) {__re_ += __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(double __re) {__re_ -= __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(double __re) {__re_ *= __re; __im_ *= __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(double __re) {__re_ /= __re; __im_ /= __re; return *this;}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const complex<_Xp>& __c)
{
__re_ = __c.real();
__im_ = __c.imag();
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c)
{
__re_ += __c.real();
__im_ += __c.imag();
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c)
{
__re_ -= __c.real();
__im_ -= __c.imag();
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c)
{
*this = *this * complex(__c.real(), __c.imag());
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c)
{
*this = *this / complex(__c.real(), __c.imag());
return *this;
@@ -450,40 +450,40 @@ public:
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR long double real() const {return __re_;}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR long double imag() const {return __im_;}
- _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;}
- _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;}
- _LIBCPP_INLINE_VISIBILITY complex& operator= (long double __re)
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (long double __re)
{__re_ = __re; __im_ = value_type(); return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator+=(long double __re) {__re_ += __re; return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator-=(long double __re) {__re_ -= __re; return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator*=(long double __re) {__re_ *= __re; __im_ *= __re; return *this;}
- _LIBCPP_INLINE_VISIBILITY complex& operator/=(long double __re) {__re_ /= __re; __im_ /= __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(long double __re) {__re_ += __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(long double __re) {__re_ -= __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(long double __re) {__re_ *= __re; __im_ *= __re; return *this;}
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(long double __re) {__re_ /= __re; __im_ /= __re; return *this;}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const complex<_Xp>& __c)
{
__re_ = __c.real();
__im_ = __c.imag();
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c)
{
__re_ += __c.real();
__im_ += __c.imag();
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c)
{
__re_ -= __c.real();
__im_ -= __c.imag();
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c)
{
*this = *this * complex(__c.real(), __c.imag());
return *this;
}
- template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c)
+ template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c)
{
*this = *this / complex(__c.real(), __c.imag());
return *this;
@@ -523,7 +523,7 @@ complex<long double>::complex(const complex<double>& __c)
// 26.3.6 operators:
template<class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
complex<_Tp>
operator+(const complex<_Tp>& __x, const complex<_Tp>& __y)
{
@@ -533,7 +533,7 @@ operator+(const complex<_Tp>& __x, const complex<_Tp>& __y)
}
template<class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
complex<_Tp>
operator+(const complex<_Tp>& __x, const _Tp& __y)
{
@@ -543,7 +543,7 @@ operator+(const complex<_Tp>& __x, const _Tp& __y)
}
template<class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
complex<_Tp>
operator+(const _Tp& __x, const complex<_Tp>& __y)
{
@@ -553,7 +553,7 @@ operator+(const _Tp& __x, const complex<_Tp>& __y)
}
template<class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
complex<_Tp>
operator-(const complex<_Tp>& __x, const complex<_Tp>& __y)
{
@@ -563,7 +563,7 @@ operator-(const complex<_Tp>& __x, const complex<_Tp>& __y)
}
template<class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
complex<_Tp>
operator-(const complex<_Tp>& __x, const _Tp& __y)
{
@@ -573,7 +573,7 @@ operator-(const complex<_Tp>& __x, const _Tp& __y)
}
template<class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
complex<_Tp>
operator-(const _Tp& __x, const complex<_Tp>& __y)
{
@@ -583,13 +583,46 @@ operator-(const _Tp& __x, const complex<_Tp>& __y)
}
template<class _Tp>
-_LIBCPP_HIDE_FROM_ABI complex<_Tp>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator*(const complex<_Tp>& __z, const complex<_Tp>& __w)
{
_Tp __a = __z.real();
_Tp __b = __z.imag();
_Tp __c = __w.real();
_Tp __d = __w.imag();
+
+ // Avoid floating point operations that are invalid during constant evaluation
+ if (__libcpp_is_constant_evaluated()) {
+ bool __z_zero = __a == _Tp(0) && __b == _Tp(0);
+ bool __w_zero = __c == _Tp(0) && __d == _Tp(0);
+ bool __z_inf = std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b);
+ bool __w_inf = std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d);
+ bool __z_nan = !__z_inf && (
+ (std::__constexpr_isnan(__a) && std::__constexpr_isnan(__b))
+ || (std::__constexpr_isnan(__a) && __b == _Tp(0))
+ || (__a == _Tp(0) && std::__constexpr_isnan(__b))
+ );
+ bool __w_nan = !__w_inf && (
+ (std::__constexpr_isnan(__c) && std::__constexpr_isnan(__d))
+ || (std::__constexpr_isnan(__c) && __d == _Tp(0))
+ || (__c == _Tp(0) && std::__constexpr_isnan(__d))
+ );
+ if (__z_nan || __w_nan) {
+ return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
+ }
+ if (__z_inf || __w_inf) {
+ if (__z_zero || __w_zero) {
+ return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
+ }
+ return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity()));
+ }
+ bool __z_nonzero_nan = !__z_inf && !__z_nan && (std::__constexpr_isnan(__a) || std::__constexpr_isnan(__b));
+ bool __w_nonzero_nan = !__w_inf && !__w_nan && (std::__constexpr_isnan(__c) || std::__constexpr_isnan(__d));
+ if (__z_nonzero_nan || __w_nonzero_nan) {
+ return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
+ }
+ }
+
_Tp __ac = __a * __c;
_Tp __bd = __b * __d;
_Tp __ad = __a * __d;
@@ -601,35 +634,35 @@ operator*(const complex<_Tp>& __z, const complex<_Tp>& __w)
bool __recalc = false;
if (std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b))
{
- __a = std::copysign(std::__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a);
- __b = std::copysign(std::__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b);
+ __a = std::__constexpr_copysign(std::__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a);
+ __b = std::__constexpr_copysign(std::__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b);
if (std::__constexpr_isnan(__c))
- __c = std::copysign(_Tp(0), __c);
+ __c = std::__constexpr_copysign(_Tp(0), __c);
if (std::__constexpr_isnan(__d))
- __d = std::copysign(_Tp(0), __d);
+ __d = std::__constexpr_copysign(_Tp(0), __d);
__recalc = true;
}
if (std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d))
{
- __c = std::copysign(std::__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c);
- __d = std::copysign(std::__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d);
+ __c = std::__constexpr_copysign(std::__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c);
+ __d = std::__constexpr_copysign(std::__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d);
if (std::__constexpr_isnan(__a))
- __a = std::copysign(_Tp(0), __a);
+ __a = std::__constexpr_copysign(_Tp(0), __a);
if (std::__constexpr_isnan(__b))
- __b = std::copysign(_Tp(0), __b);
+ __b = std::__constexpr_copysign(_Tp(0), __b);
__recalc = true;
}
if (!__recalc && (std::__constexpr_isinf(__ac) || std::__constexpr_isinf(__bd) ||
std::__constexpr_isinf(__ad) || std::__constexpr_isinf(__bc)))
{
if (std::__constexpr_isnan(__a))
- __a = std::copysign(_Tp(0), __a);
+ __a = std::__constexpr_copysign(_Tp(0), __a);
if (std::__constexpr_isnan(__b))
- __b = std::copysign(_Tp(0), __b);
+ __b = std::__constexpr_copysign(_Tp(0), __b);
if (std::__constexpr_isnan(__c))
- __c = std::copysign(_Tp(0), __c);
+ __c = std::__constexpr_copysign(_Tp(0), __c);
if (std::__constexpr_isnan(__d))
- __d = std::copysign(_Tp(0), __d);
+ __d = std::__constexpr_copysign(_Tp(0), __d);
__recalc = true;
}
if (__recalc)
@@ -642,7 +675,7 @@ operator*(const complex<_Tp>& __z, const complex<_Tp>& __w)
}
template<class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
complex<_Tp>
operator*(const complex<_Tp>& __x, const _Tp& __y)
{
@@ -652,7 +685,7 @@ operator*(const complex<_Tp>& __x, const _Tp& __y)
}
template<class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
complex<_Tp>
operator*(const _Tp& __x, const complex<_Tp>& __y)
{
@@ -662,7 +695,7 @@ operator*(const _Tp& __x, const complex<_Tp>& __y)
}
template<class _Tp>
-_LIBCPP_HIDE_FROM_ABI complex<_Tp>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
operator/(const complex<_Tp>& __z, const complex<_Tp>& __w)
{
int __ilogbw = 0;
@@ -670,34 +703,74 @@ operator/(const complex<_Tp>& __z, const complex<_Tp>& __w)
_Tp __b = __z.imag();
_Tp __c = __w.real();
_Tp __d = __w.imag();
- _Tp __logbw = std::logb(std::fmax(std::fabs(__c), std::fabs(__d)));
+ _Tp __logbw = std::__constexpr_logb(std::__constexpr_fmax(std::__constexpr_fabs(__c), std::__constexpr_fabs(__d)));
if (std::__constexpr_isfinite(__logbw))
{
__ilogbw = static_cast<int>(__logbw);
- __c = std::scalbn(__c, -__ilogbw);
- __d = std::scalbn(__d, -__ilogbw);
+ __c = std::__constexpr_scalbn(__c, -__ilogbw);
+ __d = std::__constexpr_scalbn(__d, -__ilogbw);
}
+
+ // Avoid floating point operations that are invalid during constant evaluation
+ if (__libcpp_is_constant_evaluated()) {
+ bool __z_zero = __a == _Tp(0) && __b == _Tp(0);
+ bool __w_zero = __c == _Tp(0) && __d == _Tp(0);
+ bool __z_inf = std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b);
+ bool __w_inf = std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d);
+ bool __z_nan = !__z_inf && (
+ (std::__constexpr_isnan(__a) && std::__constexpr_isnan(__b))
+ || (std::__constexpr_isnan(__a) && __b == _Tp(0))
+ || (__a == _Tp(0) && std::__constexpr_isnan(__b))
+ );
+ bool __w_nan = !__w_inf && (
+ (std::__constexpr_isnan(__c) && std::__constexpr_isnan(__d))
+ || (std::__constexpr_isnan(__c) && __d == _Tp(0))
+ || (__c == _Tp(0) && std::__constexpr_isnan(__d))
+ );
+ if ((__z_nan || __w_nan) || (__z_inf && __w_inf)) {
+ return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
+ }
+ bool __z_nonzero_nan = !__z_inf && !__z_nan && (std::__constexpr_isnan(__a) || std::__constexpr_isnan(__b));
+ bool __w_nonzero_nan = !__w_inf && !__w_nan && (std::__constexpr_isnan(__c) || std::__constexpr_isnan(__d));
+ if (__z_nonzero_nan || __w_nonzero_nan) {
+ if (__w_zero) {
+ return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity()));
+ }
+ return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
+ }
+ if (__w_inf) {
+ return complex<_Tp>(_Tp(0), _Tp(0));
+ }
+ if (__z_inf) {
+ return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity()));
+ }
+ if (__w_zero) {
+ if (__z_zero) {
+ return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
+ }
+ return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity()));
+ }
+ }
+
_Tp __denom = __c * __c + __d * __d;
- _Tp __x = std::scalbn((__a * __c + __b * __d) / __denom, -__ilogbw);
- _Tp __y = std::scalbn((__b * __c - __a * __d) / __denom, -__ilogbw);
+ _Tp __x = std::__constexpr_scalbn((__a * __c + __b * __d) / __denom, -__ilogbw);
+ _Tp __y = std::__constexpr_scalbn((__b * __c - __a * __d) / __denom, -__ilogbw);
if (std::__constexpr_isnan(__x) && std::__constexpr_isnan(__y))
{
if ((__denom == _Tp(0)) && (!std::__constexpr_isnan(__a) || !std::__constexpr_isnan(__b)))
{
- __x = std::copysign(_Tp(INFINITY), __c) * __a;
- __y = std::copysign(_Tp(INFINITY), __c) * __b;
- }
- else if ((std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b)) && std::__constexpr_isfinite(__c) && std::__constexpr_isfinite(__d))
- {
- __a = std::copysign(std::__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a);
- __b = std::copysign(std::__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b);
+ __x = std::__constexpr_copysign(_Tp(INFINITY), __c) * __a;
+ __y = std::__constexpr_copysign(_Tp(INFINITY), __c) * __b;
+ } else if ((std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b)) && std::__constexpr_isfinite(__c) &&
+ std::__constexpr_isfinite(__d)) {
+ __a = std::__constexpr_copysign(std::__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a);
+ __b = std::__constexpr_copysign(std::__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b);
__x = _Tp(INFINITY) * (__a * __c + __b * __d);
__y = _Tp(INFINITY) * (__b * __c - __a * __d);
- }
- else if (std::__constexpr_isinf(__logbw) && __logbw > _Tp(0) && std::__constexpr_isfinite(__a) && std::__constexpr_isfinite(__b))
- {
- __c = std::copysign(std::__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c);
- __d = std::copysign(std::__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d);
+ } else if (std::__constexpr_isinf(__logbw) && __logbw > _Tp(0) && std::__constexpr_isfinite(__a) &&
+ std::__constexpr_isfinite(__b)) {
+ __c = std::__constexpr_copysign(std::__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c);
+ __d = std::__constexpr_copysign(std::__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d);
__x = _Tp(0) * (__a * __c + __b * __d);
__y = _Tp(0) * (__b * __c - __a * __d);
}
@@ -706,7 +779,7 @@ operator/(const complex<_Tp>& __z, const complex<_Tp>& __w)
}
template<class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
complex<_Tp>
operator/(const complex<_Tp>& __x, const _Tp& __y)
{
@@ -714,7 +787,7 @@ operator/(const complex<_Tp>& __x, const _Tp& __y)
}
template<class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
complex<_Tp>
operator/(const _Tp& __x, const complex<_Tp>& __y)
{
@@ -724,7 +797,7 @@ operator/(const _Tp& __x, const complex<_Tp>& __y)
}
template<class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
complex<_Tp>
operator+(const complex<_Tp>& __x)
{
@@ -732,7 +805,7 @@ operator+(const complex<_Tp>& __x)
}
template<class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
complex<_Tp>
operator-(const complex<_Tp>& __x)
{
@@ -903,7 +976,7 @@ arg(_Tp __re)
// norm
template<class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_Tp
norm(const complex<_Tp>& __c)
{
@@ -915,7 +988,7 @@ norm(const complex<_Tp>& __c)
}
template <class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
typename __libcpp_complex_overload_traits<_Tp>::_ValueType
norm(_Tp __re)
{
@@ -926,7 +999,7 @@ norm(_Tp __re)
// conj
template<class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
complex<_Tp>
conj(const complex<_Tp>& __c)
{
@@ -934,7 +1007,7 @@ conj(const complex<_Tp>& __c)
}
template <class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
typename __libcpp_complex_overload_traits<_Tp>::_ComplexType
conj(_Tp __re)
{
diff --git a/libcxx/include/math.h b/libcxx/include/math.h
index 14fa9e286ea30..1636ec4b7050e 100644
--- a/libcxx/include/math.h
+++ b/libcxx/include/math.h
@@ -1043,43 +1043,12 @@ cbrt(_A1 __x) _NOEXCEPT {return __builtin_cbrt((double)__x);}
// copysign
-_LIBCPP_CONSTEXPR
-inline _LIBCPP_HIDE_FROM_ABI float __libcpp_copysign(float __x, float __y) _NOEXCEPT {
- return __builtin_copysignf(__x, __y);
-}
-
-_LIBCPP_CONSTEXPR
-inline _LIBCPP_HIDE_FROM_ABI double __libcpp_copysign(double __x, double __y) _NOEXCEPT {
- return __builtin_copysign(__x, __y);
-}
-
-_LIBCPP_CONSTEXPR
-inline _LIBCPP_HIDE_FROM_ABI long double __libcpp_copysign(long double __x, long double __y) _NOEXCEPT {
- return __builtin_copysignl(__x, __y);
-}
-
-template <class _A1, class _A2>
-_LIBCPP_CONSTEXPR
-inline _LIBCPP_HIDE_FROM_ABI
-typename std::__enable_if_t
-<
- std::is_arithmetic<_A1>::value &&
- std::is_arithmetic<_A2>::value,
- std::__promote<_A1, _A2>
->::type
-__libcpp_copysign(_A1 __x, _A2 __y) _NOEXCEPT {
- typedef typename std::__promote<_A1, _A2>::type __result_type;
- static_assert((!(std::_IsSame<_A1, __result_type>::value &&
- std::_IsSame<_A2, __result_type>::value)), "");
- return __builtin_copysign((__result_type)__x, (__result_type)__y);
-}
-
inline _LIBCPP_HIDE_FROM_ABI float copysign(float __x, float __y) _NOEXCEPT {
- return ::__libcpp_copysign(__x, __y);
+ return ::__builtin_copysignf(__x, __y);
}
inline _LIBCPP_HIDE_FROM_ABI long double copysign(long double __x, long double __y) _NOEXCEPT {
- return ::__libcpp_copysign(__x, __y);
+ return ::__builtin_copysignl(__x, __y);
}
template <class _A1, class _A2>
@@ -1091,7 +1060,7 @@ typename std::__enable_if_t
std::__promote<_A1, _A2>
>::type
copysign(_A1 __x, _A2 __y) _NOEXCEPT {
- return ::__libcpp_copysign(__x, __y);
+ return ::__builtin_copysign(__x, __y);
}
// erf
diff --git a/libcxx/include/version b/libcxx/include/version
index ae4e14f337284..d348325d1bf50 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -317,7 +317,7 @@ __cpp_lib_void_t 201411L <type_traits>
# endif
# define __cpp_lib_concepts 202002L
# define __cpp_lib_constexpr_algorithms 201806L
-// # define __cpp_lib_constexpr_complex 201711L
+# define __cpp_lib_constexpr_complex 201711L
# define __cpp_lib_constexpr_dynamic_alloc 201907L
# define __cpp_lib_constexpr_functional 201907L
# define __cpp_lib_constexpr_iterator 201811L
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.compile.pass.cpp
index 527805f7c36b7..1ee022b94cc56 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.compile.pass.cpp
@@ -68,17 +68,11 @@
# error "__cpp_lib_complex_udls should have the value 201309L in c++20"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_constexpr_complex
-# error "__cpp_lib_constexpr_complex should be defined in c++20"
-# endif
-# if __cpp_lib_constexpr_complex != 201711L
-# error "__cpp_lib_constexpr_complex should have the value 201711L in c++20"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_constexpr_complex
-# error "__cpp_lib_constexpr_complex should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_constexpr_complex
+# error "__cpp_lib_constexpr_complex should be defined in c++20"
+# endif
+# if __cpp_lib_constexpr_complex != 201711L
+# error "__cpp_lib_constexpr_complex should have the value 201711L in c++20"
# endif
#elif TEST_STD_VER > 20
@@ -90,17 +84,11 @@
# error "__cpp_lib_complex_udls should have the value 201309L in c++2b"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_constexpr_complex
-# error "__cpp_lib_constexpr_complex should be defined in c++2b"
-# endif
-# if __cpp_lib_constexpr_complex != 201711L
-# error "__cpp_lib_constexpr_complex should have the value 201711L in c++2b"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_constexpr_complex
-# error "__cpp_lib_constexpr_complex should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_constexpr_complex
+# error "__cpp_lib_constexpr_complex should be defined in c++2b"
+# endif
+# if __cpp_lib_constexpr_complex != 201711L
+# error "__cpp_lib_constexpr_complex should have the value 201711L in c++2b"
# endif
#endif // TEST_STD_VER > 20
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 9026cd120bbd3..9af0226b0e5e4 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -2705,17 +2705,11 @@
# error "__cpp_lib_constexpr_cmath should not be defined before c++2b"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_constexpr_complex
-# error "__cpp_lib_constexpr_complex should be defined in c++20"
-# endif
-# if __cpp_lib_constexpr_complex != 201711L
-# error "__cpp_lib_constexpr_complex should have the value 201711L in c++20"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_constexpr_complex
-# error "__cpp_lib_constexpr_complex should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_constexpr_complex
+# error "__cpp_lib_constexpr_complex should be defined in c++20"
+# endif
+# if __cpp_lib_constexpr_complex != 201711L
+# error "__cpp_lib_constexpr_complex should have the value 201711L in c++20"
# endif
# ifndef __cpp_lib_constexpr_dynamic_alloc
@@ -3931,17 +3925,11 @@
# endif
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_constexpr_complex
-# error "__cpp_lib_constexpr_complex should be defined in c++2b"
-# endif
-# if __cpp_lib_constexpr_complex != 201711L
-# error "__cpp_lib_constexpr_complex should have the value 201711L in c++2b"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_constexpr_complex
-# error "__cpp_lib_constexpr_complex should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_constexpr_complex
+# error "__cpp_lib_constexpr_complex should be defined in c++2b"
+# endif
+# if __cpp_lib_constexpr_complex != 201711L
+# error "__cpp_lib_constexpr_complex should have the value 201711L in c++2b"
# endif
# ifndef __cpp_lib_constexpr_dynamic_alloc
diff --git a/libcxx/test/std/numerics/complex.number/cases.h b/libcxx/test/std/numerics/complex.number/cases.h
index ccab643879cd2..b360e1423ff57 100644
--- a/libcxx/test/std/numerics/complex.number/cases.h
+++ b/libcxx/test/std/numerics/complex.number/cases.h
@@ -13,10 +13,13 @@
#ifndef CASES_H
#define CASES_H
-#include <complex>
#include <cassert>
+#include <complex>
+#include <type_traits>
+
+#include "test_macros.h"
-const std::complex<double> testcases[] =
+TEST_CONSTEXPR_CXX20 const std::complex<double> testcases[] =
{
std::complex<double>( 1.e-6, 1.e-6),
std::complex<double>(-1.e-6, 1.e-6),
@@ -56,32 +59,32 @@ const std::complex<double> testcases[] =
std::complex<double>( 1.e+6, 0),
std::complex<double>(-1.e+6, 0),
- std::complex<double>(NAN, NAN),
- std::complex<double>(-INFINITY, NAN),
- std::complex<double>(-2, NAN),
- std::complex<double>(-1, NAN),
- std::complex<double>(-0.5, NAN),
- std::complex<double>(-0., NAN),
- std::complex<double>(+0., NAN),
- std::complex<double>(0.5, NAN),
- std::complex<double>(1, NAN),
- std::complex<double>(2, NAN),
- std::complex<double>(INFINITY, NAN),
-
- std::complex<double>(NAN, -INFINITY),
- std::complex<double>(-INFINITY, -INFINITY),
- std::complex<double>(-2, -INFINITY),
- std::complex<double>(-1, -INFINITY),
- std::complex<double>(-0.5, -INFINITY),
- std::complex<double>(-0., -INFINITY),
- std::complex<double>(+0., -INFINITY),
- std::complex<double>(0.5, -INFINITY),
- std::complex<double>(1, -INFINITY),
- std::complex<double>(2, -INFINITY),
- std::complex<double>(INFINITY, -INFINITY),
-
- std::complex<double>(NAN, -2),
- std::complex<double>(-INFINITY, -2),
+ 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),
@@ -90,10 +93,10 @@ const std::complex<double> testcases[] =
std::complex<double>(0.5, -2),
std::complex<double>(1, -2),
std::complex<double>(2, -2),
- std::complex<double>(INFINITY, -2),
+ std::complex<double>(std::numeric_limits<double>::infinity(), -2),
- std::complex<double>(NAN, -1),
- std::complex<double>(-INFINITY, -1),
+ 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),
@@ -102,10 +105,10 @@ const std::complex<double> testcases[] =
std::complex<double>(0.5, -1),
std::complex<double>(1, -1),
std::complex<double>(2, -1),
- std::complex<double>(INFINITY, -1),
+ std::complex<double>(std::numeric_limits<double>::infinity(), -1),
- std::complex<double>(NAN, -0.5),
- std::complex<double>(-INFINITY, -0.5),
+ 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),
@@ -114,10 +117,10 @@ const std::complex<double> testcases[] =
std::complex<double>(0.5, -0.5),
std::complex<double>(1, -0.5),
std::complex<double>(2, -0.5),
- std::complex<double>(INFINITY, -0.5),
+ std::complex<double>(std::numeric_limits<double>::infinity(), -0.5),
- std::complex<double>(NAN, -0.),
- std::complex<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.),
@@ -126,10 +129,10 @@ const std::complex<double> testcases[] =
std::complex<double>(0.5, -0.),
std::complex<double>(1, -0.),
std::complex<double>(2, -0.),
- std::complex<double>(INFINITY, -0.),
+ std::complex<double>(std::numeric_limits<double>::infinity(), -0.),
- std::complex<double>(NAN, +0.),
- std::complex<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.),
@@ -138,10 +141,10 @@ const std::complex<double> testcases[] =
std::complex<double>(0.5, +0.),
std::complex<double>(1, +0.),
std::complex<double>(2, +0.),
- std::complex<double>(INFINITY, +0.),
+ std::complex<double>(std::numeric_limits<double>::infinity(), +0.),
- std::complex<double>(NAN, 0.5),
- std::complex<double>(-INFINITY, 0.5),
+ 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),
@@ -150,10 +153,10 @@ const std::complex<double> testcases[] =
std::complex<double>(0.5, 0.5),
std::complex<double>(1, 0.5),
std::complex<double>(2, 0.5),
- std::complex<double>(INFINITY, 0.5),
+ std::complex<double>(std::numeric_limits<double>::infinity(), 0.5),
- std::complex<double>(NAN, 1),
- std::complex<double>(-INFINITY, 1),
+ 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),
@@ -162,10 +165,10 @@ const std::complex<double> testcases[] =
std::complex<double>(0.5, 1),
std::complex<double>(1, 1),
std::complex<double>(2, 1),
- std::complex<double>(INFINITY, 1),
+ std::complex<double>(std::numeric_limits<double>::infinity(), 1),
- std::complex<double>(NAN, 2),
- std::complex<double>(-INFINITY, 2),
+ 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),
@@ -174,40 +177,51 @@ const std::complex<double> testcases[] =
std::complex<double>(0.5, 2),
std::complex<double>(1, 2),
std::complex<double>(2, 2),
- std::complex<double>(INFINITY, 2),
-
- std::complex<double>(NAN, INFINITY),
- std::complex<double>(-INFINITY, INFINITY),
- std::complex<double>(-2, INFINITY),
- std::complex<double>(-1, INFINITY),
- std::complex<double>(-0.5, INFINITY),
- std::complex<double>(-0., INFINITY),
- std::complex<double>(+0., INFINITY),
- std::complex<double>(0.5, INFINITY),
- std::complex<double>(1, INFINITY),
- std::complex<double>(2, INFINITY),
- std::complex<double>(INFINITY, INFINITY)
+ 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())
};
enum {zero, non_zero, 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) {
+ return v == std::numeric_limits<T>::infinity() || v == -std::numeric_limits<T>::infinity();
+}
+
+template <class T, typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0>
+TEST_CONSTEXPR_CXX20 bool test_isnan(T v) {
+ return v != v;
+}
+
template <class T>
+TEST_CONSTEXPR_CXX20
int
classify(const std::complex<T>& x)
{
if (x == std::complex<T>())
return zero;
- if (std::isinf(x.real()) || std::isinf(x.imag()))
+ if (test_isinf(x.real()) || test_isinf(x.imag()))
return inf;
- if (std::isnan(x.real()) && std::isnan(x.imag()))
+ if (test_isnan(x.real()) && test_isnan(x.imag()))
return NaN;
- if (std::isnan(x.real()))
+ if (test_isnan(x.real()))
{
if (x.imag() == T(0))
return NaN;
return non_zero_nan;
}
- if (std::isnan(x.imag()))
+ if (test_isnan(x.imag()))
{
if (x.real() == T(0))
return NaN;
diff --git a/libcxx/test/std/numerics/complex.number/cmplx.over/conj.pass.cpp b/libcxx/test/std/numerics/complex.number/cmplx.over/conj.pass.cpp
index 3367620aaf3be..553ead653bbf5 100644
--- a/libcxx/test/std/numerics/complex.number/cmplx.over/conj.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/cmplx.over/conj.pass.cpp
@@ -8,11 +8,11 @@
// <complex>
-// template<class T> complex<T> conj(const complex<T>&);
-// complex<long double> conj(long double);
-// complex<double> conj(double);
-// template<Integral T> complex<double> conj(T);
-// complex<float> conj(float);
+// template<class T> complex<T> conj(const complex<T>&); // constexpr in C++20
+// complex<long double> conj(long double); // constexpr in C++20
+// complex<double> conj(double); // constexpr in C++20
+// template<Integral T> complex<double> conj(T); // constexpr in C++20
+// complex<float> conj(float); // constexpr in C++20
#include <complex>
#include <type_traits>
@@ -22,6 +22,7 @@
#include "../cases.h"
template <class T>
+TEST_CONSTEXPR_CXX20
void
test(T x, typename std::enable_if<std::is_integral<T>::value>::type* = 0)
{
@@ -30,6 +31,7 @@ test(T x, typename std::enable_if<std::is_integral<T>::value>::type* = 0)
}
template <class T>
+TEST_CONSTEXPR_CXX20
void
test(T x, typename std::enable_if<std::is_floating_point<T>::value>::type* = 0)
{
@@ -38,6 +40,7 @@ test(T x, typename std::enable_if<std::is_floating_point<T>::value>::type* = 0)
}
template <class T>
+TEST_CONSTEXPR_CXX20
void
test(T x, typename std::enable_if<!std::is_integral<T>::value &&
!std::is_floating_point<T>::value>::type* = 0)
@@ -47,12 +50,14 @@ test(T x, typename std::enable_if<!std::is_integral<T>::value &&
}
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
test<T>(0);
test<T>(1);
test<T>(10);
+ return true;
}
int main(int, char**)
@@ -64,5 +69,14 @@ int main(int, char**)
test<unsigned>();
test<long long>();
- return 0;
+#if TEST_STD_VER >= 20
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+ static_assert(test<int>());
+ static_assert(test<unsigned>());
+ static_assert(test<long long>());
+#endif
+
+ return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/cmplx.over/norm.pass.cpp b/libcxx/test/std/numerics/complex.number/cmplx.over/norm.pass.cpp
index 8dc6daa93fc5f..c56123a78e27f 100644
--- a/libcxx/test/std/numerics/complex.number/cmplx.over/norm.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/cmplx.over/norm.pass.cpp
@@ -10,7 +10,7 @@
// template<Arithmetic T>
// T
-// norm(T x);
+// norm(T x); // constexpr in C++20
#include <complex>
#include <type_traits>
@@ -20,6 +20,7 @@
#include "../cases.h"
template <class T>
+TEST_CONSTEXPR_CXX20
void
test(T x, typename std::enable_if<std::is_integral<T>::value>::type* = 0)
{
@@ -28,6 +29,7 @@ test(T x, typename std::enable_if<std::is_integral<T>::value>::type* = 0)
}
template <class T>
+TEST_CONSTEXPR_CXX20
void
test(T x, typename std::enable_if<!std::is_integral<T>::value>::type* = 0)
{
@@ -36,12 +38,14 @@ test(T x, typename std::enable_if<!std::is_integral<T>::value>::type* = 0)
}
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
test<T>(0);
test<T>(1);
test<T>(10);
+ return true;
}
int main(int, char**)
@@ -53,5 +57,14 @@ int main(int, char**)
test<unsigned>();
test<long long>();
- return 0;
+#if TEST_STD_VER >= 20
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+ static_assert(test<int>());
+ static_assert(test<unsigned>());
+ static_assert(test<long long>());
+#endif
+
+ return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_complex.pass.cpp
index e6522c0628cbf..1d0e868e789a8 100644
--- a/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_complex.pass.cpp
@@ -9,7 +9,7 @@
// <complex>
// complex& operator=(const complex&);
-// template<class X> complex& operator= (const complex<X>&);
+// template<class X> complex& operator= (const complex<X>&); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -17,7 +17,8 @@
#include "test_macros.h"
template <class T, class X>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
std::complex<T> c;
@@ -31,6 +32,7 @@ test()
c = c3;
assert(c.real() == 3.5);
assert(c.imag() == -4.5);
+ return true;
}
int main(int, char**)
@@ -47,5 +49,19 @@ int main(int, char**)
test<long double, double>();
test<long double, long double>();
+#if TEST_STD_VER >= 20
+ static_assert(test<float, float>());
+ static_assert(test<float, double>());
+ static_assert(test<float, long double>());
+
+ static_assert(test<double, float>());
+ static_assert(test<double, double>());
+ static_assert(test<double, long double>());
+
+ static_assert(test<long double, float>());
+ static_assert(test<long double, double>());
+ static_assert(test<long double, long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_scalar.pass.cpp
index 176c3c7591c3d..6a8c73948e33c 100644
--- a/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_scalar.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_scalar.pass.cpp
@@ -8,7 +8,7 @@
// <complex>
-// complex& operator= (const T&);
+// complex& operator= (const T&); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -16,7 +16,8 @@
#include "test_macros.h"
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
std::complex<T> c;
@@ -28,6 +29,7 @@ test()
c = -1.5;
assert(c.real() == -1.5);
assert(c.imag() == 0);
+ return true;
}
int main(int, char**)
@@ -36,5 +38,11 @@ int main(int, char**)
test<double>();
test<long double>();
+#if TEST_STD_VER >= 20
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp
index 989177b25bff9..af2561e4cb9e9 100644
--- a/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp
@@ -8,7 +8,7 @@
// <complex>
-// complex& operator/=(const complex& rhs);
+// complex& operator/=(const complex& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -16,7 +16,8 @@
#include "test_macros.h"
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
std::complex<T> c(-4, 7.5);
@@ -35,15 +36,15 @@ test()
c3 = c;
std::complex<int> ic (1,1);
c3 /= ic;
- assert(c3.real() == 0.5);
+ assert(c3.real() == 0.5);
assert(c3.imag() == -0.5);
c3 = c;
std::complex<float> fc (1,1);
c3 /= fc;
- assert(c3.real() == 0.5);
+ assert(c3.real() == 0.5);
assert(c3.imag() == -0.5);
-
+ return true;
}
int main(int, char**)
@@ -52,5 +53,11 @@ int main(int, char**)
test<double>();
test<long double>();
- return 0;
+#if TEST_STD_VER >= 20
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
+ return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_scalar.pass.cpp
index 100cd34f1064c..9251fb4f1bfeb 100644
--- a/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_scalar.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_scalar.pass.cpp
@@ -8,7 +8,7 @@
// <complex>
-// complex& operator/=(const T& rhs);
+// complex& operator/=(const T& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -16,7 +16,8 @@
#include "test_macros.h"
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
std::complex<T> c(1);
@@ -35,6 +36,7 @@ test()
c /= 0.5;
assert(c.real() == -16);
assert(c.imag() == 4);
+ return true;
}
int main(int, char**)
@@ -43,5 +45,11 @@ int main(int, char**)
test<double>();
test<long double>();
+#if TEST_STD_VER >= 20
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_complex.pass.cpp
index b47793d09f0a5..c801a700e05ae 100644
--- a/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_complex.pass.cpp
@@ -8,7 +8,7 @@
// <complex>
-// complex& operator-=(const complex& rhs);
+// complex& operator-=(const complex& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -16,7 +16,8 @@
#include "test_macros.h"
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
std::complex<T> c;
@@ -43,6 +44,7 @@ test()
c3 -= fc;
assert(c3.real() == -4);
assert(c3.imag() == -6);
+ return true;
}
int main(int, char**)
@@ -51,5 +53,11 @@ int main(int, char**)
test<double>();
test<long double>();
- return 0;
+#if TEST_STD_VER >= 20
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
+ return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_scalar.pass.cpp
index 6fccd8bcb9fe5..b9b240cefea74 100644
--- a/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_scalar.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_scalar.pass.cpp
@@ -8,7 +8,7 @@
// <complex>
-// complex& operator-=(const T& rhs);
+// complex& operator-=(const T& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -16,7 +16,8 @@
#include "test_macros.h"
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
std::complex<T> c;
@@ -31,6 +32,7 @@ test()
c -= -1.5;
assert(c.real() == -1.5);
assert(c.imag() == 0);
+ return true;
}
int main(int, char**)
@@ -39,5 +41,11 @@ int main(int, char**)
test<double>();
test<long double>();
+#if TEST_STD_VER >= 20
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_complex.pass.cpp
index 43357a80d6234..6ceb56b66ea2c 100644
--- a/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_complex.pass.cpp
@@ -8,7 +8,7 @@
// <complex>
-// complex& operator+=(const complex& rhs);
+// complex& operator+=(const complex& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -16,7 +16,8 @@
#include "test_macros.h"
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
std::complex<T> c;
@@ -43,6 +44,7 @@ test()
c3 += fc;
assert(c3.real() == 4);
assert(c3.imag() == 6);
+ return true;
}
int main(int, char**)
@@ -51,5 +53,11 @@ int main(int, char**)
test<double>();
test<long double>();
- return 0;
+#if TEST_STD_VER >= 20
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
+ return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_scalar.pass.cpp
index 78bf371eeb28d..fab151d0946da 100644
--- a/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_scalar.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_scalar.pass.cpp
@@ -8,7 +8,7 @@
// <complex>
-// complex& operator+=(const T& rhs);
+// complex& operator+=(const T& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -16,7 +16,8 @@
#include "test_macros.h"
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
std::complex<T> c;
@@ -31,6 +32,7 @@ test()
c += -1.5;
assert(c.real() == 1.5);
assert(c.imag() == 0);
+ return true;
}
int main(int, char**)
@@ -39,5 +41,11 @@ int main(int, char**)
test<double>();
test<long double>();
+#if TEST_STD_VER >= 20
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_complex.pass.cpp
index aabe9229cb52a..65492857db55e 100644
--- a/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_complex.pass.cpp
@@ -8,7 +8,7 @@
// <complex>
-// complex& operator*=(const complex& rhs);
+// complex& operator*=(const complex& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -16,7 +16,8 @@
#include "test_macros.h"
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
std::complex<T> c(1);
@@ -36,13 +37,14 @@ test()
std::complex<int> ic (1,1);
c3 *= ic;
assert(c3.real() == -11.5);
- assert(c3.imag() == 3.5);
+ assert(c3.imag() == 3.5);
c3 = c;
std::complex<float> fc (1,1);
c3 *= fc;
assert(c3.real() == -11.5);
- assert(c3.imag() == 3.5);
+ assert(c3.imag() == 3.5);
+ return true;
}
int main(int, char**)
@@ -51,5 +53,11 @@ int main(int, char**)
test<double>();
test<long double>();
- return 0;
+#if TEST_STD_VER >= 20
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
+ return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_scalar.pass.cpp
index 600c79f8d2100..56606248a07d6 100644
--- a/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_scalar.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_scalar.pass.cpp
@@ -8,7 +8,7 @@
// <complex>
-// complex& operator*=(const T& rhs);
+// complex& operator*=(const T& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -16,7 +16,8 @@
#include "test_macros.h"
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
std::complex<T> c(1);
@@ -35,6 +36,7 @@ test()
c *= 1.5;
assert(c.real() == -5.0625);
assert(c.imag() == 3);
+ return true;
}
int main(int, char**)
@@ -43,5 +45,11 @@ int main(int, char**)
test<double>();
test<long double>();
+#if TEST_STD_VER >= 20
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.members/real_imag.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.members/real_imag.pass.cpp
index c4a1ef9353982..26db8ddf3b4ca 100644
--- a/libcxx/test/std/numerics/complex.number/complex.members/real_imag.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.members/real_imag.pass.cpp
@@ -8,8 +8,8 @@
// <complex>
-// void real(T val);
-// void imag(T val);
+// void real(T val); // constexpr in C++20
+// void imag(T val); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -17,6 +17,7 @@
#include "test_macros.h"
template <class T>
+TEST_CONSTEXPR_CXX20
void
test_constexpr()
{
@@ -34,7 +35,8 @@ test_constexpr()
}
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
std::complex<T> c;
@@ -53,15 +55,21 @@ test()
assert(c.real() == -4.5);
assert(c.imag() == -5.5);
- test_constexpr<T> ();
+ test_constexpr<T>();
+ return true;
}
-int main(int, char**)
-{
+int main(int, char**) {
test<float>();
test<double>();
test<long double>();
- test_constexpr<int> ();
+ test_constexpr<int>();
+
+#if TEST_STD_VER >= 20
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
return 0;
}
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 363b0189ed1cd..7119710a95557 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
@@ -10,7 +10,9 @@
// template<class T>
// complex<T>
-// operator/(const complex<T>& lhs, const complex<T>& rhs);
+// operator/(const complex<T>& lhs, const complex<T>& rhs); // constexpr in C++20
+
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=5000000
#include <complex>
#include <cassert>
@@ -19,135 +21,128 @@
#include "../cases.h"
template <class T>
-void
-test(const std::complex<T>& lhs, const std::complex<T>& rhs, std::complex<T> x)
-{
- assert(lhs / rhs == x);
-}
-
-template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
- std::complex<T> lhs(-4.0, 7.5);
- std::complex<T> rhs(1.5, 2.5);
- std::complex<T> x(1.5, 2.5);
- test(lhs, rhs, x);
+ const std::complex<T> lhs(-4.0, 7.5);
+ const std::complex<T> rhs(1.5, 2.5);
+ assert(lhs / rhs == std::complex<T>(1.5, 2.5));
+ return true;
}
-void test_edges()
+TEST_CONSTEXPR_CXX20
+bool
+test_edges()
{
- const unsigned N = sizeof(testcases) / sizeof(testcases[0]);
- for (unsigned i = 0; i < N; ++i)
- {
- for (unsigned j = 0; j < N; ++j)
- {
- std::complex<double> r = testcases[i] / testcases[j];
- switch (classify(testcases[i]))
- {
- case zero:
- switch (classify(testcases[j]))
- {
- case zero:
- assert(classify(r) == NaN);
- break;
- case non_zero:
- assert(classify(r) == zero);
- break;
- case inf:
- assert(classify(r) == zero);
- break;
- case NaN:
- assert(classify(r) == NaN);
- break;
- case non_zero_nan:
- assert(classify(r) == NaN);
- break;
- }
- break;
- case non_zero:
- switch (classify(testcases[j]))
- {
- case zero:
- assert(classify(r) == inf);
- break;
- case non_zero:
- assert(classify(r) == non_zero);
- break;
- case inf:
- assert(classify(r) == zero);
- break;
- case NaN:
- assert(classify(r) == NaN);
- break;
- case non_zero_nan:
- assert(classify(r) == NaN);
- break;
- }
- break;
- case inf:
- switch (classify(testcases[j]))
- {
- case zero:
- assert(classify(r) == inf);
- break;
- case non_zero:
- assert(classify(r) == inf);
- break;
- case inf:
- assert(classify(r) == NaN);
- break;
- case NaN:
- assert(classify(r) == NaN);
- break;
- case non_zero_nan:
- assert(classify(r) == NaN);
- break;
- }
- break;
- case NaN:
- switch (classify(testcases[j]))
- {
- case zero:
- assert(classify(r) == NaN);
- break;
- case non_zero:
- assert(classify(r) == NaN);
- break;
- case inf:
- assert(classify(r) == NaN);
- break;
- case NaN:
- assert(classify(r) == NaN);
- break;
- case non_zero_nan:
- assert(classify(r) == NaN);
- break;
- }
- break;
- case non_zero_nan:
- switch (classify(testcases[j]))
- {
- case zero:
- assert(classify(r) == inf);
- break;
- case non_zero:
- assert(classify(r) == NaN);
- break;
- case inf:
- assert(classify(r) == NaN);
- break;
- case NaN:
- assert(classify(r) == NaN);
- break;
- case non_zero_nan:
- assert(classify(r) == NaN);
- break;
- }
- break;
- }
+ const unsigned N = sizeof(testcases) / sizeof(testcases[0]);
+ int classification[N];
+ for (unsigned i=0; i < N; ++i)
+ classification[i] = classify(testcases[i]);
+
+ for (unsigned i = 0; i < N; ++i) {
+ for (unsigned j = 0; j < N; ++j) {
+ std::complex<double> r = testcases[i] / testcases[j];
+ switch (classification[i]) {
+ case zero:
+ switch (classification[j]) {
+ case zero:
+ assert(classify(r) == NaN);
+ break;
+ case non_zero:
+ assert(classify(r) == zero);
+ break;
+ case inf:
+ assert(classify(r) == zero);
+ break;
+ case NaN:
+ assert(classify(r) == NaN);
+ break;
+ case non_zero_nan:
+ assert(classify(r) == NaN);
+ break;
}
+ break;
+ case non_zero:
+ switch (classification[j]) {
+ case zero:
+ assert(classify(r) == inf);
+ break;
+ case non_zero:
+ assert(classify(r) == non_zero);
+ break;
+ case inf:
+ assert(classify(r) == zero);
+ break;
+ case NaN:
+ assert(classify(r) == NaN);
+ break;
+ case non_zero_nan:
+ assert(classify(r) == NaN);
+ break;
+ }
+ break;
+ case inf:
+ switch (classification[j]) {
+ case zero:
+ assert(classify(r) == inf);
+ break;
+ case non_zero:
+ assert(classify(r) == inf);
+ break;
+ case inf:
+ assert(classify(r) == NaN);
+ break;
+ case NaN:
+ assert(classify(r) == NaN);
+ break;
+ case non_zero_nan:
+ assert(classify(r) == NaN);
+ break;
+ }
+ break;
+ case NaN:
+ switch (classification[j]) {
+ case zero:
+ assert(classify(r) == NaN);
+ break;
+ case non_zero:
+ assert(classify(r) == NaN);
+ break;
+ case inf:
+ assert(classify(r) == NaN);
+ break;
+ case NaN:
+ assert(classify(r) == NaN);
+ break;
+ case non_zero_nan:
+ assert(classify(r) == NaN);
+ break;
+ }
+ break;
+ case non_zero_nan:
+ switch (classification[j]) {
+ case zero:
+ assert(classify(r) == inf);
+ break;
+ case non_zero:
+ assert(classify(r) == NaN);
+ break;
+ case inf:
+ assert(classify(r) == NaN);
+ break;
+ case NaN:
+ assert(classify(r) == NaN);
+ break;
+ case non_zero_nan:
+ assert(classify(r) == NaN);
+ break;
+ }
+ break;
+ }
}
+ }
+ return true;
}
int main(int, char**)
@@ -157,5 +152,12 @@ int main(int, char**)
test<long double>();
test_edges();
- return 0;
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+ static_assert(test_edges());
+#endif
+
+ return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_scalar.pass.cpp
index 24a0e8cb61a38..b7fc9a9a0f10a 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_scalar.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_scalar.pass.cpp
@@ -10,7 +10,7 @@
// template<class T>
// complex<T>
-// operator/(const complex<T>& lhs, const T& rhs);
+// operator/(const complex<T>& lhs, const T& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -18,20 +18,14 @@
#include "test_macros.h"
template <class T>
-void
-test(const std::complex<T>& lhs, const T& rhs, std::complex<T> x)
-{
- assert(lhs / rhs == x);
-}
-
-template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
- std::complex<T> lhs(-4.0, 7.5);
- T rhs(2);
- std::complex<T> x(-2, 3.75);
- test(lhs, rhs, x);
+ const std::complex<T> lhs(-4.0, 7.5);
+ const T rhs(2);
+ assert(lhs / rhs == std::complex<T>(-2, 3.75));
+ return true;
}
int main(int, char**)
@@ -40,5 +34,11 @@ int main(int, char**)
test<double>();
test<long double>();
- return 0;
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
+ return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_complex.pass.cpp
index 27621f165cf8a..bf18a8422d1a8 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_complex.pass.cpp
@@ -18,25 +18,8 @@
#include "test_macros.h"
template <class T>
-void
-test_constexpr()
-{
-#if TEST_STD_VER > 11
- {
- constexpr std::complex<T> lhs(1.5, 2.5);
- constexpr std::complex<T> rhs(1.5, -2.5);
- static_assert( !(lhs == rhs), "");
- }
- {
- constexpr std::complex<T> lhs(1.5, 2.5);
- constexpr std::complex<T> rhs(1.5, 2.5);
- static_assert(lhs == rhs, "");
- }
-#endif
-}
-
-template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
{
@@ -49,7 +32,7 @@ test()
std::complex<T> rhs(1.5, 2.5);
assert(lhs == rhs);
}
- test_constexpr<T> ();
+ return true;
}
int main(int, char**)
@@ -57,7 +40,11 @@ int main(int, char**)
test<float>();
test<double>();
test<long double>();
-// test_constexpr<int> ();
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_scalar.pass.cpp
index 1ec74e703f117..151a356d7930a 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_scalar.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_scalar.pass.cpp
@@ -18,6 +18,7 @@
#include "test_macros.h"
template <class T>
+TEST_CONSTEXPR_CXX20
void
test_constexpr()
{
@@ -46,7 +47,8 @@ test_constexpr()
}
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
{
@@ -71,14 +73,20 @@ test()
}
test_constexpr<T> ();
- }
+ return true;
+}
int main(int, char**)
{
test<float>();
test<double>();
test<long double>();
-// test_constexpr<int> ();
+
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_complex.pass.cpp
index f96cc47a470fb..d61f6e8f1fee3 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_complex.pass.cpp
@@ -10,7 +10,7 @@
// template<class T>
// complex<T>
-// operator-(const complex<T>& lhs, const complex<T>& rhs);
+// operator-(const complex<T>& lhs, const complex<T>& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -18,28 +18,21 @@
#include "test_macros.h"
template <class T>
-void
-test(const std::complex<T>& lhs, const std::complex<T>& rhs, std::complex<T> x)
-{
- assert(lhs - rhs == x);
-}
-
-template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
{
- std::complex<T> lhs(1.5, 2.5);
- std::complex<T> rhs(3.5, 4.5);
- std::complex<T> x(-2.0, -2.0);
- test(lhs, rhs, x);
+ const std::complex<T> lhs(1.5, 2.5);
+ const std::complex<T> rhs(3.5, 4.5);
+ assert(lhs - rhs == std::complex<T>(-2.0, -2.0));
}
{
- std::complex<T> lhs(1.5, -2.5);
- std::complex<T> rhs(-3.5, 4.5);
- std::complex<T> x(5.0, -7.0);
- test(lhs, rhs, x);
+ const std::complex<T> lhs(1.5, -2.5);
+ const std::complex<T> rhs(-3.5, 4.5);
+ assert(lhs - rhs == std::complex<T>(5.0, -7.0));
}
+ return true;
}
int main(int, char**)
@@ -48,5 +41,11 @@ int main(int, char**)
test<double>();
test<long double>();
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_scalar.pass.cpp
index 3002085968517..8d4ecffa41baf 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_scalar.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_scalar.pass.cpp
@@ -10,7 +10,7 @@
// template<class T>
// complex<T>
-// operator-(const complex<T>& lhs, const T& rhs);
+// operator-(const complex<T>& lhs, const T& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -18,28 +18,21 @@
#include "test_macros.h"
template <class T>
-void
-test(const std::complex<T>& lhs, const T& rhs, std::complex<T> x)
-{
- assert(lhs - rhs == x);
-}
-
-template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
{
- std::complex<T> lhs(1.5, 2.5);
- T rhs(3.5);
- std::complex<T> x(-2.0, 2.5);
- test(lhs, rhs, x);
+ const std::complex<T> lhs(1.5, 2.5);
+ const T rhs(3.5);
+ assert(lhs - rhs == std::complex<T>(-2.0, 2.5));
}
{
- std::complex<T> lhs(1.5, -2.5);
- T rhs(-3.5);
- std::complex<T> x(5.0, -2.5);
- test(lhs, rhs, x);
+ const std::complex<T> lhs(1.5, -2.5);
+ const T rhs(-3.5);
+ assert(lhs - rhs == std::complex<T>(5.0, -2.5));
}
+ return true;
}
int main(int, char**)
@@ -48,5 +41,11 @@ int main(int, char**)
test<double>();
test<long double>();
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_complex.pass.cpp
index 319e453a900a4..81adc690dc26e 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_complex.pass.cpp
@@ -18,6 +18,7 @@
#include "test_macros.h"
template <class T>
+TEST_CONSTEXPR_CXX20
void
test_constexpr()
{
@@ -35,31 +36,37 @@ test_constexpr()
#endif
}
-
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
{
- std::complex<T> lhs(1.5, 2.5);
- std::complex<T> rhs(1.5, -2.5);
+ const std::complex<T> lhs(1.5, 2.5);
+ const std::complex<T> rhs(1.5, -2.5);
assert(lhs != rhs);
}
{
- std::complex<T> lhs(1.5, 2.5);
- std::complex<T> rhs(1.5, 2.5);
+ const std::complex<T> lhs(1.5, 2.5);
+ const std::complex<T> rhs(1.5, 2.5);
assert(!(lhs != rhs));
}
test_constexpr<T> ();
- }
+ return true;
+}
int main(int, char**)
{
test<float>();
test<double>();
test<long double>();
-// test_constexpr<int> ();
+
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_scalar.pass.cpp
index 35074e5772dcb..702900b381433 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_scalar.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_scalar.pass.cpp
@@ -18,6 +18,7 @@
#include "test_macros.h"
template <class T>
+TEST_CONSTEXPR_CXX20
void
test_constexpr()
{
@@ -46,7 +47,8 @@ test_constexpr()
}
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
{
@@ -71,6 +73,7 @@ test()
}
test_constexpr<T> ();
+ return true;
}
int main(int, char**)
@@ -78,7 +81,12 @@ int main(int, char**)
test<float>();
test<double>();
test<long double>();
-// test_constexpr<int> ();
+
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_complex.pass.cpp
index 963b026f26990..f9a22f6effbc4 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_complex.pass.cpp
@@ -10,7 +10,7 @@
// template<class T>
// complex<T>
-// operator+(const complex<T>& lhs, const complex<T>& rhs);
+// operator+(const complex<T>& lhs, const complex<T>& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -18,28 +18,22 @@
#include "test_macros.h"
template <class T>
-void
-test(const std::complex<T>& lhs, const std::complex<T>& rhs, std::complex<T> x)
-{
- assert(lhs + rhs == x);
-}
-
-template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
{
- std::complex<T> lhs(1.5, 2.5);
- std::complex<T> rhs(3.5, 4.5);
- std::complex<T> x(5.0, 7.0);
- test(lhs, rhs, x);
+ const std::complex<T> lhs(1.5, 2.5);
+ const std::complex<T> rhs(3.5, 4.5);
+ assert(lhs + rhs == std::complex<T>(5.0, 7.0));
}
{
- std::complex<T> lhs(1.5, -2.5);
- std::complex<T> rhs(-3.5, 4.5);
- std::complex<T> x(-2.0, 2.0);
- test(lhs, rhs, x);
+ const std::complex<T> lhs(1.5, -2.5);
+ const std::complex<T> rhs(-3.5, 4.5);
+ assert(lhs + rhs == std::complex<T>(-2.0, 2.0));
}
+
+ return true;
}
int main(int, char**)
@@ -48,5 +42,11 @@ int main(int, char**)
test<double>();
test<long double>();
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_scalar.pass.cpp
index f4d6b6b9ac569..e86ded70e4797 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_scalar.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_scalar.pass.cpp
@@ -10,7 +10,7 @@
// template<class T>
// complex<T>
-// operator+(const complex<T>& lhs, const T& rhs);
+// operator+(const complex<T>& lhs, const T& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -18,28 +18,22 @@
#include "test_macros.h"
template <class T>
-void
-test(const std::complex<T>& lhs, const T& rhs, std::complex<T> x)
-{
- assert(lhs + rhs == x);
-}
-
-template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
{
- std::complex<T> lhs(1.5, 2.5);
- T rhs(3.5);
- std::complex<T> x(5.0, 2.5);
- test(lhs, rhs, x);
+ const std::complex<T> lhs(1.5, 2.5);
+ const T rhs(3.5);
+ assert(lhs + rhs == std::complex<T>(5.0, 2.5));
}
{
- std::complex<T> lhs(1.5, -2.5);
- T rhs(-3.5);
- std::complex<T> x(-2.0, -2.5);
- test(lhs, rhs, x);
+ const std::complex<T> lhs(1.5, -2.5);
+ const T rhs(-3.5);
+ assert(lhs + rhs == std::complex<T>(-2.0, -2.5));
}
+
+ return true;
}
int main(int, char**)
@@ -48,5 +42,11 @@ int main(int, char**)
test<double>();
test<long double>();
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp
index bcf85a9aabb83..38ec71e3a00a5 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp
@@ -10,7 +10,9 @@
// template<class T>
// complex<T>
-// operator*(const complex<T>& lhs, const complex<T>& rhs);
+// operator*(const complex<T>& lhs, const complex<T>& rhs); // constexpr in C++20
+
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=5000000
#include <complex>
#include <cassert>
@@ -19,56 +21,48 @@
#include "../cases.h"
template <class T>
-void
-test(const std::complex<T>& lhs, const std::complex<T>& rhs, std::complex<T> x)
-{
- assert(lhs * rhs == x);
-}
-
-template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
- std::complex<T> lhs(1.5, 2.5);
- std::complex<T> rhs(1.5, 2.5);
- std::complex<T> x(-4.0, 7.5);
- test(lhs, rhs, x);
+ const std::complex<T> lhs(1.5, 2.5);
+ const std::complex<T> rhs(1.5, 2.5);
+ assert(lhs * rhs == std::complex<T>(-4.0, 7.5));
+ return true;
}
// test edges
-void test_edges()
+TEST_CONSTEXPR_CXX20 bool test_edges()
{
const unsigned N = sizeof(testcases) / sizeof(testcases[0]);
+ int classification[N];
+ for (unsigned i=0; i < N; ++i)
+ classification[i] = classify(testcases[i]);
+
for (unsigned i = 0; i < N; ++i)
{
for (unsigned j = 0; j < N; ++j)
{
std::complex<double> r = testcases[i] * testcases[j];
- switch (classify(testcases[i]))
+ switch (classification[i])
{
case zero:
- switch (classify(testcases[j]))
+ switch (classification[j])
{
case zero:
- assert(classify(r) == zero);
- break;
case non_zero:
assert(classify(r) == zero);
break;
case inf:
- assert(classify(r) == NaN);
- break;
case NaN:
- assert(classify(r) == NaN);
- break;
case non_zero_nan:
assert(classify(r) == NaN);
break;
}
break;
case non_zero:
- switch (classify(testcases[j]))
+ switch (classification[j])
{
case zero:
assert(classify(r) == zero);
@@ -80,68 +74,37 @@ void test_edges()
assert(classify(r) == inf);
break;
case NaN:
- assert(classify(r) == NaN);
- break;
case non_zero_nan:
assert(classify(r) == NaN);
break;
}
break;
case inf:
- switch (classify(testcases[j]))
+ switch (classification[j])
{
case zero:
+ case NaN:
assert(classify(r) == NaN);
break;
case non_zero:
- assert(classify(r) == inf);
- break;
case inf:
- assert(classify(r) == inf);
- break;
- case NaN:
- assert(classify(r) == NaN);
- break;
case non_zero_nan:
assert(classify(r) == inf);
break;
}
break;
case NaN:
- switch (classify(testcases[j]))
- {
- case zero:
- assert(classify(r) == NaN);
- break;
- case non_zero:
- assert(classify(r) == NaN);
- break;
- case inf:
- assert(classify(r) == NaN);
- break;
- case NaN:
- assert(classify(r) == NaN);
- break;
- case non_zero_nan:
- assert(classify(r) == NaN);
- break;
- }
+ assert(classify(r) == NaN);
break;
case non_zero_nan:
- switch (classify(testcases[j]))
+ switch (classification[j])
{
- case zero:
- assert(classify(r) == NaN);
- break;
- case non_zero:
- assert(classify(r) == NaN);
- break;
case inf:
assert(classify(r) == inf);
break;
+ case zero:
+ case non_zero:
case NaN:
- assert(classify(r) == NaN);
- break;
case non_zero_nan:
assert(classify(r) == NaN);
break;
@@ -150,6 +113,7 @@ void test_edges()
}
}
}
+ return true;
}
int main(int, char**)
@@ -159,5 +123,12 @@ int main(int, char**)
test<long double>();
test_edges();
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+ static_assert(test_edges());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_scalar.pass.cpp
index 897d2c290f2d7..19c0f22b63d0b 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_scalar.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_scalar.pass.cpp
@@ -10,7 +10,7 @@
// template<class T>
// complex<T>
-// operator*(const complex<T>& lhs, const T& rhs);
+// operator*(const complex<T>& lhs, const T& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -18,20 +18,14 @@
#include "test_macros.h"
template <class T>
-void
-test(const std::complex<T>& lhs, const T& rhs, std::complex<T> x)
-{
- assert(lhs * rhs == x);
-}
-
-template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
- std::complex<T> lhs(1.5, 2.5);
- T rhs(1.5);
- std::complex<T> x(2.25, 3.75);
- test(lhs, rhs, x);
+ const std::complex<T> lhs(1.5, 2.5);
+ const T rhs(1.5);
+ assert(lhs * rhs == std::complex<T>(2.25, 3.75));
+ return true;
}
int main(int, char**)
@@ -40,5 +34,11 @@ int main(int, char**)
test<double>();
test<long double>();
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp
index 2b72a1a78d07e..50981216cc5f0 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp
@@ -10,7 +10,7 @@
// template<class T>
// complex<T>
-// operator/(const T& lhs, const complex<T>& rhs);
+// operator/(const T& lhs, const complex<T>& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -18,20 +18,14 @@
#include "test_macros.h"
template <class T>
-void
-test(const T& lhs, const std::complex<T>& rhs, std::complex<T> x)
-{
- assert(lhs / rhs == x);
-}
-
-template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
- T lhs(-8.5);
- std::complex<T> rhs(1.5, 2.5);
- std::complex<T> x(-1.5, 2.5);
- test(lhs, rhs, x);
+ const T lhs(-8.5);
+ const std::complex<T> rhs(1.5, 2.5);
+ assert(lhs / rhs == std::complex<T>(-1.5, 2.5));
+ return true;
}
int main(int, char**)
@@ -40,5 +34,11 @@ int main(int, char**)
test<double>();
test<long double>();
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_equals_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_equals_complex.pass.cpp
index d5dcc29182de0..4fe46bb370041 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_equals_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_equals_complex.pass.cpp
@@ -18,6 +18,7 @@
#include "test_macros.h"
template <class T>
+TEST_CONSTEXPR_CXX20
void
test_constexpr()
{
@@ -46,7 +47,8 @@ test_constexpr()
}
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
{
@@ -71,6 +73,7 @@ test()
}
test_constexpr<T> ();
+ return true;
}
int main(int, char**)
@@ -78,7 +81,12 @@ int main(int, char**)
test<float>();
test<double>();
test<long double>();
-// test_constexpr<int>();
+
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_minus_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_minus_complex.pass.cpp
index 9cd9207c0323e..126782ccc18bd 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_minus_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_minus_complex.pass.cpp
@@ -10,7 +10,7 @@
// template<class T>
// complex<T>
-// operator-(const T& lhs, const complex<T>& rhs);
+// operator-(const T& lhs, const complex<T>& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -18,35 +18,33 @@
#include "test_macros.h"
template <class T>
-void
-test(const T& lhs, const std::complex<T>& rhs, std::complex<T> x)
-{
- assert(lhs - rhs == x);
-}
-
-template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
{
- T lhs(1.5);
- std::complex<T> rhs(3.5, 4.5);
- std::complex<T> x(-2.0, -4.5);
- test(lhs, rhs, x);
+ const T lhs(1.5);
+ const std::complex<T> rhs(3.5, 4.5);
+ assert(lhs - rhs == std::complex<T>(-2.0, -4.5));
}
{
- T lhs(1.5);
- std::complex<T> rhs(-3.5, 4.5);
- std::complex<T> x(5.0, -4.5);
- test(lhs, rhs, x);
+ const T lhs(1.5);
+ const std::complex<T> rhs(-3.5, 4.5);
+ assert(lhs - rhs == std::complex<T>(5.0, -4.5));
}
+ return true;
}
-int main(int, char**)
-{
+int main(int, char**) {
test<float>();
test<double>();
test<long double>();
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_not_equals_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_not_equals_complex.pass.cpp
index edff47a016069..f5be41fa4074c 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_not_equals_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_not_equals_complex.pass.cpp
@@ -18,6 +18,7 @@
#include "test_macros.h"
template <class T>
+TEST_CONSTEXPR_CXX20
void
test_constexpr()
{
@@ -46,7 +47,8 @@ test_constexpr()
}
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
{
@@ -71,14 +73,20 @@ test()
}
test_constexpr<T> ();
- }
+ return true;
+}
int main(int, char**)
{
test<float>();
test<double>();
test<long double>();
-// test_constexpr<int>();
+
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_plus_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_plus_complex.pass.cpp
index 6f8e0495b475c..a2fe82e42ff19 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_plus_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_plus_complex.pass.cpp
@@ -10,7 +10,7 @@
// template<class T>
// complex<T>
-// operator+(const T& lhs, const complex<T>& rhs);
+// operator+(const T& lhs, const complex<T>& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -18,28 +18,21 @@
#include "test_macros.h"
template <class T>
-void
-test(const T& lhs, const std::complex<T>& rhs, std::complex<T> x)
-{
- assert(lhs + rhs == x);
-}
-
-template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
{
- T lhs(1.5);
- std::complex<T> rhs(3.5, 4.5);
- std::complex<T> x(5.0, 4.5);
- test(lhs, rhs, x);
+ const T lhs(1.5);
+ const std::complex<T> rhs(3.5, 4.5);
+ assert(lhs + rhs == std::complex<T>(5.0, 4.5));
}
{
- T lhs(1.5);
- std::complex<T> rhs(-3.5, 4.5);
- std::complex<T> x(-2.0, 4.5);
- test(lhs, rhs, x);
+ const T lhs(1.5);
+ const std::complex<T> rhs(-3.5, 4.5);
+ assert(lhs + rhs == std::complex<T>(-2.0, 4.5));
}
+ return true;
}
int main(int, char**)
@@ -48,5 +41,11 @@ int main(int, char**)
test<double>();
test<long double>();
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_times_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_times_complex.pass.cpp
index 3ab8be29f88e6..4c523da67f50c 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_times_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_times_complex.pass.cpp
@@ -10,7 +10,7 @@
// template<class T>
// complex<T>
-// operator*(const T& lhs, const complex<T>& rhs);
+// operator*(const T& lhs, const complex<T>& rhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -18,20 +18,14 @@
#include "test_macros.h"
template <class T>
-void
-test(const T& lhs, const std::complex<T>& rhs, std::complex<T> x)
-{
- assert(lhs * rhs == x);
-}
-
-template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
- T lhs(1.5);
- std::complex<T> rhs(1.5, 2.5);
- std::complex<T> x(2.25, 3.75);
- test(lhs, rhs, x);
+ const T lhs(1.5);
+ const std::complex<T> rhs(1.5, 2.5);
+ assert(lhs * rhs == std::complex<T>(2.25, 3.75));
+ return true;
}
int main(int, char**)
@@ -40,5 +34,11 @@ int main(int, char**)
test<double>();
test<long double>();
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/unary_minus.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/unary_minus.pass.cpp
index a61218323a616..9310ac8f223bd 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/unary_minus.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/unary_minus.pass.cpp
@@ -10,7 +10,7 @@
// template<class T>
// complex<T>
-// operator-(const complex<T>& lhs);
+// operator-(const complex<T>& lhs); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -18,15 +18,13 @@
#include "test_macros.h"
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
- std::complex<T> z(1.5, 2.5);
- assert(z.real() == 1.5);
- assert(z.imag() == 2.5);
- std::complex<T> c = -z;
- assert(c.real() == -1.5);
- assert(c.imag() == -2.5);
+ assert(-std::complex<T>(1.5, -2.5) == std::complex<T>(-1.5, 2.5));
+ assert(-std::complex<T>(-1.5, 2.5) == std::complex<T>(1.5, -2.5));
+ return true;
}
int main(int, char**)
@@ -35,5 +33,11 @@ int main(int, char**)
test<double>();
test<long double>();
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/unary_plus.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/unary_plus.pass.cpp
index 4c693a581a492..cfd494b3c7dff 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/unary_plus.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/unary_plus.pass.cpp
@@ -10,7 +10,7 @@
// template<class T>
// complex<T>
-// operator+(const complex<T>&);
+// operator+(const complex<T>&); // constexpr in C++20
#include <complex>
#include <cassert>
@@ -18,22 +18,26 @@
#include "test_macros.h"
template <class T>
-void
+TEST_CONSTEXPR_CXX20
+bool
test()
{
- std::complex<T> z(1.5, 2.5);
- assert(z.real() == 1.5);
- assert(z.imag() == 2.5);
- std::complex<T> c = +z;
- assert(c.real() == 1.5);
- assert(c.imag() == 2.5);
+ assert(+std::complex<T>(1.5, -2.5) == std::complex<T>(1.5, -2.5));
+ assert(+std::complex<T>(-1.5, 2.5) == std::complex<T>(-1.5, 2.5));
+ return true;
}
int main(int, char**)
{
- test<float>();
- test<double>();
- test<long double>();
+ test<float>();
+ test<double>();
+ test<long double>();
+
+#if TEST_STD_VER > 17
+ static_assert(test<float>());
+ static_assert(test<double>());
+ static_assert(test<long double>());
+#endif
return 0;
}
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index ed502184a3413..c09ea3e980b89 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -231,7 +231,6 @@ def add_version_header(tc):
"name": "__cpp_lib_constexpr_complex",
"values": { "c++20": 201711 },
"headers": ["complex"],
- "unimplemented": True,
}, {
"name": "__cpp_lib_constexpr_dynamic_alloc",
"values": { "c++20": 201907 },
More information about the libcxx-commits
mailing list