/******************************************************************************* * * TRIQS: a Toolbox for Research in Interacting Quantum Systems * * Copyright (C) 2012 by M. Ferrero, O. Parcollet * * TRIQS is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * TRIQS. If not, see . * ******************************************************************************/ #ifndef TRIQS_GF_EXPR_H #define TRIQS_GF_EXPR_H #include namespace triqs { namespace gfs { using utility::is_in_ZRC; using utility::remove_rvalue_ref; namespace gfs_expr_tools { // a wrapper for scalars template struct scalar_wrap { typedef void variable_t; typedef void target_t; typedef void option_t; S s; template scalar_wrap(T && x):s(std::forward(x)){} S singularity() const { return s;} template S operator[](KeyType && key) const { return s;} template inline S operator()(Args && ... args) const { return s;} friend std::ostream &operator <<(std::ostream &sout, scalar_wrap const &expr){return sout << expr.s; } }; // Combine the two meshes of LHS and RHS : need to specialize where there is a scalar struct combine_mesh { template auto operator() (L && l, R && r) const -> decltype(std::forward(l).mesh()) { if (!(l.mesh() == r.mesh())) TRIQS_RUNTIME_ERROR << "Mesh mismatch : in Green Function Expression "<< l.mesh()<<" vs" <(l).mesh(); } template auto operator() (scalar_wrap const &, R && r) const DECL_AND_RETURN(std::forward(r).mesh()); template auto operator() (L && l, scalar_wrap const &) const DECL_AND_RETURN(std::forward(l).mesh()); }; // Same thing to get the data shape // NB : could be unified to one combine, where F is a functor, but an easy usage requires polymorphic lambda ... struct combine_shape { template auto operator() (L && l, R && r) const -> decltype(get_gf_data_shape(std::forward(l))) { if (!(get_gf_data_shape(l) == get_gf_data_shape(r))) TRIQS_RUNTIME_ERROR << "Shape mismatch in Green Function Expression: " << get_gf_data_shape(l) << " vs "<< get_gf_data_shape(r); return get_gf_data_shape(std::forward(l)); } template auto operator() (scalar_wrap const &, R && r) const DECL_AND_RETURN(get_gf_data_shape(std::forward(r))); template auto operator() (L && l, scalar_wrap const &) const DECL_AND_RETURN(get_gf_data_shape(std::forward(l))); }; template struct node_t : std::conditional::value, scalar_wrap, typename remove_rvalue_ref::type> {}; template struct _or_ {typedef void type;}; template struct _or_ {typedef A type;}; template struct _or_ {typedef A type;}; template struct _or_ {typedef A type;}; template <> struct _or_ {typedef void type;}; }// gfs_expr_tools template struct gf_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction){ typedef typename std::remove_reference::type L_t; typedef typename std::remove_reference::type R_t; typedef typename gfs_expr_tools::_or_::type variable_t; typedef typename gfs_expr_tools::_or_::type target_t; typedef typename gfs_expr_tools::_or_::type option_t; static_assert(!std::is_same::value, "Cannot combine two gf expressions with different variables"); static_assert(!std::is_same::value, "Cannot combine two gf expressions with different target"); L l; R r; template gf_expr(LL && l_, RR && r_):l(std::forward(l_)), r(std::forward(r_)) {} auto mesh() const DECL_AND_RETURN(gfs_expr_tools::combine_mesh()(l,r)); auto singularity() const DECL_AND_RETURN (utility::operation()(l.singularity() , r.singularity())); auto get_data_shape() const DECL_AND_RETURN (gfs_expr_tools::combine_shape()(l,r)); template auto operator[](KeyType && key) const DECL_AND_RETURN(utility::operation()(l[std::forward(key)] , r[std::forward(key)])); template auto operator()(Args && ... args) const DECL_AND_RETURN(utility::operation()(l(std::forward(args)...) , r(std::forward(args)...))); friend std::ostream &operator <<(std::ostream &sout, gf_expr const &expr){return sout << "("<::name << " "< struct gf_unary_m_expr : TRIQS_CONCEPT_TAG_NAME(ImmutableGreenFunction){ typedef typename std::remove_reference::type L_t; typedef typename L_t::variable_t variable_t; typedef typename L_t::target_t target_t; typedef typename L_t::option_t option_t; L l; template gf_unary_m_expr(LL && l_) : l(std::forward(l_)) {} auto mesh() const DECL_AND_RETURN(l.mesh()); auto singularity() const DECL_AND_RETURN(l.singularity()); AUTO_DECL get_data_shape() const RETURN (get_gf_data_shape(l)); template auto operator[](KeyType&& key) const DECL_AND_RETURN( -l[key]); template auto operator()(Args && ... args) const DECL_AND_RETURN( -l(std::forward(args)...)); friend std::ostream &operator <<(std::ostream &sout, gf_unary_m_expr const &expr){return sout << '-'<\ typename std::enable_if::value && TRAIT2 ::value, \ gf_expr::type, typename gfs_expr_tools::node_t::type>>::type\ operator OP (A1 && a1, A2 && a2) { return {std::forward(a1),std::forward(a2)};} DEFINE_OPERATOR(plus, +, ImmutableGreenFunction,ImmutableGreenFunction); DEFINE_OPERATOR(minus, -, ImmutableGreenFunction,ImmutableGreenFunction); DEFINE_OPERATOR(multiplies, *, ImmutableGreenFunction,ImmutableGreenFunction); DEFINE_OPERATOR(multiplies, *, is_in_ZRC,ImmutableGreenFunction); DEFINE_OPERATOR(multiplies, *, ImmutableGreenFunction,is_in_ZRC); DEFINE_OPERATOR(divides, /, ImmutableGreenFunction,ImmutableGreenFunction); DEFINE_OPERATOR(divides, /, is_in_ZRC,ImmutableGreenFunction); DEFINE_OPERATOR(divides, /, ImmutableGreenFunction,is_in_ZRC); #undef DEFINE_OPERATOR // the unary is special template typename std::enable_if< ImmutableGreenFunction::value, gf_unary_m_expr::type > >::type operator - (A1 && a1) { return {std::forward(a1)};} }}//namespace triqs::gf #endif