<complex>: Fix the pow(complex, arithmetic) overload set (#1299)

Co-authored-by: Stephan T. Lavavej <stl@microsoft.com>
This commit is contained in:
MattStephanson 2020-10-02 19:59:49 -07:00 коммит произвёл GitHub
Родитель bb05875900
Коммит d05f8ecbb2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 12 добавлений и 59 удалений

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

@ -1853,65 +1853,22 @@ _NODISCARD complex<_Upgrade_to_double<_Ty>> proj(_Ty _Left) {
// FUNCTION TEMPLATE pow
template <class _Ty1, class _Ty2>
_NODISCARD complex<_Common_float_type_t<_Ty1, _Ty2>> pow(const complex<_Ty1>& _Left, const complex<_Ty2>& _Right) {
using type = complex<_Common_float_type_t<_Ty1, _Ty2>>;
return _STD pow(type(_Left), type(_Right));
using _Type = complex<_Common_float_type_t<_Ty1, _Ty2>>;
return _STD pow(_Type(_Left), _Type(_Right));
}
template <class _Ty1, class _Ty2, enable_if_t<!is_integral_v<_Ty2>, int> = 0>
template <class _Ty1, class _Ty2, enable_if_t<is_arithmetic_v<_Ty2>, int> = 0>
_NODISCARD complex<_Common_float_type_t<_Ty1, _Ty2>> pow(const complex<_Ty1>& _Left, const _Ty2& _Right) {
using type = complex<_Common_float_type_t<_Ty1, _Ty2>>;
return _STD pow(type(_Left), type(_Right));
using _Promoted = _Common_float_type_t<_Ty1, _Ty2>;
using _Type = complex<_Promoted>;
return _STD pow(_Type(_Left), _Type(static_cast<_Promoted>(_Right)));
}
template <class _Ty1, class _Ty2, enable_if_t<!is_integral_v<_Ty1> && is_integral_v<_Ty2>, int> = 0>
_NODISCARD complex<_Common_float_type_t<_Ty1, _Ty2>> pow(const complex<_Ty1>& _Left, const _Ty2 _Right) {
using type = complex<_Common_float_type_t<_Ty1, _Ty2>>;
type _Tmp = _Left;
auto _Count = static_cast<make_unsigned_t<_Ty2>>(_Right);
if (_Right < 0) {
_Count = 0 - _Count; // safe negation as unsigned
}
for (type _Zv(1);; _Tmp *= _Tmp) { // fold in _Left ^ (2 ^ _Count) as needed
if ((_Count & 1) != 0) {
_Zv *= _Tmp;
}
if ((_Count >>= 1) == 0) {
return _Right < 0 ? type(1) / _Zv : _Zv;
}
}
}
template <class _Ty1, class _Ty2, enable_if_t<is_integral_v<_Ty1> && is_integral_v<_Ty2>, int> = 0>
_NODISCARD complex<_Ty1> pow(const complex<_Ty1>& _Left, _Ty2 _Right) {
// raise Gaussian integer to an integer power
using type = complex<_Ty1>;
type _Ans = type(1, 0);
if (_Right < 0) {
_Ans = type(0, 0); // ignore 1/type(0, 0) error
} else if (0 < _Right) { // raise to a positive power
for (type _Factor = _Left;; _Factor *= _Factor) { // fold in _Left^(2^N))
if ((_Right & 1) != 0) {
_Ans *= _Factor;
}
if ((_Right >>= 1) == 0) {
break;
}
}
}
return _Ans;
}
template <class _Ty1, class _Ty2>
template <class _Ty1, class _Ty2, enable_if_t<is_arithmetic_v<_Ty1>, int> = 0>
_NODISCARD complex<_Common_float_type_t<_Ty1, _Ty2>> pow(const _Ty1& _Left, const complex<_Ty2>& _Right) {
using type = complex<_Common_float_type_t<_Ty1, _Ty2>>;
return _STD pow(type(_Left), type(_Right));
using _Promoted = _Common_float_type_t<_Ty1, _Ty2>;
using _Type = complex<_Promoted>;
return _STD pow(_Type(static_cast<_Promoted>(_Left)), _Type(_Right));
}
// FUNCTION TEMPLATE operator>>

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

@ -530,9 +530,6 @@ std/input.output/file.streams/fstreams/filebuf.virtuals/underflow.pass.cpp FAIL
# GH-1004 <regex>: Error C2664 in std::regex_traits::transform
std/re/re.traits/transform.pass.cpp FAIL
# GH-1260 <complex>: pow, incorrect type conversion
std/numerics/complex.number/cmplx.over/pow.pass.cpp FAIL
# GH-1295 <array>: array<const T, 0> allows fill() and swap()
std/containers/sequences/array/array.fill/fill.fail.cpp FAIL
std/containers/sequences/array/array.swap/swap.fail.cpp FAIL
@ -752,6 +749,7 @@ std/iterators/predef.iterators/insert.iterators/insert.iterator/types.pass.cpp F
# Tests emit warning C4244: 'argument': conversion from 'T' to 'const std::complex<double>::_Ty', possible loss of data
std/numerics/complex.number/cmplx.over/conj.pass.cpp:0 FAIL
std/numerics/complex.number/cmplx.over/pow.pass.cpp:0 FAIL
std/numerics/complex.number/cmplx.over/proj.pass.cpp:0 FAIL
# Assertion failed: std::abs(skew - x_skew) < 0.01

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

@ -530,9 +530,6 @@ input.output\file.streams\fstreams\filebuf.virtuals\underflow.pass.cpp
# GH-1004 <regex>: Error C2664 in std::regex_traits::transform
re\re.traits\transform.pass.cpp
# GH-1260 <complex>: pow, incorrect type conversion
numerics\complex.number\cmplx.over\pow.pass.cpp
# GH-1295 <array>: array<const T, 0> allows fill() and swap()
containers\sequences\array\array.fill\fill.fail.cpp
containers\sequences\array\array.swap\swap.fail.cpp
@ -752,6 +749,7 @@ iterators\predef.iterators\insert.iterators\insert.iterator\types.pass.cpp
# Tests emit warning C4244: 'argument': conversion from 'T' to 'const std::complex<double>::_Ty', possible loss of data
numerics\complex.number\cmplx.over\conj.pass.cpp
numerics\complex.number\cmplx.over\pow.pass.cpp
numerics\complex.number\cmplx.over\proj.pass.cpp
# Assertion failed: std::abs(skew - x_skew) < 0.01