Commit 33566de9 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Enforce style convention to apply and forEach functions and add recursive implementations

parent 7febbf22
...@@ -10,19 +10,19 @@ ...@@ -10,19 +10,19 @@
namespace AMDiS namespace AMDiS
{ {
namespace Tools namespace Ranges
{ {
namespace Impl_ namespace Impl_
{ {
template <class Functor, class Tuple, std::size_t... I> template <class Functor, class Tuple, std::size_t... I>
constexpr decltype(auto) apply_impl(Functor&& f, Tuple&& t, std::index_sequence<I...>) constexpr decltype(auto) applyImpl(Functor&& f, Tuple&& t, std::index_sequence<I...>)
{ {
using std::get; using std::get;
return f(get<I>(FWD(t))...); return f(get<I>(FWD(t))...);
} }
template <class Functor, std::size_t I0, std::size_t... I> template <class Functor, std::size_t I0, std::size_t... I>
constexpr decltype(auto) apply_indices_impl(Functor&& f, index_t<I0>, std::index_sequence<I...>) constexpr decltype(auto) applyIndicesImpl(Functor&& f, index_t<I0>, std::index_sequence<I...>)
{ {
return f(index_t<I0+I>{}...); return f(index_t<I0+I>{}...);
} }
...@@ -31,35 +31,44 @@ namespace AMDiS ...@@ -31,35 +31,44 @@ namespace AMDiS
template <class F, class Tuple> template <class F, class Tuple>
constexpr decltype(auto) apply(F&& f, Tuple&& t) constexpr decltype(auto) apply(F&& f, Tuple&& t)
{ {
return Impl_::apply_impl(FWD(f), FWD(t), return Impl_::applyImpl(FWD(f), FWD(t),
std::make_index_sequence<static_size_v<Tuple>>{}); std::make_index_sequence<static_size_v<Tuple>>{});
} }
template <class Functor, class... Args> template <class Functor, class... Args>
constexpr decltype(auto) apply_variadic(Functor&& f, Args&&... args) constexpr decltype(auto) applyVariadic(Functor&& f, Args&&... args)
{ {
return apply(FWD(f), std::forward_as_tuple(args...)); return Impl_::applyImpl(FWD(f), std::forward_as_tuple(args...),
std::make_index_sequence<sizeof...(Args)>{});
} }
template <std::size_t N, class Functor> template <std::size_t N, class Functor>
constexpr decltype(auto) apply_indices(Functor&& f) constexpr decltype(auto) applyIndices(Functor&& f)
{ {
return Impl_::apply_indices_impl(FWD(f), index_t<0>{}, return Impl_::applyIndicesImpl(FWD(f), index_t<0>{},
std::make_index_sequence<N>{}); std::make_index_sequence<N>{});
} }
template <std::size_t I0, std::size_t I1, class Functor>
constexpr decltype(auto) applyIndices(Functor&& f)
{
return Impl_::applyIndicesImpl(FWD(f), index_t<I0>{},
std::make_index_sequence<I1-I0>{});
}
template <class Functor, std::size_t N> template <class Functor, std::size_t N>
constexpr decltype(auto) apply_indices(Functor&& f, index_t<N>) constexpr decltype(auto) applyIndices(Functor&& f, index_t<N>)
{ {
return Impl_::apply_indices_impl(FWD(f), index_t<0>{}, return Impl_::applyIndicesImpl(FWD(f), index_t<0>{},
std::make_index_sequence<N>{}); std::make_index_sequence<N>{});
} }
template <class Functor, std::size_t I0, std::size_t I1> template <class Functor, std::size_t I0, std::size_t I1>
constexpr decltype(auto) apply_indices(Functor&& f, index_t<I0>, index_t<I1>) constexpr decltype(auto) applyIndices(Functor&& f, index_t<I0>, index_t<I1>)
{ {
return Impl_::apply_indices_impl(FWD(f), index_t<I0>{}, return Impl_::applyIndicesImpl(FWD(f), index_t<I0>{},
std::make_index_sequence<I1-I0>{}); std::make_index_sequence<I1-I0>{});
} }
}
} // end namespace Ranges
} // end namespace AMDiS } // end namespace AMDiS
...@@ -24,6 +24,8 @@ install(FILES ...@@ -24,6 +24,8 @@ install(FILES
Math.hpp Math.hpp
Order.hpp Order.hpp
Range.hpp Range.hpp
RecursiveApply.hpp
RecursiveForEach.hpp
QuadMath.hpp QuadMath.hpp
SharedPtr.hpp SharedPtr.hpp
StaticSize.hpp StaticSize.hpp
......
...@@ -7,36 +7,36 @@ ...@@ -7,36 +7,36 @@
namespace AMDiS namespace AMDiS
{ {
namespace Tools namespace Ranges
{ {
template <class Functor, class... Args> template <class Functor, class... Args>
constexpr void for_variadic(Functor&& f, Args&&... args) constexpr void forVariadic(Functor&& f, Args&&... args)
{ {
(f(FWD(args)),...); (f(FWD(args)),...);
} }
template <std::size_t... I, class Tuple, class Functor> template <std::size_t... I, class Tuple, class Functor>
constexpr void for_each(std::index_sequence<I...>, Tuple&& tuple, Functor&& f) constexpr void forEach(std::index_sequence<I...>, Tuple&& tuple, Functor&& f)
{ {
using std::get; using std::get;
(f(get<I>(tuple)),...); (f(get<I>(tuple)),...);
} }
template <class Tuple, class Functor> template <class Tuple, class Functor>
constexpr void for_each(Tuple&& tuple, Functor&& f) constexpr void forEach(Tuple&& tuple, Functor&& f)
{ {
Tools::for_each(std::make_index_sequence<static_size_v<Tuple>>{}, FWD(tuple), FWD(f)); Ranges::forEach(std::make_index_sequence<static_size_v<Tuple>>{}, FWD(tuple), FWD(f));
} }
template <class T, std::size_t n, class Functor> template <class T, std::size_t n, class Functor>
constexpr void for_each(std::array<T,n> const& a, Functor&& f) constexpr void forEach(std::array<T,n> const& a, Functor&& f)
{ {
for (auto const& ai : a) for (auto const& ai : a)
f(ai); f(ai);
} }
template <class T, class Functor> template <class T, class Functor>
constexpr void for_each(std::vector<T> const& v, Functor&& f) constexpr void forEach(std::vector<T> const& v, Functor&& f)
{ {
for (auto const& vi : v) for (auto const& vi : v)
f(vi); f(vi);
...@@ -44,28 +44,34 @@ namespace AMDiS ...@@ -44,28 +44,34 @@ namespace AMDiS
template <std::size_t I0 = 0, std::size_t... I, class Functor> template <std::size_t I0 = 0, std::size_t... I, class Functor>
constexpr void for_range(std::index_sequence<I...>, Functor&& f) constexpr void forIndices(std::index_sequence<I...>, Functor&& f)
{ {
(f(index_t<I0+I>{}),...); (f(index_t<I0+I>{}),...);
} }
template <std::size_t I0, std::size_t I1, class Functor> template <std::size_t I0, std::size_t I1, class Functor>
constexpr void for_range(index_t<I0>, index_t<I1>, Functor&& f) constexpr void forIndices(index_t<I0>, index_t<I1>, Functor&& f)
{ {
Tools::for_range<I0>(std::make_index_sequence<std::size_t(I1-I0)>{}, FWD(f)); Ranges::forIndices<I0>(std::make_index_sequence<std::size_t(I1-I0)>{}, FWD(f));
} }
template <std::size_t N, class Functor> template <std::size_t N, class Functor>
constexpr void for_range(index_t<N>, Functor&& f) constexpr void forIndices(index_t<N>, Functor&& f)
{ {
Tools::for_range(std::make_index_sequence<N>{}, FWD(f)); Ranges::forIndices(std::make_index_sequence<N>{}, FWD(f));
} }
template <std::size_t I0, std::size_t I1, class Functor> template <std::size_t I0, std::size_t I1, class Functor>
constexpr void for_range(Functor&& f) constexpr void forIndices(Functor&& f)
{ {
Tools::for_range<I0>(std::make_index_sequence<std::size_t(I1-I0)>{}, FWD(f)); Ranges::forIndices<I0>(std::make_index_sequence<std::size_t(I1-I0)>{}, FWD(f));
} }
} // end namespace Tools template <std::size_t N, class Functor>
constexpr void forIndices(Functor&& f)
{
Ranges::forIndices<0>(std::make_index_sequence<N>{}, FWD(f));
}
} // end namespace Ranges
} // end namespace AMDiS } // end namespace AMDiS
#pragma once
#include <array>
#include <tuple>
#include <vector>
#include <dune/common/tuplevector.hh>
#include <amdis/common/Apply.hpp>
namespace AMDiS
{
namespace Recursive
{
/// Default implementation of the recursive \ref map function.
template <class T>
struct Apply
{
template <class F>
static auto impl(F&& f, T const& t)
{
return f(t);
}
};
/// \brief Recursive application of a transformation functor `f` to a hierarchic
/// container of containers, returning the transformed container.
/**
* This utility function applies the given functor `f` to the "leaf" entries in
* a hierarchic container that returns a transformed container. Therefore, the
* container is traversed recursively, using specializations of the `Map<Container>::apply`
* class method. If no specialization is provided, the function is applied to the
* whole container or leaf entry, respectively.
**/
template <class F, class T>
auto apply(F&& f, T const& t)
{
return Apply<T>::impl(f,t);
}
// specializations for container types
template <class T, std::size_t n>
struct Apply<std::array<T,n>>
{
template <class F>
static auto impl(F&& f, std::array<T,n> const& a)
{
return Ranges::applyIndices<n>([&](auto... ii) {
return std::array{Recursive::apply(f,a[ii])...}; });
}
};
template <class... TT>
struct Apply<std::tuple<TT...>>
{
template <class F>
static auto impl(F&& f, std::tuple<TT...> const& t)
{
return Ranges::apply([&](auto const&... ti) {
return std::tuple{Recursive::apply(f,ti)...}; }, t);
}
};
template <class T1, class T2>
struct Apply<std::pair<T1,T2>>
{
template <class F>
static auto impl(F&& f, std::pair<T1,T2> const& t)
{
return std::pair{Recursive::apply(f,t.first),
Recursive::apply(f,t.second)};
}
};
template <class... TT>
struct Apply<Dune::TupleVector<TT...>>
{
template <class F>
static auto impl(F&& f, Dune::TupleVector<TT...> const& t)
{
return Ranges::apply([&](auto const&... ti) {
return Dune::makeTupleVector(Recursive::apply(f,ti)...); }, t);
}
};
template <class T>
struct Apply<std::vector<T>>
{
template <class F>
static auto impl(F&& f, std::vector<T> const& v)
{
using U = TYPEOF(Recursive::apply(f,std::declval<T>()));
std::vector<U> out;
out.reserve(v.size());
for (std::size_t i = 0; i < v.size(); ++i)
out.emplace_back(Recursive::apply(f,v[i]));
return out;
}
};
} // end namespace Recursive
} // end namespace AMDiS
\ No newline at end of file
#pragma once
#include <array>
#include <tuple>
#include <vector>
#include <type_traits>
#include <utility>
#include <dune/common/tuplevector.hh>
#include <amdis/common/TypeTraits.hpp>
namespace AMDiS
{
namespace Recursive
{
/// Default implementation of the recursive \ref forEach function.
/**
* \tparam V The type of the container/value decayed to the raw type
**/
template <class V>
struct ForEach
{
template <class Value, class F>
static void impl(Value&& v, F&& f)
{
f(v);
}
};
/// \brief Recursive application of a functor `f` to a hierarchic container of containers.
/**
* This utility function applies the given functor `f` to the "leaf" entries in
* a hierarchic container. Therefore, the container is traversed recursively,
* using specializations of the `ForEach<Container>::apply` class method.
* If no specialization is provided, the function is applied to the whole container
* or leaf entry, respectively.
**/
template <class Container, class F>
void forEach(Container&& container, F&& f)
{
ForEach<TYPEOF(container)>::impl(container,f);
}
// specializations for container types
template <class... TT>
struct ForEach<std::tuple<TT...>>
{
using indices = std::make_index_sequence<sizeof...(TT)>;
template <std::size_t... I, class Tuple, class F>
static void impl2(std::index_sequence<I...>, Tuple&& tuple, F&& f)
{
using std::get;
(Recursive::forEach(get<I>(tuple), f),...);
}
template <class Tuple, class F>
static void impl(Tuple&& tuple, F&& f)
{
impl2(indices{}, tuple, f);
}
};
template <class T1, class T2>
struct ForEach<std::pair<T1,T2>>
{
template <class Pair, class F>
static void impl(Pair&& pair, F&& f)
{
Recursive::forEach(pair.first, f);
Recursive::forEach(pair.second, f);
}
};
template <class... TT>
struct ForEach<Dune::TupleVector<TT...>>
{
template <class Tuple, class F>
static void impl(Tuple&& tuple, F&& f)
{
ForEach<std::tuple<TT...>>::impl(tuple, f);
}
};
template <class T, std::size_t n>
struct ForEach<std::array<T,n>>
{
template <class Array, class F>
static void impl(Array&& a, F&& f)
{
for (auto&& ai : a)
Recursive::forEach(ai, f);
}
};
template <class T>
struct ForEach<std::vector<T>>
{
template <class Vector, class F>
static void impl(Vector&& v, F&& f)
{
for (auto&& vi : v)
Recursive::forEach(vi, f);
}
};
} // end namespace Recursive
} // end namespace AMDiS
...@@ -370,7 +370,7 @@ namespace AMDiS ...@@ -370,7 +370,7 @@ namespace AMDiS
public: public:
NodeIdSet(GridView const& gridView) NodeIdSet(GridView const& gridView)
: idsTuple_(Tools::apply_indices<children>([&](auto... i) { : idsTuple_(Ranges::applyIndices<children>([&](auto... i) {
return std::make_tuple(SubNodeIdSet<VALUE(i)>(gridView)...); return std::make_tuple(SubNodeIdSet<VALUE(i)>(gridView)...);
})) }))
{} {}
...@@ -379,7 +379,7 @@ namespace AMDiS ...@@ -379,7 +379,7 @@ namespace AMDiS
void bind(const Node& node) void bind(const Node& node)
{ {
node_ = &node; node_ = &node;
Tools::for_range<0,children>([&](auto i) { Ranges::forIndices<0,children>([&](auto i) {
std::get<VALUE(i)>(idsTuple_).bind(node.child(i)); std::get<VALUE(i)>(idsTuple_).bind(node.child(i));
}); });
} }
...@@ -388,7 +388,7 @@ namespace AMDiS ...@@ -388,7 +388,7 @@ namespace AMDiS
void unbind() void unbind()
{ {
node_ = nullptr; node_ = nullptr;
Tools::for_each(idsTuple_, [](auto& ids) { Ranges::forEach(idsTuple_, [](auto& ids) {
ids.unbind(); ids.unbind();
}); });
} }
...@@ -404,7 +404,7 @@ namespace AMDiS ...@@ -404,7 +404,7 @@ namespace AMDiS
It fillIn(Twist const& twist, It it, size_type shift = 0) const It fillIn(Twist const& twist, It it, size_type shift = 0) const
{ {
assert(node_ != nullptr); assert(node_ != nullptr);
Tools::for_each(idsTuple_, [&](auto const& ids) Ranges::forEach(idsTuple_, [&](auto const& ids)
{ {
size_type subTreeSize = ids.size(); size_type subTreeSize = ids.size();
it = ids.fillIn(twist, it, shift); it = ids.fillIn(twist, it, shift);
......
...@@ -51,7 +51,7 @@ namespace AMDiS ...@@ -51,7 +51,7 @@ namespace AMDiS
template <class TreePath> template <class TreePath>
static auto transformTreePath(TreePath const& treePath) static auto transformTreePath(TreePath const& treePath)
{ {
return Tools::apply([](auto... i) { return Dune::makeTupleVector(i...); }, treePath._data); return Ranges::apply([](auto... i) { return Dune::makeTupleVector(i...); }, treePath._data);
} }
#endif #endif
}; };
......
...@@ -16,7 +16,7 @@ namespace AMDiS ...@@ -16,7 +16,7 @@ namespace AMDiS
else if constexpr (N::isPower) else if constexpr (N::isPower)
return order(node.child(0u)); return order(node.child(0u));
else if constexpr (N::isComposite) else if constexpr (N::isComposite)
return Tools::apply_indices<N::degree()>([&](auto... ii) { return Ranges::applyIndices<N::degree()>([&](auto... ii) {
return Math::max(order(node.child(ii))...); return Math::max(order(node.child(ii))...);
}); });
else { else {
......
...@@ -72,7 +72,7 @@ namespace AMDiS ...@@ -72,7 +72,7 @@ namespace AMDiS
template <class Element> template <class Element>
void bind(Element const& element) void bind(Element const& element)
{ {
Tools::for_each(localFcts_, [&](auto& localFct) { Ranges::forEach(localFcts_, [&](auto& localFct) {
(*localFct).bind(element); (*localFct).bind(element);
}); });
} }
...@@ -80,7 +80,7 @@ namespace AMDiS ...@@ -80,7 +80,7 @@ namespace AMDiS
/// Calls \ref unbind for all localFunctions /// Calls \ref unbind for all localFunctions
void unbind() void unbind()
{ {
Tools::for_each(localFcts_, [&](auto& localFct) { Ranges::forEach(localFcts_, [&](auto& localFct) {
(*localFct).unbind(); (*localFct).unbind();
}); });
} }
...@@ -88,7 +88,7 @@ namespace AMDiS ...@@ -88,7 +88,7 @@ namespace AMDiS
/// Applies the functor \ref fct_ to the evaluated localFunctions /// Applies the functor \ref fct_ to the evaluated localFunctions
Range operator()(Domain const& x) const Range operator()(Domain const& x) const
{ {
return Tools::apply([&](auto&&... localFct) { return fct_((*localFct)(x)...); }, localFcts_); return Ranges::apply([&](auto&&... localFct) { return fct_((*localFct)(x)...); }, localFcts_);
} }
public: public:
...@@ -127,7 +127,7 @@ namespace AMDiS ...@@ -127,7 +127,7 @@ namespace AMDiS
// d_i(f)[lgfs...] * lgfs_i // d_i(f)[lgfs...] * lgfs_i
auto term_i = [&](auto const _i) auto term_i = [&](auto const _i)
{ {
auto di_f = Tools::apply([&](auto const&... lgfs) { auto di_f = Ranges::apply([&](auto const&... lgfs) {
return makeFunctorGridFunction(partial(lf.fct(), _i), (*lgfs)...); return makeFunctorGridFunction(partial(lf.fct(), _i), (*lgfs)...);
}, lf.localFcts()); }, lf.localFcts());
...@@ -137,7 +137,7 @@ namespace AMDiS ...@@ -137,7 +137,7 @@ namespace AMDiS
}; };