3
0
mirror of https://github.com/triqs/dft_tools synced 2024-11-01 19:53:45 +01:00
dft_tools/doc/reference/c++/utilities/tupletools.rst

247 lines
5.6 KiB
ReStructuredText
Raw Normal View History

2013-08-22 16:55:51 +02:00
.. highlight:: c
.. _util_tuple:
Tuple tools
2013-08-22 16:55:51 +02:00
=============================
Various standard functional operations on tuple (which should be in the STL but are not ...).
2013-08-22 16:55:51 +02:00
..
.. note::
Simple measures have shown that these routines are **as fast as native code** (tested on gcc, clang, icc),
due to inlining. They can therefore be used in critical parts of codes.
2013-08-22 16:55:51 +02:00
apply
-----------------------------------------------
*Purpose* : `apply a function on a tuple of arguments`
Given a function object `f`, and its arguments stored in a tuple `t`, and we want to apply `f` on `t`.
*Python equivalent*:
.. code-block:: python
def apply(f,t) :
return f(*t)
2013-08-22 16:55:51 +02:00
*Synopsis* ::
template<typename Function, typename Tuple> auto apply (Function && f, Tuple const & t);
*Example* :
2013-08-22 16:55:51 +02:00
.. triqs_example:: ./tupletools_0.cpp
2013-08-22 16:55:51 +02:00
for_each
-------------------------------------------------------------------------
*Purpose* : `apply a function for each element of a tuple (in order)`
Given a function object `f`, we want to apply it to all elements of a tuple `t`.
*Python equivalent*:
.. code-block:: python
def for_each(t,f) :
for x in t:
f(x)
2013-08-22 16:55:51 +02:00
*Synopsis* ::
template<typename Function, typename Tuple> void for_each(Tuple const & t, Function && f);
*Example* :
2013-08-22 16:55:51 +02:00
.. triqs_example:: ./tupletools_1.cpp
for_each_zip
-------------------------------------------------------------------------
*Purpose* : `apply a function for each element of tuple zip (in order)`
*Python equivalent*:
.. code-block:: python
def for_each(f,t0,t1) :
for x0,x1 in itertools.zip(t0,t1):
f(x0,x1)
*Synopsis* ::
template <typename F, typename T0, typename T1> void for_each_zip(F &&f, T0 &&t0, T1 &&t1);
template <typename F, typename T0, typename T1, typename T2> void for_each_zip(F &&f, T0 &&t0, T1 &&t1, T2 &&t2);
*Example* :
.. triqs_example:: ./tupletools_2.cpp
map
-------------------------------------------------------------------------
*Purpose* : `map a function on a tuple to create a new tuple`
*Python equivalent*:
.. code-block:: python
def map(f,t) :
return (f(x) for x in t)
*Synopsis* ::
template <typename T, typename F> auto map(F &&f, T &&t);
*Returns*:
The result is a tuple, of the same length as T, made of the evaluation of f on the elements on T
*Example* :
.. triqs_example:: ./tupletools_3.cpp
fold
-------------------------------------------------------------------------
*Purpose* : `reduction of a tuple with a function`
*Python equivalent*:
.. code-block:: python
def fold(f,t,r) :
return reduce(f,t,r)
*Synopsis* ::
(1) template <typename F, typename T, typename R>
decltype(auto) fold(F &&f, T &&t, R &&r);
(2) template <typename F, typename T0, typename T1, typename R>
decltype(auto) fold(F &&f, T0 &&t0, T1 &&t1, R &&r);
*Returns*::
f(get<N>(t),
f(get<N-1>(t),
...,
f(get<0>(t),r))) (1)
f(get<N>(t0), get<N>(t1),
f(get<N-1>(t0), get<N-1>(t1),
...,
f(get<0>(t0), get<0>(t1), r))) (2)
*Parameters* :
* f : a callable object of signature ::
f(x, r) -> r' (1)
f(x, y, r) -> r' (2)
The return type of f must be a valid last parameter for f (at least for one overload).
* t : a tuple
* t0,t1 : two tuples of the same size
* r : anything that can be a last parameter for f.
* Precondition: everything so that the resulting expression is valid (in particular, f must be called on each tuple elements,
with its return type as last parameter.
.. warning::
The type of the result is not necessarly R : it is automatically deduced from this expression. Cf example.
*Example* :
.. triqs_example:: ./tupletools_4.cpp
reverse
-------------------------------------------------------------------------
*Purpose* : `lazy reverse of a tuple`
*Python equivalent*: None.
*Synopsis* ::
namespace std {
template<typename ... T> TU reverse(std::tuple<T...> && x);
template<typename ... T> TU reverse(std::tuple<T...> & x);
template<typename ... T> TU reverse(std::tuple<T...> const& x);
}
.. warning::
reverse is declared in std:: to benefit from ADL (a bit dangerous, but ok here).
*Returns*:
TU is a tuple like type, that :
* Contains a ref of the original tuple, or the tuple if a && was passed.
* Hence, no copy is ever made.
* Accepts std::get and std::tuple_size, like tuple.
reverse(t) can therefore be used in place of a regular tuple in the algorithms of this section.
*Example* :
.. triqs_example:: ./tupletools_reverse.cpp
called_on_tuple
-------------------------------------------------------------------------
*Purpose* : `Adapting a function to call with a tuple argument and flatten it`
*Python equivalent*:
.. code-block:: python
def called_on_tuple(f) :
return lambda x : f(*x)
*Synopsis* ::
template <typename F> F2 called_on_tuple(F &&f);
*Returns*:
F2 is a function object which adapts the function f for calling on a tuple.
The following call are therefore equivalent::
called_on_tuple(f)( std::tie(x0,x1,x2))
f(x0,x1,x2)
*Example* :
.. triqs_example:: ./tupletools_called.cpp
*Implementation* :
The C++ is simple in fact ::
template <typename F> struct _called_on_tuple {
F _f;
template <typename Tu> decltype(auto) operator()(Tu &&tu) {
return apply(_f, std::forward<Tu>(tu));
}
};
template <typename F> _called_on_tuple<F> called_on_tuple(F &&f) {
return {std::forward<F>(f)};
}