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.

Ed



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

        Implement P0415 More constexpr for std::complex.
        * include/std/complex (proj(), norm(), conj(), arg()): 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/
        constexpr_all_the_things.cc: New test.
        * testsuite/26_numerics/complex/operators/
        constexpr_all_the_things.cc: New test.
        * testsuite/26_numerics/complex/requirements/
        constexpr_all_the_things.cc: New test.
        * testsuite/26_numerics/complex/value_operations/
        constexpr_all_the_things.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)
@@ -68,12 +68,13 @@
   ///  Return magnitude of @a z.
   template<typename _Tp> _Tp abs(const complex<_Tp>&);
   ///  Return phase angle of @a z.
-  template<typename _Tp> _Tp arg(const complex<_Tp>&);
+  template<typename _Tp> _Tp _GLIBCXX20_CONSTEXPR 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.
@@ -625,27 +602,27 @@
 
   // 26.2.7/4: arg(__z): Returns the phase angle of __z.
   template<typename _Tp>
-    inline _Tp
+    inline _GLIBCXX20_CONSTEXPR _Tp
     __complex_arg(const complex<_Tp>& __z)
     { return  atan2(__z.imag(), __z.real()); }
 
 #if _GLIBCXX_USE_C99_COMPLEX
-  inline float
+  inline _GLIBCXX20_CONSTEXPR float
   __complex_arg(__complex__ float __z) { return __builtin_cargf(__z); }
 
-  inline double
+  inline _GLIBCXX20_CONSTEXPR double
   __complex_arg(__complex__ double __z) { return __builtin_carg(__z); }
 
-  inline long double
+  inline _GLIBCXX20_CONSTEXPR long double
   __complex_arg(const __complex__ long double& __z)
   { return __builtin_cargl(__z); }
 
   template<typename _Tp>
-    inline _Tp
+    inline _GLIBCXX20_CONSTEXPR _Tp
     arg(const complex<_Tp>& __z) { return __complex_arg(__z.__rep()); }
 #else
   template<typename _Tp>
-    inline _Tp
+    inline _GLIBCXX20_CONSTEXPR _Tp
     arg(const complex<_Tp>& __z) { return __complex_arg(__z); }
 #endif
 
@@ -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;
        }
@@ -1854,7 +1813,7 @@
 
   /// Additional overloads [8.1.9].
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type
+    inline _GLIBCXX20_CONSTEXPR typename __gnu_cxx::__promote<_Tp>::__type
     arg(_Tp __x)
     {
       typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
@@ -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,10 +1870,11 @@
 
   // Forward declarations.
   // DR 781.
-  template<typename _Tp> std::complex<_Tp> proj(const std::complex<_Tp>&);
+  template<typename _Tp>
+    _GLIBCXX20_CONSTEXPR std::complex<_Tp> proj(const std::complex<_Tp>&);
 
   template<typename _Tp>
-    std::complex<_Tp>
+    _GLIBCXX20_CONSTEXPR std::complex<_Tp>
     __complex_proj(const std::complex<_Tp>& __z)
     {
       const _Tp __den = (__z.real() * __z.real()
@@ -1925,31 +1885,32 @@
     }
 
 #if _GLIBCXX_USE_C99_COMPLEX
-  inline __complex__ float
+  inline _GLIBCXX20_CONSTEXPR __complex__ float
   __complex_proj(__complex__ float __z)
   { return __builtin_cprojf(__z); }
 
-  inline __complex__ double
+  inline _GLIBCXX20_CONSTEXPR __complex__ double
   __complex_proj(__complex__ double __z)
   { return __builtin_cproj(__z); }
 
-  inline __complex__ long double
+  inline _GLIBCXX20_CONSTEXPR __complex__ long double
   __complex_proj(const __complex__ long double& __z)
   { return __builtin_cprojl(__z); }
 
   template<typename _Tp>
-    inline std::complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR std::complex<_Tp>
     proj(const std::complex<_Tp>& __z)
     { return __complex_proj(__z.__rep()); }
 #else
   template<typename _Tp>
-    inline std::complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR std::complex<_Tp>
     proj(const std::complex<_Tp>& __z)
     { return __complex_proj(__z); }
 #endif
 
   template<typename _Tp>
-    inline std::complex<typename __gnu_cxx::__promote<_Tp>::__type>
+    inline _GLIBCXX20_CONSTEXPR
+       std::complex<typename __gnu_cxx::__promote<_Tp>::__type>
     proj(_Tp __x)
     {
       typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
@@ -1957,7 +1918,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/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:
Index: 
testsuite/26_numerics/complex/comparison_operators/constexpr_all_the_things.cc
===================================================================
--- 
testsuite/26_numerics/complex/comparison_operators/constexpr_all_the_things.cc  
    (nonexistent)
+++ 
testsuite/26_numerics/complex/comparison_operators/constexpr_all_the_things.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/constexpr_all_the_things.cc
===================================================================
--- testsuite/26_numerics/complex/operators/constexpr_all_the_things.cc 
(nonexistent)
+++ testsuite/26_numerics/complex/operators/constexpr_all_the_things.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/constexpr_all_the_things.cc
===================================================================
--- testsuite/26_numerics/complex/requirements/constexpr_all_the_things.cc      
(nonexistent)
+++ testsuite/26_numerics/complex/requirements/constexpr_all_the_things.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/constexpr_all_the_things.cc
===================================================================
--- testsuite/26_numerics/complex/value_operations/constexpr_all_the_things.cc  
(nonexistent)
+++ testsuite/26_numerics/complex/value_operations/constexpr_all_the_things.cc  
(working copy)
@@ -0,0 +1,60 @@
+// { 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);
+           constexpr auto v3 [[maybe_unused]] = proj(a);
+           constexpr auto v4 [[maybe_unused]] = arg(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;
+}

Reply via email to