/******************************************************************************* * * TRIQS: a Toolbox for Research in Interacting Quantum Systems * * Copyright (C) 2013 by 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_CURRY_H #define TRIQS_GF_CURRY_H #include "./product.hpp" namespace triqs { namespace gfs { template struct lambda_valued {}; namespace gfs_implementation { /// --------------------------- data access --------------------------------- template struct data_proxy,Opt> : data_proxy_lambda {}; /// --------------------------- Factories --------------------------------- template struct factories, lambda_valued, Opt> {}; /// --------------------------- partial_eval --------------------------------- // partial_eval<0> (g, 1) returns : x -> g(1,x) // partial_eval<1> (g, 3) returns : x -> g(x,3) // a technical trait: from a tuple of mesh, return the mesh (either M if it is a tuple of size 1, or the corresponding cartesian_product). template struct cart_prod_impl; template using cart_prod = typename cart_prod_impl::type; template struct cart_prod_impl> { using type = cartesian_product;}; template struct cart_prod_impl> { typedef M type;}; //using type = M;}; template auto rm_tuple_of_size_one(std::tuple const & t) DECL_AND_RETURN(t); template auto rm_tuple_of_size_one(std::tuple const & t) DECL_AND_RETURN(std::get<0>(t)); // as_tuple leaves a tuple intact and wrap everything else in a tuple... template std::tuple as_tuple(T && x) { return std::tuple {std::forward(x)};} template std::tuple as_tuple(std::tuple && x) { return std::forward(x);} template std::tuple const & as_tuple(std::tuple const & x) { return x;} template std::tuple & as_tuple(std::tuple & x) { return x;} template gf_view< typename cart_prod_impl< triqs::tuple::filter_out_t, pos...>>::type ,Target, Opt,IsConst> partial_eval(gf_impl< cartesian_product, Target,Opt,B,IsConst> const & g, IT index) { // meshes of the returned gf_view : just drop the mesh of the evaluated variables auto meshes_tuple_partial = triqs::tuple::filter_out(g.mesh().components()); // a view of the array of g, with the dimension sizeof...(Ms) auto arr = reinterpret_linear_array(g.mesh(),g.data()); // NO the second () forces a view // now rebuild a tuple of the size sizeof...(Ms), containing the indices and range at the position of evaluated variables. auto arr_args = triqs::tuple::inverse_filter(as_tuple(index), arrays::range()); // from it, we make a slice of the array of g, corresponding to the data of the returned gf_view auto arr2 = triqs::tuple::apply(arr, arr_args); // finally, we build the view on this data. using r_t = gf_view< cart_prod< triqs::tuple::filter_out_t, pos...>> ,Target, Opt,IsConst>; return r_t{ rm_tuple_of_size_one(meshes_tuple_partial), arr2, typename r_t::singularity_non_view_t{}, typename r_t::symmetry_t{} }; } /// --------------------------- curry --------------------------------- // curry<0>(g) returns : x-> y... -> g(x,y...) // curry<1>(g) returns : y-> x,z... -> g(x,y,z...) // to adapt the partial_eval as a polymorphic lambda (replace by a lambda in c++14) template struct curry_polymorphic_lambda { Gview g; template auto operator()(I ... i) const DECL_AND_RETURN(partial_eval(g,std::make_tuple(i...))); friend int get_shape(curry_polymorphic_lambda const&) { return 0;}// no shape here, but needed for compilation //void resize(int){} }; // curry function ... template gf_view, pos...>>, lambda_valued, Target, Opt,IsConst>, pos...>>, Opt, IsConst> curry(gf_view, Target, Opt, IsConst> g) { // pick up the meshed corresponding to the curryed variables auto meshes_tuple = triqs::tuple::filter(g.mesh().components()); // building the view return {rm_tuple_of_size_one(meshes_tuple),curry_polymorphic_lambda, Target,Opt,IsConst>, pos ...>{g}, nothing(), nothing()}; //using m_t = gf_mesh< cart_prod< triqs::tuple::filter_t,pos...>>>; //return {triqs::tuple::apply_construct(meshes_tuple),curry_polymorphic_lambda, Target,Opt>, pos ...>{g}, nothing(), nothing()}; }; template auto curry(gf, Target, Opt> & g) DECL_AND_RETURN(curry(g())); template auto curry(gf, Target, Opt> const & g) DECL_AND_RETURN(curry(g())); } // gf_implementation using gfs_implementation::partial_eval; using gfs_implementation::curry; }} #endif