PackedList.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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.
20 
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/>.
23 
24 Class
25  Foam::PackedList
26 
27 Description
28  A dynamically allocatable list of packed unsigned integers.
29 
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.
33 
34  The number of bits per item is specified by the template parameter nBits.
35 
36 Note
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.
42 
43  Using the iteratorBase as a proxy allows assignment of values
44  between list elements. Thus the following bit of code works as expected:
45  \code
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
49  \endcode
50 
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.
53 
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.
58 
59  \code
60  list[5] = 4;
61  changed = list.set(5, 8);
62  if (changed) ...
63  \endcode
64 
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.
68  For example,
69  \code
70  list.resize(4);
71  Info<< list[10] << "\n"; // print zero, but doesn't adjust list
72  list[8] = 1;
73  \endcode
74 
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
77  inheriting classes.
78 
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:
82  \verbatim
83  { (index1 value1) (index2 value2) (index3 value3) }
84  \endverbatim
85  The bool specialization just uses the indices corresponding to
86  non-zero entries instead of a index/value pair:
87  \verbatim
88  { index1 index2 index3 }
89  \endverbatim
90  In both cases, the supplied indices can be randomly ordered.
91 
92 See also
93  Foam::DynamicList
94 
95 SourceFiles
96  PackedListI.H
97  PackedList.C
98 
99 \*---------------------------------------------------------------------------*/
100 
101 #ifndef PackedList_H
102 #define PackedList_H
103 
104 #include "labelList.H"
105 #include "UIndirectList.H"
106 #include <type_traits>
107 
108 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
109 
110 namespace Foam
111 {
112 
113 // Forward declaration of classes
114 class Istream;
115 class Ostream;
116 
117 // Forward declaration of friend functions and operators
118 template<unsigned nBits> class PackedList;
119 
120 template<unsigned nBits>
122 template<unsigned nBits>
123 Ostream& operator<<(Ostream&, const PackedList<nBits>&);
124 
125 
126 /*---------------------------------------------------------------------------*\
127  Class PackedListCore Declaration
128 \*---------------------------------------------------------------------------*/
129 
130 //- Template-invariant bits for PackedList
131 struct PackedListCore
132 {
133  //- Construct null
135  {}
136 
137  //- Define template name and debug
138  ClassName("PackedList");
139 };
140 
141 
142 /*---------------------------------------------------------------------------*\
143  Class PackedList Declaration
144 \*---------------------------------------------------------------------------*/
145 
146 template<unsigned nBits=1>
147 class PackedList
148 :
149  public PackedListCore,
150  private List<unsigned int>
151 {
152 protected:
154  typedef unsigned int StorageType;
155  typedef List<StorageType> StorageList;
156 
157  // Protected Member Functions
158 
159  //- Calculate the list length when packed
160  inline static label packedLength(const label);
161 
162  //- Read a list entry (allows for specialization)
163  inline static unsigned int readValue(Istream&);
164 
165  //- Read an index/value pair and set accordingly.
166  // For bool specialization, read a single index value
167  inline void setPair(Istream&);
168 
169 
170 private:
171 
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  static_assert
178  (
179  nBits && nBits <= (sizeof(StorageType) << 2),
180  "nBits must be positive (non-zero) and fit within the storage"
181  );
182 
183  // Private data
184 
185  //- Number of nBits entries
186  label size_;
187 
188 
189 public:
190 
191  // Public data
192 
193  //- The max. number of bits that can be templated.
194  // Might someday be useful for a template assert.
195  inline static unsigned int max_bits();
196 
197  //- The max. value for an entry, which simultaneously the bit-mask
198  // eg, ((1 << 2) - 1) yields 0b0011
199  inline static unsigned int max_value();
200 
201  //- The number of entries per packed storage element
202  inline static unsigned int packing();
203 
204  //- Masking for all bits below the offset
205  inline static unsigned int maskLower(unsigned offset);
206 
207 
208  // Forward declaration of iterators
209 
210  class iteratorBase;
211  class iterator;
212  class const_iterator;
213 
214 
215  // Constructors
216 
217  //- Null constructor
218  inline PackedList();
219 
220  //- Construct with given size, initializes list to 0
221  explicit inline PackedList(const label size);
222 
223  //- Construct with given size and value for all elements
224  inline PackedList(const label size, const unsigned val);
225 
226  //- Construct from Istream
227  inline PackedList(Istream&);
228 
229  //- Copy constructor
230  inline PackedList(const PackedList<nBits>&);
231 
232  //- Construct by transferring the parameter contents
233  inline PackedList(const Xfer<PackedList<nBits>>&);
234 
235  //- Construct from a list of labels
236  explicit inline PackedList(const labelUList&);
237 
238  //- Construct from an indirect list of labels
239  explicit inline PackedList(const UIndirectList<label>&);
240 
241  //- Clone
242  inline autoPtr<PackedList<nBits>> clone() const;
243 
244 
245  // Member Functions
246 
247  // Access
248 
249  //- The number of elements that can be stored before reallocating
250  inline label capacity() const;
251 
252  //- Number of entries.
253  inline label size() const;
254 
255  //- Return true if the list is empty (ie, size() is zero).
256  inline bool empty() const;
257 
258  //- Get value at index I.
259  // Never auto-vivify entries.
260  inline unsigned int get(const label) const;
261 
262  //- Set value at index I. Return true if value changed.
263  // Does auto-vivify for non-existent entries.
264  // Default value set is the max_value.
265  inline bool set(const label, const unsigned int val = ~0u);
266 
267  //- Unset the entry at index I. Return true if value changed.
268  // Never auto-vivify entries.
269  inline bool unset(const label);
270 
271  //- Return the underlying packed storage
272  // Manipulate with utmost caution
273  inline List<unsigned int>& storage();
274 
275  //- Return the underlying packed storage
276  inline const List<unsigned int>& storage() const;
277 
278  //- The list length when packed
279  inline label packedLength() const;
280 
281  //- Return the binary size in number of characters
282  // used in the underlying storage
283  inline std::streamsize byteSize() const;
284 
285  //- Count number of bits set, O(log(n))
286  // Uses the Hamming weight (population count) method
287  // http://en.wikipedia.org/wiki/Hamming_weight
288  unsigned int count() const;
289 
290  //- Return the values as a list of labels
291  Xfer<labelList> values() const;
292 
293  //- Print bit patterns, optionally output unused elements
294  //
295  // addressable bits:
296  // on: '1', off: '-'
297  //
298  // non-addressable bits:
299  // on: '!', off: '.'
300  //
301  Ostream& printBits(Ostream&, const bool fullOutput=false) const;
302 
303  //- Print information and bit patterns (with printBits)
304  Ostream& printInfo(Ostream&, const bool fullOutput=false) const;
305 
306 
307  // Edit
308 
309  //- Trim any trailing zero elements
310  bool trim();
311 
312  //- Invert the bits in the addressable region
313  void flip();
314 
315  //- Clear all bits
316  inline void reset();
317 
318  //- Alter the size of the underlying storage.
319  // The addressed size will be truncated if needed to fit, but will
320  // remain otherwise untouched.
321  inline void setCapacity(const label);
322 
323  //- Reset addressable list size, does not shrink the allocated size.
324  // Optionally specify a value for new elements.
325  inline void resize(const label, const unsigned int& val = 0u);
326 
327  //- Alias for resize()
328  inline void setSize(const label, const unsigned int& val = 0u);
329 
330  //- Reserve allocation space for at least this size.
331  // Never shrinks the allocated size.
332  // The list size is adjusted as per DynamicList with
333  // SizeInc=0, SizeMult=2, SizeDiv=1
334  inline void reserve(const label);
335 
336  //- Clear the list, i.e. set addressable size to zero.
337  // Does not adjust the underlying storage
338  inline void clear();
339 
340  //- Clear the list and delete storage.
341  inline void clearStorage();
342 
343  //- Shrink the allocated space to what is actually used.
344  inline void shrink();
345 
346  //- Transfer the contents of the argument list into this list
347  // and annul the argument list.
348  inline void transfer(PackedList<nBits>&);
349 
350  //- Transfer contents to the Xfer container
351  inline Xfer<PackedList<nBits>> xfer();
352 
353 
354  // IO
355 
356  //- Clear list and read from stream
357  Istream& read(Istream&);
358 
359  //- Write, optionally with indexedOutput
360  //
361  // The indexed output may be convenient in some situations.
362  // The general format is a group of index/value pairs:
363  // \verbatim
364  // { (index1 value1) (index2 value2) (index3 value3) }
365  // \endverbatim
366  // The bool specialization just uses the indices corresponding to
367  // non-zero entries instead of a index/value pair:
368  // \verbatim
369  // { index1 index2 index3 }
370  // \endverbatim
371  //
372  // Note the indexed output is only supported for ASCII streams.
373  Ostream& write
374  (
375  Ostream&,
376  const bool indexedOutput=false
377  ) const;
378 
379 
380  //- Write as a dictionary entry
381  void writeEntry(Ostream&) const;
382 
383  //- Write as a dictionary entry with keyword
384  void writeEntry(const word& keyword, Ostream&) const;
385 
386 
387  // Member operators
388 
389  //- Append a value at the end of the list
390  inline PackedList<nBits>& append(const unsigned int val);
391 
392  //- Remove and return the last element
393  inline unsigned int remove();
394 
395  //- Get value at index I
396  // Never auto-vivify entries.
397  inline unsigned int operator[](const label) const;
398 
399  //- Set value at index I.
400  // Returns iterator to perform the actual operation.
401  // Does not auto-vivify entries, but will when assigned to.
402  inline iteratorBase operator[](const label);
403 
404  //- Assignment of all entries to the given value. Takes linear time.
405  inline void operator=(const unsigned int val);
406 
407  //- Assignment operator.
408  void operator=(const PackedList<nBits>&);
409 
410  //- Assignment operator.
411  void operator=(const labelUList&);
412 
413  //- Assignment operator.
414  void operator=(const UIndirectList<label>&);
415 
416 
417  // Iterators and helpers
418 
419  //- The iterator base for PackedList
420  // Note: data and functions are protected, to allow reuse by iterator
421  // and prevent most external usage.
422  class iteratorBase
423  {
424  friend class PackedList;
425 
426  protected:
427 
428  // Protected Data
429 
430  //- Pointer to original list
431  // This also lets us use the default bitwise copy/assignment
432  PackedList* list_;
433 
434  //- Element index
435  label index_;
436 
437 
438  // Protected Member Functions
439 
440  //- Get value as unsigned, no range-checking
441  inline unsigned int get() const;
442 
443  //- Set value, returning true if changed, no range-checking
444  inline bool set(unsigned int);
445 
446 
447  // Constructors
448 
449  //- Construct null
450  inline iteratorBase();
451 
452  //- Construct from base list and position index
453  inline iteratorBase(const PackedList*, const label);
454 
455 
456  public:
457 
458  // Member Functions
459 
460  //- Return the element index corresponding to the iterator
461  inline label key() const;
462 
463  //- Write index/value for a non-zero entry
464  // The bool specialization writes the index only
465  inline bool writeIfSet(Ostream&) const;
466 
467  // Member Operators
468 
469  //- Compare values (not positions)
470  inline bool operator==(const iteratorBase&) const;
471  inline bool operator!=(const iteratorBase&) const;
472 
473  //- Assign value, not position.
474  // This allows packed[0] = packed[3] for assigning values
475  inline void operator=(const iteratorBase&);
476 
477  //- Assign value.
478  // A non-existent entry will be auto-vivified.
479  inline void operator=(const unsigned int val);
480 
481  //- Conversion operator
482  // Never auto-vivify entries.
483  inline operator unsigned int () const;
484 
485  //- Print information and values
486  Ostream& printInfo(Ostream&) const;
487  };
488 
489 
490  //- The iterator class used for PackedList
491  class iterator
492  :
493  public iteratorBase
494  {
495 
496  //- Disallow copy constructor from const_iterator
497  // This would violate const-ness!
498  iterator(const const_iterator&);
499 
500  //- Disallow assignment from const_iterator
501  // This would violate const-ness!
502  void operator=(const const_iterator&);
503 
504 
505  public:
506 
507  // Constructors
508 
509  //- Construct null
510  inline iterator();
511 
512  //- Construct from iterator base, eg iter(packedlist[i])
513  // but also "iterator iter = packedlist[i];"
514  // An out-of-range iterator is assigned end()
515  inline iterator(const iteratorBase&);
516 
517  //- Construct from base list and position index
518  inline iterator(const PackedList*, const label);
519 
520 
521  // Member Operators
522 
523  //- Compare positions (not values)
524  inline bool operator==(const iteratorBase&) const;
525  inline bool operator!=(const iteratorBase&) const;
526 
527  //- Assign from iteratorBase, eg iter = packedlist[i]
528  // An out-of-range iterator is assigned end()
529  inline void operator=(const iteratorBase&);
530 
531  //- Return value
532  inline unsigned int operator*() const;
533 
534  //- Return value
535  inline unsigned int operator()() const;
536 
537  //- Return iteratorBase for assigning values
538  inline iteratorBase& operator*();
539 
540  //- Return iteratorBase for assigning values
541  inline iteratorBase& operator()();
542 
543  inline iterator& operator++();
544  inline iterator operator++(int);
545 
546  inline iterator& operator--();
547  inline iterator operator--(int);
548 
549  };
550 
551  //- Iterator set to the beginning of the PackedList
552  inline iterator begin();
553 
554  //- Iterator set to beyond the end of the PackedList
555  inline iterator end();
556 
557 
558  //- The const_iterator for PackedList
559  class const_iterator
560  :
561  public iteratorBase
562  {
563  public:
564 
565  // Constructors
566 
567  //- Construct null
568  inline const_iterator();
569 
570  //- Construct from iterator base, eg iter(packedlist[i])
571  // but also "const_iterator iter = packedlist[i];"
572  // An out-of-range iterator is assigned cend()
573  inline const_iterator(const iteratorBase&);
574 
575  //- Construct from base list and position index
576  inline const_iterator(const PackedList*, const label);
577 
578  //- Construct from iterator
579  inline const_iterator(const iterator&);
580 
581 
582  // Member operators
583 
584  //- Compare positions (not values)
585  inline bool operator==(const iteratorBase&) const;
586  inline bool operator!=(const iteratorBase&) const;
587 
588  //- Assign from iteratorBase or derived
589  // eg, iter = packedlist[i] or even iter = list.begin()
590  inline void operator=(const iteratorBase&);
591 
592  //- Return referenced value directly
593  inline unsigned int operator*() const;
594 
595  //- Return referenced value directly
596  inline unsigned int operator()() const;
597 
598  inline const_iterator& operator++();
599  inline const_iterator operator++(int);
600 
601  inline const_iterator& operator--();
602  inline const_iterator operator--(int);
603  };
604 
605 
606  //- const_iterator set to the beginning of the PackedList
607  inline const_iterator cbegin() const;
608 
609  //- const_iterator set to beyond the end of the PackedList
610  inline const_iterator cend() const;
611 
612  //- const_iterator set to the beginning of the PackedList
613  inline const_iterator begin() const;
614 
615  //- const_iterator set to beyond the end of the PackedList
616  inline const_iterator end() const;
617 
618 
619  // IOstream Operators
620 
621  friend Istream& operator>> <nBits>
622  (
623  Istream&,
625  );
626 
627  friend Ostream& operator<< <nBits>
628  (
629  Ostream&,
630  const PackedList<nBits>&
631  );
632 };
633 
634 
635 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
636 
637 } // End namespace Foam
638 
639 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
640 
641 #include "PackedListI.H"
642 
643 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
644 
645 #ifdef NoRepository
646  #include "PackedList.C"
647 #endif
648 
649 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
650 
651 #endif
652 
653 // ************************************************************************* //
A simple container for copying or transferring objects of type <T>.
Definition: Xfer.H:85
The iterator class used for PackedList.
Definition: PackedList.H:490
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
tUEqn clear()
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:60
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
T * iterator
Random access iterator for traversing UList.
Definition: UList.H:272
ClassName("PackedList")
Define template name and debug.
string trim(const string &)
Return string trimmed of leading and trailing whitespace.
Definition: stringOps.C:923
points setSize(newPointi)
void write(Ostream &, const label, const dictionary &)
Write with dictionary lookup.
bool read(const char *, int32_t &)
Definition: int32IO.C:85
tmp< fvMatrix< Type > > operator*(const volScalarField::Internal &, const fvMatrix< Type > &)
A dynamically allocatable list of packed unsigned integers.
Definition: PackedList.H:117
tmp< fvMatrix< Type > > operator==(const fvMatrix< Type > &, const fvMatrix< Type > &)
A class for handling words, derived from string.
Definition: word.H:59
Istream & operator>>(Istream &, directionInfo &)
triSurfaceToAgglom resize(surfacesMesh.size())
PackedListCore()
Construct null.
Definition: PackedList.H:133
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:61
Template-invariant bits for PackedList.
Definition: PackedList.H:130
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
The const_iterator for PackedList.
Definition: PackedList.H:558
The iterator base for PackedList.
Definition: PackedList.H:421
const T * const_iterator
Random access iterator for traversing UList.
Definition: UList.H:284
A List with indirect addressing.
Definition: fvMatrix.H:106
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:52
bool operator!=(const particle &, const particle &)
Definition: particle.C:1106
Namespace for OpenFOAM.