Fixed the assignment operator
[OpenFOAM-1.6.x.git] / src / OpenFOAM / containers / Lists / PackedList / PackedList.H
blob2ef6d29d0c98a3b50be99a347f4859248438dd2b
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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
25 Class
26     Foam::PackedList
28 Description
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.
37 Note
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:
46     @code
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
50     @endcode
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.
60     @code
61         list[5] = 4;
62         changed = list.set(5, 8);
63         if (changed) ...
64     @endcode
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.
69     For example,
70     @code
71         list.resize(4);
72         Info<< list[10] << "\n";  // print zero, but doesn't adjust list
73         list[8] = 1;
74     @endcode
76 SeeAlso
77     Foam::DynamicList
79 SourceFiles
80     PackedListI.H
81     PackedList.C
83 \*---------------------------------------------------------------------------*/
85 #ifndef PackedList_H
86 #define PackedList_H
88 #include "labelList.H"
89 #include "StaticAssert.H"
91 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
93 namespace Foam
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>
114 class PackedList
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));
125     // Private data
127         //- Number of nBits entries
128         label size_;
130     // Private Member Functions
132         //- Calculate the list length when packed
133         inline static label packedLength(const label);
135 public:
137     // Public data
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
155         class iteratorBase;
156         class iterator;
157         class const_iterator;
159     // Constructors
161         //- Null constructor
162         inline PackedList();
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>&);
179         //- Clone
180         inline autoPtr< PackedList<nBits> > clone() const;
182     // Member Functions
184         // Access
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;
225         // Edit
227         //- Trim any trailing zero elements
228         bool trim();
230         //- Invert the bits in the addressable region.
231         void flip();
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
253         inline void clear();
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();
269     // Member operators
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>&);
295     // Ostream operator
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.
305         class iteratorBase
306         {
307             friend class PackedList;
309         protected:
311             // Protected Data
313                 //- Pointer to original list
314                 //  This also lets us use the default bitwise copy/assignment
315                 PackedList* list_;
317                 //- Element index
318                 label index_;
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);
328             // Constructors
330                 //- Construct null
331                 inline iteratorBase();
333                 //- Construct from base list and position index
334                 inline iteratorBase(const PackedList*, const label);
336         public:
338             // Member Operators
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&);
348                 //- Assign value.
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;
358         };
361         //- The iterator class used for PackedList
362         class iterator
363         :
364             public iteratorBase
365         {
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&);
373         public:
375             // Constructors
377                 //- Construct null
378                 inline 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);
388             // Member Operators
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&);
398                 //- Return value
399                 inline unsigned int operator*() const;
401                 //- Return value
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);
416         };
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
426         class const_iterator
427         :
428             public iteratorBase
429         {
430         public:
432             // Constructors
434                 //- Construct null
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&);
448             // Member operators
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);
470         };
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 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
498 #ifdef NoRepository
499 #   include "PackedList.C"
500 #endif
502 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
504 #endif
506 // ************************************************************************* //