AMDiS 2.10
The Adaptive Multi-Dimensional Simulation Toolbox
InnerProduct.hpp
1#pragma once
2
3#include <functional>
4#include <type_traits>
5#include <utility>
6#include <vector>
7
8#include <dune/common/typeutilities.hh>
9#include <amdis/common/ForEach.hpp>
10#include <amdis/common/StaticSize.hpp>
11
12namespace AMDiS {
13namespace Recursive {
14
15template <class>
16struct InnerProduct;
17
31template <class In1, class In2, class T, class BinaryOp1, class BinaryOp2>
32T innerProduct (In1 const& in1, In2 const& in2, T init, BinaryOp1 op1, BinaryOp2 op2)
33{
34 return InnerProduct<In1>::impl(in1, in2, std::move(init), op1, op2);
35}
36
39
48template <class In1, class In2, class T>
49T innerProduct (In1 const& in1, In2 const& in2, T init)
50{
51 return InnerProduct<In1>::impl(in1, in2, std::move(init), std::plus<>{}, std::multiplies<>{});
52}
53
54
56template <class>
58{
59private:
60 // dynamic ranges
61 template <class In1, class In2, class T, class BinOp1, class BinOp2,
62 class = decltype(std::begin(std::declval<In1>())),
63 class = decltype(std::end(std::declval<In1>())),
64 class = decltype(std::begin(std::declval<In2>()))>
65 static T impl2 (Dune::PriorityTag<2>, In1 const& in1, In2 const& in2, T init,
66 BinOp1 op1, BinOp2 op2)
67 {
68 auto first1 = std::begin(in1);
69 auto first2 = std::begin(in2);
70 for (; first1 != std::end(in1); ++first1, ++first2)
71 init = Recursive::innerProduct(*first1, *first2, std::move(init), op1, op2);
72 return init;
73 }
74
75 // ranges with static index access
76 template <class In1, class In2, class T, class BinOp1, class BinOp2,
77 class = decltype(std::declval<In1>()[std::integral_constant<std::size_t,0>{}])>
78 static T impl2 (Dune::PriorityTag<1>, In1 const& in1, In2 const& in2, T init,
79 BinOp1 op1, BinOp2 op2)
80 {
81 static_assert(static_size_v<In1> == static_size_v<In2>);
82 Ranges::forIndices<static_size_v<In1>>([&](auto ii) {
83 init = Recursive::innerProduct(in1[ii], in2[ii], std::move(init), op1, op2);
84 });
85 return init;
86 }
87
88 // no range
89 template <class In1, class In2, class T, class BinOp1, class BinOp2>
90 static T impl2 (Dune::PriorityTag<0>, In1 const& in1, In2 const& in2, T init,
91 BinOp1 op1, BinOp2 op2)
92 {
93 return op1(std::move(init), op2(in1, in2));
94 }
95
96public:
97 template <class In1, class In2, class T, class BinOp1, class BinOp2>
98 static T impl (In1 const& in1, In2 const& in2, T init, BinOp1 op1, BinOp2 op2)
99 {
100 return impl2(Dune::PriorityTag<5>{}, in1, in2, init, op1, op2);
101 }
102};
103
104}} // end namespace AMDiS::Recursive
General implementation of recursive inner-product.
Definition: InnerProduct.hpp:58