ATLAS Offline Software
Loading...
Searching...
No Matches
DVL_algorithms.icc
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// $Id$
6/**
7 * @file AthContainers/tools/DVL_algorithms.icc
8 * @author scott snyder <snyder@bnl.gov>
9 * @date Sep, 2010
10 * @brief Helpers for STL algorithms for @c DataVector/List.
11 */
12
13
14#include "AthContainers/tools/DVLNoBase.h"
15#include "AthContainers/tools/DVLCast.h"
16#include "AthContainers/AuxElement.h"
17#include "AthContainersInterfaces/AuxStore_traits.h"
18#include <algorithm>
19
20
21template <class DV> class ConstDataVector;
22
23
24namespace DataModel_detail {
25
26
27/**
28 * @brief Comparison helper for @c DataVector/List classes.
29 *
30 * When doing operations such as @c sort on a @c DataVector/List,
31 * we'd like to be able to give to sort the iterators of the underlying
32 * @c BaseContainer container, for the sake of efficiency. But we also
33 * have to make sure that the comparisons see the proper pointer types
34 * for derived @c DataVector/List classes. This can be done with the following
35 * functional wrapper. This wraps a comparison object, putting the
36 * arguments through @c DVLCast before calling the comparison.
37 *
38 * There is also a specialization for the case where no casting
39 * is required.
40 */
41template <class DVL, class Compare, class DVL_Base=typename DVL::DVL_BASE>
42struct Compwrapper
43{
44 typedef typename DVL::BaseContainer::value_type inptr;
45 Compare m_comp;
46 Compwrapper (Compare comp) : m_comp (comp) {}
47 bool operator() (inptr x, inptr y)
48 {
49 return m_comp (DataModel_detail::DVLCast<DVL>::cast (x),
50 DataModel_detail::DVLCast<DVL>::cast (y));
51 }
52};
53
54
55/**
56 * @brief Comparison helper for @c DataVector/List classes (specialization).
57 *
58 * This is specialized for the case where we're dealing with
59 * a base @c DataVector/List, and thus no casting is required.
60 */
61template <class DVL, class Compare>
62struct Compwrapper<DVL, Compare, DataModel_detail::NoBase>
63 : public Compare
64{
65 Compwrapper (Compare comp) : Compare (std::move(comp)) {}
66};
67
68
69/**
70 * @brief Predicate helper for @c DataVector/List classes.
71 *
72 * When doing operations such as @c partition on a @c DataVector/List,
73 * we'd like to be able to give the operation the iterators of the underlying
74 * @c BaseContainer container, for the sake of efficiency. But we also
75 * have to make sure that the predicate sees the proper pointer types
76 * for derived @c DataVector/List classes. This can be done with the following
77 * functional wrapper. This wraps a predicate object, putting the
78 * arguments through @c DVLCast before calling the predicate.
79 *
80 * There is also a specialization for the case where no casting
81 * is required.
82 */
83template <class DVL, class Predicate, class DVL_Base=typename DVL::DVL_BASE>
84struct Predwrapper
85{
86 typedef typename DVL::BaseContainer::value_type inptr;
87 Predicate m_pred;
88 Predwrapper (Predicate pred) : m_pred (pred) {}
89 bool operator() (inptr x)
90 {
91 return m_pred (DataModel_detail::DVLCast<DVL>::cast (x));
92 }
93};
94
95
96/**
97 * @brief Predicate helper for @c DataVector/List classes (specialization).
98 *
99 * This is specialized for the case where we're dealing with
100 * a base @c DataVector/List, and thus no casting is required.
101 */
102template <class DV, class Predicate>
103struct Predwrapper<DV, Predicate, DataModel_detail::NoBase>
104 : public Predicate
105{
106 Predwrapper (Predicate pred) : Predicate (std::move(pred)) {}
107};
108
109
110/**
111 * @brief Specialization of @c remove for @c DataVector/List.
112 * @param beg The start iterator for the remove.
113 * @param end The end iterator for the remove.
114 * @param value The value to remove.
115 *
116 * @c beg and @c end should both be iterators from the same @c DataVector/List.
117 * This performs the remove in a way that doesn't run afoul of
118 * @c DataVector/List's object ownership rules.
119 */
120template <class Iterator, class T>
121Iterator
122dvl_remove (Iterator beg,
123 Iterator end,
124 const T& value)
125{
126 beg = std::find (beg, end, value);
127 if (beg == end)
128 return end;
129 Iterator res = beg;
130 *beg = 0;
131 ++beg;
132 for (; beg != end; ++beg) {
133 if (!(*beg == value)) {
134 std::iter_swap (res, beg);
135 ++res;
136 }
137 else
138 *beg = 0;
139 }
140 return res;
141}
142
143
144/**
145 * @brief Specialization of @c remove_if for @c DataVector/List.
146 * @param beg The start iterator for the remove.
147 * @param end The end iterator for the remove.
148 * @param pred The predicate for the removal.
149 *
150 * @c beg and @c end should both be iterators from the same @c DataVector/List.
151 * This performs the remove in a way that doesn't run afoul
152 * of @c DataVector/List's object ownership rules.
153 */
154template <class Iterator, class Predicate>
155Iterator
156dvl_remove_if (Iterator beg,
157 Iterator end,
158 Predicate pred)
159{
160 beg = std::find_if (beg, end, pred);
161 if (beg == end)
162 return end;
163 Iterator res = beg;
164 *beg = 0;
165 ++beg;
166 for (; beg != end; ++beg) {
167 if (!bool(pred(*beg))) {
168 std::iter_swap (res, beg);
169 ++res;
170 }
171 else
172 *beg = 0;
173 }
174 return res;
175}
176
177
178/**
179 * @brief Specialization of @c unique for @c DataVector/List.
180 * @param beg The start iterator for the unique operation.
181 * @param end The end iterator for the unique operation.
182 *
183 * @c beg and @c end should both be iterators from the same @c DataVector/List.
184 * This performs the operation in a way
185 * that doesn't run afoul of @c DataVector/List's object ownership rules.
186 */
187template <class Iterator>
188Iterator
189dvl_unique (Iterator beg,
190 Iterator end)
191{
192 beg = std::adjacent_find (beg, end);
193 if (beg == end)
194 return end;
195 Iterator res = beg;
196 ++beg;
197 *beg = 0;
198 while (++beg != end) {
199 if (!(*res == *beg))
200 std::iter_swap (++res, beg);
201 else
202 *beg = 0;
203 }
204 return ++res;
205}
206
207
208/**
209 * @brief Specialization of @c unique for @c DataVector/List.
210 * @param beg The start iterator for the unique operation.
211 * @param end The end iterator for the unique operation.
212 * @param pred The predicate for the operation.
213 *
214 * @c beg and @c end should both be iterators from the same @c DataVector/List.
215 * This performs the operation in a way
216 * that doesn't run afoul of @c DataVector/List's
217 * object ownership rules.
218 */
219template <class Iterator, class BinaryPredicate>
220Iterator
221dvl_unique (Iterator beg,
222 Iterator end,
223 BinaryPredicate pred)
224{
225 beg = std::adjacent_find (beg, end, pred);
226 if (beg == end)
227 return end;
228 Iterator res = beg;
229 ++beg;
230 *beg = 0;
231 while (++beg != end) {
232 if (!pred(*res, *beg))
233 std::iter_swap (++res, beg);
234 else
235 *beg = 0;
236 }
237 return ++res;
238}
239
240
241/**
242 * @brief Reset indices / reorder aux data after elements have been permuted.
243 * @param beg Start of the range of elements to process.
244 * @param end End of the range of elements to process.
245 *
246 * Call this after some operation that has permuted the elements in the
247 * container (such as sort). The index information in the elements
248 * will be used to permute all auxiliary data in the same way.
249 * Finally, all the indices will be reset in the correct order.
250 *
251 * @c ForwardIterator should be an iterator over the @c DataVector
252 * (not a base iterator).
253 */
254template <class ForwardIterator>
255inline
256void resortAux (ForwardIterator beg,
257 ForwardIterator end)
258{
259 // Forward to the appropriate specialization, depending on whether
260 // or not aux data is supported.
261 typedef typename std::iterator_traits<ForwardIterator>::value_type valtype;
262 resortAux1 (typename SG::AuxStore_traits<valtype>::flag(), beg, end);
263}
264
265
266/**
267 * @brief Reset indices / reorder aux data after elements have been permuted.
268 * @param beg Start of the range of elements to process.
269 * @param end End of the range of elements to process.
270 *
271 * Aux data case.
272 */
273template <class DVL>
274void resortAux1 (const std::true_type&,
275 typename DataModel_detail::iterator<DVL> beg,
276 typename DataModel_detail::iterator<DVL> end)
277{
278 if (beg != end) {
279 DVL* cont = dynamic_cast<DVL*> (beg.container());
280 if (cont)
281 cont->resortAux (beg, end);
282 }
283}
284
285
286/**
287 * @brief Reset indices / reorder aux data after elements have been permuted.
288 * @param beg Start of the range of elements to process.
289 * @param end End of the range of elements to process.
290 *
291 * Aux data case with reverse iterators.
292 */
293template <class DVL>
294void resortAux1 (const std::true_type&,
295 typename std::reverse_iterator<typename DataModel_detail::iterator<DVL> > beg,
296 typename std::reverse_iterator<typename DataModel_detail::iterator<DVL> > end)
297{
298 if (beg != end) {
299 DVL* cont = dynamic_cast<DVL*> (beg.base().container());
300 if (cont)
301 cont->resortAux (end.base(), beg.base());
302 }
303}
304
305
306/**
307 * @brief Reset indices / reorder aux data after elements have been permuted.
308 * @param beg Start of the range of elements to process.
309 * @param end End of the range of elements to process.
310 *
311 * No-auxdata case; just a no-op.
312 */
313template <class ForwardIterator>
314inline
315void resortAux1 (const std::false_type&,
316 ForwardIterator,
317 ForwardIterator)
318{
319}
320
321
322} // namespace DataModel_detail