bitvect: add a foreach_set_index(callback) function
Related to #476, where that is needed. * spot/misc/bitvect.hh: Here. * tests/core/bitvect.cc, tests/core/bitvect.test: Add some tests.
This commit is contained in:
parent
850608a5fd
commit
b6df1f8f92
3 changed files with 68 additions and 5 deletions
|
|
@ -1,5 +1,5 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2013-2020 Laboratoire de Recherche et Développement
|
||||
// Copyright (C) 2013-2021 Laboratoire de Recherche et Développement
|
||||
// de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
|
|
@ -364,6 +364,45 @@ namespace spot
|
|||
return !(other < *this);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void foreach_set_index(F callback) const
|
||||
{
|
||||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
size_t rest = size() % bpb;
|
||||
for (size_t i = 0; i <= block_count_ - 1; ++i)
|
||||
{
|
||||
block_t b = storage_[i];
|
||||
if ((i == block_count_ - 1) && rest)
|
||||
// The last block might not be fully used, scan only the
|
||||
// relevant portion.
|
||||
b &= (1UL << rest) - 1;
|
||||
if (b != 0)
|
||||
{
|
||||
unsigned base = i * bpb;
|
||||
#if __GNUC__
|
||||
// This version is probably faster on sparse bitsets.
|
||||
do
|
||||
{
|
||||
unsigned bit = __builtin_ctzl(b);
|
||||
b ^= 1UL << bit;
|
||||
callback(base + bit);
|
||||
}
|
||||
while (b);
|
||||
#else
|
||||
unsigned bit = 0;
|
||||
do
|
||||
{
|
||||
if (b & 1)
|
||||
callback(base + bit);
|
||||
++bit;
|
||||
b >>= 1;
|
||||
}
|
||||
while (b);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
friend SPOT_API bitvect* make_bitvect(size_t bitcount);
|
||||
|
||||
/// Print a bitvect.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue