P0415R1 constexpr For <complex> (Again) (#367)

Fixes #16 and fixes #190.

Co-authored-by: Curtis.Bezault <curtbezault@gmail.com>
Co-authored-by: Stephan T. Lavavej <stl@microsoft.com>
This commit is contained in:
Daniil Goncharov 2020-04-30 14:13:55 +05:00 коммит произвёл GitHub
Родитель 852a308590
Коммит 2bc5f9bc71
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
10 изменённых файлов: 319 добавлений и 159 удалений

Просмотреть файл

@ -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 <class _To, class _From,
enable_if_t<sizeof(_To) == sizeof(_From) && is_trivially_copyable_v<_To> && 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;

Просмотреть файл

@ -9,6 +9,7 @@
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#include <cmath>
#include <cstdint>
#include <sstream>
#include <ymath.h>
@ -57,11 +58,11 @@ class complex<long double>;
template <class _Ty>
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<double>(_Left);
return _CSTD _Dtest(&_Tmp) == _INFCODE;
const auto _Tmp = static_cast<double>(_Left);
const auto _Uint = _Bit_cast<uint64_t>(_Tmp);
return (_Uint & 0x7fffffffffffffffU) == 0x7ff0000000000000U;
}
static bool _Isnan(_Ty _Left) {
double _Tmp = static_cast<double>(_Left);
return _CSTD _Dtest(&_Tmp) == _NANCODE;
static _CONSTEXPR20 bool _Isnan(_Ty _Left) {
const auto _Tmp = static_cast<double>(_Left);
const auto _Uint = _Bit_cast<uint64_t>(_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<long double> {
public:
using _Ty = long double;
static _Ty _Flt_eps() { // get epsilon
return LDBL_EPSILON;
static constexpr _Ty _Flt_eps() { // get epsilon
return numeric_limits<long double>::epsilon();
}
static _Ty _Flt_max() {
return LDBL_MAX;
static constexpr _Ty _Flt_max() {
return (numeric_limits<long double>::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<long double>::infinity();
}
static bool _Isinf(_Ty _Left) { // test for infinity
return _CSTD _LDtest(&_Left) == _INFCODE;
const auto _Uint = _Bit_cast<uint64_t>(_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<uint64_t>(_Left);
return (_Uint & 0x7fffffffffffffffU) > 0x7ff0000000000000U;
}
static _Ty _Nanv() { // return NaN
static constexpr _Ty _Nanv() { // return NaN
return numeric_limits<long double>::quiet_NaN();
}
@ -288,12 +293,12 @@ class _Ctraits<double> {
public:
using _Ty = double;
static _Ty _Flt_eps() { // get epsilon
return DBL_EPSILON;
static constexpr _Ty _Flt_eps() { // get epsilon
return numeric_limits<double>::epsilon();
}
static _Ty _Flt_max() {
return DBL_MAX;
static constexpr _Ty _Flt_max() {
return (numeric_limits<double>::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<double>::infinity();
}
static bool _Isinf(_Ty _Left) { // test for infinity
return _CSTD _Dtest(&_Left) == _INFCODE;
const auto _Uint = _Bit_cast<uint64_t>(_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<uint64_t>(_Left);
return (_Uint & 0x7fffffffffffffffU) > 0x7ff0000000000000U;
}
static _Ty _Nanv() { // return NaN
static constexpr _Ty _Nanv() { // return NaN
return numeric_limits<double>::quiet_NaN();
}
@ -408,12 +415,12 @@ class _Ctraits<float> {
public:
using _Ty = float;
static _Ty _Flt_eps() { // get epsilon
return FLT_EPSILON;
static constexpr _Ty _Flt_eps() { // get epsilon
return numeric_limits<float>::epsilon();
}
static _Ty _Flt_max() {
return FLT_MAX;
static constexpr _Ty _Flt_max() {
return (numeric_limits<float>::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<float>::infinity();
}
static bool _Isinf(_Ty _Left) { // test for infinity
return _CSTD _FDtest(&_Left) == _INFCODE;
const auto _Uint = _Bit_cast<uint32_t>(_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<uint32_t>(_Left);
return (_Uint & 0x7fffffffU) > 0x7f800000U;
}
static _Ty _Nanv() { // return NaN
static constexpr _Ty _Nanv() { // return NaN
return numeric_limits<float>::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 <class _Other>
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 <class _Other>
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 <class _Other>
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 <class _Other>
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<float, _Fcomplex_value>(
static_cast<float>(_Right._Val[_RE]), static_cast<float>(_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 <class _Other>
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 <class _Other>
complex& operator+=(const complex<_Other>& _Right) {
_CONSTEXPR20 complex& operator+=(const complex<_Other>& _Right) {
this->_Add(_Right);
return *this;
}
template <class _Other>
complex& operator-=(const complex<_Other>& _Right) {
_CONSTEXPR20 complex& operator-=(const complex<_Other>& _Right) {
this->_Sub(_Right);
return *this;
}
template <class _Other>
complex& operator*=(const complex<_Other>& _Right) {
_CONSTEXPR20 complex& operator*=(const complex<_Other>& _Right) {
this->_Mul(_Right);
return *this;
}
template <class _Other>
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<double, _Dcomplex_value>(
static_cast<double>(_Right._Val[_RE]), static_cast<double>(_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 <class _Other>
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 <class _Other>
complex& operator+=(const complex<_Other>& _Right) {
_CONSTEXPR20 complex& operator+=(const complex<_Other>& _Right) {
this->_Add(_Right);
return *this;
}
template <class _Other>
complex& operator-=(const complex<_Other>& _Right) {
_CONSTEXPR20 complex& operator-=(const complex<_Other>& _Right) {
this->_Sub(_Right);
return *this;
}
template <class _Other>
complex& operator*=(const complex<_Other>& _Right) {
_CONSTEXPR20 complex& operator*=(const complex<_Other>& _Right) {
this->_Mul(_Right);
return *this;
}
template <class _Other>
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<long double, _Lcomplex_value>(_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 <class _Other>
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 <class _Other>
complex& operator+=(const complex<_Other>& _Right) {
_CONSTEXPR20 complex& operator+=(const complex<_Other>& _Right) {
this->_Add(_Right);
return *this;
}
template <class _Other>
complex& operator-=(const complex<_Other>& _Right) {
_CONSTEXPR20 complex& operator-=(const complex<_Other>& _Right) {
this->_Sub(_Right);
return *this;
}
template <class _Other>
complex& operator*=(const complex<_Other>& _Right) {
_CONSTEXPR20 complex& operator*=(const complex<_Other>& _Right) {
this->_Mul(_Right);
return *this;
}
template <class _Other>
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 <class _Other>
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 <class _Other>
complex& operator+=(const complex<_Other>& _Right) {
_CONSTEXPR20 complex& operator+=(const complex<_Other>& _Right) {
this->_Add(_Right);
return *this;
}
template <class _Other>
complex& operator-=(const complex<_Other>& _Right) {
_CONSTEXPR20 complex& operator-=(const complex<_Other>& _Right) {
this->_Sub(_Right);
return *this;
}
template <class _Other>
complex& operator*=(const complex<_Other>& _Right) {
_CONSTEXPR20 complex& operator*=(const complex<_Other>& _Right) {
this->_Mul(_Right);
return *this;
}
template <class _Other>
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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
_NODISCARD complex<_Ty> operator+(const complex<_Ty>& _Left) {
_NODISCARD _CONSTEXPR20 complex<_Ty> operator+(const complex<_Ty>& _Left) {
return _Left;
}
// FUNCTION TEMPLATE UNARY operator-
template <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
_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 <class _Ty>
struct _Promote_to_float { // promote integral to double
using type = conditional_t<is_integral_v<_Ty>, double, _Ty>;
};
using _Upgrade_to_double = conditional_t<is_integral_v<_Ty>, double, _Ty>;
#define _GENERIC_MATHC0X(FUN, VAL) \
template <class _Ty, enable_if_t<is_arithmetic_v<_Ty>, int> = 0> \
_NODISCARD typename _Promote_to_float<_Ty>::type FUN(_Ty) { \
return static_cast<typename _Promote_to_float<_Ty>::type>(VAL); \
template <class _Ty, enable_if_t<is_arithmetic_v<_Ty>, int> = 0>
_NODISCARD _Upgrade_to_double<_Ty> arg(_Ty) {
return 0;
}
#define _GENERIC_MATHC1X(FUN, VAL) \
template <class _Ty, enable_if_t<is_arithmetic_v<_Ty>, int> = 0> \
_NODISCARD typename _Promote_to_float<_Ty>::type FUN(_Ty _Left) { \
return static_cast<typename _Promote_to_float<_Ty>::type>(VAL); \
template <class _Ty, enable_if_t<is_arithmetic_v<_Ty>, 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 <class _Ty, enable_if_t<is_arithmetic_v<_Ty>, 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 <class _Ty, enable_if_t<is_arithmetic_v<_Ty>, 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 <class _Ty, enable_if_t<is_arithmetic_v<_Ty>, 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 <class _Ty, enable_if_t<is_arithmetic_v<_Ty>, int> = 0>
_NODISCARD _Upgrade_to_double<_Ty> proj(_Ty _Left) {
return static_cast<_Upgrade_to_double<_Ty>>(_Left);
}
// FUNCTION TEMPLATE pow
template <class _Ty1, class _Ty2>

Просмотреть файл

@ -47,6 +47,23 @@ _END_EXTERN_C
_STD_BEGIN
// FUNCTION TEMPLATE _Bit_cast
template <class _To, class _From,
enable_if_t<conjunction_v<bool_constant<sizeof(_To) == sizeof(_From)>, 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 <class _Ty>
struct _Get_first_parameter;

Просмотреть файл

@ -138,6 +138,7 @@
// P0325R4 to_array()
// P0356R5 bind_front()
// P0357R3 Supporting Incomplete Types In reference_wrapper
// P0415R1 constexpr For <complex> (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

Просмотреть файл

@ -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 <complex> (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> bit_cast"
std/language.support/support.limits/support.limits.general/bit.version.pass.cpp SKIPPED

Просмотреть файл

@ -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 <complex> (Again)"
numerics\complex.number\cmplx.over\imag.pass.cpp
numerics\complex.number\cmplx.over\real.pass.cpp
# C++20 P0476R2 "<bit> bit_cast"
language.support\support.limits\support.limits.general\bit.version.pass.cpp

Просмотреть файл

@ -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

Просмотреть файл

@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
RUNALL_INCLUDE ..\usual_latest_matrix.lst

Просмотреть файл

@ -0,0 +1,131 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <assert.h>
#include <complex>
#include <type_traits>
using namespace std;
template <typename F>
constexpr void test_type() {
static_assert(is_floating_point_v<F>);
constexpr F f1{1};
constexpr F f2{2};
constexpr F f3{3};
constexpr F f4{4};
complex<F> c{f1, f2};
assert(c.real() == f1);
assert(c.imag() == f2);
assert((c == complex<F>{f1, f2}));
c.real(f3);
assert((c == complex<F>{f3, f2}));
c.imag(f4);
assert((c == complex<F>{f3, f4}));
// Test GH-190 "<complex>: real(T) and imag(T) setters should return void".
static_assert(is_void_v<decltype(c.real(f3))>);
static_assert(is_void_v<decltype(c.imag(f4))>);
c = f1;
assert(c == complex<F>{f1});
c.imag(f1);
assert((c == complex<F>{f1, f1}));
c += f2;
assert((c == complex<F>{f3, f1}));
c -= f1;
assert((c == complex<F>{f2, f1}));
c *= f2;
assert((c == complex<F>{f4, f2}));
c /= f2;
assert((c == complex<F>{f2, f1}));
c = complex<F>{f1, f3};
assert((c == complex<F>{f1, f3}));
c += complex<F>{f2, f1};
assert((c == complex<F>{f3, f4}));
c -= complex<F>{f1, f3};
assert((c == complex<F>{f2, f1}));
c *= complex<F>{f1, f1};
assert((c == complex<F>{f1, f3}));
c /= complex<F>{f1, f3};
assert(c == complex<F>{f1});
{
using Other = conditional_t<is_same_v<F, float>, double, float>;
c = complex<Other>{Other{1}, Other{3}};
assert((c == complex<F>{f1, f3}));
c += complex<Other>{Other{2}, Other{1}};
assert((c == complex<F>{f3, f4}));
c -= complex<Other>{Other{1}, Other{3}};
assert((c == complex<F>{f2, f1}));
c *= complex<Other>{Other{1}, Other{1}};
assert((c == complex<F>{f1, f3}));
c /= complex<Other>{Other{1}, Other{3}};
assert(c == complex<F>{f1});
}
assert((complex<F>{f1, f1} + complex<F>{f1, f2} == complex<F>{f2, f3}));
assert((complex<F>{f1, f1} + f1 == complex<F>{f2, f1}));
assert((f1 + complex<F>{f2, f2} == complex<F>{f3, f2}));
assert((complex<F>{f3, f4} - complex<F>{f1, f1} == complex<F>{f2, f3}));
assert((complex<F>{f4, f4} - f2 == complex<F>{f2, f4}));
assert((f2 - complex<F>{f1, f1} == complex<F>{f1, -f1}));
assert((complex<F>{f1, f1} * complex<F>{f2, f1} == complex<F>{f1, f3}));
assert((complex<F>{f1, f2} * f2 == complex<F>{f2, f4}));
assert((f3 * complex<F>{f1, f1} == complex<F>{f3, f3}));
assert((complex<F>{f4, f4} / complex<F>{f2, f2} == complex<F>{f2}));
assert((complex<F>{f3, f3} / f3 == complex<F>{f1, f1}));
assert((f1 / complex<F>{f1, f1} == complex<F>{F{0.5}, F{-0.5}}));
assert((+complex<F>{f2, f3} == complex<F>{f2, f3}));
assert((-complex<F>{f2, f3} == complex<F>{-f2, -f3}));
assert((norm(complex<F>{f3, f4}) == F{25}));
assert((conj(complex<F>{f3, f4}) == complex<F>{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<float>();
test_type<double>();
test_type<long double>();
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());
}

Просмотреть файл

@ -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