1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2010 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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
29 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
31 template<unsigned nBits>
32 inline unsigned int Foam::PackedList<nBits>::max_bits()
34 return sizeof(StorageType)*CHAR_BIT - 1;
38 template<unsigned nBits>
39 inline unsigned int Foam::PackedList<nBits>::max_value()
41 return (1u << nBits) - 1;
45 template<unsigned nBits>
46 inline unsigned int Foam::PackedList<nBits>::packing()
48 return sizeof(StorageType)*CHAR_BIT / nBits;
52 template<unsigned nBits>
53 inline unsigned int Foam::PackedList<nBits>::maskLower(unsigned offset)
55 // return (1u << (nBits * offset)) - 1;
56 // The next one works more reliably with overflows
57 // eg, when compiled without optimization
58 return (~0u >> ( sizeof(StorageType)*CHAR_BIT - nBits * offset));
62 template<unsigned nBits>
63 inline Foam::label Foam::PackedList<nBits>::packedLength(const label nElem)
65 return (nElem + packing() - 1) / packing();
71 // Template specialization for bool entries
73 inline unsigned int Foam::PackedList<1>::readValue(Istream& is)
78 // Template specialization for bool entries
80 inline void Foam::PackedList<1>::setPair(Istream& is)
82 set(readLabel(is), true);
85 // Template specialization for bool entries
87 inline bool Foam::PackedList<1>::iteratorBase::writeIfSet(Ostream& os) const
103 template<unsigned nBits>
104 inline unsigned int Foam::PackedList<nBits>::readValue(Istream& is)
106 const unsigned int val = readLabel(is);
108 if (val > max_value())
112 "PackedList<nBits>::readValue(Istream&)",
115 << "Out-of-range value " << val << " for PackedList<" << nBits
116 << ">. Maximum permitted value is " << max_value() << "."
117 << exit(FatalIOError);
124 template<unsigned nBits>
125 inline void Foam::PackedList<nBits>::setPair(Istream& is)
127 is.readBegin("Tuple2<label, unsigned int>");
129 const label ind = readLabel(is);
130 const unsigned int val = readLabel(is);
132 is.readEnd("Tuple2<label, unsigned int>");
134 if (val > max_value())
138 "PackedList<nBits>::setPair(Istream&)",
141 << "Out-of-range value " << val << " for PackedList<" << nBits
142 << "> at index " << ind
143 << ". Maximum permitted value is " << max_value() << "."
144 << exit(FatalIOError);
149 // Check state of Istream
150 is.check("PackedList<nBits>::setPair(Istream&)");
154 template<unsigned nBits>
155 inline bool Foam::PackedList<nBits>::iteratorBase::writeIfSet(Ostream& os) const
157 const label val = this->get();
161 os << token::BEGIN_LIST
162 << index_ << token::SPACE << val
174 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
176 template<unsigned nBits>
177 inline Foam::PackedList<nBits>::PackedList()
185 template<unsigned nBits>
186 inline Foam::PackedList<nBits>::PackedList(const label size)
189 StorageList(packedLength(size), 0u),
194 template<unsigned nBits>
195 inline Foam::PackedList<nBits>::PackedList
198 const unsigned int val
202 StorageList(packedLength(size), 0u),
212 template<unsigned nBits>
213 inline Foam::PackedList<nBits>::PackedList(Istream& is)
223 template<unsigned nBits>
224 inline Foam::PackedList<nBits>::PackedList(const PackedList<nBits>& lst)
232 template<unsigned nBits>
233 inline Foam::PackedList<nBits>::PackedList(const Xfer<PackedList<nBits> >& lst)
239 template<unsigned nBits>
240 inline Foam::PackedList<nBits>::PackedList(const labelUList& lst)
243 StorageList(packedLength(lst.size()), 0u),
253 template<unsigned nBits>
254 inline Foam::PackedList<nBits>::PackedList(const UIndirectList<label>& lst)
257 StorageList(packedLength(lst.size()), 0u),
267 template<unsigned nBits>
268 inline Foam::autoPtr<Foam::PackedList<nBits> >
269 Foam::PackedList<nBits>::clone() const
271 return autoPtr<PackedList<nBits> >(new PackedList<nBits>(*this));
275 // * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * //
279 template<unsigned nBits>
280 inline Foam::PackedList<nBits>::iteratorBase::iteratorBase()
287 template<unsigned nBits>
288 inline Foam::PackedList<nBits>::iteratorBase::iteratorBase
290 const PackedList<nBits>* lst,
294 list_(const_cast<PackedList<nBits>*>(lst)),
299 template<unsigned nBits>
301 Foam::PackedList<nBits>::iteratorBase::get() const
303 const unsigned int seg = index_ / packing();
304 const unsigned int off = index_ % packing();
306 const unsigned int& stored = list_->StorageList::operator[](seg);
307 return (stored >> (nBits * off)) & max_value();
311 template<unsigned nBits>
313 Foam::PackedList<nBits>::iteratorBase::set(const unsigned int val)
315 const unsigned int seg = index_ / packing();
316 const unsigned int off = index_ % packing();
318 const unsigned int startBit = nBits * off;
319 const unsigned int mask = max_value() << startBit;
321 unsigned int& stored = list_->StorageList::operator[](seg);
322 const unsigned int prev = stored;
324 if (val >= max_value())
326 // overflow is max_value, fill everything
332 stored |= mask & (val << startBit);
335 return prev != stored;
339 template<unsigned nBits>
340 inline Foam::label Foam::PackedList<nBits>::iteratorBase::key() const
346 template<unsigned nBits>
347 inline bool Foam::PackedList<nBits>::iteratorBase::operator==
349 const iteratorBase& iter
352 return this->get() == iter.get();
356 template<unsigned nBits>
357 inline bool Foam::PackedList<nBits>::iteratorBase::operator!=
359 const iteratorBase& iter
362 return this->get() != iter.get();
366 template<unsigned nBits>
368 Foam::PackedList<nBits>::iteratorBase::operator=(const iteratorBase& iter)
370 const unsigned int val = iter.get();
376 template<unsigned nBits>
378 Foam::PackedList<nBits>::iteratorBase::operator=(const unsigned int val)
380 // lazy evaluation - increase size on assigment
381 if (index_ >= list_->size_)
383 list_->resize(index_ + 1);
391 template<unsigned nBits>
392 inline Foam::PackedList<nBits>::iteratorBase::operator
393 unsigned int () const
395 // lazy evaluation - return 0 for out-of-range
396 if (index_ >= list_->size_)
405 // const_iterator, iterator
407 template<unsigned nBits>
408 inline Foam::PackedList<nBits>::iterator::iterator()
414 template<unsigned nBits>
415 inline Foam::PackedList<nBits>::const_iterator::const_iterator()
421 template<unsigned nBits>
422 inline Foam::PackedList<nBits>::iterator::iterator
424 const iteratorBase& iter
429 // avoid going past end()
430 // eg, iter = iterator(list, Inf)
431 if (this->index_ > this->list_->size_)
433 this->index_ = this->list_->size_;
438 template<unsigned nBits>
439 inline Foam::PackedList<nBits>::const_iterator::const_iterator
441 const iteratorBase& iter
446 // avoid going past end()
447 // eg, iter = iterator(list, Inf)
448 if (this->index_ > this->list_->size_)
450 this->index_ = this->list_->size_;
455 template<unsigned nBits>
456 inline Foam::PackedList<nBits>::iterator::iterator
458 const PackedList<nBits>* lst,
466 template<unsigned nBits>
467 inline Foam::PackedList<nBits>::const_iterator::const_iterator
469 const PackedList<nBits>* lst,
477 template<unsigned nBits>
478 inline Foam::PackedList<nBits>::const_iterator::const_iterator
483 iteratorBase(static_cast<const iteratorBase&>(iter))
487 template<unsigned nBits>
488 inline bool Foam::PackedList<nBits>::iterator::operator==
490 const iteratorBase& iter
493 return this->index_ == iter.index_;
497 template<unsigned nBits>
498 inline bool Foam::PackedList<nBits>::iterator::operator!=
500 const iteratorBase& iter
503 return this->index_ != iter.index_;
507 template<unsigned nBits>
508 inline bool Foam::PackedList<nBits>::const_iterator::operator==
510 const iteratorBase& iter
513 return this->index_ == iter.index_;
517 template<unsigned nBits>
518 inline bool Foam::PackedList<nBits>::const_iterator::operator!=
520 const iteratorBase& iter
523 return this->index_ != iter.index_;
527 template<unsigned nBits>
528 inline typename Foam::PackedList<nBits>::iterator&
529 Foam::PackedList<nBits>::iterator::operator=(const iteratorBase& iter)
531 this->list_ = iter.list_;
532 this->index_ = iter.index_;
534 // avoid going past end()
535 // eg, iter = iterator(list, Inf)
536 if (this->index_ > this->list_->size_)
538 this->index_ = this->list_->size_;
545 template<unsigned nBits>
546 inline typename Foam::PackedList<nBits>::const_iterator&
547 Foam::PackedList<nBits>::const_iterator::operator=(const iteratorBase& iter)
549 this->list_ = iter.list_;
550 this->index_ = iter.index_;
552 // avoid going past end()
553 // eg, iter = iterator(list, Inf)
554 if (this->index_ > this->list_->size_)
556 this->index_ = this->list_->size_;
563 template<unsigned nBits>
564 inline typename Foam::PackedList<nBits>::iterator&
565 Foam::PackedList<nBits>::iterator::operator++()
572 template<unsigned nBits>
573 inline typename Foam::PackedList<nBits>::const_iterator&
574 Foam::PackedList<nBits>::const_iterator::operator++()
581 template<unsigned nBits>
582 inline typename Foam::PackedList<nBits>::iterator
583 Foam::PackedList<nBits>::iterator::operator++(int)
585 iterator old = *this;
591 template<unsigned nBits>
592 inline typename Foam::PackedList<nBits>::const_iterator
593 Foam::PackedList<nBits>::const_iterator::operator++(int)
595 const_iterator old = *this;
601 template<unsigned nBits>
602 inline typename Foam::PackedList<nBits>::iterator&
603 Foam::PackedList<nBits>::iterator::operator--()
610 template<unsigned nBits>
611 inline typename Foam::PackedList<nBits>::const_iterator&
612 Foam::PackedList<nBits>::const_iterator::operator--()
619 template<unsigned nBits>
620 inline typename Foam::PackedList<nBits>::iterator
621 Foam::PackedList<nBits>::iterator::operator--(int)
623 iterator old = *this;
629 template<unsigned nBits>
630 inline typename Foam::PackedList<nBits>::const_iterator
631 Foam::PackedList<nBits>::const_iterator::operator--(int)
633 const_iterator old = *this;
639 template<unsigned nBits>
640 inline typename Foam::PackedList<nBits>::iteratorBase&
641 Foam::PackedList<nBits>::iterator::operator*()
643 return static_cast<iteratorBase&>(*this);
647 template<unsigned nBits>
648 inline typename Foam::PackedList<nBits>::iteratorBase&
649 Foam::PackedList<nBits>::iterator::operator()()
651 return static_cast<iteratorBase&>(*this);
655 template<unsigned nBits>
657 Foam::PackedList<nBits>::const_iterator::operator*() const
663 template<unsigned nBits>
665 Foam::PackedList<nBits>::const_iterator::operator()() const
671 template<unsigned nBits>
672 inline typename Foam::PackedList<nBits>::iterator
673 Foam::PackedList<nBits>::begin()
675 return iterator(this, 0);
679 template<unsigned nBits>
680 inline typename Foam::PackedList<nBits>::const_iterator
681 Foam::PackedList<nBits>::begin() const
683 return const_iterator(this, 0);
687 template<unsigned nBits>
688 inline typename Foam::PackedList<nBits>::const_iterator
689 Foam::PackedList<nBits>::cbegin() const
691 return const_iterator(this, 0);
695 template<unsigned nBits>
696 inline typename Foam::PackedList<nBits>::iterator
697 Foam::PackedList<nBits>::end()
699 return iterator(this, size_);
703 template<unsigned nBits>
704 inline typename Foam::PackedList<nBits>::const_iterator
705 Foam::PackedList<nBits>::end() const
707 return const_iterator(this, size_);
711 template<unsigned nBits>
712 inline typename Foam::PackedList<nBits>::const_iterator
713 Foam::PackedList<nBits>::cend() const
715 return const_iterator(this, size_);
719 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
721 template<unsigned nBits>
722 inline Foam::label Foam::PackedList<nBits>::size() const
728 template<unsigned nBits>
729 inline bool Foam::PackedList<nBits>::empty() const
735 template<unsigned nBits>
736 inline void Foam::PackedList<nBits>::resize
739 const unsigned int& val
744 const label oldSize = size_;
749 // fill new elements or newly exposed elements
752 // fill value for complete segments
753 unsigned int fill = val;
755 if (val >= max_value())
758 fill = maskLower(packing());
762 for (unsigned int i = 1; i < packing(); ++i)
764 fill |= (fill << nBits);
768 // fill in complete segments
769 const label oldLen = packedLength(oldSize);
770 const label newLen = packedLength(size_);
771 for (label i=oldLen; i < newLen; ++i)
773 StorageList::operator[](i) = fill;
776 // finish previous partial segment, preserve existing value
778 const unsigned int off = oldSize % packing();
781 const unsigned int seg = oldSize / packing();
782 const unsigned int mask = maskLower(off);
784 StorageList::operator[](seg) &= mask;
785 StorageList::operator[](seg) |= ~mask & fill;
790 // mask off the (new) final partial segment
792 const unsigned int off = size_ % packing();
795 const unsigned int seg = size_ / packing();
797 StorageList::operator[](seg) &= maskLower(off);
802 else if (size_ < oldSize)
805 // - clear newly exposed elements
807 // fill in complete segments
808 const label oldLen = packedLength(oldSize);
809 const label newLen = packedLength(size_);
810 for (label i=newLen; i < oldLen; ++i)
812 StorageList::operator[](i) = 0u;
815 // mask off the final partial segment
817 const unsigned int off = size_ % packing();
820 const unsigned int seg = size_ / packing();
822 StorageList::operator[](seg) &= maskLower(off);
829 template<unsigned nBits>
830 inline void Foam::PackedList<nBits>::setSize
833 const unsigned int& val
836 resize(newSize, val);
841 template<unsigned nBits>
842 inline Foam::label Foam::PackedList<nBits>::capacity() const
844 return packing() * StorageList::size();
848 template<unsigned nBits>
849 inline void Foam::PackedList<nBits>::setCapacity(const label nElem)
851 StorageList::setSize(packedLength(nElem), 0u);
853 // truncate addressed size too
858 // mask off the final partial segment
859 const unsigned int off = size_ % packing();
862 const unsigned int seg = size_ / packing();
864 StorageList::operator[](seg) &= maskLower(off);
870 template<unsigned nBits>
871 inline void Foam::PackedList<nBits>::reserve(const label nElem)
873 const label len = packedLength(nElem);
875 // need more capacity?
876 if (len > StorageList::size())
878 // Like DynamicList with SizeInc=0, SizeMult=2, SizeDiv=1
884 StorageList::size()*2
892 template<unsigned nBits>
893 inline void Foam::PackedList<nBits>::reset()
895 StorageList::operator=(0u);
899 template<unsigned nBits>
900 inline void Foam::PackedList<nBits>::clear()
907 template<unsigned nBits>
908 inline void Foam::PackedList<nBits>::clearStorage()
910 StorageList::clear();
915 template<unsigned nBits>
916 inline void Foam::PackedList<nBits>::shrink()
918 // any uneed space allocated?
919 const label len = packedLength();
920 if (len < StorageList::size())
922 StorageList::setSize(len);
926 template<unsigned nBits>
927 inline Foam::List<unsigned int>& Foam::PackedList<nBits>::storage()
929 return static_cast<StorageList&>(*this);
933 template<unsigned nBits>
934 inline const Foam::List<unsigned int>& Foam::PackedList<nBits>::storage() const
936 return static_cast<const StorageList&>(*this);
940 template<unsigned nBits>
941 inline Foam::label Foam::PackedList<nBits>::packedLength() const
943 return packedLength(size_);
947 template<unsigned nBits>
948 inline Foam::label Foam::PackedList<nBits>::byteSize() const
950 return packedLength() * sizeof(StorageType);
954 template<unsigned nBits>
955 inline void Foam::PackedList<nBits>::transfer(PackedList<nBits>& lst)
960 StorageList::transfer(lst);
964 template<unsigned nBits>
965 inline Foam::Xfer<Foam::PackedList<nBits> > Foam::PackedList<nBits>::xfer()
967 return xferMove(*this);
971 template<unsigned nBits>
972 inline unsigned int Foam::PackedList<nBits>::get(const label i) const
974 // lazy evaluation - return 0 for out-of-range
975 if (i < 0 || i >= size_)
981 return iteratorBase(this, i).get();
986 template<unsigned nBits>
987 inline unsigned int Foam::PackedList<nBits>::operator[](const label i) const
989 // lazy evaluation - return 0 for out-of-range
990 if (i < 0 || i >= size_)
996 return iteratorBase(this, i).get();
1001 template<unsigned nBits>
1002 inline bool Foam::PackedList<nBits>::set
1005 const unsigned int val
1010 // lazy evaluation - ignore out-of-bounds
1013 else if (i >= size_)
1015 // lazy evaluation - increase size on assigment
1019 return iteratorBase(this, i).set(val);
1023 template<unsigned nBits>
1024 inline bool Foam::PackedList<nBits>::unset(const label i)
1026 // lazy evaluation - ignore out-of-bounds
1027 if (i < 0 || i >= size_)
1033 return iteratorBase(this, i).set(0u);
1038 template<unsigned nBits>
1039 inline Foam::PackedList<nBits>&
1040 Foam::PackedList<nBits>::append(const unsigned int val)
1042 const label elemI = size_;
1046 iteratorBase(this, elemI).set(val);
1051 template<unsigned nBits>
1052 inline unsigned int Foam::PackedList<nBits>::remove()
1058 "Foam::PackedList<nBits>::remove()"
1059 ) << "List is empty" << abort(FatalError);
1062 label elemI = size_ - 1;
1063 const unsigned int val = iteratorBase(this, elemI).get();
1070 template<unsigned nBits>
1071 inline typename Foam::PackedList<nBits>::iteratorBase
1072 Foam::PackedList<nBits>::operator[](const label i)
1074 return iteratorBase(this, i);
1078 template<unsigned nBits>
1079 inline Foam::PackedList<nBits>&
1080 Foam::PackedList<nBits>::operator=(const unsigned int val)
1082 const label packLen = packedLength();
1086 unsigned int fill = val;
1088 if (val >= max_value())
1091 fill = maskLower(packing());
1095 for (unsigned int i = 1; i < packing(); ++i)
1097 fill |= (fill << nBits);
1101 for (label i=0; i < packLen; ++i)
1103 StorageList::operator[](i) = fill;
1106 // mask off the final partial segment
1108 const unsigned int off = size_ % packing();
1111 const unsigned int seg = size_ / packing();
1113 StorageList::operator[](seg) &= maskLower(off);
1119 for (label i=0; i < packLen; ++i)
1121 StorageList::operator[](i) = 0u;
1129 // ************************************************************************* //