3
0
mirror of https://github.com/triqs/dft_tools synced 2024-12-25 05:43:40 +01:00

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
This commit is contained in:
Olivier Parcollet 2013-09-19 11:13:24 +02:00
parent 1e94eab495
commit 1906dc30a5
6 changed files with 151 additions and 159 deletions

View File

@ -42,9 +42,7 @@ namespace triqs { namespace gfs {
arrays::matrix_view_proxy<storage_view_t,0> operator()(storage_view_t & data, size_t i) const { return arrays::matrix_view_proxy<storage_view_t,0>(data,i); } arrays::matrix_view_proxy<storage_view_t,0> operator()(storage_view_t & data, size_t i) const { return arrays::matrix_view_proxy<storage_view_t,0>(data,i); }
arrays::const_matrix_view_proxy<storage_view_t,0> operator()(storage_view_t const & data, size_t i) const { return arrays::const_matrix_view_proxy<storage_view_t,0>(data,i); } arrays::const_matrix_view_proxy<storage_view_t,0> operator()(storage_view_t const & data, size_t i) const { return arrays::const_matrix_view_proxy<storage_view_t,0>(data,i); }
template<typename S, typename RHS> static void assign_no_resize (S & data, RHS && rhs) { data() = std::forward<RHS>(rhs);}
template<typename S, typename RHS> static void assign_to_scalar (S & data, RHS && rhs) { data() = std::forward<RHS>(rhs);} template<typename S, typename RHS> static void assign_to_scalar (S & data, RHS && rhs) { data() = std::forward<RHS>(rhs);}
template<typename RHS> static void assign_with_resize (storage_t & data, RHS && rhs) { data = std::forward<RHS>(rhs);}
template<typename RHS> static void rebind (storage_view_t & data, RHS && rhs) { data.rebind(rhs.data()); } template<typename RHS> 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 & 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);} auto operator()(storage_view_t const & data,size_t i) const -> decltype(data(i)) { return data(i);}
template<typename S, typename RHS> static void assign_no_resize (S & data, RHS && rhs) { data() = std::forward<RHS>(rhs);}
template<typename S, typename RHS> static void assign_to_scalar (S & data, RHS && rhs) { data() = std::forward<RHS>(rhs);} template<typename S, typename RHS> static void assign_to_scalar (S & data, RHS && rhs) { data() = std::forward<RHS>(rhs);}
template<typename RHS> static void assign_with_resize (storage_t & data, RHS && rhs) { data = std::forward<RHS>(rhs);}
template<typename RHS> static void rebind (storage_view_t & data, RHS && rhs) { data.rebind(rhs.data()); } template<typename RHS> 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 & 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];} Tv const & operator()(storage_view_t const & data, size_t i) const { return data[i];}
template<typename S, typename RHS> 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<data.size(); ++i) data[i] = rhs[i];
}
template<typename S, typename RHS> static void assign_with_resize (S & data, RHS && rhs) {data = utility::factory<storage_t>(rhs);}
template<typename S, typename RHS> static void assign_to_scalar (S & data, RHS && rhs) {for (size_t i =0; i<data.size(); ++i) data[i] = rhs;} template<typename S, typename RHS> static void assign_to_scalar (S & data, RHS && rhs) {for (size_t i =0; i<data.size(); ++i) data[i] = rhs;}
template<typename RHS> static void rebind (storage_view_t & data, RHS && rhs) { data.clear(); for (auto & x : rhs.data()) data.push_back(x);} template<typename RHS> 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 & data, size_t i) DECL_AND_RETURN( data(i));
auto operator()(storage_t const & data, size_t i) const DECL_AND_RETURN( data(i)); auto operator()(storage_t const & data, size_t i) const DECL_AND_RETURN( data(i));
template<typename S, typename RHS> static void assign_no_resize (S & data, RHS && rhs) { data() = std::forward<RHS>(rhs);}
template<typename S, typename RHS> static void assign_with_resize (S & data, RHS && rhs) = delete;
template<typename S, typename RHS> static void assign_to_scalar (S & data, RHS && rhs) = delete; template<typename S, typename RHS> static void assign_to_scalar (S & data, RHS && rhs) = delete;
template<typename RHS> static void rebind (storage_view_t & data, RHS && rhs) = delete;// { data = std::forward<RHS>(rhs);} template<typename RHS> static void rebind (storage_view_t & data, RHS && rhs) = delete;// { data = std::forward<RHS>(rhs);}
}; };

View File

@ -33,7 +33,6 @@ namespace triqs { namespace gfs {
using utility::factory; using utility::factory;
using arrays::make_shape; using arrays::make_shape;
// GENERALISE matrxi TO DEFAULT
template<typename Variable, typename Opt=void> struct gf_mesh; template<typename Variable, typename Opt=void> struct gf_mesh;
template<typename Variable, typename Target=matrix_valued, typename Opt=void> class gf; // the regular type template<typename Variable, typename Target=matrix_valued, typename Opt=void> class gf; // the regular type
template<typename Variable, typename Target=matrix_valued, typename Opt=void> class gf_view; // the view type template<typename Variable, typename Target=matrix_valued, typename Opt=void> class gf_view; // the view type
@ -41,7 +40,7 @@ namespace triqs { namespace gfs {
// various implementation traits // various implementation traits
namespace gfs_implementation { // never use using of this... 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<typename Variable, typename Target, typename Opt> struct evaluator{ static constexpr int arity = 0;}; template<typename Variable, typename Target, typename Opt> struct evaluator{ static constexpr int arity = 0;};
// closest_point mechanism // 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, ...) // 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<typename Variable, typename Target, typename Opt, typename Enable = void> struct data_proxy; template<typename Variable, typename Target, typename Opt, typename Enable = void> 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 <typename Variable, typename Target, typename Opt> struct h5_name; // value is a const char * template <typename Variable, typename Target, typename Opt> struct h5_name; // value is a const char *
template<typename Variable, typename Opt> struct h5_name<Variable,scalar_valued,Opt> { static std::string invoke(){ return h5_name<Variable,matrix_valued,Opt>::invoke() + "_s";}}; template<typename Variable, typename Opt> struct h5_name<Variable,scalar_valued,Opt> { static std::string invoke(){ return h5_name<Variable,matrix_valued,Opt>::invoke() + "_s";}};
@ -83,9 +82,6 @@ namespace triqs { namespace gfs {
template <typename Variable, typename Target=matrix_valued, typename Opt=void, typename ... U> template <typename Variable, typename Target=matrix_valued, typename Opt=void, typename ... U>
gf_view<Variable,Target,Opt> make_gf_view(U && ... x) { return gfs_implementation::factories<Variable,Target,Opt>::make_gf_view(std::forward<U>(x)...);} gf_view<Variable,Target,Opt> make_gf_view(U && ... x) { return gfs_implementation::factories<Variable,Target,Opt>::make_gf_view(std::forward<U>(x)...);}
template<typename Variable, typename Target, typename Opt> struct gf_desc{};
template<typename Descriptor> struct gf_tag{};
// The trait that "marks" the Green function // The trait that "marks" the Green function
TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT(ImmutableGreenFunction); TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT(ImmutableGreenFunction);
@ -93,16 +89,13 @@ namespace triqs { namespace gfs {
/// A common implementation class for gf and gf_view. They will only redefine contructor and = ... /// A common implementation class for gf and gf_view. They will only redefine contructor and = ...
template<typename Variable, typename Target, typename Opt, bool IsView> class gf_impl : template<typename Variable, typename Target, typename Opt, bool IsView> class gf_impl :
TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction), gf_tag<gf_desc<Variable,Target,Opt>> { TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction){
public : public :
// Pattern : ValueView
typedef gf_view<Variable,Target,Opt> view_type; typedef gf_view<Variable,Target,Opt> view_type;
typedef gf<Variable,Target,Opt> regular_type; typedef gf<Variable,Target,Opt> regular_type;
typedef gf_desc<Variable,Target,Opt> descriptor_t;
typedef Variable variable_t; typedef Variable variable_t;
typedef Target target_t;
typedef Opt option_t; typedef Opt option_t;
typedef gf_mesh<Variable,Opt> mesh_t; typedef gf_mesh<Variable,Opt> mesh_t;
@ -185,13 +178,6 @@ namespace triqs { namespace gfs {
>::type // end of add_Const >::type // end of add_Const
operator() (Arg0&& arg0, Args&&... args) const { return _evaluator(this,std::forward<Arg0>( arg0), std::forward<Args>(args)...); } operator() (Arg0&& arg0, Args&&... args) const { return _evaluator(this,std::forward<Arg0>( arg0), std::forward<Args>(args)...); }
// Interaction with the CLEF library : calling the gf with any clef expression as argument build a new clef expression
//template<typename Arg0, typename ...Args>
// auto operator()(Arg0 arg0, Args... args) const DECL_AND_RETURN( clef::make_expr_call(view_type(*this),arg0, args...));
//template<typename Arg0, typename ...Args>
// auto operator()(Arg0 arg0, Args... args) DECL_AND_RETURN( clef::make_expr_call(view_type(*this),arg0, args...));
template<typename Arg0, typename ...Args> template<typename Arg0, typename ...Args>
typename clef::_result_of::make_expr_call<view_type,Arg0, Args...>::type typename clef::_result_of::make_expr_call<view_type,Arg0, Args...>::type
operator()(Arg0 arg0, Args... args) const { operator()(Arg0 arg0, Args... args) const {
@ -227,34 +213,14 @@ namespace triqs { namespace gfs {
template<typename ... U> template<typename ... U>
cr_type operator[] (closest_pt_wrap<U...> const & p) const { return _data_proxy(_data, _mesh.index_to_linear( gfs_implementation::get_closest_point<Variable,Target,Opt>::invoke(this,p)));} cr_type operator[] (closest_pt_wrap<U...> const & p) const { return _data_proxy(_data, _mesh.index_to_linear( gfs_implementation::get_closest_point<Variable,Target,Opt>::invoke(this,p)));}
// Interaction with the CLEF library : calling the gf with any clef expression as argument build a new clef expression
/* template<typename Arg>
typename boost::lazy_enable_if< // enable the template if
clef::is_any_lazy<Arg>, // One of Args is a lazy expression
clef::_result_of::make_expr_subscript<view_type,Arg>
>::type // end of lazy_enable_if
operator[](Arg && arg) const { return clef::make_expr_subscript(view_type(*this),std::forward<Arg>(arg));}
*/
/*template<typename Arg>
//auto operator[](Arg && arg) const DECL_AND_RETURN(clef::make_expr_subscript((*this)(),std::forward<Arg>(arg)));
auto operator[](Arg && arg) const DECL_AND_RETURN(clef::make_expr_subscript(view_type(*this),std::forward<Arg>(arg)));
template<typename Arg>
//auto operator[](Arg && arg) DECL_AND_RETURN(clef::make_expr_subscript((*this)(),std::forward<Arg>(arg)));
auto operator[](Arg && arg) DECL_AND_RETURN(clef::make_expr_subscript(view_type(*this),std::forward<Arg>(arg)));
*/
template<typename Arg> template<typename Arg>
typename clef::_result_of::make_expr_subscript<view_type,Arg>::type typename clef::_result_of::make_expr_subscript<view_type,Arg>::type
operator[](Arg && arg) const { return clef::make_expr_subscript(view_type(*this),std::forward<Arg>(arg));} operator[](Arg && arg) const { return clef::make_expr_subscript(view_type(*this),std::forward<Arg>(arg));}
/// A direct access to the grid point /// A direct access to the grid point
template<typename... Args> template<typename... Args>
r_type on_mesh (Args&&... args) { return _data_proxy(_data,_mesh.index_to_linear(mesh_index_t(std::forward<Args>(args)...)));} r_type on_mesh (Args&&... args) { return _data_proxy(_data,_mesh.index_to_linear(mesh_index_t(std::forward<Args>(args)...)));}
/// A direct access to the grid point (const version)
template<typename... Args> template<typename... Args>
cr_type on_mesh (Args&&... args) const { return _data_proxy(_data,_mesh.index_to_linear(mesh_index_t(std::forward<Args>(args)...)));} cr_type on_mesh (Args&&... args) const { return _data_proxy(_data,_mesh.index_to_linear(mesh_index_t(std::forward<Args>(args)...)));}
@ -279,7 +245,7 @@ namespace triqs { namespace gfs {
friend void h5_write (h5::group fg, std::string subgroup_name, gf_impl const & g) { friend void h5_write (h5::group fg, std::string subgroup_name, gf_impl const & g) {
auto gr = fg.create_group(subgroup_name); auto gr = fg.create_group(subgroup_name);
gr.write_triqs_hdf5_data_scheme(g); gr.write_triqs_hdf5_data_scheme(g);
gfs_implementation::h5_ops<Variable,Target,Opt>::write(gr, "data", g._data, g);//can be specialized for some descriptors (E.g. blocks) gfs_implementation::h5_ops<Variable,Target,Opt>::write(gr, "data", g._data, g);
h5_write(gr,"singularity",g._singularity); h5_write(gr,"singularity",g._singularity);
h5_write(gr,"mesh",g._mesh); h5_write(gr,"mesh",g._mesh);
h5_write(gr,"symmetry",g._symmetry); h5_write(gr,"symmetry",g._symmetry);
@ -293,7 +259,7 @@ namespace triqs { namespace gfs {
auto tag_expected= get_triqs_hdf5_data_scheme(g); auto tag_expected= get_triqs_hdf5_data_scheme(g);
if (tag_file != tag_expected) if (tag_file != tag_expected)
TRIQS_RUNTIME_ERROR<< "h5_read : mismatch of the tag TRIQS_HDF5_data_scheme tag in the h5 group : found "<<tag_file << " while I expected "<< tag_expected; TRIQS_RUNTIME_ERROR<< "h5_read : mismatch of the tag TRIQS_HDF5_data_scheme tag in the h5 group : found "<<tag_file << " while I expected "<< tag_expected;
gfs_implementation::h5_ops<Variable,Target,Opt>::read(gr, "data", g._data, g);//can be specialized for some descriptors (E.g. blocks) gfs_implementation::h5_ops<Variable,Target,Opt>::read(gr, "data", g._data, g);
h5_read(gr,"singularity",g._singularity); h5_read(gr,"singularity",g._singularity);
h5_read(gr,"mesh",g._mesh); h5_read(gr,"mesh",g._mesh);
h5_read(gr,"symmetry",g._symmetry); h5_read(gr,"symmetry",g._symmetry);
@ -339,11 +305,11 @@ namespace triqs { namespace gfs {
gf & operator = (gf const & rhs) { *this = gf(rhs); return *this;} // use move = 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) { *this = gf(rhs); return *this;} // use move =
gf & operator = (gf && rhs) noexcept { swap(*this, rhs); return *this;} gf & operator = (gf && rhs) noexcept { swap(*this,rhs); return *this;}
template<typename RHS> void operator = (RHS && rhs) { template<typename RHS> void operator = (RHS && rhs) {
this->_mesh = rhs.mesh(); this->_mesh = std::forward<RHS>(rhs).mesh();
B::data_proxy_t::assign_with_resize(this->data(), std::forward<RHS>(rhs).data()); // looks strange for && for (auto const & w: this->mesh()) (*this)[w] = rhs[w];
this->_singularity = rhs.singularity(); this->_singularity = rhs.singularity();
// to be implemented : there is none in the gf_expr in particular.... // to be implemented : there is none in the gf_expr in particular....
//this->_symmetry = rhs.symmetry(); //this->_symmetry = rhs.symmetry();
@ -406,7 +372,7 @@ namespace triqs { namespace gfs {
template<typename Variable, typename Target, typename Opt, typename RHS> template<typename Variable, typename Target, typename Opt, typename RHS>
DISABLE_IF(arrays::is_scalar<RHS>) triqs_gf_view_assign_delegation( gf_view<Variable,Target,Opt> g, RHS const & rhs) { DISABLE_IF(arrays::is_scalar<RHS>) triqs_gf_view_assign_delegation( gf_view<Variable,Target,Opt> g, RHS const & rhs) {
if (!(g.mesh() == rhs.mesh())) TRIQS_RUNTIME_ERROR<<"Gf Assignment in View : incompatible mesh"; if (!(g.mesh() == rhs.mesh())) TRIQS_RUNTIME_ERROR<<"Gf Assignment in View : incompatible mesh";
gf_view<Variable,Target,Opt>::data_proxy_t::assign_no_resize(g.data(),rhs.data()); for (auto const & w: g.mesh()) g[w] = rhs[w];
g.singularity() = rhs.singularity(); g.singularity() = rhs.singularity();
} }

View File

@ -22,47 +22,61 @@
#define TRIQS_GF_EXPR_H #define TRIQS_GF_EXPR_H
#include <triqs/utility/expression_template_tools.hpp> #include <triqs/utility/expression_template_tools.hpp>
namespace triqs { namespace gfs { namespace triqs { namespace gfs {
using utility::is_in_ZRC; using utility::is_in_ZRC;
using utility::remove_rvalue_ref;
namespace gfs_expr_tools { namespace gfs_expr_tools {
// a wrapper for scalars
template<typename S> struct scalar_wrap { template<typename S> struct scalar_wrap {
typedef S value_type; typedef void variable_t;
S s; scalar_wrap(S const &s_):s(s_){} typedef void target_t;
typedef void option_t;
S s;
template<typename T> scalar_wrap(T && x):s(std::forward<T>(x)){}
S singularity() const { return s;} S singularity() const { return s;}
S data() const { return s;} template<typename KeyType> S operator[](KeyType && key) const { return s;}
template<typename KeyType> value_type operator[](KeyType && key) const { return s;} template<typename ... Args> inline S operator()(Args && ... args) const { return s;}
template<typename ... Args> inline value_type operator()(Args && ... args) const { return s;}
friend std::ostream &operator <<(std::ostream &sout, scalar_wrap const &expr){return sout << expr.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 // Combine the two meshes of LHS and RHS : need to specialize where there is a scalar
struct combine_mesh { struct combine_mesh {
template<typename L, typename R> template<typename L, typename R>
inline auto operator() (L const & l, R const & r) const -> decltype(l.mesh()) { auto operator() (L && l, R && r) const -> decltype(std::forward<L>(l).mesh()) {
if (!(l.mesh() == r.mesh())) TRIQS_RUNTIME_ERROR << "Mesh mismatch : ";//<< l.mesh()<<" vs" <<r.mesh(); if (!(l.mesh() == r.mesh())) TRIQS_RUNTIME_ERROR << "Mesh mismatch : ";//<< l.mesh()<<" vs" <<r.mesh();
return l.mesh(); return std::forward<L>(l).mesh();
} }
template<typename S, typename R> auto operator() (scalar_wrap<S> const & w, R const & r) const -> decltype(r.mesh()) { return r.mesh();} template<typename S, typename R> auto operator() (scalar_wrap<S> const &, R && r) const DECL_AND_RETURN(std::forward<R>(r).mesh());
template<typename S, typename L> auto operator() (L const & l, scalar_wrap<S> const & w) const -> decltype(l.mesh()) { return l.mesh();} template<typename S, typename L> auto operator() (L && l, scalar_wrap<S> const &) const DECL_AND_RETURN(std::forward<L>(l).mesh());
}; };
template<typename T> struct keeper_type : std::conditional<utility::is_in_ZRC<T>::value, scalar_wrap<T>, typename view_type_if_exists_else_type<T>::type> {}; template<typename T> struct node_t : std::conditional<utility::is_in_ZRC<T>::value, scalar_wrap<T>, typename remove_rvalue_ref<T>::type> {};
template <typename A, typename B> struct _or_ {typedef void type;};
template <typename A> struct _or_<A,A> {typedef A type;};
template <typename A> struct _or_<void,A> {typedef A type;};
template <typename A> struct _or_<A,void> {typedef A type;};
template <> struct _or_<void,void> {typedef void type;};
}// gfs_expr_tools }// gfs_expr_tools
template<typename Descriptor, typename Tag, typename L, typename R> struct gf_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction),gf_tag<Descriptor> { template<typename Tag, typename L, typename R> struct gf_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction){
typedef typename gfs_expr_tools::keeper_type<L>::type L_t; typedef typename std::remove_reference<L>::type L_t;
typedef typename gfs_expr_tools::keeper_type<R>::type R_t; typedef typename std::remove_reference<R>::type R_t;
typedef Descriptor descriptor_t; typedef typename gfs_expr_tools::_or_<typename L_t::variable_t,typename R_t::variable_t>::type variable_t;
//typedef typename std::result_of<utility::operation<Tag>(typename L_t::value_type,typename R_t::value_type)>::type value_t; typedef typename gfs_expr_tools::_or_<typename L_t::target_t,typename R_t::target_t>::type target_t;
typedef typename std::remove_reference<typename std::result_of<gfs_expr_tools::combine_mesh(L_t,R_t)>::type>::type mesh_t; typedef typename gfs_expr_tools::_or_<typename L_t::option_t,typename R_t::option_t>::type option_t;
//typedef typename Descriptor::singularity_t::view_type singularity_view_t; static_assert(!std::is_same<variable_t,void>::value, "Can not combine two gf expressions with different variables");
//typedef value_t value_type; static_assert(!std::is_same<target_t,void>::value, "Can not combine two gf expressions with different target");
L_t l; R_t r;
template<typename LL, typename RR> gf_expr(LL && l_, RR && r_) : l(std::forward<LL>(l_)), r(std::forward<RR>(r_)) {} L l; R r;
mesh_t mesh() const { return gfs_expr_tools::combine_mesh()(l,r); } template<typename LL, typename RR> gf_expr(LL && l_, RR && r_):l(std::forward<LL>(l_)), r(std::forward<RR>(r_)) {}
auto data() const ->decltype( utility::operation<Tag>()(l.data(), r.data())) { return utility::operation<Tag>()(l.data(), r.data());}
auto mesh() const DECL_AND_RETURN(gfs_expr_tools::combine_mesh()(l,r));
auto singularity() const DECL_AND_RETURN (utility::operation<Tag>()(l.singularity() , r.singularity())); auto singularity() const DECL_AND_RETURN (utility::operation<Tag>()(l.singularity() , r.singularity()));
//const singularity_view_t singularity() const { return utility::operation<Tag>()(l.singularity() , r.singularity());}
//symmetry_t const & symmetry() const { return _symmetry;}
template<typename KeyType> auto operator[](KeyType && key) const DECL_AND_RETURN(utility::operation<Tag>()(l[std::forward<KeyType>(key)] , r[std::forward<KeyType>(key)])); template<typename KeyType> auto operator[](KeyType && key) const DECL_AND_RETURN(utility::operation<Tag>()(l[std::forward<KeyType>(key)] , r[std::forward<KeyType>(key)]));
template<typename ... Args> auto operator()(Args && ... args) const DECL_AND_RETURN(utility::operation<Tag>()(l(std::forward<Args>(args)...) , r(std::forward<Args>(args)...))); template<typename ... Args> auto operator()(Args && ... args) const DECL_AND_RETURN(utility::operation<Tag>()(l(std::forward<Args>(args)...) , r(std::forward<Args>(args)...)));
friend std::ostream &operator <<(std::ostream &sout, gf_expr const &expr){return sout << "("<<expr.l << " "<<utility::operation<Tag>::name << " "<<expr.r<<")" ; } friend std::ostream &operator <<(std::ostream &sout, gf_expr const &expr){return sout << "("<<expr.l << " "<<utility::operation<Tag>::name << " "<<expr.r<<")" ; }
@ -70,44 +84,30 @@ namespace triqs { namespace gfs {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//a special case : the unary operator ! //a special case : the unary operator !
template<typename Descriptor, typename L> struct gf_unary_m_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction),gf_tag<Descriptor>{ template<typename L> struct gf_unary_m_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction){
typedef typename gfs_expr_tools::keeper_type<L>::type L_t; typedef typename std::remove_reference<L>::type L_t;
typedef Descriptor descriptor_t; typedef typename L_t::variable_t variable_t;
//typedef typename L_t::value_type value_type; typedef typename L_t::target_t target_t;
typedef typename L_t::mesh_t mesh_t; typedef typename L_t::option_t option_t;
//typedef typename Descriptor::singularity_t::view_type singularity_view_t;
L_t l; L l;
template<typename LL> gf_unary_m_expr(LL && l_) : l(std::forward<LL>(l_)) {} template<typename LL> gf_unary_m_expr(LL && l_) : l(std::forward<LL>(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()); 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<typename KeyType> auto operator[](KeyType&& key) const DECL_AND_RETURN( -l[key]); template<typename KeyType> auto operator[](KeyType&& key) const DECL_AND_RETURN( -l[key]);
template<typename ... Args> auto operator()(Args && ... args) const DECL_AND_RETURN( -l(std::forward<Args>(args)...)); template<typename ... Args> auto operator()(Args && ... args) const DECL_AND_RETURN( -l(std::forward<Args>(args)...));
friend std::ostream &operator <<(std::ostream &sout, gf_unary_m_expr const &expr){return sout << '-'<<expr.l; } friend std::ostream &operator <<(std::ostream &sout, gf_unary_m_expr const &expr){return sout << '-'<<expr.l; }
}; };
// -------------------------------------------------------------------
// get the descriptor ...
template<typename A1, typename A2, typename Enable=void> struct get_desc;
template<typename A1, typename A2>
struct get_desc <A1,A2, typename std::enable_if<((!ImmutableGreenFunction<A1>::value) && (ImmutableGreenFunction<A2>::value))>::type > {
typedef typename A2::descriptor_t type;
};
template<typename A1, typename A2>
struct get_desc <A1,A2,typename std::enable_if<(!ImmutableGreenFunction<A2>::value) && (ImmutableGreenFunction<A1>::value)>::type > {
typedef typename A1::descriptor_t type;
};
template<typename A1, typename A2>
struct get_desc <A1,A2, typename std::enable_if< (ImmutableGreenFunction<A1>::value) && (ImmutableGreenFunction<A2>::value) && std::is_same<typename A1::descriptor_t,typename A2::descriptor_t>::value >::type > { typedef typename A2::descriptor_t type; };
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Now we can define all the C++ operators ... // Now we can define all the C++ operators ...
#define DEFINE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \ #define DEFINE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \
template<typename A1, typename A2>\ template<typename A1, typename A2>\
typename std::enable_if<TRAIT1<A1>::value && TRAIT2 <A2>::value, gf_expr<typename get_desc<A1,A2>::type, utility::tags::TAG, A1,A2>>::type\ typename std::enable_if<TRAIT1<A1>::value && TRAIT2 <A2>::value, \
operator OP (A1 const & a1, A2 const & a2) { return gf_expr<typename get_desc<A1,A2>::type,utility::tags::TAG, A1,A2>(a1,a2);} gf_expr<utility::tags::TAG, typename gfs_expr_tools::node_t<A1>::type, typename gfs_expr_tools::node_t<A2>::type>>::type\
operator OP (A1 && a1, A2 && a2) { return {std::forward<A1>(a1),std::forward<A2>(a2)};}
DEFINE_OPERATOR(plus, +, ImmutableGreenFunction,ImmutableGreenFunction); DEFINE_OPERATOR(plus, +, ImmutableGreenFunction,ImmutableGreenFunction);
DEFINE_OPERATOR(minus, -, ImmutableGreenFunction,ImmutableGreenFunction); DEFINE_OPERATOR(minus, -, ImmutableGreenFunction,ImmutableGreenFunction);
@ -120,8 +120,12 @@ namespace triqs { namespace gfs {
#undef DEFINE_OPERATOR #undef DEFINE_OPERATOR
// the unary is special // the unary is special
template<typename A1> typename std::enable_if<ImmutableGreenFunction<A1>::value, gf_unary_m_expr<typename A1::descriptor_t, A1>>::type template<typename A1>
operator - (A1 const & a1) { return gf_unary_m_expr<typename A1::descriptor_t, A1>(a1);} typename std::enable_if<
ImmutableGreenFunction<A1>::value,
gf_unary_m_expr<typename gfs_expr_tools::node_t<A1>::type >
>::type
operator - (A1 && a1) { return {std::forward<A1>(a1)};}
}}//namespace triqs::gf }}//namespace triqs::gf
#endif #endif

View File

@ -32,8 +32,9 @@
#define TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT(MyBeautifulConcept) \ #define TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT(MyBeautifulConcept) \
struct TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept) {};\ struct TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept) {};\
template<typename T> struct MyBeautifulConcept : boost::is_base_of<TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept) , T> {};\ template<typename T> struct MyBeautifulConcept : boost::is_base_of<TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept) , T> {};\
template<typename T> struct MyBeautifulConcept<T&> : boost::is_base_of<TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept), T> {};\ template<typename T> struct MyBeautifulConcept<const T> : MyBeautifulConcept<T>{};\
template<typename T> struct MyBeautifulConcept<T&&> : boost::is_base_of<TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept), T> {}; template<typename T> struct MyBeautifulConcept<T&> : MyBeautifulConcept<T>{};\
template<typename T> struct MyBeautifulConcept<T&&> : MyBeautifulConcept<T>{};
#define TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R_AUX(r, data, i, elem) BOOST_PP_COMMA_IF(i) TRIQS_CONCEPT_TAG_NAME(elem) #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) \ #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) {};\ struct TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept) : BOOST_PP_SEQ_FOR_EACH_I (TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R_AUX,nil,Rs) {};\
template<typename T> struct MyBeautifulConcept : boost::is_base_of<TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept), T> {};\ template<typename T> struct MyBeautifulConcept : boost::is_base_of<TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept), T> {};\
template<typename T> struct MyBeautifulConcept<T&> : boost::is_base_of<TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept), T> {};\ template<typename T> struct MyBeautifulConcept<const T> : MyBeautifulConcept<T>{};\
template<typename T> struct MyBeautifulConcept<T&&> : boost::is_base_of<TRIQS_CONCEPT_TAG_NAME(MyBeautifulConcept), T> {}; template<typename T> struct MyBeautifulConcept<T&> : MyBeautifulConcept<T>{};\
template<typename T> struct MyBeautifulConcept<T&&> : MyBeautifulConcept<T>{};
#ifdef TRIQS_COMPILE_TIME_DEBUG #ifdef TRIQS_COMPILE_TIME_DEBUG
#define TRIQS_ASSERT_MODEL_CONCEPT(MyBeautifulConcept,T) BOOST_CONCEPT_ASSERT((BCC_##MyBeautifulConcept<T>)); #define TRIQS_ASSERT_MODEL_CONCEPT(MyBeautifulConcept,T) BOOST_CONCEPT_ASSERT((BCC_##MyBeautifulConcept<T>));

View File

@ -22,26 +22,32 @@
#define TRIQS_UTILITY_EXPRESSION_TEMPLATE_TOOLS_H #define TRIQS_UTILITY_EXPRESSION_TEMPLATE_TOOLS_H
#include <type_traits> #include <type_traits>
#include <complex> #include <complex>
#include "./macros.hpp"
namespace triqs { namespace utility { namespace triqs { namespace utility {
template<class T> struct remove_rvalue_ref {typedef T type;};
template<class T> struct remove_rvalue_ref<T&> {typedef T const & type;};
template<class T> struct remove_rvalue_ref<T&&> {typedef T type;};
namespace tags { struct plus{}; struct minus{}; struct multiplies{}; struct divides{}; } 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<typename Tag> struct operation; template<typename Tag> struct operation;
template<> struct operation<tags::plus> { template<> struct operation<tags::plus> {
template<typename L, typename R> auto operator()(L const & l, R const & r) const -> decltype(l+r) { return l+r;} template<typename L, typename R> auto operator()(L && l, R && r) const DECL_AND_RETURN(std::forward<L>(l) + std::forward<R>(r));
static const char name = '+'; static const char name = '+';
}; };
template<> struct operation<tags::minus> { template<> struct operation<tags::minus> {
template<typename L, typename R> auto operator()(L const & l, R const & r) const -> decltype(l-r) { return l-r;} template<typename L, typename R> auto operator()(L && l, R && r) const DECL_AND_RETURN(std::forward<L>(l) - std::forward<R>(r));
static const char name = '-'; static const char name = '-';
}; };
template<> struct operation<tags::multiplies> { template<> struct operation<tags::multiplies> {
template<typename L, typename R> auto operator()(L const & l, R const & r) const -> decltype(l*r) { return l*r;} template<typename L, typename R> auto operator()(L && l, R && r) const DECL_AND_RETURN(std::forward<L>(l) * std::forward<R>(r));
static const char name = '*'; static const char name = '*';
}; };
template<> struct operation<tags::divides> { template<> struct operation<tags::divides> {
template<typename L, typename R> auto operator()(L const & l, R const & r) const -> decltype(l/r) { return l/r;} template<typename L, typename R> auto operator()(L && l, R && r) const DECL_AND_RETURN(std::forward<L>(l) / std::forward<R>(r));
static const char name = '/'; static const char name = '/';
}; };
@ -49,11 +55,15 @@ namespace triqs { namespace utility {
template<typename T> struct is_in_ZRC : std::is_arithmetic<T> {}; template<typename T> struct is_in_ZRC : std::is_arithmetic<T> {};
template<> struct is_in_ZRC<bool> : std::true_type {}; template<> struct is_in_ZRC<bool> : std::true_type {};
template<typename T> struct is_in_ZRC<std::complex<T> > : std::true_type {}; template<typename T> struct is_in_ZRC<std::complex<T> > : std::true_type {};
template<typename T> struct is_in_ZRC<T&> : is_in_ZRC<T>{};
template<typename T> struct is_in_ZRC<T&&> : is_in_ZRC<T>{};
template<typename T> struct is_in_ZRC<const T> : is_in_ZRC<T>{};
template<typename A, typename B> template<typename A, typename B>
struct type_of_mult{ struct type_of_mult{
typedef decltype ( std::declval<typename std::remove_reference<A>::type>() * std::declval<typename std::remove_reference<B>::type>() ) type; typedef decltype ( std::declval<typename std::remove_reference<A>::type>() * std::declval<typename std::remove_reference<B>::type>() ) type;
}; };
}}//namespace triqs::utility }}//namespace triqs::utility
#endif #endif

View File

@ -24,6 +24,8 @@
#include <triqs/utility/concept_tools.hpp> #include <triqs/utility/concept_tools.hpp>
#include <triqs/utility/exceptions.hpp> #include <triqs/utility/exceptions.hpp>
#include <vector> #include <vector>
#include <iostream>
namespace triqs { namespace utility { namespace triqs { namespace utility {
// a trait to identify the std::vector ... // a trait to identify the std::vector ...
@ -31,11 +33,12 @@ namespace triqs { namespace utility {
template<typename T> struct ImmutableStdVector<std::vector<T>> : std::true_type{}; template<typename T> struct ImmutableStdVector<std::vector<T>> : std::true_type{};
namespace expr_temp_vec_tools { namespace expr_temp_vec_tools {
template<typename S> struct scalar_wrap { template<typename S> struct scalar_wrap {// S can be a T or a T &
typedef S value_type; typedef typename std::remove_reference<S>::type value_type;
S s; scalar_wrap(S const &s_):s(s_){} S s;
S operator[](size_t i) const { return s;} template<typename T> scalar_wrap(T && x):s(std::forward<T>(x)){}
friend std::ostream &operator <<(std::ostream &sout, scalar_wrap const &expr){return sout << expr.s; } 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 // 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" <<r.size(); if (!(l.size() == r.size())) TRIQS_RUNTIME_ERROR << "size mismatch : ";//<< l.size()<<" vs" <<r.size();
return l.size(); return l.size();
} }
template<typename S, typename R> size_t operator() (scalar_wrap<S> const & w, R const & r) const {return r.size();} template<typename S, typename R> size_t operator() (scalar_wrap<S> const &, R const & r) const {return r.size();}
template<typename S, typename L> size_t operator() (L const & l, scalar_wrap<S> const & w) const {return l.size();} template<typename S, typename L> size_t operator() (L const & l, scalar_wrap<S> const &) const {return l.size();}
}; };
template<typename T> struct keeper_type : std::conditional<utility::is_in_ZRC<T>::value, scalar_wrap<T>, T const &> {}; template<typename T> struct node_t : std::conditional<utility::is_in_ZRC<T>::value, scalar_wrap<T>, typename remove_rvalue_ref<T>::type> {};
template<typename V> template<typename V>
std::vector<typename V::value_type> make_vector(V const & v) { auto make_vector(V const & v) -> std::vector<typename std::remove_reference<decltype(v[0])>::type> {
std::vector<typename V::value_type> res; res.reserve(v.size()); //auto make_vector(V const & v) -> std::vector<typename std::remove_reference<decltype(static_cast<V const &>(v)[0])>::type> {
for (size_t i =0; i<v.size(); ++i) res.push_back( v[i]); std::vector<typename std::remove_reference<decltype(v[0])>::type> res;
std::cout << "makeVector"<< std::endl;
res.reserve(v.size());
for (size_t i =0; i<v.size(); ++i) res.push_back(v[i]);
return res; return res;
} }
@ -64,38 +70,40 @@ namespace triqs { namespace utility {
namespace std { // no choice since the operators are found by ADL.. namespace std { // no choice since the operators are found by ADL..
template<typename Tag, typename L, typename R> struct std_vec_expr : triqs::utility::ImmutableStdVector__concept_tag { template<typename Tag, typename L, typename R> struct std_vec_expr : triqs::utility::ImmutableStdVector__concept_tag {
typedef typename triqs::utility::expr_temp_vec_tools::keeper_type<L>::type L_t; L l; R r;
typedef typename triqs::utility::expr_temp_vec_tools::keeper_type<R>::type R_t;
typedef typename std::result_of<triqs::utility::operation<Tag>(typename std::remove_reference<L_t>::type::value_type,
typename std::remove_reference<R_t>::type::value_type)>::type value_t;
typedef value_t value_type;
L_t l; R_t r;
template<typename LL, typename RR> std_vec_expr(LL && l_, RR && r_) : l(std::forward<LL>(l_)), r(std::forward<RR>(r_)) {} template<typename LL, typename RR> std_vec_expr(LL && l_, RR && r_) : l(std::forward<LL>(l_)), r(std::forward<RR>(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); } 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<Tag>()(l[i] , r[i]);} auto operator[](size_t i) const DECL_AND_RETURN(triqs::utility::operation<Tag>()(l[i] , r[i]));
friend std::ostream &operator <<(std::ostream &sout, std_vec_expr const &expr){return sout << "("<<expr.l << " "<<triqs::utility::operation<Tag>::name << " "<<expr.r<<")" ; } friend std::ostream &operator <<(std::ostream &sout, std_vec_expr const &expr){return sout << "("<<expr.l <<" "<<triqs::utility::operation<Tag>::name <<" "<<expr.r<<")";}
friend std::vector<value_type> make_vector(std_vec_expr const & v) { return triqs::utility::expr_temp_vec_tools::make_vector(v);}
}; };
template<typename Tag, typename L, typename R>
auto make_vector(std_vec_expr<Tag,L,R> const & v) DECL_AND_RETURN(triqs::utility::expr_temp_vec_tools::make_vector(v));
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//a special case : the unary operator ! //a special case : the unary operator !
template<typename L> struct std_vec_expr_unary : triqs::utility::ImmutableStdVector__concept_tag { template<typename L> struct std_vec_expr_unary : triqs::utility::ImmutableStdVector__concept_tag {
typedef typename triqs::utility::expr_temp_vec_tools::keeper_type<L>::type L_t; L l;
typedef typename L_t::value_type value_type;
L_t l;
template<typename LL> std_vec_expr_unary(LL && l_) : l(std::forward<LL>(l_)) {} template<typename LL> std_vec_expr_unary(LL && l_) : l(std::forward<LL>(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(); } 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 << '-'<<expr.l; } friend std::ostream &operator <<(std::ostream &sout, std_vec_expr_unary const &expr){return sout << '-'<<expr.l; }
friend std::vector<value_type> make_vector(std_vec_expr_unary const & v) { return triqs::utility::expr_temp_vec_tools::make_vector(v);}
}; };
template<typename L>
auto make_vector(std_vec_expr_unary<L> const & v) DECL_AND_RETURN(triqs::utility::expr_temp_vec_tools::make_vector(v));
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Now we can define all the C++ operators ... // Now we can define all the C++ operators ...
#define DEFINE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \ #define DEFINE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \
template<typename A1, typename A2>\ template<typename A1, typename A2>\
typename std::enable_if<triqs::utility::TRAIT1<A1>::value && triqs::utility::TRAIT2 <A2>::value, std_vec_expr<triqs::utility::tags::TAG, A1,A2>>::type\ typename std::enable_if<triqs::utility::TRAIT1<A1>::value && triqs::utility::TRAIT2 <A2>::value, \
operator OP (A1 const & a1, A2 const & a2) { return std_vec_expr<triqs::utility::tags::TAG, A1,A2>(a1,a2);} std_vec_expr<triqs::utility::tags::TAG, typename triqs::utility::expr_temp_vec_tools::node_t<A1>::type, typename triqs::utility::expr_temp_vec_tools::node_t<A2>::type>>::type\
operator OP (A1 && a1, A2 && a2) { return {std::forward<A1>(a1),std::forward<A2>(a2)};}
DEFINE_OPERATOR(plus, +, ImmutableStdVector,ImmutableStdVector); DEFINE_OPERATOR(plus, +, ImmutableStdVector,ImmutableStdVector);
DEFINE_OPERATOR(minus, -, 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 // the unary is special
template<typename A1> typename std::enable_if<triqs::utility::ImmutableStdVector<A1>::value, std_vec_expr_unary<A1>>::type template<typename A1> typename std::enable_if<triqs::utility::ImmutableStdVector<A1>::value, std_vec_expr_unary<A1>>::type
operator - (A1 const & a1) { return std_vec_expr_unary<A1>(a1);} operator - (A1 const & a1) { return std_vec_expr_unary<A1>(a1);}
} }
/*
namespace triqs { namespace utility { namespace expr_temp_vec_tools {
//make sure expression are never taken by const &
template<typename Tag, typename L, typename R> struct expr_node_storage_t <std::std_vec_expr<Tag,L,R> &> ;// { typedef std::std_vec_expr<Tag,L,R> type;};
template<typename Tag, typename L, typename R> struct expr_node_storage_t <std::std_vec_expr<Tag,L,R> const &> ;//{ typedef std::std_vec_expr<Tag,L,R> type;};
template<typename L> struct expr_node_storage_t <std::std_vec_expr_unary<L> &> ;// { typedef std::std_vec_expr_unary<L> type;};
template<typename L> struct expr_node_storage_t <std::std_vec_expr_unary<L> const &>;// { typedef std::std_vec_expr_unary<L> type;};
}// std_vec_expr_tools
}}
*/
#endif #endif