1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
25 \*---------------------------------------------------------------------------*/
30 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
32 template<unsigned nBits>
33 inline unsigned int Foam::PackedList<nBits>::max_bits()
35 return sizeof(StorageType)*CHAR_BIT - 1;
39 template<unsigned nBits>
40 inline unsigned int Foam::PackedList<nBits>::max_value()
42 return (1u << nBits) - 1;
46 template<unsigned nBits>
47 inline unsigned int Foam::PackedList<nBits>::packing()
49 return sizeof(StorageType)*CHAR_BIT / nBits;
53 template<unsigned nBits>
54 inline unsigned int Foam::PackedList<nBits>::maskLower(unsigned offset)
56 // return (1u << (nBits * offset)) - 1;
57 // The next one works more reliably with overflows
58 // eg, when compiled without optimization
59 return (~0u >> ( sizeof(StorageType)*CHAR_BIT - nBits * offset));
63 template<unsigned nBits>
64 inline Foam::label Foam::PackedList<nBits>::packedLength(const label nElem)
66 return (nElem + packing() - 1) / packing();
70 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
72 template<unsigned nBits>
73 inline Foam::PackedList<nBits>::PackedList()
80 template<unsigned nBits>
81 inline Foam::PackedList<nBits>::PackedList(const label size)
83 StorageList(packedLength(size), 0u),
88 template<unsigned nBits>
89 inline Foam::PackedList<nBits>::PackedList(const PackedList<nBits>& lst)
96 template<unsigned nBits>
97 inline Foam::PackedList<nBits>::PackedList(const Xfer<PackedList<nBits> >& lst)
103 template<unsigned nBits>
104 inline Foam::autoPtr<Foam::PackedList<nBits> >
105 Foam::PackedList<nBits>::clone() const
107 return autoPtr<PackedList<nBits> >(new PackedList<nBits>(*this));
111 // * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * //
115 template<unsigned nBits>
116 inline Foam::PackedList<nBits>::iteratorBase::iteratorBase()
123 template<unsigned nBits>
124 inline Foam::PackedList<nBits>::iteratorBase::iteratorBase
126 const PackedList<nBits>* lst,
130 list_(const_cast<PackedList<nBits>*>(lst)),
135 template<unsigned nBits>
137 Foam::PackedList<nBits>::iteratorBase::get() const
139 const unsigned int seg = index_ / packing();
140 const unsigned int off = index_ % packing();
142 const unsigned int& stored = list_->StorageList::operator[](seg);
143 return (stored >> (nBits * off)) & max_value();
147 template<unsigned nBits>
149 Foam::PackedList<nBits>::iteratorBase::set(const unsigned int val)
151 const unsigned int seg = index_ / packing();
152 const unsigned int off = index_ % packing();
154 unsigned int& stored = list_->StorageList::operator[](seg);
155 const unsigned int prev = stored;
157 const unsigned int startBit = nBits * off;
158 const unsigned int maskNew = max_value() << startBit;
160 if (val & ~max_value())
162 // overflow is max_value, fill everything
168 stored |= maskNew & (val << startBit);
171 return prev != stored;
175 template<unsigned nBits>
176 inline bool Foam::PackedList<nBits>::iteratorBase::operator==
178 const iteratorBase& iter
181 return this->get() == iter.get();
185 template<unsigned nBits>
186 inline bool Foam::PackedList<nBits>::iteratorBase::operator!=
188 const iteratorBase& iter
191 return this->get() != iter.get();
195 template<unsigned nBits>
197 Foam::PackedList<nBits>::iteratorBase::operator=(const iteratorBase& iter)
199 const unsigned int val = iter.get();
205 template<unsigned nBits>
207 Foam::PackedList<nBits>::iteratorBase::operator=(const unsigned int val)
209 // lazy evaluation - increase size on assigment
210 if (index_ >= list_->size_)
212 list_->resize(index_ + 1);
220 template<unsigned nBits>
221 inline Foam::PackedList<nBits>::iteratorBase::operator
222 unsigned int () const
224 // lazy evaluation - return 0 for out-of-range
225 if (index_ >= list_->size_)
234 // const_iterator, iterator
236 template<unsigned nBits>
237 inline Foam::PackedList<nBits>::iterator::iterator()
243 template<unsigned nBits>
244 inline Foam::PackedList<nBits>::const_iterator::const_iterator()
250 template<unsigned nBits>
251 inline Foam::PackedList<nBits>::iterator::iterator
253 const iteratorBase& iter
258 // avoid going past end()
259 // eg, iter = iterator(list, Inf)
260 if (this->index_ > this->list_->size_)
262 this->index_ = this->list_->size_;
267 template<unsigned nBits>
268 inline Foam::PackedList<nBits>::const_iterator::const_iterator
270 const iteratorBase& iter
275 // avoid going past end()
276 // eg, iter = iterator(list, Inf)
277 if (this->index_ > this->list_->size_)
279 this->index_ = this->list_->size_;
284 template<unsigned nBits>
285 inline Foam::PackedList<nBits>::iterator::iterator
287 const PackedList<nBits>* lst,
295 template<unsigned nBits>
296 inline Foam::PackedList<nBits>::const_iterator::const_iterator
298 const PackedList<nBits>* lst,
306 template<unsigned nBits>
307 inline Foam::PackedList<nBits>::const_iterator::const_iterator
312 iteratorBase(static_cast<const iteratorBase&>(iter))
316 template<unsigned nBits>
317 inline bool Foam::PackedList<nBits>::iterator::operator==
319 const iteratorBase& iter
322 return this->index_ == iter.index_;
326 template<unsigned nBits>
327 inline bool Foam::PackedList<nBits>::iterator::operator!=
329 const iteratorBase& iter
332 return this->index_ != iter.index_;
337 template<unsigned nBits>
338 inline bool Foam::PackedList<nBits>::const_iterator::operator==
340 const iteratorBase& iter
343 return this->index_ == iter.index_;
347 template<unsigned nBits>
348 inline bool Foam::PackedList<nBits>::const_iterator::operator!=
350 const iteratorBase& iter
353 return this->index_ != iter.index_;
358 template<unsigned nBits>
359 inline typename Foam::PackedList<nBits>::iterator&
360 Foam::PackedList<nBits>::iterator::operator=(const iteratorBase& iter)
362 this->list_ = iter.list_;
363 this->index_ = iter.index_;
365 // avoid going past end()
366 // eg, iter = iterator(list, Inf)
367 if (this->index_ > this->list_->size_)
369 this->index_ = this->list_->size_;
376 template<unsigned nBits>
377 inline typename Foam::PackedList<nBits>::const_iterator&
378 Foam::PackedList<nBits>::const_iterator::operator=(const iteratorBase& iter)
380 this->list_ = iter.list_;
381 this->index_ = iter.index_;
383 // avoid going past end()
384 // eg, iter = iterator(list, Inf)
385 if (this->index_ > this->list_->size_)
387 this->index_ = this->list_->size_;
394 template<unsigned nBits>
395 inline typename Foam::PackedList<nBits>::iterator&
396 Foam::PackedList<nBits>::iterator::operator++()
403 template<unsigned nBits>
404 inline typename Foam::PackedList<nBits>::const_iterator&
405 Foam::PackedList<nBits>::const_iterator::operator++()
412 template<unsigned nBits>
413 inline typename Foam::PackedList<nBits>::iterator
414 Foam::PackedList<nBits>::iterator::operator++(int)
416 iterator old = *this;
422 template<unsigned nBits>
423 inline typename Foam::PackedList<nBits>::const_iterator
424 Foam::PackedList<nBits>::const_iterator::operator++(int)
426 const_iterator old = *this;
432 template<unsigned nBits>
433 inline typename Foam::PackedList<nBits>::iterator&
434 Foam::PackedList<nBits>::iterator::operator--()
441 template<unsigned nBits>
442 inline typename Foam::PackedList<nBits>::const_iterator&
443 Foam::PackedList<nBits>::const_iterator::operator--()
450 template<unsigned nBits>
451 inline typename Foam::PackedList<nBits>::iterator
452 Foam::PackedList<nBits>::iterator::operator--(int)
454 iterator old = *this;
460 template<unsigned nBits>
461 inline typename Foam::PackedList<nBits>::const_iterator
462 Foam::PackedList<nBits>::const_iterator::operator--(int)
464 const_iterator old = *this;
470 template<unsigned nBits>
471 inline typename Foam::PackedList<nBits>::iteratorBase&
472 Foam::PackedList<nBits>::iterator::operator*()
474 return static_cast<iteratorBase&>(*this);
478 template<unsigned nBits>
479 inline typename Foam::PackedList<nBits>::iteratorBase&
480 Foam::PackedList<nBits>::iterator::operator()()
482 return static_cast<iteratorBase&>(*this);
486 template<unsigned nBits>
488 Foam::PackedList<nBits>::const_iterator::operator*() const
494 template<unsigned nBits>
496 Foam::PackedList<nBits>::const_iterator::operator()() const
502 template<unsigned nBits>
503 inline typename Foam::PackedList<nBits>::iterator
504 Foam::PackedList<nBits>::begin()
506 return iterator(this, 0);
510 template<unsigned nBits>
511 inline typename Foam::PackedList<nBits>::const_iterator
512 Foam::PackedList<nBits>::begin() const
514 return const_iterator(this, 0);
518 template<unsigned nBits>
519 inline typename Foam::PackedList<nBits>::const_iterator
520 Foam::PackedList<nBits>::cbegin() const
522 return const_iterator(this, 0);
526 template<unsigned nBits>
527 inline typename Foam::PackedList<nBits>::iterator
528 Foam::PackedList<nBits>::end()
530 return iterator(this, size_);
534 template<unsigned nBits>
535 inline typename Foam::PackedList<nBits>::const_iterator
536 Foam::PackedList<nBits>::end() const
538 return const_iterator(this, size_);
542 template<unsigned nBits>
543 inline typename Foam::PackedList<nBits>::const_iterator
544 Foam::PackedList<nBits>::cend() const
546 return const_iterator(this, size_);
550 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
552 template<unsigned nBits>
553 inline Foam::label Foam::PackedList<nBits>::size() const
559 template<unsigned nBits>
560 inline bool Foam::PackedList<nBits>::empty() const
566 template<unsigned nBits>
567 inline void Foam::PackedList<nBits>::resize
570 const unsigned int& val
577 // fill new elements or newly exposed elements
580 // fill value for complete segments
581 unsigned int fill = val;
583 if (fill & ~max_value())
585 // overflow is max_value, fill everything
590 for (unsigned int i = 1; i < packing(); ++i)
592 fill |= (fill << nBits);
596 unsigned int seg = size_ / packing();
597 unsigned int off = size_ % packing();
599 // partial segment, preserve existing value
602 unsigned int maskOld = maskLower(off);
604 StorageList::operator[](seg) &= maskOld;
605 StorageList::operator[](seg) |= ~maskOld & fill;
607 // continue with the next segment
611 unsigned int endSeg = nElem / packing();
612 // fill in complete elements
615 StorageList::operator[](seg++) = fill;
620 // no original size - simply flood-fill
629 template<unsigned nBits>
630 inline void Foam::PackedList<nBits>::setSize
633 const unsigned int& val
636 resize(newSize, val);
641 template<unsigned nBits>
642 inline Foam::label Foam::PackedList<nBits>::capacity() const
644 return packing() * StorageList::size();
648 template<unsigned nBits>
649 inline void Foam::PackedList<nBits>::setCapacity(const label nElem)
651 StorageList::setSize(packedLength(nElem), 0u);
653 // truncate addressed size too?
661 template<unsigned nBits>
662 inline void Foam::PackedList<nBits>::reserve
667 label len = packedLength(nElem);
669 // need more capacity?
670 if (len > StorageList::size())
672 // Like DynamicList with SizeInc=0, SizeMult=2, SizeDiv=1
678 StorageList::size()*2
686 template<unsigned nBits>
687 inline void Foam::PackedList<nBits>::clear()
693 template<unsigned nBits>
694 inline void Foam::PackedList<nBits>::clearStorage()
696 StorageList::clear();
701 template<unsigned nBits>
702 inline void Foam::PackedList<nBits>::shrink()
704 label len = packedLength(size_);
706 // we have unused space?
707 if (len < StorageList::size())
709 StorageList::setSize(len);
713 template<unsigned nBits>
714 inline Foam::List<unsigned int>&
715 Foam::PackedList<nBits>::storage()
717 return static_cast<StorageList&>(*this);
721 template<unsigned nBits>
722 inline const Foam::List<unsigned int>&
723 Foam::PackedList<nBits>::storage() const
725 return static_cast<const StorageList&>(*this);
729 template<unsigned nBits>
730 inline void Foam::PackedList<nBits>::transfer(PackedList<nBits>& lst)
735 StorageList::transfer(lst);
739 template<unsigned nBits>
740 inline Foam::Xfer< Foam::PackedList<nBits> >
741 Foam::PackedList<nBits>::xfer()
743 return xferMove(*this);
747 template<unsigned nBits>
748 inline unsigned int Foam::PackedList<nBits>::get(const label i) const
753 FatalErrorIn("PackedList<nBits>::get(const label)")
754 << "negative index " << i << " max=" << size_-1
755 << abort(FatalError);
759 // lazy evaluation - return 0 for out-of-range
762 return iteratorBase(this, i).get();
771 template<unsigned nBits>
772 inline unsigned int Foam::PackedList<nBits>::operator[](const label i) const
774 // lazy evaluation - return 0 for out-of-range
777 return iteratorBase(this, i).get();
786 template<unsigned nBits>
787 inline bool Foam::PackedList<nBits>::set
790 const unsigned int val
796 FatalErrorIn("PackedList<nBits>::set(const label)")
797 << "negative index " << i << " max=" << size_-1
798 << abort(FatalError);
802 // lazy evaluation - increase size on assigment
808 return iteratorBase(this, i).set(val);
812 template<unsigned nBits>
813 inline bool Foam::PackedList<nBits>::unset(const label i)
815 // lazy - ignore out-of-bounds
816 if (i < 0 || i >= size_)
821 return iteratorBase(this, i).set(0u);
825 template<unsigned nBits>
826 inline void Foam::PackedList<nBits>::append(const unsigned int val)
832 iteratorBase(this, elemI).set(val);
836 template<unsigned nBits>
837 inline unsigned int Foam::PackedList<nBits>::remove()
843 "Foam::PackedList<nBits>::remove()"
844 ) << "List is empty" << abort(FatalError);
847 label elemI = size_ - 1;
848 const unsigned int val = iteratorBase(this, elemI).get();
855 template<unsigned nBits>
856 inline typename Foam::PackedList<nBits>::iteratorBase
857 Foam::PackedList<nBits>::operator[](const label i)
859 return iteratorBase(this, i);
865 // specialization for nBits=1
867 inline void Foam::PackedList<1>::operator=(const unsigned int val)
871 StorageList::operator=(~0u);
875 StorageList::operator=(0u);
881 template<unsigned nBits>
882 inline void Foam::PackedList<nBits>::operator=(const unsigned int val)
886 unsigned int fill = val;
888 if (fill & ~max_value())
890 // treat overflow as max_value
895 for (unsigned int i = 1; i < packing(); ++i)
897 fill |= (fill << nBits);
901 StorageList::operator=(fill);
905 StorageList::operator=(0u);
910 // ************************************************************************* //