From db5ab3aa920cee83ecda219f0faa1e35ed1e3864 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 14 Jun 2018 20:36:54 +0100 Subject: [PATCH] LWG 3074 make scalar types non-deduced in valarray non-member functions * include/bits/valarray_after.h (_DEFINE_EXPR_BINARY_FUNCTION): Change scalar parameters to be a non-deduced context. * include/std/valarray (_DEFINE_BINARY_OPERATOR): Likewise. Adjust whitespace. * testsuite/26_numerics/valarray/operators.cc: Test scalar operands. * testsuite/26_numerics/valarray/transcend.cc: New. From-SVN: r261610 --- libstdc++-v3/ChangeLog | 8 ++ libstdc++-v3/doc/xml/manual/intro.xml | 8 ++ libstdc++-v3/include/bits/valarray_after.h | 6 +- libstdc++-v3/include/std/valarray | 42 ++++---- .../26_numerics/valarray/operators.cc | 47 +++++++- .../26_numerics/valarray/transcend.cc | 100 ++++++++++++++++++ 6 files changed, 188 insertions(+), 23 deletions(-) create mode 100644 libstdc++-v3/testsuite/26_numerics/valarray/transcend.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 2bfda083ee3..6db36225c1f 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,13 @@ 2018-06-14 Jonathan Wakely + LWG 3074 make scalar types non-deduced in valarray non-member functions + * include/bits/valarray_after.h (_DEFINE_EXPR_BINARY_FUNCTION): Change + scalar parameters to be a non-deduced context. + * include/std/valarray (_DEFINE_BINARY_OPERATOR): Likewise. Adjust + whitespace. + * testsuite/26_numerics/valarray/operators.cc: Test scalar operands. + * testsuite/26_numerics/valarray/transcend.cc: New. + * include/std/tuple (__cpp_lib_tuple_element_t, tuple_element_t): Move back to . * include/std/utility (__cpp_lib_tuple_element_t. tuple_element_t): diff --git a/libstdc++-v3/doc/xml/manual/intro.xml b/libstdc++-v3/doc/xml/manual/intro.xml index 38b6eb36477..b0fc131d1eb 100644 --- a/libstdc++-v3/doc/xml/manual/intro.xml +++ b/libstdc++-v3/doc/xml/manual/intro.xml @@ -1160,6 +1160,14 @@ requirements of the license of GCC. Add noexcept. + 3074: + Non-member functions for valarray should only deduce from the valarray + + + Change scalar operands to be non-deduced context, so that + they will allow conversions from other types to the value_type. + + diff --git a/libstdc++-v3/include/bits/valarray_after.h b/libstdc++-v3/include/bits/valarray_after.h index bb1a3c9b513..d2ba76d54c5 100644 --- a/libstdc++-v3/include/bits/valarray_after.h +++ b/libstdc++-v3/include/bits/valarray_after.h @@ -529,7 +529,8 @@ namespace __detail \ template \ inline _Expr<_BinClos<_UFun, _ValArray, _Constant, _Tp, _Tp>, _Tp> \ - _Fun(const valarray<_Tp>& __v, const _Tp& __t) \ + _Fun(const valarray<_Tp>& __v, \ + const typename valarray<_Tp>::value_type& __t) \ { \ typedef _BinClos<_UFun, _ValArray, _Constant, _Tp, _Tp> _Closure;\ return _Expr<_Closure, _Tp>(_Closure(__v, __t)); \ @@ -537,7 +538,8 @@ namespace __detail \ template \ inline _Expr<_BinClos<_UFun, _Constant, _ValArray, _Tp, _Tp>, _Tp> \ - _Fun(const _Tp& __t, const valarray<_Tp>& __v) \ + _Fun(const typename valarray<_Tp>::value_type& __t, \ + const valarray<_Tp>& __v) \ { \ typedef _BinClos<_UFun, _Constant, _ValArray, _Tp, _Tp> _Closure;\ return _Expr<_Closure, _Tp>(_Closure(__t, __v)); \ diff --git a/libstdc++-v3/include/std/valarray b/libstdc++-v3/include/std/valarray index 03e0badfc53..7b446fdf9eb 100644 --- a/libstdc++-v3/include/std/valarray +++ b/libstdc++-v3/include/std/valarray @@ -1078,11 +1078,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #define _DEFINE_VALARRAY_UNARY_OPERATOR(_Op, _Name) \ template \ - inline typename valarray<_Tp>::template _UnaryOp<_Name>::_Rt \ + inline typename valarray<_Tp>::template _UnaryOp<_Name>::_Rt \ valarray<_Tp>::operator _Op() const \ { \ - typedef _UnClos<_Name, _ValArray, _Tp> _Closure; \ - typedef typename __fun<_Name, _Tp>::result_type _Rt; \ + typedef _UnClos<_Name, _ValArray, _Tp> _Closure; \ + typedef typename __fun<_Name, _Tp>::result_type _Rt; \ return _Expr<_Closure, _Rt>(_Closure(*this)); \ } @@ -1150,34 +1150,36 @@ _DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(>>, __shift_right) #define _DEFINE_BINARY_OPERATOR(_Op, _Name) \ template \ - inline _Expr<_BinClos<_Name, _ValArray, _ValArray, _Tp, _Tp>, \ - typename __fun<_Name, _Tp>::result_type> \ + inline _Expr<_BinClos<_Name, _ValArray, _ValArray, _Tp, _Tp>, \ + typename __fun<_Name, _Tp>::result_type> \ operator _Op(const valarray<_Tp>& __v, const valarray<_Tp>& __w) \ { \ - __glibcxx_assert(__v.size() == __w.size()); \ - typedef _BinClos<_Name, _ValArray, _ValArray, _Tp, _Tp> _Closure; \ - typedef typename __fun<_Name, _Tp>::result_type _Rt; \ - return _Expr<_Closure, _Rt>(_Closure(__v, __w)); \ + __glibcxx_assert(__v.size() == __w.size()); \ + typedef _BinClos<_Name, _ValArray, _ValArray, _Tp, _Tp> _Closure; \ + typedef typename __fun<_Name, _Tp>::result_type _Rt; \ + return _Expr<_Closure, _Rt>(_Closure(__v, __w)); \ } \ \ template \ - inline _Expr<_BinClos<_Name, _ValArray,_Constant, _Tp, _Tp>, \ - typename __fun<_Name, _Tp>::result_type> \ - operator _Op(const valarray<_Tp>& __v, const _Tp& __t) \ + inline _Expr<_BinClos<_Name, _ValArray,_Constant, _Tp, _Tp>, \ + typename __fun<_Name, _Tp>::result_type> \ + operator _Op(const valarray<_Tp>& __v, \ + const typename valarray<_Tp>::value_type& __t) \ { \ typedef _BinClos<_Name, _ValArray, _Constant, _Tp, _Tp> _Closure; \ - typedef typename __fun<_Name, _Tp>::result_type _Rt; \ - return _Expr<_Closure, _Rt>(_Closure(__v, __t)); \ + typedef typename __fun<_Name, _Tp>::result_type _Rt; \ + return _Expr<_Closure, _Rt>(_Closure(__v, __t)); \ } \ \ template \ - inline _Expr<_BinClos<_Name, _Constant, _ValArray, _Tp, _Tp>, \ - typename __fun<_Name, _Tp>::result_type> \ - operator _Op(const _Tp& __t, const valarray<_Tp>& __v) \ + inline _Expr<_BinClos<_Name, _Constant, _ValArray, _Tp, _Tp>, \ + typename __fun<_Name, _Tp>::result_type> \ + operator _Op(const typename valarray<_Tp>::value_type& __t, \ + const valarray<_Tp>& __v) \ { \ - typedef _BinClos<_Name, _Constant, _ValArray, _Tp, _Tp> _Closure; \ - typedef typename __fun<_Name, _Tp>::result_type _Rt; \ - return _Expr<_Closure, _Rt>(_Closure(__t, __v)); \ + typedef _BinClos<_Name, _Constant, _ValArray, _Tp, _Tp> _Closure; \ + typedef typename __fun<_Name, _Tp>::result_type _Rt; \ + return _Expr<_Closure, _Rt>(_Closure(__t, __v)); \ } _DEFINE_BINARY_OPERATOR(+, __plus) diff --git a/libstdc++-v3/testsuite/26_numerics/valarray/operators.cc b/libstdc++-v3/testsuite/26_numerics/valarray/operators.cc index f85a2b755d7..f0d5c05c0b7 100644 --- a/libstdc++-v3/testsuite/26_numerics/valarray/operators.cc +++ b/libstdc++-v3/testsuite/26_numerics/valarray/operators.cc @@ -58,9 +58,54 @@ void test02() // check binary operators VERIFY( (u>=v)[0] == (1>=3) ); } +void test03() // check binary operators with scalar operands +{ + std::valarray u(1); + u[0]=1; + long v = 3; // LWG 3074 allows scalar operand to be different to value_type. + + VERIFY( (u+ v)[0] == (1+ 3) ); + VERIFY( (u- v)[0] == (1- 3) ); + VERIFY( (u* v)[0] == (1* 3) ); + VERIFY( (u/ v)[0] == (1/ 3) ); + VERIFY( (u% v)[0] == (1% 3) ); + VERIFY( (u^ v)[0] == (1^ 3) ); + VERIFY( (u& v)[0] == (1& 3) ); + VERIFY( (u| v)[0] == (1| 3) ); + VERIFY( (u<>v)[0] == (1>>3) ); + VERIFY( (u&&v)[0] == (1&&3) ); + VERIFY( (u||v)[0] == (1||3) ); + VERIFY( (u==v)[0] == (1==3) ); + VERIFY( (u!=v)[0] == (1!=3) ); + VERIFY( (u< v)[0] == (1< 3) ); + VERIFY( (u> v)[0] == (1> 3) ); + VERIFY( (u<=v)[0] == (1<=3) ); + VERIFY( (u>=v)[0] == (1>=3) ); + + VERIFY( (v+ u)[0] == (3+ 1) ); + VERIFY( (v- u)[0] == (3- 1) ); + VERIFY( (v* u)[0] == (3* 1) ); + VERIFY( (v/ u)[0] == (3/ 1) ); + VERIFY( (v% u)[0] == (3% 1) ); + VERIFY( (v^ u)[0] == (3^ 1) ); + VERIFY( (v& u)[0] == (3& 1) ); + VERIFY( (v| u)[0] == (3| 1) ); + VERIFY( (v<>u)[0] == (3>>1) ); + VERIFY( (v&&u)[0] == (3&&1) ); + VERIFY( (v||u)[0] == (3||1) ); + VERIFY( (v==u)[0] == (3==1) ); + VERIFY( (v!=u)[0] == (3!=1) ); + VERIFY( (v< u)[0] == (3< 1) ); + VERIFY( (v> u)[0] == (3> 1) ); + VERIFY( (v<=u)[0] == (3<=1) ); + VERIFY( (v>=u)[0] == (3>=1) ); +} + int main() { test01(); test02(); - return 0; + test03(); } diff --git a/libstdc++-v3/testsuite/26_numerics/valarray/transcend.cc b/libstdc++-v3/testsuite/26_numerics/valarray/transcend.cc new file mode 100644 index 00000000000..e18c30ac35a --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/valarray/transcend.cc @@ -0,0 +1,100 @@ +// 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 +// . + +// { dg-do run } + +#include +#include + +bool eq(double d, double e) +{ + return (int)(d * 100) == (int)(e * 100); +} + +void +test01() +{ + std::valarray v(2); + v[0] = -0.5; + v[1] = 0.25; + std::valarray v_abs = abs(v); + VERIFY( v_abs[0] == 0.5 ); + VERIFY( v_abs[1] == 0.25 ); + + std::valarray v_acos = acos(v); + VERIFY( eq( v_acos[0], 2.09 ) ); + VERIFY( eq( v_acos[1], 1.31 ) ); + + std::valarray v_asin = asin(v); + VERIFY( eq( v_asin[0], -0.52 ) ); + VERIFY( eq( v_asin[1], 0.25 ) ); + + std::valarray v_atan = atan(v); + VERIFY( eq( v_atan[0], -0.46 ) ); + VERIFY( eq( v_atan[1], 0.24 ) ); + + std::valarray v2(2); + v2[0] = 4; + v2[1] = 3; + std::valarray v_atan2 = atan2(v, v2); + VERIFY( eq( v_atan2[0], -0.12 ) ); + VERIFY( eq( v_atan2[1], 0.08 ) ); + + v_atan2 = atan2(v, 4); // LWG 3074 allows mixed types + VERIFY( eq( v_atan2[0], -0.12 ) ); + VERIFY( eq( v_atan2[1], 0.06 ) ); + + v_atan2 = atan2(4, v); // LWG 3074 allows mixed types + VERIFY( eq( v_atan2[0], 1.69 ) ); + VERIFY( eq( v_atan2[1], 1.50 ) ); + + std::valarray v_cos = cos(v); + VERIFY( eq( v_cos[0], 0.87 ) ); + VERIFY( eq( v_cos[1], 0.96 ) ); + + std::valarray v_cosh = cosh(v); + VERIFY( eq( v_cosh[0], 1.12 ) ); + VERIFY( eq( v_cosh[1], 1.03 ) ); + + std::valarray v_exp = exp(v); + VERIFY( eq( v_exp[0], 0.60 ) ); + VERIFY( eq( v_exp[1], 1.28 ) ); + + std::valarray v_log = log(v); + VERIFY( eq( v_log[1], -1.38 ) ); + + std::valarray v_log10 = log10(v); + VERIFY( eq( v_log10[1], -0.60 ) ); + + std::valarray v_pow = pow(v, v2); + VERIFY( eq( v_pow[0], 0.06 ) ); + VERIFY( eq( v_pow[1], 0.01 ) ); + + v_pow = pow(v, 3); // LWG 3074 allows mixed types + VERIFY( eq( v_pow[0], -0.12 ) ); + VERIFY( eq( v_pow[1], 0.01 ) ); + + v_pow = pow(4, v); // LWG 3074 allows mixed types + VERIFY( eq( v_pow[0], 0.5 ) ); + VERIFY( eq( v_pow[1], 1.41 ) ); +} + +int +main() +{ + test01(); +} -- 2.30.2