Belle II Software development
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
19namespace 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
AFirstType FirstType
Type of the first coordinate.
Definition: Box.h:65
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
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
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
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
bool intersectsImpl(const This &box, std::index_sequence< Is... > is) const
Indicates if this box intersects with the other box.
Definition: Box.h:359
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< HasType< T >::value, T > & getUpperBound() const
Get the upper bound of the box by the type of the coordinate.
Definition: Box.h:173
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
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
Type< I > getCenter() const
Get the center of the box in the coordinate I.
Definition: Box.h:307
bool isIn(const ASubordinaryValue &value) const
Indicate if the given value is in the range of the coordinate I.
Definition: Box.h:328
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
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
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 coordinate.
Definition: Box.h:398
const Box< ASubordinaryTypes... > & getSubordinaryBox() const
Getter for the box in excluding the first coordinate.
Definition: Box.h:127
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
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
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
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
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
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
std::array< Type< I >, 2 > getLowerHalfBounds() const
Get the lower partition in the coordinate I.
Definition: Box.h:314
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
Box< ASubordinaryTypes... > m_subordinaryBox
Box in the other coordinate.
Definition: Box.h:401
void setBounds(std::array< FirstType, 2 > firstBounds, std::array< ASubordinaryTypes, 2 >... subordinaryBounds)
Set bounds of the box to new values.
Definition: Box.h:118
typename std::tuple_element< I, Point >::type Type
Accessor for the individual coordinate types.
Definition: Box.h:79
std::array< Type< I >, 2 > getUpperHalfBounds() const
Get the upper partition in the coordinate I.
Definition: Box.h:321
Width< I > getWidth() const
Get the difference of upper and lower bound.
Definition: Box.h:202
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
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 intersects(const This &box) const
Indicates if this box intersects with the other box.
Definition: Box.h:379
friend std::ostream & operator<<(std::ostream &output, const This &box)
Output operator for debugging.
Definition: Box.h:109
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 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
Box Base class specification without any template arguments.
Definition: Box.h:40
friend std::ostream & operator<<(std::ostream &output, const Box<> &voidBox)
Nothing to do on printing.
Definition: Box.h:48
void setBounds()
Nothing to do on set bounds.
Definition: Box.h:43
The base class for all boxes.
Definition: Box.h:33
Abstract base class for different kinds of events.
STL namespace.
Looks up, at which index the given Type can be found in a tuple.
Definition: EvalVariadic.h:78