bitSet.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-2026 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 "bitSet.H"
29 #include "IOstreams.H"
30 #include "UPstream.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37  defineTypeNameAndDebug(bitSet, 0);
38 
39  // TBD: add IO support of compound type?
40  // defineNamedCompoundTypeName(bitSet, List<1>);
41  // addNamedCompoundToRunTimeSelectionTable(bitSet, bitSet, List<1>);
42 }
43 
44 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
45 
47 {
48  if (&other == this)
49  {
50  // Self '-=' : clears all bits
51  if (debug & 2)
52  {
54  << "Perform -= on self: clears all bits" << nl;
55  }
56 
57  reset();
58  return *this;
59  }
60  else if (none() || other.none())
61  {
62  // no-op: nothing can change
63  return *this;
64  }
65 
66 
67  label nblocks(0);
68 
69  // Determine the overlap
70  {
71  const label thisExtent = (this->find_last()+1);
72  const label thatExtent = (other.find_last()+1);
73 
74  // min overlap
75  if (label common = std::min(thisExtent, thatExtent); common > 0)
76  {
77  nblocks = num_blocks(common);
78  }
79  }
80 
81  // The operation (on overlapping blocks)
82  {
83  const auto& rhs = other.blocks_;
84 
85  for (label blocki = 0; blocki < nblocks; ++blocki)
86  {
87  blocks_[blocki] &= ~rhs[blocki];
88  }
89  }
90 
91  return *this;
92 }
93 
94 
95 Foam::bitSet& Foam::bitSet::andEq(const bitSet& other)
96 {
97  if (FOAM_UNLIKELY(&other == this))
98  {
99  // Self '&=' : no-op
100 
101  if (debug & 2)
102  {
104  << "Perform &= on self: ignore" << nl;
105  }
106 
107  return *this;
108  }
109  else if (none())
110  {
111  // no-op: nothing is set - no intersection possible
112  return *this;
113  }
114  else if (other.none())
115  {
116  // no-op: other has nothing set - no intersection possible
117  reset();
118  return *this;
119  }
120 
121 
122  label nblocks(0);
123 
124  // Determine the overlap
125  {
126  const label thisExtent = (this->find_last()+1);
127  const label thatExtent = (other.find_last()+1);
128 
129  // min overlap
130  if (label common = std::min(thisExtent, thatExtent); common > 0)
131  {
132  nblocks = num_blocks(common);
133  }
134 
135  if (thatExtent < thisExtent)
136  {
137  // Clear bits (and blocks) that do not overlap at all
138  const auto origSize = size();
139  resize(thatExtent);
140  resize(origSize);
141  }
142  }
143 
144  // The operation (on overlapping blocks)
145  {
146  const auto& rhs = other.blocks_;
147 
148  for (label blocki = 0; blocki < nblocks; ++blocki)
149  {
150  blocks_[blocki] &= rhs[blocki];
151  }
152  }
153 
154  return *this;
155 }
156 
157 
158 Foam::bitSet& Foam::bitSet::orEq(const bitSet& other)
159 {
160  if (&other == this)
161  {
162  // Self '|=' : no-op
163 
164  if (debug & 2)
165  {
167  << "Perform |= on self: ignore" << nl;
168  }
169 
170  return *this;
171  }
172  else if (other.none())
173  {
174  // no-op: nothing can change
175  return *this;
176  }
177 
178 
179  label nblocks(0);
180 
181  // Determine the overlap
182  {
183  const label thisExtent = (this->find_last()+1);
184  const label thatExtent = (other.find_last()+1);
185 
186  // max overlap
187  if (label common = std::max(thisExtent, thatExtent); common > 0)
188  {
189  nblocks = num_blocks(common);
190  }
191 
192  if (size() < thatExtent)
193  {
194  // Accommodate any extra bits from 'other'
195  resize(thatExtent);
196  }
197  }
198 
199  // The operation (on overlapping blocks)
200  {
201  const auto& rhs = other.blocks_;
202 
203  for (label blocki = 0; blocki < nblocks; ++blocki)
204  {
205  blocks_[blocki] |= rhs[blocki];
206  }
207  }
208 
209  return *this;
210 }
211 
212 
213 Foam::bitSet& Foam::bitSet::xorEq(const bitSet& other)
214 {
215  if (&other == this)
216  {
217  // Self '^=' : clears all bits
218 
219  if (debug & 2)
220  {
222  << "Perform ^= on self: clears all bits" << nl;
223  }
224 
225  reset();
226  return *this;
227  }
228  else if (other.none())
229  {
230  // no-op: nothing can change
231  return *this;
232  }
233 
234 
235  label nblocks(0);
236 
237  // Determine the overlap
238  {
239  const label thisExtent = (this->find_last()+1);
240  const label thatExtent = (other.find_last()+1);
241 
242  // max overlap
243  if (label common = std::max(thisExtent, thatExtent); common > 0)
244  {
245  nblocks = num_blocks(common);
246  }
247 
248  if (size() < thatExtent)
249  {
250  // Accommodate any extra bits from 'other'
251  resize(thatExtent);
252  }
253  }
254 
255  // The operation (on overlapping blocks)
256  {
257  const auto& rhs = other.blocks_;
258 
259  for (label blocki = 0; blocki < nblocks; ++blocki)
260  {
261  blocks_[blocki] ^= rhs[blocki];
262  }
263  }
265  return *this;
266 }
267 
268 
269 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
270 
272 :
273  PackedList<1>()
274 {
275  is >> *this;
276 }
277 
278 
279 Foam::bitSet::bitSet(const bitSet& bitset, const labelUList& addr)
280 :
281  bitSet(addr.size())
282 {
283  const label len = addr.size();
284 
285  for (label i = 0; i < len; ++i)
286  {
287  set(i, bitset.get(addr[i]));
288  }
289 }
290 
291 
292 Foam::bitSet::bitSet(const bitSet& bitset, const labelRange& range)
293 :
294  bitSet(range.size())
295 {
296  label pos = range.start();
297  const label len = range.size();
298 
299  for (label i = 0; i < len; ++i)
300  {
301  set(i, bitset.get(pos));
302  ++pos;
303  }
304 }
305 
306 
307 Foam::bitSet::bitSet(const label n, const labelRange& range)
308 :
309  bitSet(n)
310 {
311  this->set(range);
312 }
313 
314 
316 {
317  this->set(range);
318 }
319 
320 
321 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
322 
324 {
325  fill(false);
326  resize(bools.size());
327 
328  unsigned bitIdx = 0u;
329  auto* packed = blocks_.data();
330 
331  // Set according to indices that are true
332  for (const auto b : bools)
333  {
334  if (b)
335  {
336  *packed |= (1u << bitIdx);
337  }
338 
339  if (++bitIdx >= PackedList<1>::elem_per_block)
340  {
341  bitIdx = 0u;
342  ++packed;
343  }
344  }
345 }
346 
347 
348 bool Foam::bitSet::intersects(const bitSet& other) const
349 {
350  if (size() && other.size())
351  {
352  const label nblocks = num_blocks(std::min(size(), other.size()));
353  const auto& rhs = other.blocks_;
354 
355  for (label blocki = 0; blocki < nblocks; ++blocki)
356  {
357  if (bool(blocks_[blocki] & rhs[blocki]))
358  {
359  return true;
360  }
361  }
362  }
363 
364  return false;
365 }
366 
367 
368 void Foam::bitSet::set(const labelRange& range)
369 {
370  labelRange slice(range);
371  slice.adjust(); // No negative start, size adjusted accordingly
372 
373  // Range is invalid (zero-sized or entirely negative) - noop
374  if (slice.empty())
375  {
376  return;
377  }
378 
379  // Range finishes at or beyond the right side.
380  // - zero fill any gaps that we might create.
381  // - flood-fill the reset, which now corresponds to the full range.
382  if (slice.end_value() >= size())
383  {
384  reserve(slice.end_value());
385  resize(slice.begin_value(), false);
386  resize(slice.end_value(), true);
387  return;
388  }
389 
390  // The more difficult case - everything in between.
391  // 1. sequence may begin/end in the same block
392  // 2. Cover more than one block
393  // a. with partial coverage in the first block
394  // b. with partial coverage in the end block
395 
396  // The begin block/offset
397  unsigned int bblock = slice.begin_value() / elem_per_block;
398  unsigned int bmask = slice.begin_value() % elem_per_block;
399 
400  // The end block/offset
401  unsigned int eblock = slice.end_value() / elem_per_block;
402  unsigned int emask = slice.end_value() % elem_per_block;
403 
404  // Transform offsets to lower bit masks
405  if (bmask) bmask = mask_lower(bmask);
406  if (emask) emask = mask_lower(emask);
407 
408  if (bblock == eblock)
409  {
410  // Same block - flll between the begin/end bits.
411  // Example:
412  // bmask = 0000000000001111 (lower bits)
413  // emask = 0000111111111111 (lower bits)
414  // -> set 0000111111110000 (xor)
415 
416  blocks_[bblock] |= (emask^bmask);
417  }
418  else
419  {
420  if (bmask)
421  {
422  // The first (partial) block
423  // - set everything above the bmask.
424  blocks_[bblock] |= (~bmask);
425  ++bblock;
426  }
427 
428  // Fill these blocks
429  for (unsigned blocki = bblock; blocki < eblock; ++blocki)
430  {
431  blocks_[blocki] = (~0u);
432  }
433 
434  if (emask)
435  {
436  // The last (partial) block.
437  // - set everything below emask.
438  blocks_[eblock] |= (emask);
439  }
440  }
441 }
442 
443 
444 void Foam::bitSet::unset(const labelRange& range)
445 {
446  // Require intersection with the current bitset
447  const labelRange slice = range.subset0(size());
448 
449  // Range does not intersect (invalid, empty, bitset is empty)
450  if (slice.empty())
451  {
452  return;
453  }
454 
455  // Range finishes at or beyond the right side.
456  if (slice.end_value() >= size())
457  {
458  // The original size
459  const label orig = size();
460 
461  resize(slice.begin_value(), false);
462  resize(orig, false);
463  return;
464  }
465 
466 
467  // The more difficult case - everything in between.
468  // 1. sequence may begin/end in the same block
469  // 2. Cover more than one block
470  // a. with partial coverage in the first block
471  // b. with partial coverage in the end block
472 
473  // The begin block/offset
474  unsigned int bblock = slice.begin_value() / elem_per_block;
475  unsigned int bmask = slice.begin_value() % elem_per_block;
476 
477  // The end block/offset
478  unsigned int eblock = slice.end_value() / elem_per_block;
479  unsigned int emask = slice.end_value() % elem_per_block;
480 
481  // Transform offsets to lower bit masks
482  if (bmask) bmask = mask_lower(bmask);
483  if (emask) emask = mask_lower(emask);
484 
485  if (bblock == eblock)
486  {
487  // Same block - flll between the begin/end bits.
488  // Example:
489  // bmask = 0000000000001111 (lower bits)
490  // emask = 0000111111111111 (lower bits)
491  // -> set 0000111111110000 (xor)
492  // -> ~ 1111000000001111
493 
494  blocks_[bblock] &= (~(emask^bmask));
495  }
496  else
497  {
498  if (bmask)
499  {
500  // The first (partial) block
501  // - only retain things below bmask.
502  blocks_[bblock] &= (bmask);
503  ++bblock;
504  }
505 
506  // Clear these blocks
507  for (unsigned blocki = bblock; blocki < eblock; ++blocki)
508  {
509  blocks_[blocki] = (0u);
510  }
511 
512  if (emask)
513  {
514  // The last (partial) block.
515  // - only retain things above bmask.
516  blocks_[eblock] &= (~emask);
517  }
518  }
519 }
520 
521 
523 {
524  // Number of used (set) entries
525  const label total = any() ? count() : 0;
526 
527  if (!total)
528  {
529  return labelList();
530  }
531 
532  labelList output(total);
533  label nItem = 0;
534 
535  // Process block-wise, detecting any '1' bits
536 
537  const label nblocks = num_blocks(size());
538  for (label blocki = 0; blocki < nblocks; ++blocki)
539  {
540  unsigned int blockval = blocks_[blocki];
541 
542  if (blockval)
543  {
544  for (label pos = (blocki * elem_per_block); blockval; ++pos)
545  {
546  if (blockval & 1u)
547  {
548  output[nItem] = pos;
549  ++nItem;
550  }
551  blockval >>= 1u;
552  }
553  if (nItem == total) break; // Terminate early
554  }
555  }
556 
557  return output;
558 }
559 
560 
562 {
563  List<bool> output(size(), false);
564 
565  // Process block-wise, detecting any '1' bits
566 
567  const label nblocks = num_blocks(size());
568  for (label blocki = 0; blocki < nblocks; ++blocki)
569  {
570  label pos = (blocki * elem_per_block);
571 
572  for
573  (
574  unsigned int blockval = blocks_[blocki];
575  blockval;
576  blockval >>= 1u
577  )
578  {
579  if (blockval & 1u)
580  {
581  output[pos] = true;
582  }
583  ++pos;
584  }
585  }
586 
587  return output;
588 }
589 
590 
591 // * * * * * * * * * * * * * * Parallel Functions * * * * * * * * * * * * * //
592 
593 // Special purpose broadcast for bitSet which is more efficient than
594 // either a regular broadcast (with serialization) or the usual
595 // broadcast for lists.
596 //
597 // The initial broadcast sends the extent (last bit on) and the length.
598 // The receive clears out its bits and resizes (ie, all zeros and the proper
599 // length).
600 // The final broadcast can be skipped (if there is no non-zero content),
601 // or simply minimized the amount of data broadcast.
602 
603 void Foam::bitSet::broadcast(int communicator, int root)
604 {
605  if (communicator < 0)
606  {
607  communicator = UPstream::worldComm;
608  }
609 
610  if (!UPstream::is_parallel(communicator))
611  {
612  return;
613  }
614 
615  // The number of data blocks for the operation
616  label nblocks(0);
617 
618  // Determine the extent/sizing
619  {
620  int64_t sizing[2] = { 0, 0 };
621 
622  if (root == UPstream::myProcNo(communicator))
623  {
624  // Sender: extent of content and size
625  sizing[0] = static_cast<int64_t>(find_last()+1);
626  sizing[1] = static_cast<int64_t>(size());
627 
628  UPstream::broadcast(sizing, 2, communicator, root);
629  }
630  else
631  {
632  // Receiver: use a clean bitset with the updated size
633  UPstream::broadcast(sizing, 2, communicator, root);
634 
635  clear(); // Clear old contents
636  resize(sizing[1]);
637  }
638 
639  nblocks = num_blocks(sizing[0]);
640  }
641 
642  if (nblocks > 0)
643  {
644  UPstream::broadcast(this->data(), nblocks, communicator, root);
645  }
646 }
647 
648 
649 void Foam::bitSet::reduceAnd(int communicator, bool syncSizes)
650 {
651  if (communicator < 0)
652  {
653  communicator = UPstream::worldComm;
654  }
655 
656  if (!UPstream::is_parallel(communicator))
657  {
658  return;
659  }
660 
661  // The number of data blocks for the operation
662  label nblocks(0);
663 
664  // Operation is an intersection.
665  // - can restrict to a smaller region than the original size
666  if (syncSizes)
667  {
668  int64_t common(find_last()+1); // Size to include last bit
669 
670  UPstream::mpiAllReduce_min(&common, 1, communicator);
671 
672  nblocks = num_blocks(common);
673 
674  if (common > 0)
675  {
676  // Clear bits (and blocks) that do not overlap at all
677  const auto origSize = size();
678  resize(common);
679  resize(origSize);
680  }
681  else
682  {
683  // No intersections
684  reset();
685  }
686  }
687  else
688  {
689  nblocks = this->num_blocks();
690  }
691 
692  if (nblocks > 0)
693  {
694  UPstream::mpiAllReduce<UPstream::opCodes::op_bit_and>
695  (
696  this->data(),
697  nblocks,
698  communicator
699  );
700  }
701 }
702 
703 
704 void Foam::bitSet::reduceOr(int communicator, bool syncSizes)
705 {
706  if (communicator < 0)
707  {
708  communicator = UPstream::worldComm;
709  }
710 
711  if (!UPstream::is_parallel(communicator))
712  {
713  return;
714  }
715 
716  // The number of data blocks needed for the operation
717  label nblocks(0);
718 
719  // Operation can increase the addressed size
720  if (syncSizes)
721  {
722  // Operational sizes
723  int64_t sizing[2] =
724  {
725  static_cast<int64_t>(find_last()+1), // Size to include last bit
726  static_cast<int64_t>(size()) // The overall size
727  };
728 
729  UPstream::mpiAllReduce_max(sizing, 2, communicator);
730 
731  nblocks = num_blocks(sizing[0]);
732 
733  // Extend local size to the max size encountered
734  // This is greedy, but produces consistent sizing
735  if (size() < sizing[1])
736  {
737  resize(sizing[1]);
738  }
739 
740  // Alternative:
741  // Extend local size to include any 'on' bits.
742  // The resulting bitsets will not have identical sizes on all ranks.
743  // if (size() < sizing[0])
744  // {
745  // resize(sizing[0]);
746  // }
747  }
748  else
749  {
750  nblocks = this->num_blocks();
751  }
752 
753  if (nblocks > 0)
754  {
755  UPstream::mpiAllReduce<UPstream::opCodes::op_bit_or>
756  (
757  this->data(),
758  nblocks,
759  communicator
760  );
761  }
762 }
763 
764 
765 Foam::bitSet Foam::bitSet::gatherValues(bool localValue, int communicator)
766 {
767  if (communicator < 0)
768  {
769  communicator = UPstream::worldComm;
770  }
771 
772  bitSet allValues;
773 
774  if (!UPstream::is_parallel(communicator))
775  {
776  // non-parallel: return own value
777  // TBD: only when UPstream::is_rank(communicator) as well?
778  allValues.resize(1);
779  allValues.set(0, localValue);
780  }
781  else
782  {
783  List<bool> bools;
784  if (UPstream::master(communicator))
785  {
786  bools.resize(UPstream::nProcs(communicator), false);
787  }
788 
790  (
791  &localValue, // Send
792  bools.data(), // Recv
793  1, // Num send/recv data per rank
794  communicator
795  );
796 
797  // Transcribe to bitSet (on master)
798  allValues.assign(bools);
799  }
800 
801  return allValues;
802 }
804 
805 // Note that for allGather()
806 // - MPI_Gather of individual bool values and broadcast the packed result
807 // - this avoids bit_or on 32bit values everywhere, since we know a priori
808 // that each rank only contributes 1bit of info
809 
810 Foam::bitSet Foam::bitSet::allGather(bool localValue, int communicator)
811 {
812  if (communicator < 0)
813  {
814  communicator = UPstream::worldComm;
815  }
816 
817  bitSet allValues(bitSet::gatherValues(localValue, communicator));
818 
819  if (UPstream::is_parallel(communicator))
820  {
821  // Identical size on all ranks
822  allValues.resize(UPstream::nProcs(communicator));
823 
825  (
826  allValues.data(),
827  allValues.num_blocks(),
828  communicator
829  // root = 0
830  );
831  }
832 
833  return allValues;
834 }
835 
836 
837 // ************************************************************************* //
void reduceOr(int communicator=-1, bool syncSizes=true)
Inplace bit_or parallel reduction.
Definition: bitSet.C:697
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:119
bitSet & orEq(const bitSet &other)
The set logical OR.
Definition: bitSet.C:151
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:502
bool any(const UList< bool > &bools)
True if any entries are &#39;true&#39;.
Definition: BitOps.H:90
bool none(const UList< bool > &bools)
True if no entries are &#39;true&#39;.
Definition: BitOps.H:97
patchWriters resize(patchIds.size())
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:153
label find_last() const
Locate the last bit set.
Definition: bitSetI.H:321
static bitSet gatherValues(bool localValue, int communicator=-1)
Gather individual values into bitSet locations.
Definition: bitSet.C:758
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:63
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
T * data() noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:267
List< bool > values() const
Return the bitset values as a boolList.
Definition: bitSet.C:554
static int myProcNo(label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
Definition: UPstream.H:1799
void broadcast(int communicator=-1, int root=0)
Broadcast the contents.
Definition: bitSet.C:596
bitSet & minusEq(const bitSet &other)
The set difference.
Definition: bitSet.C:39
static void mpiAllReduce_max(T values[], int count, const int communicator=UPstream::worldComm)
MPI Allreduce max.
Definition: UPstream.H:2434
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:1094
static void mpiAllReduce_min(T values[], int count, const int communicator=UPstream::worldComm)
MPI Allreduce min.
Definition: UPstream.H:2433
bitSet & xorEq(const bitSet &other)
The set logical XOR.
Definition: bitSet.C:206
static void mpiGather(const Type *sendData, Type *recvData, int count, const int communicator=UPstream::worldComm)
Receive identically-sized (contiguous) data from all ranks.
Macros for easy insertion into run-time selection tables.
scalar range
void resize(const label numElem, const unsigned int val=0u)
Reset addressable list size, does not shrink the allocated size.
Definition: PackedListI.H:455
block_type * data() noexcept
A pointer to the raw storage.
Definition: PackedList.H:590
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
void rhs(fvMatrix< typename Expr::value_type > &m, const Expr &expression)
dimensionedScalar pos(const dimensionedScalar &ds)
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
A dynamic list of packed unsigned integers, with the number of bits per item specified by the <Width>...
Definition: PackedList.H:105
bitSet & unset(const bitSet &other)
Unset (subtract) the bits specified in the other bitset, which is a set difference corresponds to the...
Definition: bitSetI.H:540
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
static bool broadcast(Type *buffer, std::streamsize count, const int communicator, const int root=UPstream::masterNo())
Broadcast buffer contents (contiguous types) to all ranks (default: from rank=0). The sizes must matc...
#define FOAM_UNLIKELY(cond)
Definition: stdFoam.H:65
static bitSet allGather(bool localValue, int communicator=-1)
Allgather individual values into bitSet locations.
Definition: bitSet.C:803
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
constexpr bitSet() noexcept
Default construct an empty, zero-sized bitSet.
Definition: bitSetI.H:23
List< bool > bools(const labelHashSet &locations)
Transform the on locations to a boolList, with true for each non-negative location and false for all ...
Definition: HashOps.C:72
bitSet & andEq(const bitSet &other)
The set logical AND.
Definition: bitSet.C:88
int debug
Static debugging option.
defineTypeNameAndDebug(combustionModel, 0)
labelList toc() const
The indices of the on bits as a sorted labelList.
Definition: bitSet.C:515
static bool is_parallel(label communicator=worldComm)
True if parallel algorithm or exchange is required.
Definition: UPstream.H:1836
static label nProcs(label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
Definition: UPstream.H:1790
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:58
limits reset(1/(limits.max()+VSMALL), 1/(limits.min()+VSMALL))
surface1 clear()
triangles reserve(surf.size())
void assign(const UList< bool > &bools)
Copy assign all entries from a list of bools.
Definition: bitSet.C:316
bool intersects(const bitSet &other) const
True if any bits in the other bitset intersect (are the same).
Definition: bitSet.C:341
static bool master(label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1807
block_container blocks_
The blocks of raw data.
Definition: PackedList.H:224
label n
static constexpr label num_blocks(label numElem) noexcept
Calculate the number of blocks required to _address_ the requested number of elements.
Definition: PackedList.H:196
void reset()
Clear all bits but do not adjust the addressable size.
Definition: PackedListI.H:570
static constexpr unsigned elem_per_block
The number of elements stored per data block.
Definition: PackedList.H:174
List< label > labelList
A List of labels.
Definition: List.H:61
label num_blocks() const noexcept
The number of internal storage blocks.
Definition: PackedListI.H:605
unsigned int get(const label i) const
Get value at specified index. A no-op and returns 0 for out-of-range positions (safely/silently ignor...
Definition: PackedListI.H:674
void reduceAnd(int communicator=-1, bool syncSizes=true)
Inplace bit_and parallel reduction.
Definition: bitSet.C:642
bool none() const
True if no bits in this bitset are set.
Definition: bitSetI.H:414
bitSet bitset(const labelHashSet &locations)
Transform the on locations to a bitSet.
Definition: HashOps.C:63
Namespace for OpenFOAM.
#define InfoInFunction
Report an information message using Foam::Info.