From 1906dc30a5363351a1a5d8fd429a2f91caf944bd Mon Sep 17 00:00:00 2001 From: Olivier Parcollet Date: Thu, 19 Sep 2013 11:13:24 +0200 Subject: [PATCH] Fix expression template for gf & std::vector - add move semantics in expression template. for gfs : - rm descriptor - Remove data from expr, rewrote assignment which now iterates on the mesh, simply. RHS models now FunctionOnMesh - This fix the multiplication bug of gf - Remove assign_no_resize/assign_with_resize from proxy --- triqs/gfs/data_proxies.hpp | 12 -- triqs/gfs/gf.hpp | 70 +++--------- triqs/gfs/gf_expr.hpp | 116 ++++++++++---------- triqs/utility/concept_tools.hpp | 10 +- triqs/utility/expression_template_tools.hpp | 20 +++- triqs/utility/std_vector_expr_template.hpp | 82 +++++++++----- 6 files changed, 151 insertions(+), 159 deletions(-) diff --git a/triqs/gfs/data_proxies.hpp b/triqs/gfs/data_proxies.hpp index 3e8605d2..24d3b3c0 100644 --- a/triqs/gfs/data_proxies.hpp +++ b/triqs/gfs/data_proxies.hpp @@ -42,9 +42,7 @@ namespace triqs { namespace gfs { arrays::matrix_view_proxy operator()(storage_view_t & data, size_t i) const { return arrays::matrix_view_proxy(data,i); } arrays::const_matrix_view_proxy operator()(storage_view_t const & data, size_t i) const { return arrays::const_matrix_view_proxy(data,i); } - template static void assign_no_resize (S & data, RHS && rhs) { data() = std::forward(rhs);} template static void assign_to_scalar (S & data, RHS && rhs) { data() = std::forward(rhs);} - template static void assign_with_resize (storage_t & data, RHS && rhs) { data = std::forward(rhs);} template static void rebind (storage_view_t & data, RHS && rhs) { data.rebind(rhs.data()); } }; @@ -61,9 +59,7 @@ namespace triqs { namespace gfs { auto operator()(storage_view_t & data,size_t i) const -> decltype(data(i)) { return data(i);} auto operator()(storage_view_t const & data,size_t i) const -> decltype(data(i)) { return data(i);} - template static void assign_no_resize (S & data, RHS && rhs) { data() = std::forward(rhs);} template static void assign_to_scalar (S & data, RHS && rhs) { data() = std::forward(rhs);} - template static void assign_with_resize (storage_t & data, RHS && rhs) { data = std::forward(rhs);} template static void rebind (storage_view_t & data, RHS && rhs) { data.rebind(rhs.data()); } }; @@ -82,12 +78,6 @@ namespace triqs { namespace gfs { Tv & operator()(storage_view_t & data, size_t i) { return data[i];} Tv const & operator()(storage_view_t const & data, size_t i) const { return data[i];} - template static void assign_no_resize (S & data, RHS && rhs) { - //auto r = make_vector(rhs); - if (data.size() !=rhs.size()) TRIQS_RUNTIME_ERROR << "Size mismatch in gf assignment"; - for (size_t i =0; i static void assign_with_resize (S & data, RHS && rhs) {data = utility::factory(rhs);} template static void assign_to_scalar (S & data, RHS && rhs) {for (size_t i =0; i static void rebind (storage_view_t & data, RHS && rhs) { data.clear(); for (auto & x : rhs.data()) data.push_back(x);} }; @@ -104,8 +94,6 @@ namespace triqs { namespace gfs { auto operator()(storage_t & data, size_t i) DECL_AND_RETURN( data(i)); auto operator()(storage_t const & data, size_t i) const DECL_AND_RETURN( data(i)); - template static void assign_no_resize (S & data, RHS && rhs) { data() = std::forward(rhs);} - template static void assign_with_resize (S & data, RHS && rhs) = delete; template static void assign_to_scalar (S & data, RHS && rhs) = delete; template static void rebind (storage_view_t & data, RHS && rhs) = delete;// { data = std::forward(rhs);} }; diff --git a/triqs/gfs/gf.hpp b/triqs/gfs/gf.hpp index f2422468..adc70a64 100644 --- a/triqs/gfs/gf.hpp +++ b/triqs/gfs/gf.hpp @@ -33,7 +33,6 @@ namespace triqs { namespace gfs { using utility::factory; using arrays::make_shape; - // GENERALISE matrxi TO DEFAULT template struct gf_mesh; template class gf; // the regular type template class gf_view; // the view type @@ -41,7 +40,7 @@ namespace triqs { namespace gfs { // various implementation traits namespace gfs_implementation { // never use using of this... - // evaluator regroup functions to evaluate the function. Cf descriptors + // evaluator regroup functions to evaluate the function. template struct evaluator{ static constexpr int arity = 0;}; // closest_point mechanism @@ -60,7 +59,7 @@ namespace triqs { namespace gfs { // this is used to specialize this part of the code to array of dim 3 (matrix gf), dim 1 (scalar gf) and vector (e.g. block gf, ...) template struct data_proxy; - // This trait contains functions to read/write in hdf5 files. Can be specialized for some descriptor (Cf block) + // This trait contains functions to read/write in hdf5 files. Can be specialized for some case (Cf block) template struct h5_name; // value is a const char * template struct h5_name { static std::string invoke(){ return h5_name::invoke() + "_s";}}; @@ -83,9 +82,6 @@ namespace triqs { namespace gfs { template gf_view make_gf_view(U && ... x) { return gfs_implementation::factories::make_gf_view(std::forward(x)...);} - template struct gf_desc{}; - template struct gf_tag{}; - // The trait that "marks" the Green function TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT(ImmutableGreenFunction); @@ -93,31 +89,28 @@ namespace triqs { namespace gfs { /// A common implementation class for gf and gf_view. They will only redefine contructor and = ... template class gf_impl : - TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction), gf_tag> { + TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction){ public : - - // Pattern : ValueView typedef gf_view view_type; typedef gf regular_type; - typedef gf_desc descriptor_t; - typedef Variable variable_t; + typedef Target target_t; typedef Opt option_t; typedef gf_mesh mesh_t; typedef typename mesh_t::domain_t domain_t; typedef typename mesh_t::mesh_point_t mesh_point_t; typedef typename mesh_t::index_t mesh_index_t; - typedef typename gfs_implementation::symmetry::type symmetry_t; - typedef gfs_implementation::evaluator evaluator_t; + typedef typename gfs_implementation::symmetry::type symmetry_t; + typedef gfs_implementation::evaluator evaluator_t; - typedef gfs_implementation::data_proxy data_proxy_t; + typedef gfs_implementation::data_proxy data_proxy_t; typedef typename data_proxy_t::storage_t data_regular_t; typedef typename data_proxy_t::storage_view_t data_view_t; - typedef typename std::conditional::type data_t; + typedef typename std::conditional::type data_t; - typedef typename gfs_implementation::singularity::type singularity_non_view_t; + typedef typename gfs_implementation::singularity::type singularity_non_view_t; typedef typename view_type_if_exists_else_type::type singularity_view_t; typedef typename std::conditional::type singularity_t; @@ -185,13 +178,6 @@ namespace triqs { namespace gfs { >::type // end of add_Const operator() (Arg0&& arg0, Args&&... args) const { return _evaluator(this,std::forward( arg0), std::forward(args)...); } - // Interaction with the CLEF library : calling the gf with any clef expression as argument build a new clef expression - //template - // auto operator()(Arg0 arg0, Args... args) const DECL_AND_RETURN( clef::make_expr_call(view_type(*this),arg0, args...)); - - //template - // auto operator()(Arg0 arg0, Args... args) DECL_AND_RETURN( clef::make_expr_call(view_type(*this),arg0, args...)); - template typename clef::_result_of::make_expr_call::type operator()(Arg0 arg0, Args... args) const { @@ -227,34 +213,14 @@ namespace triqs { namespace gfs { template cr_type operator[] (closest_pt_wrap const & p) const { return _data_proxy(_data, _mesh.index_to_linear( gfs_implementation::get_closest_point::invoke(this,p)));} - // Interaction with the CLEF library : calling the gf with any clef expression as argument build a new clef expression - /* template - typename boost::lazy_enable_if< // enable the template if - clef::is_any_lazy, // One of Args is a lazy expression - clef::_result_of::make_expr_subscript - >::type // end of lazy_enable_if - operator[](Arg && arg) const { return clef::make_expr_subscript(view_type(*this),std::forward(arg));} - */ - - /*template - //auto operator[](Arg && arg) const DECL_AND_RETURN(clef::make_expr_subscript((*this)(),std::forward(arg))); - auto operator[](Arg && arg) const DECL_AND_RETURN(clef::make_expr_subscript(view_type(*this),std::forward(arg))); - - template - //auto operator[](Arg && arg) DECL_AND_RETURN(clef::make_expr_subscript((*this)(),std::forward(arg))); - auto operator[](Arg && arg) DECL_AND_RETURN(clef::make_expr_subscript(view_type(*this),std::forward(arg))); - */ - template typename clef::_result_of::make_expr_subscript::type operator[](Arg && arg) const { return clef::make_expr_subscript(view_type(*this),std::forward(arg));} /// A direct access to the grid point - template r_type on_mesh (Args&&... args) { return _data_proxy(_data,_mesh.index_to_linear(mesh_index_t(std::forward(args)...)));} - /// A direct access to the grid point (const version) template cr_type on_mesh (Args&&... args) const { return _data_proxy(_data,_mesh.index_to_linear(mesh_index_t(std::forward(args)...)));} @@ -279,7 +245,7 @@ namespace triqs { namespace gfs { friend void h5_write (h5::group fg, std::string subgroup_name, gf_impl const & g) { auto gr = fg.create_group(subgroup_name); gr.write_triqs_hdf5_data_scheme(g); - gfs_implementation::h5_ops::write(gr, "data", g._data, g);//can be specialized for some descriptors (E.g. blocks) + gfs_implementation::h5_ops::write(gr, "data", g._data, g); h5_write(gr,"singularity",g._singularity); h5_write(gr,"mesh",g._mesh); h5_write(gr,"symmetry",g._symmetry); @@ -293,7 +259,7 @@ namespace triqs { namespace gfs { auto tag_expected= get_triqs_hdf5_data_scheme(g); if (tag_file != tag_expected) TRIQS_RUNTIME_ERROR<< "h5_read : mismatch of the tag TRIQS_HDF5_data_scheme tag in the h5 group : found "<::read(gr, "data", g._data, g);//can be specialized for some descriptors (E.g. blocks) + gfs_implementation::h5_ops::read(gr, "data", g._data, g); h5_read(gr,"singularity",g._singularity); h5_read(gr,"mesh",g._mesh); h5_read(gr,"symmetry",g._symmetry); @@ -337,13 +303,13 @@ namespace triqs { namespace gfs { friend void swap (gf & a, gf & b) noexcept { a.swap_impl (b);} - gf & operator = (gf const & rhs) { *this = gf(rhs); return *this;} // use move = - gf & operator = (gf & rhs) { *this = gf(rhs); return *this;} // use move = - gf & operator = (gf && rhs) noexcept { swap(*this, rhs); return *this;} + gf & operator = (gf const & rhs) { *this = gf(rhs); return *this;} // use move = + gf & operator = (gf & rhs) { *this = gf(rhs); return *this;} // use move = + gf & operator = (gf && rhs) noexcept { swap(*this,rhs); return *this;} template void operator = (RHS && rhs) { - this->_mesh = rhs.mesh(); - B::data_proxy_t::assign_with_resize(this->data(), std::forward(rhs).data()); // looks strange for && + this->_mesh = std::forward(rhs).mesh(); + for (auto const & w: this->mesh()) (*this)[w] = rhs[w]; this->_singularity = rhs.singularity(); // to be implemented : there is none in the gf_expr in particular.... //this->_symmetry = rhs.symmetry(); @@ -405,8 +371,8 @@ namespace triqs { namespace gfs { // delegate = so that I can overload it for specific RHS... template DISABLE_IF(arrays::is_scalar) triqs_gf_view_assign_delegation( gf_view g, RHS const & rhs) { - if (!(g.mesh() == rhs.mesh())) TRIQS_RUNTIME_ERROR<<"Gf Assignment in View : incompatible mesh"; - gf_view::data_proxy_t::assign_no_resize(g.data(),rhs.data()); + if (!(g.mesh() == rhs.mesh())) TRIQS_RUNTIME_ERROR<<"Gf Assignment in View : incompatible mesh"; + for (auto const & w: g.mesh()) g[w] = rhs[w]; g.singularity() = rhs.singularity(); } diff --git a/triqs/gfs/gf_expr.hpp b/triqs/gfs/gf_expr.hpp index 88bfada4..21804105 100644 --- a/triqs/gfs/gf_expr.hpp +++ b/triqs/gfs/gf_expr.hpp @@ -21,93 +21,93 @@ #ifndef TRIQS_GF_EXPR_H #define TRIQS_GF_EXPR_H #include -namespace triqs { namespace gfs { +namespace triqs { namespace gfs { + using utility::is_in_ZRC; - namespace gfs_expr_tools { + using utility::remove_rvalue_ref; + + namespace gfs_expr_tools { + + // a wrapper for scalars template struct scalar_wrap { - typedef S value_type; - S s; scalar_wrap(S const &s_):s(s_){} + typedef void variable_t; + typedef void target_t; + typedef void option_t; + S s; + template scalar_wrap(T && x):s(std::forward(x)){} S singularity() const { return s;} - S data() const { return s;} - template value_type operator[](KeyType && key) const { return s;} - template inline value_type operator()(Args && ... args) const { return s;} + template S operator[](KeyType && key) const { return s;} + template inline S operator()(Args && ... args) const { return s;} friend std::ostream &operator <<(std::ostream &sout, scalar_wrap const &expr){return sout << expr.s; } }; // Combine the two meshes of LHS and RHS : need to specialize where there is a scalar struct combine_mesh { template - inline auto operator() (L const & l, R const & r) const -> decltype(l.mesh()) { + auto operator() (L && l, R && r) const -> decltype(std::forward(l).mesh()) { if (!(l.mesh() == r.mesh())) TRIQS_RUNTIME_ERROR << "Mesh mismatch : ";//<< l.mesh()<<" vs" <(l).mesh(); } - template auto operator() (scalar_wrap const & w, R const & r) const -> decltype(r.mesh()) { return r.mesh();} - template auto operator() (L const & l, scalar_wrap const & w) const -> decltype(l.mesh()) { return l.mesh();} + template auto operator() (scalar_wrap const &, R && r) const DECL_AND_RETURN(std::forward(r).mesh()); + template auto operator() (L && l, scalar_wrap const &) const DECL_AND_RETURN(std::forward(l).mesh()); }; - template struct keeper_type : std::conditional::value, scalar_wrap, typename view_type_if_exists_else_type::type> {}; + template struct node_t : std::conditional::value, scalar_wrap, typename remove_rvalue_ref::type> {}; + + template struct _or_ {typedef void type;}; + template struct _or_ {typedef A type;}; + template struct _or_ {typedef A type;}; + template struct _or_ {typedef A type;}; + template <> struct _or_ {typedef void type;}; + }// gfs_expr_tools - template struct gf_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction),gf_tag { - typedef typename gfs_expr_tools::keeper_type::type L_t; - typedef typename gfs_expr_tools::keeper_type::type R_t; - typedef Descriptor descriptor_t; - //typedef typename std::result_of(typename L_t::value_type,typename R_t::value_type)>::type value_t; - typedef typename std::remove_reference::type>::type mesh_t; - //typedef typename Descriptor::singularity_t::view_type singularity_view_t; - //typedef value_t value_type; - L_t l; R_t r; - template gf_expr(LL && l_, RR && r_) : l(std::forward(l_)), r(std::forward(r_)) {} - mesh_t mesh() const { return gfs_expr_tools::combine_mesh()(l,r); } - auto data() const ->decltype( utility::operation()(l.data(), r.data())) { return utility::operation()(l.data(), r.data());} + template struct gf_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction){ + typedef typename std::remove_reference::type L_t; + typedef typename std::remove_reference::type R_t; + typedef typename gfs_expr_tools::_or_::type variable_t; + typedef typename gfs_expr_tools::_or_::type target_t; + typedef typename gfs_expr_tools::_or_::type option_t; + static_assert(!std::is_same::value, "Can not combine two gf expressions with different variables"); + static_assert(!std::is_same::value, "Can not combine two gf expressions with different target"); + + L l; R r; + template gf_expr(LL && l_, RR && r_):l(std::forward(l_)), r(std::forward(r_)) {} + + auto mesh() const DECL_AND_RETURN(gfs_expr_tools::combine_mesh()(l,r)); auto singularity() const DECL_AND_RETURN (utility::operation()(l.singularity() , r.singularity())); - //const singularity_view_t singularity() const { return utility::operation()(l.singularity() , r.singularity());} - //symmetry_t const & symmetry() const { return _symmetry;} - template auto operator[](KeyType && key) const DECL_AND_RETURN(utility::operation()(l[std::forward(key)] , r[std::forward(key)])); + + template auto operator[](KeyType && key) const DECL_AND_RETURN(utility::operation()(l[std::forward(key)] , r[std::forward(key)])); template auto operator()(Args && ... args) const DECL_AND_RETURN(utility::operation()(l(std::forward(args)...) , r(std::forward(args)...))); friend std::ostream &operator <<(std::ostream &sout, gf_expr const &expr){return sout << "("<::name << " "< struct gf_unary_m_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction),gf_tag{ - typedef typename gfs_expr_tools::keeper_type::type L_t; - typedef Descriptor descriptor_t; - //typedef typename L_t::value_type value_type; - typedef typename L_t::mesh_t mesh_t; - //typedef typename Descriptor::singularity_t::view_type singularity_view_t; - L_t l; + template struct gf_unary_m_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction){ + typedef typename std::remove_reference::type L_t; + typedef typename L_t::variable_t variable_t; + typedef typename L_t::target_t target_t; + typedef typename L_t::option_t option_t; + + L l; template gf_unary_m_expr(LL && l_) : l(std::forward(l_)) {} - mesh_t mesh() const { return l.mesh(); } - auto data() const ->decltype( - l.data()) { return - l.data();} + + auto mesh() const DECL_AND_RETURN(l.mesh()); auto singularity() const DECL_AND_RETURN(l.singularity()); - //const singularity_view_t singularity() const { return l.singularity();} - //symmetry_t const & symmetry() const { return _symmetry;} + template auto operator[](KeyType&& key) const DECL_AND_RETURN( -l[key]); template auto operator()(Args && ... args) const DECL_AND_RETURN( -l(std::forward(args)...)); friend std::ostream &operator <<(std::ostream &sout, gf_unary_m_expr const &expr){return sout << '-'< struct get_desc; - template - struct get_desc ::value) && (ImmutableGreenFunction::value))>::type > { - typedef typename A2::descriptor_t type; - }; - template - struct get_desc ::value) && (ImmutableGreenFunction::value)>::type > { - typedef typename A1::descriptor_t type; - }; - template - struct get_desc ::value) && (ImmutableGreenFunction::value) && std::is_same::value >::type > { typedef typename A2::descriptor_t type; }; - // ------------------------------------------------------------------- // Now we can define all the C++ operators ... #define DEFINE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \ template\ - typename std::enable_if::value && TRAIT2 ::value, gf_expr::type, utility::tags::TAG, A1,A2>>::type\ - operator OP (A1 const & a1, A2 const & a2) { return gf_expr::type,utility::tags::TAG, A1,A2>(a1,a2);} + typename std::enable_if::value && TRAIT2 ::value, \ + gf_expr::type, typename gfs_expr_tools::node_t::type>>::type\ + operator OP (A1 && a1, A2 && a2) { return {std::forward(a1),std::forward(a2)};} DEFINE_OPERATOR(plus, +, ImmutableGreenFunction,ImmutableGreenFunction); DEFINE_OPERATOR(minus, -, ImmutableGreenFunction,ImmutableGreenFunction); @@ -120,8 +120,12 @@ namespace triqs { namespace gfs { #undef DEFINE_OPERATOR // the unary is special - template typename std::enable_if::value, gf_unary_m_expr>::type - operator - (A1 const & a1) { return gf_unary_m_expr(a1);} + template + typename std::enable_if< + ImmutableGreenFunction::value, + gf_unary_m_expr::type > + >::type + operator - (A1 && a1) { return {std::forward(a1)};} }}//namespace triqs::gf #endif diff --git a/triqs/utility/concept_tools.hpp b/triqs/utility/concept_tools.hpp index 99b9ccb6..2b7ce339 100644 --- a/triqs/utility/concept_tools.hpp +++ b/triqs/utility/concept_tools.hpp @@ -32,8 +32,9 @@ #define TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT(MyBeautifulConcept) \ struct TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept) {};\ template struct MyBeautifulConcept : boost::is_base_of {};\ - template struct MyBeautifulConcept : boost::is_base_of {};\ - template struct MyBeautifulConcept : boost::is_base_of {}; + template struct MyBeautifulConcept : MyBeautifulConcept{};\ + template struct MyBeautifulConcept : MyBeautifulConcept{};\ + template struct MyBeautifulConcept : MyBeautifulConcept{}; #define TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R_AUX(r, data, i, elem) BOOST_PP_COMMA_IF(i) TRIQS_CONCEPT_TAG_NAME(elem) @@ -41,8 +42,9 @@ #define TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R(MyBeautifulConcept,Rs) \ struct TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept) : BOOST_PP_SEQ_FOR_EACH_I (TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R_AUX,nil,Rs) {};\ template struct MyBeautifulConcept : boost::is_base_of {};\ - template struct MyBeautifulConcept : boost::is_base_of {};\ - template struct MyBeautifulConcept : boost::is_base_of {}; + template struct MyBeautifulConcept : MyBeautifulConcept{};\ + template struct MyBeautifulConcept : MyBeautifulConcept{};\ + template struct MyBeautifulConcept : MyBeautifulConcept{}; #ifdef TRIQS_COMPILE_TIME_DEBUG #define TRIQS_ASSERT_MODEL_CONCEPT(MyBeautifulConcept,T) BOOST_CONCEPT_ASSERT((BCC_##MyBeautifulConcept)); diff --git a/triqs/utility/expression_template_tools.hpp b/triqs/utility/expression_template_tools.hpp index 1b3d8522..3e0c8037 100644 --- a/triqs/utility/expression_template_tools.hpp +++ b/triqs/utility/expression_template_tools.hpp @@ -22,26 +22,32 @@ #define TRIQS_UTILITY_EXPRESSION_TEMPLATE_TOOLS_H #include #include +#include "./macros.hpp" + namespace triqs { namespace utility { + template struct remove_rvalue_ref {typedef T type;}; + template struct remove_rvalue_ref {typedef T const & type;}; + template struct remove_rvalue_ref {typedef T type;}; + namespace tags { struct plus{}; struct minus{}; struct multiplies{}; struct divides{}; } -// The basic operations put in a template.... + // The basic operations put in a template.... template struct operation; template<> struct operation { - template auto operator()(L const & l, R const & r) const -> decltype(l+r) { return l+r;} + template auto operator()(L && l, R && r) const DECL_AND_RETURN(std::forward(l) + std::forward(r)); static const char name = '+'; }; template<> struct operation { - template auto operator()(L const & l, R const & r) const -> decltype(l-r) { return l-r;} + template auto operator()(L && l, R && r) const DECL_AND_RETURN(std::forward(l) - std::forward(r)); static const char name = '-'; }; template<> struct operation { - template auto operator()(L const & l, R const & r) const -> decltype(l*r) { return l*r;} + template auto operator()(L && l, R && r) const DECL_AND_RETURN(std::forward(l) * std::forward(r)); static const char name = '*'; }; template<> struct operation { - template auto operator()(L const & l, R const & r) const -> decltype(l/r) { return l/r;} + template auto operator()(L && l, R && r) const DECL_AND_RETURN(std::forward(l) / std::forward(r)); static const char name = '/'; }; @@ -49,11 +55,15 @@ namespace triqs { namespace utility { template struct is_in_ZRC : std::is_arithmetic {}; template<> struct is_in_ZRC : std::true_type {}; template struct is_in_ZRC > : std::true_type {}; + template struct is_in_ZRC : is_in_ZRC{}; + template struct is_in_ZRC : is_in_ZRC{}; + template struct is_in_ZRC : is_in_ZRC{}; template struct type_of_mult{ typedef decltype ( std::declval::type>() * std::declval::type>() ) type; }; + }}//namespace triqs::utility #endif diff --git a/triqs/utility/std_vector_expr_template.hpp b/triqs/utility/std_vector_expr_template.hpp index 69ffbcca..0eab5e7b 100644 --- a/triqs/utility/std_vector_expr_template.hpp +++ b/triqs/utility/std_vector_expr_template.hpp @@ -24,6 +24,8 @@ #include #include #include +#include + namespace triqs { namespace utility { // a trait to identify the std::vector ... @@ -31,11 +33,12 @@ namespace triqs { namespace utility { template struct ImmutableStdVector> : std::true_type{}; namespace expr_temp_vec_tools { - template struct scalar_wrap { - typedef S value_type; - S s; scalar_wrap(S const &s_):s(s_){} - S operator[](size_t i) const { return s;} - friend std::ostream &operator <<(std::ostream &sout, scalar_wrap const &expr){return sout << expr.s; } + template struct scalar_wrap {// S can be a T or a T & + typedef typename std::remove_reference::type value_type; + S s; + template scalar_wrap(T && x):s(std::forward(x)){} + S operator[](size_t i) const {return s;} + friend std::ostream &operator <<(std::ostream &sout, scalar_wrap const &expr){return sout << expr.s;} }; // Combine the two sizes of LHS and RHS : need to specialize where there is a scalar @@ -45,16 +48,19 @@ namespace triqs { namespace utility { if (!(l.size() == r.size())) TRIQS_RUNTIME_ERROR << "size mismatch : ";//<< l.size()<<" vs" < size_t operator() (scalar_wrap const & w, R const & r) const {return r.size();} - template size_t operator() (L const & l, scalar_wrap const & w) const {return l.size();} + template size_t operator() (scalar_wrap const &, R const & r) const {return r.size();} + template size_t operator() (L const & l, scalar_wrap const &) const {return l.size();} }; - - template struct keeper_type : std::conditional::value, scalar_wrap, T const &> {}; + + template struct node_t : std::conditional::value, scalar_wrap, typename remove_rvalue_ref::type> {}; template - std::vector make_vector(V const & v) { - std::vector res; res.reserve(v.size()); - for (size_t i =0; i std::vector::type> { + //auto make_vector(V const & v) -> std::vector(v)[0])>::type> { + std::vector::type> res; + std::cout << "makeVector"<< std::endl; + res.reserve(v.size()); + for (size_t i =0; i struct std_vec_expr : triqs::utility::ImmutableStdVector__concept_tag { - typedef typename triqs::utility::expr_temp_vec_tools::keeper_type::type L_t; - typedef typename triqs::utility::expr_temp_vec_tools::keeper_type::type R_t; - typedef typename std::result_of(typename std::remove_reference::type::value_type, - typename std::remove_reference::type::value_type)>::type value_t; - typedef value_t value_type; - L_t l; R_t r; + L l; R r; template std_vec_expr(LL && l_, RR && r_) : l(std::forward(l_)), r(std::forward(r_)) {} + std_vec_expr(std_vec_expr const &) = delete; + std_vec_expr(std_vec_expr &&) = default; size_t size() const { return triqs::utility::expr_temp_vec_tools::combine_size()(l,r); } - value_type operator[](size_t i) const { return triqs::utility::operation()(l[i] , r[i]);} - friend std::ostream &operator <<(std::ostream &sout, std_vec_expr const &expr){return sout << "("<::name << " "< make_vector(std_vec_expr const & v) { return triqs::utility::expr_temp_vec_tools::make_vector(v);} + auto operator[](size_t i) const DECL_AND_RETURN(triqs::utility::operation()(l[i] , r[i])); + friend std::ostream &operator <<(std::ostream &sout, std_vec_expr const &expr){return sout << "("<::name <<" "< + auto make_vector(std_vec_expr const & v) DECL_AND_RETURN(triqs::utility::expr_temp_vec_tools::make_vector(v)); + // ------------------------------------------------------------------- //a special case : the unary operator ! - template struct std_vec_expr_unary : triqs::utility::ImmutableStdVector__concept_tag { - typedef typename triqs::utility::expr_temp_vec_tools::keeper_type::type L_t; - typedef typename L_t::value_type value_type; - L_t l; + template struct std_vec_expr_unary : triqs::utility::ImmutableStdVector__concept_tag { + L l; template std_vec_expr_unary(LL && l_) : l(std::forward(l_)) {} + std_vec_expr_unary(std_vec_expr_unary const &) = delete; + std_vec_expr_unary(std_vec_expr_unary &&) = default; size_t size() const { return l.size(); } - value_type operator[](size_t i) const { return -l[i];} + auto operator[](size_t i) const DECL_AND_RETURN( -l[i]); friend std::ostream &operator <<(std::ostream &sout, std_vec_expr_unary const &expr){return sout << '-'< make_vector(std_vec_expr_unary const & v) { return triqs::utility::expr_temp_vec_tools::make_vector(v);} }; + + template + auto make_vector(std_vec_expr_unary const & v) DECL_AND_RETURN(triqs::utility::expr_temp_vec_tools::make_vector(v)); // ------------------------------------------------------------------- // Now we can define all the C++ operators ... #define DEFINE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \ template\ - typename std::enable_if::value && triqs::utility::TRAIT2 ::value, std_vec_expr>::type\ - operator OP (A1 const & a1, A2 const & a2) { return std_vec_expr(a1,a2);} + typename std::enable_if::value && triqs::utility::TRAIT2 ::value, \ + std_vec_expr::type, typename triqs::utility::expr_temp_vec_tools::node_t::type>>::type\ + operator OP (A1 && a1, A2 && a2) { return {std::forward(a1),std::forward(a2)};} DEFINE_OPERATOR(plus, +, ImmutableStdVector,ImmutableStdVector); DEFINE_OPERATOR(minus, -, ImmutableStdVector,ImmutableStdVector); @@ -110,8 +118,22 @@ namespace std { // no choice since the operators are found by ADL.. // the unary is special template typename std::enable_if::value, std_vec_expr_unary>::type operator - (A1 const & a1) { return std_vec_expr_unary(a1);} - } + +/* +namespace triqs { namespace utility { namespace expr_temp_vec_tools { + + //make sure expression are never taken by const & + template struct expr_node_storage_t &> ;// { typedef std::std_vec_expr type;}; + template struct expr_node_storage_t const &> ;//{ typedef std::std_vec_expr type;}; + + template struct expr_node_storage_t &> ;// { typedef std::std_vec_expr_unary type;}; + template struct expr_node_storage_t const &>;// { typedef std::std_vec_expr_unary type;}; + + }// std_vec_expr_tools + }} +*/ + #endif