diff --git a/applications/test/PackedList/PackedListTest.C b/applications/test/PackedList/PackedListTest.C index a3767e86803ce5964c88424041ca4ee9bcd53889..6bc951cfa748fc4bc1dbd8a0aca4c32852183d2f 100644 --- a/applications/test/PackedList/PackedListTest.C +++ b/applications/test/PackedList/PackedListTest.C @@ -56,8 +56,9 @@ void printPackedList(const PackedList<nBits>& L) { cout<< L[i] << ' '; } - cout<< ")\n\n"; + cout<< ")\n"; + // using std:bitset for output works, but annoys valgrind cout<< "storage: " << stor.size() << "( "; forAll(stor, i) { @@ -99,6 +100,41 @@ int main(int argc, char *argv[]) list1.resize(8); printPackedList(list1); + list1.append(2); + list1.append(3); + list1.append(4); + printPackedList(list1); + + list1.reserve(32); + printPackedList(list1); + + list1.shrink(); + printPackedList(list1); + + list1.setSize(15); + printPackedList(list1); + + list1.setSize(32); + printPackedList(list1); + + // test assignment + list1[16] = 5; + printPackedList(list1); + + // auto-vivify + list1[36] = list1.max_value(); + printPackedList(list1); + + list1.setSize(4); + printPackedList(list1); + + PackedList<3> list2(list1); + list2.append(4); + + cout << "after copy + append\n"; + printPackedList(list1); + printPackedList(list2); + return 0; } diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedList.C b/src/OpenFOAM/containers/Lists/PackedList/PackedList.C index ff006523fce6098fabacd9d9d77db0f8223ad145..3af810cefa4daa15b143bf2c6ece723d1616fff8 100644 --- a/src/OpenFOAM/containers/Lists/PackedList/PackedList.C +++ b/src/OpenFOAM/containers/Lists/PackedList/PackedList.C @@ -38,21 +38,6 @@ Foam::PackedList<nBits>::PackedList(const label size, const unsigned int val) } -template<int nBits> -Foam::PackedList<nBits>::PackedList(const PackedList<nBits>& lst) -: - List<unsigned int>(lst), - size_(lst.size()) -{} - - -template<int nBits> -Foam::PackedList<nBits>::PackedList(const Xfer<PackedList<nBits> >& lst) -{ - transfer(lst()); -} - - template<int nBits> Foam::PackedList<nBits>::PackedList(const UList<label>& lst) : @@ -66,62 +51,19 @@ Foam::PackedList<nBits>::PackedList(const UList<label>& lst) } -template<int nBits> -Foam::autoPtr<Foam::PackedList<nBits> > Foam::PackedList<nBits>::clone() const -{ - return autoPtr<PackedList<nBits> >(new PackedList<nBits>(*this)); -} - // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template<int nBits> -void Foam::PackedList<nBits>::setSize(const label newSize) -{ - List<unsigned int>::setSize(storageSize(newSize), 0); - size_ = newSize; -} - - -template<int nBits> -void Foam::PackedList<nBits>::setSize -( - const label newSize, - const unsigned int& val -) +Foam::labelList Foam::PackedList<nBits>::values() const { -# ifdef DEBUGList - checkValue(val); -# endif - - List<unsigned int>::setSize(storageSize(newSize), 0); + labelList elems(size()); - if (val && newSize > size_) + forAll(*this, i) { - // fill new elements - for (label i = size_; i < newSize; i++) - { - set(i, val); - } + elems[i] = get(i); } - - size_ = newSize; -} - - -template<int nBits> -void Foam::PackedList<nBits>::clear() -{ - List<unsigned int>::clear(); - size_ = 0; -} - - -template<int nBits> -void Foam::PackedList<nBits>::transfer(PackedList<nBits>& lst) -{ - size_ = lst.size(); - List<unsigned int>::transfer(lst); + return elems; } @@ -130,24 +72,24 @@ void Foam::PackedList<nBits>::transfer(PackedList<nBits>& lst) template<int nBits> void Foam::PackedList<nBits>::operator=(const PackedList<nBits>& lst) { - setSize(lst.size()); + setCapacity(lst.size()); List<unsigned int>::operator=(lst); } template<int nBits> -Foam::labelList Foam::PackedList<nBits>::operator()() const +void Foam::PackedList<nBits>::operator=(const UList<label>& lst) { - labelList elems(size()); + setCapacity(lst.size()); - forAll(*this, i) + forAll(lst, i) { - elems[i] = get(i); + set(i, lst[i]); } - return elems; } + // * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * // //template<int nBits> diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedList.H b/src/OpenFOAM/containers/Lists/PackedList/PackedList.H index a6544b59a49fee82b3742fc588efc56c2124d3a4..214c5e6f6ca3c416fb4675c57ed1493f50eb75c5 100644 --- a/src/OpenFOAM/containers/Lists/PackedList/PackedList.H +++ b/src/OpenFOAM/containers/Lists/PackedList/PackedList.H @@ -26,14 +26,21 @@ Class Foam::PackedList Description - List of packed unsigned ints. + A Dynamically allocatable list of packed unsigned ints. Gets given the number of bits per item. +Note + The list resizing is similar to DynamicList, thus the methods clear() + and setSize() behave like their DynamicList counterparts and the methods + reserve() and setCapacity() can be used to influence the allocation. + +SeeAlso + Foam::DynamicList + ToDo Add checks for bad template parameters (ie, nBits=0, nBits too large). Could make PackedBitRef an iterator and use for traversing as well. - It could be useful to make PackedList behave a bit like DynamicList. SourceFiles PackedListI.H @@ -52,6 +59,13 @@ SourceFiles namespace Foam { +// Forward declaration of friend functions and operators +template<int nBits> class PackedList; + +// template<int nBits> +// Ostream& operator<<(Ostream&, const PackedList<nBits>&); + + /*---------------------------------------------------------------------------*\ Class PackedListName Declaration \*---------------------------------------------------------------------------*/ @@ -64,42 +78,73 @@ TemplateName(PackedList); \*---------------------------------------------------------------------------*/ //- The PackedBitRef is used for PackedList +template <int nBits> class PackedBitRef { private: // private data + // const mutable List<unsigned int>& list_; + unsigned int& elem_; const label startBit_; - const unsigned int mask_; - public: - inline PackedBitRef(unsigned int& elem, label startBit, unsigned int mask) + // Static Public Members + + //- The max. number of bits that can be templated. + // Might someday be useful for a template assert. + inline static unsigned int max_bits(); + + //- The max. value for an entry, can also be used as the mask + // eg, ((1 << 2) - 1) yields 0b0011 + inline static unsigned int max_value(); + + //- The number of entries per storage entry + inline static unsigned int packing(); + + + // Constructors + inline PackedBitRef + ( + // const List<unsigned int>& lst + const unsigned int& elem, label startBit) : - elem_(elem), - startBit_(startBit), - mask_(mask) + // list_(lst), + elem_(const_cast<unsigned int&>(elem)), + startBit_(startBit) {} + + // Members + + // Assign value inline void operator=(const unsigned int val) { - unsigned int shiftedMask = mask_ << startBit_; - unsigned int shiftedVal = (val & mask_) << startBit_; + unsigned int shiftedMask = max_value() << startBit_; + unsigned int shiftedVal = (val & max_value()) << startBit_; elem_ = (elem_ & ~shiftedMask) | shiftedVal; } + // return value + inline unsigned int operator()() const + { + return ((elem_ >> startBit_) & max_value()); + } + + //- Conversion operator inline operator unsigned int () const { - return ((elem_ >> startBit_) & mask_); + return ((elem_ >> startBit_) & max_value()); } + //- Conversion operator inline operator bool() const { - return !!((elem_ >> startBit_) & mask_); + return !!((elem_ >> startBit_) & max_value()); } }; @@ -139,14 +184,23 @@ public: //- The max. number of bits that can be templated. // Might someday be useful for a template assert. - inline static unsigned int max_bits(); + inline static unsigned int max_bits() + { + return PackedBitRef<nBits>::max_bits(); + } //- The max. value for an entry, can also be used as the mask // eg, ((1 << 2) - 1) yields 0b0011 - inline static unsigned int max_value(); + inline static unsigned int max_value() + { + return PackedBitRef<nBits>::max_value(); + } //- The number of entries per storage entry - inline static unsigned int packing(); + inline static unsigned int packing() + { + return PackedBitRef<nBits>::packing(); + } // Constructors @@ -154,101 +208,116 @@ public: //- Null constructor inline PackedList(); - //- Construct with given size. Note: initializes intList to 0. + //- Construct with given size. Note: initializes list to 0. inline PackedList(const label size); //- Construct with given size and value for all elements. PackedList(const label size, const unsigned val); //- Copy constructor. - PackedList(const PackedList<nBits>& PList); + inline PackedList(const PackedList<nBits>&); //- Construct by transferring the parameter contents - PackedList(const Xfer<PackedList<nBits> >&); + inline PackedList(const Xfer<PackedList<nBits> >&); //- Construct from a list of labels PackedList(const UList<label>&); //- Clone - inline autoPtr<PackedList<nBits> > clone() const; + inline autoPtr< PackedList<nBits> > clone() const; // Member Functions // Access - //- The number of elements that can be stored before resizing - inline label capacity() const; - - //- Number of packed elements - inline label size() const; + //- The number of elements that can be stored before resizing + inline label capacity() const; - //- Return true if the list is empty (i.e., if size() == 0). - inline bool empty() const; + //- Number of packed elements. + inline label size() const; - //- Get value at index I - inline unsigned int get(const label i) const; + //- Return true if the list is empty (i.e., if size() == 0). + inline bool empty() const; - //- Set value at index I. Return true if value changed. - inline bool set(const label i, const unsigned int val); + //- Get value at index I. + // Does not auto-vivifies elements. + inline unsigned int get(const label i) const; - //- Underlying storage - inline List<unsigned int>& storage(); + //- Set value at index I. Return true if value changed. + // Does not auto-vivifies elements. + inline bool set(const label i, const unsigned int val); - //- Underlying storage - inline const List<unsigned int>& storage() const; + //- Underlying storage + inline const List<unsigned int>& storage() const; + //- Return as labelList + labelList values() const; // Edit - //- Reset size of List, setting zero for any new elements. - void setSize(const label); + //- Alter the size of the underlying storage. + // The addressed size will be truncated if needed to fit, but will + // remain otherwise untouched. + // Use this or reserve() in combination with append(). + inline void setCapacity(const label); - //- Reset size of List and value for new elements. - void setSize(const label, const unsigned int& val); + //- Reset size of List, optionally specify a value for new elements. + inline void resize(const label, const unsigned int& val = 0); - //- Reset size of List, setting zero for any new elements. - inline void resize(const label); + //- Reset size of List, optionally specify a value for new elements. + inline void setSize(const label, const unsigned int& val = 0); - //- Reset size of List and value for new elements. - inline void resize(const label, const unsigned int& val); + //- Reserve allocation space for at least this size. + // Never shrinks the allocated size. + // Optionally provide an initialization value for new elements. + inline void reserve(const label, const unsigned int& val = 0); - //- Construct with given size and value for all elements. + //- Clear the list, i.e. set size to zero. + //- Does not adjust the underlying storage + inline void clear(); - //- Clear the list, i.e. set size to zero. - void clear(); + //- Clear the list and delete storage. + inline void clearStorage(); - //- Transfer the contents of the argument List into this List - // and annull the argument list. - void transfer(PackedList<nBits>&); + //- Shrink the allocated space to what is used. + inline void shrink(); - //- Transfer contents to the Xfer container - inline Xfer<PackedList<nBits> > xfer(); + //- Transfer the contents of the argument List into this List + // and annull the argument list. + inline void transfer(PackedList<nBits>&); + //- Transfer contents to the Xfer container + inline Xfer<PackedList<nBits> > xfer(); // Member operators - //- Get value at index i - inline unsigned int operator[](const label i) const; + //- Append a value at the end of the list. Return true if value changed. + inline bool append(const unsigned int val); - //- Set value at index i. - // Returns proxy to perform the actual operation - inline ::Foam::PackedBitRef operator[](const label i); + //- Get value at index I + // Does not auto-vivifies elements. + inline unsigned int operator[](const label i) const; - //- Assignment operator. Takes linear time. - void operator=(const PackedList<nBits>&); + //- Set value at index I. + // Returns proxy to perform the actual operation. + // Auto-vivifies any new values to zero. + inline ::Foam::PackedBitRef<nBits> operator[](const label i); - //- Assignment of all entries to the given value. - // Does set on all elements. - inline void operator=(const unsigned int val); + //- Assignment of all entries to the given value. + // Does set on all elements. + inline void operator=(const unsigned int val); - //- Return as labelList - labelList operator()() const; + //- Assignment operator. Takes linear time. + void operator=(const PackedList<nBits>&); + //- Assignment operator. Takes linear time. + void operator=(const UList<label>&); // Ostream operator - // // Write PackedList to Ostream. - // friend Ostream& operator<< <nBits> (Ostream&, const PackedList<nBits>&); + // // Write PackedList to Ostream. + // friend Ostream& operator<< <nBits> (Ostream&, const PackedList<nBits>&); + }; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedListI.H b/src/OpenFOAM/containers/Lists/PackedList/PackedListI.H index d753a89426c1eab1c2d624e61bfaa6ab28f3caec..5d534e88da2f44bc9e5084efdca98fcc2e738308 100644 --- a/src/OpenFOAM/containers/Lists/PackedList/PackedListI.H +++ b/src/OpenFOAM/containers/Lists/PackedList/PackedListI.H @@ -33,21 +33,21 @@ License // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // template<int nBits> -inline unsigned int Foam::PackedList<nBits>::max_bits() +inline unsigned int Foam::PackedBitRef<nBits>::max_bits() { return sizeof(unsigned int)*8 - 1; } template<int nBits> -inline unsigned int Foam::PackedList<nBits>::max_value() +inline unsigned int Foam::PackedBitRef<nBits>::max_value() { return ((1u << nBits) - 1); } template<int nBits> -inline unsigned int Foam::PackedList<nBits>::packing() +inline unsigned int Foam::PackedBitRef<nBits>::packing() { return sizeof(unsigned int)*8 / nBits; } @@ -114,7 +114,7 @@ inline void Foam::PackedList<nBits>::checkIndex(const label i) const template<int nBits> inline Foam::PackedList<nBits>::PackedList() : - List<unsigned int>(0), + List<unsigned int>(), size_(0) {} @@ -128,12 +128,42 @@ inline Foam::PackedList<nBits>::PackedList(const label size) {} +template<int nBits> +inline Foam::PackedList<nBits>::PackedList(const PackedList<nBits>& lst) +: + List<unsigned int>(lst), + size_(lst.size()) +{} + + +template<int nBits> +inline Foam::PackedList<nBits>::PackedList(const Xfer<PackedList<nBits> >& lst) +{ + transfer(lst()); +} + + + +template<int nBits> +inline Foam::autoPtr<Foam::PackedList<nBits> > Foam::PackedList<nBits>::clone() const +{ + return autoPtr<PackedList<nBits> >(new PackedList<nBits>(*this)); +} + + // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template<int nBits> -inline void Foam::PackedList<nBits>::resize(const label newSize) +inline Foam::label Foam::PackedList<nBits>::size() const +{ + return size_; +} + + +template<int nBits> +inline bool Foam::PackedList<nBits>::empty() const { - setSize(newSize); + return !size_; } @@ -144,10 +174,23 @@ inline void Foam::PackedList<nBits>::resize const unsigned int& val ) { - setSize(newSize, val); + reserve(newSize, val); + size_ = newSize; +} + + +template<int nBits> +inline void Foam::PackedList<nBits>::setSize +( + const label newSize, + const unsigned int& val +) +{ + resize(newSize, val); } + template<int nBits> inline Foam::label Foam::PackedList<nBits>::capacity() const { @@ -156,16 +199,67 @@ inline Foam::label Foam::PackedList<nBits>::capacity() const template<int nBits> -inline Foam::label Foam::PackedList<nBits>::size() const +inline void Foam::PackedList<nBits>::setCapacity(const label nElem) { - return size_; + List<unsigned int>::setSize(storageSize(nElem), 0); + + for (label i = size_; i < nElem; i++) + { + set(i, 0); + } + + size_ = nElem; } template<int nBits> -inline bool Foam::PackedList<nBits>::empty() const +inline void Foam::PackedList<nBits>::reserve +( + const label nElem, + const unsigned int& val +) { - return !size_; + label rawSize = storageSize(nElem); + + // need more capacity? + if (rawSize > List<unsigned int>::size()) + { + List<unsigned int>::setSize(rawSize, 0); + } + + // fill new elements, don't rely on List::setSize + for (label i = size_; i < nElem; i++) + { + set(i, val); + } +} + + +template<int nBits> +inline void Foam::PackedList<nBits>::clear() +{ + size_ = 0; +} + + +template<int nBits> +inline void Foam::PackedList<nBits>::clearStorage() +{ + List<unsigned int>::clear(); + size_ = 0; +} + + +template<int nBits> +inline void Foam::PackedList<nBits>::shrink() +{ + label rawSize = storageSize(size_); + + // we have unused space? + if (rawSize < List<unsigned int>::size()) + { + List<unsigned int>::setSize(rawSize); + } } @@ -183,6 +277,10 @@ inline unsigned int Foam::PackedList<nBits>::get(const label i) const location(i, startBit) ); + // PackedBitRef<nBits> iter(*this, elem, startBit); + + // return PackedBitRef<nBits>(*this, elem, startBit)(); + return (elem >> startBit) & max_value(); } @@ -221,9 +319,13 @@ inline bool Foam::PackedList<nBits>::set(const label i, const unsigned int val) template<int nBits> -inline Foam::List<unsigned int>& Foam::PackedList<nBits>::storage() +inline bool Foam::PackedList<nBits>::append(const unsigned int val) { - return static_cast<List<unsigned int>&>(*this); + label elemI = size_; + reserve(elemI + 1); + size_++; + + return set(elemI, val); } @@ -234,6 +336,17 @@ inline const Foam::List<unsigned int>& Foam::PackedList<nBits>::storage() const } +template<int nBits> +inline void Foam::PackedList<nBits>::transfer(PackedList<nBits>& lst) +{ + size_ = lst.size_; + lst.size_ = 0; + + List<unsigned int>::transfer(lst); +} + + + template<int nBits> inline Foam::Xfer<Foam::PackedList<nBits> > Foam::PackedList<nBits>::xfer() @@ -244,12 +357,13 @@ Foam::PackedList<nBits>::xfer() template<int nBits> -inline Foam::PackedBitRef +inline typename Foam::PackedBitRef<nBits> Foam::PackedList<nBits>::operator[](const label i) { -# ifdef DEBUGList - checkIndex(i); -# endif + if (i >= size_) + { + setSize(i + 1); + } label startBit; unsigned int& elem = List<unsigned int>::operator[] @@ -257,7 +371,12 @@ Foam::PackedList<nBits>::operator[](const label i) location(i, startBit) ); - return ::Foam::PackedBitRef(elem, startBit, max_value()); + return ::Foam::PackedBitRef<nBits> + ( + // *this, + elem, + startBit + ); } @@ -269,17 +388,17 @@ inline void Foam::PackedList<nBits>::operator=(const unsigned int val) checkValue(val); # endif - if (val == 0) + if (val) { - List<unsigned int>::operator=(val); - } - else - { - for (label i = 0; i < size_; i++) + forAll(*this, i) { set(i, val); } } + else + { + List<unsigned int>::operator=(val); + } }