From patchwork Fri Nov 16 17:13:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ed Smith-Rowland <3dw4rd@verizon.net> X-Patchwork-Id: 999097 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-490311-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=verizon.net Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="txGs3pwg"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=yahoo.com header.i=@yahoo.com header.b="myfzuPUa"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42xPvn022mz9s47 for ; Sat, 17 Nov 2018 04:13:40 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=Ewk2iIixPu2xkbXqyyaUoyK+IsFSLj1+c9Ro5HxZJMlHJdQUqC 1T5KZ0bw8/MjyZ3WcelKL5T3u+f2Xv8z4VKmt03ijY6bejMeWgOlrwRb61dQByzr TvsupibHHheDDBU/gvNEoXoi78OWxvGfdkl2jRU34bXB5mR/SdiacRqLc= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=Wc2/Br2d9kXWhah9geQN6vKsIVM=; b=txGs3pwgGjZf03PTNwsD 0GVqbnSYY1h3VVew56ZHwmk32v/ZdBkkv5taR9206inxCgawV74PKwMXU3IZ9KRu TjvE2ZxS8t7CoKRndK+Gvmh/J7NHyENskN71o/pkUhr3ZGUwcffzzzdsGC9bewV+ C46RVwuOH+FYqDv1C1SqVUg= Received: (qmail 15395 invoked by alias); 16 Nov 2018 17:13:31 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 15376 invoked by uid 89); 16 Nov 2018 17:13:30 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-7.7 required=5.0 tests=AWL, BAYES_20, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_NEUTRAL autolearn=ham version=3.3.2 spammy=H*F:D*verizon.net, trustworthy, school, stability X-HELO: sonic304-11.consmr.mail.bf2.yahoo.com Received: from sonic304-11.consmr.mail.bf2.yahoo.com (HELO sonic304-11.consmr.mail.bf2.yahoo.com) (74.6.128.34) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 16 Nov 2018 17:13:25 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1542388403; bh=7h6jiKv1KhImeBrtKfEoI13F474+QAEeCvl01j81v4I=; h=To:From:Subject:Date:From:Subject; b=myfzuPUa1CUoNM4aOQNRwq/xWKxIntnZxilYgyBe5SE30wgXbIKY/kMczDL0+fPTH2ied+s7MLYYpqbH4IPW6GbmN3TXwc2GWHEthv+Upos75nQT3C84+ZPdXbhcxOK43PfjWljV8GMOpNkSwaZHij80QAJ5SukW8EWIByTt3xkJExMSTlbBB1eSDqsEwYdRIadN+5TNzJ1GRcdYajNgJVL8+ZWEgY0j0rhhKBxl/Y6Xj7pkB6O9KB4gc9+HcQr6EJqXGM7a3neI8pIm+CMRmuHa0AKgNF0Vl74UsfYmrYUw1CN3TGeuHkwJ9hY/F8jpSBm8P1WCkl4ybhIp3eGkeA== Received: from sonic.gate.mail.ne1.yahoo.com by sonic304.consmr.mail.bf2.yahoo.com with HTTP; Fri, 16 Nov 2018 17:13:23 +0000 Received: from pool-173-64-121-45.bltmmd.fios.verizon.net (EHLO [192.168.1.3]) ([173.64.121.45]) by smtp401.mail.bf1.yahoo.com (Oath Hermes SMTP Server) with ESMTPA ID 75b3b4d50128c14a73d21cb09d9abb8b; Fri, 16 Nov 2018 17:13:20 +0000 (UTC) To: "libstdc++@gcc.gnu.org" , gcc-patches , Jonathan Wakely From: Ed Smith-Rowland <3dw4rd@verizon.net> Subject: [PATCH, libstdc++] Implement P0415 More constexpr for std::complex. Message-ID: <5e2b3a30-fd0c-351d-256c-b70e060d4994@verizon.net> Date: Fri, 16 Nov 2018 12:13:19 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 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     {       template         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 <3dw4rd@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)): Constexpr. (operator@(Tp,complex), operator@(complex,Tp) operator@(complex,complex)): 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 _Tp abs(const complex<_Tp>&); /// Return phase angle of @a z. - template _Tp arg(const complex<_Tp>&); + template _Tp _GLIBCXX20_CONSTEXPR arg(const complex<_Tp>&); /// Return @a z magnitude squared. - template _Tp norm(const complex<_Tp>&); + template _Tp _GLIBCXX20_CONSTEXPR norm(const complex<_Tp>&); /// Return complex conjugate of @a z. - template complex<_Tp> conj(const complex<_Tp>&); + template + _GLIBCXX20_CONSTEXPR complex<_Tp> conj(const complex<_Tp>&); /// Return complex with magnitude @a rho and angle @a theta. template 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 - complex<_Tp>& operator=(const complex<_Up>&); + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator=(const complex<_Up>&); /// Add another complex number to this one. template - complex<_Tp>& operator+=(const complex<_Up>&); + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator+=(const complex<_Up>&); /// Subtract another complex number from this one. template - complex<_Tp>& operator-=(const complex<_Up>&); + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator-=(const complex<_Up>&); /// Multiply this complex number by another. template - complex<_Tp>& operator*=(const complex<_Up>&); + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator*=(const complex<_Up>&); /// Divide this complex number by another. template - 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 - complex<_Tp>& + _GLIBCXX20_CONSTEXPR complex<_Tp>& complex<_Tp>::operator=(const _Tp& __t) { _M_real = __t; @@ -241,7 +242,7 @@ // 26.2.5/5 template - complex<_Tp>& + _GLIBCXX20_CONSTEXPR complex<_Tp>& complex<_Tp>::operator*=(const _Tp& __t) { _M_real *= __t; @@ -251,7 +252,7 @@ // 26.2.5/7 template - complex<_Tp>& + _GLIBCXX20_CONSTEXPR complex<_Tp>& complex<_Tp>::operator/=(const _Tp& __t) { _M_real /= __t; @@ -261,7 +262,7 @@ template template - 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 template - 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 template - 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 template - 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 template - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - inline complex<_Tp> + inline _GLIBCXX20_CONSTEXPR complex<_Tp> operator+(const complex<_Tp>& __x) { return __x; } /// Return complex negation of @a x. template - 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 - 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 - inline _Tp + inline _GLIBCXX20_CONSTEXPR _Tp arg(const complex<_Tp>& __z) { return __complex_arg(__z.__rep()); } #else template - inline _Tp + inline _GLIBCXX20_CONSTEXPR _Tp arg(const complex<_Tp>& __z) { return __complex_arg(__z); } #endif @@ -658,7 +635,7 @@ struct _Norm_helper { template - 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 { template - 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 - inline _Tp + inline _GLIBCXX20_CONSTEXPR _Tp norm(const complex<_Tp>& __z) { return _Norm_helper<__is_floating<_Tp>::__value @@ -694,7 +674,7 @@ } template - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 std::complex<_Tp> proj(const std::complex<_Tp>&); + template + _GLIBCXX20_CONSTEXPR std::complex<_Tp> proj(const std::complex<_Tp>&); template - 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 - inline std::complex<_Tp> + inline _GLIBCXX20_CONSTEXPR std::complex<_Tp> proj(const std::complex<_Tp>& __z) { return __complex_proj(__z.__rep()); } #else template - inline std::complex<_Tp> + inline _GLIBCXX20_CONSTEXPR std::complex<_Tp> proj(const std::complex<_Tp>& __z) { return __complex_proj(__z); } #endif template - inline std::complex::__type> + inline _GLIBCXX20_CONSTEXPR + std::complex::__type> proj(_Tp __x) { typedef typename __gnu_cxx::__promote<_Tp>::__type __type; @@ -1957,7 +1918,8 @@ } template - inline std::complex::__type> + inline _GLIBCXX20_CONSTEXPR + std::complex::__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 - complex operator+(const complex&, const complex&); - template complex operator+(const complex&, const T&); - template complex operator+(const T&, const complex&); - template complex operator- + _GLIBCXX20_CONSTEXPR complex + operator+(const complex&, const complex&); + template + _GLIBCXX20_CONSTEXPR complex operator+(const complex&, const T&); + template + _GLIBCXX20_CONSTEXPR complex operator+(const T&, const complex&); + + template + _GLIBCXX20_CONSTEXPR complex + operator-(const complex&, const complex&); + template + _GLIBCXX20_CONSTEXPR complex operator-(const complex&, const T&); + template + _GLIBCXX20_CONSTEXPR complex operator-(const T&, const complex&); + + template + _GLIBCXX20_CONSTEXPR complex operator* (const complex&, const complex&); - template complex operator-(const complex&, const T&); - template complex operator-(const T&, const complex&); - template complex operator* - (const complex&, const complex&); - template complex operator*(const complex&, const T&); - template complex operator*(const T&, const complex&); - template complex operator/ - (const complex&, const complex&); - template complex operator/(const complex&, const T&); - template complex operator/(const T&, const complex&); - template complex operator+(const complex&); - template complex operator-(const complex&); - template _GLIBCXX_CONSTEXPR bool operator== - (const complex&, const complex&); - template _GLIBCXX_CONSTEXPR bool operator== - (const complex&, const T&); - template _GLIBCXX_CONSTEXPR bool operator== - (const T&, const complex&); + template + _GLIBCXX20_CONSTEXPR complex operator*(const complex&, const T&); + template + _GLIBCXX20_CONSTEXPR complex operator*(const T&, const complex&); + template + _GLIBCXX20_CONSTEXPR complex + operator/(const complex&, const complex&); + template + _GLIBCXX20_CONSTEXPR complex operator/(const complex&, const T&); + template + _GLIBCXX20_CONSTEXPR complex operator/(const T&, const complex&); - template _GLIBCXX_CONSTEXPR bool operator!= - (const complex&, const complex&); - template _GLIBCXX_CONSTEXPR bool operator!= - (const complex&, const T&); - template _GLIBCXX_CONSTEXPR bool operator!= - (const T&, const complex&); + template + _GLIBCXX20_CONSTEXPR complex operator+(const complex&); + template + _GLIBCXX20_CONSTEXPR complex operator-(const complex&); + + template + _GLIBCXX_CONSTEXPR bool operator==(const complex&, const complex&); + template + _GLIBCXX_CONSTEXPR bool operator==(const complex&, const T&); + template + _GLIBCXX_CONSTEXPR bool operator==(const T&, const complex&); + + template + _GLIBCXX_CONSTEXPR bool operator!=(const complex&, const complex&); + template + _GLIBCXX_CONSTEXPR bool operator!=(const complex&, const T&); + template + _GLIBCXX_CONSTEXPR bool operator!=(const T&, const complex&); + template - basic_istream& - operator>>(basic_istream&, complex&); + basic_istream& + operator>>(basic_istream&, complex&); template - basic_ostream& - operator<<(basic_ostream&, const complex&); + basic_ostream& + operator<<(basic_ostream&, const complex&); // 26.2.7 values: template _GLIBCXX_CONSTEXPR T real(const complex&); template _GLIBCXX_CONSTEXPR T imag(const complex&); template T abs(const complex&); - template T arg(const complex&); - template T norm(const complex&); - template complex conj(const complex&); + template _GLIBCXX20_CONSTEXPR T arg(const complex&); + template _GLIBCXX20_CONSTEXPR T norm(const complex&); + template _GLIBCXX20_CONSTEXPR complex conj(const complex&); + template _GLIBCXX20_CONSTEXPR complex proj(const complex&); template complex 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 +// . + +#include +#include + +template + struct thing + { }; + +// +template + 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 thing1 [[maybe_unused]]; + thing thing2 [[maybe_unused]]; + } + +int +main() +{ + test_comparison(); + test_comparison(); + test_comparison(); + + 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 +// . + +#include +#include + +namespace __gnu_test +{ + // Test constexpr symmetric complex @ real, real @ complex, complex @ complex. + template + 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(); + __gnu_test::test_operators(); + __gnu_test::test_operators(); + + 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 +// . + +#include +#include + +namespace __gnu_test +{ + + // Test constexpr real(val) imag(val). + template + inline void + set_real(std::complex<_Tp>& a) + { a.real(_Val); } + + template + inline void + set_imag(std::complex<_Tp>& a) + { a.imag(_Val); } + + template + 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 + 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 + constexpr std::complex<_Tp> + sum(const std::complex<_Tp>& z, _Up w) + { + std::complex<_Tp> x = z; + x += w; + return x; + } + + template + 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 + constexpr std::complex<_Tp> + dif(const std::complex<_Tp>& z, _Up w) + { + std::complex<_Tp> x = z; + x -= w; + return x; + } + + template + 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 + constexpr std::complex<_Tp> + prod(const std::complex<_Tp>& z, _Up w) + { + std::complex<_Tp> x = z; + x *= w; + return x; + } + + template + 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 + constexpr std::complex<_Tp> + quot(const std::complex<_Tp>& z, _Up w) + { + std::complex<_Tp> x = z; + x /= w; + return x; + } + + template + 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(); + __gnu_test::test_members(); + __gnu_test::test_members(); + + __gnu_test::test_operator_members(); + __gnu_test::test_operator_members(); + __gnu_test::test_operator_members(); + __gnu_test::test_operator_members(); + __gnu_test::test_operator_members(); + __gnu_test::test_operator_members(); + __gnu_test::test_operator_members(); + __gnu_test::test_operator_members(); + __gnu_test::test_operator_members(); + + // 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 +// . + +#include +#include + +namespace __gnu_test +{ + struct constexpr_functions + { + template + 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()>(); + test.operator()>(); + test.operator()>(); + + return 0; +}