Belle II Software  release-06-02-00
group_helper.h
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #pragma once
9 #include <type_traits>
10 #include <unordered_map>
11 #include <algorithm>
12 #include <numeric>
13 #include <vector>
14 #include <tuple>
15 
16 namespace Belle2::group_helper {
17 
18  template <class _Ty>
19  using _Remove_cvref_t = std::remove_cv_t<std::remove_reference_t<_Ty>>;
20 
21 
22  template <typename T>
23  struct axis_name_t {
24  T m_value = T{};
25 
26  using my_type = T;
27  axis_name_t() = default;
28  explicit axis_name_t(T val) : m_value(val) {}
29 
30  operator T() const
31  {
32  return m_value;
33  }
34 
35  };
36 
37 
38 #define AXIS_NAME(name_, type_) \
39  struct name_; \
40  struct name_ : axis_name_t<type_> { \
41  name_(type_ val) : axis_name_t<type_>(val) {} \
42  template <typename... T1>\
43  name_(const std::tuple <T1...> & val) :name_( std::get<name_>(val)) {} \
44  name_() = default; \
45  template <typename T1> \
46  auto operator()(const T1& val){ \
47  m_value = std::get<name_>(val); \
48  return *this; \
49  } \
50  template <typename T1>\
51  auto operator==(const T1& rhs ) const -> decltype( std::get<name_>(rhs) == m_value ){\
52  return std::get<name_>(rhs) == m_value ;\
53  }\
54  };
55 
56 
57 
58 
59  template <typename T, typename... FUNC_T>
60  auto fill_vector(T& klmDigits, FUNC_T&& ... func)
61  {
62  std::vector<std::tuple< decltype(func(klmDigits[0]))... >> hits;
63  for (int i = 0; i < klmDigits.getEntries(); ++i) {
64  hits.emplace_back(func(klmDigits[i])...);
65  }
66  return hits;
67  }
68 
69 
70  template <typename T1, typename T2>
71  class __range__impl {
72 
73  public:
74 
75  __range__impl(T1&& b, T2&& e) : m_begin(b), m_end(e) {}
76  __range__impl(const T1& b, const T2& e) : m_begin(b), m_end(e) {}
77  auto begin() const
78  {
79  return m_begin;
80  }
81  auto back() const
82  {
83  return *(m_end - 1);
84  }
85  auto front() const
86  {
87  return *(m_begin);
88  }
89  auto end() const
90  {
91  return m_end;
92  }
93  auto operator[](size_t i) const
94  {
95  return *(m_begin + i);
96  }
97  size_t size() const
98  {
99  return m_end - m_begin;
100  }
101  T1 m_begin;
102  T2 m_end;
103 
104  };
105 
106 
107  template <typename T1, typename T2>
108  auto __range__(T1&& b, T2&& e)
109  {
110  return __range__impl< _Remove_cvref_t<T1>, _Remove_cvref_t<T2> >(std::forward<T1>(b), std::forward<T2>(e));
111  }
112 
113 
114  template <typename... T>
115  struct group {
116  template <typename VEC_T, typename T1, typename... T_rest>
117  static auto __isEequal(const VEC_T& vecA, const VEC_T& vecB) -> decltype(std::enable_if_t< (bool)sizeof...(T_rest), bool> {})
118  {
119  if (std::get<T1>(vecA) != std::get<T1>(vecB)) {
120  return false;
121  }
122  return __isEequal< VEC_T, T_rest...>(vecA, vecB);
123  }
124 
125 
126  template <typename VEC_T, typename T1>
127  static bool __isEequal(const VEC_T& vecA, const VEC_T& vecB)
128  {
129  return std::get<T1>(vecA) == std::get<T1>(vecB);
130  }
131 
132  template <typename VEC_T, typename... FUNC_T>
133  static auto apply(const std::vector<VEC_T>& vec, FUNC_T&& ... fun)
134  {
135 
136  std::vector< std::tuple<T..., decltype(fun(__range__(std::begin(vec), std::end(vec))))... >> ret;
137  if (vec.empty()) {
138  return ret;
139  }
140  auto tail = std::begin(vec);
141 
142  for (auto head = std::begin(vec); head != std::end(vec); ++head) {
143  if (!group<T...>::__isEequal<VEC_T, T...>(*head, *tail)) {
144 
145  ret.emplace_back(std::get<T>(*tail)..., fun(__range__(tail, head))...);
146  tail = head;
147  }
148  }
149 
150 
151  ret.emplace_back(std::get<T>(*tail)..., fun(__range__(tail, std::end(vec)))...);
152  return ret;
153  }
154 
155  template <typename A1 , typename... ARGGS>
156  struct __get_element {
157 
158  template<class ARRAY_T>
159  static constexpr auto has_safe_access(ARRAY_T&& arr) -> decltype(arr.at(0), std::true_type());
160  static constexpr auto has_safe_access(...)->std::false_type;
161 
162  template <class ARRAY_T>
163  static auto& get_safe_if_possible(ARRAY_T& arr, size_t i)
164  {
165  if constexpr(decltype(has_safe_access(arr))::value) {
166  return arr.at(i);
167  } else {
168  return arr[i];
169  }
170  }
171 
172 
173 
174  template <typename T1, typename T2>
175  static auto& get(const T1& e, T2& out_array)
176  {
177  if constexpr(sizeof...(ARGGS)) {
179  get_safe_if_possible(out_array, std::get<A1>(e))
180  );
181  } else {
182  return get_safe_if_possible(out_array, std::get<A1>(e));
183  }
184  }
185 
186  };
187 
188  template <typename T1, typename T2, typename T3, typename FUNC_T>
189  static auto to_array(const T2& in_array, T3& out_array, FUNC_T&& fun)
190  {
191  for (const auto& e : in_array) {
192  auto& x = __get_element<T...>::get(e, out_array);
193  x = fun(x, std::get<T1>(e));
194  }
195  }
196  template <typename T1, typename T2, typename T3>
197  static auto to_array(const T2& in_array, T3& out_array)
198  {
199  return to_array<T1>(in_array, out_array, std::plus());
200  }
201 
202  };
203 
204  template <typename CONTAINER_T, typename FUNC_T>
205  void erase_remove_if(CONTAINER_T& container, FUNC_T&& fun)
206  {
207  container.erase(
208  std::remove_if(container.begin(), container.end(),
209  std::forward<FUNC_T>(fun)),
210  container.end()
211  );
212  }
213 
214  template <typename CONTAINER_T>
215  void sort(CONTAINER_T& container)
216  {
217  std::sort(container.begin(), container.end());
218  }
219 
220  template <typename CONTAINER_T>
221  void drop_duplicates(CONTAINER_T& container)
222  {
223  container.erase(std::unique(container.begin(), container.end()), container.end());
224  }
225 
226  struct plus {
227  template<typename T, typename U>
228  constexpr auto operator()(T&& t, U&& u) const -> decltype((T&&) t + (U&&) u)
229  {
230  return (T&&) t + (U&&) u;
231  }
232  };
233 
234  template<typename T1 = int>
235  struct greater {
236  explicit greater(T1&& data) : m_data(data) {}
237  explicit greater(const T1& data) : m_data(data) {}
238  T1 m_data;
239 
240 
241  constexpr auto operator()(const T1& u) const
242  {
243  return m_data < u;
244  }
245  };
246 
247  template<typename T1>
248  struct greater_equal {
249  explicit greater_equal(T1 data) : m_data(data) {}
250 
251  T1 m_data;
252  template<typename U>
253  constexpr auto operator()(U&& u) const
254  {
255  return m_data <= (U&&) u;
256  }
257  };
258  struct identity {
259  template<typename T>
260  constexpr T&& operator()(T&& t) const noexcept
261  {
262  return (T&&) t;
263  }
264  };
265 
266 
267  template <typename CONTAINER_T, typename INIT_T, typename OP_T = plus, typename PROJECTION_T = identity>
268  auto accumulate(const CONTAINER_T& container, INIT_T init, OP_T op = plus {} , PROJECTION_T proj = identity{})
269  {
270  for (const auto& e : container)
271  init = op(init, proj(e));
272  return init;
273  }
274 
275  template <typename CONTAINER_T, typename OP_T = group_helper::greater<int>, typename PROJECTION_T = identity>
276  auto count_if(const CONTAINER_T& container, OP_T op = group_helper::greater<int> {0} , PROJECTION_T proj = identity{})
277  {
278  int i = 0;
279  for (const auto& e : container)
280  if (op(proj(e)))
281  ++i;
282  return i;
283  }
284 
285  template <typename CONTAINER_T, typename CONDITION_T, typename DEFAULT_T = int, typename PROJECTION_T = identity>
286  auto first_or_default(const CONTAINER_T& container, const CONDITION_T& con, DEFAULT_T default__ = 0,
287  PROJECTION_T proj = identity {})
288  {
289  decltype(proj(container[0])) ret = default__;
290  for (const auto& e : container) {
291  if (con == e) {
292  return proj(e);
293  }
294  }
295  return ret;
296  }
297 }