ATLAS Offline Software
Loading...
Searching...
No Matches
PackedArray.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
10
11
14#include <stdexcept>
15#include <climits>
16#include <cassert>
17
18
19namespace {
20
21
23const int nper = sizeof (unsigned int) * CHAR_BIT;
24
25
30inline
32{
33 return (1<<sz) - 1;
34}
35
36
37} // anonymous namespace
38
39
40namespace CxxUtils {
41
42
48inline
50{
51 return (n * m_bitsize + nper-1) / nper;
52}
53
54
59inline
61{
62 return (n * m_bitsize) / nper;
63}
64
65
70inline
72{
73 return (n * m_bitsize) % nper;
74}
75
76
83inline
85{
86 // Get the bits from the first entry.
87 value_type v = m_vec[ndx] >> off;
88
89 // If the packed entry wraps between two base entries, collect the bits
90 // from the next base entry.
91 if (m_bitsize > nper - off) {
92 int bits = m_bitsize - (nper - off);
93 // cppcheck-suppress shiftTooManyBits; false positive
94 // m_bitsize <= nper
95 v |= ((m_vec[ndx+1] & mask(bits)) << (nper - off));
96 }
97
98 // Mask down to the proper number of bits.
99 return v & m_mask;
100}
101
102
110inline
112{
113 // Set the bits in the first entry.
114 m_vec[ndx] = (m_vec[ndx] & ~(m_mask<<off)) | ((v&m_mask) << off);
115
116 // If the packed entry wraps between two base entries, set the bits
117 // in the next entry.
118 if (m_bitsize > nper - off) {
119 value_type mask2 = mask (m_bitsize - (nper - off));
120 m_vec[ndx+1] = (m_vec[ndx+1] & ~mask2) | ((v >> (nper - off)) & mask2);
121 }
122}
123
124
130{
131 if (n >= m_size) {
132 throw_out_of_range (__PRETTY_FUNCTION__, n, m_size, this);
133 }
134}
135
136
145 const allocator_type& allocator/*=allocator_type()*/)
146 : m_bitsize (bitsize),
147 m_size (0),
148 m_mask (mask (bitsize)),
149 m_vec (allocator)
150{
151 assert (m_bitsize > 0 && m_bitsize <= nper);
152}
153
154
165 size_type n,
166 value_type val /*= 0*/,
167 const allocator_type& allocator/*=allocator_type()*/)
168 : m_bitsize (bitsize),
169 m_size (n),
170 m_mask (mask (bitsize)),
171 m_vec (nbase(n), 0, allocator)
172{
173 assert (m_bitsize > 0 && m_bitsize <= nper);
174 if (val != 0) {
175 for (size_type i = 0; i < n; i++)
176 set (i, val);
177 }
178}
179
180
187{
188 m_size = n;
189 m_vec.clear();
190 m_vec.resize (nbase(n));
191 if (u != 0) {
192 for (size_type i = 0; i < n; i++)
193 set (i, u);
194 }
195}
196
197
202{
203 return m_vec.get_allocator();
204}
205
206
211{
212 return m_size;
213}
214
215
220{
221 return m_vec.max_size();
222}
223
224
230{
231 return m_vec.capacity() * nper / m_bitsize;
232}
233
234
241{
242 m_vec.resize (nbase (sz));
243 if (sz > m_size) {
244 // Making the container bigger. Need to fill the remaining values.
245 if (c != 0) {
246 // Set them to something non-zero.
247 for (size_t i = m_size; i < sz; i++)
248 set (i, c);
249 }
250 else {
251 // Filling the new entries with 0.
252 // New elements in the base vector will have been set to 0.
253 // However, we also need to zero out any remaining packed elements
254 // (or piece thereof) in the last base element that was occupied
255 // before the resize.
256 int off = tooff (m_size);
257 // Don't need to do anything if packed entries exactly fit
258 // in the allocated base size.
259 if (off != 0) {
260 size_t ndx = tondx (m_size);
261 m_vec[ndx] &= mask (off);
262 }
263 }
264 }
265 m_size = sz;
266}
267
268
273{
274 return m_size == 0;
275}
276
277
284{
285 m_vec.reserve (nbase (n));
286}
287
288
294{
295 return doget (tondx (n), tooff (n));
296}
297
298
305{
306 return doset (tondx (n), tooff (n), val);
307}
308
309
322
323
333{
334 return proxy (*this, n);
335}
336
337
347{
348 range_check (n);
349 return doget (tondx (n), tooff (n));
350}
351
352
362{
363 range_check (n);
364 return proxy (*this, n);
365}
366
367
376{
377 return doget (0, 0);
378}
379
380
389{
390 return doget (tondx (m_size-1), tooff (m_size-1));
391}
392
393
402{
403 return proxy (*this, 0);
404}
405
406
415{
416 return proxy (*this, m_size-1);
417}
418
419
425{
426 ++m_size;
427 size_t nb = nbase (m_size);
428 if (nb != m_vec.size())
429 m_vec.resize (nb);
430 doset (tondx (m_size-1), tooff (m_size-1), x);
431}
432
433
438{
439 --m_size;
440 size_t nb = nbase (m_size);
441 if (nb != m_vec.size())
442 m_vec.resize (nb);
443}
444
445
451{
452 std::swap (m_bitsize, other.m_bitsize);
453 std::swap (m_size, other.m_size);
454 std::swap (m_mask, other.m_mask);
455 std::swap (m_vec, other.m_vec);
456}
457
458
463{
464 m_size = 0;
465 m_vec.clear();
466}
467
468
476{
477 assert (m_size == 0);
478 assert (bitsize > 0 && bitsize <= nper);
480 m_mask = mask (bitsize);
481}
482
483
488{
489 return m_bitsize;
490}
491
492
493} // namespace CxxUtils
static Double_t sz
An array of unsigned values of some bit size, packed tightly.
#define x
proxy class for representing an lvalue to an element of PackedArray.
Definition PackedArray.h:58
int m_bitsize
The current bitsize of the container.
size_type size() const
Returns the number of elements in the collection.
void set_bitsize(int bitsize)
Change the bitsize of the container.
allocator_type get_allocator() const
Returns the allocator of the underlying vector.
size_t tondx(size_type n) const
Find the index in the base vector where entry starts.
void clear()
Erase all the elements in the collection.
size_type m_size
The current number of entries in the container.
value_type front() const
Access the first element in the collection as an rvalue.
value_type operator[](size_type n) const
Access an element, as an rvalue.
value_type m_mask
Mask with m_bitsize bits set.
size_type capacity() const
Returns the total number of elements that the collection can hold before needing to allocate more mem...
basetype m_vec
Underlying vector holding the data.
void range_check(size_type n) const
Check that n is in range and throw out_of_range if not.
value_type doget(size_type ndx, int off) const
Return the entry at base index ndx/offset off.
PackedArray(int bitsize=8, const allocator_type &allocator=allocator_type())
Constructor.
void doset(size_type ndx, int off, value_type v)
Set the entry at base index ndx/offset off to v.
int bitsize() const
Return the bitsize of the container.
value_type at(size_type n) const
Access an element, as an rvalue.
size_type max_size() const
Returns the size() of the largest possible collection.
void resize(size_type sz, value_type c=0)
Resizes the collection to the specified number of elements.
int tooff(size_type n) const
Find the bit offset of entry within its entry in the base vector.
value_type get(size_type n) const
Return the entry at index n.
void assign(size_type n, value_type u)
Set the container to multiple copies of the same value.
bool empty() const
Returns true if the collection is empty.
void push_back(value_type x)
Add an element to the end of the collection.
value_type back() const
Access the last element in the collection as an rvalue.
void swap(PackedArray &other)
Swap this collection with another.
void pop_back()
Remove the last element from the collection.
size_t nbase(size_type n) const
Calculate the number of entries in the base vector needed to hold entries with the current bitsize.
basetype::allocator_type allocator_type
Definition PackedArray.h:51
void reserve(size_type n)
Attempt to preallocate enough memory for a specified number of elements.
void set(size_type n, value_type val)
Set the entry at index n.
unsigned int value_type
Definition PackedArray.h:50
void throw_out_of_range(const std::string &what, size_t index, size_t size, const void *obj)
Throw an out_of_range exception.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
Helpers for throwing out_of_range exceptions.