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:
Alexandre Duret-Lutz 2021-09-10 11:46:26 +02:00
parent 850608a5fd
commit b6df1f8f92
3 changed files with 68 additions and 5 deletions

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- 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). // de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
@ -364,6 +364,45 @@ namespace spot
return !(other < *this); 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); friend SPOT_API bitvect* make_bitvect(size_t bitcount);
/// Print a bitvect. /// Print a bitvect.

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2013-2016, 2018 Laboratoire de Recherche et // Copyright (C) 2013-2016, 2018, 2021 Laboratoire de Recherche et
// Développement de l'Epita (LRDE). // Développement de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
@ -35,6 +35,11 @@ static void ruler()
std::cout << "\n\n"; std::cout << "\n\n";
} }
static void print_callback(unsigned t)
{
std::cout << t << ',';
}
#define ECHO(name) std::cout << #name": " << *name << '\n' #define ECHO(name) std::cout << #name": " << *name << '\n'
int main() int main()
@ -65,9 +70,24 @@ int main()
*x |= *w; *x |= *w;
ECHO(x); ECHO(x);
std::cout << "foreach in v: ";
v->foreach_set_index(print_callback);
std::cout << '\n';
std::cout << "foreach in w: ";
w->foreach_set_index(print_callback);
std::cout << '\n';
std::cout << "foreach in x: ";
x->foreach_set_index(print_callback);
std::cout << '\n';
std::cout << "subset? " << w->is_subset_of(*x) std::cout << "subset? " << w->is_subset_of(*x)
<< ' ' << v->is_subset_of(*w) << '\n'; << ' ' << v->is_subset_of(*w) << '\n';
*x -= *x;
std::cout << "foreach in x-x: ";
x->foreach_set_index(print_callback);
std::cout << '\n';
delete v; delete v;
delete w; delete w;
delete x; delete x;

View file

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2013, 2015, 2016 Laboratoire de Recherche et Développement # Copyright (C) 2013, 2015, 2016, 2021 Laboratoire de Recherche et
# de l'Epita (LRDE). # Développement de l'Epita (LRDE).
# #
# This file is part of Spot, a model checking library. # This file is part of Spot, a model checking library.
# #
@ -23,7 +23,7 @@
set -e set -e
run 0 ../bitvect | tee stderr run 0 ../bitvect | sed 's/ $//' | tee stderr
cat >expected <<EOF cat >expected <<EOF
0_________1_________2_________3_________4_________5_________6_________7_____ 0_________1_________2_________3_________4_________5_________6_________7_____
@ -43,7 +43,11 @@ w: 000000000010110000000000000000100000000001
x: 000000000000000000000000000000000000000000000000000000000000100000000010000 x: 000000000000000000000000000000000000000000000000000000000000100000000010000
x: 000000000010110000000000000000100000000001000000000000000000100000000010000 x: 000000000010110000000000000000100000000001000000000000000000100000000010000
foreach in v: 7,10,12,
foreach in w: 10,12,13,30,41,
foreach in x: 10,12,13,30,41,60,70,
subset? 1 0 subset? 1 0
foreach in x-x:
0_________1_________2_________3_________4_________5_________6_________7_____ 0_________1_________2_________3_________4_________5_________6_________7_____
0123456789012345678901234567890123456789012345678901234567890123456789012345 0123456789012345678901234567890123456789012345678901234567890123456789012345