diff --git a/spot/misc/bitvect.hh b/spot/misc/bitvect.hh index 7c54658a5..d91653381 100644 --- a/spot/misc/bitvect.hh +++ b/spot/misc/bitvect.hh @@ -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 + 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. diff --git a/tests/core/bitvect.cc b/tests/core/bitvect.cc index d8b0750d5..cf74dcddf 100644 --- a/tests/core/bitvect.cc +++ b/tests/core/bitvect.cc @@ -1,5 +1,5 @@ // -*- 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). // // This file is part of Spot, a model checking library. @@ -35,6 +35,11 @@ static void ruler() std::cout << "\n\n"; } +static void print_callback(unsigned t) +{ + std::cout << t << ','; +} + #define ECHO(name) std::cout << #name": " << *name << '\n' int main() @@ -65,9 +70,24 @@ int main() *x |= *w; 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) << ' ' << 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 w; delete x; diff --git a/tests/core/bitvect.test b/tests/core/bitvect.test index 6da55d655..c76b3808f 100755 --- a/tests/core/bitvect.test +++ b/tests/core/bitvect.test @@ -1,7 +1,7 @@ #!/bin/sh # -*- coding: utf-8 -*- -# Copyright (C) 2013, 2015, 2016 Laboratoire de Recherche et Développement -# de l'Epita (LRDE). +# Copyright (C) 2013, 2015, 2016, 2021 Laboratoire de Recherche et +# Développement de l'Epita (LRDE). # # This file is part of Spot, a model checking library. # @@ -23,7 +23,7 @@ set -e -run 0 ../bitvect | tee stderr +run 0 ../bitvect | sed 's/ $//' | tee stderr cat >expected <