00001 /*---------------------------------------------------------------------------*\ 00002 ========= | 00003 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox 00004 \\ / O peration | 00005 \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd. 00006 \\/ M anipulation | 00007 ------------------------------------------------------------------------------- 00008 License 00009 This file is part of OpenFOAM. 00010 00011 OpenFOAM is free software: you can redistribute it and/or modify it 00012 under the terms of the GNU General Public License as published by 00013 the Free Software Foundation, either version 3 of the License, or 00014 (at your option) any later version. 00015 00016 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT 00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00018 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 00019 for more details. 00020 00021 You should have received a copy of the GNU General Public License 00022 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. 00023 00024 Class 00025 Foam::PackedList 00026 00027 Description 00028 A dynamically allocatable list of packed unsigned integers. 00029 00030 The list resizing is similar to DynamicList, thus the methods clear() 00031 and setSize() behave like their DynamicList counterparts and the methods 00032 reserve() and setCapacity() can be used to influence the allocation. 00033 00034 The number of bits per item is specified by the template parameter nBits. 00035 00036 Note 00037 In a const context, the '[]' operator simply returns the stored value, 00038 with out-of-range elements returned as zero. 00039 In a non-const context, the '[]' operator returns an iteratorBase, which 00040 might not have a valid reference for out-of-range elements. 00041 The iteratorBase class handles the assignment of new values. 00042 00043 Using the iteratorBase as a proxy allows assignment of values 00044 between list elements. Thus the following bit of code works as expected: 00045 @code 00046 list[1] = list[5]; // value assignment, not iterator position 00047 list[2] = list[5] = 4; // propagates value 00048 list[1] = list[5] = list[6]; // propagates value 00049 @endcode 00050 00051 Using get() or the '[]' operator are similarly fast. Looping and reading 00052 via an iterator is approx. 15% slower, but can be more flexible. 00053 00054 Using the set() operator (and the '[]' operator) are marginally slower 00055 (approx. 5%) than using an iterator, but the set() method has the 00056 advantage of also returning a bool if the value changed. This can be 00057 useful for branching on changed values. 00058 00059 @code 00060 list[5] = 4; 00061 changed = list.set(5, 8); 00062 if (changed) ... 00063 @endcode 00064 00065 The lazy evaluation used means that reading an out-of-range element 00066 returns zero, but does not affect the list size. Even in a non-const 00067 context, only the assigment itself causes the element to be created. 00068 For example, 00069 @code 00070 list.resize(4); 00071 Info<< list[10] << "\n"; // print zero, but doesn't adjust list 00072 list[8] = 1; 00073 @endcode 00074 00075 SeeAlso 00076 Foam::DynamicList 00077 00078 SourceFiles 00079 PackedListI.H 00080 PackedList.C 00081 00082 \*---------------------------------------------------------------------------*/ 00083 00084 #ifndef PackedList_H 00085 #define PackedList_H 00086 00087 #include <OpenFOAM/labelList.H> 00088 #include <OpenFOAM/StaticAssert.H> 00089 00090 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 00091 00092 namespace Foam 00093 { 00094 00095 // Forward declaration of friend functions and operators 00096 template<unsigned nBits> class PackedList; 00097 00098 // template<unsigned nBits> 00099 // Ostream& operator<<(Ostream&, const PackedList<nBits>&); 00100 00101 00102 /*---------------------------------------------------------------------------*\ 00103 Class PackedListName Declaration 00104 \*---------------------------------------------------------------------------*/ 00105 00106 TemplateName(PackedList); 00107 00108 /*---------------------------------------------------------------------------*\ 00109 Class PackedList Declaration 00110 \*---------------------------------------------------------------------------*/ 00111 00112 template<unsigned nBits=1> 00113 class PackedList 00114 : 00115 private List<unsigned int> 00116 { 00117 typedef unsigned int StorageType; 00118 typedef List<StorageType> StorageList; 00119 00120 //- nBits must be positive (non-zero) and fit within the storage 00121 // For simplicity, assume 8-bit bytes 00122 StaticAssert(nBits && nBits < (sizeof(StorageType) << 3)); 00123 00124 // Private data 00125 00126 //- Number of nBits entries 00127 label size_; 00128 00129 // Private Member Functions 00130 00131 //- Calculate the list length when packed 00132 inline static label packedLength(const label); 00133 00134 public: 00135 00136 // Public data 00137 00138 //- The max. number of bits that can be templated. 00139 // Might someday be useful for a template assert. 00140 inline static unsigned int max_bits(); 00141 00142 //- The max. value for an entry, which simultaneously the bit-mask 00143 // eg, ((1 << 2) - 1) yields 0b0011 00144 inline static unsigned int max_value(); 00145 00146 //- The number of entries per packed storage element 00147 inline static unsigned int packing(); 00148 00149 //- Masking for all bits below the offset 00150 inline static unsigned int maskLower(unsigned offset); 00151 00152 // Forward declaration of iterators 00153 00154 class iteratorBase; 00155 class iterator; 00156 class const_iterator; 00157 00158 // Constructors 00159 00160 //- Null constructor 00161 inline PackedList(); 00162 00163 //- Construct with given size, initializes list to 0. 00164 explicit inline PackedList(const label size); 00165 00166 //- Construct with given size and value for all elements. 00167 PackedList(const label size, const unsigned val); 00168 00169 //- Copy constructor. 00170 inline PackedList(const PackedList<nBits>&); 00171 00172 //- Construct by transferring the parameter contents 00173 inline PackedList(const Xfer< PackedList<nBits> >&); 00174 00175 //- Construct from a list of labels 00176 explicit PackedList(const UList<label>&); 00177 00178 //- Clone 00179 inline autoPtr< PackedList<nBits> > clone() const; 00180 00181 // Member Functions 00182 00183 // Access 00184 00185 //- The number of elements that can be stored before reallocating 00186 inline label capacity() const; 00187 00188 //- Number of entries. 00189 inline label size() const; 00190 00191 //- Return true if the list is empty (ie, size() is zero). 00192 inline bool empty() const; 00193 00194 //- Get value at index I. 00195 // Never auto-vivify entries. 00196 inline unsigned int get(const label) const; 00197 00198 //- Set value at index I. Return true if value changed. 00199 // Does auto-vivify for non-existent entries. 00200 // Default value set is the max_value. 00201 inline bool set(const label, const unsigned int val = ~0u); 00202 00203 //- Unset the entry at index I. Return true if value changed. 00204 // Never auto-vivify entries. 00205 inline bool unset(const label); 00206 00207 //- Return the underlying packed storage 00208 inline List<unsigned int>& storage(); 00209 00210 //- Return the underlying packed storage 00211 inline const List<unsigned int>& storage() const; 00212 00213 //- Count number of bits set, O(log(n)) 00214 // Uses the Hamming weight (population count) method 00215 // http://en.wikipedia.org/wiki/Hamming_weight 00216 unsigned int count() const; 00217 00218 //- Return the values as a labelList 00219 labelList values() const; 00220 00221 //- Print values and information 00222 Ostream& print(Ostream&) const; 00223 00224 // Edit 00225 00226 //- Trim any trailing zero elements 00227 bool trim(); 00228 00229 //- Invert the bits in the addressable region. 00230 void flip(); 00231 00232 //- Alter the size of the underlying storage. 00233 // The addressed size will be truncated if needed to fit, but will 00234 // remain otherwise untouched. 00235 inline void setCapacity(const label); 00236 00237 //- Reset addressable list size, does not shrink the allocated size. 00238 // Optionally specify a value for new elements. 00239 inline void resize(const label, const unsigned int& val = 0); 00240 00241 //- Alias for resize() 00242 inline void setSize(const label, const unsigned int& val = 0); 00243 00244 //- Reserve allocation space for at least this size. 00245 // Never shrinks the allocated size. 00246 // The list size is adjusted as per DynamicList with 00247 // SizeInc=0, SizeMult=2, SizeDiv=1 00248 inline void reserve(const label); 00249 00250 //- Clear the list, i.e. set addressable size to zero. 00251 // Does not adjust the underlying storage 00252 inline void clear(); 00253 00254 //- Clear the list and delete storage. 00255 inline void clearStorage(); 00256 00257 //- Shrink the allocated space to what is actually used. 00258 inline void shrink(); 00259 00260 //- Transfer the contents of the argument list into this list 00261 // and annul the argument list. 00262 inline void transfer(PackedList<nBits>&); 00263 00264 //- Transfer contents to the Xfer container 00265 inline Xfer< PackedList<nBits> > xfer(); 00266 00267 00268 // Member operators 00269 00270 //- Append a value at the end of the list 00271 inline void append(const unsigned int val); 00272 00273 //- Remove and return the last element 00274 inline unsigned int remove(); 00275 00276 //- Get value at index I 00277 // Never auto-vivify entries. 00278 inline unsigned int operator[](const label) const; 00279 00280 //- Set value at index I. 00281 // Returns iterator to perform the actual operation. 00282 // Does not auto-vivify entries, but will when assigned to. 00283 inline iteratorBase operator[](const label); 00284 00285 //- Assignment of all entries to the given value. Takes linear time. 00286 inline void operator=(const unsigned int val); 00287 00288 //- Assignment operator. Takes linear time. 00289 void operator=(const PackedList<nBits>&); 00290 00291 //- Assignment operator. Takes linear time. 00292 void operator=(const UList<label>&); 00293 00294 // Ostream operator 00295 00296 // // Write PackedList to Ostream. 00297 // friend Ostream& operator<< <nBits> (Ostream&, const PackedList<nBits>&); 00298 00299 // Iterators and helpers 00300 00301 //- The iterator base for PackedList 00302 // Note: data and functions are protected, to allow reuse by iterator 00303 // and prevent most external usage. 00304 class iteratorBase 00305 { 00306 friend class PackedList; 00307 00308 protected: 00309 00310 // Protected Data 00311 00312 //- Pointer to original list 00313 // This also lets us use the default bitwise copy/assignment 00314 PackedList* list_; 00315 00316 //- Element index 00317 label index_; 00318 00319 // Protected Member Functions 00320 00321 //- Get value as unsigned, no range-checking 00322 inline unsigned int get() const; 00323 00324 //- Set value, returning true if changed, no range-checking 00325 inline bool set(unsigned int); 00326 00327 // Constructors 00328 00329 //- Construct null 00330 inline iteratorBase(); 00331 00332 //- Construct from base list and position index 00333 inline iteratorBase(const PackedList*, const label); 00334 00335 public: 00336 00337 // Member Operators 00338 00339 //- Compare values (not positions) 00340 inline bool operator==(const iteratorBase&) const; 00341 inline bool operator!=(const iteratorBase&) const; 00342 00343 //- Assign value, not position. 00344 // This allows packed[0] = packed[3] for assigning values 00345 inline unsigned int operator=(const iteratorBase&); 00346 00347 //- Assign value. 00348 // A non-existent entry will be auto-vivified. 00349 inline unsigned int operator=(const unsigned int val); 00350 00351 //- Conversion operator 00352 // Never auto-vivify entries. 00353 inline operator unsigned int () const; 00354 00355 //- Print value and information 00356 Ostream& print(Ostream&) const; 00357 }; 00358 00359 00360 //- The iterator class used for PackedList 00361 class iterator 00362 : 00363 public iteratorBase 00364 { 00365 00366 //- Disallow copy constructor from const_iterator - violates const-ness! 00367 iterator(const const_iterator&); 00368 00369 //- Disallow assignment from const_iterator - violates const-ness! 00370 void operator=(const const_iterator&); 00371 00372 public: 00373 00374 // Constructors 00375 00376 //- Construct null 00377 inline iterator(); 00378 00379 //- Construct from iterator base, eg iter(packedlist[i]) 00380 // but also "iterator iter = packedlist[i];" 00381 // An out-of-range iterator is assigned end() 00382 inline iterator(const iteratorBase&); 00383 00384 //- Construct from base list and position index 00385 inline iterator(const PackedList*, const label); 00386 00387 // Member Operators 00388 00389 //- Compare positions (not values) 00390 inline bool operator==(const iteratorBase&) const; 00391 inline bool operator!=(const iteratorBase&) const; 00392 00393 //- Assign from iteratorBase, eg iter = packedlist[i] 00394 // An out-of-range iterator is assigned end() 00395 inline iterator& operator=(const iteratorBase&); 00396 00397 //- Return value 00398 inline unsigned int operator*() const; 00399 00400 //- Return value 00401 inline unsigned int operator()() const; 00402 00403 //- Return iteratorBase for assigning values 00404 inline iteratorBase& operator*(); 00405 00406 //- Return iteratorBase for assigning values 00407 inline iteratorBase& operator()(); 00408 00409 inline iterator& operator++(); 00410 inline iterator operator++(int); 00411 00412 inline iterator& operator--(); 00413 inline iterator operator--(int); 00414 00415 }; 00416 00417 //- iterator set to the beginning of the PackedList 00418 inline iterator begin(); 00419 00420 //- iterator set to beyond the end of the PackedList 00421 inline iterator end(); 00422 00423 00424 //- The const_iterator for PackedList 00425 class const_iterator 00426 : 00427 public iteratorBase 00428 { 00429 public: 00430 00431 // Constructors 00432 00433 //- Construct null 00434 inline const_iterator(); 00435 00436 //- Construct from iterator base, eg iter(packedlist[i]) 00437 // but also "const_iterator iter = packedlist[i];" 00438 // An out-of-range iterator is assigned cend() 00439 inline const_iterator(const iteratorBase&); 00440 00441 //- Construct from base list and position index 00442 inline const_iterator(const PackedList*, const label); 00443 00444 //- Construct from iterator 00445 inline const_iterator(const iterator&); 00446 00447 // Member operators 00448 00449 //- Compare positions (not values) 00450 inline bool operator==(const iteratorBase&) const; 00451 inline bool operator!=(const iteratorBase&) const; 00452 00453 //- Assign from iteratorBase or derived 00454 // eg, iter = packedlist[i] or even iter = list.begin() 00455 inline const_iterator& operator=(const iteratorBase&); 00456 00457 //- Return referenced value directly 00458 inline unsigned int operator*() const; 00459 00460 //- Return referenced value directly 00461 inline unsigned int operator()() const; 00462 00463 inline const_iterator& operator++(); 00464 inline const_iterator operator++(int); 00465 00466 inline const_iterator& operator--(); 00467 inline const_iterator operator--(int); 00468 00469 }; 00470 00471 00472 //- const_iterator set to the beginning of the PackedList 00473 inline const_iterator cbegin() const; 00474 00475 //- const_iterator set to beyond the end of the PackedList 00476 inline const_iterator cend() const; 00477 00478 //- const_iterator set to the beginning of the PackedList 00479 inline const_iterator begin() const; 00480 00481 //- const_iterator set to beyond the end of the PackedList 00482 inline const_iterator end() const; 00483 00484 }; 00485 00486 00487 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 00488 00489 } // End namespace Foam 00490 00491 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 00492 00493 #include "PackedListI.H" 00494 00495 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 00496 00497 #ifdef NoRepository 00498 # include "PackedList.C" 00499 #endif 00500 00501 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 00502 00503 #endif 00504 00505 // ************************ vim: set sw=4 sts=4 et: ************************ //