PackedListI.H
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2017-2021 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "error.H"
30
31// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
32
33template<unsigned Width>
34inline unsigned int Foam::PackedList<Width>::repeated_value(unsigned val)
35{
36 return BitOps::repeat_value<block_type,Width>(val);
37}
38
39
40template<unsigned Width>
42{
43 const unsigned int val = readLabel(is);
44
45 if (val > max_value)
46 {
48 << "Out-of-range value " << val << " for PackedList<" << Width
49 << ">. Maximum permitted value is " << max_value << "."
51 }
52
53 return val;
54}
55
56
57template<unsigned Width>
59{
60 is.readBegin("Tuple2<label,uint32>");
61
62 const label ind = readLabel(is);
63 const unsigned int val = readLabel(is);
64
65 is.readEnd("Tuple2<label,uint32>");
66
67 if (val > max_value)
68 {
70 << "Out-of-range value " << val << " for PackedList<" << Width
71 << "> at index " << ind
72 << ". Maximum permitted value is " << max_value << "."
74 }
75
76 set(ind, val);
77
79}
80
81
82template<unsigned Width>
84{
85 // Mask off any partial rubbish in final block
86 const unsigned int blk = size() / elem_per_block;
87 const unsigned int off = size() % elem_per_block;
88
89 if (off)
90 {
91 blocks_[blk] &= mask_lower(off);
92 }
93}
94
95
96template<unsigned Width>
97inline bool Foam::PackedList<Width>::trim(label minpos)
98{
99 if (empty())
100 {
101 return false; // Trivial case
102 }
103
104 const label orig = size();
105 if (orig < minpos)
106 {
107 minpos = orig; // Don't allow allow accidental growth!
108 }
109
110 for (label blocki = num_blocks(size())-1; blocki >= 0; --blocki)
111 {
112 // Truncate to the block begin
113 size_ = blocki * elem_per_block;
114
115 unsigned int blockval = blocks_[blocki];
116
117 // Some bits were found in the block, increment size again
118 if (blockval)
119 {
120 for (; blockval; ++size_)
121 {
122 blockval >>= Width;
123 }
124 break;
125 }
126 else if (size_ < minpos)
127 {
128 break;
129 }
130 }
131
132 if (size_ < minpos)
133 {
134 size_ = minpos;
135 }
136
137 return (size() != orig);
138}
139
140
141template<unsigned Width>
143{
144 // Self-assignment silently ignored
145 blocks_ = rhs.blocks_;
146 size_ = rhs.size_;
147}
148
149
150// * * * * * * * * * * * * * * * Specializations * * * * * * * * * * * * * * //
151
152namespace Foam
153{
154
155// constexpr noexcept
156template<> inline unsigned int PackedList<1>::repeated_value(unsigned val)
157{
158 return (val ? ~0u : 0u);
159}
160
161template<> inline unsigned int PackedList<1>::readValue(Istream& is)
162{
163 return readBool(is);
164}
165
166template<> inline void PackedList<1>::setPair(Istream& is)
167{
168 set(readLabel(is), true);
169}
170
171} // End namespace Foam
172
173
174// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
175
176template<unsigned Width>
177inline constexpr Foam::PackedList<Width>::PackedList() noexcept
178:
179 blocks_(),
180 size_(0)
181{}
182
183
184template<unsigned Width>
185inline Foam::PackedList<Width>::PackedList(const label numElem)
186:
187 blocks_(num_blocks(numElem), 0u),
188 size_(numElem)
189{}
190
191
192template<unsigned Width>
194(
195 const label numElem,
196 const unsigned int val
197)
198:
199 blocks_(num_blocks(numElem), 0u),
200 size_(numElem)
201{
202 if (val)
203 {
205 }
206}
208
209template<unsigned Width>
212 blocks_(),
213 size_(0)
214{
215 readList(is);
216}
217
219template<unsigned Width>
222 blocks_(list.blocks_),
223 size_(list.size_)
224{}
225
226
227template<unsigned Width>
229:
230 blocks_(std::move(list.blocks_)),
231 size_(list.size_)
232{
233 list.size_ = 0;
234}
236
237template<unsigned Width>
239:
240 blocks_(num_blocks(values.size()), 0u),
241 size_(values.size())
243 const label len = values.size();
244
245 // Could add more intelligent filling (blockwise),
246 // but likely done fairly infrequently
247
248 for (label i = 0; i < len; ++i)
249 {
250 const unsigned int val(values[i]);
251 if (val) set(i, val);
252 }
253}
254
255
256template<unsigned Width>
257template<class Addr>
259(
261)
262:
263 blocks_(num_blocks(values.size()), 0u),
264 size_(values.size())
265{
266 const label len = values.size();
267
268 // Could add more intelligent filling (blockwise),
269 // but likely done fairly infrequently
270
271 for (label i = 0; i < len; ++i)
273 const unsigned int val(values[i]);
274 if (val) set(i, val);
276}
277
278
279template<unsigned Width>
282{
284}
285
287// * * * * * * * * * * * * * * * * References * * * * * * * * * * * * * * * * //
288
289template<unsigned Width>
291(
293 const label index
294)
295:
296 ref_(parent->blocks_[index / elem_per_block]),
297 shift_(Width * (index % elem_per_block))
298{}
299
300
301template<unsigned Width>
303{
304 return ((ref_ >> shift_) & max_value);
306
307
308template<unsigned Width>
309inline bool Foam::PackedList<Width>::reference::set(const unsigned int val)
311 const unsigned int mask = (max_value << shift_);
312 const unsigned int prev = ref_;
313
314 if (val >= max_value)
316 ref_ |= mask; // Overflow is max_value, so fill entirely
317 }
318 else
319 {
320 ref_ &= ~mask;
321 ref_ |= mask & (val << shift_);
322 }
323
324 return (prev != ref_);
325}
326
327
328template<unsigned Width>
330(
331 const reference& other
332)
333{
334 // Accepts self-assignment
335 this->set(other.get());
336}
337
338
339template<unsigned Width>
341(
342 const unsigned int val
343)
344{
345 this->set(val);
347
348
349template<unsigned Width>
351{
352 return this->get();
353}
354
356// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
357
358template<unsigned Width>
359inline void Foam::PackedList<Width>::checkIndex(const label i) const
360{
361 if (!size_)
364 << "attempt to access element " << i << " from zero sized list"
365 << abort(FatalError);
366 }
367 else if (i < 0 || i >= size_)
368 {
370 << "index " << i << " out of range [0," << size_ << ")"
372 }
373}
375
376template<unsigned Width>
377inline Foam::label Foam::PackedList<Width>::size() const noexcept
378{
379 return size_;
381
382
383template<unsigned Width>
385{
386 return !size_;
387}
388
389
390template<unsigned Width>
392{
394}
395
396
397template<unsigned Width>
399(
400 const label numElem
401)
402{
403 this->resize(numElem);
404}
405
407template<unsigned Width>
410 const label newSize,
411 const unsigned int val
412)
414 reserve(newSize);
415
416 const label oldSize = size();
417 size_ = newSize;
418
419 if (oldSize < newSize)
420 {
421 // Fill new elements or newly exposed elements
422 if (val)
423 {
424 // Fill value for complete blocks
425 const unsigned int blockval = repeated_value(val);
426
427 // Fill complete blocks
428 const label oldLen = num_blocks(oldSize);
429 const label newLen = num_blocks(size());
430 for (label blocki = oldLen; blocki < newLen; ++blocki)
431 {
432 blocks_[blocki] = blockval;
433 }
434
435 // Finish previous partial block, preserve existing value
436 {
437 const unsigned int blk = oldSize / elem_per_block;
438 const unsigned int off = oldSize % elem_per_block;
439 if (off)
440 {
441 const unsigned int mask = mask_lower(off);
443 blocks_[blk] &= mask;
444 blocks_[blk] |= ~mask & blockval;
445 }
447
449 }
451 else if (newSize < oldSize)
452 {
453 // The list is now shorter than before, so we zero assign the unused
454 // blocks and any trailing junk. This costs slightly here, but make
455 // things much simpler elsewhere.
457 // Clear complete blocks
458 const label oldLen = num_blocks(oldSize);
459 const label newLen = num_blocks(size());
460 for (label blocki = newLen; blocki < oldLen; ++blocki)
461 {
462 blocks_[blocki] = 0u;
463 }
464
466 }
467}
468
469
470template<unsigned Width>
471inline void Foam::PackedList<Width>::setCapacity(const label numElem)
472{
473 const label nblocks = num_blocks(numElem);
474
475 blocks_.resize(nblocks, 0u);
476
477 if (numElem < size())
478 {
479 size_ = numElem;
481 }
482}
484
485template<unsigned Width>
486inline void Foam::PackedList<Width>::reserve(const label numElem)
487{
488 const label oldLen = blocks_.size();
489 const label newLen = num_blocks(numElem);
490
491 // Allocate more capacity if necessary
492 if (oldLen < newLen)
493 {
495 (
496 // SizeMin=16, allocation doubling
497 max(16, max(newLen, 2*oldLen)),
498 0u
499 );
501}
502
504template<unsigned Width>
506{
507 blocks_ = 0u;
508}
509
510
511template<unsigned Width>
513{
514 reset();
515 size_ = 0;
516}
517
518
519template<unsigned Width>
521{
522 blocks_.clear();
523 size_ = 0;
524}
525
526
527template<unsigned Width>
529{
530 // Any unneeded space allocated?
531 const label nblocks = num_blocks(size());
532 if (nblocks < blocks_.size())
533 {
534 blocks_.resize(nblocks);
535 }
536}
537
538
539template<unsigned Width>
541{
542 return blocks_;
543}
544
545
546template<unsigned Width>
548{
549 return blocks_;
550}
551
552
553template<unsigned Width>
554inline Foam::label Foam::PackedList<Width>::nBlocks() const
555{
556 return num_blocks(size());
557}
558
559
560template<unsigned Width>
561inline const unsigned int* Foam::PackedList<Width>::cdata() const noexcept
562{
563 return blocks_.cdata();
564}
565
566
567template<unsigned Width>
569{
570 return blocks_.data();
571}
572
573
574template<unsigned Width>
576{
577 return blocks_.cdata_bytes();
578}
579
580
581template<unsigned Width>
583{
584 return blocks_.data_bytes();
585}
586
587
588template<unsigned Width>
589inline std::streamsize Foam::PackedList<Width>::size_bytes() const noexcept
590{
591 return num_blocks(size()) * sizeof(block_type);
592}
593
594
595template<unsigned Width>
596inline std::streamsize Foam::PackedList<Width>::byteSize() const noexcept
597{
598 return this->size_bytes();
599}
600
601
602template<unsigned Width>
604{
605 if (this == &rhs)
606 {
607 return; // Self-swap is a no-op
608 }
609
610 blocks_.swap(rhs.blocks_);
611 std::swap(size_, rhs.size_);
612}
613
614
615template<unsigned Width>
617{
618 if (this == &rhs)
619 {
620 return; // Self-assignment is a no-op
621 }
622
624 size_ = rhs.size_;
625 rhs.size_ = 0;
626}
627
628
629template<unsigned Width>
630inline unsigned int Foam::PackedList<Width>::get(const label i) const
631{
632 if (i < 0 || i >= size())
633 {
634 #ifdef FULLDEBUG
635 if (i < 0)
636 {
638 << "Ignoring attempt to get a negative index " << i
639 << " range is [0," << size_ << ")"
640 << endl;
641 }
642 #endif
643
644 return 0u; // Out-of-bounds (lazy): return 0 (false)
645 }
646
647 return reference(const_cast<PackedList<Width>*>(this), i).get();
648}
649
650
651template<unsigned Width>
653(
654 const label i,
655 const unsigned int val
656)
657{
658 if (i < 0)
659 {
660 #ifdef FULLDEBUG
662 << "Ignoring attempt to set a negative index " << i
663 << " range is [0," << size_ << ")"
664 << endl;
665 #endif
666
667 return false; // Out-of-bounds: ignore
668 }
669 else if (i >= size())
670 {
671 if (!val) // Unset out-of-bounds: ignore
672 {
673 return false;
674 }
675
676 resize(i + 1); // Lazy evaluation: adjust size for assign
677 }
678
679 return reference(this, i).set(val);
680}
681
682
683template<unsigned Width>
684inline bool Foam::PackedList<Width>::unset(const label i)
685{
686 if (i < 0 || i >= size())
687 {
688 return false; // Unset out-of-bounds: ignore
689 }
690
691 return reference(this, i).set(0u);
692}
693
694
695template<unsigned Width>
697Foam::PackedList<Width>::append(const unsigned int val)
698{
699 const label idx = size();
700 reserve(idx + 1);
701 ++size_;
702
703 reference(this, idx).set(val);
704 return *this;
705}
706
707
708template<unsigned Width>
710{
711 // Location of last element and simultaneously the new size
712 const label idx = size()-1;
713
714 if (idx < 0)
715 {
717 << "List is empty" << abort(FatalError);
718 }
719
720 const unsigned int old = reference(this, idx).get();
721 resize(idx);
722
723 return old;
724}
725
726
727template<unsigned Width>
728inline void Foam::PackedList<Width>::fill(const unsigned int val)
729{
730 if (empty())
731 {
732 return; // Trivial case
733 }
734
735 const label nblocks = num_blocks(size());
736
737 // Fill value for complete blocks
738 const unsigned int blockval = (val ? repeated_value(val) : 0u);
739
740 for (label blocki=0; blocki < nblocks; ++blocki)
741 {
742 blocks_[blocki] = blockval;
743 }
744
745 if (val)
746 {
748 }
749}
750
751
752// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
753
754template<unsigned Width>
755inline unsigned int Foam::PackedList<Width>::operator[](const label i) const
756{
757 return get(i);
758}
759
760
761template<unsigned Width>
764{
765 #ifdef FULLDEBUG
766 checkIndex(i);
767 #endif
768 return reference(this, i);
769}
770
771
772template<unsigned Width>
774{
775 copyAssign(rhs);
776}
777
778
779template<unsigned Width>
781{
782 transfer(rhs);
783}
784
785
786template<unsigned Width>
787inline void Foam::PackedList<Width>::operator=(const unsigned int val)
788{
789 fill(val);
790}
791
792
793// * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
794
795template<unsigned Width>
796inline bool Foam::operator==
797(
798 const PackedList<Width>& a,
799 const PackedList<Width>& b
800)
801{
802 return a.equal(b);
803}
804
805
806template<unsigned Width>
807inline bool Foam::operator!=
808(
809 const PackedList<Width>& a,
810 const PackedList<Width>& b
811)
812{
813 return !a.equal(b);
814}
815
816
817// ************************************************************************* //
virtual bool resize()
Resize the ODE solver.
Definition: Euler.C:53
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:58
Base for lists with indirect addressing, templated on the list contents type and the addressing type....
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:64
bool readEnd(const char *funcName)
End read of data chunk, ends with ')'.
Definition: Istream.C:129
bool readBegin(const char *funcName)
Begin read of data chunk, starts with '('.
Definition: Istream.C:111
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:77
void transfer(List< T > &list)
Definition: List.C:447
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:116
virtual char fill() const =0
Get padding character.
A reference supporting read/write access to an entry.
Definition: PackedList.H:466
unsigned shift_
The bit shift to access the given sub-portion.
Definition: PackedList.H:476
block_type & ref_
Reference to the block.
Definition: PackedList.H:473
unsigned int get() const
Get value as unsigned, no range-checking.
Definition: PackedListI.H:302
bool set(unsigned int val)
Set value, returning true if changed, no range-checking.
Definition: PackedListI.H:309
A dynamic list of packed unsigned integers, with the number of bits per item specified by the <Width>...
Definition: PackedList.H:129
void copyAssign(const PackedList< Width > &rhs)
Copy assignment.
Definition: PackedListI.H:142
void shrink()
Shrink the allocated space to what is actually used.
Definition: PackedListI.H:528
label size_
Number of entries used.
Definition: PackedList.H:187
static unsigned int readValue(Istream &is)
Read a list entry (allows for specialization)
Definition: PackedListI.H:41
void swap(PackedList< Width > &rhs)
Swap contents with argument.
Definition: PackedListI.H:603
char * data_bytes() noexcept
A pointer to the raw storage, reinterpreted as byte data.
Definition: PackedListI.H:582
void checkIndex(const label i) const
Check index is within valid range [0,size)
Definition: PackedListI.H:359
const unsigned int * cdata() const noexcept
A const pointer to the raw storage.
Definition: PackedListI.H:561
bool equal(const PackedList< Width > &other) const
Test for equality of sizes and the bits set.
Definition: PackedList.C:152
static constexpr block_type mask_lower(unsigned elementOffset)
Masking for all bits below the element offset.
Definition: PackedList.H:170
block_container blocks_
The blocks of raw data.
Definition: PackedList.H:184
bool empty() const noexcept
True if the list is empty (ie, size() is zero).
Definition: PackedListI.H:384
labelList values() const
Return the values as a list of labels.
Definition: PackedList.C:175
void resize_nocopy(const label numElem)
Currently identical to resize. Subject to future change (Oct-2021)
Definition: PackedListI.H:399
autoPtr< PackedList< Width > > clone() const
Clone.
Definition: PackedListI.H:281
void resize(const label numElem, const unsigned int val=0u)
Reset addressable list size, does not shrink the allocated size.
Definition: PackedListI.H:409
void fill(const unsigned int val)
Assign all entries to the given value.
Definition: PackedListI.H:728
static constexpr block_type max_value
Definition: PackedList.H:152
static unsigned int repeated_value(unsigned val)
A fill value for complete blocks.
Definition: PackedListI.H:34
void setCapacity(const label numElem)
Alter the size of the underlying storage.
Definition: PackedListI.H:471
void clear_trailing_bits()
Clear any partial rubbish in the last addressable block.
Definition: PackedListI.H:83
std::streamsize byteSize() const noexcept
Definition: PackedListI.H:596
label nBlocks() const
The number of internal storage blocks.
Definition: PackedListI.H:554
void clearStorage()
Clear the list and delete storage.
Definition: PackedListI.H:520
label capacity() const noexcept
The number of elements that can be stored with reallocating.
Definition: PackedListI.H:391
label size() const noexcept
Number of entries.
Definition: PackedListI.H:377
bool set(const label i, unsigned int val=~0u)
Set value at index i, default value set is the max_value.
Definition: PackedListI.H:653
void reserve(const label numElem)
Definition: PackedListI.H:486
unsigned int get(const label i) const
Get value at index i or 0 for out-of-range.
Definition: PackedListI.H:630
void operator=(const PackedList< Width > &lst)
Copy assignment.
Definition: PackedListI.H:773
constexpr PackedList() noexcept
Default construct, zero-sized and no allocation.
Definition: PackedListI.H:177
static constexpr unsigned elem_per_block
The number of elements stored per data block.
Definition: PackedList.H:147
unsigned int * data() noexcept
A pointer to the raw storage.
Definition: PackedListI.H:568
void transfer(PackedList< Width > &rhs)
Definition: PackedListI.H:616
const char * cdata_bytes() const noexcept
A const pointer to the raw storage, reinterpreted as byte data.
Definition: PackedListI.H:575
const List< unsigned int > & storage() const
Return the underlying storage blocks.
Definition: PackedListI.H:547
static constexpr label num_blocks(label numElem) noexcept
Definition: PackedList.H:163
void setPair(Istream &is)
Read an index/value pair and set accordingly.
Definition: PackedListI.H:58
unsigned int block_type
The storage block type for bit elements.
Definition: PackedList.H:136
void clear()
Clear the list, i.e. set addressable size to zero.
Definition: PackedListI.H:512
void reset()
Clear all bits but do not adjust the addressable size.
Definition: PackedListI.H:505
std::streamsize size_bytes() const noexcept
Definition: PackedListI.H:589
unsigned int operator[](const label i) const
Identical to get() - get value at index.
Definition: PackedListI.H:755
unsigned int remove()
Remove and return the last element.
Definition: PackedListI.H:709
void swap(UList< T > &list)
Swap content with another UList of the same type in constant time.
Definition: UListI.H:434
char * data_bytes() noexcept
Return pointer to the underlying array serving as data storage,.
Definition: UListI.H:251
const T * cdata() const noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:230
T * data() noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:237
const char * cdata_bytes() const noexcept
Return pointer to the underlying array serving as data storage,.
Definition: UListI.H:244
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
void trim()
Inplace trim leading and trailing whitespace.
Definition: exprString.C:96
Computes a field whose values are offset to a reference value obtained by from a Function1.
Definition: reference.H:211
static const triad unset
Definition: triad.H:97
bool set() const
Are all the vector set.
Definition: triadI.H:76
bool append() const noexcept
True if output format uses an append mode.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
#define WarningInFunction
Report a warning using Foam::Warning.
#define FUNCTION_NAME
Namespace for OpenFOAM.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:66
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
errorManip< error > abort(error &err)
Definition: errorManip.H:144
IOerror FatalIOError
const direction noexcept
Definition: Scalar.H:223
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
error FatalError
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
bool readBool(Istream &is)
Read bool from stream using Foam::Switch(Istream&)
Definition: bool.C:69
volScalarField & b
Definition: createFields.H:27