PackedList.C
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) 2018-2019 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
28#include "PackedList.H"
29#include "labelRange.H"
30
31// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
32
33template<unsigned Width>
35(
36 const PackedList<Width>& list,
37 const labelUList& addr
38)
39:
40 PackedList<Width>(addr.size())
41{
42 const label len = addr.size();
43
44 for (label i = 0; i < len; ++i)
45 {
46 set(i, list.get(addr[i]));
47 }
48}
49
50
51template<unsigned Width>
52template<class Addr>
54(
55 const PackedList<Width>& list,
57)
58:
59 PackedList<Width>(addr.size())
60{
61 const label len = addr.size();
62
63 for (label i = 0; i < len; ++i)
64 {
65 set(i, list.get(addr[i]));
66 }
67}
68
69
70template<unsigned Width>
72(
73 const PackedList<Width>& list,
74 const labelRange& range
75)
76:
77 PackedList<Width>(range.size())
78{
79 label pos = range.start();
80 const label len = range.size();
81
82 for (label i = 0; i < len; ++i)
83 {
84 set(i, list.get(pos));
85 ++pos;
86 }
87}
88
89
90// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
91
92template<unsigned Width>
94{
95 // Trivial cases
96 if (empty())
97 {
98 return false;
99 }
100 else if (size() == 1)
101 {
102 return true;
103 }
104
105
106 // The value of the first element for testing
107 const unsigned int val = get(0);
108
109 const label nblocks = num_blocks(size());
110
111 bool identical = true;
112
113 if (!val)
114 {
115 // Zero value: can just check block content directly
116
117 for (label blocki = 0; identical && blocki < nblocks; ++blocki)
118 {
119 identical = !blocks_[blocki];
120 }
121
122 return identical;
123 }
124 else if (nblocks > 1)
125 {
126 // Fill value for complete blocks
127 const unsigned int blockval = repeated_value(val);
128
129 // Check each complete block (nblocks-1)
130 for (label blocki = 0; identical && blocki < (nblocks-1); ++blocki)
131 {
132 identical = (blocks_[blocki] == blockval);
133 }
134 }
135
136 // Partial block: check manually
137 for
138 (
139 label elemi = elem_per_block*(nblocks-1);
140 identical && elemi < size();
141 ++elemi
142 )
143 {
144 identical = (val == get(elemi));
145 }
146
147 return identical;
148}
149
150
151template<unsigned Width>
153{
154 if (size() != other.size())
155 {
156 return false;
157 }
158
159 const label nblocks = num_blocks(size());
160 const auto& rhs = other.blocks_;
161
162 for (label blocki = 0; blocki < nblocks; ++blocki)
163 {
164 if (blocks_[blocki] != rhs[blocki])
165 {
166 return false;
167 }
168 }
169
170 return true;
171}
172
173
174template<unsigned Width>
176{
177 return this->unpack<label>();
178}
179
180
181template<unsigned Width>
182template<class IntType>
185{
186 static_assert
187 (
188 std::is_integral<IntType>::value,
189 "Integral required for output."
190 );
191 static_assert
192 (
193 std::numeric_limits<IntType>::digits >= Width,
194 "Width of IntType is too small to hold result"
195 );
196
197 if (empty())
198 {
199 return List<IntType>(0);
200 }
201 else if (uniform())
202 {
203 return List<IntType>(size(), static_cast<IntType>(get(0)));
204 }
205
206 List<IntType> output(size());
207 label outi = 0;
208
209 // Process n-1 complete blocks
210 const label nblocks = num_blocks(size());
211
212 for (label blocki=0; blocki < nblocks-1; ++blocki)
213 {
214 unsigned int blockval = blocks_[blocki];
215
216 for (unsigned nget = elem_per_block; nget; --nget, ++outi)
217 {
218 output[outi] = IntType(blockval & max_value);
219 blockval >>= Width;
220 }
221 }
222
223 // Any partial blocks
224 for (/*nil*/; outi < size(); ++outi)
225 {
226 output[outi] = get(outi);
227 }
228
229 return output;
230}
231
232
233template<unsigned Width>
234template<class IntType>
237{
238 static_assert
239 (
240 std::is_integral<IntType>::value,
241 "Integral required for unpack output."
242 );
243 static_assert
244 (
245 std::numeric_limits<IntType>::digits >= Width,
246 "Width of IntType is too small to hold unpack output."
247 );
248
249
250 // Could be more efficient but messier with block-wise access.
251 // - automatically handles any invalid positions
252
253 auto pos = range.start();
255 List<IntType> output(range.size());
256
257 for (IntType& out : output)
259 out = IntType(get(pos));
260 ++pos;
261 }
262
263 return output;
264}
266
267template<unsigned Width>
268template<class IntType>
271{
272 static_assert
273 (
274 std::is_integral<IntType>::value,
275 "Integral required for unpack output."
276 );
277 static_assert
278 (
279 std::numeric_limits<IntType>::digits >= Width,
280 "Width of IntType is too small to hold unpack output."
281 );
282
283
284 label pos = 0;
285
286 List<IntType> output(locations.size());
287
288 for (IntType& out : output)
289 {
290 out = IntType(get(locations[pos]));
291 ++pos;
292 }
293
294 return output;
296
297
298// ************************************************************************* //
scalar range
Base for lists with indirect addressing, templated on the list contents type and the addressing type....
label size() const noexcept
The number of elements in the list.
A dynamic list of packed unsigned integers, with the number of bits per item specified by the <Width>...
Definition: PackedList.H:129
bool equal(const PackedList< Width > &other) const
Test for equality of sizes and the bits set.
Definition: PackedList.C:152
block_container blocks_
The blocks of raw data.
Definition: PackedList.H:184
labelList values() const
Return the values as a list of labels.
Definition: PackedList.C:175
List< IntType > unpack() const
Return the values as a list of integral type.
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
bool uniform() const
True if all entries have identical values, and list is non-empty.
Definition: PackedList.C:93
unsigned int get(const label i) const
Get value at index i or 0 for out-of-range.
Definition: PackedListI.H:630
constexpr PackedList() noexcept
Default construct, zero-sized and no allocation.
Definition: PackedListI.H:177
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:58
dimensionedScalar pos(const dimensionedScalar &ds)
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:66