2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
5 * @file AthContainers/tools/AuxTypeVectorFactory.icc
6 * @author scott snyder <snyder@bnl.gov>
8 * @brief Factory objects that creates vectors using @c AuxTypeVector.
12 #ifndef XAOD_STANDALONE
13 #include "AthLinks/ElementLink.h"
20 #ifndef XAOD_STANDALONE
22 * @brief Apply output thinning to one item.
24 * Generic version; doesn't do anything.
28 void applyAuxThinning (const SG::ThinningCache*, T*)
34 * @brief Apply output thinning to an ElementLink.
35 * @param p Object being written.
36 * @param tc Thinning cache for the current stream.
40 void applyAuxThinning (const SG::ThinningCache* tc, ElementLink<T>* p)
47 * @brief Apply output thinning to a vector of ElementLinks.
48 * @param p Object being written.
49 * @param tc Thinning cache for the current stream.
52 void applyAuxThinning (const SG::ThinningCache* tc, std::vector<ElementLink<T> >* p)
54 for (ElementLink<T>& el : *p) {
62 * @brief Create a vector object of this type.
63 * @param auxid ID for the variable being created.
64 * @param size Initial size of the new vector.
65 * @param capacity Initial capacity of the new vector.
66 * @param isLinked True if this variable is linked from another one.
68 template <class T, class ALLOC>
69 std::unique_ptr<IAuxTypeVector>
70 AuxTypeVectorFactoryImpl<T, ALLOC>::create (SG::auxid_t auxid,
71 size_t size, size_t capacity,
74 return std::make_unique<AuxTypeVector<T, ALLOC> > (auxid, size, capacity,
80 * @brief Create a vector object of this type from a data blob.
81 * @param auxid ID for the variable being created.
82 * @param data The vector object.
83 * @param isPacked If true, @c data is a @c PackedContainer.
84 * @param ownFlag If true, the newly-created IAuxTypeVector object
85 * will take ownership of @c data.
86 * @param isLinked True if this variable is linked from another one.
88 * This is for types which are packable.
90 template <class T, class ALLOC>
91 std::unique_ptr<IAuxTypeVector>
92 AuxTypeVectorFactoryImpl<T, ALLOC>::createFromData (auxid_t auxid,
100 using unpacked_vector_type = typename SG::AuxDataTraits<T, ALLOC>::vector_type;
101 using element_type = typename unpacked_vector_type::value_type;
102 using unpacked_vector_allocator_type = typename SG::AuxDataTraits<T, ALLOC>::allocator_type;
103 using vector_type = SG::PackedContainer<element_type, unpacked_vector_allocator_type>;
104 return std::make_unique<AuxTypeVectorHolder<T, vector_type > >
105 (auxid, reinterpret_cast<vector_type*>(data), ownFlag, isLinked);
108 using vector_type = typename SG::AuxDataTraits<T, ALLOC>::vector_type;
109 return std::make_unique<AuxTypeVectorHolder<T, vector_type> > (auxid, reinterpret_cast<vector_type*>(data), true, isLinked);
115 * @brief Create a vector object of this type from a data blob.
116 * @param auxid ID for the variable being created.
117 * @param data The vector object.
118 * @param isPacked If true, @c data is a @c PackedContainer.
119 * @param ownFlag If true, the newly-created IAuxTypeVector object
120 * will take ownership of @c data.
121 * @param isLinked True if this variable is linked from another one.
123 * This is for types which are not packable.
125 template <class T, class ALLOC>
126 std::unique_ptr<IAuxTypeVector>
127 AuxTypeVectorFactoryImpl<T, ALLOC>::createFromData (auxid_t auxid,
132 std::false_type) const
134 if (isPacked) std::abort();
135 using vector_type = typename SG::AuxDataTraits<T, ALLOC>::vector_type;
136 return std::make_unique<AuxTypeVectorHolder<T, vector_type> >
137 (auxid, reinterpret_cast<vector_type*>(data), ownFlag, isLinked);
142 * @brief Create a vector object of this type from a data blob.
143 * @param auxid ID for the variable being created.
144 * @param data The vector object.
145 * @param linkedVector The interface for another variable linked to this one,
146 * or nullptr if there isn't one.
147 * (We do not take ownership.)
148 * @param isPacked If true, @c data is a @c PackedContainer.
149 * @param ownFlag If true, the newly-created IAuxTypeVector object
150 * will take ownership of @c data.
151 * @param isLinked True if this variable is linked from another one.
153 * If the element type is T, then @c data should be a pointer
154 * to a std::vector<T> object, which was obtained with @c new.
155 * But if @c isPacked is @c true, then @c data
156 * should instead point at an object of type @c SG::PackedContainer<T>.
158 * Returns a newly-allocated object.
160 template <class T, class ALLOC>
161 std::unique_ptr<IAuxTypeVector>
162 AuxTypeVectorFactoryImpl<T, ALLOC>::createFromData (SG::auxid_t auxid,
164 IAuxTypeVector* linkedVector,
169 if (linkedVector) std::abort();
170 return createFromData (auxid,
171 data, isPacked, ownFlag,
173 typename DataModel_detail::can_pack<T>::type());
177 /// Helper for copy; returns a pointer to the first destination object,
178 /// or nullptr if the destination was cleared rather than copied.
179 template <class T, class ALLOC>
181 AuxTypeVectorFactoryImpl<T, ALLOC>::copyImpl (SG::auxid_t auxid,
184 const AuxVectorData& src,
186 size_t n) const -> vector_value_type*
188 if (n == 0) return nullptr;
189 auto dstptr = reinterpret_cast<vector_value_type*>(dst.getDataArray (auxid));
191 // Source and destination containers are the same.
192 // We don't need to bother with fetching the src pointer, but we do
193 // need to check for overlaps.
194 if (dst_index >= src_index && dst_index < src_index+n) {
195 std::copy_backward (dstptr+src_index, dstptr+src_index+n, dstptr+dst_index+n);
198 std::copy (dstptr+src_index, dstptr+src_index+n, dstptr+dst_index);
200 return dstptr + dst_index;
203 auto srcptr = reinterpret_cast<const vector_value_type*>(src.getDataArrayAllowMissing (auxid));
205 std::copy (srcptr+src_index, srcptr+src_index+n, dstptr+dst_index);
206 return dstptr + dst_index;
209 std::fill (dstptr+dst_index, dstptr+dst_index+n, SG::Zero<vector_value_type>::zero());
218 * @brief Copy elements between vectors.
219 * @param auxid The aux data item being operated on.
220 * @param dst Container for the destination vector.
221 * @param dst_index Index of the first destination element in the vector.
222 * @param src Container for the source vector.
223 * @param src_index Index of the first source element in the vector.
224 * @param n Number of elements to copy.
226 * @c dst and @ src can be either the same or different.
228 template <class T, class ALLOC>
229 void AuxTypeVectorFactoryImpl<T, ALLOC>::copy (SG::auxid_t auxid,
232 const AuxVectorData& src,
236 (void)copyImpl (auxid, dst, dst_index, src, src_index, n);
242 * @brief Copy elements between vectors, possibly applying thinning.
243 * @param auxid The aux data item being operated on.
244 * @param dst Container for the destination vector.
245 * @param dst_index Index of the first destination element in the vector.
246 * @param src Container for the source vector.
247 * @param src_index Index of source element in the vector.
248 * @param src_index Index of the first source element in the vector.
249 * @param n Number of elements to copy.
251 * @c dst and @ src can be either the same or different.
253 template <class T, class ALLOC>
254 void AuxTypeVectorFactoryImpl<T, ALLOC>::copyForOutput (SG::auxid_t auxid,
255 AuxVectorData& dst, size_t dst_index,
256 const AuxVectorData& src, size_t src_index,
260 vector_value_type* dstptr = copyImpl (auxid, dst, dst_index, src, src_index, n);
261 #ifndef XAOD_STANDALONE
262 const SG::ThinningCache* tc = SG::getThinningCache();
263 for (size_t i = 0; i < n; i++) {
264 applyAuxThinning (tc, dstptr + i);
271 * @brief Swap elements between vectors.
272 * @param auxid The aux data item being operated on.
273 * @param a Container for the first vector.
274 * @param aindex Index of the first element in the first vector.
275 * @param b Container for the second vector.
276 * @param bindex Index of the first element in the second vector.
277 * @param n Number of elements to swap.
279 * @c a and @ b can be either the same or different.
280 * However, the ranges should not overlap.
282 template <class T, class ALLOC>
283 void AuxTypeVectorFactoryImpl<T, ALLOC>::swap (SG::auxid_t auxid,
284 AuxVectorData& a, size_t aindex,
285 AuxVectorData& b, size_t bindex,
289 auto aptr = reinterpret_cast<vector_value_type*>(a.getDataArray (auxid));
290 auto bptr = &a == &b ? aptr : reinterpret_cast<vector_value_type*>(b.getDataArray (auxid));
291 for (size_t i = 0; i < n; i++) {
292 std::swap (aptr[aindex+i], bptr[bindex+i]);
298 * @brief Clear a range of elements within a vector.
299 * @param auxid The aux data item being operated on.
300 * @param dst Container holding the element
301 * @param dst_index Index of the first element in the vector.
302 * @param n Number of elements to clear.
304 template <class T, class ALLOC>
305 void AuxTypeVectorFactoryImpl<T, ALLOC>::clear (SG::auxid_t auxid,
311 auto ptr = reinterpret_cast<vector_value_type*>(dst.getDataArray (auxid));
312 std::fill (ptr+dst_index, ptr+dst_index+n, SG::Zero<vector_value_type>::zero());
317 * @brief Return the size of an element of this vector type.
319 template <class T, class ALLOC>
320 size_t AuxTypeVectorFactoryImpl<T, ALLOC>::getEltSize() const
322 return sizeof (typename AuxTypeVector<T, ALLOC>::vector_type::value_type);
327 * @brief Return the @c type_info of the vector.
329 template <class T, class ALLOC>
330 const std::type_info* AuxTypeVectorFactoryImpl<T, ALLOC>::tiVec() const
332 return &typeid (typename AuxTypeVector<T, ALLOC>::vector_type);
337 * @brief True if the vectors created by this factory work by dynamic
338 * emulation (via @c TVirtualCollectionProxy or similar); false
339 * if the std::vector code is used directly.
341 template <class T, class ALLOC>
342 bool AuxTypeVectorFactoryImpl<T, ALLOC>::isDynamic() const
349 * @brief Return the @c type_info of the vector allocator.
351 template <class T, class ALLOC>
352 const std::type_info* AuxTypeVectorFactoryImpl<T, ALLOC>::tiAlloc() const
354 return &typeid(ALLOC);
359 * @brief Return the @c type_info of the vector allocator.
361 template <class T, class ALLOC>
362 std::string AuxTypeVectorFactoryImpl<T, ALLOC>::tiAllocName() const
364 return SG::normalizedTypeinfoName (typeid(ALLOC));