We implemented DR 1137 which changed the return types of proj and conj on scalars, but then before the final C++11 standard DR 1522 reverted that change, and we never implemented it. That means since GCC 4.5.0 we've been shipping non-conforming proj and conj functions.
This fixes the return types to match the standard, and adds some missing constexpr on the real and imag overloads for scalars. Since we're reverting the change from DR 1137 there's no reason to name the test after that DR, so I'm moving it back to its original name. I'm also changing a test's { target c++14 } to c++11. It was originally written to test std::complex in C++14 mode when the default was gnu++98, so needed an explicit -std=gnu++14. Now that is the default and so isn't needed, but there's no reason the test can't also be used in C++11 mode. PR libstdc++/61791 PR libstdc++/70607 * include/std/complex (real(T), imag(T)): Add _GLIBCXX_CONSTEXPR. (proj(T), conj(T)): Change return types per DR 1522. * include/tr1/complex (conj): Remove overloads and use std::conj. * testsuite/26_numerics/complex/dr781_dr1137.cc: Rename to... * testsuite/26_numerics/complex/dr781.cc: ... this, and update. * testsuite/26_numerics/complex/value_operations/constexpr2.cc: Test real(T) and imag(T). Allow testing for C++11 too. Tested powerpc64le-linux, committed to trunk.
commit 4fb1b36a299577fdf65008a9793fbaf66204f6a2 Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed Jan 25 10:24:43 2017 +0000 PR libstdc++/70607 make proj(T) and conj(T) return complex<T> PR libstdc++/61791 PR libstdc++/70607 * include/std/complex (real(T), imag(T)): Add _GLIBCXX_CONSTEXPR. (proj(T), conj(T)): Change return types per DR 1522. * include/tr1/complex (conj): Remove overloads and use std::conj. * testsuite/26_numerics/complex/dr781_dr1137.cc: Rename to... * testsuite/26_numerics/complex/dr781.cc: ... this, and update. * testsuite/26_numerics/complex/value_operations/constexpr2.cc: Test real(T) and imag(T). Allow testing for C++11 too. diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex index 12b6e41..6342c98 100644 --- a/libstdc++-v3/include/std/complex +++ b/libstdc++-v3/include/std/complex @@ -1840,7 +1840,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _Tp> - inline typename __gnu_cxx::__promote<_Tp>::__type + _GLIBCXX_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type imag(_Tp) { return _Tp(); } @@ -1853,7 +1853,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _Tp> - inline typename __gnu_cxx::__promote<_Tp>::__type + _GLIBCXX_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type real(_Tp __x) { return __x; } @@ -1921,16 +1921,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __complex_proj(__z); } #endif - // DR 1137. template<typename _Tp> - inline typename __gnu_cxx::__promote<_Tp>::__type + inline std::complex<typename __gnu_cxx::__promote<_Tp>::__type> proj(_Tp __x) - { return __x; } + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return std::proj(std::complex<__type>(__x)); + } template<typename _Tp> - inline typename __gnu_cxx::__promote<_Tp>::__type + inline std::complex<typename __gnu_cxx::__promote<_Tp>::__type> conj(_Tp __x) - { return __x; } + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return std::complex<__type>(__x, -__type()); + } _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/tr1/complex b/libstdc++-v3/include/tr1/complex index 8624e55..06f9ab0 100644 --- a/libstdc++-v3/include/tr1/complex +++ b/libstdc++-v3/include/tr1/complex @@ -371,17 +371,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } using std::arg; - - template<typename _Tp> - inline std::complex<_Tp> - conj(const std::complex<_Tp>& __z) - { return std::conj(__z); } - - template<typename _Tp> - inline std::complex<typename __gnu_cxx::__promote<_Tp>::__type> - conj(_Tp __x) - { return __x; } - + using std::conj; using std::imag; using std::norm; using std::polar; diff --git a/libstdc++-v3/testsuite/26_numerics/complex/dr781.cc b/libstdc++-v3/testsuite/26_numerics/complex/dr781.cc new file mode 100644 index 0000000..3fb6cd1 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/complex/dr781.cc @@ -0,0 +1,81 @@ +// { dg-do run { target c++11 } } +// 2008-05-22 Paolo Carlini <paolo.carl...@oracle.com> +// +// Copyright (C) 2008-2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <complex> +#include <testsuite_hooks.h> +#include <testsuite_tr1.h> + +// DR 781. std::complex should add missing C99 functions. +// DR 1137. Return type of conj and proj. +// 1522. conj specification is now nonsense +void test01() +{ + using __gnu_test::check_ret_type; + + typedef std::complex<float> cmplx_f_type; + typedef std::complex<double> cmplx_d_type; + typedef std::complex<long double> cmplx_ld_type; + + const int i1 = 1; + const float f1 = 1.0f; + const double d1 = 1.0; + const long double ld1 = 1.0l; + + const cmplx_f_type c_f1(f1, f1); + const cmplx_d_type c_d1(d1, d1); + const cmplx_ld_type c_ld1(ld1, ld1); + + check_ret_type<cmplx_f_type>(std::proj(c_f1)); + check_ret_type<cmplx_d_type>(std::proj(c_d1)); + check_ret_type<cmplx_ld_type>(std::proj(c_ld1)); + + check_ret_type<cmplx_f_type>(std::proj(f1)); + check_ret_type<cmplx_d_type>(std::proj(d1)); + check_ret_type<cmplx_d_type>(std::proj(i1)); + check_ret_type<cmplx_ld_type>(std::proj(ld1)); + + VERIFY( std::proj(f1) == std::proj(cmplx_f_type(f1)) ); + VERIFY( std::proj(d1) == std::proj(cmplx_d_type(d1)) ); + VERIFY( std::proj(ld1) == std::proj(cmplx_ld_type(ld1)) ); + VERIFY( std::proj(i1) == std::proj(double(i1)) ); + + check_ret_type<cmplx_f_type>(std::conj(c_f1)); + check_ret_type<cmplx_d_type>(std::conj(c_d1)); + check_ret_type<cmplx_ld_type>(std::conj(c_ld1)); + + check_ret_type<cmplx_f_type>(std::conj(f1)); + check_ret_type<cmplx_d_type>(std::conj(d1)); + check_ret_type<cmplx_d_type>(std::conj(i1)); + check_ret_type<cmplx_ld_type>(std::conj(ld1)); + + VERIFY( std::conj(f1) == std::conj(cmplx_f_type(f1)) ); + VERIFY( std::conj(d1) == std::conj(cmplx_d_type(d1)) ); + VERIFY( std::conj(ld1) == std::conj(cmplx_ld_type(ld1)) ); + VERIFY( std::conj(i1) == std::conj(double(i1)) ); + VERIFY( std::signbit(std::conj(f1).imag()) ); + VERIFY( std::signbit(std::conj(d1).imag()) ); + VERIFY( std::signbit(std::conj(ld1).imag()) ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/26_numerics/complex/dr781_dr1137.cc b/libstdc++-v3/testsuite/26_numerics/complex/dr781_dr1137.cc deleted file mode 100644 index 8612087..0000000 --- a/libstdc++-v3/testsuite/26_numerics/complex/dr781_dr1137.cc +++ /dev/null @@ -1,69 +0,0 @@ -// { dg-do run { target c++11 } } -// 2008-05-22 Paolo Carlini <paolo.carl...@oracle.com> -// -// Copyright (C) 2008-2017 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this library; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include <complex> -#include <testsuite_hooks.h> -#include <testsuite_tr1.h> - -// DR 781. std::complex should add missing C99 functions. -// DR 1137. Return type of conj and proj. -void test01() -{ - using __gnu_test::check_ret_type; - - typedef std::complex<float> cmplx_f_type; - typedef std::complex<double> cmplx_d_type; - typedef std::complex<long double> cmplx_ld_type; - - const int i1 = 1; - const float f1 = 1.0f; - const double d1 = 1.0; - const long double ld1 = 1.0l; - - const cmplx_f_type c_f1(f1, f1); - const cmplx_d_type c_d1(d1, d1); - const cmplx_ld_type c_ld1(ld1, ld1); - - check_ret_type<cmplx_f_type>(std::proj(c_f1)); - check_ret_type<cmplx_d_type>(std::proj(c_d1)); - check_ret_type<cmplx_ld_type>(std::proj(c_ld1)); - - check_ret_type<float>(std::proj(f1)); - check_ret_type<double>(std::proj(d1)); - check_ret_type<double>(std::proj(i1)); - VERIFY( std::proj(i1) == std::proj(double(i1)) ); - check_ret_type<long double>(std::proj(ld1)); - - check_ret_type<cmplx_f_type>(std::conj(c_f1)); - check_ret_type<cmplx_d_type>(std::conj(c_d1)); - check_ret_type<cmplx_ld_type>(std::conj(c_ld1)); - - check_ret_type<float>(std::conj(f1)); - check_ret_type<double>(std::conj(d1)); - check_ret_type<double>(std::conj(i1)); - VERIFY( std::conj(i1) == std::conj(double(i1)) ); - check_ret_type<long double>(std::conj(ld1)); -} - -int main() -{ - test01(); - return 0; -} diff --git a/libstdc++-v3/testsuite/26_numerics/complex/value_operations/constexpr2.cc b/libstdc++-v3/testsuite/26_numerics/complex/value_operations/constexpr2.cc index 94840ec..c6e91c2 100644 --- a/libstdc++-v3/testsuite/26_numerics/complex/value_operations/constexpr2.cc +++ b/libstdc++-v3/testsuite/26_numerics/complex/value_operations/constexpr2.cc @@ -1,4 +1,4 @@ -// { dg-do compile { target c++14 } } +// { dg-do compile { target c++11 } } // Copyright (C) 2014-2017 Free Software Foundation, Inc. // @@ -24,4 +24,6 @@ int main() constexpr std::complex<int> c{}; constexpr auto r __attribute__((unused)) = real(c); constexpr auto i __attribute__((unused)) = imag(c); + constexpr double r2 __attribute__((unused)) = std::real(0.0); + constexpr double i2 __attribute__((unused)) = std::imag(0.0); }