diff --git a/stl/inc/charconv b/stl/inc/charconv index 66fd8c9f837..11ab046a08c 100644 --- a/stl/inc/charconv +++ b/stl/inc/charconv @@ -193,17 +193,6 @@ inline to_chars_result to_chars(char* const _First, char* const _Last, const uns to_chars_result to_chars(char* _First, char* _Last, bool _Value, int _Base = 10) = delete; -// FUNCTION TEMPLATE _Bit_cast -template && is_trivially_copyable_v<_From>, int> = - 0> -_NODISCARD /*constexpr*/ _To _Bit_cast(const _From& _From_obj) noexcept { - _To _To_obj; // assumes default-init - _CSTD memcpy(_STD addressof(_To_obj), _STD addressof(_From_obj), sizeof(_To)); - return _To_obj; -} - - // STRUCT from_chars_result struct from_chars_result { const char* ptr; diff --git a/stl/inc/complex b/stl/inc/complex index 01986df49ea..dc9ced16f3b 100644 --- a/stl/inc/complex +++ b/stl/inc/complex @@ -9,6 +9,7 @@ #include #if _STL_COMPILER_PREPROCESSOR #include +#include #include #include @@ -57,11 +58,11 @@ class complex; template class _Ctraits { public: - static _Ty _Flt_eps() { // get epsilon + static constexpr _Ty _Flt_eps() { // get epsilon return numeric_limits<_Ty>::epsilon(); } - static _Ty _Flt_max() { + static constexpr _Ty _Flt_max() { return (numeric_limits<_Ty>::max)(); } @@ -76,21 +77,23 @@ public: return _Ans; } - static _Ty _Infv() { // return infinity + static constexpr _Ty _Infv() { // return infinity return numeric_limits<_Ty>::infinity(); } static bool _Isinf(_Ty _Left) { // test for infinity - double _Tmp = static_cast(_Left); - return _CSTD _Dtest(&_Tmp) == _INFCODE; + const auto _Tmp = static_cast(_Left); + const auto _Uint = _Bit_cast(_Tmp); + return (_Uint & 0x7fffffffffffffffU) == 0x7ff0000000000000U; } - static bool _Isnan(_Ty _Left) { - double _Tmp = static_cast(_Left); - return _CSTD _Dtest(&_Tmp) == _NANCODE; + static _CONSTEXPR20 bool _Isnan(_Ty _Left) { + const auto _Tmp = static_cast(_Left); + const auto _Uint = _Bit_cast(_Tmp); + return (_Uint & 0x7fffffffffffffffU) > 0x7ff0000000000000U; } - static _Ty _Nanv() { // return NaN + static constexpr _Ty _Nanv() { // return NaN return numeric_limits<_Ty>::quiet_NaN(); } @@ -175,12 +178,12 @@ class _Ctraits { public: using _Ty = long double; - static _Ty _Flt_eps() { // get epsilon - return LDBL_EPSILON; + static constexpr _Ty _Flt_eps() { // get epsilon + return numeric_limits::epsilon(); } - static _Ty _Flt_max() { - return LDBL_MAX; + static constexpr _Ty _Flt_max() { + return (numeric_limits::max)(); } static _Ty _Cosh(_Ty _Left, _Ty _Right) { // return cosh(_Left) * _Right @@ -191,19 +194,21 @@ public: return _CSTD _LExp(_Pleft, _Right, _Exponent); } - static _Ty _Infv() { // return infinity + static constexpr _Ty _Infv() { // return infinity return numeric_limits::infinity(); } static bool _Isinf(_Ty _Left) { // test for infinity - return _CSTD _LDtest(&_Left) == _INFCODE; + const auto _Uint = _Bit_cast(_Left); + return (_Uint & 0x7fffffffffffffffU) == 0x7ff0000000000000U; } - static bool _Isnan(_Ty _Left) { - return _CSTD _LDtest(&_Left) == _NANCODE; + static _CONSTEXPR20 bool _Isnan(_Ty _Left) { + const auto _Uint = _Bit_cast(_Left); + return (_Uint & 0x7fffffffffffffffU) > 0x7ff0000000000000U; } - static _Ty _Nanv() { // return NaN + static constexpr _Ty _Nanv() { // return NaN return numeric_limits::quiet_NaN(); } @@ -288,12 +293,12 @@ class _Ctraits { public: using _Ty = double; - static _Ty _Flt_eps() { // get epsilon - return DBL_EPSILON; + static constexpr _Ty _Flt_eps() { // get epsilon + return numeric_limits::epsilon(); } - static _Ty _Flt_max() { - return DBL_MAX; + static constexpr _Ty _Flt_max() { + return (numeric_limits::max)(); } static _Ty _Cosh(_Ty _Left, _Ty _Right) { // return cosh(_Left) * _Right @@ -304,19 +309,21 @@ public: return _CSTD _Exp(_Pleft, _Right, _Exponent); } - static _Ty _Infv() { // return infinity + static constexpr _Ty _Infv() { // return infinity return numeric_limits::infinity(); } static bool _Isinf(_Ty _Left) { // test for infinity - return _CSTD _Dtest(&_Left) == _INFCODE; + const auto _Uint = _Bit_cast(_Left); + return (_Uint & 0x7fffffffffffffffU) == 0x7ff0000000000000U; } - static bool _Isnan(_Ty _Left) { - return _CSTD _Dtest(&_Left) == _NANCODE; + static _CONSTEXPR20 bool _Isnan(_Ty _Left) { + const auto _Uint = _Bit_cast(_Left); + return (_Uint & 0x7fffffffffffffffU) > 0x7ff0000000000000U; } - static _Ty _Nanv() { // return NaN + static constexpr _Ty _Nanv() { // return NaN return numeric_limits::quiet_NaN(); } @@ -408,12 +415,12 @@ class _Ctraits { public: using _Ty = float; - static _Ty _Flt_eps() { // get epsilon - return FLT_EPSILON; + static constexpr _Ty _Flt_eps() { // get epsilon + return numeric_limits::epsilon(); } - static _Ty _Flt_max() { - return FLT_MAX; + static constexpr _Ty _Flt_max() { + return (numeric_limits::max)(); } static _Ty _Cosh(_Ty _Left, _Ty _Right) { // return cosh(_Left) * _Right @@ -424,19 +431,21 @@ public: return _CSTD _FExp(_Pleft, _Right, _Exponent); } - static _Ty _Infv() { // return infinity + static constexpr _Ty _Infv() { // return infinity return numeric_limits::infinity(); } static bool _Isinf(_Ty _Left) { // test for infinity - return _CSTD _FDtest(&_Left) == _INFCODE; + const auto _Uint = _Bit_cast(_Left); + return (_Uint & 0x7fffffffU) == 0x7f800000U; } - static bool _Isnan(_Ty _Left) { - return _CSTD _FDtest(&_Left) == _NANCODE; + static _CONSTEXPR20 bool _Isnan(_Ty _Left) { + const auto _Uint = _Bit_cast(_Left); + return (_Uint & 0x7fffffffU) > 0x7f800000U; } - static _Ty _Nanv() { // return NaN + static constexpr _Ty _Nanv() { // return NaN return numeric_limits::quiet_NaN(); } @@ -531,12 +540,12 @@ public: constexpr _Complex_base(const _Ty& _Realval, const _Ty& _Imagval) : _Valbase{{_Realval, _Imagval}} {} - _Ty real(const _Ty& _Right) { // set real component - return this->_Val[_RE] = _Right; + _CONSTEXPR20 void real(const _Ty& _Right) { // set real component + this->_Val[_RE] = _Right; } - _Ty imag(const _Ty& _Right) { // set imaginary component - return this->_Val[_IM] = _Right; + _CONSTEXPR20 void imag(const _Ty& _Right) { // set imaginary component + this->_Val[_IM] = _Right; } _NODISCARD constexpr _Ty real() const { // return real component @@ -549,19 +558,19 @@ public: protected: template - void _Add(const complex<_Other>& _Right) { + _CONSTEXPR20 void _Add(const complex<_Other>& _Right) { this->_Val[_RE] = this->_Val[_RE] + static_cast<_Ty>(_Right.real()); this->_Val[_IM] = this->_Val[_IM] + static_cast<_Ty>(_Right.imag()); } template - void _Sub(const complex<_Other>& _Right) { + _CONSTEXPR20 void _Sub(const complex<_Other>& _Right) { this->_Val[_RE] = this->_Val[_RE] - static_cast<_Ty>(_Right.real()); this->_Val[_IM] = this->_Val[_IM] - static_cast<_Ty>(_Right.imag()); } template - void _Mul(const complex<_Other>& _Right) { + _CONSTEXPR20 void _Mul(const complex<_Other>& _Right) { _Ty _Rightreal = static_cast<_Ty>(_Right.real()); _Ty _Rightimag = static_cast<_Ty>(_Right.imag()); @@ -571,7 +580,7 @@ protected: } template - void _Div(const complex<_Other>& _Right) { + _CONSTEXPR20 void _Div(const complex<_Other>& _Right) { using _Myctraits = _Ctraits<_Ty>; _Ty _Rightreal = static_cast<_Ty>(_Right.real()); @@ -635,82 +644,81 @@ public: : _Complex_base( static_cast(_Right._Val[_RE]), static_cast(_Right._Val[_IM])) {} - complex<_Ty>& operator=(const _Ty& _Right) { - + _CONSTEXPR20 complex& operator=(const _Ty& _Right) { _Val[_RE] = _Right; _Val[_IM] = 0; return *this; } - complex& operator+=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator+=(const _Ty& _Right) { _Val[_RE] = _Val[_RE] + _Right; return *this; } - complex& operator-=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator-=(const _Ty& _Right) { _Val[_RE] = _Val[_RE] - _Right; return *this; } - complex& operator*=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator*=(const _Ty& _Right) { _Val[_RE] = _Val[_RE] * _Right; _Val[_IM] = _Val[_IM] * _Right; return *this; } - complex& operator/=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator/=(const _Ty& _Right) { _Val[_RE] = _Val[_RE] / _Right; _Val[_IM] = _Val[_IM] / _Right; return *this; } - complex& operator+=(const complex& _Right) { + _CONSTEXPR20 complex& operator+=(const complex& _Right) { this->_Add(_Right); return *this; } - complex& operator-=(const complex& _Right) { + _CONSTEXPR20 complex& operator-=(const complex& _Right) { this->_Sub(_Right); return *this; } - complex& operator*=(const complex& _Right) { + _CONSTEXPR20 complex& operator*=(const complex& _Right) { this->_Mul(_Right); return *this; } - complex& operator/=(const complex& _Right) { + _CONSTEXPR20 complex& operator/=(const complex& _Right) { this->_Div(_Right); return *this; } template - complex& operator=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator=(const complex<_Other>& _Right) { _Val[_RE] = static_cast<_Ty>(_Right._Val[_RE]); _Val[_IM] = static_cast<_Ty>(_Right._Val[_IM]); return *this; } template - complex& operator+=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator+=(const complex<_Other>& _Right) { this->_Add(_Right); return *this; } template - complex& operator-=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator-=(const complex<_Other>& _Right) { this->_Sub(_Right); return *this; } template - complex& operator*=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator*=(const complex<_Other>& _Right) { this->_Mul(_Right); return *this; } template - complex& operator/=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator/=(const complex<_Other>& _Right) { this->_Div(_Right); return *this; } @@ -735,82 +743,81 @@ public: : _Complex_base( static_cast(_Right._Val[_RE]), static_cast(_Right._Val[_IM])) {} - complex<_Ty>& operator=(const _Ty& _Right) { - + _CONSTEXPR20 complex& operator=(const _Ty& _Right) { _Val[_RE] = _Right; _Val[_IM] = 0; return *this; } - complex& operator+=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator+=(const _Ty& _Right) { _Val[_RE] = _Val[_RE] + _Right; return *this; } - complex& operator-=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator-=(const _Ty& _Right) { _Val[_RE] = _Val[_RE] - _Right; return *this; } - complex& operator*=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator*=(const _Ty& _Right) { _Val[_RE] = _Val[_RE] * _Right; _Val[_IM] = _Val[_IM] * _Right; return *this; } - complex& operator/=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator/=(const _Ty& _Right) { _Val[_RE] = _Val[_RE] / _Right; _Val[_IM] = _Val[_IM] / _Right; return *this; } - complex& operator+=(const complex& _Right) { + _CONSTEXPR20 complex& operator+=(const complex& _Right) { this->_Add(_Right); return *this; } - complex& operator-=(const complex& _Right) { + _CONSTEXPR20 complex& operator-=(const complex& _Right) { this->_Sub(_Right); return *this; } - complex& operator*=(const complex& _Right) { + _CONSTEXPR20 complex& operator*=(const complex& _Right) { this->_Mul(_Right); return *this; } - complex& operator/=(const complex& _Right) { + _CONSTEXPR20 complex& operator/=(const complex& _Right) { this->_Div(_Right); return *this; } template - complex& operator=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator=(const complex<_Other>& _Right) { _Val[_RE] = static_cast<_Ty>(_Right._Val[_RE]); _Val[_IM] = static_cast<_Ty>(_Right._Val[_IM]); return *this; } template - complex& operator+=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator+=(const complex<_Other>& _Right) { this->_Add(_Right); return *this; } template - complex& operator-=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator-=(const complex<_Other>& _Right) { this->_Sub(_Right); return *this; } template - complex& operator*=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator*=(const complex<_Other>& _Right) { this->_Mul(_Right); return *this; } template - complex& operator/=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator/=(const complex<_Other>& _Right) { this->_Div(_Right); return *this; } @@ -831,82 +838,81 @@ public: constexpr complex(const _Lcomplex_value& _Right) : _Complex_base(_Right._Val[_RE], _Right._Val[_IM]) {} - complex<_Ty>& operator=(const _Ty& _Right) { - + _CONSTEXPR20 complex& operator=(const _Ty& _Right) { _Val[_RE] = _Right; _Val[_IM] = 0; return *this; } - complex& operator+=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator+=(const _Ty& _Right) { _Val[_RE] = _Val[_RE] + _Right; return *this; } - complex& operator-=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator-=(const _Ty& _Right) { _Val[_RE] = _Val[_RE] - _Right; return *this; } - complex& operator*=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator*=(const _Ty& _Right) { _Val[_RE] = _Val[_RE] * _Right; _Val[_IM] = _Val[_IM] * _Right; return *this; } - complex& operator/=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator/=(const _Ty& _Right) { _Val[_RE] = _Val[_RE] / _Right; _Val[_IM] = _Val[_IM] / _Right; return *this; } - complex& operator+=(const complex& _Right) { + _CONSTEXPR20 complex& operator+=(const complex& _Right) { this->_Add(_Right); return *this; } - complex& operator-=(const complex& _Right) { + _CONSTEXPR20 complex& operator-=(const complex& _Right) { this->_Sub(_Right); return *this; } - complex& operator*=(const complex& _Right) { + _CONSTEXPR20 complex& operator*=(const complex& _Right) { this->_Mul(_Right); return *this; } - complex& operator/=(const complex& _Right) { + _CONSTEXPR20 complex& operator/=(const complex& _Right) { this->_Div(_Right); return *this; } template - complex& operator=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator=(const complex<_Other>& _Right) { _Val[_RE] = static_cast<_Ty>(_Right._Val[_RE]); _Val[_IM] = static_cast<_Ty>(_Right._Val[_IM]); return *this; } template - complex& operator+=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator+=(const complex<_Other>& _Right) { this->_Add(_Right); return *this; } template - complex& operator-=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator-=(const complex<_Other>& _Right) { this->_Sub(_Right); return *this; } template - complex& operator*=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator*=(const complex<_Other>& _Right) { this->_Mul(_Right); return *this; } template - complex& operator/=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator/=(const complex<_Other>& _Right) { this->_Div(_Right); return *this; } @@ -939,7 +945,7 @@ public: constexpr complex(const _Ty& _Realval = _Ty(), const _Ty& _Imagval = _Ty()) : _Mybase(_Realval, _Imagval) {} - complex& operator=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator=(const _Ty& _Right) { this->_Val[_RE] = _Right; this->_Val[_IM] = _Ty(); return *this; @@ -950,74 +956,74 @@ public: : _Mybase(static_cast<_Ty>(_Right.real()), static_cast<_Ty>(_Right.imag())) {} template - complex& operator=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator=(const complex<_Other>& _Right) { this->_Val[_RE] = static_cast<_Ty>(_Right.real()); this->_Val[_IM] = static_cast<_Ty>(_Right.imag()); return *this; } - complex& operator+=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator+=(const _Ty& _Right) { this->_Val[_RE] = this->_Val[_RE] + _Right; return *this; } - complex& operator-=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator-=(const _Ty& _Right) { this->_Val[_RE] = this->_Val[_RE] - _Right; return *this; } - complex& operator*=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator*=(const _Ty& _Right) { this->_Val[_RE] = this->_Val[_RE] * _Right; this->_Val[_IM] = this->_Val[_IM] * _Right; return *this; } - complex& operator/=(const _Ty& _Right) { + _CONSTEXPR20 complex& operator/=(const _Ty& _Right) { this->_Val[_RE] = this->_Val[_RE] / _Right; this->_Val[_IM] = this->_Val[_IM] / _Right; return *this; } - complex& operator+=(const complex& _Right) { + _CONSTEXPR20 complex& operator+=(const complex& _Right) { this->_Add(_Right); return *this; } - complex& operator-=(const complex& _Right) { + _CONSTEXPR20 complex& operator-=(const complex& _Right) { this->_Sub(_Right); return *this; } - complex& operator*=(const complex& _Right) { + _CONSTEXPR20 complex& operator*=(const complex& _Right) { this->_Mul(_Right); return *this; } - complex& operator/=(const complex& _Right) { + _CONSTEXPR20 complex& operator/=(const complex& _Right) { this->_Div(_Right); return *this; } template - complex& operator+=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator+=(const complex<_Other>& _Right) { this->_Add(_Right); return *this; } template - complex& operator-=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator-=(const complex<_Other>& _Right) { this->_Sub(_Right); return *this; } template - complex& operator*=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator*=(const complex<_Other>& _Right) { this->_Mul(_Right); return *this; } template - complex& operator/=(const complex<_Other>& _Right) { + _CONSTEXPR20 complex& operator/=(const complex<_Other>& _Right) { this->_Div(_Right); return *this; } @@ -1025,21 +1031,21 @@ public: // FUNCTION TEMPLATE operator+ template -_NODISCARD complex<_Ty> operator+(const complex<_Ty>& _Left, const complex<_Ty>& _Right) { +_NODISCARD _CONSTEXPR20 complex<_Ty> operator+(const complex<_Ty>& _Left, const complex<_Ty>& _Right) { complex<_Ty> _Tmp(_Left); _Tmp += _Right; return _Tmp; } template -_NODISCARD complex<_Ty> operator+(const complex<_Ty>& _Left, const _Ty& _Right) { +_NODISCARD _CONSTEXPR20 complex<_Ty> operator+(const complex<_Ty>& _Left, const _Ty& _Right) { complex<_Ty> _Tmp(_Left); _Tmp.real(_Tmp.real() + _Right); return _Tmp; } template -_NODISCARD complex<_Ty> operator+(const _Ty& _Left, const complex<_Ty>& _Right) { +_NODISCARD _CONSTEXPR20 complex<_Ty> operator+(const _Ty& _Left, const complex<_Ty>& _Right) { complex<_Ty> _Tmp(_Left); _Tmp += _Right; return _Tmp; @@ -1047,21 +1053,21 @@ _NODISCARD complex<_Ty> operator+(const _Ty& _Left, const complex<_Ty>& _Right) // FUNCTION TEMPLATE operator- template -_NODISCARD complex<_Ty> operator-(const complex<_Ty>& _Left, const complex<_Ty>& _Right) { +_NODISCARD _CONSTEXPR20 complex<_Ty> operator-(const complex<_Ty>& _Left, const complex<_Ty>& _Right) { complex<_Ty> _Tmp(_Left); _Tmp -= _Right; return _Tmp; } template -_NODISCARD complex<_Ty> operator-(const complex<_Ty>& _Left, const _Ty& _Right) { +_NODISCARD _CONSTEXPR20 complex<_Ty> operator-(const complex<_Ty>& _Left, const _Ty& _Right) { complex<_Ty> _Tmp(_Left); _Tmp.real(_Tmp.real() - _Right); return _Tmp; } template -_NODISCARD complex<_Ty> operator-(const _Ty& _Left, const complex<_Ty>& _Right) { +_NODISCARD _CONSTEXPR20 complex<_Ty> operator-(const _Ty& _Left, const complex<_Ty>& _Right) { complex<_Ty> _Tmp(_Left); _Tmp -= _Right; return _Tmp; @@ -1069,14 +1075,14 @@ _NODISCARD complex<_Ty> operator-(const _Ty& _Left, const complex<_Ty>& _Right) // FUNCTION TEMPLATE operator* template -_NODISCARD complex<_Ty> operator*(const complex<_Ty>& _Left, const complex<_Ty>& _Right) { +_NODISCARD _CONSTEXPR20 complex<_Ty> operator*(const complex<_Ty>& _Left, const complex<_Ty>& _Right) { complex<_Ty> _Tmp(_Left); _Tmp *= _Right; return _Tmp; } template -_NODISCARD complex<_Ty> operator*(const complex<_Ty>& _Left, const _Ty& _Right) { +_NODISCARD _CONSTEXPR20 complex<_Ty> operator*(const complex<_Ty>& _Left, const _Ty& _Right) { complex<_Ty> _Tmp(_Left); _Tmp.real(_Tmp.real() * _Right); _Tmp.imag(_Tmp.imag() * _Right); @@ -1084,7 +1090,7 @@ _NODISCARD complex<_Ty> operator*(const complex<_Ty>& _Left, const _Ty& _Right) } template -_NODISCARD complex<_Ty> operator*(const _Ty& _Left, const complex<_Ty>& _Right) { +_NODISCARD _CONSTEXPR20 complex<_Ty> operator*(const _Ty& _Left, const complex<_Ty>& _Right) { complex<_Ty> _Tmp(_Left); _Tmp *= _Right; return _Tmp; @@ -1092,14 +1098,14 @@ _NODISCARD complex<_Ty> operator*(const _Ty& _Left, const complex<_Ty>& _Right) // FUNCTION TEMPLATE operator/ template -_NODISCARD complex<_Ty> operator/(const complex<_Ty>& _Left, const complex<_Ty>& _Right) { +_NODISCARD _CONSTEXPR20 complex<_Ty> operator/(const complex<_Ty>& _Left, const complex<_Ty>& _Right) { complex<_Ty> _Tmp(_Left); _Tmp /= _Right; return _Tmp; } template -_NODISCARD complex<_Ty> operator/(const complex<_Ty>& _Left, const _Ty& _Right) { +_NODISCARD _CONSTEXPR20 complex<_Ty> operator/(const complex<_Ty>& _Left, const _Ty& _Right) { complex<_Ty> _Tmp(_Left); _Tmp.real(_Tmp.real() / _Right); _Tmp.imag(_Tmp.imag() / _Right); @@ -1107,7 +1113,7 @@ _NODISCARD complex<_Ty> operator/(const complex<_Ty>& _Left, const _Ty& _Right) } template -_NODISCARD complex<_Ty> operator/(const _Ty& _Left, const complex<_Ty>& _Right) { +_NODISCARD _CONSTEXPR20 complex<_Ty> operator/(const _Ty& _Left, const complex<_Ty>& _Right) { complex<_Ty> _Tmp(_Left); _Tmp /= _Right; return _Tmp; @@ -1115,13 +1121,13 @@ _NODISCARD complex<_Ty> operator/(const _Ty& _Left, const complex<_Ty>& _Right) // FUNCTION TEMPLATE UNARY operator+ template -_NODISCARD complex<_Ty> operator+(const complex<_Ty>& _Left) { +_NODISCARD _CONSTEXPR20 complex<_Ty> operator+(const complex<_Ty>& _Left) { return _Left; } // FUNCTION TEMPLATE UNARY operator- template -_NODISCARD complex<_Ty> operator-(const complex<_Ty>& _Left) { +_NODISCARD _CONSTEXPR20 complex<_Ty> operator-(const complex<_Ty>& _Left) { return complex<_Ty>(-_Left.real(), -_Left.imag()); } @@ -1682,7 +1688,7 @@ _NODISCARD _Ty arg(const complex<_Ty>& _Left) { // return phase angle of complex // FUNCTION TEMPLATE conj template -_NODISCARD complex<_Ty> conj(const complex<_Ty>& _Left) { // return complex conjugate +_NODISCARD _CONSTEXPR20 complex<_Ty> conj(const complex<_Ty>& _Left) { // return complex conjugate return complex<_Ty>(real(_Left), -imag(_Left)); } @@ -1718,7 +1724,7 @@ _NODISCARD complex<_Ty> log10(const complex<_Ty>& _Left) { // FUNCTION TEMPLATE norm template -_NODISCARD _Ty norm(const complex<_Ty>& _Left) { // return squared magnitude +_NODISCARD _CONSTEXPR20 _Ty norm(const complex<_Ty>& _Left) { // return squared magnitude return real(_Left) * real(_Left) + imag(_Left) * imag(_Left); } @@ -1749,33 +1755,37 @@ _NODISCARD complex<_Ty> tan(const complex<_Ty>& _Left) { // ADDITIONAL OVERLOADS template -struct _Promote_to_float { // promote integral to double - using type = conditional_t, double, _Ty>; -}; +using _Upgrade_to_double = conditional_t, double, _Ty>; -#define _GENERIC_MATHC0X(FUN, VAL) \ - template , int> = 0> \ - _NODISCARD typename _Promote_to_float<_Ty>::type FUN(_Ty) { \ - return static_cast::type>(VAL); \ - } +template , int> = 0> +_NODISCARD _Upgrade_to_double<_Ty> arg(_Ty) { + return 0; +} -#define _GENERIC_MATHC1X(FUN, VAL) \ - template , int> = 0> \ - _NODISCARD typename _Promote_to_float<_Ty>::type FUN(_Ty _Left) { \ - return static_cast::type>(VAL); \ - } +template , int> = 0> +_NODISCARD _CONSTEXPR20 _Upgrade_to_double<_Ty> imag(_Ty) { + return 0; +} -_GENERIC_MATHC0X(arg, 0) -_GENERIC_MATHC0X(imag, 0) -_GENERIC_MATHC1X(real, _Left) +template , int> = 0> +_NODISCARD _CONSTEXPR20 _Upgrade_to_double<_Ty> real(_Ty _Left) { + return static_cast<_Upgrade_to_double<_Ty>>(_Left); +} -_GENERIC_MATHC1X(norm, (_Left * _Left)) +template , int> = 0> +_NODISCARD _CONSTEXPR20 _Upgrade_to_double<_Ty> norm(_Ty _Left) { + return static_cast<_Upgrade_to_double<_Ty>>(_Left * _Left); +} -_GENERIC_MATHC1X(conj, _Left) -_GENERIC_MATHC1X(proj, _Left) +template , int> = 0> +_NODISCARD _CONSTEXPR20 _Upgrade_to_double<_Ty> conj(_Ty _Left) { + return static_cast<_Upgrade_to_double<_Ty>>(_Left); +} -#undef _GENERIC_MATHC0X -#undef _GENERIC_MATHC1X +template , int> = 0> +_NODISCARD _Upgrade_to_double<_Ty> proj(_Ty _Left) { + return static_cast<_Upgrade_to_double<_Ty>>(_Left); +} // FUNCTION TEMPLATE pow template diff --git a/stl/inc/xutility b/stl/inc/xutility index 14296662fbf..1b773ec377a 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -47,6 +47,23 @@ _END_EXTERN_C _STD_BEGIN +// FUNCTION TEMPLATE _Bit_cast +template , is_trivially_copyable<_To>, + is_trivially_copyable<_From>>, + int> = 0> +#ifdef __CUDACC__ +_NODISCARD _To _Bit_cast(const _From& _Val) noexcept { + _To _To_obj; // assumes default-init + _CSTD memcpy(_STD addressof(_To_obj), _STD addressof(_Val), sizeof(_To)); + return _To_obj; +} +#else // ^^^ workaround ^^^ / vvv no workaround vvv +_NODISCARD constexpr _To _Bit_cast(const _From& _Val) noexcept { + return __builtin_bit_cast(_To, _Val); +} +#endif // ^^^ no workaround ^^^ + // STRUCT TEMPLATE _Get_first_parameter template struct _Get_first_parameter; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index f2185779727..ec232d028a4 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -138,6 +138,7 @@ // P0325R4 to_array() // P0356R5 bind_front() // P0357R3 Supporting Incomplete Types In reference_wrapper +// P0415R1 constexpr For (Again) // P0439R0 enum class memory_order // P0457R2 starts_with()/ends_with() For basic_string/basic_string_view // P0458R2 contains() For Ordered And Unordered Associative Containers @@ -1137,6 +1138,7 @@ #endif // defined(__cpp_concepts) && __cpp_concepts > 201507L #define __cpp_lib_constexpr_algorithms 201806L +#define __cpp_lib_constexpr_complex 201711L #define __cpp_lib_constexpr_memory 201811L #define __cpp_lib_constexpr_numeric 201911L diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index a91dbd2300e..14769153ed3 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -408,10 +408,6 @@ std/utilities/time/time.hms/time.hms.members/subseconds.pass.cpp SKIPPED std/utilities/time/time.hms/time.hms.members/to_duration.pass.cpp SKIPPED std/utilities/time/time.hms/time.hms.members/width.pass.cpp SKIPPED -# C++20 P0415R1 "constexpr For (Again)" -std/numerics/complex.number/cmplx.over/imag.pass.cpp SKIPPED -std/numerics/complex.number/cmplx.over/real.pass.cpp SKIPPED - # C++20 P0476R2 " bit_cast" std/language.support/support.limits/support.limits.general/bit.version.pass.cpp SKIPPED diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 20caf9c5777..2f98c0fdedd 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -408,10 +408,6 @@ utilities\time\time.hms\time.hms.members\subseconds.pass.cpp utilities\time\time.hms\time.hms.members\to_duration.pass.cpp utilities\time\time.hms\time.hms.members\width.pass.cpp -# C++20 P0415R1 "constexpr For (Again)" -numerics\complex.number\cmplx.over\imag.pass.cpp -numerics\complex.number\cmplx.over\real.pass.cpp - # C++20 P0476R2 " bit_cast" language.support\support.limits\support.limits.general\bit.version.pass.cpp diff --git a/tests/std/test.lst b/tests/std/test.lst index 300921abe31..9cdaa15d150 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -209,6 +209,7 @@ tests\P0325R4_to_array tests\P0356R5_bind_front tests\P0357R3_supporting_incomplete_types_in_reference_wrapper tests\P0414R2_shared_ptr_for_arrays +tests\P0415R1_constexpr_complex tests\P0426R1_constexpr_char_traits tests\P0433R2_deduction_guides tests\P0476R2_bit_cast diff --git a/tests/std/tests/P0415R1_constexpr_complex/env.lst b/tests/std/tests/P0415R1_constexpr_complex/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P0415R1_constexpr_complex/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P0415R1_constexpr_complex/test.cpp b/tests/std/tests/P0415R1_constexpr_complex/test.cpp new file mode 100644 index 00000000000..e02267a93f2 --- /dev/null +++ b/tests/std/tests/P0415R1_constexpr_complex/test.cpp @@ -0,0 +1,131 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +using namespace std; + +template +constexpr void test_type() { + static_assert(is_floating_point_v); + + constexpr F f1{1}; + constexpr F f2{2}; + constexpr F f3{3}; + constexpr F f4{4}; + + complex c{f1, f2}; + assert(c.real() == f1); + assert(c.imag() == f2); + assert((c == complex{f1, f2})); + + c.real(f3); + assert((c == complex{f3, f2})); + + c.imag(f4); + assert((c == complex{f3, f4})); + + // Test GH-190 ": real(T) and imag(T) setters should return void". + static_assert(is_void_v); + static_assert(is_void_v); + + c = f1; + assert(c == complex{f1}); + + c.imag(f1); + assert((c == complex{f1, f1})); + + c += f2; + assert((c == complex{f3, f1})); + + c -= f1; + assert((c == complex{f2, f1})); + + c *= f2; + assert((c == complex{f4, f2})); + + c /= f2; + assert((c == complex{f2, f1})); + + c = complex{f1, f3}; + assert((c == complex{f1, f3})); + + c += complex{f2, f1}; + assert((c == complex{f3, f4})); + + c -= complex{f1, f3}; + assert((c == complex{f2, f1})); + + c *= complex{f1, f1}; + assert((c == complex{f1, f3})); + + c /= complex{f1, f3}; + assert(c == complex{f1}); + + { + using Other = conditional_t, double, float>; + + c = complex{Other{1}, Other{3}}; + assert((c == complex{f1, f3})); + + c += complex{Other{2}, Other{1}}; + assert((c == complex{f3, f4})); + + c -= complex{Other{1}, Other{3}}; + assert((c == complex{f2, f1})); + + c *= complex{Other{1}, Other{1}}; + assert((c == complex{f1, f3})); + + c /= complex{Other{1}, Other{3}}; + assert(c == complex{f1}); + } + + assert((complex{f1, f1} + complex{f1, f2} == complex{f2, f3})); + assert((complex{f1, f1} + f1 == complex{f2, f1})); + assert((f1 + complex{f2, f2} == complex{f3, f2})); + + assert((complex{f3, f4} - complex{f1, f1} == complex{f2, f3})); + assert((complex{f4, f4} - f2 == complex{f2, f4})); + assert((f2 - complex{f1, f1} == complex{f1, -f1})); + + assert((complex{f1, f1} * complex{f2, f1} == complex{f1, f3})); + assert((complex{f1, f2} * f2 == complex{f2, f4})); + assert((f3 * complex{f1, f1} == complex{f3, f3})); + + assert((complex{f4, f4} / complex{f2, f2} == complex{f2})); + assert((complex{f3, f3} / f3 == complex{f1, f1})); + assert((f1 / complex{f1, f1} == complex{F{0.5}, F{-0.5}})); + + assert((+complex{f2, f3} == complex{f2, f3})); + + assert((-complex{f2, f3} == complex{-f2, -f3})); + + assert((norm(complex{f3, f4}) == F{25})); + + assert((conj(complex{f3, f4}) == complex{f3, -f4})); + + assert(real(f2) == f2); + assert(imag(f2) == F{0}); + assert(norm(f2) == f4); + assert(conj(f2) == f2); +} + +constexpr bool test_all() { + test_type(); + test_type(); + test_type(); + + assert(real(2) == 2.0); + assert(imag(2) == 0.0); + assert(norm(2) == 4.0); + assert(conj(2) == 2.0); + + return true; +} + +int main() { + assert(test_all()); + static_assert(test_all()); +} diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.cpp index 11822b07574..57134316e3d 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.cpp @@ -313,6 +313,20 @@ STATIC_ASSERT(__cpp_lib_constexpr_algorithms == 201806L); #endif #endif +#if _HAS_CXX20 +#ifndef __cpp_lib_constexpr_complex +#error __cpp_lib_constexpr_complex is not defined +#elif __cpp_lib_constexpr_complex != 201711L +#error __cpp_lib_constexpr_complex is not 201711L +#else +STATIC_ASSERT(__cpp_lib_constexpr_complex == 201711L); +#endif +#else +#ifdef __cpp_lib_constexpr_complex +#error __cpp_lib_constexpr_complex is defined +#endif +#endif + #if _HAS_CXX20 #ifndef __cpp_lib_constexpr_memory #error __cpp_lib_constexpr_memory is not defined