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 
12 namespace AMDiS {
13 namespace Recursive {
14 
15 template <class>
16 struct InnerProduct;
17 
31 template <class In1, class In2, class T, class BinaryOp1, class BinaryOp2>
32 T 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 
48 template <class In1, class In2, class T>
49 T 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 
56 template <class>
57 struct InnerProduct
58 {
59 private:
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 
96 public:
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
Definition: AdaptBase.hpp:6
General implementation of recursive inner-product.
Definition: InnerProduct.hpp:16