/*******************************************************************************
*
* 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"
#ifndef TRIQS_COMPILER_IS_C11_COMPLIANT
#error "This header requires a fully C++11 compliant compiler"
#endif
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> {};
// detail
template struct cartesian_product_add_front;
template struct cartesian_product_add_front>{ typedef cartesian_product type; };
// -------------------------------------------------
// Partial evaluation of the gf
// -------------------------------------------------
//
// Given a cartesian_product of meshes (CP), and a compile time list of int (I)
// - metacompute the list of Ms without position those at position 0,2 (type)
// - provide 2 runtimes functions :
// - sl : given empty tuple () and a tuple (it) of indices
// return the tuple of indices and range, where range are at the position defined by I,
// and the indices in other places, in order.
// - m : returns from a CP object the corresponding tuple of meshes of the remaining meshes
// after partial eval (of the type computed by "type").
// - auxiliary data :
// pos : position in the CP tuple (CP::size-1 ->0)
// ip : position in the tuple of indices (for sl)
// MP : accumulation of the final type metacomputed.
//
template struct pv_impl;
template struct pv_ : pv_impl,I...>{};
template struct pv_impl<-1, ip, CP, MP, I... > {
// the final type is a cartesian_product<...> if there is more than one mess
// and otherwise the only mesh remaining... (avoiding cartesian_product e.g. which makes little sense).
typedef typename std::conditional::type, MP>::type type;
template static T sl(T t, IT const & it) {return t;}
template static T m (T t, MT const & mt) {return t;}
};
template struct pv_impl {
typedef pv_impl B;
typedef typename B::type type;
template static auto sl (T t, IT const & it) DECL_AND_RETURN( B::sl(triqs::tuple::push_front(t,arrays::range()),it));
template static auto m (T t, MT const & mt) DECL_AND_RETURN( B::m(t,mt));
};
template struct pv_impl {
typedef typename cartesian_product_add_front::type, MP>::type MP2;
typedef pv_impl B;
typedef typename B::type type;
template static auto sl (T t, IT const & it) DECL_AND_RETURN( B::sl(triqs::tuple::push_front(t,std::get(it)),it));
template static auto m (T t, MT const & mt) DECL_AND_RETURN( B::m (triqs::tuple::push_front(t,std::get(mt)),mt));
};
// partial_eval<0> (g, 1) : returns : x -> g(1,x)
// partial_eval<1> (g, 3) : returns : x -> g(x,3)
//
template
gf_view,pos...>::type ,Target, Opt>
partial_eval(gf_impl< cartesian_product, Target,Opt,B> const & g, IT index) {
auto arr = reinterpret_linear_array(g.mesh(),g.data());
typedef pv_,pos...> pv_t;
typedef gf_view< typename pv_t::type,Target, Opt> r_t;
auto comp = pv_t::m(std::make_tuple(),g.mesh().components());
auto arr_args = pv_t::sl(std::make_tuple(),index);
// generalize this get<0> ---> flatten the tuple (construct from a tuple of args...)
return r_t{ std::get<0>(comp), triqs::tuple::apply(arr, arr_args), typename r_t::singularity_non_view_t{}, typename r_t::symmetry_t{} };
}
// 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...)));
};
// curry<0>(g) returns : x-> y... -> g(x,y...)
// curry<1>(g) returns : x-> y,z... -> g(y,x,z...)
// and so on
template
gf_view< typename pv_,pos...>::type,
lambda_valued, Target,Opt>,pos...>>,
Opt>
curry (gf_impl, Target,Opt,B> const & g) {
auto comp = pv_,pos...>::m(std::make_tuple(),g.mesh().components());
typedef mesh< typename pv_,pos...>::type,Opt> m_t;
return {triqs::tuple::apply_construct(comp),curry_polymorphic_lambda, Target,Opt>, pos ...>{g}, nothing(), nothing()};
};
} // gf_implementation
using gfs_implementation::partial_eval;
using gfs_implementation::curry;
/// ----- first implementation
/*
// slicing on first arg
template
gf_view slice_mesh0 (gf_view< cartesian_product, scalar_valued,Opt> g, size_t index) {
auto arr = reinterpret_linear_array(g.mesh(),g.data());
typedef gf_view r_t;
return { std::get<1>(g.mesh().components()), arr(index,arrays::range()), typename r_t::singularity_non_view_t{}, typename r_t::symmetry_t{} };
}
// slicing on first arg
template
gf_view slice_mesh1 (gf_view< cartesian_product, scalar_valued,Opt> g, size_t index) {
auto arr = reinterpret_linear_array(g.mesh(),g.data());
typedef gf_view r_t;
return { std::get<0>(g.mesh().components()), arr(arrays::range(), index), typename r_t::singularity_non_view_t{}, typename r_t::symmetry_t{} };
}
template struct curry_lambda0 {
Gview g;
auto operator()(size_t i) const DECL_AND_RETURN( slice_mesh0(g,i));
};
template
gf_view, scalar_valued,Opt>>>, Opt>
curry0 (gf_impl, scalar_valued,Opt,B> const & g) {
return {std::get<0>(g.mesh().components()),curry_lambda0, scalar_valued,Opt>>{g}, nothing(), nothing()};
};
*/
}}
#endif