3
0
mirror of https://github.com/triqs/dft_tools synced 2025-01-12 22:18:23 +01:00

Work on gf

- clean curry.
- start testing.
This commit is contained in:
Olivier Parcollet 2013-09-06 15:53:28 +02:00
parent 5d0049de7a
commit 9790fe8bd0
9 changed files with 320 additions and 112 deletions

View File

@ -0,0 +1,45 @@
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
#include <triqs/gfs.hpp>
#include <triqs/gfs/product.hpp>
#include <triqs/gfs/curry.hpp>
#include <triqs/gfs/local/fourier_real.hpp>
#include <triqs/gfs/local/fourier_matsubara.hpp>
#include <triqs/arrays.hpp>
using namespace triqs::gfs;
int main() {
try {
double beta =1.;
double tmin=0.;
double tmax=10;
double wmin=0.;
double wmax=1.0;
int n_re_freq=100;
int n_im_freq=100;
int Nt=100;
triqs::clef::placeholder<0> w_;
triqs::clef::placeholder<1> wn_;
triqs::clef::placeholder<2> tau_;
auto G_w_wn = make_gf<cartesian_product<refreq,refreq>, scalar_valued>( gf_mesh<refreq>(wmin, wmax, n_re_freq), gf_mesh<refreq>(wmin, wmax, n_re_freq));
auto G_w_tau = make_gf<cartesian_product<refreq,retime>, scalar_valued>( gf_mesh<refreq>(wmin, wmax, n_re_freq), gf_mesh<retime>(-tmax, tmax, Nt));
G_w_wn(w_,wn_)<<1/(wn_-1)/( pow(w_,3) );
G_w_tau(w_,tau_)<< exp( -2*tau_ ) / (w_*w_ + 1 );
auto G_w_wn_curry0 = curry<0>(G_w_wn);
auto G_w_tau_curry0 = curry<0>(G_w_tau);
for (auto const & w : G_w_wn_curry0.mesh()) G_w_wn_curry0[w] = lazy_fourier(G_w_tau_curry0[w]);
G_w_wn_curry0[w_] << lazy_fourier(G_w_tau_curry0[w_]);
curry<0>(G_w_wn) [w_] << lazy_fourier(curry<0>(G_w_tau)[w_]);
}
catch(std::exception const & e ) { std::cout << "error "<< e.what()<< std::endl;}
}

View File

@ -48,6 +48,7 @@ try {
auto G_w_wn2_view = G_w_wn2();
auto G_w_wn_sl0_a = partial_eval<0>(G_w_wn2(), std::make_tuple(8));
static_assert(std::is_same<typename std::remove_reference<decltype(G_w_wn_sl0_a.mesh())>::type, const gf_mesh<imfreq>>::value, "oops");
//auto G_w_wn_curry0_a = curry0(G_w_wn2);
//auto G_w_wn_sl0_a = slice_mesh0(G_w_wn2(), 8);
@ -84,6 +85,8 @@ try {
std::cout << "curry no"<< G_w_wn.on_mesh(8,3) << std::endl ;
auto G_w_wn_curry0 = curry<0>(G_w_wn2);
static_assert(std::is_same<typename std::remove_reference<decltype(G_w_wn_curry0[0].mesh())>::type, const gf_mesh<imfreq>>::value, "oops");
static_assert(std::is_same<typename std::remove_reference<decltype(G_w_wn_curry0.mesh())>::type, const gf_mesh<refreq>>::value, "oops");
auto G_w_wn_curry1 = curry<1>(G_w_wn2);
auto G_w_wn2_view2 = G_w_wn2();
@ -91,7 +94,6 @@ try {
std::cout << " curry "<<G_w_wn_curry1[3][8] << std::endl;
std::cout << "G_w_wn_sl0_a [3]"<<G_w_wn_sl0_a[3] << std::endl ;
// test hdf5
H5::H5File file("gf_re_im_freq_time.h5", H5F_ACC_TRUNC );
h5_write(file, "g_t_tau", G_t_tau);

View File

@ -46,6 +46,9 @@ template<typename T1, typename T2>
std::string my_print_str(int x, int y) { std::stringstream fs; fs << "the string is "<< x<< " " << y; return fs.str();}
namespace triqs { namespace tuple {
}}
int main(int argc, char **argv) {
@ -99,11 +102,64 @@ int main(int argc, char **argv) {
}
{ // to mini_vector
auto t = std::make_tuple(1,2,3.4);
auto m = triqs::utility::tuple_to_mini_vector<double>(t);
std::cout << m<< std::endl ;
}
{ // filter
std::cout << " ----- filter ----"<< std::endl ;
auto t= std::make_tuple(0,1,2,3,4,"=5");
std::cout << "filter "<< t << triqs::tuple::filter<0,2,3>(t)<< std::endl;
std::cout << "filter "<< t << triqs::tuple::filter<1,3,5>(t)<< std::endl;
std::cout << "filter out "<< t << triqs::tuple::filter_out<0,2,3>(t)<< std::endl;
std::cout << "filter out "<< t << triqs::tuple::filter_out<1,3,5>(t)<< std::endl;
auto t2= std::make_tuple(0,1);
std::cout << "filter out "<< t2 << triqs::tuple::filter_out<0>(t2)<< std::endl;
typedef typename triqs::tuple::filter_t_tr< decltype(t), 0,2,3>::type TY;
static_assert(std::is_same<TY, decltype(triqs::tuple::filter<0,2,3>(t))>::value, "EEE");
}
{ // filter
std::cout << " ----- inverse filter ----"<< std::endl ;
auto t= std::make_tuple(1,4,5);
auto s = std::string{"--"};
{
auto r = triqs::tuple::inverse_filter<6,0,2,3>(t, s);
std::cout << "inverse filter "<< t << r<< triqs::tuple::filter<0,2,3>(r)<<std::endl;
}
{ auto r = triqs::tuple::inverse_filter<6,0,2,5>(t, s);
std::cout << "inverse filter "<< t << r<< triqs::tuple::filter<0,2,5>(r)<<std::endl;
}
{ auto r = triqs::tuple::inverse_filter<8,0,2,5>(t, s);
std::cout << "inverse filter "<< t << r<< triqs::tuple::filter<0,2,5>(r)<<std::endl;
}
{
auto r = triqs::tuple::inverse_filter_out<0,2,3>(t, s);
std::cout << "inverse filter out "<< t << r<< triqs::tuple::filter_out<0,2,3>(r)<<std::endl;
}
{ auto r = triqs::tuple::inverse_filter_out<0,2,3,5>(t, s);
std::cout << "inverse filter out "<< t << r<< triqs::tuple::filter_out<0,2,3,5>(r)<<std::endl;
}
{ auto r = triqs::tuple::inverse_filter_out<0,2,3,6>(t, s);
std::cout << "inverse filter out "<< t << r<< triqs::tuple::filter_out<0,2,3,6>(r)<<std::endl;
}
}
{ // replace
std::cout << " ----- filter ----"<< std::endl ;
auto t= std::make_tuple(0,1,2,3,4,"=5");
auto s = std::string{"--"};
std::cout << "replace 0,2,3"<< t << triqs::tuple::replace<0,2,3>(t,s)<< std::endl;
std::cout << "replace 1,3,5"<< t << triqs::tuple::replace<1,3,5>(t,s)<< std::endl;
}
}

View File

@ -21,17 +21,15 @@
#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<typename F> struct lambda_valued {};
namespace gfs_implementation {
/// --------------------------- data access ---------------------------------
template<typename Opt, typename F, typename M> struct data_proxy<M,lambda_valued<F>,Opt> : data_proxy_lambda<F> {};
@ -41,124 +39,63 @@ namespace triqs { namespace gfs {
template<typename F, typename Opt, typename ... Ms>
struct factories<cartesian_product<Ms...>, lambda_valued<F>, Opt> {};
// detail
template<typename M0, typename CP> struct cartesian_product_add_front;
template<typename M0, typename ... Ms> struct cartesian_product_add_front<M0,cartesian_product<Ms...>>{ typedef cartesian_product<M0,Ms...> type; };
/// --------------------------- partial_eval ---------------------------------
// partial_eval<0> (g, 1) returns : x -> g(1,x)
// partial_eval<1> (g, 3) returns : x -> g(x,3)
// -------------------------------------------------
// 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<int pos, int ip, typename CP, typename MP, int ... I> struct pv_impl;
template<typename CP, int ... I> struct pv_ : pv_impl<CP::size-1,0,CP,cartesian_product<>,I...>{};
template<typename CP, int ip, typename MP, int ... I> 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<imfreq> e.g. which makes little sense).
typedef typename std::conditional<MP::size==1, typename std::tuple_element<0,typename MP::type>::type, MP>::type type;
template<typename T, typename IT> static T sl(T t, IT const & it) {return t;}
template<typename T, typename MT> static T m (T t, MT const & mt) {return t;}
};
// 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<M..>).
template<typename ... Ms> struct cart_prod_impl;
template<typename ... Ms> using cart_prod = typename cart_prod_impl<Ms...>::type;
template<typename ... Ms> struct cart_prod_impl<std::tuple<Ms...>> { using type = cartesian_product<Ms...>;};
template<typename M> struct cart_prod_impl<std::tuple<M>> { typedef M type;}; //using type = M;};
template<int pos, int ip, typename CP, typename MP, int ... I> struct pv_impl {
typedef pv_impl<pos-1, ip, CP,MP, I...> B;
typedef typename B::type type;
template<typename T, typename IT> static auto sl (T t, IT const & it) DECL_AND_RETURN( B::sl(triqs::tuple::push_front(t,arrays::range()),it));
template<typename T, typename MT> static auto m (T t, MT const & mt) DECL_AND_RETURN( B::m(t,mt));
};
template<typename M0, typename M1, typename ...M> auto rm_tuple_of_size_one(std::tuple<M0,M1,M...> const & t) DECL_AND_RETURN(t);
template<typename M> auto rm_tuple_of_size_one(std::tuple<M> const & t) DECL_AND_RETURN(std::get<0>(t));
template<int pos, int ip, typename CP, typename MP, int ... I> struct pv_impl<pos, ip, CP, MP, pos ,I...> {
typedef typename cartesian_product_add_front<typename std::tuple_element<pos,typename CP::type>::type, MP>::type MP2;
typedef pv_impl<pos-1,ip+1, CP,MP2,I...> B;
typedef typename B::type type;
template<typename T, typename IT> static auto sl (T t, IT const & it) DECL_AND_RETURN( B::sl(triqs::tuple::push_front(t,std::get<ip >(it)),it));
template<typename T, typename MT> static auto m (T t, MT const & mt) DECL_AND_RETURN( B::m (triqs::tuple::push_front(t,std::get<pos>(mt)),mt));
};
// partial_eval<0> (g, 1) : returns : x -> g(1,x)
// partial_eval<1> (g, 3) : returns : x -> g(x,3)
//
template<int ... pos, typename Opt, typename Target, bool B, typename IT, typename ... Ms>
gf_view<typename pv_<cartesian_product<Ms...>,pos...>::type ,Target, Opt>
gf_view< typename cart_prod_impl< triqs::tuple::filter_out_t<std::tuple<Ms...>, pos...>>::type ,Target, Opt>
partial_eval(gf_impl< cartesian_product<Ms...>, Target,Opt,B> 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<pos...>(g.mesh().components());
// a view of the array of g, with the dimension sizeof...(Ms)
auto arr = reinterpret_linear_array(g.mesh(),g.data());
typedef pv_<cartesian_product<Ms...>,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{} };
// 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<sizeof...(Ms),pos...>(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<std::tuple<Ms...>, pos...>> ,Target, Opt>;
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<typename Gview, int ... pos> struct curry_polymorphic_lambda {
Gview g;
template<typename ...I>
auto operator()(I ... i) const DECL_AND_RETURN( partial_eval<pos...>(g,std::make_tuple(i...)));
template<typename ...I> auto operator()(I ... i) const DECL_AND_RETURN(partial_eval<pos...>(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
// curry function ...
template<int ... pos, typename Target, typename Opt, bool B, typename ... Ms>
gf_view< typename pv_<cartesian_product<Ms...>,pos...>::type,
gf_view<cart_prod< triqs::tuple::filter_t<std::tuple<Ms...>,pos...> >,
lambda_valued<curry_polymorphic_lambda<gf_view<cartesian_product<Ms...>, Target,Opt>,pos...>>,
Opt>
curry (gf_impl<cartesian_product<Ms...>, Target,Opt,B> const & g) {
auto comp = pv_<cartesian_product<Ms...>,pos...>::m(std::make_tuple(),g.mesh().components());
typedef gf_mesh< typename pv_<cartesian_product<Ms...>,pos...>::type,Opt> m_t;
return {triqs::tuple::apply_construct<m_t>(comp),curry_polymorphic_lambda<gf_view<cartesian_product<Ms...>, Target,Opt>, pos ...>{g}, nothing(), nothing()};
// pick up the meshed corresponding to the curryed variables
auto meshes_tuple = triqs::tuple::filter<pos...>(g.mesh().components());
// building the view
return {rm_tuple_of_size_one(meshes_tuple),curry_polymorphic_lambda<gf_view<cartesian_product<Ms...>, Target,Opt>, pos ...>{g}, nothing(), nothing()};
//using m_t = gf_mesh< cart_prod< triqs::tuple::filter_t<std::tuple<Ms...>,pos...>>>;
//return {triqs::tuple::apply_construct<m_t>(meshes_tuple),curry_polymorphic_lambda<gf_view<cartesian_product<Ms...>, Target,Opt>, pos ...>{g}, nothing(), nothing()};
};
} // gf_implementation
using gfs_implementation::partial_eval;
using gfs_implementation::curry;
/// ----- first implementation
/*
// slicing on first arg
template<typename Opt, typename M0, typename M1>
gf_view<M1,scalar_valued, Opt> slice_mesh0 (gf_view< cartesian_product<M0,M1>, scalar_valued,Opt> g, size_t index) {
auto arr = reinterpret_linear_array(g.mesh(),g.data());
typedef gf_view<M1,scalar_valued, Opt> 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<typename Opt, typename M0, typename M1>
gf_view<M0,scalar_valued, Opt> slice_mesh1 (gf_view< cartesian_product<M0,M1>, scalar_valued,Opt> g, size_t index) {
auto arr = reinterpret_linear_array(g.mesh(),g.data());
typedef gf_view<M0,scalar_valued, Opt> 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<typename Gview> struct curry_lambda0 {
Gview g;
auto operator()(size_t i) const DECL_AND_RETURN( slice_mesh0(g,i));
};
template<typename Opt, bool B, typename M0, typename M1>
gf_view<M0,lambda_valued<curry_lambda0<gf_view<cartesian_product<M0,M1>, scalar_valued,Opt>>>, Opt>
curry0 (gf_impl<cartesian_product<M0,M1>, scalar_valued,Opt,B> const & g) {
return {std::get<0>(g.mesh().components()),curry_lambda0<gf_view<cartesian_product<M0,M1>, scalar_valued,Opt>>{g}, nothing(), nothing()};
};
*/
}}
#endif

View File

@ -340,9 +340,9 @@ namespace triqs { namespace gfs {
template<bool V> gf_view(gf_impl<Variable,Target,Opt,V> const & g): B(g){}
template<typename D, typename T>
template<typename D>
gf_view (typename B::mesh_t const & m,
D const & dat,T const & t,typename B::symmetry_t const & s,
D const & dat,typename B::singularity_view_t const & t,typename B::symmetry_t const & s,
typename B::evaluator_t const &e = typename B::evaluator_t () ) :
B(m,factory<typename B::data_t>(dat),t,s,e) {}
@ -359,7 +359,7 @@ namespace triqs { namespace gfs {
template<typename RHS> gf_view & operator = (RHS const & rhs) { triqs_gf_view_assign_delegation(*this,rhs); return *this;}
// Interaction with the CLEF library : auto assignment of the gf (gf(om_) << expression fills the functions by evaluation of expression)
template<typename RHS> friend void triqs_clef_auto_assign (gf_view & g, RHS rhs) {
template<typename RHS> friend void triqs_clef_auto_assign (gf_view g, RHS rhs) {
// access to the data . Beware, we view it as a *matrix* NOT an array... (crucial for assignment to scalars !)
g.triqs_clef_auto_assign_impl(rhs, typename std::is_base_of<tag::composite,typename B::mesh_t>::type());
assign_from_expression(g.singularity(),rhs);
@ -367,6 +367,9 @@ namespace triqs { namespace gfs {
// it uses the fact that tail_non_view_t can be casted into freq_infty
}
// enable the writing g[om_] << .... also
template<typename RHS> friend void triqs_clef_auto_assign_subscript (gf_view g, RHS rhs) { triqs_clef_auto_assign(g,rhs);}
private:
template<typename RHS> void triqs_clef_auto_assign_impl (RHS const & rhs, std::integral_constant<bool,false>) {
for (auto const & w: this->mesh()) (*this)[w] = rhs(w);
@ -381,14 +384,14 @@ namespace triqs { namespace gfs {
// delegate = so that I can overload it for specific RHS...
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) {
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());
g.singularity() = rhs.singularity();
}
template<typename Variable, typename Target, typename Opt, typename T>
ENABLE_IF(arrays::is_scalar<T>) triqs_gf_view_assign_delegation( gf_view<Variable,Target,Opt> & g, T const & x) {
ENABLE_IF(arrays::is_scalar<T>) triqs_gf_view_assign_delegation( gf_view<Variable,Target,Opt> g, T const & x) {
gf_view<Variable,Target,Opt>::data_proxy_t::assign_to_scalar(g.data(), x);
g.singularity() = x;
}

View File

@ -74,8 +74,11 @@ namespace triqs { namespace gfs {
void triqs_gf_view_assign_delegation( gf_view<imfreq,matrix_valued> g, gf_keeper<tags::fourier,imtime,matrix_valued> const & L);
void triqs_gf_view_assign_delegation( gf_view<imtime,scalar_valued> g, gf_keeper<tags::fourier,imfreq,scalar_valued> const & L);
void triqs_gf_view_assign_delegation( gf_view<imtime,matrix_valued> g, gf_keeper<tags::fourier,imfreq,matrix_valued> const & L);
}}
namespace triqs { namespace clef {
TRIQS_CLEF_MAKE_FNT_LAZY (lazy_fourier);
TRIQS_CLEF_MAKE_FNT_LAZY (lazy_inverse_fourier);
}}
#endif

View File

@ -80,8 +80,10 @@ namespace triqs { namespace gfs {
inline gf_keeper<tags::fourier,retime,matrix_valued> lazy_fourier (gf_view<retime,matrix_valued> const & g) { return g;}
inline gf_keeper<tags::fourier,refreq,matrix_valued> lazy_inverse_fourier (gf_view<refreq,matrix_valued> const & g) { return g;}
void triqs_gf_view_assign_delegation( gf_view<refreq> g, gf_keeper<tags::fourier,retime> const & L);
void triqs_gf_view_assign_delegation( gf_view<retime> g, gf_keeper<tags::fourier,refreq> const & L);
void triqs_gf_view_assign_delegation( gf_view<refreq,scalar_valued> g, gf_keeper<tags::fourier,retime,scalar_valued> const & L);
void triqs_gf_view_assign_delegation( gf_view<refreq,matrix_valued> g, gf_keeper<tags::fourier,retime,matrix_valued> const & L);
void triqs_gf_view_assign_delegation( gf_view<retime,scalar_valued> g, gf_keeper<tags::fourier,refreq,scalar_valued> const & L);
void triqs_gf_view_assign_delegation( gf_view<retime,matrix_valued> g, gf_keeper<tags::fourier,refreq,matrix_valued> const & L);
}}
#endif

View File

@ -31,6 +31,9 @@ namespace triqs { namespace gfs {
static constexpr size_t size = sizeof...(Ms);
};
// use alias
template<typename ... Ms> struct cartesian_product <std::tuple<Ms...>> : cartesian_product<Ms...>{};
// the mesh is simply a cartesian product
template<typename Opt, typename ... Ms> struct gf_mesh<cartesian_product<Ms...>,Opt> : mesh_product< gf_mesh<Ms,Opt> ... > {
typedef mesh_product< gf_mesh<Ms,Opt> ... > B;

View File

@ -32,7 +32,7 @@ namespace triqs { namespace tuple {
* push_back (t,x) -> returns new tuple with x append at the end
*/
template<typename T, typename X>
auto push_back(T const &t, X const &x) DECL_AND_RETURN ( std::tuple_cat(t,std::make_tuple(x)));
auto push_back(T && t, X &&x) DECL_AND_RETURN ( std::tuple_cat(std::forward<T>(t),std::make_tuple(std::forward<X>(x))));
/**
* t : a tuple
@ -40,7 +40,7 @@ namespace triqs { namespace tuple {
* push_front (t,x) -> returns new tuple with x append at the first position
*/
template<typename T, typename X>
auto push_front(T const &t, X const &x) DECL_AND_RETURN ( std::tuple_cat(std::make_tuple(x),t));
auto push_front(T && t, X &&x) DECL_AND_RETURN ( std::tuple_cat(std::make_tuple(std::forward<X>(x)),std::forward<T>(t)));
/**
* apply(f, t)
@ -264,6 +264,158 @@ namespace triqs { namespace tuple {
template<typename F, typename T1, typename T2, typename R>
auto fold_on_zip (F && f,T1 const & t1, T2 const & t2, R && r) DECL_AND_RETURN( fold_on_zip_impl<std::tuple_size<T1>::value-1,T1,T2>()(std::forward<F>(f),t1,t2,std::forward<R>(r)));
/**
* filter<int ... I>(t) :
* Given a tuple t, and integers, returns the tuple where the elements at initial position I are dropped.
*/
// pos = position in the tuple, c : counter tuplesize-1 ->0, I : position to filter
template<int pos, int c, int ... I> struct filter_impl;
// default case where pos != the first I : increase pos
template<int pos, int c, int ... I> struct filter_impl : filter_impl<pos+1, c-1, I...> {};
// when pos == first I
template<int pos, int c, int ... I> struct filter_impl<pos, c, pos, I...> {
template<typename TupleIn, typename TupleOut> auto operator() (TupleIn const & t, TupleOut && out) const
DECL_AND_RETURN( filter_impl<pos+1,c-1, I...>() ( t, push_back(std::forward<TupleOut>(out),std::get<pos>(t))));
};
template<int pos, int ... I> struct filter_impl <pos,-1, I...> {
template<typename TupleIn, typename TupleOut> TupleOut operator() (TupleIn const & t, TupleOut && out) const {return out;}
};
template<int ...I, typename Tu>
auto filter(Tu const & tu) DECL_AND_RETURN ( filter_impl<0,std::tuple_size<Tu>::value-1, I...>()(tu, std::make_tuple()));
template<typename Tu,int ...I> struct filter_t_tr : std::result_of< filter_impl<0,std::tuple_size<Tu>::value-1, I...>( Tu, std::tuple<>)>{};
#ifdef TRIQS_COMPILER_IS_C11_COMPLIANT
template<typename Tu,int ...I> using filter_t = typename filter_t_tr<Tu,I...>::type;
#endif
/**
* filter_out<int ... I>(t) :
* Given a tuple t, and integers, returns the tuple where the elements at initial position I are dropped.
*/
// pos = position in the tuple, c : counter tuplesize-1 ->0, I : position to filter
template<int pos, int c, int ... I> struct filter_out_impl;
// default case where pos != the first I : increase pos
template<int pos, int c, int ... I> struct filter_out_impl<pos, c, pos, I...> : filter_out_impl<pos+1, c-1, I...> {};
// when pos == first I
template<int pos, int c, int ... I> struct filter_out_impl {
template<typename TupleIn, typename TupleOut> auto operator() (TupleIn const & t, TupleOut && out) const
DECL_AND_RETURN( filter_out_impl<pos+1,c-1, I...> ()( t, push_back(std::forward<TupleOut>(out),std::get<pos>(t))));
};
template<int pos, int ... I> struct filter_out_impl <pos,-1, I...> {
template<typename TupleIn, typename TupleOut> TupleOut operator() (TupleIn const & t, TupleOut && out) const {return out;}
};
template<int ...I, typename Tu>
auto filter_out(Tu const & tu) DECL_AND_RETURN ( filter_out_impl<0,std::tuple_size<Tu>::value-1, I...>()(tu, std::make_tuple()));
template<typename Tu,int ...I> struct filter_out_t_tr : std::result_of< filter_out_impl<0,std::tuple_size<Tu>::value-1, I...>( Tu, std::tuple<>)>{};
#ifdef TRIQS_COMPILER_IS_C11_COMPLIANT
template<typename Tu,int ...I> using filter_out_t = typename filter_out_t_tr<Tu,I...>::type;
#endif
/**
* inverse_filter<int L, int ... I>(t,x)
* Given a tuple t, and integers, returns the tuple R of size L such that filter<I...>(R) == t
* and the missing position are filled with object x.
* Precondition (static_assert : sizeof...(I)==size of t)
* and max (I) < L
*/
// pos = position in the tuple, c : counter tuplesize-1 ->0, I : position to filter
template<int pos, int pos_in, int c, int ... I> struct inverse_filter_impl;
// default case where pos != the first I
template<int pos, int pos_in, int c, int ... I> struct inverse_filter_impl<pos, pos_in, c, pos, I...> {
template<typename TupleIn, typename TupleOut, typename X> auto operator() (TupleIn const & t, TupleOut && out, X const & x) const
DECL_AND_RETURN( inverse_filter_impl<pos+1,pos_in+1,c-1, I...> ()( t, push_back(std::forward<TupleOut>(out),std::get<pos_in>(t)),x));
};
// when pos == first I
template<int pos, int pos_in, int c, int ... I> struct inverse_filter_impl {
template<typename TupleIn, typename TupleOut, typename X> auto operator() (TupleIn const & t, TupleOut && out, X const & x) const
DECL_AND_RETURN( inverse_filter_impl<pos+1,pos_in,c-1, I...> ()( t, push_back(std::forward<TupleOut>(out),x), x));
};
template<int pos, int pos_in, int ... I> struct inverse_filter_impl <pos,pos_in, -1, I...> {
template<typename TupleIn, typename TupleOut, typename X> TupleOut operator() (TupleIn const &, TupleOut && out, X const &) const {return out;}
};
// put out for clearer error message
template< typename Tu, typename X, int L, int ...I> struct inverse_filter_r_type {
static_assert(sizeof...(I) == std::tuple_size<Tu>::value, "inverse filter : the # of int must be equal to the tuple size !!");
typedef inverse_filter_impl<0,0,L-1, I...> type;
};
template<int L, int ...I, typename Tu, typename X>
auto inverse_filter(Tu const & tu, X const &x) DECL_AND_RETURN ( typename inverse_filter_r_type<Tu, X, L, I...>::type ()(tu, std::make_tuple(),x));
/**
* inverse_filter_out<int ... I>(t,x)
* Given a tuple t, and integers, returns the tuple R such that filter_out<I...>(R) == t
* and the missing position are filled with object x.
*/
// pos = position in the tuple, c : counter tuplesize-1 ->0, I : position to filter
template<int pos, int pos_in, int c, int ... I> struct inverse_filter_out_impl;
// default case where pos != the first I
template<int pos, int pos_in, int c, int ... I> struct inverse_filter_out_impl {
template<typename TupleIn, typename TupleOut, typename X> auto operator() (TupleIn const & t, TupleOut && out, X const & x) const
DECL_AND_RETURN( inverse_filter_out_impl<pos+1,pos_in+1,c-1, I...> ()( t, push_back(std::forward<TupleOut>(out),std::get<pos_in>(t)),x));
};
// when pos == first I
template<int pos, int pos_in, int c, int ... I> struct inverse_filter_out_impl <pos, pos_in, c, pos, I...> {
template<typename TupleIn, typename TupleOut, typename X> auto operator() (TupleIn const & t, TupleOut && out, X const & x) const
DECL_AND_RETURN( inverse_filter_out_impl<pos+1,pos_in,c-1, I...> ()( t, push_back(std::forward<TupleOut>(out),x), x));
};
template<int pos, int pos_in, int ... I> struct inverse_filter_out_impl <pos,pos_in, -1, I...> {
template<typename TupleIn, typename TupleOut, typename X> TupleOut operator() (TupleIn const &, TupleOut && out, X const &) const {return out;}
};
template<int ...I, typename Tu, typename X>
auto inverse_filter_out(Tu const & tu, X const &x) DECL_AND_RETURN ( inverse_filter_out_impl<0,0,std::tuple_size<Tu>::value+sizeof...(I)-1, I...>()(tu, std::make_tuple(),x));
/**
* replace<int ... I>(t,r)
* Given a tuple t, and integers, returns the tuple where the elements at initial position I are replaced by r
*/
// pos = position in the tuple, c : counter tuplesize-1 ->0, I : position to filter
template<int pos, int c, int ... I> struct replace_impl;
// default case where pos != the first I : increase pos
template<int pos, int c, int ... I> struct replace_impl<pos, c, pos, I...> {
template<typename TupleIn, typename TupleOut, typename R> auto operator() (TupleIn const & t, TupleOut && out, R const & r) const
DECL_AND_RETURN( replace_impl<pos+1,c-1, I...> ()( t, push_back(std::forward<TupleOut>(out),r),r));
};
// when pos == first I
template<int pos, int c, int ... I> struct replace_impl {
template<typename TupleIn, typename TupleOut, typename R> auto operator() (TupleIn const & t, TupleOut && out, R const & r) const
DECL_AND_RETURN( replace_impl<pos+1,c-1, I...> ()( t, push_back(std::forward<TupleOut>(out),std::get<pos>(t)), r));
};
template<int pos, int ... I> struct replace_impl <pos,-1, I...> {
template<typename TupleIn, typename TupleOut, typename R> TupleOut operator() (TupleIn const & t, TupleOut && out, R const & r) const {return out;}
};
template<int ...I, typename Tu, typename R>
auto replace(Tu const & tu, R const &r) DECL_AND_RETURN ( replace_impl<0,std::tuple_size<Tu>::value-1, I...>()(tu, std::make_tuple(),r));
/*
* print a tuple
*/
@ -285,5 +437,10 @@ namespace std {
}
}
#endif