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>
83 using TypeIndex = GetIndexInTuple<T, Point>;
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>
202 Width<I> getWidth() const
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>
247 getLowerDivisionBoundWithOverlap(const Width<I>& overlap,
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>
270 getUpperDivisionBoundWithOverlap(const Width<I>& overlap,
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 >
294 getDivisionBoundsWithOverlap(const Width<I>& overlap,
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>
307 Type<I> getCenter() const
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 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.