Belle II Software  release-06-00-14
Box.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/EvalVariadic.h>
11 
12 #include <type_traits>
13 #include <utility>
14 #include <array>
15 #include <cassert>
16 #include <numeric>
17 #include <ostream>
18 
19 namespace Belle2 {
24  namespace TrackFindingCDC {
25 
32  template<class... ATypes>
33  class Box;
34 
39  template<>
40  class Box<> {
41  public:
43  void setBounds()
44  {
45  }
46 
48  friend std::ostream& operator<<(std::ostream& output, const Box<>& voidBox __attribute__((unused)))
49  {
50  return output;
51  }
52  };
53 
61  template<class AFirstType, class... ASubordinaryTypes>
62  class Box<AFirstType, ASubordinaryTypes...> {
63  public:
65  using FirstType = AFirstType;
66 
68  using This = Box<AFirstType, ASubordinaryTypes...>;
69 
71  using Point = std::tuple<FirstType, ASubordinaryTypes...>;
72 
74  using Delta = std::tuple < decltype(FirstType() - FirstType()),
75  decltype(ASubordinaryTypes() - ASubordinaryTypes())... >;
76 
78  template<std::size_t I>
79  using Type = typename std::tuple_element<I, Point>::type;
80 
82  template<class T>
84 
86  template<class T>
87  using HasType = TypeInTuple<T, Point>;
88 
90  template<std::size_t I>
91  using Width = typename std::tuple_element<I, Delta>::type;
92 
94  static const size_t c_nTypes = std::tuple_size<Point>::value;
95 
97  using Indices = std::make_index_sequence<c_nTypes>;
98 
100  Box(const std::array<FirstType, 2>& firstBound,
101  const std::array<ASubordinaryTypes, 2>& ... subordinaryBounds)
102  : m_firstBounds{{
103  std::min(firstBound[0], firstBound[1]),
104  std::max(firstBound[1], firstBound[0])}}
105  , m_subordinaryBox(subordinaryBounds...)
106  {
107  }
108 
110  friend std::ostream& operator<<(std::ostream& output, const This& box)
111  {
112  return output <<
113  "Range from " << box.m_firstBounds[0] <<
114  " to " << box.m_firstBounds[1] << std::endl <<
115  box.getSubordinaryBox();
116  }
117 
119  void setBounds(std::array<FirstType, 2> firstBounds,
120  std::array<ASubordinaryTypes, 2>... subordinaryBounds)
121  {
122  m_firstBounds[0] = std::min(firstBounds[0], firstBounds[1]);
123  m_firstBounds[1] = std::max(firstBounds[0], firstBounds[1]);
124  m_subordinaryBox.setBounds(subordinaryBounds...);
125  }
126 
128  const Box<ASubordinaryTypes...>& getSubordinaryBox() const
129  {
130  return m_subordinaryBox;
131  }
132 
134  template<std::size_t I>
135  const std::enable_if_t<I == 0, Type<I> >& getLowerBound() const
136  {
137  return m_firstBounds[0];
138  }
139 
141  template<std::size_t I>
142  const std::enable_if_t < I != 0, Type<I> > & getLowerBound() const
143  {
144  static_assert(I < c_nTypes,
145  "Accessed index exceeds number of coordinates");
146  return m_subordinaryBox.template getLowerBound < I - 1 > ();
147  }
148 
150  template <class T>
151  const std::enable_if_t<HasType<T>::value, T>& getLowerBound() const
152  {
153  return getLowerBound<TypeIndex<T>::value>();
154  }
155 
157  template <std::size_t I>
158  const std::enable_if_t<I == 0, Type<I>>& getUpperBound() const
159  {
160  return m_firstBounds[1];
161  }
162 
164  template<std::size_t I>
165  const std::enable_if_t < I != 0, Type<I> > & getUpperBound() const
166  {
167  static_assert(I < c_nTypes,
168  "Accessed index exceeds number of coordinates");
169  return m_subordinaryBox.template getUpperBound < I - 1 > ();
170  }
171 
173  template <class T>
174  const std::enable_if_t<HasType<T>::value, T>& getUpperBound() const
175  {
176  return getUpperBound<TypeIndex<T>::value>();
177  }
178 
180  template <std::size_t I>
181  const std::enable_if_t<I == 0, std::array<Type<I>, 2>>& getBounds() const
182  {
183  return m_firstBounds;
184  }
185 
187  template <std::size_t I>
188  const std::enable_if_t < I != 0, std::array<Type<I>, 2 >>& getBounds() const
189  {
190  static_assert(I < c_nTypes, "Accessed index exceeds number of coordinates");
191  return m_subordinaryBox.template getBounds < I - 1 > ();
192  }
193 
195  template <class T>
196  const std::enable_if_t<HasType<T>::value, std::array<T, 2>>& getBounds() const
197  {
198  return getBounds<TypeIndex<T>::value>();
199  }
200 
202  template <std::size_t I>
204  {
205  return getUpperBound<I>() - getLowerBound<I>();
206  }
207 
208  public:
210  template<std::size_t I>
211  Type<I> getDivision(size_t nDivisions, size_t iDivision) const
212  {
213  assert(nDivisions >= iDivision);
214  return Type<I>(getLowerBound<I>() + getWidth<I>() * iDivision / nDivisions);
215  }
216 
218  template<std::size_t I>
219  std::array<Type<I>, 2 >
220  getDivisionBounds(size_t nDivisions, size_t iDivision) const
221  {
222  assert(nDivisions > iDivision);
223  return {{getDivision<I>(nDivisions, iDivision), getDivision<I>(nDivisions, iDivision + 1)}};
224  }
225 
227  template <std::size_t I>
228  Width<I> getDivisionWidthWithOverlap(const Width<I>& overlap, size_t nDivisions) const
229  {
230  return (getWidth<I>() + (nDivisions - 1) * overlap) / nDivisions;
231  }
232 
246  template<std::size_t I>
247  Type<I>
249  size_t nDivisions,
250  size_t iDivision) const
251  {
252  assert(nDivisions >= iDivision);
253  return Type<I>(getLowerBound<I>() + (getWidth<I>() - overlap) * iDivision / nDivisions);
254  }
255 
269  template<std::size_t I>
270  Type<I>
272  size_t nDivisions,
273  size_t iDivision) const
274  {
275  assert(nDivisions >= iDivision);
276  return Type<I>(getUpperBound<I>() - (getWidth<I>() - overlap) * (nDivisions - iDivision - 1) / nDivisions);
277  }
278 
279 
293  template<std::size_t I>
294  std::array<Type<I>, 2 >
296  size_t nDivisions,
297  size_t iDivision) const
298  {
299  assert(nDivisions > iDivision);
300  return {{
301  getLowerDivisionBoundWithOverlap<I>(overlap, nDivisions, iDivision),
302  getUpperDivisionBoundWithOverlap<I>(overlap, nDivisions, iDivision)
303  }};
304  }
305 
307  template <std::size_t I>
309  {
310  return getDivision<I>(2, 1);
311  }
312 
314  template <std::size_t I>
315  std::array<Type<I>, 2> getLowerHalfBounds() const
316  {
317  return getDivisionBounds(2, 0);
318  }
319 
321  template <std::size_t I>
322  std::array<Type<I>, 2> getUpperHalfBounds() const
323  {
324  return getDivisionBounds(2, 1);
325  }
326 
328  template <std::size_t I, class ASubordinaryValue>
329  bool isIn(const ASubordinaryValue& value) const
330  {
331  return getLowerBound<I>() < value and not(getUpperBound<I>() < value);
332  }
333 
334  private:
336  static bool any(const std::initializer_list<bool>& booleans)
337  {
338  return std::accumulate(std::begin(booleans), std::end(booleans),
339  false, [](const bool & lhs, const bool & rhs) {return lhs or rhs;});
340 
341  }
342 
344  static bool all(const std::initializer_list<bool>& booleans)
345  {
346  return std::accumulate(std::begin(booleans), std::end(booleans),
347  true, [](const bool & lhs, const bool & rhs) {return lhs and rhs;});
348  }
349 
359  template <size_t... Is>
360  bool intersectsImpl(const This& box,
361  std::index_sequence<Is...> is __attribute__((unused))) const
362  {
363  return not(any({box.getUpperBound<Is>() < this->getLowerBound<Is>()... }) or
364  any({this->getUpperBound<Is>() < box.getLowerBound<Is>()... }));
365  }
366 
371  template <size_t... Is>
372  bool isInImpl(const Point& point,
373  std::index_sequence<Is...> is __attribute__((unused))) const
374  {
375  return not all({isIn<Is>(std::get<Is>(point))...});
376  }
377 
378  public:
380  bool intersects(const This& box) const
381  {
382  return intersectsImpl(box, Indices());
383  }
384 
386  bool isIn(const Point& point) const
387  {
388  return isInImpl(point, Indices());
389  }
390 
392  bool isIn(const FirstType& value, const ASubordinaryTypes& ... values) const
393  {
394  return isInImpl(Point(value, values...), Indices());
395  }
396 
397  private:
399  std::array<FirstType, 2> m_firstBounds;
400 
402  Box<ASubordinaryTypes... > m_subordinaryBox;
403  };
404 
405  }
407 }
Box Base class specification without a first and subordinary types which can be used to "stack" vario...
Definition: Box.h:62
const std::enable_if_t< I !=0, std::array< Type< I >, 2 > > & getBounds() const
Get the bounds of the box in the coordinate I - subordinary coordinate case.
Definition: Box.h:188
AFirstType FirstType
Type of the first coordinate.
Definition: Box.h:65
std::array< Type< I >, 2 > getDivisionBoundsWithOverlap(const Width< I > &overlap, size_t nDivisions, size_t iDivision) const
Getter for the both bounds of a subbox along the Ith axes in an equal spaced division with overlap.
Definition: Box.h:295
const Box< ASubordinaryTypes... > & getSubordinaryBox() const
Getter for the box in excluding the first coordinate.
Definition: Box.h:128
Type< I > getLowerDivisionBoundWithOverlap(const Width< I > &overlap, size_t nDivisions, size_t iDivision) const
Getter for the lower bound of a subbox along the Ith axes in an equal spaced division with overlap.
Definition: Box.h:248
bool intersectsImpl(const This &box, std::index_sequence< Is... > is) const
Indicates if this box intersects with the other box.
Definition: Box.h:360
const std::enable_if_t< HasType< T >::value, std::array< T, 2 > > & getBounds() const
Get the bounds of the box by the type of the coordinate.
Definition: Box.h:196
TypeInTuple< T, Point > HasType
Check if the type is a coordinate of the box which amounts to a std::integral_constant.
Definition: Box.h:87
const std::enable_if_t< I !=0, Type< I > > & getLowerBound() const
Get the lower bound of the box in the coordinate I - subordinary coordinate case.
Definition: Box.h:142
bool isIn(const ASubordinaryValue &value) const
Indicate if the given value is in the range of the coordinate I.
Definition: Box.h:329
Type< I > getDivision(size_t nDivisions, size_t iDivision) const
Get for break point in the range of coordinate I out of nDivsions equal spaced points.
Definition: Box.h:211
const std::enable_if_t< I==0, std::array< Type< I >, 2 > > & getBounds() const
Get the bounds of the box in the coordinate I - first coordinate case.
Definition: Box.h:181
const std::enable_if_t< I==0, Type< I > > & getUpperBound() const
Get the upper bound of the box in the coordinate I.
Definition: Box.h:158
typename std::tuple_element< I, Delta >::type Width
Accessor for the individual coordinate difference types.
Definition: Box.h:91
static bool all(const std::initializer_list< bool > &booleans)
Indicates if all of the boolean values are true.
Definition: Box.h:344
std::tuple< decltype(FirstType() - FirstType()), decltype(ASubordinaryTypes() - ASubordinaryTypes())... > Delta
Tuple of differencs in each coordinate.
Definition: Box.h:75
std::array< FirstType, 2 > m_firstBounds
Bound in the first coordindate.
Definition: Box.h:399
std::array< Type< I >, 2 > getUpperHalfBounds() const
Get the upper partition in the coordinate I.
Definition: Box.h:322
Type< I > getUpperDivisionBoundWithOverlap(const Width< I > &overlap, size_t nDivisions, size_t iDivision) const
Getter for the upper bound of a subbox along the Ith axes in an equal spaced division with overlap.
Definition: Box.h:271
bool isIn(const Point &point) const
Indicate if all given values are in the range of their coordinates.
Definition: Box.h:386
static bool any(const std::initializer_list< bool > &booleans)
Indicates if any of the boolean values is true.
Definition: Box.h:336
std::make_index_sequence< c_nTypes > Indices
Helper class to iterate over the individual coordinates.
Definition: Box.h:97
Width< I > getWidth() const
Get the difference of upper and lower bound.
Definition: Box.h:203
bool isInImpl(const Point &point, std::index_sequence< Is... > is) const
Indicate if all given values are in the range of their coordinates.
Definition: Box.h:372
std::tuple< FirstType, ASubordinaryTypes... > Point
Tuple of the types of each coordinates.
Definition: Box.h:71
Box(const std::array< FirstType, 2 > &firstBound, const std::array< ASubordinaryTypes, 2 > &... subordinaryBounds)
Initialise the box with bound in each dimension.
Definition: Box.h:100
bool isIn(const FirstType &value, const ASubordinaryTypes &... values) const
Indicate if all given values are in the range of their coordinates.
Definition: Box.h:392
const std::enable_if_t< I !=0, Type< I > > & getUpperBound() const
Get the lower bound of the box in the coordinate I - subordinary coordinate case.
Definition: Box.h:165
Box< ASubordinaryTypes... > m_subordinaryBox
Box in the other coordinate.
Definition: Box.h:402
const std::enable_if_t< HasType< T >::value, T > & getLowerBound() const
Get the lower bound of the box by the type of the coordinate.
Definition: Box.h:151
const std::enable_if_t< I==0, Type< I > > & getLowerBound() const
Get the lower bound of the box in the coordinate I - first coordinate case.
Definition: Box.h:135
void setBounds(std::array< FirstType, 2 > firstBounds, std::array< ASubordinaryTypes, 2 >... subordinaryBounds)
Set bounds of the box to new values.
Definition: Box.h:119
friend std::ostream & operator<<(std::ostream &output, const This &box)
Output operator for debugging.
Definition: Box.h:110
typename std::tuple_element< I, Point >::type Type
Accessor for the individual coordinate types.
Definition: Box.h:79
Width< I > getDivisionWidthWithOverlap(const Width< I > &overlap, size_t nDivisions) const
Get for the distance between two division bounds with overlap.
Definition: Box.h:228
std::array< Type< I >, 2 > getDivisionBounds(size_t nDivisions, size_t iDivision) const
Get the lower partition in the coordinate I.
Definition: Box.h:220
bool intersects(const This &box) const
Indicates if this box intersects with the other box.
Definition: Box.h:380
std::array< Type< I >, 2 > getLowerHalfBounds() const
Get the lower partition in the coordinate I.
Definition: Box.h:315
Type< I > getCenter() const
Get the center of the box in the coordinate I.
Definition: Box.h:308
const std::enable_if_t< HasType< T >::value, T > & getUpperBound() const
Get the upper bound of the box by the type of the coordinate.
Definition: Box.h:174
Box Base class specification without any template arguments.
Definition: Box.h:40
void setBounds()
Nothing to do on set bounds.
Definition: Box.h:43
friend std::ostream & operator<<(std::ostream &output, const Box<> &voidBox)
Nothing to do on printing.
Definition: Box.h:48
The base class for all boxes.
Definition: Box.h:33
Abstract base class for different kinds of events.
Looks up, at which index the given Type can be found in a tuple.
Definition: EvalVariadic.h:78