ATLAS Offline Software
Loading...
Searching...
No Matches
JaggedVecVectorFactory.cxx
Go to the documentation of this file.
2#include <cstring>
3
4
6
7
18 size_t index,
19 size_t sz,
21{
22 if (index > 0 && elts[index-1].end() == 0 && elts[sz-1].end() == 0) {
23 if (size_t n_payload = lv->getDataSpan().size) {
24 Shift shift (n_payload);
25 for (--index; elts[index].end() == 0; --index) {
26 shift (elts[index]);
27 if (index == 0) break;
28 }
29 }
30 }
31}
32
33
48 AuxVectorData& dst,
49 size_t dst_index,
50 const AuxVectorData& src,
51 size_t src_index,
52 size_t n,
53 bool for_output)
54{
55 using vector_value_type = JaggedVecEltBase;
56
57 if (n == 0) return;
58
59 // Check for overlaps.
60 if (&src == &dst) {
61 size_t src_end = src_index + n;
62 size_t dst_end = dst_index + n;
63 if ((src_end > dst_index && src_end <= dst_end) ||
64 (dst_end > src_index && dst_end <= src_end))
65 {
66 // Overlapping copies not implemented for jagged vectors.
67 // Talk to core software if this is an issue.
69 }
70 }
71
72 vector_value_type* v_dst = reinterpret_cast<vector_value_type*> (dst.getDataArray (auxid));
73 const vector_value_type* v_src = &dst==&src ? v_dst : reinterpret_cast<const vector_value_type*> (src.getDataArray (auxid));
74 IAuxTypeVector* dst_lv = dst.getStore()->linkedVector (auxid);
75 const SG::auxid_t payload_auxid = dst_lv->auxid();
77 const IAuxTypeVectorFactory* payload_fac = r.getFactory (payload_auxid);
78 const size_t dst_sz = dst.size_v();
79
80 // Make sure there are no trailing zeros in the destination within the
81 fillTrailingZeros (v_dst, dst_index+n, dst_sz, dst_lv);
82
83 const size_t dst_first = v_dst[dst_index].begin(dst_index);
84 size_t src_first = v_src[src_index].begin(src_index);
85 size_t src_first_orig = src_first;
86 const size_t n_dst = v_dst[dst_index+n-1].end() - dst_first;
87 size_t n_src = v_src[src_index+n-1].end() - src_first;
88
89 // First copy the Elt elements. We'll fix up the indices below.
90 std::copy_n (v_src+src_index, n, v_dst+dst_index);
91
92 // If the source had trailing zeros, fix them up here.
93 if (v_dst[dst_index+n-1].end() == 0) {
94 const size_t src_sz = src.size_v();
95 if (v_src[src_sz-1].end() == 0) {
96 const IAuxTypeVector* src_lv = src.getConstStore()->linkedVector (auxid);
97 if (size_t src_n_payload = src_lv->getDataSpan().size) {
98
99 bool adjust = true;
100 for (size_t i = src_index+n; i < src_sz; ++i) {
101 if (v_src[i].end() != 0) {
102 adjust = false;
103 break;
104 }
105 }
106 if (adjust) {
107 Shift shift (src_n_payload);
108 for (size_t i = dst_index+n-1; v_dst[i].end() == 0; --i) {
109 shift (v_dst[i]);
110 if (i == dst_index) break;
111 }
112 if (src_first == 0 && src_index > 0) {
113 src_first = v_src[src_index-1].end();
114 src_first_orig = src_first;
115 }
116 n_src = src_n_payload - src_first;
117 }
118 }
119 }
120 }
121
122 // Adjust the size of the destination payload container.
123 if (n_src != n_dst) {
124 if (!dst_lv->shift (dst_first+n_dst, n_src - n_dst)) {
125 dst.clearCache (payload_auxid);
126 }
127 if (&dst == &src && src_first > dst_first) {
128 src_first += (n_src - n_dst);
129 }
130 }
131
132 // Copy the payload elements.
133 if (for_output) {
134 payload_fac->copyForOutput (payload_auxid, dst, dst_first, src, src_first, n_src);
135 }
136 else {
137 payload_fac->copy (payload_auxid, dst, dst_first, src, src_first, n_src);
138 }
139
140 // Fix up the Elt entries --- first the ones we copied, then the following
141 // ones in the destination container.
142 std::for_each_n (v_dst+dst_index, n, Shift (dst_first - src_first_orig));
143 // Avoid N^2.
144 if (dst_index+n < dst_sz && !(v_dst[dst_index+n].end() == 0 && v_dst[dst_sz-1].end() == 0))
145 {
146 std::for_each (v_dst+dst_index+n, v_dst+dst_sz, Shift (n_src - n_dst));
147 }
148}
149
150
164 AuxVectorData& a, size_t aindex,
165 AuxVectorData& b, size_t bindex,
166 size_t n)
167{
168 using vector_value_type = JaggedVecEltBase;
169
170 if (n == 0) return;
171
172 vector_value_type* v_a = reinterpret_cast<vector_value_type*> (a.getDataArray (auxid));
173 vector_value_type* v_b = &a==&b ? v_a : reinterpret_cast<vector_value_type*> (b.getDataArray (auxid));
174 IAuxTypeVector* alv = a.getStore()->linkedVector (auxid);
175 IAuxTypeVector* blv = &a==&b ? alv : b.getStore()->linkedVector (auxid);
176 const SG::auxid_t payload_auxid = alv->auxid();
178 const IAuxTypeVectorFactory* payload_fac = r.getFactory (payload_auxid);
179 const size_t a_sz = a.size_v();
180 const size_t b_sz = b.size_v();
181
182 // Make sure there are no trailing zeros in the ranges we're looking at.
183 fillTrailingZeros (v_a, a_sz, a_sz, alv);
184 fillTrailingZeros (v_b, b_sz, b_sz, blv);
185
186 size_t a_first = v_a[aindex].begin(aindex);
187 size_t b_first = v_b[bindex].begin(bindex);
188 const size_t a_first_orig = a_first;
189 const size_t b_first_orig = b_first;
190 const size_t n_a = v_a[aindex+n-1].end() - a_first;
191 const size_t n_b = v_b[bindex+n-1].end() - b_first;
192
193 // First swap the Elt entries. We'll fix up the indices below.
194 std::swap_ranges (v_a+aindex, v_a+aindex+n, v_b+bindex);
195
196 // We have two payload ranges to swap, a and b.
197 // One is probably longer than the other, so we'll need to adjust the
198 // payload vector lengths.
199 // But first, swap the common part of the payloads.
200 const size_t n_common = std::min (n_a, n_b);
201 payload_fac->swap (payload_auxid, a, a_first, b, b_first, n_common);
202
203 // Now we move the tail; that is, the piece of one payload range
204 // that is not in the other. Define a function to reduce duplicate
205 // code. Here, 1 is the range that is longer and 2 the range
206 // that is shorter.
207 auto shiftTail = [payload_fac, n_common, payload_auxid]
208 (AuxVectorData& vd1,
209 IAuxTypeVector* lv1,
210 size_t& first1,
211 const size_t n1,
212 AuxVectorData& vd2,
213 IAuxTypeVector* lv2,
214 size_t& first2)
215 {
216 // Lengthen the shorter payload to receive the extra elements from
217 // the longer one.
218 if (!lv2->shift (first2 + n_common, n1 - n_common)) {
219 vd2.clearCache (payload_auxid);
220 }
221 if (&vd1 == &vd2 && first1 > first2) {
222 // Special case for self-swapping: keep indices consistent.
223 first1 += (n1 - n_common);
224 }
225 // Copy the extra elements.
226 payload_fac->copy (payload_auxid,
227 vd2, first2 + n_common, vd1, first1 + n_common,
228 n1 - n_common);
229 // Now remove those elements from the longer one.
230 lv1->shift (first1 + n1, - (n1 - n_common));
231 if (&vd1 == &vd2 && first2 > first1) {
232 // Special case for self-swapping: keep indices consistent.
233 first2 -= (n1 - n_common);
234 }
235 };
236
237 // Now move the tail, depending on which is larger.
238 if (n_a > n_b) {
239 shiftTail (a, alv, a_first, n_a, b, blv, b_first);
240 }
241 else if (n_b > n_a) {
242 shiftTail (b, blv, b_first, n_b, a, alv, a_first);
243 }
244
245 // Now adjust the indices in the Elt ranges that were swapped.
246 // In the case of self-swapping, the _first indices may have changed,
247 // so need to remember to use the original values.
248 std::for_each_n (v_a+aindex, n, Shift (a_first - b_first_orig));
249 std::for_each_n (v_b+bindex, n, Shift (b_first - a_first_orig));
250
251 if (n_a != n_b) {
252 if (&a == &b) {
253 // Self-swapping case.
254 // Adjust the indices between the two ranges that were swapped
255 // (but we needn't do anything if the number of payload items
256 // was the same).
257 if (aindex < bindex) {
258 std::for_each (v_a+aindex+n, v_a+bindex, Shift (n_b - n_a));
259 }
260 else {
261 std::for_each (v_a+bindex+n, v_a+aindex, Shift (n_a - n_b));
262 }
263 }
264 else {
265 // Distinct container case. Adjust indices after the swapped ranges.
266 std::for_each (v_a+aindex+n, v_a+a_sz, Shift (n_b - n_a));
267 std::for_each (v_b+bindex+n, v_b+b_sz, Shift (n_a - n_b));
268 }
269 }
270}
271
272
283 AuxVectorData& dst,
284 size_t dst_index,
285 size_t n)
286{
287 const size_t dst_sz = dst.size_v();
289
290 // Make sure there are no trailing zeros in the destination.
291 fillTrailingZeros (v, dst_sz, dst_sz, lv);
292
293 size_t begin = v[dst_index].begin(dst_index);
294 size_t end = v[dst_index+n-1].end();
295
296 size_t n_payload = end - begin;
297
298 // Erase the payload elements.
299 lv->shift (end, - n_payload);
300
301 // Adjust indices for following elements.
302 std::for_each (v+dst_index+n, v+dst_sz, Shift (-n_payload));
303 // Clear out the given range.
304 std::fill_n (v+dst_index, n, JaggedVecEltBase(begin));
305}
306
307
308} // namespace SG::JaggedVecVectorFactoryFuncs
@ Shift
Factory object that creates vectors using AuxTypeVector, specialized for JaggedVec.
static Double_t sz
static Double_t a
void clear()
Empty the pool.
Handle mappings between names and auxid_t.
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Manage lookup of vectors of auxiliary data.
void clearCache()
Clear the cached aux data pointers.
virtual size_t size_v() const =0
Return the size of the container.
const void * getDataArray(SG::auxid_t auxid) const
Return a const pointer to the start of an aux data vector.
SG::IAuxStore * getStore()
Return the current store, as a non-const interface.
virtual IAuxTypeVector * linkedVector(SG::auxid_t)
Definition IAuxStore.h:187
Interface for factory objects that create vectors.
virtual void copyForOutput(SG::auxid_t auxid, AuxVectorData &dst, size_t dst_index, const AuxVectorData &src, size_t src_index, size_t n) const =0
Copy elements between vectors, possibly applying thinning.
virtual void copy(SG::auxid_t auxid, AuxVectorData &dst, size_t dst_index, const AuxVectorData &src, size_t src_index, size_t n) const =0
Copy elements between vectors.
virtual void swap(SG::auxid_t auxid, AuxVectorData &a, size_t aindex, AuxVectorData &b, size_t bindex, size_t n) const =0
Swap elements between vectors.
Abstract interface for manipulating vectors of arbitrary types.
auxid_t auxid() const
Return the auxid of the variable this vector represents.
virtual bool shift(size_t pos, ptrdiff_t offs)=0
Shift the elements of the vector.
const AuxDataSpanBase & getDataSpan() const
Return a reference to a description of this vector's start+size.
Describe one element of a jagged vector (base class).
index_type end() const
Return the index of the end of the range.
int r
Definition globals.cxx:22
void fillTrailingZeros(JaggedVecEltBase *elts, size_t index, size_t sz, IAuxTypeVector *lv)
Fill in trailing zeros in a range.
void copyImpl(SG::auxid_t auxid, AuxVectorData &dst, size_t dst_index, const AuxVectorData &src, size_t src_index, size_t n, bool for_output)
Copy elements between vectors: out-of-line portion.
void swap(SG::auxid_t auxid, AuxVectorData &a, size_t aindex, AuxVectorData &b, size_t bindex, size_t n)
Swap elements between vectors.
SG::auxid_t auxid() const
Return the aux id for this variable.
virtual void shift(size_t pos, ptrdiff_t offs) override
Shift the elements of the container.
void throwJaggedVecOverlappingCopy()
Throw a SG::ExcJaggedVecOverlappingCopy exception.
size_t auxid_t
Identifier for a particular aux data item.
Definition AuxTypes.h:27
Definition index.py:1
DataModel_detail::iterator< DV > swap_ranges(DataModel_detail::iterator< DV > first1, DataModel_detail::iterator< DV > last1, DataModel_detail::iterator< DV > first2)
Specialization of swap_ranges for DataVector/DataList.
size_t size
The length of the variable's vector.
Definition AuxDataSpan.h:57