1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2011 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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
28 A dynamically allocatable list of packed unsigned integers.
30 The list resizing is similar to DynamicList, thus the methods clear()
31 and setSize() behave like their DynamicList counterparts and the methods
32 reserve() and setCapacity() can be used to influence the allocation.
34 The number of bits per item is specified by the template parameter nBits.
37 In a const context, the '[]' operator simply returns the stored value,
38 with out-of-range elements returned as zero.
39 In a non-const context, the '[]' operator returns an iteratorBase, which
40 might not have a valid reference for out-of-range elements.
41 The iteratorBase class handles the assignment of new values.
43 Using the iteratorBase as a proxy allows assignment of values
44 between list elements. Thus the following bit of code works as expected:
46 list[1] = list[5]; // value assignment, not iterator position
47 list[2] = list[5] = 4; // propagates value
48 list[1] = list[5] = list[6]; // propagates value
51 Using get() or the '[]' operator are similarly fast. Looping and reading
52 via an iterator is approx. 15% slower, but can be more flexible.
54 Using the set() operator (and the '[]' operator) are marginally slower
55 (approx. 5%) than using an iterator, but the set() method has the
56 advantage of also returning a bool if the value changed. This can be
57 useful for branching on changed values.
61 changed = list.set(5, 8);
65 The lazy evaluation used means that reading an out-of-range element
66 returns zero, but does not affect the list size. Even in a non-const
67 context, only the assigment itself causes the element to be created.
71 Info<< list[10] << "\n"; // print zero, but doesn't adjust list
75 Also note that all unused internal storage elements are guaranteed to
76 always be bit-wise zero. This property must not be violated by any
79 In addition to the normal output format, PackedList also supports a
80 compact ASCII format that may be convenient for user input in some
81 situations. The general format is a group of index/value pairs:
83 { (index1 value1) (index2 value2) (index3 value3) }
85 The bool specialization just uses the indices corresponding to
86 non-zero entries instead of a index/value pair:
88 { index1 index2 index3 }
90 In both cases, the supplied indices can be randomly ordered.
99 \*---------------------------------------------------------------------------*/
104 #include "labelList.H"
105 #include "UIndirectList.H"
106 #include "StaticAssert.H"
108 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
113 // Forward declaration of classes
117 // Forward declaration of friend functions and operators
118 template<unsigned nBits> class PackedList;
120 template<unsigned nBits>
121 Istream& operator>>(Istream&, PackedList<nBits>&);
122 template<unsigned nBits>
123 Ostream& operator<<(Ostream&, const PackedList<nBits>&);
126 /*---------------------------------------------------------------------------*\
127 Class PackedListCore Declaration
128 \*---------------------------------------------------------------------------*/
130 //- Template-invariant bits for PackedList
131 struct PackedListCore
137 //- Define template name and debug
138 ClassName("PackedList");
142 /*---------------------------------------------------------------------------*\
143 Class PackedList Declaration
144 \*---------------------------------------------------------------------------*/
146 template<unsigned nBits=1>
149 public PackedListCore,
150 private List<unsigned int>
154 typedef unsigned int StorageType;
155 typedef List<StorageType> StorageList;
157 // Protected Member Functions
159 //- Calculate the list length when packed
160 inline static label packedLength(const label);
162 //- Read a list entry (allows for specialization)
163 inline static unsigned int readValue(Istream&);
165 //- Read an index/value pair and set accordingly.
166 // For bool specialization, read a single index value
167 inline void setPair(Istream&);
172 //- nBits must be positive (non-zero) and fit within the storage.
173 // For efficiency, however, require packing at least 2 items otherwise
174 // it is more efficient to use a normal list.
175 // Thus max nBits is 1/2 of the base storage size.
176 // For simplicity, assume 8-bit bytes in the assert.
177 StaticAssert(nBits && nBits <= (sizeof(StorageType) << 2));
181 //- Number of nBits entries
189 //- The max. number of bits that can be templated.
190 // Might someday be useful for a template assert.
191 inline static unsigned int max_bits();
193 //- The max. value for an entry, which simultaneously the bit-mask
194 // eg, ((1 << 2) - 1) yields 0b0011
195 inline static unsigned int max_value();
197 //- The number of entries per packed storage element
198 inline static unsigned int packing();
200 //- Masking for all bits below the offset
201 inline static unsigned int maskLower(unsigned offset);
204 // Forward declaration of iterators
208 class const_iterator;
216 //- Construct with given size, initializes list to 0
217 explicit inline PackedList(const label size);
219 //- Construct with given size and value for all elements
220 inline PackedList(const label size, const unsigned val);
222 //- Construct from Istream
223 inline PackedList(Istream&);
226 inline PackedList(const PackedList<nBits>&);
228 //- Construct by transferring the parameter contents
229 inline PackedList(const Xfer<PackedList<nBits> >&);
231 //- Construct from a list of labels
232 explicit inline PackedList(const labelUList&);
234 //- Construct from an indirect list of labels
235 explicit inline PackedList(const UIndirectList<label>&);
238 inline autoPtr< PackedList<nBits> > clone() const;
245 //- The number of elements that can be stored before reallocating
246 inline label capacity() const;
248 //- Number of entries.
249 inline label size() const;
251 //- Return true if the list is empty (ie, size() is zero).
252 inline bool empty() const;
254 //- Get value at index I.
255 // Never auto-vivify entries.
256 inline unsigned int get(const label) const;
258 //- Set value at index I. Return true if value changed.
259 // Does auto-vivify for non-existent entries.
260 // Default value set is the max_value.
261 inline bool set(const label, const unsigned int val = ~0u);
263 //- Unset the entry at index I. Return true if value changed.
264 // Never auto-vivify entries.
265 inline bool unset(const label);
267 //- Return the underlying packed storage
268 // Manipulate with utmost caution
269 inline List<unsigned int>& storage();
271 //- Return the underlying packed storage
272 inline const List<unsigned int>& storage() const;
274 //- The list length when packed
275 inline label packedLength() const;
277 //- Return the binary size in number of characters
278 // used in the underlying storage
279 inline label byteSize() const;
281 //- Count number of bits set, O(log(n))
282 // Uses the Hamming weight (population count) method
283 // http://en.wikipedia.org/wiki/Hamming_weight
284 unsigned int count() const;
286 //- Return the values as a list of labels
287 Xfer<labelList> values() const;
289 //- Print bit patterns, optionally output unused elements
294 // non-addressable bits:
297 Ostream& printBits(Ostream&, const bool fullOutput=false) const;
299 //- Print information and bit patterns (with printBits)
300 Ostream& printInfo(Ostream&, const bool fullOutput=false) const;
305 //- Trim any trailing zero elements
308 //- Invert the bits in the addressable region
314 //- Alter the size of the underlying storage.
315 // The addressed size will be truncated if needed to fit, but will
316 // remain otherwise untouched.
317 inline void setCapacity(const label);
319 //- Reset addressable list size, does not shrink the allocated size.
320 // Optionally specify a value for new elements.
321 inline void resize(const label, const unsigned int& val = 0u);
323 //- Alias for resize()
324 inline void setSize(const label, const unsigned int& val = 0u);
326 //- Reserve allocation space for at least this size.
327 // Never shrinks the allocated size.
328 // The list size is adjusted as per DynamicList with
329 // SizeInc=0, SizeMult=2, SizeDiv=1
330 inline void reserve(const label);
332 //- Clear the list, i.e. set addressable size to zero.
333 // Does not adjust the underlying storage
336 //- Clear the list and delete storage.
337 inline void clearStorage();
339 //- Shrink the allocated space to what is actually used.
340 inline void shrink();
342 //- Transfer the contents of the argument list into this list
343 // and annul the argument list.
344 inline void transfer(PackedList<nBits>&);
346 //- Transfer contents to the Xfer container
347 inline Xfer<PackedList<nBits> > xfer();
352 //- Clear list and read from stream
353 Istream& read(Istream&);
355 //- Write, optionally with indexedOutput
357 // The indexed output may be convenient in some situations.
358 // The general format is a group of index/value pairs:
360 // { (index1 value1) (index2 value2) (index3 value3) }
362 // The bool specialization just uses the indices corresponding to
363 // non-zero entries instead of a index/value pair:
365 // { index1 index2 index3 }
368 // Note the indexed output is only supported for ASCII streams.
372 const bool indexedOutput=false
376 //- Write as a dictionary entry
377 void writeEntry(Ostream&) const;
379 //- Write as a dictionary entry with keyword
380 void writeEntry(const word& keyword, Ostream&) const;
385 //- Append a value at the end of the list
386 inline PackedList<nBits>& append(const unsigned int val);
388 //- Remove and return the last element
389 inline unsigned int remove();
391 //- Get value at index I
392 // Never auto-vivify entries.
393 inline unsigned int operator[](const label) const;
395 //- Set value at index I.
396 // Returns iterator to perform the actual operation.
397 // Does not auto-vivify entries, but will when assigned to.
398 inline iteratorBase operator[](const label);
400 //- Assignment of all entries to the given value. Takes linear time.
401 inline PackedList<nBits>& operator=(const unsigned int val);
403 //- Assignment operator.
404 PackedList<nBits>& operator=(const PackedList<nBits>&);
406 //- Assignment operator.
407 PackedList<nBits>& operator=(const labelUList&);
409 //- Assignment operator.
410 PackedList<nBits>& operator=(const UIndirectList<label>&);
413 // Iterators and helpers
415 //- The iterator base for PackedList
416 // Note: data and functions are protected, to allow reuse by iterator
417 // and prevent most external usage.
420 friend class PackedList;
426 //- Pointer to original list
427 // This also lets us use the default bitwise copy/assignment
434 // Protected Member Functions
436 //- Get value as unsigned, no range-checking
437 inline unsigned int get() const;
439 //- Set value, returning true if changed, no range-checking
440 inline bool set(unsigned int);
446 inline iteratorBase();
448 //- Construct from base list and position index
449 inline iteratorBase(const PackedList*, const label);
456 //- Return the element index corresponding to the iterator
457 inline label key() const;
459 //- Write index/value for a non-zero entry
460 // The bool specialization writes the index only
461 inline bool writeIfSet(Ostream&) const;
465 //- Compare values (not positions)
466 inline bool operator==(const iteratorBase&) const;
467 inline bool operator!=(const iteratorBase&) const;
469 //- Assign value, not position.
470 // This allows packed[0] = packed[3] for assigning values
471 inline unsigned int operator=(const iteratorBase&);
474 // A non-existent entry will be auto-vivified.
475 inline unsigned int operator=(const unsigned int val);
477 //- Conversion operator
478 // Never auto-vivify entries.
479 inline operator unsigned int () const;
481 //- Print information and values
482 Ostream& printInfo(Ostream&) const;
486 //- The iterator class used for PackedList
492 //- Disallow copy constructor from const_iterator
493 // This would violate const-ness!
494 iterator(const const_iterator&);
496 //- Disallow assignment from const_iterator
497 // This would violate const-ness!
498 void operator=(const const_iterator&);
508 //- Construct from iterator base, eg iter(packedlist[i])
509 // but also "iterator iter = packedlist[i];"
510 // An out-of-range iterator is assigned end()
511 inline iterator(const iteratorBase&);
513 //- Construct from base list and position index
514 inline iterator(const PackedList*, const label);
519 //- Compare positions (not values)
520 inline bool operator==(const iteratorBase&) const;
521 inline bool operator!=(const iteratorBase&) const;
523 //- Assign from iteratorBase, eg iter = packedlist[i]
524 // An out-of-range iterator is assigned end()
525 inline iterator& operator=(const iteratorBase&);
528 inline unsigned int operator*() const;
531 inline unsigned int operator()() const;
533 //- Return iteratorBase for assigning values
534 inline iteratorBase& operator*();
536 //- Return iteratorBase for assigning values
537 inline iteratorBase& operator()();
539 inline iterator& operator++();
540 inline iterator operator++(int);
542 inline iterator& operator--();
543 inline iterator operator--(int);
547 //- iterator set to the beginning of the PackedList
548 inline iterator begin();
550 //- iterator set to beyond the end of the PackedList
551 inline iterator end();
554 //- The const_iterator for PackedList
564 inline const_iterator();
566 //- Construct from iterator base, eg iter(packedlist[i])
567 // but also "const_iterator iter = packedlist[i];"
568 // An out-of-range iterator is assigned cend()
569 inline const_iterator(const iteratorBase&);
571 //- Construct from base list and position index
572 inline const_iterator(const PackedList*, const label);
574 //- Construct from iterator
575 inline const_iterator(const iterator&);
580 //- Compare positions (not values)
581 inline bool operator==(const iteratorBase&) const;
582 inline bool operator!=(const iteratorBase&) const;
584 //- Assign from iteratorBase or derived
585 // eg, iter = packedlist[i] or even iter = list.begin()
586 inline const_iterator& operator=(const iteratorBase&);
588 //- Return referenced value directly
589 inline unsigned int operator*() const;
591 //- Return referenced value directly
592 inline unsigned int operator()() const;
594 inline const_iterator& operator++();
595 inline const_iterator operator++(int);
597 inline const_iterator& operator--();
598 inline const_iterator operator--(int);
602 //- const_iterator set to the beginning of the PackedList
603 inline const_iterator cbegin() const;
605 //- const_iterator set to beyond the end of the PackedList
606 inline const_iterator cend() const;
608 //- const_iterator set to the beginning of the PackedList
609 inline const_iterator begin() const;
611 //- const_iterator set to beyond the end of the PackedList
612 inline const_iterator end() const;
615 // IOstream Operators
617 friend Istream& operator>> <nBits>
623 friend Ostream& operator<< <nBits>
626 const PackedList<nBits>&
631 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
633 } // End namespace Foam
635 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
637 #include "PackedListI.H"
639 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
642 # include "PackedList.C"
645 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
649 // ************************************************************************* //