3
0
mirror of https://github.com/triqs/dft_tools synced 2024-12-24 13:23:37 +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::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 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()); }
};
@ -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<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 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()); }
};
@ -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<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 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 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 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 arrays::make_shape;
// GENERALISE matrxi TO DEFAULT
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_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<typename Variable, typename Target, typename Opt> 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<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 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>
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
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<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 :
// Pattern : ValueView
typedef gf_view<Variable,Target,Opt> view_type;
typedef gf<Variable,Target,Opt> regular_type;
typedef gf_desc<Variable,Target,Opt> descriptor_t;
typedef Variable variable_t;
typedef Target target_t;
typedef Opt option_t;
typedef gf_mesh<Variable,Opt> 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<Variable,Target,Opt>::type symmetry_t;
typedef gfs_implementation::evaluator<Variable,Target,Opt> evaluator_t;
typedef typename gfs_implementation::symmetry<Variable,Target,Opt>::type symmetry_t;
typedef gfs_implementation::evaluator<Variable,Target,Opt> evaluator_t;
typedef gfs_implementation::data_proxy<Variable,Target,Opt> data_proxy_t;
typedef gfs_implementation::data_proxy<Variable,Target,Opt> 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<IsView, data_view_t, data_regular_t>::type data_t;
typedef typename std::conditional<IsView, data_view_t, data_regular_t>::type data_t;
typedef typename gfs_implementation::singularity<Variable,Target,Opt>::type singularity_non_view_t;
typedef typename gfs_implementation::singularity<Variable,Target,Opt>::type singularity_non_view_t;
typedef typename view_type_if_exists_else_type<singularity_non_view_t>::type singularity_view_t;
typedef typename std::conditional<IsView, singularity_view_t, singularity_non_view_t>::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>( 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>
typename clef::_result_of::make_expr_call<view_type,Arg0, Args...>::type
operator()(Arg0 arg0, Args... args) const {
@ -227,34 +213,14 @@ namespace triqs { namespace gfs {
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)));}
// 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>
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));}
/// A direct access to the grid point
template<typename... 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>
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) {
auto gr = fg.create_group(subgroup_name);
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,"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 "<<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,"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<typename RHS> void operator = (RHS && rhs) {
this->_mesh = rhs.mesh();
B::data_proxy_t::assign_with_resize(this->data(), std::forward<RHS>(rhs).data()); // looks strange for &&
this->_mesh = std::forward<RHS>(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<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) {
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());
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();
}

View File

@ -21,93 +21,93 @@
#ifndef TRIQS_GF_EXPR_H
#define TRIQS_GF_EXPR_H
#include <triqs/utility/expression_template_tools.hpp>
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<typename S> 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<typename T> scalar_wrap(T && x):s(std::forward<T>(x)){}
S singularity() const { return s;}
S data() const { return s;}
template<typename KeyType> value_type operator[](KeyType && key) const { return s;}
template<typename ... Args> inline value_type operator()(Args && ... args) const { return s;}
template<typename KeyType> S operator[](KeyType && key) const { return s;}
template<typename ... Args> 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<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();
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 L> auto operator() (L const & l, scalar_wrap<S> const & w) const -> decltype(l.mesh()) { return l.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 && 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
template<typename Descriptor, typename Tag, typename L, typename R> struct gf_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction),gf_tag<Descriptor> {
typedef typename gfs_expr_tools::keeper_type<L>::type L_t;
typedef typename gfs_expr_tools::keeper_type<R>::type R_t;
typedef Descriptor descriptor_t;
//typedef typename std::result_of<utility::operation<Tag>(typename L_t::value_type,typename R_t::value_type)>::type value_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 Descriptor::singularity_t::view_type singularity_view_t;
//typedef value_t value_type;
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_)) {}
mesh_t mesh() const { return gfs_expr_tools::combine_mesh()(l,r); }
auto data() const ->decltype( utility::operation<Tag>()(l.data(), r.data())) { return utility::operation<Tag>()(l.data(), r.data());}
template<typename Tag, typename L, typename R> struct gf_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction){
typedef typename std::remove_reference<L>::type L_t;
typedef typename std::remove_reference<R>::type R_t;
typedef typename gfs_expr_tools::_or_<typename L_t::variable_t,typename R_t::variable_t>::type variable_t;
typedef typename gfs_expr_tools::_or_<typename L_t::target_t,typename R_t::target_t>::type target_t;
typedef typename gfs_expr_tools::_or_<typename L_t::option_t,typename R_t::option_t>::type option_t;
static_assert(!std::is_same<variable_t,void>::value, "Can not combine two gf expressions with different variables");
static_assert(!std::is_same<target_t,void>::value, "Can not combine two gf expressions with different target");
L l; R r;
template<typename LL, typename RR> gf_expr(LL && l_, RR && r_):l(std::forward<LL>(l_)), r(std::forward<RR>(r_)) {}
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()));
//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)...)));
friend std::ostream &operator <<(std::ostream &sout, gf_expr const &expr){return sout << "("<<expr.l << " "<<utility::operation<Tag>::name << " "<<expr.r<<")" ; }
};
// -------------------------------------------------------------------
//a special case : the unary operator !
template<typename Descriptor, typename L> struct gf_unary_m_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction),gf_tag<Descriptor>{
typedef typename gfs_expr_tools::keeper_type<L>::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<typename L> struct gf_unary_m_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction){
typedef typename std::remove_reference<L>::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<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());
//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 ... 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; }
};
// -------------------------------------------------------------------
// 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 ...
#define DEFINE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \
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\
operator OP (A1 const & a1, A2 const & a2) { return gf_expr<typename get_desc<A1,A2>::type,utility::tags::TAG, A1,A2>(a1,a2);}
typename std::enable_if<TRAIT1<A1>::value && TRAIT2 <A2>::value, \
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(minus, -, ImmutableGreenFunction,ImmutableGreenFunction);
@ -120,8 +120,12 @@ namespace triqs { namespace gfs {
#undef DEFINE_OPERATOR
// the unary is special
template<typename A1> typename std::enable_if<ImmutableGreenFunction<A1>::value, gf_unary_m_expr<typename A1::descriptor_t, A1>>::type
operator - (A1 const & a1) { return gf_unary_m_expr<typename A1::descriptor_t, A1>(a1);}
template<typename 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
#endif

View File

@ -32,8 +32,9 @@
#define TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT(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<T&> : 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&> : 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)
@ -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<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<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&> : MyBeautifulConcept<T>{};\
template<typename T> struct MyBeautifulConcept<T&&> : MyBeautifulConcept<T>{};
#ifdef TRIQS_COMPILE_TIME_DEBUG
#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
#include <type_traits>
#include <complex>
#include "./macros.hpp"
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{}; }
// The basic operations put in a template....
// The basic operations put in a template....
template<typename Tag> struct operation;
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 = '+';
};
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 = '-';
};
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 = '*';
};
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 = '/';
};
@ -49,11 +55,15 @@ namespace triqs { namespace utility {
template<typename T> struct is_in_ZRC : std::is_arithmetic<T> {};
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<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>
struct type_of_mult{
typedef decltype ( std::declval<typename std::remove_reference<A>::type>() * std::declval<typename std::remove_reference<B>::type>() ) type;
};
}}//namespace triqs::utility
#endif

View File

@ -24,6 +24,8 @@
#include <triqs/utility/concept_tools.hpp>
#include <triqs/utility/exceptions.hpp>
#include <vector>
#include <iostream>
namespace triqs { namespace utility {
// 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{};
namespace expr_temp_vec_tools {
template<typename S> 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<typename S> struct scalar_wrap {// S can be a T or a T &
typedef typename std::remove_reference<S>::type value_type;
S s;
template<typename T> scalar_wrap(T && x):s(std::forward<T>(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" <<r.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 L> size_t operator() (L const & l, scalar_wrap<S> const & w) const {return l.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 &) 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>
std::vector<typename V::value_type> make_vector(V const & v) {
std::vector<typename V::value_type> res; res.reserve(v.size());
for (size_t i =0; i<v.size(); ++i) res.push_back( v[i]);
auto make_vector(V const & v) -> std::vector<typename std::remove_reference<decltype(v[0])>::type> {
//auto make_vector(V const & v) -> std::vector<typename std::remove_reference<decltype(static_cast<V const &>(v)[0])>::type> {
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;
}
@ -64,38 +70,40 @@ namespace triqs { namespace utility {
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 {
typedef typename triqs::utility::expr_temp_vec_tools::keeper_type<L>::type L_t;
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;
L l; R 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); }
value_type operator[](size_t i) const { 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::vector<value_type> 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<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<<")";}
};
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 !
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;
typedef typename L_t::value_type value_type;
L_t l;
template<typename L> struct std_vec_expr_unary : triqs::utility::ImmutableStdVector__concept_tag {
L 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(); }
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::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 ...
#define DEFINE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \
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\
operator OP (A1 const & a1, A2 const & a2) { return std_vec_expr<triqs::utility::tags::TAG, A1,A2>(a1,a2);}
typename std::enable_if<triqs::utility::TRAIT1<A1>::value && triqs::utility::TRAIT2 <A2>::value, \
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(minus, -, ImmutableStdVector,ImmutableStdVector);
@ -110,8 +118,22 @@ namespace std { // no choice since the operators are found by ADL..
// the unary is special
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);}
}
/*
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