From 0e263d03bf2dc80db3f5d90c826e46d093083231 Mon Sep 17 00:00:00 2001 From: Matt Stephanson Date: Fri, 4 Sep 2020 22:26:46 -0700 Subject: [PATCH 1/2] Removes pow(complex,int) overload, per N4861 [cmplx.over]/3. - Restrict overloads to complex and arithmetic types. - _Uglify exiting type aliases. --- stl/inc/complex | 48 +++++++++---------------------- tests/libcxx/expected_results.txt | 4 +-- tests/libcxx/skipped_tests.txt | 4 +-- 3 files changed, 16 insertions(+), 40 deletions(-) diff --git a/stl/inc/complex b/stl/inc/complex index 2bbba58573b..e3c0e2d471c 100644 --- a/stl/inc/complex +++ b/stl/inc/complex @@ -1866,49 +1866,28 @@ _NODISCARD complex<_Upgrade_to_double<_Ty>> proj(_Ty _Left) { // FUNCTION TEMPLATE pow template _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 , int> = 0> +template , 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)); -} - -template && 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>(_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; - } - } + using _Promoted = _Common_float_type_t<_Ty1, _Ty2>; + using _Type = complex<_Promoted>; + return _STD pow(_Type(_Left), _Type(static_cast<_Promoted>(_Right))); } template && 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>; + using _Type = complex<_Ty1>; - type _Ans = type(1, 0); + _Type _Ans = _Type(1, 0); if (_Right < 0) { - _Ans = type(0, 0); // ignore 1/type(0, 0) error + _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)) + for (_Type _Factor = _Left;; _Factor *= _Factor) { // fold in _Left^(2^N)) if ((_Right & 1) != 0) { _Ans *= _Factor; } @@ -1921,10 +1900,11 @@ _NODISCARD complex<_Ty1> pow(const complex<_Ty1>& _Left, _Ty2 _Right) { return _Ans; } -template +template , 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>> diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 3e4254debc4..669d9877e32 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -534,9 +534,6 @@ std/numerics/complex.number/complex.special/float_long_double_implicit.compile.f # STL bug: regex_traits::transform() isn't following the Standard. std/re/re.traits/transform.pass.cpp FAIL -# STL bug: Incorrect return types. -std/numerics/complex.number/cmplx.over/pow.pass.cpp FAIL - # STL bug: We allow fill() and swap() for array. std/containers/sequences/array/array.fill/fill.fail.cpp FAIL std/containers/sequences/array/array.swap/swap.fail.cpp FAIL @@ -755,6 +752,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::_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 diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index bc5a21bba1f..ec39a60fefc 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -534,9 +534,6 @@ numerics\complex.number\complex.special\float_long_double_implicit.compile.fail. # STL bug: regex_traits::transform() isn't following the Standard. re\re.traits\transform.pass.cpp -# STL bug: Incorrect return types. -numerics\complex.number\cmplx.over\pow.pass.cpp - # STL bug: We allow fill() and swap() for array. containers\sequences\array\array.fill\fill.fail.cpp containers\sequences\array\array.swap\swap.fail.cpp @@ -755,6 +752,7 @@ iterators\predef.iterators\insert.iterators\insert.iterator\types.pass.cpp # Tests emit warning C4244: 'argument': conversion from 'T' to 'const std::complex::_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 From f31f73f84aa4327f1bb908ab998d460f0c550469 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 2 Oct 2020 03:39:38 -0700 Subject: [PATCH 2/2] Remove the "Gaussian integer" pow(). This scenario has always been broken. --- stl/inc/complex | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/stl/inc/complex b/stl/inc/complex index defb4b7d646..cbcc0e0d454 100644 --- a/stl/inc/complex +++ b/stl/inc/complex @@ -1856,29 +1856,6 @@ _NODISCARD complex<_Common_float_type_t<_Ty1, _Ty2>> pow(const complex<_Ty1>& _L return _STD pow(_Type(_Left), _Type(static_cast<_Promoted>(_Right))); } -template && 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 , int> = 0> _NODISCARD complex<_Common_float_type_t<_Ty1, _Ty2>> pow(const _Ty1& _Left, const complex<_Ty2>& _Right) { using _Promoted = _Common_float_type_t<_Ty1, _Ty2>;