diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -192,6 +192,8 @@ ------------------------------------------------- ----------------- ``__cpp_lib_concepts`` *unimplemented* ------------------------------------------------- ----------------- + ``__cpp_lib_constexpr_complex`` ``201711L`` + ------------------------------------------------- ----------------- ``__cpp_lib_constexpr_dynamic_alloc`` ``201907L`` ------------------------------------------------- ----------------- ``__cpp_lib_constexpr_misc`` *unimplemented* diff --git a/libcxx/include/complex b/libcxx/include/complex --- a/libcxx/include/complex +++ b/libcxx/include/complex @@ -29,21 +29,21 @@ T real() const; // constexpr in C++14 T imag() const; // constexpr in C++14 - void real(T); - void imag(T); - - complex& operator= (const T&); - complex& operator+=(const T&); - complex& operator-=(const T&); - complex& operator*=(const T&); - complex& operator/=(const T&); - - complex& operator=(const complex&); - template complex& operator= (const complex&); - template complex& operator+=(const complex&); - template complex& operator-=(const complex&); - template complex& operator*=(const complex&); - template complex& operator/=(const complex&); + void real(T); // constexpr in C++20 + void imag(T); // constexpr in C++20 + + complex& operator= (const T&); // constexpr in C++20 + complex& operator+=(const T&); // constexpr in C++20 + complex& operator-=(const T&); // constexpr in C++20 + complex& operator*=(const T&); // constexpr in C++20 + complex& operator/=(const T&); // constexpr in C++20 + + complex& operator=(const complex&); // constexpr in C++20 + template complex& operator= (const complex&); // constexpr in C++20 + template complex& operator+=(const complex&); // constexpr in C++20 + template complex& operator-=(const complex&); // constexpr in C++20 + template complex& operator*=(const complex&); // constexpr in C++20 + template complex& operator/=(const complex&); // constexpr in C++20 }; template<> @@ -57,22 +57,22 @@ explicit constexpr complex(const complex&); constexpr float real() const; - void real(float); + void real(float); // constexpr in C++20 constexpr float imag() const; - void imag(float); - - complex& operator= (float); - complex& operator+=(float); - complex& operator-=(float); - complex& operator*=(float); - complex& operator/=(float); - - complex& operator=(const complex&); - template complex& operator= (const complex&); - template complex& operator+=(const complex&); - template complex& operator-=(const complex&); - template complex& operator*=(const complex&); - template complex& operator/=(const complex&); + void imag(float); // constexpr in C++20 + + complex& operator= (float); // constexpr in C++20 + complex& operator+=(float); // constexpr in C++20 + complex& operator-=(float); // constexpr in C++20 + complex& operator*=(float); // constexpr in C++20 + complex& operator/=(float); // constexpr in C++20 + + complex& operator=(const complex&); // constexpr in C++20 + template complex& operator= (const complex&); // constexpr in C++20 + template complex& operator+=(const complex&); // constexpr in C++20 + template complex& operator-=(const complex&); // constexpr in C++20 + template complex& operator*=(const complex&); // constexpr in C++20 + template complex& operator/=(const complex&); // constexpr in C++20 }; template<> @@ -86,22 +86,22 @@ explicit constexpr complex(const complex&); constexpr double real() const; - void real(double); + void real(double); // constexpr in C++20 constexpr double imag() const; - void imag(double); - - complex& operator= (double); - complex& operator+=(double); - complex& operator-=(double); - complex& operator*=(double); - complex& operator/=(double); - complex& operator=(const complex&); - - template complex& operator= (const complex&); - template complex& operator+=(const complex&); - template complex& operator-=(const complex&); - template complex& operator*=(const complex&); - template complex& operator/=(const complex&); + void imag(double); // constexpr in C++20 + + complex& operator= (double); // constexpr in C++20 + complex& operator+=(double); // constexpr in C++20 + complex& operator-=(double); // constexpr in C++20 + complex& operator*=(double); // constexpr in C++20 + complex& operator/=(double); // constexpr in C++20 + complex& operator=(const complex&); // constexpr in C++20 + + template complex& operator= (const complex&); // constexpr in C++20 + template complex& operator+=(const complex&); // constexpr in C++20 + template complex& operator-=(const complex&); // constexpr in C++20 + template complex& operator*=(const complex&); // constexpr in C++20 + template complex& operator/=(const complex&); // constexpr in C++20 }; template<> @@ -115,39 +115,39 @@ constexpr complex(const complex&); 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& operator=(const complex&); - complex& operator= (long double); - complex& operator+=(long double); - complex& operator-=(long double); - complex& operator*=(long double); - complex& operator/=(long double); - - template complex& operator= (const complex&); - template complex& operator+=(const complex&); - template complex& operator-=(const complex&); - template complex& operator*=(const complex&); - template complex& operator/=(const complex&); + void imag(long double); // constexpr in C++20 + + complex& operator=(const complex&); // constexpr in C++20 + complex& operator= (long double); // constexpr in C++20 + complex& operator+=(long double); // constexpr in C++20 + complex& operator-=(long double); // constexpr in C++20 + complex& operator*=(long double); // constexpr in C++20 + complex& operator/=(long double); // constexpr in C++20 + + template complex& operator= (const complex&); // constexpr in C++20 + template complex& operator+=(const complex&); // constexpr in C++20 + template complex& operator-=(const complex&); // constexpr in C++20 + template complex& operator*=(const complex&); // constexpr in C++20 + template complex& operator/=(const complex&); // constexpr in C++20 }; // 26.3.6 operators: -template complex operator+(const complex&, const complex&); -template complex operator+(const complex&, const T&); -template complex operator+(const T&, const complex&); -template complex operator-(const complex&, const complex&); -template complex operator-(const complex&, const T&); -template complex operator-(const T&, const complex&); -template complex operator*(const complex&, const complex&); -template complex operator*(const complex&, const T&); -template complex operator*(const T&, const complex&); -template complex operator/(const complex&, const complex&); -template complex operator/(const complex&, const T&); -template complex operator/(const T&, const complex&); -template complex operator+(const complex&); -template complex operator-(const complex&); +template complex operator+(const complex&, const complex&); // constexpr in C++20 +template complex operator+(const complex&, const T&); // constexpr in C++20 +template complex operator+(const T&, const complex&); // constexpr in C++20 +template complex operator-(const complex&, const complex&); // constexpr in C++20 +template complex operator-(const complex&, const T&); // constexpr in C++20 +template complex operator-(const T&, const complex&); // constexpr in C++20 +template complex operator*(const complex&, const complex&); // constexpr in C++20 +template complex operator*(const complex&, const T&); // constexpr in C++20 +template complex operator*(const T&, const complex&); // constexpr in C++20 +template complex operator/(const complex&, const complex&); // constexpr in C++20 +template complex operator/(const complex&, const T&); // constexpr in C++20 +template complex operator/(const T&, const complex&); // constexpr in C++20 +template complex operator+(const complex&); // constexpr in C++20 +template complex operator-(const complex&); // constexpr in C++20 template bool operator==(const complex&, const complex&); // constexpr in C++14 template bool operator==(const complex&, const T&); // constexpr in C++14 template bool operator==(const T&, const complex&); // constexpr in C++14 @@ -184,17 +184,17 @@ template double arg(T); float arg(float); -template T norm(const complex&); - long double norm(long double); - double norm(double); -template double norm(T); - float norm(float); +template T norm(const complex&); // constexpr in C++20 + long double norm(long double); // constexpr in C++20 + double norm(double); // constexpr in C++20 +template double norm(T); // constexpr in C++20 + float norm(float); // constexpr in C++20 -template complex conj(const complex&); - complex conj(long double); - complex conj(double); -template complex conj(T); - complex conj(float); +template complex conj(const complex&); // constexpr in C++20 + complex conj(long double); // constexpr in C++20 + complex conj(double); // constexpr in C++20 +template complex conj(T); // constexpr in C++20 + complex conj(float); // constexpr in C++20 template complex proj(const complex&); complex proj(long double); @@ -234,6 +234,8 @@ #include <__config> #include #include +// TODO: Should we use FLT_RADIX from or __FLT_RADIX__ from or numeric_limits::radix from ? +#include #include #include #include @@ -250,8 +252,8 @@ template class _LIBCPP_TEMPLATE_VIS complex; -template complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w); -template complex<_Tp> operator/(const complex<_Tp>& __x, const complex<_Tp>& __y); +template _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w); +template _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator/(const complex<_Tp>& __x, const complex<_Tp>& __y); template class _LIBCPP_TEMPLATE_VIS complex @@ -272,40 +274,40 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 value_type real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 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_AFTER_CXX17 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (const value_type& __re) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 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_AFTER_CXX17 complex& operator+=(const value_type& __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator-=(const value_type& __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator*=(const value_type& __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator/=(const value_type& __re) {__re_ /= __re; __im_ /= __re; return *this;} - template _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -333,40 +335,40 @@ _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_AFTER_CXX17 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (float __re) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 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_AFTER_CXX17 complex& operator+=(float __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator-=(float __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator*=(float __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator/=(float __re) {__re_ /= __re; __im_ /= __re; return *this;} - template _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -391,40 +393,40 @@ _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_AFTER_CXX17 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (double __re) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 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_AFTER_CXX17 complex& operator+=(double __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator-=(double __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator*=(double __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator/=(double __re) {__re_ /= __re; __im_ /= __re; return *this;} - template _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -449,40 +451,40 @@ _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_AFTER_CXX17 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (long double __re) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 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_AFTER_CXX17 complex& operator+=(long double __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator-=(long double __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator*=(long double __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator/=(long double __re) {__re_ /= __re; __im_ /= __re; return *this;} - template _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -522,7 +524,7 @@ // 26.3.6 operators: template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator+(const complex<_Tp>& __x, const complex<_Tp>& __y) { @@ -532,7 +534,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator+(const complex<_Tp>& __x, const _Tp& __y) { @@ -542,7 +544,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator+(const _Tp& __x, const complex<_Tp>& __y) { @@ -552,7 +554,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator-(const complex<_Tp>& __x, const complex<_Tp>& __y) { @@ -562,7 +564,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator-(const complex<_Tp>& __x, const _Tp& __y) { @@ -572,7 +574,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator-(const _Tp& __x, const complex<_Tp>& __y) { @@ -581,7 +583,54 @@ return __t; } +template +constexpr _Tp __copysign_constexpr(_Tp __lcpp_x, _Tp __lcpp_y); + +template <> +inline _LIBCPP_INLINE_VISIBILITY +constexpr float __copysign_constexpr(float __lcpp_x, float __lcpp_y) +{ + return __builtin_copysignf(__lcpp_x, __lcpp_y); +} + +template <> +inline _LIBCPP_INLINE_VISIBILITY +constexpr double __copysign_constexpr(double __lcpp_x, double __lcpp_y) +{ + return __builtin_copysignl(__lcpp_x, __lcpp_y); +} + +template <> +inline _LIBCPP_INLINE_VISIBILITY +constexpr long double __copysign_constexpr(long double __lcpp_x, long double __lcpp_y) +{ + return __builtin_copysignl(__lcpp_x, __lcpp_y); +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp +__abs_constexpr(_Tp __lcpp_x) _NOEXCEPT { + return (__lcpp_x < _Tp(0)) ? -__lcpp_x : __lcpp_x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr +typename enable_if +< + is_integral<_Tp>::value, + _Tp +>::type +__copysign_constexpr(_Tp __lcpp_x, _Tp __lcpp_y) +{ + if (__lcpp_y < _Tp(0)) { + return -abs(__lcpp_x); + } + return abs(__lcpp_x); +} + template +_LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w) { @@ -589,6 +638,36 @@ _Tp __b = __z.imag(); _Tp __c = __w.real(); _Tp __d = __w.imag(); + 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 = __libcpp_isinf_or_builtin(__a) || __libcpp_isinf_or_builtin(__b); + bool __w_inf = __libcpp_isinf_or_builtin(__c) || __libcpp_isinf_or_builtin(__d); + bool __z_nan = !__z_inf && ( + (__libcpp_isnan_or_builtin(__a) && __libcpp_isnan_or_builtin(__b)) + || (__libcpp_isnan_or_builtin(__a) && __b == _Tp(0)) + || (__a == _Tp(0) && __libcpp_isnan_or_builtin(__b)) + ); + bool __w_nan = !__w_inf && ( + (__libcpp_isnan_or_builtin(__c) && __libcpp_isnan_or_builtin(__d)) + || (__libcpp_isnan_or_builtin(__c) && __d == _Tp(0)) + || (__c == _Tp(0) && __libcpp_isnan_or_builtin(__d)) + ); + if (__z_nan || __w_nan) { + return complex<_Tp>(_Tp(NAN), _Tp(0)); + } + if (__z_inf || __w_inf) { + if (__z_zero || __w_zero) { + return complex<_Tp>(_Tp(NAN), _Tp(0)); + } + return complex<_Tp>(_Tp(INFINITY), _Tp(INFINITY)); + } + bool __z_nonzero_nan = !__z_inf && !__z_nan && (__libcpp_isnan_or_builtin(__a) || __libcpp_isnan_or_builtin(__b)); + bool __w_nonzero_nan = !__w_inf && !__w_nan && (__libcpp_isnan_or_builtin(__c) || __libcpp_isnan_or_builtin(__d)); + if (__z_nonzero_nan || __w_nonzero_nan) { + return complex<_Tp>(_Tp(NAN), _Tp(0)); + } + } _Tp __ac = __a * __c; _Tp __bd = __b * __d; _Tp __ad = __a * __d; @@ -600,35 +679,74 @@ bool __recalc = false; if (__libcpp_isinf_or_builtin(__a) || __libcpp_isinf_or_builtin(__b)) { - __a = copysign(__libcpp_isinf_or_builtin(__a) ? _Tp(1) : _Tp(0), __a); - __b = copysign(__libcpp_isinf_or_builtin(__b) ? _Tp(1) : _Tp(0), __b); - if (__libcpp_isnan_or_builtin(__c)) - __c = copysign(_Tp(0), __c); - if (__libcpp_isnan_or_builtin(__d)) - __d = copysign(_Tp(0), __d); + if (__libcpp_is_constant_evaluated()) { + __a = __copysign_constexpr(__libcpp_isinf_or_builtin(__a) ? _Tp(1) : _Tp(0), __a); + __b = __copysign_constexpr(__libcpp_isinf_or_builtin(__b) ? _Tp(1) : _Tp(0), __b); + if (__libcpp_isnan_or_builtin(__c)) + __c = __copysign_constexpr(_Tp(0), __c); + if (__libcpp_isnan_or_builtin(__d)) + __d = __copysign_constexpr(_Tp(0), __d); + } else { + if (__libcpp_is_constant_evaluated()) { + __a = __copysign_constexpr(__libcpp_isinf_or_builtin(__a) ? _Tp(1) : _Tp(0), __a); + __b = __copysign_constexpr(__libcpp_isinf_or_builtin(__b) ? _Tp(1) : _Tp(0), __b); + if (__libcpp_isnan_or_builtin(__c)) + __c = __copysign_constexpr(_Tp(0), __c); + if (__libcpp_isnan_or_builtin(__d)) + __d = __copysign_constexpr(_Tp(0), __d); + } else { + __a = copysign(__libcpp_isinf_or_builtin(__a) ? _Tp(1) : _Tp(0), __a); + __b = copysign(__libcpp_isinf_or_builtin(__b) ? _Tp(1) : _Tp(0), __b); + if (__libcpp_isnan_or_builtin(__c)) + __c = copysign(_Tp(0), __c); + if (__libcpp_isnan_or_builtin(__d)) + __d = copysign(_Tp(0), __d); + } + } __recalc = true; } if (__libcpp_isinf_or_builtin(__c) || __libcpp_isinf_or_builtin(__d)) { - __c = copysign(__libcpp_isinf_or_builtin(__c) ? _Tp(1) : _Tp(0), __c); - __d = copysign(__libcpp_isinf_or_builtin(__d) ? _Tp(1) : _Tp(0), __d); - if (__libcpp_isnan_or_builtin(__a)) - __a = copysign(_Tp(0), __a); - if (__libcpp_isnan_or_builtin(__b)) - __b = copysign(_Tp(0), __b); - __recalc = true; + if (__libcpp_is_constant_evaluated()) { + __c = __copysign_constexpr(__libcpp_isinf_or_builtin(__c) ? _Tp(1) : _Tp(0), __c); + __d = __copysign_constexpr(__libcpp_isinf_or_builtin(__d) ? _Tp(1) : _Tp(0), __d); + if (__libcpp_isnan_or_builtin(__a)) + __a = __copysign_constexpr(_Tp(0), __a); + if (__libcpp_isnan_or_builtin(__b)) + __b = __copysign_constexpr(_Tp(0), __b); + __recalc = true; + } else { + __c = copysign(__libcpp_isinf_or_builtin(__c) ? _Tp(1) : _Tp(0), __c); + __d = copysign(__libcpp_isinf_or_builtin(__d) ? _Tp(1) : _Tp(0), __d); + if (__libcpp_isnan_or_builtin(__a)) + __a = copysign(_Tp(0), __a); + if (__libcpp_isnan_or_builtin(__b)) + __b = copysign(_Tp(0), __b); + __recalc = true; + } } if (!__recalc && (__libcpp_isinf_or_builtin(__ac) || __libcpp_isinf_or_builtin(__bd) || __libcpp_isinf_or_builtin(__ad) || __libcpp_isinf_or_builtin(__bc))) { - if (__libcpp_isnan_or_builtin(__a)) - __a = copysign(_Tp(0), __a); - if (__libcpp_isnan_or_builtin(__b)) - __b = copysign(_Tp(0), __b); - if (__libcpp_isnan_or_builtin(__c)) - __c = copysign(_Tp(0), __c); - if (__libcpp_isnan_or_builtin(__d)) - __d = copysign(_Tp(0), __d); + if (__libcpp_is_constant_evaluated()) { + if (__libcpp_isnan_or_builtin(__a)) + __a = __copysign_constexpr(_Tp(0), __a); + if (__libcpp_isnan_or_builtin(__b)) + __b = __copysign_constexpr(_Tp(0), __b); + if (__libcpp_isnan_or_builtin(__c)) + __c = __copysign_constexpr(_Tp(0), __c); + if (__libcpp_isnan_or_builtin(__d)) + __d = __copysign_constexpr(_Tp(0), __d); + } else { + if (__libcpp_isnan_or_builtin(__a)) + __a = copysign(_Tp(0), __a); + if (__libcpp_isnan_or_builtin(__b)) + __b = copysign(_Tp(0), __b); + if (__libcpp_isnan_or_builtin(__c)) + __c = copysign(_Tp(0), __c); + if (__libcpp_isnan_or_builtin(__d)) + __d = copysign(_Tp(0), __d); + } __recalc = true; } if (__recalc) @@ -641,7 +759,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator*(const complex<_Tp>& __x, const _Tp& __y) { @@ -651,7 +769,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator*(const _Tp& __x, const complex<_Tp>& __y) { @@ -660,7 +778,83 @@ return __t; } +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp +__fmax_constexpr(_Tp __lcpp_x, _Tp __lcpp_y) _NOEXCEPT { + // Treat NaNs as smaller. + if (__libcpp_isnan_or_builtin(__lcpp_x)) + return __lcpp_y; + if (__libcpp_isnan_or_builtin(__lcpp_y)) + return __lcpp_x; + return __lcpp_x < __lcpp_y ? __lcpp_y : __lcpp_x; +} + +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp +__fabs_constexpr(_Tp __lcpp_x) _NOEXCEPT { + return (__lcpp_x < _Tp{}) ? -__lcpp_x : __lcpp_x; +} + +template +constexpr _Tp __logb_constexpr(_Tp __lcpp_x) { + if(__lcpp_x == _Tp(0)) { + // raise FE_DIVBYZERO + return -_Tp(INFINITY); + } + + if(__libcpp_isinf_or_builtin(__lcpp_x)) + return _Tp(INFINITY); + + if(__libcpp_isnan_or_builtin(__lcpp_x)) + return _Tp(NAN); + + __lcpp_x = __fabs_constexpr(__lcpp_x); + unsigned long long __exp = 0; + while (__lcpp_x >= __FLT_RADIX__) { + __lcpp_x /= __FLT_RADIX__; + __exp += 1; + } + return _Tp(__exp); +} + +template +constexpr _Tp __scalbn_constexpr(_Tp __lcpp_x, int __lcpp_exp) { + if(__lcpp_x == _Tp(0)) + return __lcpp_x; + + if(__libcpp_isinf_or_builtin(__lcpp_x)) + return __lcpp_x; + + if (__lcpp_exp == _Tp(0)) + return __lcpp_x; + + if(__libcpp_isnan_or_builtin(__lcpp_x)) + return _Tp(NAN); + + _Tp __mult{1}; + if (__lcpp_exp > 0) { + __mult = __FLT_RADIX__; + --__lcpp_exp; + } else { + ++__lcpp_exp; + __lcpp_exp = -__lcpp_exp; + __mult /= __FLT_RADIX__; + } + + while (__lcpp_exp > 0) { + if (!(__lcpp_exp & 1)) { + __mult *= __mult; + __lcpp_exp >>= 1; + } else { + __lcpp_x *= __mult; + --__lcpp_exp; + } + } + return __lcpp_x; +} + template +_LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator/(const complex<_Tp>& __z, const complex<_Tp>& __w) { @@ -669,43 +863,125 @@ _Tp __b = __z.imag(); _Tp __c = __w.real(); _Tp __d = __w.imag(); - _Tp __logbw = logb(fmax(fabs(__c), fabs(__d))); + _Tp __logbw{}; + if (__libcpp_is_constant_evaluated()) { + __logbw = __logb_constexpr( + __fmax_constexpr(__fabs_constexpr(__c), __fabs_constexpr(__d))); + } else { + __logbw = logb(fmax(fabs(__c), fabs(__d))); + } if (__libcpp_isfinite_or_builtin(__logbw)) { __ilogbw = static_cast(__logbw); - __c = scalbn(__c, -__ilogbw); - __d = scalbn(__d, -__ilogbw); + if (__libcpp_is_constant_evaluated()) { + __c = __scalbn_constexpr(__c, -__ilogbw); + __d = __scalbn_constexpr(__d, -__ilogbw); + } else { + __c = scalbn(__c, -__ilogbw); + __d = scalbn(__d, -__ilogbw); + } } - _Tp __denom = __c * __c + __d * __d; - _Tp __x = scalbn((__a * __c + __b * __d) / __denom, -__ilogbw); - _Tp __y = scalbn((__b * __c - __a * __d) / __denom, -__ilogbw); - if (__libcpp_isnan_or_builtin(__x) && __libcpp_isnan_or_builtin(__y)) - { - if ((__denom == _Tp(0)) && (!__libcpp_isnan_or_builtin(__a) || !__libcpp_isnan_or_builtin(__b))) - { - __x = copysign(_Tp(INFINITY), __c) * __a; - __y = copysign(_Tp(INFINITY), __c) * __b; + 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 = __libcpp_isinf_or_builtin(__a) || __libcpp_isinf_or_builtin(__b); + bool __w_inf = __libcpp_isinf_or_builtin(__c) || __libcpp_isinf_or_builtin(__d); + bool __z_nan = !__z_inf && ( + (__libcpp_isnan_or_builtin(__a) && __libcpp_isnan_or_builtin(__b)) + || (__libcpp_isnan_or_builtin(__a) && __b == _Tp(0)) + || (__a == _Tp(0) && __libcpp_isnan_or_builtin(__b)) + ); + bool __w_nan = !__w_inf && ( + (__libcpp_isnan_or_builtin(__c) && __libcpp_isnan_or_builtin(__d)) + || (__libcpp_isnan_or_builtin(__c) && __d == _Tp(0)) + || (__c == _Tp(0) && __libcpp_isnan_or_builtin(__d)) + ); + if ((__z_nan || __w_nan) || (__z_inf && __w_inf)) { + return complex<_Tp>(_Tp(NAN), _Tp(0)); + } + bool __z_nonzero_nan = !__z_inf && !__z_nan && (__libcpp_isnan_or_builtin(__a) || __libcpp_isnan_or_builtin(__b)); + bool __w_nonzero_nan = !__w_inf && !__w_nan && (__libcpp_isnan_or_builtin(__c) || __libcpp_isnan_or_builtin(__d)); + if (__z_nonzero_nan || __w_nonzero_nan) { + if (__w_zero) { + return complex<_Tp>(_Tp(INFINITY), _Tp(INFINITY)); + } + return complex<_Tp>(_Tp(NAN), _Tp(0)); + } + if (__w_inf) { + return complex<_Tp>(_Tp(0), _Tp(0)); + } + if (__z_inf) { + return complex<_Tp>(_Tp(INFINITY), _Tp(INFINITY)); } - else if ((__libcpp_isinf_or_builtin(__a) || __libcpp_isinf_or_builtin(__b)) && __libcpp_isfinite_or_builtin(__c) && __libcpp_isfinite_or_builtin(__d)) + if (__w_zero) { + if (__z_zero) { + return complex<_Tp>(_Tp(NAN), _Tp(0)); + } + return complex<_Tp>(_Tp(INFINITY), _Tp(INFINITY)); + } + } + _Tp __denom = __c * __c + __d * __d; + _Tp __x{}; + _Tp __y{}; + if (__libcpp_is_constant_evaluated()) { + __x = __scalbn_constexpr((__a * __c + __b * __d) / __denom, -__ilogbw); + __y = __scalbn_constexpr((__b * __c - __a * __d) / __denom, -__ilogbw); + } else { + __x = scalbn((__a * __c + __b * __d) / __denom, -__ilogbw); + __y = scalbn((__b * __c - __a * __d) / __denom, -__ilogbw); + } + if (__libcpp_is_constant_evaluated()) { + if (__libcpp_isnan_or_builtin(__x) && __libcpp_isnan_or_builtin(__y)) { - __a = copysign(__libcpp_isinf_or_builtin(__a) ? _Tp(1) : _Tp(0), __a); - __b = copysign(__libcpp_isinf_or_builtin(__b) ? _Tp(1) : _Tp(0), __b); - __x = _Tp(INFINITY) * (__a * __c + __b * __d); - __y = _Tp(INFINITY) * (__b * __c - __a * __d); + if ((__denom == _Tp(0)) && (!__libcpp_isnan_or_builtin(__a) || !__libcpp_isnan_or_builtin(__b))) + { + __x = __copysign_constexpr(_Tp(INFINITY), __c) * __a; + __y = __copysign_constexpr(_Tp(INFINITY), __c) * __b; + } + else if ((__libcpp_isinf_or_builtin(__a) || __libcpp_isinf_or_builtin(__b)) && __libcpp_isfinite_or_builtin(__c) && __libcpp_isfinite_or_builtin(__d)) + { + __a = __copysign_constexpr(__libcpp_isinf_or_builtin(__a) ? _Tp(1) : _Tp(0), __a); + __b = __copysign_constexpr(__libcpp_isinf_or_builtin(__b) ? _Tp(1) : _Tp(0), __b); + __x = _Tp(INFINITY) * (__a * __c + __b * __d); + __y = _Tp(INFINITY) * (__b * __c - __a * __d); + } + else if (__libcpp_isinf_or_builtin(__logbw) && __logbw > _Tp(0) && __libcpp_isfinite_or_builtin(__a) && __libcpp_isfinite_or_builtin(__b)) + { + __c = __copysign_constexpr(__libcpp_isinf_or_builtin(__c) ? _Tp(1) : _Tp(0), __c); + __d = __copysign_constexpr(__libcpp_isinf_or_builtin(__d) ? _Tp(1) : _Tp(0), __d); + __x = _Tp(0) * (__a * __c + __b * __d); + __y = _Tp(0) * (__b * __c - __a * __d); + } } - else if (__libcpp_isinf_or_builtin(__logbw) && __logbw > _Tp(0) && __libcpp_isfinite_or_builtin(__a) && __libcpp_isfinite_or_builtin(__b)) + } else { + if (__libcpp_isnan_or_builtin(__x) && __libcpp_isnan_or_builtin(__y)) { - __c = copysign(__libcpp_isinf_or_builtin(__c) ? _Tp(1) : _Tp(0), __c); - __d = copysign(__libcpp_isinf_or_builtin(__d) ? _Tp(1) : _Tp(0), __d); - __x = _Tp(0) * (__a * __c + __b * __d); - __y = _Tp(0) * (__b * __c - __a * __d); + if ((__denom == _Tp(0)) && (!__libcpp_isnan_or_builtin(__a) || !__libcpp_isnan_or_builtin(__b))) + { + __x = copysign(_Tp(INFINITY), __c) * __a; + __y = copysign(_Tp(INFINITY), __c) * __b; + } + else if ((__libcpp_isinf_or_builtin(__a) || __libcpp_isinf_or_builtin(__b)) && __libcpp_isfinite_or_builtin(__c) && __libcpp_isfinite_or_builtin(__d)) + { + __a = copysign(__libcpp_isinf_or_builtin(__a) ? _Tp(1) : _Tp(0), __a); + __b = copysign(__libcpp_isinf_or_builtin(__b) ? _Tp(1) : _Tp(0), __b); + __x = _Tp(INFINITY) * (__a * __c + __b * __d); + __y = _Tp(INFINITY) * (__b * __c - __a * __d); + } + else if (__libcpp_isinf_or_builtin(__logbw) && __logbw > _Tp(0) && __libcpp_isfinite_or_builtin(__a) && __libcpp_isfinite_or_builtin(__b)) + { + __c = copysign(__libcpp_isinf_or_builtin(__c) ? _Tp(1) : _Tp(0), __c); + __d = copysign(__libcpp_isinf_or_builtin(__d) ? _Tp(1) : _Tp(0), __d); + __x = _Tp(0) * (__a * __c + __b * __d); + __y = _Tp(0) * (__b * __c - __a * __d); + } } } return complex<_Tp>(__x, __y); } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator/(const complex<_Tp>& __x, const _Tp& __y) { @@ -713,7 +989,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator/(const _Tp& __x, const complex<_Tp>& __y) { @@ -723,7 +999,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator+(const complex<_Tp>& __x) { @@ -731,7 +1007,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator-(const complex<_Tp>& __x) { @@ -902,7 +1178,7 @@ // norm template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp norm(const complex<_Tp>& __c) { @@ -914,7 +1190,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename __libcpp_complex_overload_traits<_Tp>::_ValueType norm(_Tp __re) { @@ -925,7 +1201,7 @@ // conj template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> conj(const complex<_Tp>& __c) { @@ -933,7 +1209,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename __libcpp_complex_overload_traits<_Tp>::_ComplexType conj(_Tp __re) { diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -45,6 +45,7 @@ __cpp_lib_clamp 201603L __cpp_lib_complex_udls 201309L __cpp_lib_concepts 201806L +__cpp_lib_constexpr_complex 201711L __cpp_lib_constexpr_dynamic_alloc 201907L __cpp_lib_constexpr_misc 201811L @@ -251,6 +252,7 @@ # define __cpp_lib_char8_t 201811L # endif // # define __cpp_lib_concepts 201806L +# define __cpp_lib_constexpr_complex 201711L # define __cpp_lib_constexpr_dynamic_alloc 201907L // # define __cpp_lib_constexpr_misc 201811L // # define __cpp_lib_constexpr_swap_algorithms 201806L diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.pass.cpp @@ -13,8 +13,9 @@ // Test the feature test macros defined by -/* Constant Value - __cpp_lib_complex_udls 201309L [C++14] +/* Constant Value + __cpp_lib_complex_udls 201309L [C++14] + __cpp_lib_constexpr_complex 201711L [C++2a] */ #include @@ -26,6 +27,10 @@ # error "__cpp_lib_complex_udls should not be defined before c++14" # endif +# ifdef __cpp_lib_constexpr_complex +# error "__cpp_lib_constexpr_complex should not be defined before c++2a" +# endif + #elif TEST_STD_VER == 14 # ifndef __cpp_lib_complex_udls @@ -35,6 +40,10 @@ # error "__cpp_lib_complex_udls should have the value 201309L in c++14" # endif +# ifdef __cpp_lib_constexpr_complex +# error "__cpp_lib_constexpr_complex should not be defined before c++2a" +# endif + #elif TEST_STD_VER == 17 # ifndef __cpp_lib_complex_udls @@ -44,6 +53,10 @@ # error "__cpp_lib_complex_udls should have the value 201309L in c++17" # endif +# ifdef __cpp_lib_constexpr_complex +# error "__cpp_lib_constexpr_complex should not be defined before c++2a" +# endif + #elif TEST_STD_VER > 17 # ifndef __cpp_lib_complex_udls @@ -53,6 +66,13 @@ # error "__cpp_lib_complex_udls should have the value 201309L in c++2a" # endif +# ifndef __cpp_lib_constexpr_complex +# error "__cpp_lib_constexpr_complex should be defined in c++2a" +# endif +# if __cpp_lib_constexpr_complex != 201711L +# error "__cpp_lib_constexpr_complex should have the value 201711L in c++2a" +# endif + #endif // TEST_STD_VER > 17 int main(int, char**) { return 0; } diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp @@ -40,6 +40,7 @@ __cpp_lib_clamp 201603L [C++17] __cpp_lib_complex_udls 201309L [C++14] __cpp_lib_concepts 201806L [C++2a] + __cpp_lib_constexpr_complex 201711L [C++2a] __cpp_lib_constexpr_dynamic_alloc 201907L [C++2a] __cpp_lib_constexpr_misc 201811L [C++2a] __cpp_lib_constexpr_swap_algorithms 201806L [C++2a] @@ -218,6 +219,10 @@ # error "__cpp_lib_concepts should not be defined before c++2a" # endif +# ifdef __cpp_lib_constexpr_complex +# error "__cpp_lib_constexpr_complex should not be defined before c++2a" +# endif + # ifdef __cpp_lib_constexpr_dynamic_alloc # error "__cpp_lib_constexpr_dynamic_alloc should not be defined before c++2a" # endif @@ -606,6 +611,10 @@ # error "__cpp_lib_concepts should not be defined before c++2a" # endif +# ifdef __cpp_lib_constexpr_complex +# error "__cpp_lib_constexpr_complex should not be defined before c++2a" +# endif + # ifdef __cpp_lib_constexpr_dynamic_alloc # error "__cpp_lib_constexpr_dynamic_alloc should not be defined before c++2a" # endif @@ -1108,6 +1117,10 @@ # error "__cpp_lib_concepts should not be defined before c++2a" # endif +# ifdef __cpp_lib_constexpr_complex +# error "__cpp_lib_constexpr_complex should not be defined before c++2a" +# endif + # ifdef __cpp_lib_constexpr_dynamic_alloc # error "__cpp_lib_constexpr_dynamic_alloc should not be defined before c++2a" # endif @@ -1877,6 +1890,13 @@ # endif # endif +# ifndef __cpp_lib_constexpr_complex +# error "__cpp_lib_constexpr_complex should be defined in c++2a" +# endif +# if __cpp_lib_constexpr_complex != 201711L +# error "__cpp_lib_constexpr_complex should have the value 201711L in c++2a" +# endif + # ifndef __cpp_lib_constexpr_dynamic_alloc # error "__cpp_lib_constexpr_dynamic_alloc should be defined in c++2a" # endif diff --git a/libcxx/test/std/numerics/complex.number/cases.h b/libcxx/test/std/numerics/complex.number/cases.h --- a/libcxx/test/std/numerics/complex.number/cases.h +++ b/libcxx/test/std/numerics/complex.number/cases.h @@ -16,7 +16,7 @@ #include #include -const std::complex testcases[] = +TEST_CONSTEXPR_CXX20 const std::complex testcases[] = { std::complex( 1.e-6, 1.e-6), std::complex(-1.e-6, 1.e-6), @@ -174,22 +174,22 @@ enum {zero, non_zero, inf, NaN, non_zero_nan}; template -int +TEST_CONSTEXPR_CXX20 int classify(const std::complex& x) { if (x == std::complex()) return zero; - if (std::isinf(x.real()) || std::isinf(x.imag())) + if (__builtin_isinf(x.real()) || __builtin_isinf(x.imag())) return inf; - if (std::isnan(x.real()) && std::isnan(x.imag())) + if (__builtin_isnan(x.real()) && __builtin_isnan(x.imag())) return NaN; - if (std::isnan(x.real())) + if (__builtin_isnan(x.real())) { if (x.imag() == T(0)) return NaN; return non_zero_nan; } - if (std::isnan(x.imag())) + if (__builtin_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 --- 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 @@ // -// template complex conj(const complex&); -// complex conj(long double); -// complex conj(double); -// template complex conj(T); -// complex conj(float); +// template complex conj(const complex&); // constexpr in C++20 +// complex conj(long double); // constexpr in C++20 +// complex conj(double); // constexpr in C++20 +// template complex conj(T); // constexpr in C++20 +// complex conj(float); // constexpr in C++20 #include #include @@ -22,37 +22,41 @@ #include "../cases.h" template -void -test(T x, typename std::enable_if::value>::type* = 0) -{ - static_assert((std::is_same >::value), ""); - assert(std::conj(x) == conj(std::complex(x, 0))); +TEST_CONSTEXPR_CXX20 bool +test(T x, typename std::enable_if::value>::type* = 0) { + static_assert( + (std::is_same >::value), ""); + assert(std::conj(x) == conj(std::complex(x, 0))); + return true; } template -void -test(T x, typename std::enable_if::value>::type* = 0) -{ - static_assert((std::is_same >::value), ""); - assert(std::conj(x) == conj(std::complex(x, 0))); +TEST_CONSTEXPR_CXX20 bool +test(T x, + typename std::enable_if::value>::type* = 0) { + static_assert((std::is_same >::value), + ""); + assert(std::conj(x) == conj(std::complex(x, 0))); + return true; } template -void -test(T x, typename std::enable_if::value && - !std::is_floating_point::value>::type* = 0) -{ - static_assert((std::is_same >::value), ""); - assert(std::conj(x) == conj(std::complex(x, 0))); +TEST_CONSTEXPR_CXX20 bool +test(T x, + typename std::enable_if::value && + !std::is_floating_point::value>::type* = 0) { + static_assert((std::is_same >::value), + ""); + assert(std::conj(x) == conj(std::complex(x, 0))); + return true; } template -void -test() -{ - test(0); - test(1); - test(10); +TEST_CONSTEXPR_CXX20 bool test() { + test(0); + test(1); + test(10); + return true; } int main(int, char**) @@ -64,5 +68,14 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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 // T -// norm(T x); +// norm(T x); // constexpr in C++20 #include #include @@ -20,28 +20,27 @@ #include "../cases.h" template -void -test(T x, typename std::enable_if::value>::type* = 0) -{ - static_assert((std::is_same::value), ""); - assert(std::norm(x) == norm(std::complex(static_cast(x), 0))); +TEST_CONSTEXPR_CXX20 bool +test(T x, typename std::enable_if::value>::type* = 0) { + static_assert((std::is_same::value), ""); + assert(std::norm(x) == norm(std::complex(static_cast(x), 0))); + return true; } template -void -test(T x, typename std::enable_if::value>::type* = 0) -{ - static_assert((std::is_same::value), ""); - assert(std::norm(x) == norm(std::complex(x, 0))); +TEST_CONSTEXPR_CXX20 bool +test(T x, typename std::enable_if::value>::type* = 0) { + static_assert((std::is_same::value), ""); + assert(std::norm(x) == norm(std::complex(x, 0))); + return true; } template -void -test() -{ - test(0); - test(1); - test(10); +TEST_CONSTEXPR_CXX20 bool test() { + test(0); + test(1); + test(10); + return true; } int main(int, char**) @@ -53,5 +52,14 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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& operator=(const complex&); -// template complex& operator= (const complex&); +// template complex& operator= (const complex&); // constexpr in C++20 #include #include @@ -17,20 +17,19 @@ #include "test_macros.h" template -void -test() -{ - std::complex c; - assert(c.real() == 0); - assert(c.imag() == 0); - std::complex c2(1.5, 2.5); - c = c2; - assert(c.real() == 1.5); - assert(c.imag() == 2.5); - std::complex c3(3.5, -4.5); - c = c3; - assert(c.real() == 3.5); - assert(c.imag() == -4.5); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex c; + assert(c.real() == 0); + assert(c.imag() == 0); + std::complex c2(1.5, 2.5); + c = c2; + assert(c.real() == 1.5); + assert(c.imag() == 2.5); + std::complex c3(3.5, -4.5); + c = c3; + assert(c.real() == 3.5); + assert(c.imag() == -4.5); + return true; } int main(int, char**) @@ -47,5 +46,19 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + + static_assert(test()); + static_assert(test()); + static_assert(test()); + + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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& operator= (const T&); +// complex& operator= (const T&); // constexpr in C++20 #include #include @@ -16,18 +16,17 @@ #include "test_macros.h" template -void -test() -{ - std::complex c; - assert(c.real() == 0); - assert(c.imag() == 0); - c = 1.5; - assert(c.real() == 1.5); - assert(c.imag() == 0); - c = -1.5; - assert(c.real() == -1.5); - assert(c.imag() == 0); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex c; + assert(c.real() == 0); + assert(c.imag() == 0); + c = 1.5; + assert(c.real() == 1.5); + assert(c.imag() == 0); + c = -1.5; + assert(c.real() == -1.5); + assert(c.imag() == 0); + return true; } int main(int, char**) @@ -36,5 +35,11 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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& operator/=(const complex& rhs); +// complex& operator/=(const complex& rhs); // constexpr in C++20 #include #include @@ -16,34 +16,32 @@ #include "test_macros.h" template -void -test() -{ - std::complex c(-4, 7.5); - const std::complex c2(1.5, 2.5); - assert(c.real() == -4); - assert(c.imag() == 7.5); - c /= c2; - assert(c.real() == 1.5); - assert(c.imag() == 2.5); - c /= c2; - assert(c.real() == 1); - assert(c.imag() == 0); - - std::complex c3; - - c3 = c; - std::complex ic (1,1); - c3 /= ic; - assert(c3.real() == 0.5); - assert(c3.imag() == -0.5); - - c3 = c; - std::complex fc (1,1); - c3 /= fc; - assert(c3.real() == 0.5); - assert(c3.imag() == -0.5); - +TEST_CONSTEXPR_CXX20 bool test() { + std::complex c(-4, 7.5); + const std::complex c2(1.5, 2.5); + assert(c.real() == -4); + assert(c.imag() == 7.5); + c /= c2; + assert(c.real() == 1.5); + assert(c.imag() == 2.5); + c /= c2; + assert(c.real() == 1); + assert(c.imag() == 0); + + std::complex c3; + + c3 = c; + std::complex ic(1, 1); + c3 /= ic; + assert(c3.real() == 0.5); + assert(c3.imag() == -0.5); + + c3 = c; + std::complex fc(1, 1); + c3 /= fc; + assert(c3.real() == 0.5); + assert(c3.imag() == -0.5); + return true; } int main(int, char**) @@ -52,5 +50,11 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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& operator/=(const T& rhs); +// complex& operator/=(const T& rhs); // constexpr in C++20 #include #include @@ -16,25 +16,24 @@ #include "test_macros.h" template -void -test() -{ - std::complex c(1); - assert(c.real() == 1); - assert(c.imag() == 0); - c /= 0.5; - assert(c.real() == 2); - assert(c.imag() == 0); - c /= 0.5; - assert(c.real() == 4); - assert(c.imag() == 0); - c /= -0.5; - assert(c.real() == -8); - assert(c.imag() == 0); - c.imag(2); - c /= 0.5; - assert(c.real() == -16); - assert(c.imag() == 4); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex c(1); + assert(c.real() == 1); + assert(c.imag() == 0); + c /= 0.5; + assert(c.real() == 2); + assert(c.imag() == 0); + c /= 0.5; + assert(c.real() == 4); + assert(c.imag() == 0); + c /= -0.5; + assert(c.real() == -8); + assert(c.imag() == 0); + c.imag(2); + c /= 0.5; + assert(c.real() == -16); + assert(c.imag() == 4); + return true; } int main(int, char**) @@ -43,5 +42,11 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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& operator-=(const complex& rhs); +// complex& operator-=(const complex& rhs); // constexpr in C++20 #include #include @@ -16,33 +16,32 @@ #include "test_macros.h" template -void -test() -{ - std::complex c; - const std::complex c2(1.5, 2.5); - assert(c.real() == 0); - assert(c.imag() == 0); - c -= c2; - assert(c.real() == -1.5); - assert(c.imag() == -2.5); - c -= c2; - assert(c.real() == -3); - assert(c.imag() == -5); - - std::complex c3; - - c3 = c; - std::complex ic (1,1); - c3 -= ic; - assert(c3.real() == -4); - assert(c3.imag() == -6); - - c3 = c; - std::complex fc (1,1); - c3 -= fc; - assert(c3.real() == -4); - assert(c3.imag() == -6); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex c; + const std::complex c2(1.5, 2.5); + assert(c.real() == 0); + assert(c.imag() == 0); + c -= c2; + assert(c.real() == -1.5); + assert(c.imag() == -2.5); + c -= c2; + assert(c.real() == -3); + assert(c.imag() == -5); + + std::complex c3; + + c3 = c; + std::complex ic(1, 1); + c3 -= ic; + assert(c3.real() == -4); + assert(c3.imag() == -6); + + c3 = c; + std::complex fc(1, 1); + c3 -= fc; + assert(c3.real() == -4); + assert(c3.imag() == -6); + return true; } int main(int, char**) @@ -51,5 +50,11 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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& operator-=(const T& rhs); +// complex& operator-=(const T& rhs); // constexpr in C++20 #include #include @@ -16,21 +16,20 @@ #include "test_macros.h" template -void -test() -{ - std::complex c; - assert(c.real() == 0); - assert(c.imag() == 0); - c -= 1.5; - assert(c.real() == -1.5); - assert(c.imag() == 0); - c -= 1.5; - assert(c.real() == -3); - assert(c.imag() == 0); - c -= -1.5; - assert(c.real() == -1.5); - assert(c.imag() == 0); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex c; + assert(c.real() == 0); + assert(c.imag() == 0); + c -= 1.5; + assert(c.real() == -1.5); + assert(c.imag() == 0); + c -= 1.5; + assert(c.real() == -3); + assert(c.imag() == 0); + c -= -1.5; + assert(c.real() == -1.5); + assert(c.imag() == 0); + return true; } int main(int, char**) @@ -39,5 +38,11 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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& operator+=(const complex& rhs); +// complex& operator+=(const complex& rhs); // constexpr in C++20 #include #include @@ -16,33 +16,32 @@ #include "test_macros.h" template -void -test() -{ - std::complex c; - const std::complex c2(1.5, 2.5); - assert(c.real() == 0); - assert(c.imag() == 0); - c += c2; - assert(c.real() == 1.5); - assert(c.imag() == 2.5); - c += c2; - assert(c.real() == 3); - assert(c.imag() == 5); - - std::complex c3; - - c3 = c; - std::complex ic (1,1); - c3 += ic; - assert(c3.real() == 4); - assert(c3.imag() == 6); - - c3 = c; - std::complex fc (1,1); - c3 += fc; - assert(c3.real() == 4); - assert(c3.imag() == 6); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex c; + const std::complex c2(1.5, 2.5); + assert(c.real() == 0); + assert(c.imag() == 0); + c += c2; + assert(c.real() == 1.5); + assert(c.imag() == 2.5); + c += c2; + assert(c.real() == 3); + assert(c.imag() == 5); + + std::complex c3; + + c3 = c; + std::complex ic(1, 1); + c3 += ic; + assert(c3.real() == 4); + assert(c3.imag() == 6); + + c3 = c; + std::complex fc(1, 1); + c3 += fc; + assert(c3.real() == 4); + assert(c3.imag() == 6); + return true; } int main(int, char**) @@ -51,5 +50,11 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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& operator+=(const T& rhs); +// complex& operator+=(const T& rhs); // constexpr in C++20 #include #include @@ -16,21 +16,20 @@ #include "test_macros.h" template -void -test() -{ - std::complex c; - assert(c.real() == 0); - assert(c.imag() == 0); - c += 1.5; - assert(c.real() == 1.5); - assert(c.imag() == 0); - c += 1.5; - assert(c.real() == 3); - assert(c.imag() == 0); - c += -1.5; - assert(c.real() == 1.5); - assert(c.imag() == 0); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex c; + assert(c.real() == 0); + assert(c.imag() == 0); + c += 1.5; + assert(c.real() == 1.5); + assert(c.imag() == 0); + c += 1.5; + assert(c.real() == 3); + assert(c.imag() == 0); + c += -1.5; + assert(c.real() == 1.5); + assert(c.imag() == 0); + return true; } int main(int, char**) @@ -39,5 +38,11 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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& operator*=(const complex& rhs); +// complex& operator*=(const complex& rhs); // constexpr in C++20 #include #include @@ -16,33 +16,32 @@ #include "test_macros.h" template -void -test() -{ - std::complex c(1); - const std::complex c2(1.5, 2.5); - assert(c.real() == 1); - assert(c.imag() == 0); - c *= c2; - assert(c.real() == 1.5); - assert(c.imag() == 2.5); - c *= c2; - assert(c.real() == -4); - assert(c.imag() == 7.5); - - std::complex c3; - - c3 = c; - std::complex ic (1,1); - c3 *= ic; - assert(c3.real() == -11.5); - assert(c3.imag() == 3.5); - - c3 = c; - std::complex fc (1,1); - c3 *= fc; - assert(c3.real() == -11.5); - assert(c3.imag() == 3.5); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex c(1); + const std::complex c2(1.5, 2.5); + assert(c.real() == 1); + assert(c.imag() == 0); + c *= c2; + assert(c.real() == 1.5); + assert(c.imag() == 2.5); + c *= c2; + assert(c.real() == -4); + assert(c.imag() == 7.5); + + std::complex c3; + + c3 = c; + std::complex ic(1, 1); + c3 *= ic; + assert(c3.real() == -11.5); + assert(c3.imag() == 3.5); + + c3 = c; + std::complex fc(1, 1); + c3 *= fc; + assert(c3.real() == -11.5); + assert(c3.imag() == 3.5); + return true; } int main(int, char**) @@ -51,5 +50,11 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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& operator*=(const T& rhs); +// complex& operator*=(const T& rhs); // constexpr in C++20 #include #include @@ -16,25 +16,24 @@ #include "test_macros.h" template -void -test() -{ - std::complex c(1); - assert(c.real() == 1); - assert(c.imag() == 0); - c *= 1.5; - assert(c.real() == 1.5); - assert(c.imag() == 0); - c *= 1.5; - assert(c.real() == 2.25); - assert(c.imag() == 0); - c *= -1.5; - assert(c.real() == -3.375); - assert(c.imag() == 0); - c.imag(2); - c *= 1.5; - assert(c.real() == -5.0625); - assert(c.imag() == 3); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex c(1); + assert(c.real() == 1); + assert(c.imag() == 0); + c *= 1.5; + assert(c.real() == 1.5); + assert(c.imag() == 0); + c *= 1.5; + assert(c.real() == 2.25); + assert(c.imag() == 0); + c *= -1.5; + assert(c.real() == -3.375); + assert(c.imag() == 0); + c.imag(2); + c *= 1.5; + assert(c.real() == -5.0625); + assert(c.imag() == 3); + return true; } int main(int, char**) @@ -43,5 +42,11 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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 @@ // -// 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 #include @@ -17,9 +17,7 @@ #include "test_macros.h" template -void -test_constexpr() -{ +TEST_CONSTEXPR_CXX20 void test_constexpr() { #if TEST_STD_VER > 11 constexpr std::complex c1; static_assert(c1.real() == 0, ""); @@ -34,34 +32,38 @@ } template -void -test() -{ - std::complex c; - assert(c.real() == 0); - assert(c.imag() == 0); - c.real(3.5); - assert(c.real() == 3.5); - assert(c.imag() == 0); - c.imag(4.5); - assert(c.real() == 3.5); - assert(c.imag() == 4.5); - c.real(-4.5); - assert(c.real() == -4.5); - assert(c.imag() == 4.5); - c.imag(-5.5); - assert(c.real() == -4.5); - assert(c.imag() == -5.5); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex c; + assert(c.real() == 0); + assert(c.imag() == 0); + c.real(3.5); + assert(c.real() == 3.5); + assert(c.imag() == 0); + c.imag(4.5); + assert(c.real() == 3.5); + assert(c.imag() == 4.5); + c.real(-4.5); + assert(c.real() == -4.5); + assert(c.imag() == 4.5); + c.imag(-5.5); + assert(c.real() == -4.5); + assert(c.imag() == -5.5); - test_constexpr (); + test_constexpr(); + return true; } -int main(int, char**) -{ - test(); - test(); - test(); - test_constexpr (); +int main(int, char**) { + test(); + test(); + test(); + test_constexpr(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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,7 @@ // template // complex -// operator/(const complex& lhs, const complex& rhs); +// operator/(const complex& lhs, const complex& rhs); // constexpr in C++20 #include #include @@ -19,135 +19,126 @@ #include "../cases.h" template -void -test(const std::complex& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs / rhs == x); +TEST_CONSTEXPR_CXX20 bool test(const std::complex& lhs, + const std::complex& rhs, std::complex x) { + assert(lhs / rhs == x); + return true; } template -void -test() -{ - std::complex lhs(-4.0, 7.5); - std::complex rhs(1.5, 2.5); - std::complex x(1.5, 2.5); - test(lhs, rhs, x); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex lhs(-4.0, 7.5); + std::complex rhs(1.5, 2.5); + std::complex x(1.5, 2.5); + test(lhs, rhs, x); + return true; } -void 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 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; - } +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 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; + } } + } + return true; } int main(int, char**) @@ -157,5 +148,12 @@ test(); test_edges(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + 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 --- 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 // complex -// operator/(const complex& lhs, const T& rhs); +// operator/(const complex& lhs, const T& rhs); // constexpr in C++20 #include #include @@ -18,27 +18,31 @@ #include "test_macros.h" template -void -test(const std::complex& lhs, const T& rhs, std::complex x) -{ - assert(lhs / rhs == x); +TEST_CONSTEXPR_CXX20 bool test(const std::complex& lhs, const T& rhs, + std::complex x) { + assert(lhs / rhs == x); + return true; } template -void -test() -{ - std::complex lhs(-4.0, 7.5); - T rhs(2); - std::complex x(-2, 3.75); - test(lhs, rhs, x); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex lhs(-4.0, 7.5); + T rhs(2); + std::complex x(-2, 3.75); + test(lhs, rhs, x); + return true; } -int main(int, char**) -{ - test(); - test(); - test(); +int main(int, char**) { + test(); + test(); + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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,7 @@ #include "test_macros.h" template -void -test_constexpr() -{ -#if TEST_STD_VER > 11 - { - constexpr std::complex lhs(1.5, 2.5); - constexpr std::complex rhs(1.5, -2.5); - static_assert( !(lhs == rhs), ""); - } - { - constexpr std::complex lhs(1.5, 2.5); - constexpr std::complex rhs(1.5, 2.5); - static_assert(lhs == rhs, ""); - } -#endif -} - -template -void +TEST_CONSTEXPR_CXX20 bool test() { { @@ -49,7 +31,7 @@ std::complex rhs(1.5, 2.5); assert(lhs == rhs); } - test_constexpr (); + return true; } int main(int, char**) @@ -57,7 +39,11 @@ test(); test(); test(); -// test_constexpr (); +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif - return 0; + 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 --- 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,7 +18,7 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 void test_constexpr() { #if TEST_STD_VER > 11 @@ -46,7 +46,7 @@ } template -void +TEST_CONSTEXPR_CXX20 bool test() { { @@ -71,14 +71,20 @@ } test_constexpr (); - } + return true; +} int main(int, char**) { test(); test(); test(); -// test_constexpr (); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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 // complex -// operator-(const complex& lhs, const complex& rhs); +// operator-(const complex& lhs, const complex& rhs); // constexpr in C++20 #include #include @@ -18,35 +18,40 @@ #include "test_macros.h" template -void -test(const std::complex& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs - rhs == x); +TEST_CONSTEXPR_CXX20 bool test(const std::complex& lhs, + const std::complex& rhs, std::complex x) { + assert(lhs - rhs == x); + return true; } template -void -test() -{ - { +TEST_CONSTEXPR_CXX20 bool test() { + { std::complex lhs(1.5, 2.5); std::complex rhs(3.5, 4.5); std::complex x(-2.0, -2.0); test(lhs, rhs, x); - } + } { std::complex lhs(1.5, -2.5); std::complex rhs(-3.5, 4.5); std::complex x(5.0, -7.0); test(lhs, rhs, x); } + return true; } -int main(int, char**) -{ - test(); - test(); - test(); +int main(int, char**) { + test(); + test(); + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + // static_assert(test()); +#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 --- 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 // complex -// operator-(const complex& lhs, const T& rhs); +// operator-(const complex& lhs, const T& rhs); // constexpr in C++20 #include #include @@ -18,35 +18,40 @@ #include "test_macros.h" template -void -test(const std::complex& lhs, const T& rhs, std::complex x) -{ - assert(lhs - rhs == x); +TEST_CONSTEXPR_CXX20 bool test(const std::complex& lhs, const T& rhs, + std::complex x) { + assert(lhs - rhs == x); + return true; } template -void -test() -{ - { +TEST_CONSTEXPR_CXX20 bool test() { + { std::complex lhs(1.5, 2.5); T rhs(3.5); std::complex x(-2.0, 2.5); test(lhs, rhs, x); - } + } { std::complex lhs(1.5, -2.5); T rhs(-3.5); std::complex x(5.0, -2.5); test(lhs, rhs, x); } + return true; } -int main(int, char**) -{ - test(); - test(); - test(); +int main(int, char**) { + test(); + test(); + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + // static_assert(test()); +#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 --- 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,7 +18,7 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 void test_constexpr() { #if TEST_STD_VER > 11 @@ -37,7 +37,7 @@ template -void +TEST_CONSTEXPR_CXX20 bool test() { { @@ -52,14 +52,20 @@ } test_constexpr (); - } + return true; +} int main(int, char**) { test(); test(); test(); -// test_constexpr (); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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,7 +18,7 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 void test_constexpr() { #if TEST_STD_VER > 11 @@ -46,7 +46,7 @@ } template -void +TEST_CONSTEXPR_CXX20 bool test() { { @@ -71,6 +71,7 @@ } test_constexpr (); + return true; } int main(int, char**) @@ -78,7 +79,12 @@ test(); test(); test(); -// test_constexpr (); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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 // complex -// operator+(const complex& lhs, const complex& rhs); +// operator+(const complex& lhs, const complex& rhs); // constexpr in C++20 #include #include @@ -18,35 +18,41 @@ #include "test_macros.h" template -void -test(const std::complex& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs + rhs == x); +TEST_CONSTEXPR_CXX20 bool test(const std::complex& lhs, + const std::complex& rhs, std::complex x) { + assert(lhs + rhs == x); + return true; } template -void -test() -{ - { +TEST_CONSTEXPR_CXX20 bool test() { + { std::complex lhs(1.5, 2.5); std::complex rhs(3.5, 4.5); std::complex x(5.0, 7.0); test(lhs, rhs, x); - } + } { std::complex lhs(1.5, -2.5); std::complex rhs(-3.5, 4.5); std::complex x(-2.0, 2.0); test(lhs, rhs, x); } + + return true; } -int main(int, char**) -{ - test(); - test(); - test(); +int main(int, char**) { + test(); + test(); + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + // static_assert(test()); +#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 --- 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 // complex -// operator+(const complex& lhs, const T& rhs); +// operator+(const complex& lhs, const T& rhs); // constexpr in C++20 #include #include @@ -18,35 +18,41 @@ #include "test_macros.h" template -void -test(const std::complex& lhs, const T& rhs, std::complex x) -{ - assert(lhs + rhs == x); +TEST_CONSTEXPR_CXX20 bool test(const std::complex& lhs, const T& rhs, + std::complex x) { + assert(lhs + rhs == x); + return true; } template -void -test() -{ - { +TEST_CONSTEXPR_CXX20 bool test() { + { std::complex lhs(1.5, 2.5); T rhs(3.5); std::complex x(5.0, 2.5); test(lhs, rhs, x); - } + } { std::complex lhs(1.5, -2.5); T rhs(-3.5); std::complex x(-2.0, -2.5); test(lhs, rhs, x); } + + return true; } -int main(int, char**) -{ - test(); - test(); - test(); +int main(int, char**) { + test(); + test(); + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + // static_assert(test()); +#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 --- 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,7 @@ // template // complex -// operator*(const complex& lhs, const complex& rhs); +// operator*(const complex& lhs, const complex& rhs); // constexpr in C++20 #include #include @@ -19,25 +19,24 @@ #include "../cases.h" template -void -test(const std::complex& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs * rhs == x); +TEST_CONSTEXPR_CXX20 bool test(const std::complex& lhs, + const std::complex& rhs, std::complex x) { + assert(lhs * rhs == x); + return true; } template -void -test() -{ - std::complex lhs(1.5, 2.5); - std::complex rhs(1.5, 2.5); - std::complex x(-4.0, 7.5); - test(lhs, rhs, x); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex lhs(1.5, 2.5); + std::complex rhs(1.5, 2.5); + std::complex x(-4.0, 7.5); + test(lhs, rhs, x); + return true; } // test edges -void test_edges() +TEST_CONSTEXPR_CXX20 bool test_edges() { const unsigned N = sizeof(testcases) / sizeof(testcases[0]); for (unsigned i = 0; i < N; ++i) @@ -150,6 +149,7 @@ } } } + return true; } int main(int, char**) @@ -159,5 +159,13 @@ test(); test_edges(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + // static_assert(test()); + 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 --- 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 // complex -// operator*(const complex& lhs, const T& rhs); +// operator*(const complex& lhs, const T& rhs); // constexpr in C++20 #include #include @@ -18,27 +18,32 @@ #include "test_macros.h" template -void -test(const std::complex& lhs, const T& rhs, std::complex x) -{ - assert(lhs * rhs == x); +TEST_CONSTEXPR_CXX20 bool test(const std::complex& lhs, const T& rhs, + std::complex x) { + assert(lhs * rhs == x); + return true; } template -void -test() -{ - std::complex lhs(1.5, 2.5); - T rhs(1.5); - std::complex x(2.25, 3.75); - test(lhs, rhs, x); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex lhs(1.5, 2.5); + T rhs(1.5); + std::complex x(2.25, 3.75); + test(lhs, rhs, x); + return true; } -int main(int, char**) -{ - test(); - test(); - test(); +int main(int, char**) { + test(); + test(); + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + // static_assert(test()); +#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 --- 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 // complex -// operator/(const T& lhs, const complex& rhs); +// operator/(const T& lhs, const complex& rhs); // constexpr in C++20 #include #include @@ -18,27 +18,31 @@ #include "test_macros.h" template -void -test(const T& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs / rhs == x); +TEST_CONSTEXPR_CXX20 bool test(const T& lhs, const std::complex& rhs, + std::complex x) { + assert(lhs / rhs == x); + return true; } template -void -test() -{ - T lhs(-8.5); - std::complex rhs(1.5, 2.5); - std::complex x(-1.5, 2.5); - test(lhs, rhs, x); +TEST_CONSTEXPR_CXX20 bool test() { + T lhs(-8.5); + std::complex rhs(1.5, 2.5); + std::complex x(-1.5, 2.5); + test(lhs, rhs, x); + return true; } -int main(int, char**) -{ - test(); - test(); - test(); +int main(int, char**) { + test(); + test(); + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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,7 +18,7 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 void test_constexpr() { #if TEST_STD_VER > 11 @@ -46,7 +46,7 @@ } template -void +TEST_CONSTEXPR_CXX20 bool test() { { @@ -71,6 +71,7 @@ } test_constexpr (); + return true; } int main(int, char**) @@ -78,7 +79,12 @@ test(); test(); test(); -// test_constexpr(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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 // complex -// operator-(const T& lhs, const complex& rhs); +// operator-(const T& lhs, const complex& rhs); // constexpr in C++20 #include #include @@ -18,35 +18,40 @@ #include "test_macros.h" template -void -test(const T& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs - rhs == x); +TEST_CONSTEXPR_CXX20 bool test(const T& lhs, const std::complex& rhs, + std::complex x) { + assert(lhs - rhs == x); + return true; } template -void -test() -{ - { +TEST_CONSTEXPR_CXX20 bool test() { + { T lhs(1.5); std::complex rhs(3.5, 4.5); std::complex x(-2.0, -4.5); test(lhs, rhs, x); - } + } { T lhs(1.5); std::complex rhs(-3.5, 4.5); std::complex x(5.0, -4.5); test(lhs, rhs, x); } + return true; } -int main(int, char**) -{ - test(); - test(); - test(); +int main(int, char**) { + test(); + test(); + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + // static_assert(test()); +#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 --- 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,7 +18,7 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 void test_constexpr() { #if TEST_STD_VER > 11 @@ -46,7 +46,7 @@ } template -void +TEST_CONSTEXPR_CXX20 bool test() { { @@ -71,14 +71,20 @@ } test_constexpr (); - } + return true; +} int main(int, char**) { test(); test(); test(); -// test_constexpr(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#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 --- 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 // complex -// operator+(const T& lhs, const complex& rhs); +// operator+(const T& lhs, const complex& rhs); // constexpr in C++20 #include #include @@ -18,35 +18,40 @@ #include "test_macros.h" template -void -test(const T& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs + rhs == x); +TEST_CONSTEXPR_CXX20 bool test(const T& lhs, const std::complex& rhs, + std::complex x) { + assert(lhs + rhs == x); + return true; } template -void -test() -{ - { +TEST_CONSTEXPR_CXX20 bool test() { + { T lhs(1.5); std::complex rhs(3.5, 4.5); std::complex x(5.0, 4.5); test(lhs, rhs, x); - } + } { T lhs(1.5); std::complex rhs(-3.5, 4.5); std::complex x(-2.0, 4.5); test(lhs, rhs, x); } + return true; } -int main(int, char**) -{ - test(); - test(); - test(); +int main(int, char**) { + test(); + test(); + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + // static_assert(test()); +#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 --- 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 // complex -// operator*(const T& lhs, const complex& rhs); +// operator*(const T& lhs, const complex& rhs); // constexpr in C++20 #include #include @@ -18,27 +18,32 @@ #include "test_macros.h" template -void -test(const T& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs * rhs == x); +TEST_CONSTEXPR_CXX20 bool test(const T& lhs, const std::complex& rhs, + std::complex x) { + assert(lhs * rhs == x); + return true; } template -void -test() -{ - T lhs(1.5); - std::complex rhs(1.5, 2.5); - std::complex x(2.25, 3.75); - test(lhs, rhs, x); +TEST_CONSTEXPR_CXX20 bool test() { + T lhs(1.5); + std::complex rhs(1.5, 2.5); + std::complex x(2.25, 3.75); + test(lhs, rhs, x); + return true; } -int main(int, char**) -{ - test(); - test(); - test(); +int main(int, char**) { + test(); + test(); + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + // static_assert(test()); +#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 --- 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 // complex -// operator-(const complex& lhs); +// operator-(const complex& lhs); // constexpr in C++20 #include #include @@ -18,15 +18,14 @@ #include "test_macros.h" template -void -test() -{ - std::complex z(1.5, 2.5); - assert(z.real() == 1.5); - assert(z.imag() == 2.5); - std::complex c = -z; - assert(c.real() == -1.5); - assert(c.imag() == -2.5); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex z(1.5, 2.5); + assert(z.real() == T(1.5)); + assert(z.imag() == T(2.5)); + std::complex c = -z; + assert(c.real() == T(-1.5)); + assert(c.imag() == T(-2.5)); + return true; } int main(int, char**) @@ -35,5 +34,13 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + // TODO: warnings + // static_assert(test()); +#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 --- 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 // complex -// operator+(const complex&); +// operator+(const complex&); // constexpr in C++20 #include #include @@ -18,15 +18,14 @@ #include "test_macros.h" template -void -test() -{ - std::complex z(1.5, 2.5); - assert(z.real() == 1.5); - assert(z.imag() == 2.5); - std::complex c = +z; - assert(c.real() == 1.5); - assert(c.imag() == 2.5); +TEST_CONSTEXPR_CXX20 bool test() { + std::complex z(1.5, 2.5); + assert(z.real() == T(1.5)); + assert(z.imag() == T(2.5)); + std::complex c = +z; + assert(c.real() == T(1.5)); + assert(c.imag() == T(2.5)); + return true; } int main(int, char**) @@ -35,5 +34,13 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + // TODO: warnings + // static_assert(test()); +#endif + + return 0; } diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -481,6 +481,12 @@ "values": { "c++2a": int(201907) }, "headers": ["memory"] }, + {"name": "__cpp_lib_constexpr_complex", + "values": { + "c++2a": int(201711), + }, + "headers": ["complex"], + }, ]], key=lambda tc: tc["name"]) # Map from each header to the Lit annotations that should be used for diff --git a/libcxx/www/cxx2a_status.html b/libcxx/www/cxx2a_status.html --- a/libcxx/www/cxx2a_status.html +++ b/libcxx/www/cxx2a_status.html @@ -60,7 +60,7 @@ P0020R6LWGFloating Point AtomicAlbuquerque P0053R7LWGC++ Synchronized Buffered OstreamAlbuquerque P0202R3LWGAdd constexpr modifiers to functions in <algorithm> and <utility> HeadersAlbuquerqueIn Progress7.0 - P0415R1LWGConstexpr for std::complexAlbuquerqueIn Progress7.0 + P0415R1LWGConstexpr for std::complexAlbuquerqueComplete11.0 P0439R0LWGMake std::memory_order a scoped enumerationAlbuquerqueComplete P0457R2LWGString Prefix and Suffix CheckingAlbuquerqueComplete6.0 P0550R2LWGTransformation Trait remove_cvrefAlbuquerqueComplete6.0