Belle II Software development
Algorithms.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/Range.h>
11
12#include <algorithm>
13#include <iterator>
14#include <optional>
15#include <vector>
16
17namespace Belle2 {
22 namespace TrackFindingCDC {
23
28 template <class Ts, class ACategoryFunction, class ACategory>
29 ACategory common(const Ts& items, const ACategoryFunction& catFunc, const ACategory defaultCat)
30 {
31 auto it = std::begin(items);
32 auto itEnd = std::end(items);
33 return common(it, itEnd, catFunc, defaultCat);
34 }
35
40 template <class It, class ACategoryFunction, class ACategory>
41 ACategory common(It itBegin, It itEnd, const ACategoryFunction& catFunc, const ACategory defaultCat)
42 {
43 if (itBegin == itEnd) return defaultCat; // empty case
44 const ACategory cat = catFunc(*itBegin);
45 for (It it = itBegin; it != itEnd; ++it) {
46 if (cat != catFunc(*it)) {
47 return defaultCat;
48 };
49 }
50 return cat;
51 }
52
56 template <class Ts, class APredicate>
57 void erase_remove_if(Ts& ts, const APredicate& predicate)
58 {
59 ts.erase(std::remove_if(std::begin(ts), std::end(ts), predicate), std::end(ts));
60 }
61
62 template<class Ts>
63 void only_best_N(Ts& ts, const size_t N)
64 {
65 auto newEnd = std::next(ts.begin(), std::min(N, ts.size()));
66 ts.erase(newEnd, ts.end());
67 }
68
72 template <class Ts>
73 void erase_unique(Ts& ts)
74 {
75 ts.erase(std::unique(std::begin(ts), std::end(ts)), std::end(ts));
76 }
77
81 template <class Ts, class AEqual>
82 void erase_unique(Ts& ts, const AEqual& equal)
83 {
84 ts.erase(std::unique(std::begin(ts), std::end(ts), equal), std::end(ts));
85 }
86
90 template <class It>
91 std::vector<std::pair<It, int> > unique_count(It itBegin, It itEnd)
92 {
93 std::vector<std::pair<It, int> > result;
94 if (itBegin == itEnd) return result;
95 It it = itBegin;
96 result.emplace_back(it, 1);
97 ++it;
98 for (; it != itEnd; ++it) {
99 if (*it == *result.back().first) {
100 ++result.back().second;
101 } else {
102 result.emplace_back(it, 1);
103 }
104 }
105 return result;
106 }
107
111 template <class It, class AEqual>
112 std::vector<std::pair<It, int> > unique_count(It itBegin, It itEnd, const AEqual& equal)
113 {
114 std::vector<std::pair<It, int> > result;
115 if (itBegin == itEnd) return result;
116 It it = itBegin;
117 result.emplace_back(it, 1);
118 ++it;
119 for (; it != itEnd; ++it) {
120 if (equal(*it, *result.back().first)) {
121 ++result.back().second;
122 } else {
123 result.emplace_back(it, 1);
124 }
125 }
126 return result;
127 }
128
132 template <class It>
133 std::vector<Range<It> > unique_ranges(It itBegin, It itEnd)
134 {
135 std::vector<std::pair<It, It> > result;
136 if (itBegin == itEnd) return result;
137 It it1 = itBegin;
138 It it2 = itBegin + 1;
139 result.emplace_back(it1, it2);
140 for (; it2 != itEnd; ++it1, ++it2) {
141 if (not(*it1 == *it2)) {
142 result.emplace_back(it2, it2);
143 }
144 ++result.back().second;
145 }
146 return result;
147 }
148
152 template <class It, class AEqual>
153 std::vector<Range<It> > unique_ranges(It itBegin, It itEnd, const AEqual& equal)
154 {
155 std::vector<Range<It> > result;
156 if (itBegin == itEnd) return result;
157 It it1 = itBegin;
158 It it2 = itBegin + 1;
159 result.emplace_back(it1, it2);
160 for (; it2 != itEnd; ++it1, ++it2) {
161 if (not equal(*it1, *it2)) {
162 result.emplace_back(it2, it2);
163 }
164 ++result.back().second;
165 }
166 return result;
167 }
168
172 template <class It, class ACategoryFunction>
173 std::vector<Range<It>> adjacent_groupby(It itBegin, It itEnd, const ACategoryFunction& catFunc)
174 {
175 std::vector<Range<It>> result;
176 if (itBegin == itEnd) return result; // empty case
177
178 It itFirstOfGroup = itBegin;
179 auto catOfGroup = catFunc(*itBegin);
180
181 for (It it = itBegin; it != itEnd; ++it) {
182 auto cat = catFunc(*it);
183 if (catOfGroup != cat) {
184 result.emplace_back(itFirstOfGroup, it);
185 itFirstOfGroup = it;
186 catOfGroup = cat;
187 }
188 }
189 result.emplace_back(itFirstOfGroup, itEnd);
190 return result;
191 }
192
197 template <class AInputIterator, class AOutputIterator, class ABinaryOperation>
198 AOutputIterator transform_adjacent_pairs(AInputIterator itBegin,
199 AInputIterator itEnd,
200 AOutputIterator result,
201 const ABinaryOperation& map)
202 {
203 if (itBegin == itEnd) return result;
204
205 AInputIterator second = itBegin;
206 ++second;
207 while (second != itEnd) {
208 *result = map(*itBegin, *second);
209 ++result;
210 ++itBegin;
211 ++second;
212 }
213 return result;
214 }
215
220 template <class AInputIterator, class AOutputIterator, class ATrinaryOperation>
221 AOutputIterator transform_adjacent_triples(AInputIterator itBegin,
222 AInputIterator itEnd,
223 AOutputIterator result,
224 const ATrinaryOperation& map)
225 {
226 if (not(itBegin != itEnd)) return result;
227
228 AInputIterator second = itBegin;
229 ++second;
230 if (not(second != itEnd)) return result;
231
232 AInputIterator third = second;
233 ++third;
234 while (third != itEnd) {
235 *result = map(*itBegin, *second, *third);
236 ++result;
237 ++itBegin;
238 ++second;
239 ++third;
240 }
241 return result;
242 }
243
248 template <class Ts, class TCopyIfPredicate>
249 Ts copy_if(Ts const& inputContainer, TCopyIfPredicate pred)
250 {
251 Ts outputContainer;
252
253 // copy only if predicate is true
254 std::copy_if(inputContainer.begin(), inputContainer.end(), std::back_inserter(outputContainer), pred);
255 return outputContainer;
256 }
257
258
262 template <class Ts, class AUnaryPredicate>
263 bool any(const Ts& ts, const AUnaryPredicate& comparator)
264 {
265 return std::any_of(std::begin(ts), std::end(ts), comparator);
266 }
267
271 template <class Ts, class AItem>
272 bool is_in(const AItem& item, const Ts& ts)
273 {
274 return std::find(std::begin(ts), std::end(ts), item) != std::end(ts);
275 };
276
280 template <class T, class Ts>
281 std::vector<T*> as_pointers(Ts& ts)
282 {
283 using std::begin;
284 using std::end;
285 std::size_t vsize = end(ts) - begin(ts);
286 std::vector<T*> result(vsize, nullptr);
287 std::transform(begin(ts), end(ts), result.begin(), [](T & t) { return std::addressof<T>(t);});
288 return result;
289 }
290 }
292}
Abstract base class for different kinds of events.