/******************************************************************************* * * 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 . * ******************************************************************************/ #pragma once #include "./product.hpp" namespace triqs { namespace gfs { template struct lambda_valued {}; template gf_view> make_gf_view_lambda_valued(M m, L l) { return {std::move(m), l, nothing(), nothing(), {}}; } namespace gfs_implementation { /// --------------------------- data access --------------------------------- template struct data_proxy,Opt> : data_proxy_lambda {}; /// --------------------------- Factories --------------------------------- template struct data_factory, lambda_valued, nothing, 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 struct cart_prod_impl> { using type = cartesian_product;}; template struct cart_prod_impl> { using type = M;}; template using cart_prod = typename cart_prod_impl::type; // The implementation (can be overloaded for some types), so put in a struct to have partial specialization template struct partial_eval_impl; // The user function template auto partial_eval(gf_view g, T&&... x) { return partial_eval_impl::template invoke(g(), std::forward(x)...); } template auto partial_eval(gf& g, T&&... x) { return partial_eval_impl::template invoke(g(), std::forward(x)...); } template auto partial_eval(gf const& g, T&&... x) { return partial_eval_impl::template invoke(g(), std::forward(x)...); } /// --------------------------- curry --------------------------------- // curry<0>(g) returns : x-> y... -> g(x,y...) // curry<1>(g) returns : y-> x,z... -> g(x,y,z...) // The implementation (can be overloaded for some types) template auto curry_impl(gf_view, Target, Singularity, Opt, IsConst> g) { // pick up the meshed corresponding to the curryed variables auto meshes_tuple = triqs::tuple::filter(g.mesh().components()); using var_t = cart_prod, pos...>>; auto m = triqs::tuple::apply_construct>(meshes_tuple); auto l = [g](auto&&... x) { return partial_eval(g, x...); }; return make_gf_view_lambda_valued(m, l); }; // The user function template auto curry(gf_view g) { return curry_impl(g()); } template auto curry(gf& g) { return curry_impl(g()); } template auto curry(gf const& g) { return curry_impl(g()); } //--------------------------------------------- // A generic impl. for cartesian product template struct partial_eval_impl, Target, Singularity, Opt, IsConst> { template static auto invoke(gf_view, Target, Singularity, Opt, IsConst> g, T const&... x) { using var_t = cart_prod, pos...>>; // 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()); auto m = triqs::tuple::apply_construct>(meshes_tuple_partial); // 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(std::make_tuple(x...), 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(g.data(), std::tuple_cat(arr_args, std::make_tuple(arrays::ellipsis{}))); auto singv = partial_eval(g.singularity(), x...); using r_sing_t = typename decltype(singv)::regular_type; // finally, we build the view on this data. using r_t = gf_view; return r_t{m, arr2, singv, {}, {}}; } }; } // gf_implementation using gfs_implementation::partial_eval; using gfs_implementation::curry; }}