Belle II Software  release-08-01-10
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 
9 #ifndef group_helper_h
10 #define group_helper_h
11 
12 #include <algorithm>
13 #include <cstdint>
14 #include <iostream>
15 #include <numeric>
16 #include <tuple>
17 #include <type_traits>
18 #include <unordered_map>
19 #include <vector>
20 
21 #define let const auto
22 #define letref const auto&
23 
24 
25 
26 
27 namespace Belle2 {
32  namespace group_helper {
33 
34 
35  template <auto Start, auto End, auto Inc, class F>
36  constexpr void constexpr_for(F&& f)
37  {
38  if constexpr(Start < End) {
39  f(std::integral_constant<decltype(Start), Start>());
40  constexpr_for < Start + Inc, End, Inc > (f);
41  }
42  }
43 
44  inline std::string root_type_name(int)
45  {
46  return "I";
47  }
48 
49  inline std::string root_type_name(double)
50  {
51  return "D";
52  }
53  inline std::string root_type_name(float)
54  {
55  return "F";
56  }
57  inline std::string root_type_name(int64_t)
58  {
59  return "L";
60  }
61  inline std::string root_type_name(uint64_t)
62  {
63  return "l";
64  }
65 
66 
67 
68 
69 
70 
71 
72 
73 
74 
75 #define AXIS_NAME1(name_, type_, name_str) \
76  namespace name_##_impl_{\
77  struct name_##_; \
78  struct name_##_ { \
79  type_ name_ = type_{}; \
80  constexpr explicit name_##_(type_ val) : name_ (val) {} \
81  template <typename... T1>\
82  constexpr explicit name_##_(const std::tuple <T1...> & val) : name_ ( std::get<name_##_>(val)) {} \
83  constexpr name_##_() = default; \
84  template <typename... T1> \
85  auto operator()(const std::tuple<T1...>& val) const{ \
86  return std::get<name_##_>(val); \
87  } \
88  constexpr operator type_() const {\
89  return name_ ; \
90  } \
91  constexpr type_ value() const {\
92  return name_ ; \
93  } \
94  template <typename... T1>\
95  auto operator==(const std::tuple<T1...>& rhs ) const -> decltype( std::get<name_##_>(rhs) == name_ ){\
96  return std::get<name_##_>(rhs) == name_ ;\
97  }\
98  friend inline std::string __get__name__(const name_##_&){ return name_str ;}\
99  friend inline std::string __get__name__and_type(const name_##_&){ return std::string(name_str) +"/"+ Belle2::group_helper::root_type_name(type_());}\
100  friend inline std::ostream& operator<<(std::ostream& out, const name_##_ & element ){ out << __get__name__(element) << ": "<< element.value() ; return out; }\
101  };}\
102  using name_ = name_##_impl_::name_##_
103 
104 
105 
106 #define AXIS_NAME(name_, type_) AXIS_NAME1(name_, type_, #name_ )
107 
108 
109  namespace group_helper_imple__ {
110  template <int N>
111  struct print_s {
112  template <typename T >
113  static void print_name(std::ostream& out, const T& tup)
114  {
115  if constexpr(N < std::tuple_size<T> ()) {
116  out << "| " << __get__name__(std::get<N>(tup)) << " ";
118  } else {
119  out << "|";
120  }
121  }
122  template <typename T, typename FUNC_T>
123  static void print(std::ostream& out, const T& tup, const FUNC_T& fun)
124  {
125  if constexpr(N < std::tuple_size<T> ()) {
126  out << "| " << fun(std::get<N>(tup)) << " ";
127  print_s < N + 1 >::print(out, tup, fun);
128  } else {
129  out << "|";
130  }
131 
132 
133  }
134  };
135 
136  }
137 
138  template <typename... ARGS>
139  std::ostream& operator<<(std::ostream& out, const std::tuple<ARGS...>& tup)
140  {
141  group_helper_imple__::print_s<0>::print(out, tup, [](const auto & e) { return e;});
142  return out;
143  }
144 
145  template <typename... ARGS>
146  std::ostream& operator<<(std::ostream& out, const std::vector<std::tuple<ARGS...>>& vec)
147  {
148  decltype(vec[0]) header{};
149  group_helper_imple__::print_s<0>::print_name(out, header);
150  out << "\n";
151  for (const auto& ele : vec) {
152  group_helper_imple__::print_s<0>::print(out, ele, [](const auto & e) { return e.value() ;});
153  out << "\n";
154  }
155 
156  return out;
157  }
158 
159 
160 
161 
162  template<typename T, typename... Ts>
163  constexpr bool contains()
164  {
165  return std::disjunction_v<std::is_same<T, Ts>...>;
166  }
167 
168  template <typename T, typename Tuple>
169  struct has_type;
170 
171  template <typename T, typename... Us>
172  struct has_type<T, std::tuple<Us...>> : std::disjunction<std::is_same<T, Us>...> {};
173 
174  template <typename> struct is_tuple: std::false_type {};
175 
176  template <typename ...T> struct is_tuple<std::tuple<T...>>: std::true_type {};
177 
178 
179  template <class _Ty>
180  using _Remove_cvref_t = std::remove_cv_t<std::remove_reference_t<_Ty>>;
181 
182 
183  template <typename FUNC_T>
184  auto fill_vector(size_t entries, FUNC_T&& func)
185  {
186  std::vector< decltype(func(size_t(0))) > ret ;
187  ret.reserve(entries);
188  for (size_t i = 0; i < entries; ++i) {
189  ret.emplace_back(func(i));
190  }
191  return ret;
192  }
193 
194  struct identity {
195  template<typename T>
196  constexpr T&& operator()(T&& t) const noexcept
197  {
198  return (T&&)t;
199  }
200  };
201 
202  template <typename T1, typename T2, typename Prj_T = identity>
204  __range__impl_prj(T1&& b, T2&& e, Prj_T&& prj = identity{}) : m_begin(std::move(b), prj), m_end(std::move(e), prj) {}
205  __range__impl_prj(const T1& b, const T2& e, Prj_T&& prj = identity{}) : m_begin(b, prj), m_end(e, prj) {}
206  auto begin() const
207  {
208  return m_begin;
209  }
210  auto back() const
211  {
212  return m_end.m_prj(*(m_end.get_base() - 1));
213  }
214  auto front() const
215  {
216  return *(m_begin);
217  }
218  auto end() const
219  {
220  return m_end;
221  }
222  auto operator[](size_t i) const
223  {
224  return m_begin.m_prj(*(m_begin.get_base() + i));
225  }
226 
227  size_t size() const
228  {
229  return m_end - m_begin;
230  }
231  struct begin_t : T1 {
232  begin_t(T1&& t1, Prj_T& pro) : T1(std::move(t1)), m_prj(pro) {}
233  begin_t(const T1& t1, Prj_T& pro) : T1(t1), m_prj(pro) {}
234  Prj_T m_prj;
235  auto operator*() const
236  {
237  return m_prj(**((const T1*)this));
238  }
239  T1 get_base() const
240  {
241  return *((const T1*)this);
242  }
243  } m_begin, m_end;
244 
245 
246  };
247 
248  template <typename T1, typename T2>
249  auto __range__(T1&& b, T2&& e)
250  {
251  return __range__impl_prj< _Remove_cvref_t<T1>, _Remove_cvref_t<T2> >(std::forward<T1>(b), std::forward<T2>(e), {});
252  }
253  template <typename T1, typename T2, typename PRJ>
254  auto __range__(T1&& b, T2&& e, PRJ&& prj)
255  {
256  return __range__impl_prj< _Remove_cvref_t<T1>, _Remove_cvref_t<T2>, _Remove_cvref_t<PRJ> >(std::forward<T1>(b), std::forward<T2>(e),
257  std::forward<PRJ>(prj));
258  }
259 
260  template <typename PRJ, typename VEC_T>
261  auto project(VEC_T&& vec)
262  {
263  return __range__(vec.begin(), vec.end(), [](const auto & e) { return std::get<PRJ>(e); });
264  }
265  template <typename VEC_T, typename PRJ>
266  auto project(VEC_T&& vec, PRJ&& prj)
267  {
268  return __range__(vec.begin(), vec.end(), std::forward<PRJ>(prj));
269  }
270 
271 
272  template <typename T1, typename T2, typename PRJ, typename OP>
273  auto operator|(__range__impl_prj<T1, T2, PRJ> r, OP op)
274  {
275  return __range__(r.begin(), r.end(), std::move(op));
276  }
277 
278 
279 
280  struct to_range_ {
281  template <typename T>
282  friend auto operator|(T&& t, const to_range_&)
283  {
284  return __range__(t.begin(), t.end());
285  }
286 
287  template <typename T>
288  friend auto operator|(const T& t, const to_range_&)
289  {
290  return __range__(t.begin(), t.end());
291  }
292  };
293  constexpr const to_range_ to_range;
294  /*
295  template <typename T1, typename T2>
296  auto __range__(T1&& b, T2&& e)
297  {
298  return __range__impl< _Remove_cvref_t<T1>, _Remove_cvref_t<T2> >(std::forward<T1>(b), std::forward<T2>(e));
299  }
300  */
301  template <typename... T>
302  struct group {
303 
304  template <typename VEC_T, typename T1, typename... T_rest>
305  static auto __isEequal(const VEC_T& vecA, const VEC_T& vecB)
306  {
307  if constexpr(sizeof...(T_rest) > 0) {
308  if (std::get<T1>(vecA) != std::get<T1>(vecB)) {
309  return false;
310  }
311  return __isEequal< VEC_T, T_rest...>(vecA, vecB);
312  } else {
313  return std::get<T1>(vecA) == std::get<T1>(vecB);
314  }
315  }
316 
317  template <typename VEC_T, typename T1, typename... T_rest>
318  static auto __isLessthen(const VEC_T& vecA, const VEC_T& vecB)
319  {
320  if constexpr(sizeof...(T_rest) > 0) {
321  if (std::get<T1>(vecA) < std::get<T1>(vecB)) {
322  return true;
323  } else if (std::get<T1>(vecA) > std::get<T1>(vecB)) {
324  return false;
325  }
326  return __isLessthen< VEC_T, T_rest...>(vecA, vecB);
327  } else {
328  return std::get<T1>(vecA) < std::get<T1>(vecB);
329  }
330  }
331 
332 
333 
334  template <typename VEC_T, typename... FUNC_T>
335  static auto __apply__list__(const std::vector<VEC_T>& vec, FUNC_T&& ... fun)
336  {
337 
338  auto is_sorted_ = std::is_sorted(std::begin(vec), std::end(vec), [](const auto & lhs, const auto & rhs) {
339  return group<T...>::__isLessthen<VEC_T, T...>(lhs, rhs);
340  });
341 
342  if (!is_sorted_) {
343  throw std::runtime_error("group::apply expects the input vector to be sorted according to the group parameters\nthe input vector was not sorted with respect to the group axis");
344  }
345 
346 
347  std::vector< std::tuple<T..., decltype(fun(__range__(std::begin(vec), std::end(vec))))... >> ret;
348  if (vec.empty()) {
349  return ret;
350  }
351  auto tail = std::begin(vec);
352 
353  for (auto head = std::begin(vec); head != std::end(vec); ++head) {
354  if (!group<T...>::__isEequal<VEC_T, T...>(*head, *tail)) {
355 
356  ret.emplace_back(std::get<T>(*tail)..., fun(__range__(tail, head))...);
357  tail = head;
358  }
359  }
360 
361 
362  ret.emplace_back(std::get<T>(*tail)..., fun(__range__(tail, std::end(vec)))...);
363  return ret;
364  }
365 
366  template <typename VEC_T, typename FUNC_T>
367  static auto __apply__tuple__(const std::vector<VEC_T>& vec, FUNC_T&& fun)
368  {
369 
370  auto is_sorted_ = std::is_sorted(std::begin(vec), std::end(vec), [](const auto & lhs, const auto & rhs) {
371  return group<T...>::__isLessthen<VEC_T, T...>(lhs, rhs);
372  });
373 
374  if (!is_sorted_) {
375  throw std::runtime_error("group::apply1 expects the input vector to be sorted according to the group parameters\nthe input vector was not sorted with respect to the group axis");
376  }
377 
378  std::vector <
379  decltype(
380  tuple_cat(
381  std::make_tuple(std::get<T>(*vec.begin())...),
382  fun(__range__(std::begin(vec), std::end(vec)))
383  )
384  )
385  > ret;
386  if (vec.empty()) {
387  return ret;
388  }
389  auto tail = std::begin(vec);
390 
391  for (auto head = std::begin(vec); head != std::end(vec); ++head) {
392  if (!group<T...>::__isEequal<VEC_T, T...>(*head, *tail)) {
393 
394 
395  auto t = tuple_cat(
396  std::make_tuple(std::get<T>(*tail)...),
397  fun(__range__(tail, head))
398  );
399 
400  ret.push_back(t);
401  tail = head;
402  }
403  }
404  ret.push_back(tuple_cat(std::make_tuple(std::get<T>(*tail)...), fun(__range__(tail, std::end(vec)))));
405  return ret;
406  }
407 
408  template <typename VEC_T, typename FUNC_T>
409  static auto __apply__one_argument__(const std::vector<VEC_T>& vec, FUNC_T&& fun)
410  {
411  if constexpr(is_tuple< decltype(fun(__range__(std::begin(vec), std::end(vec))))>::value) {
412  return __apply__tuple__(vec, std::forward<FUNC_T>(fun));
413  } else {
414  return __apply__list__(vec, std::forward<FUNC_T>(fun));
415  }
416 
417  }
418 
419  template <typename VEC_T, typename... FUNC_T>
420  static auto apply(const std::vector<VEC_T>& vec, FUNC_T&& ... fun)
421  {
422  if constexpr(sizeof...(FUNC_T) > 1) {
423  return __apply__list__(vec, std::forward<FUNC_T>(fun)...);
424  } else {
425 
426  return __apply__one_argument__(vec, std::forward<FUNC_T>(fun)...);
427  }
428 
429  }
430  };
431 
432  template <typename CONTAINER_T, typename FUNC_T>
433  void erase_remove_if(CONTAINER_T& container, FUNC_T&& fun)
434  {
435  container.erase(
436  std::remove_if(container.begin(), container.end(),
437  std::forward<FUNC_T>(fun)),
438  container.end()
439  );
440  }
441 
442  template <typename CONTAINER_T>
443  void sort(CONTAINER_T& container)
444  {
445  std::sort(container.begin(), container.end());
446  }
447 
448  template <typename CONTAINER_T>
449  void drop_duplicates(CONTAINER_T& container)
450  {
451  container.erase(std::unique(container.begin(), container.end()), container.end());
452  }
453 
454 
455 
456  template <typename CONTAINER_T, typename T1>
457  bool contains(const CONTAINER_T& container, T1&& value)
458  {
459  return std::find(container.begin(), container.end(), value) != container.end();
460  }
461 
462 
463  template<typename T1 = int>
464  struct greater {
465  explicit greater(T1&& data) : m_data(data) {}
466  explicit greater(const T1& data) : m_data(data) {}
467  T1 m_data;
468 
469 
470  constexpr auto operator()(const T1& u) const
471  {
472  return m_data < u;
473  }
474  };
475 
476 
477 
478 
479 
480 
481 
482  template <typename CONTAINER_T, typename OP_T = group_helper::greater<int>>
483  auto count_if(const CONTAINER_T& container, OP_T op = group_helper::greater<int> { 0 })
484  {
485  int i = 0;
486  for (const auto& e : container)
487  if (op(e))
488  ++i;
489  return i;
490  }
491 
492 
493  template <typename CONTAINER_T, typename CONDITION_T>
494  auto get_first(const CONTAINER_T& container, const CONDITION_T& con)
495  {
496 
497  for (const auto& e : container) {
498  if (con == e)
499  return e;
500 
501  }
502  static decltype(container[0]) ret{};
503  return ret;
504  }
505 
506 
507 
508 
509 
510 
511  namespace comparators {
512 
513 
514 
515 
516 
518 
519 
520  template <typename T1, typename T2>
521  constexpr static bool __comp__(T1&& t1, T2&& t2)
522  {
523  bool ret = true;
524  constexpr_for<0, std::tuple_size<_Remove_cvref_t<T1> >::value, 1>(
525  [&](const auto i) {
526  using N_th_T = _Remove_cvref_t < decltype(std::get<i>(t1))>;
527  if constexpr(has_type<N_th_T, _Remove_cvref_t<T2>>::value) {
528  ret &= (std::get<N_th_T>(t1) == std::get<N_th_T>(t2));
529  }
530  }
531  );
532  return ret;
533 
534  }
535 
536 
537  template <typename T1, typename T2>
538  constexpr bool operator()(T1&& t1, T2&& t2) const
539  {
540  return __comp__(std::forward<T1>(t1), std::forward<T2>(t2));
541  }
542  };
543  constexpr on_common_args_t on_common_args;
544  }
545 
546 
547  template <typename T0, typename T1, typename T2, typename Comparision_T, typename projecttion_t >
548  void vec_join_r(T0& ret, const T1& t1, const T2& t2, Comparision_T comp, projecttion_t project)
549  {
550  ret.clear();
551  for (const auto& e1 : t1) {
552  for (const auto& e2 : t2) {
553  if (comp(e1, e2)) {
554  ret.push_back(project(e1, e2));
555  }
556  }
557  }
558 
559  }
560 
561  template <typename T1, typename T2, typename Comparision_T, typename projecttion_t >
562  auto vec_join(const T1& t1, const T2& t2, Comparision_T comp, projecttion_t project)
563  {
564  std::vector< decltype(project(t1[0], t2[0])) > ret;
565  vec_join_r(ret, t1, t2, comp, project);
566  return ret;
567  }
568 
569  }
571 }
572 
573 #endif
std::ostream & operator<<(std::ostream &output, const IntervalOfValidity &iov)
Abstract base class for different kinds of events.