1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
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
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
26 \*---------------------------------------------------------------------------*/
31 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
33 template<unsigned nBits>
34 inline unsigned int Foam::PackedList<nBits>::max_bits()
36 return sizeof(StorageType)*CHAR_BIT - 1;
40 template<unsigned nBits>
41 inline unsigned int Foam::PackedList<nBits>::max_value()
43 return (1u << nBits) - 1;
47 template<unsigned nBits>
48 inline unsigned int Foam::PackedList<nBits>::packing()
50 return sizeof(StorageType)*CHAR_BIT / nBits;
54 template<unsigned nBits>
55 inline unsigned int Foam::PackedList<nBits>::maskLower(unsigned offset)
57 // return (1u << (nBits * offset)) - 1;
58 // The next one works more reliably with overflows
59 // eg, when compiled without optimization
60 return (~0u >> ( sizeof(StorageType)*CHAR_BIT - nBits * offset));
64 template<unsigned nBits>
65 inline Foam::label Foam::PackedList<nBits>::packedLength(const label nElem)
67 return (nElem + packing() - 1) / packing();
71 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
73 template<unsigned nBits>
74 inline Foam::PackedList<nBits>::PackedList()
81 template<unsigned nBits>
82 inline Foam::PackedList<nBits>::PackedList(const label size)
84 StorageList(packedLength(size), 0u),
89 template<unsigned nBits>
90 inline Foam::PackedList<nBits>::PackedList(const PackedList<nBits>& lst)
97 template<unsigned nBits>
98 inline Foam::PackedList<nBits>::PackedList(const Xfer<PackedList<nBits> >& lst)
104 template<unsigned nBits>
105 inline Foam::autoPtr<Foam::PackedList<nBits> >
106 Foam::PackedList<nBits>::clone() const
108 return autoPtr<PackedList<nBits> >(new PackedList<nBits>(*this));
112 // * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * //
116 template<unsigned nBits>
117 inline Foam::PackedList<nBits>::iteratorBase::iteratorBase()
124 template<unsigned nBits>
125 inline Foam::PackedList<nBits>::iteratorBase::iteratorBase
127 const PackedList<nBits>* lst,
131 list_(const_cast<PackedList<nBits>*>(lst)),
136 template<unsigned nBits>
138 Foam::PackedList<nBits>::iteratorBase::get() const
140 const unsigned int seg = index_ / packing();
141 const unsigned int off = index_ % packing();
143 const unsigned int& stored = list_->StorageList::operator[](seg);
144 return (stored >> (nBits * off)) & max_value();
148 template<unsigned nBits>
150 Foam::PackedList<nBits>::iteratorBase::set(const unsigned int val)
152 const unsigned int seg = index_ / packing();
153 const unsigned int off = index_ % packing();
155 unsigned int& stored = list_->StorageList::operator[](seg);
156 const unsigned int prev = stored;
158 const unsigned int startBit = nBits * off;
159 const unsigned int maskNew = max_value() << startBit;
161 if (val & ~max_value())
163 // overflow is max_value, fill everything
169 stored |= maskNew & (val << startBit);
172 return prev != stored;
176 template<unsigned nBits>
177 inline bool Foam::PackedList<nBits>::iteratorBase::operator==
179 const iteratorBase& iter
182 return this->get() == iter.get();
186 template<unsigned nBits>
187 inline bool Foam::PackedList<nBits>::iteratorBase::operator!=
189 const iteratorBase& iter
192 return this->get() != iter.get();
196 template<unsigned nBits>
198 Foam::PackedList<nBits>::iteratorBase::operator=(const iteratorBase& iter)
200 const unsigned int val = iter.get();
206 template<unsigned nBits>
208 Foam::PackedList<nBits>::iteratorBase::operator=(const unsigned int val)
210 // lazy evaluation - increase size on assigment
211 if (index_ >= list_->size_)
213 list_->resize(index_ + 1);
221 template<unsigned nBits>
222 inline Foam::PackedList<nBits>::iteratorBase::operator
223 unsigned int () const
225 // lazy evaluation - return 0 for out-of-range
226 if (index_ >= list_->size_)
235 // const_iterator, iterator
237 template<unsigned nBits>
238 inline Foam::PackedList<nBits>::iterator::iterator()
244 template<unsigned nBits>
245 inline Foam::PackedList<nBits>::const_iterator::const_iterator()
251 template<unsigned nBits>
252 inline Foam::PackedList<nBits>::iterator::iterator
254 const iteratorBase& iter
259 // avoid going past end()
260 // eg, iter = iterator(list, Inf)
261 if (this->index_ > this->list_->size_)
263 this->index_ = this->list_->size_;
268 template<unsigned nBits>
269 inline Foam::PackedList<nBits>::const_iterator::const_iterator
271 const iteratorBase& iter
276 // avoid going past end()
277 // eg, iter = iterator(list, Inf)
278 if (this->index_ > this->list_->size_)
280 this->index_ = this->list_->size_;
285 template<unsigned nBits>
286 inline Foam::PackedList<nBits>::iterator::iterator
288 const PackedList<nBits>* lst,
296 template<unsigned nBits>
297 inline Foam::PackedList<nBits>::const_iterator::const_iterator
299 const PackedList<nBits>* lst,
307 template<unsigned nBits>
308 inline Foam::PackedList<nBits>::const_iterator::const_iterator
313 iteratorBase(static_cast<const iteratorBase&>(iter))
317 template<unsigned nBits>
318 inline bool Foam::PackedList<nBits>::iterator::operator==
320 const iteratorBase& iter
323 return this->index_ == iter.index_;
327 template<unsigned nBits>
328 inline bool Foam::PackedList<nBits>::iterator::operator!=
330 const iteratorBase& iter
333 return this->index_ != iter.index_;
338 template<unsigned nBits>
339 inline bool Foam::PackedList<nBits>::const_iterator::operator==
341 const iteratorBase& iter
344 return this->index_ == iter.index_;
348 template<unsigned nBits>
349 inline bool Foam::PackedList<nBits>::const_iterator::operator!=
351 const iteratorBase& iter
354 return this->index_ != iter.index_;
359 template<unsigned nBits>
360 inline typename Foam::PackedList<nBits>::iterator&
361 Foam::PackedList<nBits>::iterator::operator=(const iteratorBase& iter)
363 this->list_ = iter.list_;
364 this->index_ = iter.index_;
366 // avoid going past end()
367 // eg, iter = iterator(list, Inf)
368 if (this->index_ > this->list_->size_)
370 this->index_ = this->list_->size_;
377 template<unsigned nBits>
378 inline typename Foam::PackedList<nBits>::const_iterator&
379 Foam::PackedList<nBits>::const_iterator::operator=(const iteratorBase& iter)
381 this->list_ = iter.list_;
382 this->index_ = iter.index_;
384 // avoid going past end()
385 // eg, iter = iterator(list, Inf)
386 if (this->index_ > this->list_->size_)
388 this->index_ = this->list_->size_;
395 template<unsigned nBits>
396 inline typename Foam::PackedList<nBits>::iterator&
397 Foam::PackedList<nBits>::iterator::operator++()
404 template<unsigned nBits>
405 inline typename Foam::PackedList<nBits>::const_iterator&
406 Foam::PackedList<nBits>::const_iterator::operator++()
413 template<unsigned nBits>
414 inline typename Foam::PackedList<nBits>::iterator
415 Foam::PackedList<nBits>::iterator::operator++(int)
417 iterator old = *this;
423 template<unsigned nBits>
424 inline typename Foam::PackedList<nBits>::const_iterator
425 Foam::PackedList<nBits>::const_iterator::operator++(int)
427 const_iterator old = *this;
433 template<unsigned nBits>
434 inline typename Foam::PackedList<nBits>::iterator&
435 Foam::PackedList<nBits>::iterator::operator--()
442 template<unsigned nBits>
443 inline typename Foam::PackedList<nBits>::const_iterator&
444 Foam::PackedList<nBits>::const_iterator::operator--()
451 template<unsigned nBits>
452 inline typename Foam::PackedList<nBits>::iterator
453 Foam::PackedList<nBits>::iterator::operator--(int)
455 iterator old = *this;
461 template<unsigned nBits>
462 inline typename Foam::PackedList<nBits>::const_iterator
463 Foam::PackedList<nBits>::const_iterator::operator--(int)
465 const_iterator old = *this;
471 template<unsigned nBits>
472 inline typename Foam::PackedList<nBits>::iteratorBase&
473 Foam::PackedList<nBits>::iterator::operator*()
475 return static_cast<iteratorBase&>(*this);
479 template<unsigned nBits>
480 inline typename Foam::PackedList<nBits>::iteratorBase&
481 Foam::PackedList<nBits>::iterator::operator()()
483 return static_cast<iteratorBase&>(*this);
487 template<unsigned nBits>
489 Foam::PackedList<nBits>::const_iterator::operator*() const
495 template<unsigned nBits>
497 Foam::PackedList<nBits>::const_iterator::operator()() const
503 template<unsigned nBits>
504 inline typename Foam::PackedList<nBits>::iterator
505 Foam::PackedList<nBits>::begin()
507 return iterator(this, 0);
511 template<unsigned nBits>
512 inline typename Foam::PackedList<nBits>::const_iterator
513 Foam::PackedList<nBits>::begin() const
515 return const_iterator(this, 0);
519 template<unsigned nBits>
520 inline typename Foam::PackedList<nBits>::const_iterator
521 Foam::PackedList<nBits>::cbegin() const
523 return const_iterator(this, 0);
527 template<unsigned nBits>
528 inline typename Foam::PackedList<nBits>::iterator
529 Foam::PackedList<nBits>::end()
531 return iterator(this, size_);
535 template<unsigned nBits>
536 inline typename Foam::PackedList<nBits>::const_iterator
537 Foam::PackedList<nBits>::end() const
539 return const_iterator(this, size_);
543 template<unsigned nBits>
544 inline typename Foam::PackedList<nBits>::const_iterator
545 Foam::PackedList<nBits>::cend() const
547 return const_iterator(this, size_);
551 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
553 template<unsigned nBits>
554 inline Foam::label Foam::PackedList<nBits>::size() const
560 template<unsigned nBits>
561 inline bool Foam::PackedList<nBits>::empty() const
567 template<unsigned nBits>
568 inline void Foam::PackedList<nBits>::resize
571 const unsigned int& val
578 // fill new elements or newly exposed elements
581 // fill value for complete segments
582 unsigned int fill = val;
584 if (fill & ~max_value())
586 // overflow is max_value, fill everything
591 for (unsigned int i = 1; i < packing(); ++i)
593 fill |= (fill << nBits);
597 unsigned int seg = size_ / packing();
598 unsigned int off = size_ % packing();
600 // partial segment, preserve existing value
603 unsigned int maskOld = maskLower(off);
605 StorageList::operator[](seg) &= maskOld;
606 StorageList::operator[](seg) |= ~maskOld & fill;
608 // continue with the next segment
612 unsigned int endSeg = nElem / packing();
613 // fill in complete elements
616 StorageList::operator[](seg++) = fill;
621 // no original size - simply flood-fill
630 template<unsigned nBits>
631 inline void Foam::PackedList<nBits>::setSize
634 const unsigned int& val
637 resize(newSize, val);
642 template<unsigned nBits>
643 inline Foam::label Foam::PackedList<nBits>::capacity() const
645 return packing() * StorageList::size();
649 template<unsigned nBits>
650 inline void Foam::PackedList<nBits>::setCapacity(const label nElem)
652 StorageList::setSize(packedLength(nElem), 0u);
654 // truncate addressed size too?
662 template<unsigned nBits>
663 inline void Foam::PackedList<nBits>::reserve
668 label len = packedLength(nElem);
670 // need more capacity?
671 if (len > StorageList::size())
673 // Like DynamicList with SizeInc=0, SizeMult=2, SizeDiv=1
679 StorageList::size()*2
687 template<unsigned nBits>
688 inline void Foam::PackedList<nBits>::clear()
694 template<unsigned nBits>
695 inline void Foam::PackedList<nBits>::clearStorage()
697 StorageList::clear();
702 template<unsigned nBits>
703 inline void Foam::PackedList<nBits>::shrink()
705 label len = packedLength(size_);
707 // we have unused space?
708 if (len < StorageList::size())
710 StorageList::setSize(len);
714 template<unsigned nBits>
715 inline Foam::List<unsigned int>&
716 Foam::PackedList<nBits>::storage()
718 return static_cast<StorageList&>(*this);
722 template<unsigned nBits>
723 inline const Foam::List<unsigned int>&
724 Foam::PackedList<nBits>::storage() const
726 return static_cast<const StorageList&>(*this);
730 template<unsigned nBits>
731 inline void Foam::PackedList<nBits>::transfer(PackedList<nBits>& lst)
736 StorageList::transfer(lst);
740 template<unsigned nBits>
741 inline Foam::Xfer< Foam::PackedList<nBits> >
742 Foam::PackedList<nBits>::xfer()
744 return xferMove(*this);
748 template<unsigned nBits>
749 inline unsigned int Foam::PackedList<nBits>::get(const label i) const
754 FatalErrorIn("PackedList<nBits>::get(const label)")
755 << "negative index " << i << " max=" << size_-1
756 << abort(FatalError);
760 // lazy evaluation - return 0 for out-of-range
763 return iteratorBase(this, i).get();
772 template<unsigned nBits>
773 inline unsigned int Foam::PackedList<nBits>::operator[](const label i) const
775 // lazy evaluation - return 0 for out-of-range
778 return iteratorBase(this, i).get();
787 template<unsigned nBits>
788 inline bool Foam::PackedList<nBits>::set
791 const unsigned int val
797 FatalErrorIn("PackedList<nBits>::set(const label)")
798 << "negative index " << i << " max=" << size_-1
799 << abort(FatalError);
803 // lazy evaluation - increase size on assigment
809 return iteratorBase(this, i).set(val);
813 template<unsigned nBits>
814 inline bool Foam::PackedList<nBits>::unset(const label i)
816 // lazy - ignore out-of-bounds
817 if (i < 0 || i >= size_)
822 return iteratorBase(this, i).set(0u);
826 template<unsigned nBits>
827 inline void Foam::PackedList<nBits>::append(const unsigned int val)
833 iteratorBase(this, elemI).set(val);
837 template<unsigned nBits>
838 inline unsigned int Foam::PackedList<nBits>::remove()
844 "Foam::PackedList<nBits>::remove()"
845 ) << "List is empty" << abort(FatalError);
848 label elemI = size_ - 1;
849 const unsigned int val = iteratorBase(this, elemI).get();
856 template<unsigned nBits>
857 inline typename Foam::PackedList<nBits>::iteratorBase
858 Foam::PackedList<nBits>::operator[](const label i)
860 return iteratorBase(this, i);
866 // specialization for nBits=1
868 inline void Foam::PackedList<1>::operator=(const unsigned int val)
872 StorageList::operator=(~0u);
876 StorageList::operator=(0u);
882 template<unsigned nBits>
883 inline void Foam::PackedList<nBits>::operator=(const unsigned int val)
887 unsigned int fill = val;
889 if (fill & ~max_value())
891 // treat overflow as max_value
896 for (unsigned int i = 1; i < packing(); ++i)
898 fill |= (fill << nBits);
902 StorageList::operator=(fill);
906 StorageList::operator=(0u);
911 // ************************************************************************* //