Commit d773c643 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Move all recursive algorithms to algorithm subdirectory

parent 1a410159
#pragma once
#include <array>
#include <tuple>
#include <vector>
#include <dune/common/tuplevector.hh>
#include <amdis/common/Apply.hpp>
namespace AMDiS {
namespace Recursive {
template <class T>
struct Apply;
/// \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 `Apply<Container>::impl`
* 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
/// 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);
}
};
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 AMDiS::Recursive
\ No newline at end of file
install(FILES
Apply.hpp
ForEach.hpp
InnerProduct.hpp
Transform.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/algorithm)
#pragma once
#include <array>
#include <tuple>
#include <vector>
#include <type_traits>
#include <utility>
#include <dune/common/tuplevector.hh>
#include <amdis/common/ForEach.hpp>
#include <amdis/common/TypeTraits.hpp>
namespace AMDiS {
namespace Recursive {
template <class Vec>
struct ForEach;
/// \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>
struct ForEach
{
private:
// ranges with dynamic index access
template <class Vec, class F,
class = decltype(std::begin(std::declval<Vec>())),
class = decltype(std::end(std::declval<Vec>()))>
static void impl2 (Dune::PriorityTag<2>, Vec&& vec, F&& f)
{
for (auto&& v : vec)
Recursive::forEach(v, f);
}
// ranges with static index access
template <class Vec, class F,
class = decltype(std::get<0>(std::declval<Vec>()))>
static void impl2 (Dune::PriorityTag<1>, Vec&& vec, F&& f)
{
Ranges::forEach(vec, [&](auto&& v) {
Recursive::forEach(v, f);
});
}
// no range
template <class Value, class F>
static void impl2 (Dune::PriorityTag<0>, Value&& value, F&& f)
{
f(value);
}
public:
template <class Vec, class F>
static void impl (Vec&& vec, F&& f)
{
impl2(Dune::PriorityTag<5>{}, vec, f);
}
};
}} // end namespace AMDiS::Recursive
#pragma once
#include <functional>
#include <type_traits>
#include <utility>
#include <vector>
#include <dune/common/typeutilities.hh>
#include <amdis/common/ForEach.hpp>
#include <amdis/common/StaticSize.hpp>
namespace AMDiS {
namespace Recursive {
template <class>
struct InnerProduct;
/// \brief Recursive inner product of two containers [in1] and [in2] following the signature
/// of `std::inner_product` but applied to the leaf elements of the possibly hierarchic containers
template <class In1, class In2, class T, class BinaryOperation1, class BinaryOperation2>
T innerProduct (In1 const& in1, In2 const& in2, T init, BinaryOperation1 op1, BinaryOperation2 op2)
{
return InnerProduct<In1>::impl(in1, in2, std::move(init), op1, op2);
}
template <class In1, class In2, class T>
T innerProduct (In1 const& in1, In2 const& in2, T init)
{
return InnerProduct<In1>::impl(in1, in2, std::move(init), std::plus<>{}, std::multiplies<>{});
}
/// General implementation of recursive inner-product
template <class>
struct InnerProduct
{
private:
// dynamic ranges
template <class In1, class In2, class T, class BinOp1, class BinOp2,
class = decltype(std::begin(std::declval<In1>())),
class = decltype(std::end(std::declval<In1>())),
class = decltype(std::begin(std::declval<In2>()))>
static T impl2 (Dune::PriorityTag<2>, In1 const& in1, In2 const& in2, T init, BinOp1 op1, BinOp2 op2)
{
auto first1 = std::begin(in1);
auto first2 = std::begin(in2);
for (; first1 != std::end(in1); ++first1, ++first2)
init = Recursive::innerProduct(*first1, *first2, std::move(init), op1, op2);
return init;
}
// ranges with static index access
template <class In1, class In2, class T, class BinOp1, class BinOp2,
class = decltype(std::declval<In1>()[std::integral_constant<std::size_t,0>{}])>
static T impl2 (Dune::PriorityTag<1>, In1 const& in1, In2 const& in2, T init, BinOp1 op1, BinOp2 op2)
{
static_assert(static_size_v<In1> == static_size_v<In2>);
Ranges::forIndices<static_size_v<In1>>([&](auto ii) {
init = Recursive::innerProduct(in1[ii], in2[ii], std::move(init), op1, op2);
});
return init;
}
// no range
template <class In1, class In2, class T, class BinOp1, class BinOp2>
static T impl2 (Dune::PriorityTag<0>, In1 const& in1, In2 const& in2, T init,
BinOp1 op1, BinOp2 op2)
{
return op1(std::move(init), op2(in1, in2));
}
public:
template <class In1, class In2, class T, class BinOp1, class BinOp2>
static T impl (In1 const& in1, In2 const& in2, T init, BinOp1 op1, BinOp2 op2)
{
return impl2(Dune::PriorityTag<5>{}, in1, in2, init, op1, op2);
}
};
}} // end namespace AMDiS::Recursive
#pragma once
#include <type_traits>
#include <utility>
#include <vector>
#include <dune/common/typeutilities.hh>
#include <amdis/common/ForEach.hpp>
#include <amdis/common/StaticSize.hpp>
namespace AMDiS {
namespace Recursive {
template <class>
struct Transform;
/// \brief Recursive application of a functor `op` to a hierarchic container of containers.
/**
* This utility function applies the given functor `op` to the "leaf" entries in
* hierarchic containers {in...} and assigns the output to the hierarchic container [out].
* Therefore, the containers are traversed recursively, using specializations of the
* `Transform<Container>::impl` class method. If no such specialization is provided, the function
* is applied to the whole containers or leaf entries, respectively.
**/
template <class Out, class Op, class... In>
void transform (Out& out, Op&& op, In const&... in)
{
Transform<std::remove_const_t<Out>>::impl(out,op,in...);
}
template <class>
struct Transform
{
private:
// ranges with dynamic index access
template <class OutIter, class Op, class... InIter>
static void impl3 (OutIter d_first, OutIter d_last, Op&& op, InIter... first)
{
while (d_first != d_last)
Recursive::transform(*d_first++, op, *first++...);
}
// ranges with dynamic index access
template <class Out, class Op, class... In,
class = decltype(std::begin(std::declval<Out>())),
class = decltype(std::end(std::declval<Out>())),
class = std::void_t<decltype(std::begin(std::declval<In>()))...>>
static void impl2 (Dune::PriorityTag<3>, Out& out, Op&& op, In const&... in)
{
impl3(std::begin(out), std::end(out), op, std::begin(in)...);
}
// ranges with static index access
template <class Out, class Op, class... In,
class = decltype(std::declval<Out>()[std::integral_constant<std::size_t,0>{}])>
static void impl2 (Dune::PriorityTag<2>, Out& out, Op&& op, In const&... in)
{
Ranges::forIndices<static_size_v<Out>>([&](auto ii) {
Recursive::transform(out[ii], op, in[ii]...);
});
}
// ranges with static getter access
template <class Out, class Op, class... In,
class = decltype(std::get<0>(std::declval<Out>()))>
static void impl2 (Dune::PriorityTag<1>, Out& out, Op&& op, In const&... in)
{
Ranges::forIndices<static_size_v<Out>>([&](auto ii) {
Recursive::transform(std::get<ii>(out), op, std::get<ii>(in)...);
});
}
// no range
template <class Out, class Op, class... In>
static void impl2 (Dune::PriorityTag<0>, Out& out, Op&& op, In const&... in)
{
out = op(in...);
}
public:
template <class Out, class Op, class... In>
static void impl (Out& out, Op&& op, In const&... in)
{
impl2(Dune::PriorityTag<5>{}, out, op, in...);
}
};
}} // end namespace AMDiS::Recursive
......@@ -25,8 +25,6 @@ install(FILES
Order.hpp
QuadMath.hpp
Range.hpp
RecursiveApply.hpp
RecursiveForEach.hpp
SharedPtr.hpp
StaticSize.hpp
String.hpp
......
......@@ -22,7 +22,8 @@ namespace AMDiS
(f(get<I>(tuple)),...);
}
template <class Tuple, class Functor>
template <class Tuple, class Functor,
class = decltype(std::get<0>(std::declval<Tuple>()))>
constexpr void forEach(Tuple&& tuple, Functor&& f)
{
Ranges::forEach(std::make_index_sequence<static_size_v<Tuple>>{}, FWD(tuple), FWD(f));
......
#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
......@@ -4,6 +4,7 @@
#include <dune/grid/utility/hierarchicsearch.hh>
#include <amdis/algorithm/Transform.hpp>
#include <amdis/functions/Interpolate.hpp>
#include <amdis/gridfunctions/GridFunction.hpp>
#include <amdis/linearalgebra/VectorFacade.hpp>
......@@ -44,10 +45,10 @@ void DiscreteFunction<C,GB,TP,R>::
VectorType_t<short,Coefficients> counter(basis);
AMDiS::interpolate(basis, coefficients(), gf, treePath, counter);