Belle II Software  release-08-01-10
SectoredLinearDivision.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 
10 #include <tracking/trackFindingCDC/utilities/Product.h>
11 
12 #include <framework/utilities/Utils.h>
13 
14 #include <utility>
15 #include <vector>
16 #include <cassert>
17 
18 namespace Belle2 {
23  namespace TrackFindingCDC {
24 
45  template<class ABox, std::size_t... divisions>
47 
48  public:
50  static const std::size_t s_nSubBoxes = Product<divisions...>::value;
51 
52  private:
54  static constexpr std::size_t s_divisions[sizeof...(divisions)] = {divisions...};
55 
56  public:
58  explicit SectoredLinearDivision(const typename ABox::Delta& overlaps = typename ABox::Delta(),
59  int sectorLevelSkip = 0)
60  : m_overlaps(overlaps)
61  , m_sectorLevelSkip(sectorLevelSkip)
62  {
63  }
64 
65  public:
67  template <class ANode>
68  std::vector<ABox> operator()(const ANode& node)
69  {
70  const ABox& box = node;
71  if (branch_unlikely(node.getLevel() == 0)) {
72  std::vector<ABox> result = makeSubBoxes(box, std::make_index_sequence<s_nSubBoxes>());
73  // Apply further divisions sectorLevelSkip times and return all boxes.
74  for (int iSkipped = 0; iSkipped < m_sectorLevelSkip; ++iSkipped) {
75  std::vector<ABox> sectoredBoxes;
76  sectoredBoxes.reserve(result.size() * s_nSubBoxes);
77  for (const ABox& boxToDivide : result) {
78  for (const ABox& dividedBox : makeSubBoxes(boxToDivide, std::make_index_sequence<s_nSubBoxes>())) {
79  sectoredBoxes.push_back(dividedBox);
80  }
81  }
82  result = std::move(sectoredBoxes);
83  }
84 
85  return result;
86  }
87  return makeSubBoxes(box, std::make_index_sequence<s_nSubBoxes>());
88  }
89 
91  template<std::size_t... Is>
92  std::vector<ABox>
93  makeSubBoxes(const ABox& box, std::index_sequence<Is...> /*globalSubBoxIndex*/)
94  {
95  return {{ makeSubBox(box, Is, std::make_index_sequence<sizeof...(divisions)>())... }};
96  }
97 
99  template <std::size_t... Is>
100  ABox makeSubBox(const ABox& box, std::size_t globalISubBox, std::index_sequence<Is...> /*coordinatesIndex*/)
101  {
102  std::array<std::size_t, sizeof...(divisions)> indices;
103  for (size_t c_Index = 0 ; c_Index < sizeof...(divisions); ++c_Index) {
104  indices[c_Index] = globalISubBox % s_divisions[c_Index];
105  globalISubBox /= s_divisions[c_Index];
106  }
107  assert(globalISubBox == 0);
108  return ABox(box.template getDivisionBoundsWithOverlap<Is>(std::get<Is>(m_overlaps),
109  s_divisions[Is],
110  indices[Is]) ...);
111  }
112 
113  private:
115  typename ABox::Delta m_overlaps;
116 
119  };
120 
121  // Extra mention of the constexpr such that it aquires external linkage.
122  template<class ABox, std::size_t... divisions>
123  constexpr std::size_t SectoredLinearDivision<ABox, divisions...>::s_divisions[sizeof...(divisions)];
124  }
126 }
Factory object that constructs sub boxes from a given box with optional overlaps.
std::vector< ABox > makeSubBoxes(const ABox &box, std::index_sequence< Is... >)
Make all subboxs with overlap of the given box.
std::vector< ABox > operator()(const ANode &node)
Factory method to construct the subboxes with overlap from the given box.
int m_sectorLevelSkip
Number of levels to be skipped to form the finer binning at level 1.
static constexpr std::size_t s_divisions[sizeof...(divisions)]
Array of the number of divisions for each dimension.
ABox makeSubBox(const ABox &box, std::size_t globalISubBox, std::index_sequence< Is... >)
Make the subbox with overlaps of the given box at global index.
static const std::size_t s_nSubBoxes
Number of sub boxes produced by this factory facility.
ABox::Delta m_overlaps
Custom overlaps of the bounds at each division for each dimension.
SectoredLinearDivision(const typename ABox::Delta &overlaps=typename ABox::Delta(), int sectorLevelSkip=0)
Initialise the sub box factory with specific overlaps.
#define branch_unlikely(x)
A macro to tell the compiler that the argument x will be very likely be false.
Definition: Utils.h:134
Abstract base class for different kinds of events.
Template class for compile time computation of products.
Definition: Product.h:21