1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 A dynamically allocatable list of packed unsigned integers.
31 The list resizing is similar to DynamicList, thus the methods clear()
32 and setSize() behave like their DynamicList counterparts and the methods
33 reserve() and setCapacity() can be used to influence the allocation.
35 The number of bits per item is specified by the template parameter nBits.
38 In a const context, the '[]' operator simply returns the stored value,
39 with out-of-range elements returned as zero.
40 In a non-const context, the '[]' operator returns an iteratorBase, which
41 might not have a valid reference for out-of-range elements.
42 The iteratorBase class handles the assignment of new values.
44 Using the iteratorBase as a proxy allows assignment of values
45 between list elements. Thus the following bit of code works as expected:
47 list[1] = list[5]; // value assignment, not iterator position
48 list[2] = list[5] = 4; // propagates value
49 list[1] = list[5] = list[6]; // propagates value
52 Using get() or the '[]' operator are similarly fast. Looping and reading
53 via an iterator is approx. 15% slower, but can be more flexible.
55 Using the set() operator (and the '[]' operator) are marginally slower
56 (approx. 5%) than using an iterator, but the set() method has the
57 advantage of also returning a bool if the value changed. This can be
58 useful for branching on changed values.
62 changed = list.set(5, 8);
66 The lazy evaluation used means that reading an out-of-range element
67 returns zero, but does not affect the list size. Even in a non-const
68 context, only the assigment itself causes the element to be created.
72 Info<< list[10] << "\n"; // print zero, but doesn't adjust list
83 \*---------------------------------------------------------------------------*/
88 #include "labelList.H"
89 #include "StaticAssert.H"
91 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
96 // Forward declaration of friend functions and operators
97 template<unsigned nBits> class PackedList;
99 // template<unsigned nBits>
100 // Ostream& operator<<(Ostream&, const PackedList<nBits>&);
103 /*---------------------------------------------------------------------------*\
104 Class PackedListName Declaration
105 \*---------------------------------------------------------------------------*/
107 TemplateName(PackedList);
109 /*---------------------------------------------------------------------------*\
110 Class PackedList Declaration
111 \*---------------------------------------------------------------------------*/
113 template<unsigned nBits=1>
116 private List<unsigned int>
118 typedef unsigned int StorageType;
119 typedef List<StorageType> StorageList;
121 //- nBits must be positive (non-zero) and fit within the storage
122 // For simplicity, assume 8-bit bytes
123 StaticAssert(nBits && nBits < (sizeof(StorageType) << 3));
127 //- Number of nBits entries
130 // Private Member Functions
132 //- Calculate the list length when packed
133 inline static label packedLength(const label);
139 //- The max. number of bits that can be templated.
140 // Might someday be useful for a template assert.
141 inline static unsigned int max_bits();
143 //- The max. value for an entry, which simultaneously the bit-mask
144 // eg, ((1 << 2) - 1) yields 0b0011
145 inline static unsigned int max_value();
147 //- The number of entries per packed storage element
148 inline static unsigned int packing();
150 //- Masking for all bits below the offset
151 inline static unsigned int maskLower(unsigned offset);
153 // Forward declaration of iterators
157 class const_iterator;
164 //- Construct with given size, initializes list to 0.
165 explicit inline PackedList(const label size);
167 //- Construct with given size and value for all elements.
168 PackedList(const label size, const unsigned val);
170 //- Copy constructor.
171 inline PackedList(const PackedList<nBits>&);
173 //- Construct by transferring the parameter contents
174 inline PackedList(const Xfer< PackedList<nBits> >&);
176 //- Construct from a list of labels
177 explicit PackedList(const UList<label>&);
180 inline autoPtr< PackedList<nBits> > clone() const;
186 //- The number of elements that can be stored before reallocating
187 inline label capacity() const;
189 //- Number of entries.
190 inline label size() const;
192 //- Return true if the list is empty (ie, size() is zero).
193 inline bool empty() const;
195 //- Get value at index I.
196 // Never auto-vivify entries.
197 inline unsigned int get(const label) const;
199 //- Set value at index I. Return true if value changed.
200 // Does auto-vivify for non-existent entries.
201 // Default value set is the max_value.
202 inline bool set(const label, const unsigned int val = ~0u);
204 //- Unset the entry at index I. Return true if value changed.
205 // Never auto-vivify entries.
206 inline bool unset(const label);
208 //- Return the underlying packed storage
209 inline List<unsigned int>& storage();
211 //- Return the underlying packed storage
212 inline const List<unsigned int>& storage() const;
214 //- Count number of bits set, O(log(n))
215 // Uses the Hamming weight (population count) method
216 // http://en.wikipedia.org/wiki/Hamming_weight
217 unsigned int count() const;
219 //- Return the values as a labelList
220 labelList values() const;
222 //- Print values and information
223 Ostream& print(Ostream&) const;
227 //- Trim any trailing zero elements
230 //- Invert the bits in the addressable region.
233 //- Alter the size of the underlying storage.
234 // The addressed size will be truncated if needed to fit, but will
235 // remain otherwise untouched.
236 inline void setCapacity(const label);
238 //- Reset addressable list size, does not shrink the allocated size.
239 // Optionally specify a value for new elements.
240 inline void resize(const label, const unsigned int& val = 0);
242 //- Alias for resize()
243 inline void setSize(const label, const unsigned int& val = 0);
245 //- Reserve allocation space for at least this size.
246 // Never shrinks the allocated size.
247 // The list size is adjusted as per DynamicList with
248 // SizeInc=0, SizeMult=2, SizeDiv=1
249 inline void reserve(const label);
251 //- Clear the list, i.e. set addressable size to zero.
252 // Does not adjust the underlying storage
255 //- Clear the list and delete storage.
256 inline void clearStorage();
258 //- Shrink the allocated space to what is actually used.
259 inline void shrink();
261 //- Transfer the contents of the argument list into this list
262 // and annul the argument list.
263 inline void transfer(PackedList<nBits>&);
265 //- Transfer contents to the Xfer container
266 inline Xfer< PackedList<nBits> > xfer();
271 //- Append a value at the end of the list
272 inline void append(const unsigned int val);
274 //- Remove and return the last element
275 inline unsigned int remove();
277 //- Get value at index I
278 // Never auto-vivify entries.
279 inline unsigned int operator[](const label) const;
281 //- Set value at index I.
282 // Returns iterator to perform the actual operation.
283 // Does not auto-vivify entries, but will when assigned to.
284 inline iteratorBase operator[](const label);
286 //- Assignment of all entries to the given value. Takes linear time.
287 inline void operator=(const unsigned int val);
289 //- Assignment operator. Takes linear time.
290 void operator=(const PackedList<nBits>&);
292 //- Assignment operator. Takes linear time.
293 void operator=(const UList<label>&);
297 // // Write PackedList to Ostream.
298 // friend Ostream& operator<< <nBits> (Ostream&, const PackedList<nBits>&);
300 // Iterators and helpers
302 //- The iterator base for PackedList
303 // Note: data and functions are protected, to allow reuse by iterator
304 // and prevent most external usage.
307 friend class PackedList;
313 //- Pointer to original list
314 // This also lets us use the default bitwise copy/assignment
320 // Protected Member Functions
322 //- Get value as unsigned, no range-checking
323 inline unsigned int get() const;
325 //- Set value, returning true if changed, no range-checking
326 inline bool set(unsigned int);
331 inline iteratorBase();
333 //- Construct from base list and position index
334 inline iteratorBase(const PackedList*, const label);
340 //- Compare values (not positions)
341 inline bool operator==(const iteratorBase&) const;
342 inline bool operator!=(const iteratorBase&) const;
344 //- Assign value, not position.
345 // This allows packed[0] = packed[3] for assigning values
346 inline unsigned int operator=(const iteratorBase&);
349 // A non-existent entry will be auto-vivified.
350 inline unsigned int operator=(const unsigned int val);
352 //- Conversion operator
353 // Never auto-vivify entries.
354 inline operator unsigned int () const;
356 //- Print value and information
357 Ostream& print(Ostream&) const;
361 //- The iterator class used for PackedList
367 //- Disallow copy constructor from const_iterator - violates const-ness!
368 iterator(const const_iterator&);
370 //- Disallow assignment from const_iterator - violates const-ness!
371 void operator=(const const_iterator&);
380 //- Construct from iterator base, eg iter(packedlist[i])
381 // but also "iterator iter = packedlist[i];"
382 // An out-of-range iterator is assigned end()
383 inline iterator(const iteratorBase&);
385 //- Construct from base list and position index
386 inline iterator(const PackedList*, const label);
390 //- Compare positions (not values)
391 inline bool operator==(const iteratorBase&) const;
392 inline bool operator!=(const iteratorBase&) const;
394 //- Assign from iteratorBase, eg iter = packedlist[i]
395 // An out-of-range iterator is assigned end()
396 inline iterator& operator=(const iteratorBase&);
399 inline unsigned int operator*() const;
402 inline unsigned int operator()() const;
404 //- Return iteratorBase for assigning values
405 inline iteratorBase& operator*();
407 //- Return iteratorBase for assigning values
408 inline iteratorBase& operator()();
410 inline iterator& operator++();
411 inline iterator operator++(int);
413 inline iterator& operator--();
414 inline iterator operator--(int);
418 //- iterator set to the beginning of the PackedList
419 inline iterator begin();
421 //- iterator set to beyond the end of the PackedList
422 inline iterator end();
425 //- The const_iterator for PackedList
435 inline const_iterator();
437 //- Construct from iterator base, eg iter(packedlist[i])
438 // but also "const_iterator iter = packedlist[i];"
439 // An out-of-range iterator is assigned cend()
440 inline const_iterator(const iteratorBase&);
442 //- Construct from base list and position index
443 inline const_iterator(const PackedList*, const label);
445 //- Construct from iterator
446 inline const_iterator(const iterator&);
450 //- Compare positions (not values)
451 inline bool operator==(const iteratorBase&) const;
452 inline bool operator!=(const iteratorBase&) const;
454 //- Assign from iteratorBase or derived
455 // eg, iter = packedlist[i] or even iter = list.begin()
456 inline const_iterator& operator=(const iteratorBase&);
458 //- Return referenced value directly
459 inline unsigned int operator*() const;
461 //- Return referenced value directly
462 inline unsigned int operator()() const;
464 inline const_iterator& operator++();
465 inline const_iterator operator++(int);
467 inline const_iterator& operator--();
468 inline const_iterator operator--(int);
473 //- const_iterator set to the beginning of the PackedList
474 inline const_iterator cbegin() const;
476 //- const_iterator set to beyond the end of the PackedList
477 inline const_iterator cend() const;
479 //- const_iterator set to the beginning of the PackedList
480 inline const_iterator begin() const;
482 //- const_iterator set to beyond the end of the PackedList
483 inline const_iterator end() const;
488 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
490 } // End namespace Foam
492 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
494 #include "PackedListI.H"
496 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
499 # include "PackedList.C"
502 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
506 // ************************************************************************* //