Belle II Software  release-08-01-10
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{std::min(firstBound[0], firstBound[1]),
103  std::max(firstBound[1], firstBound[0])}
104  , m_subordinaryBox(subordinaryBounds...)
105  {
106  }
107 
109  friend std::ostream& operator<<(std::ostream& output, const This& box)
110  {
111  return output <<
112  "Range from " << box.m_firstBounds[0] <<
113  " to " << box.m_firstBounds[1] << std::endl <<
114  box.getSubordinaryBox();
115  }
116 
118  void setBounds(std::array<FirstType, 2> firstBounds,
119  std::array<ASubordinaryTypes, 2>... subordinaryBounds)
120  {
121  m_firstBounds[0] = std::min(firstBounds[0], firstBounds[1]);
122  m_firstBounds[1] = std::max(firstBounds[0], firstBounds[1]);
123  m_subordinaryBox.setBounds(subordinaryBounds...);
124  }
125 
127  const Box<ASubordinaryTypes...>& getSubordinaryBox() const
128  {
129  return m_subordinaryBox;
130  }
131 
133  template<std::size_t I>
134  const std::enable_if_t<I == 0, Type<I> >& getLowerBound() const
135  {
136  return m_firstBounds[0];
137  }
138 
140  template<std::size_t I>
141  const std::enable_if_t < I != 0, Type<I> > & getLowerBound() const
142  {
143  static_assert(I < c_nTypes,
144  "Accessed index exceeds number of coordinates");
145  return m_subordinaryBox.template getLowerBound < I - 1 > ();
146  }
147 
149  template <class T>
150  const std::enable_if_t<HasType<T>::value, T>& getLowerBound() const
151  {
152  return getLowerBound<TypeIndex<T>::value>();
153  }
154 
156  template <std::size_t I>
157  const std::enable_if_t<I == 0, Type<I>>& getUpperBound() const
158  {
159  return m_firstBounds[1];
160  }
161 
163  template<std::size_t I>
164  const std::enable_if_t < I != 0, Type<I> > & getUpperBound() const
165  {
166  static_assert(I < c_nTypes,
167  "Accessed index exceeds number of coordinates");
168  return m_subordinaryBox.template getUpperBound < I - 1 > ();
169  }
170 
172  template <class T>
173  const std::enable_if_t<HasType<T>::value, T>& getUpperBound() const
174  {
175  return getUpperBound<TypeIndex<T>::value>();
176  }
177 
179  template <std::size_t I>
180  const std::enable_if_t<I == 0, std::array<Type<I>, 2>>& getBounds() const
181  {
182  return m_firstBounds;
183  }
184 
186  template <std::size_t I>
187  const std::enable_if_t < I != 0, std::array<Type<I>, 2 >>& getBounds() const
188  {
189  static_assert(I < c_nTypes, "Accessed index exceeds number of coordinates");
190  return m_subordinaryBox.template getBounds < I - 1 > ();
191  }
192 
194  template <class T>
195  const std::enable_if_t<HasType<T>::value, std::array<T, 2>>& getBounds() const
196  {
197  return getBounds<TypeIndex<T>::value>();
198  }
199 
201  template <std::size_t I>
203  {
204  return getUpperBound<I>() - getLowerBound<I>();
205  }
206 
207  public:
209  template<std::size_t I>
210  Type<I> getDivision(size_t nDivisions, size_t iDivision) const
211  {
212  assert(nDivisions >= iDivision);
213  return Type<I>(getLowerBound<I>() + getWidth<I>() * iDivision / nDivisions);
214  }
215 
217  template<std::size_t I>
218  std::array<Type<I>, 2 >
219  getDivisionBounds(size_t nDivisions, size_t iDivision) const
220  {
221  assert(nDivisions > iDivision);
222  return {{getDivision<I>(nDivisions, iDivision), getDivision<I>(nDivisions, iDivision + 1)}};
223  }
224 
226  template <std::size_t I>
227  Width<I> getDivisionWidthWithOverlap(const Width<I>& overlap, size_t nDivisions) const
228  {
229  return (getWidth<I>() + (nDivisions - 1) * overlap) / nDivisions;
230  }
231 
245  template<std::size_t I>
246  Type<I>
248  size_t nDivisions,
249  size_t iDivision) const
250  {
251  assert(nDivisions >= iDivision);
252  return Type<I>(getLowerBound<I>() + (getWidth<I>() - overlap) * iDivision / nDivisions);
253  }
254 
268  template<std::size_t I>
269  Type<I>
271  size_t nDivisions,
272  size_t iDivision) const
273  {
274  assert(nDivisions >= iDivision);
275  return Type<I>(getUpperBound<I>() - (getWidth<I>() - overlap) * (nDivisions - iDivision - 1) / nDivisions);
276  }
277 
278 
292  template<std::size_t I>
293  std::array<Type<I>, 2 >
295  size_t nDivisions,
296  size_t iDivision) const
297  {
298  assert(nDivisions > iDivision);
299  return {{
300  getLowerDivisionBoundWithOverlap<I>(overlap, nDivisions, iDivision),
301  getUpperDivisionBoundWithOverlap<I>(overlap, nDivisions, iDivision)
302  }};
303  }
304 
306  template <std::size_t I>
308  {
309  return getDivision<I>(2, 1);
310  }
311 
313  template <std::size_t I>
314  std::array<Type<I>, 2> getLowerHalfBounds() const
315  {
316  return getDivisionBounds(2, 0);
317  }
318 
320  template <std::size_t I>
321  std::array<Type<I>, 2> getUpperHalfBounds() const
322  {
323  return getDivisionBounds(2, 1);
324  }
325 
327  template <std::size_t I, class ASubordinaryValue>
328  bool isIn(const ASubordinaryValue& value) const
329  {
330  return getLowerBound<I>() < value and not(getUpperBound<I>() < value);
331  }
332 
333  private:
335  static bool any(const std::initializer_list<bool>& booleans)
336  {
337  return std::accumulate(std::begin(booleans), std::end(booleans),
338  false, [](const bool & lhs, const bool & rhs) {return lhs or rhs;});
339 
340  }
341 
343  static bool all(const std::initializer_list<bool>& booleans)
344  {
345  return std::accumulate(std::begin(booleans), std::end(booleans),
346  true, [](const bool & lhs, const bool & rhs) {return lhs and rhs;});
347  }
348 
358  template <size_t... Is>
359  bool intersectsImpl(const This& box,
360  std::index_sequence<Is...> is __attribute__((unused))) const
361  {
362  return not(any({box.getUpperBound<Is>() < this->getLowerBound<Is>()... }) or
363  any({this->getUpperBound<Is>() < box.getLowerBound<Is>()... }));
364  }
365 
370  template <size_t... Is>
371  bool isInImpl(const Point& point,
372  std::index_sequence<Is...> is __attribute__((unused))) const
373  {
374  return not all({isIn<Is>(std::get<Is>(point))...});
375  }
376 
377  public:
379  bool intersects(const This& box) const
380  {
381  return intersectsImpl(box, Indices());
382  }
383 
385  bool isIn(const Point& point) const
386  {
387  return isInImpl(point, Indices());
388  }
389 
391  bool isIn(const FirstType& value, const ASubordinaryTypes& ... values) const
392  {
393  return isInImpl(Point(value, values...), Indices());
394  }
395 
396  private:
398  std::array<FirstType, 2> m_firstBounds;
399 
401  Box<ASubordinaryTypes... > m_subordinaryBox;
402  };
403 
404  }
406 }
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:187
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:294
const Box< ASubordinaryTypes... > & getSubordinaryBox() const
Getter for the box in excluding the first coordinate.
Definition: Box.h:127
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:247
bool intersectsImpl(const This &box, std::index_sequence< Is... > is) const
Indicates if this box intersects with the other box.
Definition: Box.h:359
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:195
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:141
bool isIn(const ASubordinaryValue &value) const
Indicate if the given value is in the range of the coordinate I.
Definition: Box.h:328
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:210
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:180
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:157
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:343
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:398
std::array< Type< I >, 2 > getUpperHalfBounds() const
Get the upper partition in the coordinate I.
Definition: Box.h:321
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:270
bool isIn(const Point &point) const
Indicate if all given values are in the range of their coordinates.
Definition: Box.h:385
static bool any(const std::initializer_list< bool > &booleans)
Indicates if any of the boolean values is true.
Definition: Box.h:335
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:202
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:371
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:391
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:164
Box< ASubordinaryTypes... > m_subordinaryBox
Box in the other coordinate.
Definition: Box.h:401
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:150
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:134
void setBounds(std::array< FirstType, 2 > firstBounds, std::array< ASubordinaryTypes, 2 >... subordinaryBounds)
Set bounds of the box to new values.
Definition: Box.h:118
friend std::ostream & operator<<(std::ostream &output, const This &box)
Output operator for debugging.
Definition: Box.h:109
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:227
std::array< Type< I >, 2 > getDivisionBounds(size_t nDivisions, size_t iDivision) const
Get the lower partition in the coordinate I.
Definition: Box.h:219
bool intersects(const This &box) const
Indicates if this box intersects with the other box.
Definition: Box.h:379
std::array< Type< I >, 2 > getLowerHalfBounds() const
Get the lower partition in the coordinate I.
Definition: Box.h:314
Type< I > getCenter() const
Get the center of the box in the coordinate I.
Definition: Box.h:307
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:173
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