[gcc(refs/vendors/ibm/heads/gcc-9-branch)] PR libstdc++/61761 fix std::proj for targets without C99 cproj

Peter Bergner bergner@gcc.gnu.org
Tue Feb 4 22:03:00 GMT 2020


https://gcc.gnu.org/g:e970705b48e151c5cdd63dea956c585333eea308

commit e970705b48e151c5cdd63dea956c585333eea308
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Oct 24 13:55:21 2019 +0100

    PR libstdc++/61761 fix std::proj for targets without C99 cproj
    
    The current generic implementation of __complex_proj used when cproj is
    not available calculates the wrong projection, giving a different result
    than given by C99's cproj.
    
    When C99 cproj is not available but isinf and copysign are, use those to
    give correct results for float, double and long double. Otherwise, and
    for other specializations of std::complex, just use a generic version
    that returns its argument, and so doesn't support infinities.
    
    We might want to consider adding additional overloads of __complex_proj
    to support extended types such as _Float64x, _Float128 etc.
    
    Backport from mainline
    2019-05-01  Jonathan Wakely  <jwakely@redhat.com>
    
    	PR libstdc++/61761
    	* include/std/complex (__complex_proj): Return parameter unchanged.
    	[_GLIBCXX_USE_C99_COMPLEX] (__complex_proj): Change overloads for
    	floating-point types to take std::complex arguments.
    	[_GLIBCXX_USE_C99_MATH_TR1] (__complex_proj): Add overloads for
    	floating-point types.
    	* testsuite/26_numerics/complex/proj.cc: New test.
    
    From-SVN: r277392

Diff:
---
 libstdc++-v3/ChangeLog                             |  11 +
 libstdc++-v3/include/std/complex                   |  68 ++--
 libstdc++-v3/testsuite/26_numerics/complex/proj.cc | 403 +++++++++++++++++++++
 3 files changed, 457 insertions(+), 25 deletions(-)

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 3be876e..c899cec 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,6 +1,17 @@
 2019-10-24  Jonathan Wakely  <jwakely@redhat.com>
 
 	Backport from mainline
+	2019-05-01  Jonathan Wakely  <jwakely@redhat.com>
+
+	PR libstdc++/61761
+	* include/std/complex (__complex_proj): Return parameter unchanged.
+	[_GLIBCXX_USE_C99_COMPLEX] (__complex_proj): Change overloads for
+	floating-point types to take std::complex arguments.
+	[_GLIBCXX_USE_C99_MATH_TR1] (__complex_proj): Add overloads for
+	floating-point types.
+	* testsuite/26_numerics/complex/proj.cc: New test.
+
+	Backport from mainline
 	2019-06-06  Jonathan Wakely  <jwakely@redhat.com>
 
 	* testsuite/23_containers/deque/requirements/dr438/assign_neg.cc: Add
diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex
index 0a4f68b..45450e8 100644
--- a/libstdc++-v3/include/std/complex
+++ b/libstdc++-v3/include/std/complex
@@ -1898,41 +1898,59 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     std::complex<_Tp> proj(const std::complex<_Tp>&);
 
+  // Generic implementation of std::proj, does not work for infinities.
   template<typename _Tp>
-    std::complex<_Tp>
+    inline std::complex<_Tp>
     __complex_proj(const std::complex<_Tp>& __z)
-    {
-      const _Tp __den = (__z.real() * __z.real()
-			 + __z.imag() * __z.imag() + _Tp(1.0));
-
-      return std::complex<_Tp>((_Tp(2.0) * __z.real()) / __den,
-			       (_Tp(2.0) * __z.imag()) / __den);
-    }
+    { return __z; }
 
 #if _GLIBCXX_USE_C99_COMPLEX
-  inline __complex__ float
-  __complex_proj(__complex__ float __z)
-  { return __builtin_cprojf(__z); }
-
-  inline __complex__ double
-  __complex_proj(__complex__ double __z)
-  { return __builtin_cproj(__z); }
-
-  inline __complex__ long double
-  __complex_proj(const __complex__ long double& __z)
-  { return __builtin_cprojl(__z); }
+  inline complex<float>
+  __complex_proj(const complex<float>& __z)
+  { return __builtin_cprojf(__z.__rep()); }
+
+  inline complex<double>
+  __complex_proj(const complex<double>& __z)
+  { return __builtin_cproj(__z.__rep()); }
+
+  inline complex<long double>
+  __complex_proj(const complex<long double>& __z)
+  { return __builtin_cprojl(__z.__rep()); }
+#elif defined _GLIBCXX_USE_C99_MATH_TR1
+  inline complex<float>
+  __complex_proj(const complex<float>& __z)
+  {
+    if (__builtin_isinf(__z.real()) || __builtin_isinf(__z.imag()))
+      return complex<float>(__builtin_inff(),
+			    __builtin_copysignf(0.0f, __z.imag()));
+    return __z;
+  }
+
+  inline complex<double>
+  __complex_proj(const complex<double>& __z)
+  {
+    if (__builtin_isinf(__z.real()) || __builtin_isinf(__z.imag()))
+      return complex<double>(__builtin_inf(),
+			     __builtin_copysign(0.0, __z.imag()));
+    return __z;
+  }
+
+  inline complex<long double>
+  __complex_proj(const complex<long double>& __z)
+  {
+    if (__builtin_isinf(__z.real()) || __builtin_isinf(__z.imag()))
+      return complex<long double>(__builtin_infl(),
+				  __builtin_copysignl(0.0l, __z.imag()));
+    return __z;
+  }
+#endif
 
   template<typename _Tp>
     inline std::complex<_Tp>
     proj(const std::complex<_Tp>& __z)
-    { return __complex_proj(__z.__rep()); }
-#else
-  template<typename _Tp>
-    inline std::complex<_Tp>
-    proj(const std::complex<_Tp>& __z)
     { return __complex_proj(__z); }
-#endif
 
+  // Overload for scalars
   template<typename _Tp>
     inline std::complex<typename __gnu_cxx::__promote<_Tp>::__type>
     proj(_Tp __x)
diff --git a/libstdc++-v3/testsuite/26_numerics/complex/proj.cc b/libstdc++-v3/testsuite/26_numerics/complex/proj.cc
new file mode 100644
index 0000000..64e0dec
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/complex/proj.cc
@@ -0,0 +1,403 @@
+// Copyright (C) 2019 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/>.
+
+// { dg-do run { target c++11 } }
+
+#include <complex>
+#include <limits>
+#include <testsuite_hooks.h>
+
+namespace test
+{
+#ifdef _GLIBCXX_USE_C99_MATH_TR1
+  using std::copysign;
+#else
+  bool copysign(float x, float y)
+  { return __builtin_copysignf(x, y); }
+
+  bool copysign(double x, double y)
+  { return __builtin_copysign(x, y); }
+
+  bool copysign(long double x, long double y)
+  { return __builtin_copysignl(x, y); }
+#endif
+}
+
+template<typename T>
+bool eq(const std::complex<T>& x, const std::complex<T>& y)
+{
+  bool nan_reals = std::isnan(x.real()) && std::isnan(y.real());
+  bool nan_imags = std::isnan(x.imag()) && std::isnan(y.imag());
+
+  bool sign_reals
+    = test::copysign(T(1), x.real()) == test::copysign(T(1), y.real());
+  bool sign_imags
+    = test::copysign(T(1), x.imag()) == test::copysign(T(1), y.imag());
+
+  return ((x.real() == y.real() && sign_reals) || nan_reals)
+    && ((x.imag() == y.imag() && sign_imags) || nan_imags);
+}
+
+void
+test01()
+{
+  const double qnan = std::numeric_limits<double>::quiet_NaN();
+  const double pinf = std::numeric_limits<double>::infinity();
+  const double ninf = -pinf;
+
+  std::complex<double> c00(0, 0);
+  VERIFY( eq( std::proj(c00)  , c00 ) );
+  VERIFY( eq( std::proj(-c00) , -c00 ) );
+  c00.real(-0.0);
+  VERIFY( eq( std::proj(c00)  , c00 ) );
+  VERIFY( eq( std::proj(-c00) , -c00 ) );
+
+  const std::complex<double> c01(0, 1);
+  VERIFY( eq( std::proj(c01)  , c01 ) );
+  VERIFY( eq( std::proj(-c01) , -c01 ) );
+  c00.real(-0.0);
+  VERIFY( eq( std::proj(c01)  , c01 ) );
+  VERIFY( eq( std::proj(-c01) , -c01 ) );
+
+  const std::complex<double> c10(1, 0);
+  VERIFY( eq( std::proj(c10)  , c10 ) );
+  VERIFY( eq( std::proj(-c10) , -c10 ) );
+
+  const std::complex<double> c12(1, 2);
+  VERIFY( eq( std::proj(c12)  , c12 ) );
+  VERIFY( eq( std::proj(-c12) , -c12 ) );
+
+  const std::complex<double> c0q(0, qnan);
+  VERIFY( eq( std::proj(c0q)  , c0q ) );
+  VERIFY( eq( std::proj(-c0q) , -c0q ) );
+
+  const std::complex<double> c1q(1, qnan);
+  VERIFY( eq( std::proj(c1q)  , c1q ) );
+  VERIFY( eq( std::proj(-c1q) , -c1q ) );
+
+  const std::complex<double> cq0(qnan, 0);
+  VERIFY( eq( std::proj(cq0)  , cq0 ) );
+  VERIFY( eq( std::proj(-cq0) , -cq0 ) );
+
+  const std::complex<double> cq1(qnan, 1);
+  VERIFY( eq( std::proj(cq1)  , cq1 ) );
+  VERIFY( eq( std::proj(-cq1) , -cq1 ) );
+
+  const std::complex<double> cqq(qnan, qnan);
+  VERIFY( eq( std::proj(cqq)  , cqq ) );
+  VERIFY( eq( std::proj(-cqq) , -cqq ) );
+
+  const std::complex<double> c0p(0, pinf);
+  VERIFY( eq( std::proj(c0p)  , std::complex<double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-c0p) , std::complex<double>(pinf, -0.0) ) );
+
+  const std::complex<double> c1p(1, pinf);
+  VERIFY( eq( std::proj(c1p)  , std::complex<double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-c1p) , std::complex<double>(pinf, -0.0) ) );
+
+  const std::complex<double> cqp(qnan, pinf);
+  VERIFY( eq( std::proj(cqp)  , std::complex<double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cqp) , std::complex<double>(pinf, -0.0) ) );
+
+  const std::complex<double> cpp(pinf, pinf);
+  VERIFY( eq( std::proj(cpp)  , std::complex<double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cpp) , std::complex<double>(pinf, -0.0) ) );
+
+  const std::complex<double>  c0n(0, ninf);
+  VERIFY( eq( std::proj(c0n) , std::complex<double>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-c0n) , std::complex<double>(pinf, +0.0) ) );
+
+  const std::complex<double> c1n(1, ninf);
+  VERIFY( eq( std::proj(c1n)  , std::complex<double>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-c1n) , std::complex<double>(pinf, +0.0) ) );
+
+  const std::complex<double> cqn(qnan, ninf);
+  VERIFY( eq( std::proj(cqn)  , std::complex<double>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-cqn) , std::complex<double>(pinf, +0.0) ) );
+
+  const std::complex<double> cpn(pinf, ninf);
+  VERIFY( eq( std::proj(cpn)  , std::complex<double>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-cpn) , std::complex<double>(pinf, +0.0) ) );
+
+  const std::complex<double> cnn(ninf, ninf);
+  VERIFY( eq( std::proj(cnn)  , std::complex<double>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-cnn) , std::complex<double>(pinf, +0.0) ) );
+
+  const std::complex<double> cp0(pinf, 0);
+  VERIFY( eq( std::proj(cp0)  , std::complex<double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cp0) , std::complex<double>(pinf, -0.0) ) );
+
+  const std::complex<double> cp1(pinf, 1);
+  VERIFY( eq( std::proj(cp1)  , std::complex<double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cp1) , std::complex<double>(pinf, -0.0) ) );
+
+  const std::complex<double> cpq(pinf, qnan);
+  VERIFY( eq( std::proj(cpq)  , std::complex<double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cpq) , std::complex<double>(pinf, -0.0) ) );
+
+  const std::complex<double> cn0(ninf, 0);
+  VERIFY( eq( std::proj(cn0)  , std::complex<double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cn0) , std::complex<double>(pinf, -0.0) ) );
+
+  const std::complex<double> cn1(ninf, 1);
+  VERIFY( eq( std::proj(cn1)  , std::complex<double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cn1) , std::complex<double>(pinf, -0.0) ) );
+
+  const std::complex<double> cnq(ninf, qnan);
+  VERIFY( eq( std::proj(cnq)  , std::complex<double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cnq) , std::complex<double>(pinf, -0.0) ) );
+
+  const std::complex<double> cnp(ninf, pinf);
+  VERIFY( eq( std::proj(cnp)  , std::complex<double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cnp) , std::complex<double>(pinf, -0.0) ) );
+}
+
+void
+test02()
+{
+  const float qnan = std::numeric_limits<float>::quiet_NaN();
+  const float pinf = std::numeric_limits<float>::infinity();
+  const float ninf = -pinf;
+
+  std::complex<float> c00(0, 0);
+  VERIFY( eq( std::proj(c00)  , c00 ) );
+  VERIFY( eq( std::proj(-c00) , -c00 ) );
+  c00.real(-0.0);
+  VERIFY( eq( std::proj(c00)  , c00 ) );
+  VERIFY( eq( std::proj(-c00) , -c00 ) );
+
+  const std::complex<float> c01(0, 1);
+  VERIFY( eq( std::proj(c01)  , c01 ) );
+  VERIFY( eq( std::proj(-c01) , -c01 ) );
+  c00.real(-0.0);
+  VERIFY( eq( std::proj(c01)  , c01 ) );
+  VERIFY( eq( std::proj(-c01) , -c01 ) );
+
+  const std::complex<float> c10(1, 0);
+  VERIFY( eq( std::proj(c10)  , c10 ) );
+  VERIFY( eq( std::proj(-c10) , -c10 ) );
+
+  const std::complex<float> c12(1, 2);
+  VERIFY( eq( std::proj(c12)  , c12 ) );
+  VERIFY( eq( std::proj(-c12) , -c12 ) );
+
+  const std::complex<float> c0q(0, qnan);
+  VERIFY( eq( std::proj(c0q)  , c0q ) );
+  VERIFY( eq( std::proj(-c0q) , -c0q ) );
+
+  const std::complex<float> c1q(1, qnan);
+  VERIFY( eq( std::proj(c1q)  , c1q ) );
+  VERIFY( eq( std::proj(-c1q) , -c1q ) );
+
+  const std::complex<float> cq0(qnan, 0);
+  VERIFY( eq( std::proj(cq0)  , cq0 ) );
+  VERIFY( eq( std::proj(-cq0) , -cq0 ) );
+
+  const std::complex<float> cq1(qnan, 1);
+  VERIFY( eq( std::proj(cq1)  , cq1 ) );
+  VERIFY( eq( std::proj(-cq1) , -cq1 ) );
+
+  const std::complex<float> cqq(qnan, qnan);
+  VERIFY( eq( std::proj(cqq)  , cqq ) );
+  VERIFY( eq( std::proj(-cqq) , -cqq ) );
+
+  const std::complex<float> c0p(0, pinf);
+  VERIFY( eq( std::proj(c0p)  , std::complex<float>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-c0p) , std::complex<float>(pinf, -0.0) ) );
+
+  const std::complex<float> c1p(1, pinf);
+  VERIFY( eq( std::proj(c1p)  , std::complex<float>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-c1p) , std::complex<float>(pinf, -0.0) ) );
+
+  const std::complex<float> cqp(qnan, pinf);
+  VERIFY( eq( std::proj(cqp)  , std::complex<float>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cqp) , std::complex<float>(pinf, -0.0) ) );
+
+  const std::complex<float> cpp(pinf, pinf);
+  VERIFY( eq( std::proj(cpp)  , std::complex<float>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cpp) , std::complex<float>(pinf, -0.0) ) );
+
+  const std::complex<float>  c0n(0, ninf);
+  VERIFY( eq( std::proj(c0n)  , std::complex<float>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-c0n) , std::complex<float>(pinf, +0.0) ) );
+
+  const std::complex<float> c1n(1, ninf);
+  VERIFY( eq( std::proj(c1n)  , std::complex<float>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-c1n) , std::complex<float>(pinf, +0.0) ) );
+
+  const std::complex<float> cqn(qnan, ninf);
+  VERIFY( eq( std::proj(cqn)  , std::complex<float>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-cqn) , std::complex<float>(pinf, +0.0) ) );
+
+  const std::complex<float> cpn(pinf, ninf);
+  VERIFY( eq( std::proj(cpn)  , std::complex<float>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-cpn) , std::complex<float>(pinf, +0.0) ) );
+
+  const std::complex<float> cnn(ninf, ninf);
+  VERIFY( eq( std::proj(cnn)  , std::complex<float>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-cnn) , std::complex<float>(pinf, +0.0) ) );
+
+  const std::complex<float> cp0(pinf, 0);
+  VERIFY( eq( std::proj(cp0)  , std::complex<float>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cp0) , std::complex<float>(pinf, -0.0) ) );
+
+  const std::complex<float> cp1(pinf, 1);
+  VERIFY( eq( std::proj(cp1)  , std::complex<float>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cp1) , std::complex<float>(pinf, -0.0) ) );
+
+  const std::complex<float> cpq(pinf, qnan);
+  VERIFY( eq( std::proj(cpq)  , std::complex<float>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cpq) , std::complex<float>(pinf, -0.0) ) );
+
+  const std::complex<float> cn0(ninf, 0);
+  VERIFY( eq( std::proj(cn0)  , std::complex<float>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cn0) , std::complex<float>(pinf, -0.0) ) );
+
+  const std::complex<float> cn1(ninf, 1);
+  VERIFY( eq( std::proj(cn1)  , std::complex<float>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cn1) , std::complex<float>(pinf, -0.0) ) );
+
+  const std::complex<float> cnq(ninf, qnan);
+  VERIFY( eq( std::proj(cnq)  , std::complex<float>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cnq) , std::complex<float>(pinf, -0.0) ) );
+
+  const std::complex<float> cnp(ninf, pinf);
+  VERIFY( eq( std::proj(cnp)  , std::complex<float>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cnp) , std::complex<float>(pinf, -0.0) ) );
+}
+
+void
+test03()
+{
+  const long double qnan = std::numeric_limits<long double>::quiet_NaN();
+  const long double pinf = std::numeric_limits<long double>::infinity();
+  const long double ninf = -pinf;
+
+  std::complex<long double> c00(0, 0);
+  VERIFY( eq( std::proj(c00)  , c00 ) );
+  VERIFY( eq( std::proj(-c00) , -c00 ) );
+  c00.real(-0.0);
+  VERIFY( eq( std::proj(c00)  , c00 ) );
+  VERIFY( eq( std::proj(-c00) , -c00 ) );
+
+  const std::complex<long double> c01(0, 1);
+  VERIFY( eq( std::proj(c01)  , c01 ) );
+  VERIFY( eq( std::proj(-c01) , -c01 ) );
+  c00.real(-0.0);
+  VERIFY( eq( std::proj(c01)  , c01 ) );
+  VERIFY( eq( std::proj(-c01) , -c01 ) );
+
+  const std::complex<long double> c10(1, 0);
+  VERIFY( eq( std::proj(c10)  , c10 ) );
+  VERIFY( eq( std::proj(-c10) , -c10 ) );
+
+  const std::complex<long double> c12(1, 2);
+  VERIFY( eq( std::proj(c12)  , c12 ) );
+  VERIFY( eq( std::proj(-c12) , -c12 ) );
+
+  const std::complex<long double> c0q(0, qnan);
+  VERIFY( eq( std::proj(c0q)  , c0q ) );
+  VERIFY( eq( std::proj(-c0q) , -c0q ) );
+
+  const std::complex<long double> c1q(1, qnan);
+  VERIFY( eq( std::proj(c1q)  , c1q ) );
+  VERIFY( eq( std::proj(-c1q) , -c1q ) );
+
+  const std::complex<long double> cq0(qnan, 0);
+  VERIFY( eq( std::proj(cq0)  , cq0 ) );
+  VERIFY( eq( std::proj(-cq0) , -cq0 ) );
+
+  const std::complex<long double> cq1(qnan, 1);
+  VERIFY( eq( std::proj(cq1)  , cq1 ) );
+  VERIFY( eq( std::proj(-cq1) , -cq1 ) );
+
+  const std::complex<long double> cqq(qnan, qnan);
+  VERIFY( eq( std::proj(cqq)  , cqq ) );
+  VERIFY( eq( std::proj(-cqq) , -cqq ) );
+
+  const std::complex<long double> c0p(0, pinf);
+  VERIFY( eq( std::proj(c0p)  , std::complex<long double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-c0p) , std::complex<long double>(pinf, -0.0) ) );
+
+  const std::complex<long double> c1p(1, pinf);
+  VERIFY( eq( std::proj(c1p)  , std::complex<long double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-c1p) , std::complex<long double>(pinf, -0.0) ) );
+
+  const std::complex<long double> cqp(qnan, pinf);
+  VERIFY( eq( std::proj(cqp)  , std::complex<long double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cqp) , std::complex<long double>(pinf, -0.0) ) );
+
+  const std::complex<long double> cpp(pinf, pinf);
+  VERIFY( eq( std::proj(cpp)  , std::complex<long double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cpp) , std::complex<long double>(pinf, -0.0) ) );
+
+  const std::complex<long double>  c0n(0, ninf);
+  VERIFY( eq( std::proj(c0n) , std::complex<long double>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-c0n) , std::complex<long double>(pinf, +0.0) ) );
+
+  const std::complex<long double> c1n(1, ninf);
+  VERIFY( eq( std::proj(c1n)  , std::complex<long double>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-c1n) , std::complex<long double>(pinf, +0.0) ) );
+
+  const std::complex<long double> cqn(qnan, ninf);
+  VERIFY( eq( std::proj(cqn)  , std::complex<long double>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-cqn) , std::complex<long double>(pinf, +0.0) ) );
+
+  const std::complex<long double> cpn(pinf, ninf);
+  VERIFY( eq( std::proj(cpn)  , std::complex<long double>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-cpn) , std::complex<long double>(pinf, +0.0) ) );
+
+  const std::complex<long double> cnn(ninf, ninf);
+  VERIFY( eq( std::proj(cnn)  , std::complex<long double>(pinf, -0.0) ) );
+  VERIFY( eq( std::proj(-cnn) , std::complex<long double>(pinf, +0.0) ) );
+
+  const std::complex<long double> cp0(pinf, 0);
+  VERIFY( eq( std::proj(cp0)  , std::complex<long double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cp0) , std::complex<long double>(pinf, -0.0) ) );
+
+  const std::complex<long double> cp1(pinf, 1);
+  VERIFY( eq( std::proj(cp1)  , std::complex<long double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cp1) , std::complex<long double>(pinf, -0.0) ) );
+
+  const std::complex<long double> cpq(pinf, qnan);
+  VERIFY( eq( std::proj(cpq)  , std::complex<long double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cpq) , std::complex<long double>(pinf, -0.0) ) );
+
+  const std::complex<long double> cn0(ninf, 0);
+  VERIFY( eq( std::proj(cn0)  , std::complex<long double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cn0) , std::complex<long double>(pinf, -0.0) ) );
+
+  const std::complex<long double> cn1(ninf, 1);
+  VERIFY( eq( std::proj(cn1)  , std::complex<long double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cn1) , std::complex<long double>(pinf, -0.0) ) );
+
+  const std::complex<long double> cnq(ninf, qnan);
+  VERIFY( eq( std::proj(cnq)  , std::complex<long double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cnq) , std::complex<long double>(pinf, -0.0) ) );
+
+  const std::complex<long double> cnp(ninf, pinf);
+  VERIFY( eq( std::proj(cnp)  , std::complex<long double>(pinf, +0.0) ) );
+  VERIFY( eq( std::proj(-cnp) , std::complex<long double>(pinf, -0.0) ) );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+}



More information about the Libstdc++-cvs mailing list