Belle II Software  release-05-02-19
Box.h
1 /**************************************************************************
2 * BASF2 (Belle Analysis Framework 2) *
3 * Copyright(C) 2015 - Belle II Collaboration *
4 * *
5 * Author: The Belle II Collaboration *
6 * Contributors: Oliver Frost *
7 * *
8 * This software is provided "as is" without any warranty. *
9 **************************************************************************/
10 #pragma once
11 
12 #include <tracking/trackFindingCDC/utilities/EvalVariadic.h>
13 
14 #include <type_traits>
15 #include <utility>
16 #include <array>
17 #include <cassert>
18 #include <numeric>
19 #include <ostream>
20 
21 namespace Belle2 {
26  namespace TrackFindingCDC {
27 
34  template<class... ATypes>
35  class Box;
36 
41  template<>
42  class Box<> {
43  public:
45  void setBounds()
46  {
47  }
48 
50  friend std::ostream& operator<<(std::ostream& output, const Box<>& voidBox __attribute__((unused)))
51  {
52  return output;
53  }
54  };
55 
63  template<class AFirstType, class... ASubordinaryTypes>
64  class Box<AFirstType, ASubordinaryTypes...> {
65  public:
67  using FirstType = AFirstType;
68 
70  using This = Box<AFirstType, ASubordinaryTypes...>;
71 
73  using Point = std::tuple<FirstType, ASubordinaryTypes...>;
74 
76  using Delta = std::tuple < decltype(FirstType() - FirstType()),
77  decltype(ASubordinaryTypes() - ASubordinaryTypes())... >;
78 
80  template<std::size_t I>
81  using Type = typename std::tuple_element<I, Point>::type;
82 
84  template<class T>
86 
88  template<class T>
89  using HasType = TypeInTuple<T, Point>;
90 
92  template<std::size_t I>
93  using Width = typename std::tuple_element<I, Delta>::type;
94 
96  static const size_t c_nTypes = std::tuple_size<Point>::value;
97 
99  using Indices = std::make_index_sequence<c_nTypes>;
100 
102  Box(const std::array<FirstType, 2>& firstBound,
103  const std::array<ASubordinaryTypes, 2>& ... subordinaryBounds)
104  : m_firstBounds{{
105  std::min(firstBound[0], firstBound[1]),
106  std::max(firstBound[1], firstBound[0])}}
107  , m_subordinaryBox(subordinaryBounds...)
108  {
109  }
110 
112  friend std::ostream& operator<<(std::ostream& output, const This& box)
113  {
114  return output <<
115  "Range from " << box.m_firstBounds[0] <<
116  " to " << box.m_firstBounds[1] << std::endl <<
117  box.getSubordinaryBox();
118  }
119 
121  void setBounds(std::array<FirstType, 2> firstBounds,
122  std::array<ASubordinaryTypes, 2>... subordinaryBounds)
123  {
124  m_firstBounds[0] = std::min(firstBounds[0], firstBounds[1]);
125  m_firstBounds[1] = std::max(firstBounds[0], firstBounds[1]);
126  m_subordinaryBox.setBounds(subordinaryBounds...);
127  }
128 
130  const Box<ASubordinaryTypes...>& getSubordinaryBox() const
131  {
132  return m_subordinaryBox;
133  }
134 
136  template<std::size_t I>
137  const std::enable_if_t<I == 0, Type<I> >& getLowerBound() const
138  {
139  return m_firstBounds[0];
140  }
141 
143  template<std::size_t I>
144  const std::enable_if_t < I != 0, Type<I> > & getLowerBound() const
145  {
146  static_assert(I < c_nTypes,
147  "Accessed index exceeds number of coordinates");
148  return m_subordinaryBox.template getLowerBound < I - 1 > ();
149  }
150 
152  template <class T>
153  const std::enable_if_t<HasType<T>::value, T>& getLowerBound() const
154  {
155  return getLowerBound<TypeIndex<T>::value>();
156  }
157 
159  template <std::size_t I>
160  const std::enable_if_t<I == 0, Type<I>>& getUpperBound() const
161  {
162  return m_firstBounds[1];
163  }
164 
166  template<std::size_t I>
167  const std::enable_if_t < I != 0, Type<I> > & getUpperBound() const
168  {
169  static_assert(I < c_nTypes,
170  "Accessed index exceeds number of coordinates");
171  return m_subordinaryBox.template getUpperBound < I - 1 > ();
172  }
173 
175  template <class T>
176  const std::enable_if_t<HasType<T>::value, T>& getUpperBound() const
177  {
178  return getUpperBound<TypeIndex<T>::value>();
179  }
180 
182  template <std::size_t I>
183  const std::enable_if_t<I == 0, std::array<Type<I>, 2>>& getBounds() const
184  {
185  return m_firstBounds;
186  }
187 
189  template <std::size_t I>
190  const std::enable_if_t < I != 0, std::array<Type<I>, 2 >>& getBounds() const
191  {
192  static_assert(I < c_nTypes, "Accessed index exceeds number of coordinates");
193  return m_subordinaryBox.template getBounds < I - 1 > ();
194  }
195 
197  template <class T>
198  const std::enable_if_t<HasType<T>::value, std::array<T, 2>>& getBounds() const
199  {
200  return getBounds<TypeIndex<T>::value>();
201  }
202 
204  template <std::size_t I>
205  Width<I> getWidth() const
206  {
207  return getUpperBound<I>() - getLowerBound<I>();
208  }
209 
210  public:
212  template<std::size_t I>
213  Type<I> getDivision(size_t nDivisions, size_t iDivision) const
214  {
215  assert(nDivisions >= iDivision);
216  return Type<I>(getLowerBound<I>() + getWidth<I>() * iDivision / nDivisions);
217  }
218 
220  template<std::size_t I>
221  std::array<Type<I>, 2 >
222  getDivisionBounds(size_t nDivisions, size_t iDivision) const
223  {
224  assert(nDivisions > iDivision);
225  return {{getDivision<I>(nDivisions, iDivision), getDivision<I>(nDivisions, iDivision + 1)}};
226  }
227 
229  template <std::size_t I>
230  Width<I> getDivisionWidthWithOverlap(const Width<I>& overlap, size_t nDivisions) const
231  {
232  return (getWidth<I>() + (nDivisions - 1) * overlap) / nDivisions;
233  }
234 
248  template<std::size_t I>
249  Type<I>
250  getLowerDivisionBoundWithOverlap(const Width<I>& overlap,
251  size_t nDivisions,
252  size_t iDivision) const
253  {
254  assert(nDivisions >= iDivision);
255  return Type<I>(getLowerBound<I>() + (getWidth<I>() - overlap) * iDivision / nDivisions);
256  }
257 
271  template<std::size_t I>
272  Type<I>
273  getUpperDivisionBoundWithOverlap(const Width<I>& overlap,
274  size_t nDivisions,
275  size_t iDivision) const
276  {
277  assert(nDivisions >= iDivision);
278  return Type<I>(getUpperBound<I>() - (getWidth<I>() - overlap) * (nDivisions - iDivision - 1) / nDivisions);
279  }
280 
281 
295  template<std::size_t I>
296  std::array<Type<I>, 2 >
297  getDivisionBoundsWithOverlap(const Width<I>& overlap,
298  size_t nDivisions,
299  size_t iDivision) const
300  {
301  assert(nDivisions > iDivision);
302  return {{
303  getLowerDivisionBoundWithOverlap<I>(overlap, nDivisions, iDivision),
304  getUpperDivisionBoundWithOverlap<I>(overlap, nDivisions, iDivision)
305  }};
306  }
307 
309  template <std::size_t I>
310  Type<I> getCenter() const
311  {
312  return getDivision<I>(2, 1);
313  }
314 
316  template <std::size_t I>
317  std::array<Type<I>, 2> getLowerHalfBounds() const
318  {
319  return getDivisionBounds(2, 0);
320  }
321 
323  template <std::size_t I>
324  std::array<Type<I>, 2> getUpperHalfBounds() const
325  {
326  return getDivisionBounds(2, 1);
327  }
328 
330  template <std::size_t I, class ASubordinaryValue>
331  bool isIn(const ASubordinaryValue& value) const
332  {
333  return getLowerBound<I>() < value and not(getUpperBound<I>() < value);
334  }
335 
336  private:
338  static bool any(const std::initializer_list<bool>& booleans)
339  {
340  return std::accumulate(std::begin(booleans), std::end(booleans),
341  false, [](const bool & lhs, const bool & rhs) {return lhs or rhs;});
342 
343  }
344 
346  static bool all(const std::initializer_list<bool>& booleans)
347  {
348  return std::accumulate(std::begin(booleans), std::end(booleans),
349  true, [](const bool & lhs, const bool & rhs) {return lhs and rhs;});
350  }
351 
361  template <size_t... Is>
362  bool intersectsImpl(const This& box,
363  std::index_sequence<Is...> is __attribute__((unused))) const
364  {
365  return not(any({box.getUpperBound<Is>() < this->getLowerBound<Is>()... }) or
366  any({this->getUpperBound<Is>() < box.getLowerBound<Is>()... }));
367  }
368 
373  template <size_t... Is>
374  bool isInImpl(const Point& point,
375  std::index_sequence<Is...> is __attribute__((unused))) const
376  {
377  return not all({isIn<Is>(std::get<Is>(point))...});
378  }
379 
380  public:
382  bool intersects(const This& box) const
383  {
384  return intersectsImpl(box, Indices());
385  }
386 
388  bool isIn(const Point& point) const
389  {
390  return isInImpl(point, Indices());
391  }
392 
394  bool isIn(const FirstType& value, const ASubordinaryTypes& ... values) const
395  {
396  return isInImpl(Point(value, values...), Indices());
397  }
398 
399  private:
401  std::array<FirstType, 2> m_firstBounds;
402 
404  Box<ASubordinaryTypes... > m_subordinaryBox;
405  };
406 
407  }
409 }
Belle2::TrackFindingCDC::Box
The base class for all boxes.
Definition: Box.h:43
Belle2::operator<<
std::ostream & operator<<(std::ostream &output, const IntervalOfValidity &iov)
Definition: IntervalOfValidity.cc:196
Belle2::TrackFindingCDC::Box< AFirstType, ASubordinaryTypes... >::HasType
TypeInTuple< T, Point > HasType
Check if the type is a coordinate of the box which amounts to a std::integral_constant.
Definition: Box.h:97
Belle2::TrackFindingCDC::Box< AFirstType, ASubordinaryTypes... >::Point
std::tuple< FirstType, ASubordinaryTypes... > Point
Tuple of the types of each coordinates.
Definition: Box.h:81
Belle2::TrackFindingCDC::Box< AFirstType, ASubordinaryTypes... >::Type
typename std::tuple_element< I, Point >::type Type
Accessor for the individual coordinate types.
Definition: Box.h:89
Belle2::TrackFindingCDC::Box< AFirstType, ASubordinaryTypes... >::m_firstBounds
std::array< FirstType, 2 > m_firstBounds
Bound in the first coordindate.
Definition: Box.h:409
Belle2::TrackFindingCDC::Box< AFirstType, ASubordinaryTypes... >::getSubordinaryBox
const Box< ASubordinaryTypes... > & getSubordinaryBox() const
Getter for the box in excluding the first coordinate.
Definition: Box.h:138
Belle2::TrackFindingCDC::Box<>
Box Base class specification without any template arguments.
Definition: Box.h:50
Belle2::TrackFindingCDC::Box< AFirstType, ASubordinaryTypes... >::Width
typename std::tuple_element< I, Delta >::type Width
Accessor for the individual coordinate difference types.
Definition: Box.h:101
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::TrackFindingCDC::Box< AFirstType, ASubordinaryTypes... >::getBounds
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:198
Belle2::TrackFindingCDC::Box< AFirstType, ASubordinaryTypes... >::Indices
std::make_index_sequence< c_nTypes > Indices
Helper class to iterate over the individual coordinates.
Definition: Box.h:107
Belle2::TrackFindingCDC::GetIndexInTuple
Looks up, at which index the given Type can be found in a tuple.
Definition: EvalVariadic.h:88
Belle2::TrackFindingCDC::Box< AFirstType, ASubordinaryTypes... >
Box Base class specification without a first and subordinary types which can be used to "stack" vario...
Definition: Box.h:72