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-2023 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
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 
33 template<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 
51 template<unsigned Width>
52 template<class Addr>
54 (
55  const PackedList<Width>& list,
56  const IndirectListBase<label, Addr>& addr
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 
70 template<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 
92 template<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  // The value of the first element for testing
106  const unsigned int val = get(0);
107 
108  bool identical = true;
109 
110  if (!val)
111  {
112  // No bits set: just check there are no non-zero blocks
113  // - like bitSet::none()
114  identical = (-1 == first_block());
115  }
116  else if (val == PackedList<Width>::max_value)
117  {
118  // All bits set: just check there are no zero blocks
119  // - like bitSet::all()
120  identical = (-1 == first_not_block());
121  }
122  else
123  {
124  const label nblocks = num_blocks(size());
125 
126  if (nblocks > 1)
127  {
128  // Fill value for complete blocks
129  const unsigned int blockval = repeated_value(val);
130 
131  // Check each complete block (nblocks-1)
132  for (label blocki = 0; identical && blocki < (nblocks-1); ++blocki)
133  {
134  identical = (blocks_[blocki] == blockval);
135  }
136  }
137 
138  // Partial block: check manually
139  for
140  (
141  label elemi = elem_per_block*(nblocks-1);
142  identical && elemi < size();
143  ++elemi
144  )
145  {
146  identical = (val == get(elemi));
147  }
148  }
149 
150  return identical;
151 }
152 
153 
154 template<unsigned Width>
155 bool Foam::PackedList<Width>::equal(const PackedList<Width>& other) const
156 {
157  if (size() != other.size())
158  {
159  return false;
160  }
161 
162  const label nblocks = num_blocks(size());
163  const auto& rhs = other.blocks_;
164 
165  for (label blocki = 0; blocki < nblocks; ++blocki)
166  {
167  if (blocks_[blocki] != rhs[blocki])
168  {
169  return false;
170  }
171  }
172 
173  return true;
174 }
175 
176 
177 template<unsigned Width>
179 {
180  return this->unpack<label>();
181 }
182 
183 
184 template<unsigned Width>
185 template<class IntType>
188 {
189  static_assert
190  (
191  std::is_integral<IntType>::value,
192  "Integral required for output."
193  );
194  static_assert
195  (
196  std::numeric_limits<IntType>::digits >= Width,
197  "Width of IntType is too small to hold result"
198  );
199 
200  List<IntType> output(size());
201 
202  if (empty())
203  {
204  return output;
205  }
206  else if (uniform())
207  {
208  output = static_cast<IntType>(get(0));
209  return output;
210  }
211 
212  // NON-UNIFORM and len > 0
213 
214  label outi = 0;
215 
216  // Process n-1 complete blocks
217  const label nblocks = num_blocks(size());
218 
219  for (label blocki=0; blocki < nblocks-1; ++blocki)
220  {
221  unsigned int blockval = blocks_[blocki];
222 
223  for (unsigned nget = elem_per_block; nget; --nget, ++outi)
224  {
225  output[outi] = IntType(blockval & PackedList<Width>::max_value);
226  blockval >>= Width;
227  }
228  }
229 
230  // Any partial blocks
231  for (/*nil*/; outi < size(); ++outi)
232  {
233  output[outi] = get(outi);
234  }
235 
236  return output;
237 }
238 
239 
240 template<unsigned Width>
241 template<class IntType>
244 {
245  static_assert
246  (
247  std::is_integral<IntType>::value,
248  "Integral required for unpack output."
249  );
250  static_assert
251  (
252  std::numeric_limits<IntType>::digits >= Width,
253  "Width of IntType is too small to hold unpack output."
254  );
255 
256 
257  // Could be more efficient but messier with block-wise access.
258  // - automatically handles any invalid positions
259 
260  auto pos = range.start();
261 
262  List<IntType> output(range.size());
263 
264  for (IntType& out : output)
265  {
266  out = IntType(get(pos));
267  ++pos;
268  }
269 
270  return output;
271 }
272 
273 
274 template<unsigned Width>
275 template<class IntType>
277 Foam::PackedList<Width>::unpack(const labelUList& locations) const
278 {
279  static_assert
280  (
281  std::is_integral<IntType>::value,
282  "Integral required for unpack output."
283  );
284  static_assert
285  (
286  std::numeric_limits<IntType>::digits >= Width,
287  "Width of IntType is too small to hold unpack output."
288  );
289 
290 
291  label pos = 0;
292 
293  List<IntType> output(locations.size());
294 
295  for (IntType& out : output)
296  {
297  out = IntType(get(locations[pos]));
298  ++pos;
299  }
300 
301  return output;
302 }
303 
304 
305 // ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:52
List< IntType > unpack() const
Return the values as a list of integral type.
bool uniform() const
True if all entries have identical values (and list is non-empty)
Definition: PackedList.C:86
scalar range
dimensionedScalar pos(const dimensionedScalar &ds)
constexpr PackedList() noexcept
Default construct, zero-sized and no allocation.
Definition: PackedListI.H:237
A dynamic list of packed unsigned integers, with the number of bits per item specified by the <Width>...
Definition: PackedList.H:104
labelList values() const
Return the values as a list of labels.
Definition: PackedList.C:171
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:44
bool equal(const PackedList< Width > &other) const
Test for equality of sizes and the bits set.
Definition: PackedList.C:148
unsigned int get(const label i) const
Get value at index i or 0 for out-of-range.
Definition: PackedListI.H:683