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 -------------------------------------------------------------------------------
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,
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 
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 
151 template<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 
174 template<unsigned Width>
176 {
177  return this->unpack<label>();
178 }
179 
180 
181 template<unsigned Width>
182 template<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 
233 template<unsigned Width>
234 template<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();
254 
255  List<IntType> output(range.size());
256 
257  for (IntType& out : output)
258  {
259  out = IntType(get(pos));
260  ++pos;
261  }
262 
263  return output;
264 }
265 
266 
267 template<unsigned Width>
268 template<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;
295 }
296 
297 
298 // ************************************************************************* //
Foam::BitOps::set
void set(List< bool > &bools, const labelRange &range)
Set the specified range 'on' in a boolList.
Definition: BitOps.C:37
PackedList.H
Foam::output
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:66
Foam::PackedList::PackedList
constexpr PackedList() noexcept
Default construct, zero-sized and no allocation.
Definition: PackedListI.H:177
Foam::PackedList::get
unsigned int get(const label i) const
Get value at index i or 0 for out-of-range.
Definition: PackedListI.H:630
Foam::PackedList::uniform
bool uniform() const
True if all entries have identical values, and list is non-empty.
Definition: PackedList.C:93
Foam::uniform
Definition: uniform.H:50
Foam::PackedList::blocks_
block_container blocks_
The blocks of raw data.
Definition: PackedList.H:184
Foam::labelRange
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:55
Foam::IndirectListBase::size
label size() const noexcept
The number of elements in the list.
Definition: IndirectListBase.H:125
Foam::PackedList::equal
bool equal(const PackedList< Width > &other) const
Test for equality of sizes and the bits set.
Definition: PackedList.C:152
Foam::PackedList::unpack
List< IntType > unpack() const
Return the values as a list of integral type.
range
scalar range
Definition: LISASMDCalcMethod1.H:12
labelRange.H
Foam::List< label >
Foam::PackedList
A dynamic list of packed unsigned integers, with the number of bits per item specified by the <Width>...
Definition: PackedList.H:108
Foam::PackedList::size
label size() const noexcept
Number of entries.
Definition: PackedListI.H:377
Foam::UList< label >
Foam::PtrListOps::get
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
Foam::IndirectListBase
Base for lists with indirect addressing, templated on the list contents type and the addressing type....
Definition: IndirectListBase.H:56
Foam::PackedList::values
labelList values() const
Return the values as a list of labels.
Definition: PackedList.C:175
Foam::UList::size
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:177