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 @@
namespace AMDiS
{
namespace Tools
namespace Ranges
{
namespace Impl_
{
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;
return f(get<I>(FWD(t))...);
}
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>{}...);
}
......@@ -31,35 +31,44 @@ namespace AMDiS
template <class F, class Tuple>
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>>{});
}
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>
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>{});
}
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>
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>{});
}
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>{});
}
}
} // end namespace Ranges
} // end namespace AMDiS
......@@ -24,6 +24,8 @@ install(FILES
Math.hpp
Order.hpp
Range.hpp
RecursiveApply.hpp
RecursiveForEach.hpp
QuadMath.hpp
SharedPtr.hpp
StaticSize.hpp
......
......@@ -7,36 +7,36 @@
namespace AMDiS
{
namespace Tools
namespace Ranges
{
template <class Functor, class... Args>
constexpr void for_variadic(Functor&& f, Args&&... args)
constexpr void forVariadic(Functor&& f, Args&&... args)
{
(f(FWD(args)),...);
}
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;
(f(get<I>(tuple)),...);
}
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>
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)
f(ai);
}
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)
f(vi);
......@@ -44,28 +44,34 @@ namespace AMDiS
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>{}),...);
}
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>
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>
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
#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
public:
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)...);
}))
{}
......@@ -379,7 +379,7 @@ namespace AMDiS
void bind(const 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));
});
}
......@@ -388,7 +388,7 @@ namespace AMDiS
void unbind()
{
node_ = nullptr;
Tools::for_each(idsTuple_, [](auto& ids) {
Ranges::forEach(idsTuple_, [](auto& ids) {
ids.unbind();
});
}
......@@ -404,7 +404,7 @@ namespace AMDiS
It fillIn(Twist const& twist, It it, size_type shift = 0) const
{
assert(node_ != nullptr);
Tools::for_each(idsTuple_, [&](auto const& ids)
Ranges::forEach(idsTuple_, [&](auto const& ids)
{
size_type subTreeSize = ids.size();
it = ids.fillIn(twist, it, shift);
......
......@@ -51,7 +51,7 @@ namespace AMDiS
template <class 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
};
......
......@@ -16,7 +16,7 @@ namespace AMDiS
else if constexpr (N::isPower)
return order(node.child(0u));
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))...);
});
else {
......
......@@ -72,7 +72,7 @@ namespace AMDiS
template <class Element>
void bind(Element const& element)
{
Tools::for_each(localFcts_, [&](auto& localFct) {
Ranges::forEach(localFcts_, [&](auto& localFct) {
(*localFct).bind(element);
});
}
......@@ -80,7 +80,7 @@ namespace AMDiS
/// Calls \ref unbind for all localFunctions
void unbind()
{
Tools::for_each(localFcts_, [&](auto& localFct) {
Ranges::forEach(localFcts_, [&](auto& localFct) {
(*localFct).unbind();
});
}
......@@ -88,7 +88,7 @@ namespace AMDiS
/// Applies the functor \ref fct_ to the evaluated localFunctions
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:
......@@ -127,7 +127,7 @@ namespace AMDiS
// d_i(f)[lgfs...] * lgfs_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)...);
}, lf.localFcts());
......@@ -137,7 +137,7 @@ namespace AMDiS
};
// sum_i [ d_i(f)[lgfs...] * derivativeOf(lgfs_i)
auto gridFct = Tools::apply([&](auto const... _i)
auto gridFct = Ranges::apply([&](auto const... _i)
{
return makeFunctorGridFunction(Operation::Plus{}, term_i(_i)...);
}, index_seq);
......@@ -159,7 +159,7 @@ namespace AMDiS
&& (Concepts::Polynomial<LFs> &&...))>
int order(FunctorLocalFunction<Sig,F,LFs...> const& lf)
{
return Tools::apply([&lf](auto const&... lgfs) {
return Ranges::apply([&lf](auto const&... lgfs) {
return order(lf.fct(), order(*lgfs)...);
}, lf.localFcts());
}
......@@ -216,7 +216,7 @@ namespace AMDiS
/// Applies the functor to the evaluated gridfunctions
Range operator()(Domain const& x) const
{
return Tools::apply([&](auto&&... gridFct) { return fct_(gridFct(x)...); }, gridFcts_);
return Ranges::apply([&](auto&&... gridFct) { return fct_(gridFct(x)...); }, gridFcts_);
}
/// Return the stored \ref EntitySet of the first GridFunction
......@@ -227,7 +227,7 @@ namespace AMDiS
LocalFunction makeLocalFunction() const
{
return Tools::apply([&](auto const&... gridFcts) { return LocalFunction{fct_, gridFcts...}; }, gridFcts_);
return Ranges::apply([&](auto const&... gridFcts) { return LocalFunction{fct_, gridFcts...}; }, gridFcts_);
}
private:
......@@ -260,7 +260,7 @@ namespace AMDiS
template <class GridView>
static auto create(Self const& self, GridView const& gridView)
{
return Tools::apply([&](auto const&... pgf) {
return Ranges::apply([&](auto const&... pgf) {
return makeFunctorGridFunction(self.fct_,
makeGridFunction(pgf, gridView)...);
}, self.preGridFcts_);
......
......@@ -41,7 +41,7 @@ namespace AMDiS
constexpr auto operator()(Ts const&... args) const
{
auto eval = [&](auto const& g) { return g(args...); };
return Tools::apply([&,this](auto const&... gs) { return f_(eval(gs)...); }, gs_);
return Ranges::apply([&,this](auto const&... gs) { return f_(eval(gs)...); }, gs_);
}
F f_;
......@@ -76,7 +76,7 @@ namespace AMDiS
int order(Composer<F,Gs...> const& c, Int... degrees)
{
auto deg = [&](auto const& g) { return order(g, int(degrees)...); };
return Tools::apply([&](auto const&... gs) { return order(c.f_, deg(gs)...); }, c.gs_);
return Ranges::apply([&](auto const&... gs) { return order(c.f_, deg(gs)...); }, c.gs_);
}
/// Partial derivative of composed function:
......
......@@ -6,5 +6,6 @@ install(FILES
Traits.hpp
Traversal.hpp
TreeContainer.hpp
TreeContainerTransformation.hpp
TreePath.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/typetree)
......@@ -259,7 +259,7 @@ namespace AMDiS
if constexpr (Node::isComposite) {
return ValueAndContainer{
value(node),
Tools::apply_indices<Node::degree()>(
Ranges::applyIndices<Node::degree()>(
[&](auto... ii) { return Dune::makeTupleVector((*this)(node.child(ii))...); })};
}
else {
......
#pragma once
#include <amdis/common/RecursiveForEach.hpp>
#include <amdis/common/RecursiveMap.hpp>
#include <amdis/typetree/TreeContainer.hpp>
namespace AMDiS
{
namespace Recursive
{
// specializations of recursive utilities for TreeContainer entries
template <>
struct Apply<Impl::Ignore>
{
template <class F>
static auto impl(F&& /*f*/, Impl::Ignore)
{
return Impl::Ignore{};
}
};
template <class Value, class Container>
struct Apply<Impl::ValueAndContainer<Value,Container>>
{
template <class F, class VC>
static auto impl(F&& f, VC const& vc)
{
return Impl::ValueAndContainer{
Recursive::apply(f,vc.value()),
Recursive::apply(f,vc.container())};
}
};
template <class Value>
struct Apply<Impl::ValueAndContainer<Value,void>>
{
template <class F, class VC>
static auto impl(F&& f, VC const& vc)
{