/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2012-2014 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
#include "./c14.hpp"
#include
#include
// adding to the std lib the reversed lazy tuple...
// overloading & specializing only the functions needed here.
namespace std {
// Reverse
template struct _triqs_reversed_tuple {TU _x;};
template _triqs_reversed_tuple> reverse(std::tuple && x) { return {move(x)};}
template _triqs_reversed_tuple&> reverse(std::tuple & x) { return {x};}
template _triqs_reversed_tupleconst &> reverse(std::tuple const & x) { return {x};}
template AUTO_DECL get(_triqs_reversed_tuple const & t)
RETURN(std::get>::value-1-pos>(t._x));
template AUTO_DECL get(_triqs_reversed_tuple & t)
RETURN(std::get>::value-1-pos>(t._x));
template AUTO_DECL get(_triqs_reversed_tuple && t)
RETURN(std::get>::value-1-pos>(move(t)._x));
template class tuple_size<_triqs_reversed_tuple> : public tuple_size> {};
// Zipped tuple:
template struct _triqs_zipped_tuple {
std::tuple _tu;
template _triqs_zipped_tuple(U &&... u) : _tu(std::forward(u)...) {}
template auto _get(std::c14::index_sequence) RETURN(std::tie(std::get(std::get(_tu))...));
template auto _get(std::c14::index_sequence) const RETURN(std::tie(std::get(std::get(_tu))...));
};
template
AUTO_DECL get(_triqs_zipped_tuple const &tu) RETURN(tu.template _get(std14::make_index_sequence()));
template struct tuple_size<_triqs_zipped_tuple> : public std::tuple_size> {};
template _triqs_zipped_tuple zip(T &&... x) {
return {std::forward(x)...};
}
}
namespace triqs { namespace tuple {
/// Repeat an element
template struct make_tuple_repeat_impl;
template struct make_tuple_repeat_impl {
static std::tuple invoke(T&&x) { return {x};}
};
template struct make_tuple_repeat_impl {
static std::tuple invoke(T&&x) { return {x,x};}
};
template struct make_tuple_repeat_impl {
static std::tuple invoke(T&&x) { return {x,x,x};}
};
template struct make_tuple_repeat_impl {
static std::tuple invoke(T &&x) { return {x, x, x, x}; }
};
template auto make_tuple_repeat(T &&x) { return make_tuple_repeat_impl::invoke(std::forward(x)); }
/// _get_seq() : from a tuple T, return the index sequence of the tuple length
template std14::make_index_sequence>::value> _get_seq() {
return {};
}
/// _get_seq_len : constexpr : return the length of the tuple
template constexpr int _get_seq_len() { return std::tuple_size>::value; }
/// basic tools
template struct _int {};
template struct all_indices : _int... {};
// --- impl complement -----
template struct complement_sequence_impl {
static complement_sequence_impl get(_int) {}
static complement_sequence_impl get(...) {}
using type = typename decltype(get(hole_seq()))::type;
};
template struct complement_sequence_impl<-1, hole_seq, Is...> {
using type = std14::index_sequence;
};
/// An index sequence of elements of [0,N-1] which are NOT Is
template using complement_sequence = typename complement_sequence_impl>::type;
/**
* apply(f, t)
* f : a callable object
* t a tuple
* Returns : f(t0, t1 ...)
* Cf : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3915.pdf
* for the idea of using the sequence, which is used several times below.
*/
template
AUTO_DECL apply_impl(F &&f, T &&t, std14::index_sequence) RETURN(f(std::get(std::forward(t))...));
template
AUTO_DECL apply(F &&f, T &&t) RETURN(apply_impl(std::forward(f), std::forward(t), _get_seq()));
/**
* apply_construct(t)
* C : a class
* t a tuple
* Returns : C{t0, t1, ....}
*/
template
AUTO_DECL apply_construct_impl(T &&t, std14::index_sequence) RETURN(C{std::get(std::forward(t))...});
template
AUTO_DECL apply_construct(T &&t) RETURN(apply_construct_impl(std::forward(t), _get_seq()));
/**
* apply_construct_parenthesis(t)
* C : a class
* t a tuple
* Returns : C(t0, t1, ....)
*/
template
AUTO_DECL apply_construct_parenthesis_impl(T &&t, std14::index_sequence) RETURN(C(std::get(std::forward(t))...));
template
AUTO_DECL apply_construct_parenthesis(T &&t) RETURN(apply_construct_parenthesis_impl(std::forward(t), _get_seq()));
/**
* called_on_tuple(f)
* f : a callable object
* Wrapping a function to make it callable from a tuple
* called_on_tuple(f)( std::tie(x0,x1,x2)) is equivalent to f(x0,x1,x2)
*/
template struct _called_on_tuple {
F _f;
template AUTO_DECL operator()(Tu &&tu) RETURN(apply(_f, std::forward(tu)));
};
template _called_on_tuple called_on_tuple(F &&f) {
return {std::forward(f)};
}
// Implementation tools
// _for_each_impl (f, x0, x1, ..., xn) calls f(x0); f(x1); ... f(xn); IN THIS ORDER
template void _for_each_impl(F &&f) {}
template void _for_each_impl(F &&f, T0 &&x0, T &&... x) {
f(std::forward(x0));
_for_each_impl(f, std::forward(x)...);
}
// _for_each_apply_impl (f, t0, t1, ..., tn) calls apply(f,x0); apply(f,t1); ... apply(f,tn);
template void _for_each_apply_impl(F &&f) {}
template void _for_each_apply_impl(F &&f, T0 &&t0, T &&... t) {
apply(f, std::forward(t0));
_for_each_apply_impl(f, std::forward(t)...);
}
/**
* for_each(t, f)
* t: a tuple
* f: a callable object
* calls f on all tuple elements in the order of the tuple: f(x) for all x in t
*/
template void for_each_impl(F &&f, T &&t, std14::index_sequence) {
_for_each_impl(f, std::get(t)...);
}
template void for_each(T &&t, F &&f) { for_each_impl(f, std::forward(t), _get_seq()); }
/* for_each_enumerate(t, f)
* t: a tuple
* f: a callable object
* calls f on all tuple elements:
* Python equivalent :
* for n,x in enumrate(t): f(n,x)
*/
template void _for_each_enum_impl(F &&f, T &&t, std14::index_sequence) {
_for_each_apply_impl(f, std::tuple(t))>(Is, std::get(t))...);
// not make_tuple here, we keep the ref given by the get
}
template void for_each_enumerate(T &&t, F &&f) {
_for_each_enum_impl(f, std::forward(t), _get_seq());
}
/**
* for_each_zip(f, t1,t2)
* f : a callable object
* t1,t2 : two tuples
* calls f on all tuple elements: f(x1,x2) for x1 in t1 for x2 in t2
*/
template
void _for_each_zip_impl(std14::index_sequence, F &&f, T0 &&t0, T1 &&t1) {
_for_each_impl(called_on_tuple(std::forward(f)), std::tie(std::get(t0), std::get(t1))...);
}
template void for_each_zip(F &&f, T0 &&t0, T1 &&t1) {
_for_each_zip_impl(_get_seq(), std::forward(f), std::forward(t0), std::forward(t1));
}
/**
* for_each_zip(f, t1,t2,t3)
* f : a callable object
* t1,t2,t3 : three tuples
* calls f on all tuple elements: f(x1,x2,x3) for x1 in t1 for x2 in t2 for x3 in t3
*/
template
void _for_each_zip_impl(std14::index_sequence, F &&f, T0 &&t0, T1 &&t1, T2 &&t2) {
_for_each_impl(called_on_tuple(std::forward(f)), std::tie(std::get(t0), std::get(t1), std::get(t2))...);
}
template void for_each_zip(F &&f, T0 &&t0, T1 &&t1, T2 &&t2) {
_for_each_zip_impl(_get_seq(), std::forward(f), std::forward(t0), std::forward(t1), std::forward(t2));
}
/**
* map(f, t)
* f : a callable object
* t tuple
* Returns : [f(i) for i in t]
*/
template
AUTO_DECL _map_impl(F &&f, T &&t, std14::index_sequence)
RETURN(std::make_tuple(std::forward(f)(std::get(t))...));
template
AUTO_DECL map(F &&f, T &&t) RETURN(_map_impl(std::forward(f), std::forward(t), _get_seq()));
/**
* map_on_zip(f, t1, t2)
* f : a callable object
* t1, t2 two tuples of the same size
* Returns : [f(i,j) for i,j in zip(t1,t2)]
*/
template
auto _map_impl(F &&f, T0 &&t0, T1 &&t1, std14::index_sequence)
RETURN(std::make_tuple(std::forward(f)(std::get(t0), std::get(t1))...));
template
auto map_on_zip(F &&f, T0 &&t0, T1 &&t1)
RETURN(_map_impl(std::forward(f), std::forward(t0), std::forward(t1), _get_seq()));
template
auto map_on_zip_v2(F &&f, T0 &&t0, T1 &&t1)
RETURN(map(called_on_tuple(f), zip(t0,t1)));
/**
* map_on_zip(f,t0,t1,t2)
* f : a callable object
* t0, t1, t2 two tuples of the same size
* Returns : [f(i,j,k) for i,j,k in zip(t0,t1,t2)]
*/
template
auto _map_impl(F &&f, T0 &&t0, T1 &&t1, T2 &&t2, std14::index_sequence)
RETURN(std::make_tuple(std::forward(f)(std::get(t0), std::get(t1), std::get(t2))...));
template
auto map_on_zip(F &&f, T0 &&t0, T1 &&t1, T2 &&t2)
RETURN(_map_impl(std::forward(f), std::forward(t0), std::forward(t1), std::forward(t2), _get_seq()));
/**
* fold(f, t1, r_init)
* f : a callable object : f(x,r) -> r'
* t a tuple
* Returns : f(xN,f(x_N-1,...f(x0,r_init)) on the tuple
*/
#ifndef TRIQS_C11
template decltype(auto) fold_impl(_int, F &&f, T &&t, R &&r) {
return fold_impl(_int(), std::forward(f), std::forward(t),
f(std::get<_get_seq_len() - 1 - pos>(t), std::forward(r)));
}
template R fold_impl(_int<-1>, F &&f, T &&t, R &&r) { return std::forward(r); }
template decltype(auto) fold(F &&f, T &&t, R &&r) {
return fold_impl(_int<_get_seq_len() - 1>(), std::forward(f), std::forward(t), std::forward(r));
}
#else
// old implementation, not modified for C++11
template struct fold_impl {
template
auto operator()(F &&f, T &&t,
R &&r)DECL_AND_RETURN(fold_impl()(std::forward(f), std::forward(t),
f(std::get(t), std::forward(r))));
};
template struct fold_impl {
template R operator()(F &&f, T &&t, R &&r) { return std::forward(r); }
};
template
auto fold(F &&f, T &&t, R &&r)
DECL_AND_RETURN(fold_impl>::value, std::tuple_size>::value - 1,
T>()(std::forward(f), std::forward(t), std::forward(r)));
#endif
/**
* fold(f, r_init, t1, t2)
* f : a callable object
* t1, t2 two tuples of the same size
* Returns : f(x0,y0,f(x1,y1,,f(....)) for t1 = (x0,x1 ...) and t2 = (y0,y1...).
*/
#ifndef TRIQS_C11
template
decltype(auto) fold_impl(_int, F &&f, T0 &&t0, T1 &&t1, R &&r) {
constexpr int n = _get_seq_len() - 1 - pos;
return fold_impl(_int(), std::forward(f), std::forward(t0), std::forward(t1),
f(std::get(t0), std::get(t1), std::forward(r)));
}
template R fold_impl(_int<-1>, F &&f, T0 &&t0, T1 &&t1, R &&r) {
return std::forward(r);
}
template decltype(auto) fold(F &&f, T0 &&t0, T1 &&t1, R &&r) {
return fold_impl(_int<_get_seq_len() - 1>(), std::forward(f), std::forward(t0), std::forward(t1),
std::forward(r));
}
#else
// old implementation, not modified for C++11
template struct fold_on_zip_impl {
template
auto operator()(F &&f, T1 const &t1, T2 const &t2, R &&r)DECL_AND_RETURN(fold_on_zip_impl()(
std::forward(f), t1, t2, f(std::get(t1), std::get(t2), std::forward(r))));
};
template struct fold_on_zip_impl<-1, T1, T2> {
template R operator()(F &&f, T1 const &t1, T2 const &t2, R &&r) { return std::forward(r); }
};
template
auto fold(F &&f, T1 const &t1, T2 const &t2, R &&r)
DECL_AND_RETURN(fold_on_zip_impl::value - 1, T1, T2>()(std::forward(f), t1, t2, std::forward(r)));
#endif
/**
* replace(t,r)
* Given a tuple t, and integers, returns the tuple where the elements at initial position I are replaced by r
*/
template R _get_rpl(T &&x, R &&r, _int) { return std::forward(r); }
template T _get_rpl(T &&x, R &&r, ...) { return std::forward