On 11/16/18 3:53 PM, Ed Smith-Rowland wrote:
On 11/16/18 12:38 PM, Daniel Krügler wrote:
Am Fr., 16. Nov. 2018 um 18:13 Uhr schrieb Ed Smith-Rowland
<3dw...@verizon.net>:
Greetings,

This is late but I wanted to put it out there just to finish a thing.

It's fairly straightforward constexpr of operators and some simple
functions for std::complex.

The only thing that jumped out was the norm function.  We had this:

      struct _Norm_helper<true>
      {
        template<typename _Tp>
          static inline _Tp _S_do_it(const complex<_Tp>& __z)
          {
            _Tp __res = std::abs(__z);
            return __res * __res;
          }
      };

Since abs can't be made constexpr for complex since it involves sqrt (It probably could but that's another story) I had to fall back to the x^2 +
y^2.  I don't know who that will bother.  This version should be faster
and I can't think of any useful trustworthy difference numerically
either in terms of accuracy of stability.

Barring any feedback on that I'll clean it up and maybe rename my tests
from constexpr_all_the_things.cc to more_constexpr.cc ;-)

It builds and tests cleanly on x86_64-linux.
Hmmh, according to the recent working draft the following complex
functions are *not* constexpr:

arg, proj

So, shouldn't their new C++20-constexpr specifiers be added
conditionally (In the sense of gcc extensions)?

- Daniel

I did not see that those were not constexpr.  I guess arg needs atan2 and proj

I'll remove the constexpr on those and adjust everything.

Thank you.

Ed

All,

Here is the cleaned up, conformant patch.

Builds and tests cleanly on x86_64-linux.

Is this OK or should I really wait?

Ed


2018-11-17  Edward Smith-Rowland  <3dw...@verizon.net>

        Implement P0415 More constexpr for std::complex.
        * include/std/complex (conj(complex<Tp>), norm(complex<Tp>)): Constexpr;
        (real(Tp), imag(Tp)): Constexpr;
        (operator@=(Tp), operator@=(complex<Tp>)): Constexpr;
        (operator@(Tp,complex<Tp>), operator@(complex<Tp>,Tp)
        operator@(complex<Tp>,complex<Tp>)): Constexpr.
        * testsuite/26_numerics/complex/comparison_operators/
        more_constexpr.cc: New test.
        * testsuite/26_numerics/complex/operators/more_constexpr.cc: New test.
        * testsuite/26_numerics/complex/requirements/
        more_constexpr.cc: New test.
        * testsuite/26_numerics/complex/value_operations/
        more_constexpr.cc: New test.
        * testsuite/26_numerics/headers/complex/synopsis.cc:
        Add _GLIBCXX20_CONSTEXPR to applicable operators; Add missing proj().
Index: include/std/complex
===================================================================
--- include/std/complex (revision 266189)
+++ include/std/complex (working copy)
@@ -70,10 +70,11 @@
   ///  Return phase angle of @a z.
   template<typename _Tp> _Tp arg(const complex<_Tp>&);
   ///  Return @a z magnitude squared.
-  template<typename _Tp> _Tp norm(const complex<_Tp>&);
+  template<typename _Tp> _Tp _GLIBCXX20_CONSTEXPR norm(const complex<_Tp>&);
 
   ///  Return complex conjugate of @a z.
-  template<typename _Tp> complex<_Tp> conj(const complex<_Tp>&);
+  template<typename _Tp>
+    _GLIBCXX20_CONSTEXPR complex<_Tp> conj(const complex<_Tp>&);
   ///  Return complex with magnitude @a rho and angle @a theta.
   template<typename _Tp> complex<_Tp> polar(const _Tp&, const _Tp& = 0);
 
@@ -169,18 +170,18 @@
 
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // DR 387. std::complex over-encapsulated.
-      void
+      _GLIBCXX20_CONSTEXPR void
       real(_Tp __val) { _M_real = __val; }
 
-      void
+      _GLIBCXX20_CONSTEXPR void
       imag(_Tp __val) { _M_imag = __val; }
 
       /// Assign a scalar to this complex number.
-      complex<_Tp>& operator=(const _Tp&);
+      _GLIBCXX20_CONSTEXPR complex<_Tp>& operator=(const _Tp&);
 
       /// Add a scalar to this complex number.
       // 26.2.5/1
-      complex<_Tp>&
+      _GLIBCXX20_CONSTEXPR complex<_Tp>&
       operator+=(const _Tp& __t)
       {
        _M_real += __t;
@@ -189,7 +190,7 @@
 
       /// Subtract a scalar from this complex number.
       // 26.2.5/3
-      complex<_Tp>&
+      _GLIBCXX20_CONSTEXPR complex<_Tp>&
       operator-=(const _Tp& __t)
       {
        _M_real -= __t;
@@ -197,30 +198,30 @@
       }
 
       /// Multiply this complex number by a scalar.
-      complex<_Tp>& operator*=(const _Tp&);
+      _GLIBCXX20_CONSTEXPR complex<_Tp>& operator*=(const _Tp&);
       /// Divide this complex number by a scalar.
-      complex<_Tp>& operator/=(const _Tp&);
+      _GLIBCXX20_CONSTEXPR complex<_Tp>& operator/=(const _Tp&);
 
       // Let the compiler synthesize the copy assignment operator
 #if __cplusplus >= 201103L
-      complex& operator=(const complex&) = default;
+      _GLIBCXX20_CONSTEXPR complex& operator=(const complex&) = default;
 #endif
 
       /// Assign another complex number to this one.
       template<typename _Up>
-        complex<_Tp>& operator=(const complex<_Up>&);
+        _GLIBCXX20_CONSTEXPR complex<_Tp>& operator=(const complex<_Up>&);
       /// Add another complex number to this one.
       template<typename _Up>
-        complex<_Tp>& operator+=(const complex<_Up>&);
+        _GLIBCXX20_CONSTEXPR complex<_Tp>& operator+=(const complex<_Up>&);
       /// Subtract another complex number from this one.
       template<typename _Up>
-        complex<_Tp>& operator-=(const complex<_Up>&);
+        _GLIBCXX20_CONSTEXPR complex<_Tp>& operator-=(const complex<_Up>&);
       /// Multiply this complex number by another.
       template<typename _Up>
-        complex<_Tp>& operator*=(const complex<_Up>&);
+        _GLIBCXX20_CONSTEXPR complex<_Tp>& operator*=(const complex<_Up>&);
       /// Divide this complex number by another.
       template<typename _Up>
-        complex<_Tp>& operator/=(const complex<_Up>&);
+        _GLIBCXX20_CONSTEXPR complex<_Tp>& operator/=(const complex<_Up>&);
 
       _GLIBCXX_CONSTEXPR complex __rep() const
       { return *this; }
@@ -231,7 +232,7 @@
     };
 
   template<typename _Tp>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator=(const _Tp& __t)
     {
      _M_real = __t;
@@ -241,7 +242,7 @@
 
   // 26.2.5/5
   template<typename _Tp>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator*=(const _Tp& __t)
     {
       _M_real *= __t;
@@ -251,7 +252,7 @@
 
   // 26.2.5/7
   template<typename _Tp>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator/=(const _Tp& __t)
     {
       _M_real /= __t;
@@ -261,7 +262,7 @@
 
   template<typename _Tp>
     template<typename _Up>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator=(const complex<_Up>& __z)
     {
       _M_real = __z.real();
@@ -272,7 +273,7 @@
   // 26.2.5/9
   template<typename _Tp>
     template<typename _Up>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator+=(const complex<_Up>& __z)
     {
       _M_real += __z.real();
@@ -283,7 +284,7 @@
   // 26.2.5/11
   template<typename _Tp>
     template<typename _Up>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator-=(const complex<_Up>& __z)
     {
       _M_real -= __z.real();
@@ -295,7 +296,7 @@
   // XXX: This is a grammar school implementation.
   template<typename _Tp>
     template<typename _Up>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator*=(const complex<_Up>& __z)
     {
       const _Tp __r = _M_real * __z.real() - _M_imag * __z.imag();
@@ -308,7 +309,7 @@
   // XXX: This is a grammar school implementation.
   template<typename _Tp>
     template<typename _Up>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator/=(const complex<_Up>& __z)
     {
       const _Tp __r =  _M_real * __z.real() + _M_imag * __z.imag();
@@ -322,67 +323,43 @@
   //@{
   ///  Return new complex value @a x plus @a y.
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator+(const complex<_Tp>& __x, const complex<_Tp>& __y)
-    {
-      complex<_Tp> __r = __x;
-      __r += __y;
-      return __r;
-    }
+    { return complex<_Tp>(__x.real() + __y.real(), __x.imag() + __y.imag()); }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator+(const complex<_Tp>& __x, const _Tp& __y)
-    {
-      complex<_Tp> __r = __x;
-      __r += __y;
-      return __r;
-    }
+    { return complex<_Tp>(__x.real() + __y, __x.imag()); }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator+(const _Tp& __x, const complex<_Tp>& __y)
-    {
-      complex<_Tp> __r = __y;
-      __r += __x;
-      return __r;
-    }
+    { return complex<_Tp>(__x + __y.real(), __y.imag()); }
   //@}
 
   //@{
   ///  Return new complex value @a x minus @a y.
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator-(const complex<_Tp>& __x, const complex<_Tp>& __y)
-    {
-      complex<_Tp> __r = __x;
-      __r -= __y;
-      return __r;
-    }
+    { return complex<_Tp>(__x.real() - __y.real(), __x.imag() - __y.imag()); }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator-(const complex<_Tp>& __x, const _Tp& __y)
-    {
-      complex<_Tp> __r = __x;
-      __r -= __y;
-      return __r;
-    }
+    { return complex<_Tp>(__x.real() - __y, __x.imag()); }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator-(const _Tp& __x, const complex<_Tp>& __y)
-    {
-      complex<_Tp> __r(__x, -__y.imag());
-      __r -= __y.real();
-      return __r;
-    }
+    { return complex<_Tp>(__x - __y.real(), -__y.imag()); }
   //@}
 
   //@{
   ///  Return new complex value @a x times @a y.
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator*(const complex<_Tp>& __x, const complex<_Tp>& __y)
     {
       complex<_Tp> __r = __x;
@@ -391,7 +368,7 @@
     }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator*(const complex<_Tp>& __x, const _Tp& __y)
     {
       complex<_Tp> __r = __x;
@@ -400,7 +377,7 @@
     }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator*(const _Tp& __x, const complex<_Tp>& __y)
     {
       complex<_Tp> __r = __y;
@@ -412,7 +389,7 @@
   //@{
   ///  Return new complex value @a x divided by @a y.
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator/(const complex<_Tp>& __x, const complex<_Tp>& __y)
     {
       complex<_Tp> __r = __x;
@@ -421,7 +398,7 @@
     }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator/(const complex<_Tp>& __x, const _Tp& __y)
     {
       complex<_Tp> __r = __x;
@@ -430,7 +407,7 @@
     }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator/(const _Tp& __x, const complex<_Tp>& __y)
     {
       complex<_Tp> __r = __x;
@@ -441,15 +418,15 @@
 
   ///  Return @a x.
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator+(const complex<_Tp>& __x)
     { return __x; }
 
   ///  Return complex negation of @a x.
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator-(const complex<_Tp>& __x)
-    {  return complex<_Tp>(-__x.real(), -__x.imag()); }
+    { return complex<_Tp>(-__x.real(), -__x.imag()); }
 
   //@{
   ///  Return true if @a x is equal to @a y.
@@ -658,7 +635,7 @@
     struct _Norm_helper
     {
       template<typename _Tp>
-        static inline _Tp _S_do_it(const complex<_Tp>& __z)
+        static inline _GLIBCXX_CONSTEXPR _Tp _S_do_it(const complex<_Tp>& __z)
         {
           const _Tp __x = __z.real();
           const _Tp __y = __z.imag();
@@ -670,15 +647,18 @@
     struct _Norm_helper<true>
     {
       template<typename _Tp>
-        static inline _Tp _S_do_it(const complex<_Tp>& __z)
+        static inline _GLIBCXX_CONSTEXPR _Tp _S_do_it(const complex<_Tp>& __z)
         {
-          _Tp __res = std::abs(__z);
-          return __res * __res;
+          //_Tp __res = std::abs(__z);
+          //return __res * __res;
+          const _Tp __x = __z.real();
+          const _Tp __y = __z.imag();
+          return __x * __x + __y * __y;
         }
     };
 
   template<typename _Tp>
-    inline _Tp
+    inline _GLIBCXX20_CONSTEXPR _Tp
     norm(const complex<_Tp>& __z)
     {
       return _Norm_helper<__is_floating<_Tp>::__value
@@ -694,7 +674,7 @@
     }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     conj(const complex<_Tp>& __z)
     { return complex<_Tp>(__z.real(), -__z.imag()); }
 
@@ -1115,13 +1095,13 @@
 
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // DR 387. std::complex over-encapsulated.
-      void
+      _GLIBCXX20_CONSTEXPR void
       real(float __val) { __real__ _M_value = __val; }
 
-      void
+      _GLIBCXX20_CONSTEXPR void
       imag(float __val) { __imag__ _M_value = __val; }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator=(float __f)
       {
        _M_value = __f;
@@ -1128,7 +1108,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator+=(float __f)
       {
        _M_value += __f;
@@ -1135,7 +1115,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator-=(float __f)
       {
        _M_value -= __f;
@@ -1142,7 +1122,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator*=(float __f)
       {
        _M_value *= __f;
@@ -1149,7 +1129,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator/=(float __f)
       {
        _M_value /= __f;
@@ -1163,50 +1143,43 @@
 #endif
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator=(const complex<_Tp>&  __z)
        {
-         __real__ _M_value = __z.real();
-         __imag__ _M_value = __z.imag();
+         _M_value = __z.__rep();
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator+=(const complex<_Tp>& __z)
        {
-         __real__ _M_value += __z.real();
-         __imag__ _M_value += __z.imag();
+         _M_value += __z.__rep();
          return *this;
        }
 
       template<class _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator-=(const complex<_Tp>& __z)
        {
-         __real__ _M_value -= __z.real();
-         __imag__ _M_value -= __z.imag();
+         _M_value -= __z.__rep();
          return *this;
        }
 
       template<class _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator*=(const complex<_Tp>& __z)
        {
-         _ComplexT __t;
-         __real__ __t = __z.real();
-         __imag__ __t = __z.imag();
+         const _ComplexT __t = __z.__rep();
          _M_value *= __t;
          return *this;
        }
 
       template<class _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator/=(const complex<_Tp>& __z)
        {
-         _ComplexT __t;
-         __real__ __t = __z.real();
-         __imag__ __t = __z.imag();
+         const _ComplexT __t = __z.__rep();
          _M_value /= __t;
          return *this;
        }
@@ -1268,13 +1241,13 @@
 
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // DR 387. std::complex over-encapsulated.
-      void
+      _GLIBCXX20_CONSTEXPR void
       real(double __val) { __real__ _M_value = __val; }
 
-      void
+      _GLIBCXX20_CONSTEXPR void
       imag(double __val) { __imag__ _M_value = __val; }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator=(double __d)
       {
        _M_value = __d;
@@ -1281,7 +1254,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator+=(double __d)
       {
        _M_value += __d;
@@ -1288,7 +1261,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator-=(double __d)
       {
        _M_value -= __d;
@@ -1295,7 +1268,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator*=(double __d)
       {
        _M_value *= __d;
@@ -1302,7 +1275,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator/=(double __d)
       {
        _M_value /= __d;
@@ -1315,50 +1288,43 @@
 #endif
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator=(const complex<_Tp>& __z)
        {
-         __real__ _M_value = __z.real();
-         __imag__ _M_value = __z.imag();
+         _M_value = __z.__rep();
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator+=(const complex<_Tp>& __z)
        {
-         __real__ _M_value += __z.real();
-         __imag__ _M_value += __z.imag();
+         _M_value += __z.__rep();
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator-=(const complex<_Tp>& __z)
        {
-         __real__ _M_value -= __z.real();
-         __imag__ _M_value -= __z.imag();
+         _M_value -= __z.__rep();
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator*=(const complex<_Tp>& __z)
        {
-         _ComplexT __t;
-         __real__ __t = __z.real();
-         __imag__ __t = __z.imag();
+         const _ComplexT __t = __z.__rep();
          _M_value *= __t;
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator/=(const complex<_Tp>& __z)
        {
-         _ComplexT __t;
-         __real__ __t = __z.real();
-         __imag__ __t = __z.imag();
+         const _ComplexT __t = __z.__rep();
          _M_value /= __t;
          return *this;
        }
@@ -1422,13 +1388,13 @@
 
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // DR 387. std::complex over-encapsulated.
-      void
+      _GLIBCXX20_CONSTEXPR void
       real(long double __val) { __real__ _M_value = __val; }
 
-      void
+      _GLIBCXX20_CONSTEXPR void
       imag(long double __val) { __imag__ _M_value = __val; }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator=(long double __r)
       {
        _M_value = __r;
@@ -1435,7 +1401,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator+=(long double __r)
       {
        _M_value += __r;
@@ -1442,7 +1408,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator-=(long double __r)
       {
        _M_value -= __r;
@@ -1449,7 +1415,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator*=(long double __r)
       {
        _M_value *= __r;
@@ -1456,7 +1422,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator/=(long double __r)
       {
        _M_value /= __r;
@@ -1469,50 +1435,43 @@
 #endif
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator=(const complex<_Tp>& __z)
        {
-         __real__ _M_value = __z.real();
-         __imag__ _M_value = __z.imag();
+         _M_value = __z.__rep();
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
        operator+=(const complex<_Tp>& __z)
        {
-         __real__ _M_value += __z.real();
-         __imag__ _M_value += __z.imag();
+         _M_value += __z.__rep();
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
        operator-=(const complex<_Tp>& __z)
        {
-         __real__ _M_value -= __z.real();
-         __imag__ _M_value -= __z.imag();
+         _M_value -= __z.__rep();
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
        operator*=(const complex<_Tp>& __z)
        {
-         _ComplexT __t;
-         __real__ __t = __z.real();
-         __imag__ __t = __z.imag();
+         const _ComplexT __t = __z.__rep();
          _M_value *= __t;
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
        operator/=(const complex<_Tp>& __z)
        {
-         _ComplexT __t;
-         __real__ __t = __z.real();
-         __imag__ __t = __z.imag();
+         const _ComplexT __t = __z.__rep();
          _M_value /= __t;
          return *this;
        }
@@ -1872,7 +1831,7 @@
     { return _Tp(); }
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type
+    _GLIBCXX_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type
     norm(_Tp __x)
     {
       typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
@@ -1911,7 +1870,8 @@
 
   // Forward declarations.
   // DR 781.
-  template<typename _Tp> std::complex<_Tp> proj(const std::complex<_Tp>&);
+  template<typename _Tp>
+    std::complex<_Tp> proj(const std::complex<_Tp>&);
 
   template<typename _Tp>
     std::complex<_Tp>
@@ -1957,7 +1917,8 @@
     }
 
   template<typename _Tp>
-    inline std::complex<typename __gnu_cxx::__promote<_Tp>::__type>
+    inline _GLIBCXX20_CONSTEXPR
+       std::complex<typename __gnu_cxx::__promote<_Tp>::__type>
     conj(_Tp __x)
     {
       typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
Index: testsuite/26_numerics/complex/comparison_operators/more_constexpr.cc
===================================================================
--- testsuite/26_numerics/complex/comparison_operators/more_constexpr.cc        
(nonexistent)
+++ testsuite/26_numerics/complex/comparison_operators/more_constexpr.cc        
(working copy)
@@ -0,0 +1,51 @@
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2018 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_common_types.h>
+
+template<bool ok>
+  struct thing
+  { };
+
+// 
+template<typename _Tp>
+  void
+  test_comparison()
+  {
+    constexpr std::complex<_Tp> a{1.1, 2.2};
+    constexpr std::complex<_Tp> b{3.3, 4.4};
+    if constexpr (a == b)
+      auto c [[maybe_unused]] = a + b;
+    if constexpr (a != b)
+      auto c [[maybe_unused]] = a - b;
+
+    thing<a == b> thing1 [[maybe_unused]];
+    thing<a != b> thing2 [[maybe_unused]];
+  }
+
+int
+main()
+{
+  test_comparison<float>();
+  test_comparison<double>();
+  test_comparison<long double>();
+
+  return 0;
+}
Index: testsuite/26_numerics/complex/operators/more_constexpr.cc
===================================================================
--- testsuite/26_numerics/complex/operators/more_constexpr.cc   (nonexistent)
+++ testsuite/26_numerics/complex/operators/more_constexpr.cc   (working copy)
@@ -0,0 +1,61 @@
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2018 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_common_types.h>
+
+namespace __gnu_test
+{
+  // Test constexpr symmetric complex @ real, real @ complex, complex @ 
complex.
+  template<typename _Tp>
+    void
+    test_operators()
+    {
+      constexpr std::complex<_Tp> a{1, 2};
+      constexpr std::complex<_Tp> b{3, 4};
+      constexpr _Tp c = 5;
+
+      constexpr auto w [[maybe_unused]] = +a;
+      constexpr auto z [[maybe_unused]] = -a;
+
+      constexpr auto apc [[maybe_unused]] = a + c;
+      constexpr auto amc [[maybe_unused]] = a - c;
+      constexpr auto atc [[maybe_unused]] = a * c;
+      constexpr auto adc [[maybe_unused]] = a / c;
+
+      constexpr auto cpa [[maybe_unused]] = c + a;
+      constexpr auto cma [[maybe_unused]] = c - a;
+      constexpr auto cta [[maybe_unused]] = c * a;
+      constexpr auto cda [[maybe_unused]] = c / a;
+
+      constexpr auto apb [[maybe_unused]] = a + b;
+      constexpr auto amb [[maybe_unused]] = a - b;
+      constexpr auto atb [[maybe_unused]] = a * b;
+      constexpr auto adb [[maybe_unused]] = a / b;
+    }
+}
+
+int main()
+{
+  __gnu_test::test_operators<float>();
+  __gnu_test::test_operators<double>();
+  __gnu_test::test_operators<long double>();
+
+  return 0;
+}
Index: testsuite/26_numerics/complex/requirements/more_constexpr.cc
===================================================================
--- testsuite/26_numerics/complex/requirements/more_constexpr.cc        
(nonexistent)
+++ testsuite/26_numerics/complex/requirements/more_constexpr.cc        
(working copy)
@@ -0,0 +1,170 @@
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2018 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_common_types.h>
+
+namespace __gnu_test
+{
+
+  // Test constexpr real(val) imag(val).
+  template<typename _Tp, const int _Val = 42>
+    inline void
+    set_real(std::complex<_Tp>& a)
+    { a.real(_Val); }
+
+  template<typename _Tp, const int _Val = 42>
+    inline void
+    set_imag(std::complex<_Tp>& a)
+    { a.imag(_Val); }
+
+  template<typename _Tp>
+    void
+    test_members()
+    {
+      constexpr std::complex<_Tp> a{1.1, 2.2};
+
+      std::complex<_Tp> z = a;
+
+      set_real<_Tp, 33>(z);
+      set_imag<_Tp, 44>(z);
+    }
+
+  // Test operators @=complex and @=real.
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    sum(const std::complex<_Tp>& z, const std::complex<_Up>& w)
+    {
+      std::complex<_Tp> x = z;
+      x += w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    sum(const std::complex<_Tp>& z, _Up w)
+    {
+      std::complex<_Tp> x = z;
+      x += w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    dif(const std::complex<_Tp>& z, const std::complex<_Up>& w)
+    {
+      std::complex<_Tp> x = z;
+      x -= w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    dif(const std::complex<_Tp>& z, _Up w)
+    {
+      std::complex<_Tp> x = z;
+      x -= w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    prod(const std::complex<_Tp>& z, const std::complex<_Up>& w)
+    {
+      std::complex<_Tp> x = z;
+      x *= w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    prod(const std::complex<_Tp>& z, _Up w)
+    {
+      std::complex<_Tp> x = z;
+      x *= w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    quot(const std::complex<_Tp>& z, const std::complex<_Up>& w)
+    {
+      std::complex<_Tp> x = z;
+      x /= w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    quot(const std::complex<_Tp>& z, _Up w)
+    {
+      std::complex<_Tp> x = z;
+      x /= w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    void
+    test_operator_members()
+    {
+      constexpr std::complex<_Tp> a{10, 20};
+      constexpr std::complex<_Up> b{6, 8};
+      constexpr _Up c{10};
+
+      constexpr auto apc = sum(a, c);
+      static_assert(apc == std::complex<_Tp>{20, 20});
+      constexpr auto amc = dif(a, c);
+      static_assert(amc == std::complex<_Tp>{0, 20});
+      constexpr auto atc = prod(a, c);
+      static_assert(atc == std::complex<_Tp>{100, 200});
+      constexpr auto adc = quot(a, c);
+      static_assert(adc == std::complex<_Tp>{1, 2});
+
+      constexpr auto apb = sum(a, b);
+      static_assert(apb == std::complex<_Tp>{16, 28});
+      constexpr auto amb = dif(a, b);
+      static_assert(amb == std::complex<_Tp>{4, 12});
+      constexpr auto atb = prod(a, b);
+      static_assert(atb == std::complex<_Tp>{-100, 200});
+      constexpr auto adb = quot(a, b);
+      static_assert(adb == std::complex<_Tp>{11/_Tp{5}, 2/_Tp{5}});
+    }
+}
+
+int main()
+{
+  __gnu_test::test_members<float>();
+  __gnu_test::test_members<double>();
+  __gnu_test::test_members<long double>();
+
+  __gnu_test::test_operator_members<float, float>();
+  __gnu_test::test_operator_members<float, double>();
+  __gnu_test::test_operator_members<float, long double>();
+  __gnu_test::test_operator_members<double, float>();
+  __gnu_test::test_operator_members<double, double>();
+  __gnu_test::test_operator_members<double, long double>();
+  __gnu_test::test_operator_members<long double, float>();
+  __gnu_test::test_operator_members<long double, double>();
+  __gnu_test::test_operator_members<long double, long double>();
+
+  // Test primary template.
+  __gnu_test::test_operator_members<__float128, __float128>();
+
+  return 0;
+}
Index: testsuite/26_numerics/complex/value_operations/more_constexpr.cc
===================================================================
--- testsuite/26_numerics/complex/value_operations/more_constexpr.cc    
(nonexistent)
+++ testsuite/26_numerics/complex/value_operations/more_constexpr.cc    
(working copy)
@@ -0,0 +1,58 @@
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2018 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_common_types.h>
+
+namespace __gnu_test
+{
+  struct constexpr_functions
+  {
+    template<typename _Ttesttype>
+      void
+      operator()()
+      {
+       struct _Concept
+       {
+         void __constraint()
+         { 
+           typedef typename _Ttesttype::_ComplexT _ComplexT;
+           constexpr _ComplexT cc = { 1.1 };
+           constexpr _Ttesttype a(cc);
+           constexpr auto v1 [[maybe_unused]] = norm(a);
+           constexpr auto v2 [[maybe_unused]] = conj(a);
+         }
+       };
+
+       _Concept c;
+       c.__constraint();
+      }
+  };
+}
+
+int main()
+{
+  __gnu_test::constexpr_functions test;
+
+  test.operator()<std::complex<float>>();
+  test.operator()<std::complex<double>>();
+  test.operator()<std::complex<long double>>();
+
+  return 0;
+}
Index: testsuite/26_numerics/headers/complex/synopsis.cc
===================================================================
--- testsuite/26_numerics/headers/complex/synopsis.cc   (revision 266189)
+++ testsuite/26_numerics/headers/complex/synopsis.cc   (working copy)
@@ -28,51 +28,71 @@
 
   // 26.2.6 operators:
   template<class T>
-    complex<T> operator+(const complex<T>&, const complex<T>&);
-  template<class T> complex<T> operator+(const complex<T>&, const T&);
-  template<class T> complex<T> operator+(const T&, const complex<T>&);
-  template<class T> complex<T> operator-
+    _GLIBCXX20_CONSTEXPR complex<T>
+    operator+(const complex<T>&, const complex<T>&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator+(const complex<T>&, const T&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator+(const T&, const complex<T>&);
+
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T>
+    operator-(const complex<T>&, const complex<T>&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator-(const complex<T>&, const T&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator-(const T&, const complex<T>&);
+
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator*
     (const complex<T>&, const complex<T>&);
-  template<class T> complex<T> operator-(const complex<T>&, const T&);
-  template<class T> complex<T> operator-(const T&, const complex<T>&);
-  template<class T> complex<T> operator*
-    (const complex<T>&, const complex<T>&);
-  template<class T> complex<T> operator*(const complex<T>&, const T&);
-  template<class T> complex<T> operator*(const T&, const complex<T>&);
-  template<class T> complex<T> operator/
-    (const complex<T>&, const complex<T>&);
-  template<class T> complex<T> operator/(const complex<T>&, const T&);
-  template<class T> complex<T> operator/(const T&, const complex<T>&);
-  template<class T> complex<T> operator+(const complex<T>&);
-  template<class T> complex<T> operator-(const complex<T>&);
-  template<class T> _GLIBCXX_CONSTEXPR bool operator==
-    (const complex<T>&, const complex<T>&);
-  template<class T> _GLIBCXX_CONSTEXPR bool operator==
-    (const complex<T>&, const T&);
-  template<class T> _GLIBCXX_CONSTEXPR bool operator==
-    (const T&, const complex<T>&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator*(const complex<T>&, const T&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator*(const T&, const complex<T>&);
 
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T>
+    operator/(const complex<T>&, const complex<T>&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator/(const complex<T>&, const T&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator/(const T&, const complex<T>&);
 
-  template<class T> _GLIBCXX_CONSTEXPR bool operator!=
-    (const complex<T>&, const complex<T>&);
-  template<class T> _GLIBCXX_CONSTEXPR bool operator!=
-    (const complex<T>&, const T&);
-  template<class T> _GLIBCXX_CONSTEXPR bool operator!=
-    (const T&, const complex<T>&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator+(const complex<T>&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator-(const complex<T>&);
+
+  template<class T>
+    _GLIBCXX_CONSTEXPR bool operator==(const complex<T>&, const complex<T>&);
+  template<class T>
+     _GLIBCXX_CONSTEXPR bool operator==(const complex<T>&, const T&);
+  template<class T>
+    _GLIBCXX_CONSTEXPR bool operator==(const T&, const complex<T>&);
+
+  template<class T>
+    _GLIBCXX_CONSTEXPR bool operator!=(const complex<T>&, const complex<T>&);
+  template<class T>
+    _GLIBCXX_CONSTEXPR bool operator!=(const complex<T>&, const T&);
+  template<class T>
+    _GLIBCXX_CONSTEXPR bool operator!=(const T&, const complex<T>&);
+
   template<class T, class charT, class traits>
-  basic_istream<charT, traits>&
-  operator>>(basic_istream<charT, traits>&, complex<T>&);
+    basic_istream<charT, traits>&
+    operator>>(basic_istream<charT, traits>&, complex<T>&);
   template<class T, class charT, class traits>
-  basic_ostream<charT, traits>&
-  operator<<(basic_ostream<charT, traits>&, const complex<T>&);
+    basic_ostream<charT, traits>&
+    operator<<(basic_ostream<charT, traits>&, const complex<T>&);
 
   // 26.2.7 values:
   template<class T> _GLIBCXX_CONSTEXPR T real(const complex<T>&);
   template<class T> _GLIBCXX_CONSTEXPR T imag(const complex<T>&);
   template<class T> T abs(const complex<T>&);
-  template<class T> T arg(const complex<T>&);
-  template<class T> T norm(const complex<T>&);
-  template<class T> complex<T> conj(const complex<T>&);
+  template<class T> _GLIBCXX20_CONSTEXPR T arg(const complex<T>&);
+  template<class T> _GLIBCXX20_CONSTEXPR T norm(const complex<T>&);
+  template<class T> _GLIBCXX20_CONSTEXPR complex<T> conj(const complex<T>&);
+  template<class T> _GLIBCXX20_CONSTEXPR complex<T> proj(const complex<T>&);
   template<class T> complex<T> polar(const T& rho, const T& theta);
 
   // 26.2.8 transcendentals:

Reply via email to