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:
parent
1e94eab495
commit
1906dc30a5
@ -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);}
|
||||
};
|
||||
|
@ -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,16 +89,13 @@ 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;
|
||||
@ -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);
|
||||
@ -342,8 +308,8 @@ namespace triqs { namespace gfs {
|
||||
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();
|
||||
@ -406,7 +372,7 @@ namespace triqs { namespace gfs {
|
||||
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());
|
||||
for (auto const & w: g.mesh()) g[w] = rhs[w];
|
||||
g.singularity() = rhs.singularity();
|
||||
}
|
||||
|
||||
|
@ -22,47 +22,61 @@
|
||||
#define TRIQS_GF_EXPR_H
|
||||
#include <triqs/utility/expression_template_tools.hpp>
|
||||
namespace triqs { namespace gfs {
|
||||
|
||||
using utility::is_in_ZRC;
|
||||
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 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_)) {}
|
||||
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());}
|
||||
|
||||
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 ... 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<<")" ; }
|
||||
@ -70,44 +84,30 @@ namespace triqs { namespace gfs {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
//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
|
||||
|
@ -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>));
|
||||
|
@ -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....
|
||||
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
|
||||
|
@ -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,9 +33,10 @@ 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_){}
|
||||
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;}
|
||||
};
|
||||
@ -45,15 +48,18 @@ 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());
|
||||
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]);}
|
||||
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::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 !
|
||||
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;
|
||||
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
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user