Skip to content

Commit d05f8ec

Browse files
<complex>: Fix the pow(complex, arithmetic) overload set (#1299)
Co-authored-by: Stephan T. Lavavej <[email protected]>
1 parent bb05875 commit d05f8ec

File tree

3 files changed

+12
-59
lines changed

3 files changed

+12
-59
lines changed

stl/inc/complex

Lines changed: 10 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,65 +1853,22 @@ _NODISCARD complex<_Upgrade_to_double<_Ty>> proj(_Ty _Left) {
18531853
// FUNCTION TEMPLATE pow
18541854
template <class _Ty1, class _Ty2>
18551855
_NODISCARD complex<_Common_float_type_t<_Ty1, _Ty2>> pow(const complex<_Ty1>& _Left, const complex<_Ty2>& _Right) {
1856-
using type = complex<_Common_float_type_t<_Ty1, _Ty2>>;
1857-
return _STD pow(type(_Left), type(_Right));
1856+
using _Type = complex<_Common_float_type_t<_Ty1, _Ty2>>;
1857+
return _STD pow(_Type(_Left), _Type(_Right));
18581858
}
18591859

1860-
template <class _Ty1, class _Ty2, enable_if_t<!is_integral_v<_Ty2>, int> = 0>
1860+
template <class _Ty1, class _Ty2, enable_if_t<is_arithmetic_v<_Ty2>, int> = 0>
18611861
_NODISCARD complex<_Common_float_type_t<_Ty1, _Ty2>> pow(const complex<_Ty1>& _Left, const _Ty2& _Right) {
1862-
using type = complex<_Common_float_type_t<_Ty1, _Ty2>>;
1863-
return _STD pow(type(_Left), type(_Right));
1862+
using _Promoted = _Common_float_type_t<_Ty1, _Ty2>;
1863+
using _Type = complex<_Promoted>;
1864+
return _STD pow(_Type(_Left), _Type(static_cast<_Promoted>(_Right)));
18641865
}
18651866

1866-
template <class _Ty1, class _Ty2, enable_if_t<!is_integral_v<_Ty1> && is_integral_v<_Ty2>, int> = 0>
1867-
_NODISCARD complex<_Common_float_type_t<_Ty1, _Ty2>> pow(const complex<_Ty1>& _Left, const _Ty2 _Right) {
1868-
using type = complex<_Common_float_type_t<_Ty1, _Ty2>>;
1869-
1870-
type _Tmp = _Left;
1871-
auto _Count = static_cast<make_unsigned_t<_Ty2>>(_Right);
1872-
1873-
if (_Right < 0) {
1874-
_Count = 0 - _Count; // safe negation as unsigned
1875-
}
1876-
1877-
for (type _Zv(1);; _Tmp *= _Tmp) { // fold in _Left ^ (2 ^ _Count) as needed
1878-
if ((_Count & 1) != 0) {
1879-
_Zv *= _Tmp;
1880-
}
1881-
1882-
if ((_Count >>= 1) == 0) {
1883-
return _Right < 0 ? type(1) / _Zv : _Zv;
1884-
}
1885-
}
1886-
}
1887-
1888-
template <class _Ty1, class _Ty2, enable_if_t<is_integral_v<_Ty1> && is_integral_v<_Ty2>, int> = 0>
1889-
_NODISCARD complex<_Ty1> pow(const complex<_Ty1>& _Left, _Ty2 _Right) {
1890-
// raise Gaussian integer to an integer power
1891-
using type = complex<_Ty1>;
1892-
1893-
type _Ans = type(1, 0);
1894-
1895-
if (_Right < 0) {
1896-
_Ans = type(0, 0); // ignore 1/type(0, 0) error
1897-
} else if (0 < _Right) { // raise to a positive power
1898-
for (type _Factor = _Left;; _Factor *= _Factor) { // fold in _Left^(2^N))
1899-
if ((_Right & 1) != 0) {
1900-
_Ans *= _Factor;
1901-
}
1902-
1903-
if ((_Right >>= 1) == 0) {
1904-
break;
1905-
}
1906-
}
1907-
}
1908-
return _Ans;
1909-
}
1910-
1911-
template <class _Ty1, class _Ty2>
1867+
template <class _Ty1, class _Ty2, enable_if_t<is_arithmetic_v<_Ty1>, int> = 0>
19121868
_NODISCARD complex<_Common_float_type_t<_Ty1, _Ty2>> pow(const _Ty1& _Left, const complex<_Ty2>& _Right) {
1913-
using type = complex<_Common_float_type_t<_Ty1, _Ty2>>;
1914-
return _STD pow(type(_Left), type(_Right));
1869+
using _Promoted = _Common_float_type_t<_Ty1, _Ty2>;
1870+
using _Type = complex<_Promoted>;
1871+
return _STD pow(_Type(static_cast<_Promoted>(_Left)), _Type(_Right));
19151872
}
19161873

19171874
// FUNCTION TEMPLATE operator>>

tests/libcxx/expected_results.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -530,9 +530,6 @@ std/input.output/file.streams/fstreams/filebuf.virtuals/underflow.pass.cpp FAIL
530530
# GH-1004 <regex>: Error C2664 in std::regex_traits::transform
531531
std/re/re.traits/transform.pass.cpp FAIL
532532

533-
# GH-1260 <complex>: pow, incorrect type conversion
534-
std/numerics/complex.number/cmplx.over/pow.pass.cpp FAIL
535-
536533
# GH-1295 <array>: array<const T, 0> allows fill() and swap()
537534
std/containers/sequences/array/array.fill/fill.fail.cpp FAIL
538535
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
752749

753750
# Tests emit warning C4244: 'argument': conversion from 'T' to 'const std::complex<double>::_Ty', possible loss of data
754751
std/numerics/complex.number/cmplx.over/conj.pass.cpp:0 FAIL
752+
std/numerics/complex.number/cmplx.over/pow.pass.cpp:0 FAIL
755753
std/numerics/complex.number/cmplx.over/proj.pass.cpp:0 FAIL
756754

757755
# Assertion failed: std::abs(skew - x_skew) < 0.01

tests/libcxx/skipped_tests.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -530,9 +530,6 @@ input.output\file.streams\fstreams\filebuf.virtuals\underflow.pass.cpp
530530
# GH-1004 <regex>: Error C2664 in std::regex_traits::transform
531531
re\re.traits\transform.pass.cpp
532532

533-
# GH-1260 <complex>: pow, incorrect type conversion
534-
numerics\complex.number\cmplx.over\pow.pass.cpp
535-
536533
# GH-1295 <array>: array<const T, 0> allows fill() and swap()
537534
containers\sequences\array\array.fill\fill.fail.cpp
538535
containers\sequences\array\array.swap\swap.fail.cpp
@@ -752,6 +749,7 @@ iterators\predef.iterators\insert.iterators\insert.iterator\types.pass.cpp
752749

753750
# Tests emit warning C4244: 'argument': conversion from 'T' to 'const std::complex<double>::_Ty', possible loss of data
754751
numerics\complex.number\cmplx.over\conj.pass.cpp
752+
numerics\complex.number\cmplx.over\pow.pass.cpp
755753
numerics\complex.number\cmplx.over\proj.pass.cpp
756754

757755
# Assertion failed: std::abs(skew - x_skew) < 0.01

0 commit comments

Comments
 (0)