6#include <boost/functional/hash.hpp>
23 : dataPtr(dataPtr), endIndex(endIndex) {
26 currentIndex = getNextIndexWithValue<true>(dataPtr, startIndex, endIndex);
28 currentIndex = startIndex;
39 dataPtr = other.dataPtr;
40 currentIndex = other.currentIndex;
41 endIndex = other.endIndex;
47 currentIndex = getNextIndexWithValue<true>(dataPtr, ++currentIndex, endIndex);
58 for (
size_t i = 0;
i < n; ++
i) {
59 currentIndex = getNextIndexWithValue<true>(dataPtr, ++currentIndex, endIndex);
69 return currentIndex != other.currentIndex;
73 return currentIndex == other.currentIndex;
79 : dataPtr(dataPtr), lowerBound(lowerBound) {
82 currentIndex = getNextIndexWithValue<true, true>(dataPtr, lowerBound, upperBound);
84 currentIndex = upperBound;
89 : dataPtr(other.dataPtr), currentIndex(other.currentIndex), lowerBound(other.lowerBound) {
96 dataPtr = other.dataPtr;
97 currentIndex = other.currentIndex;
98 lowerBound = other.lowerBound;
104 currentIndex = getNextIndexWithValue<true, true>(dataPtr, lowerBound, --currentIndex);
114 for (
size_t i = 0;
i < n; ++
i) {
115 currentIndex = getNextIndexWithValue<true, true>(dataPtr, lowerBound, --currentIndex);
121 return currentIndex - 1;
125 return currentIndex != other.currentIndex;
129 return currentIndex == other.currentIndex;
139 if ((length & mod64mask) != 0) {
147 truncateLastBucket();
157template<
typename InputIterator>
166BitVector::BitVector(uint64_t bucketCount, uint64_t bitCount) : bitCount(bitCount), buckets(nullptr) {
173 std::copy_n(other.buckets, other.
bucketCount(), buckets);
178 if (
this != &other) {
183 bitCount = other.bitCount;
187 std::copy_n(other.buckets, other.
bucketCount(), buckets);
195 }
else if (this->
size() > other.
size()) {
199 uint64_t* first1 = this->buckets;
200 uint64_t* last1 = this->buckets + this->
bucketCount();
201 uint64_t* first2 = other.buckets;
203 for (; first1 != last1; ++first1, ++first2) {
204 if (*first1 < *first2) {
206 }
else if (*first1 > *first2) {
215 other.buckets =
nullptr;
220 if (
this != &other) {
221 bitCount = other.bitCount;
223 delete[] this->buckets;
224 this->buckets = other.buckets;
225 other.buckets =
nullptr;
233 if (this->bitCount != other.bitCount) {
238 return std::equal(this->buckets, this->buckets + this->
bucketCount(), other.buckets);
242 return !(*
this == other);
246 STORM_LOG_ASSERT(index < bitCount,
"Invalid call to BitVector::set: written index " << index <<
" out of bounds.");
247 uint64_t bucket = index >> 6;
249 uint64_t mask = 1ull << (63 - (index & mod64mask));
251 buckets[bucket] |= mask;
253 buckets[bucket] &= ~mask;
257template<
typename InputIterator>
259 for (InputIterator it =
begin; it !=
end; ++it) {
260 this->
set(*it, value);
265 uint64_t bucket = index >> 6;
266 uint64_t mask = 1ull << (63 - (index & mod64mask));
267 return (this->buckets[bucket] & mask) == mask;
271 STORM_LOG_ASSERT(index < bitCount,
"Invalid call to BitVector::get: read index " << index <<
" out of bounds.");
272 return (*
this)[index];
276 if (newLength > bitCount) {
277 uint64_t newBucketCount = newLength >> 6;
278 if ((newLength & mod64mask) != 0) {
283 uint64_t* newBuckets =
new uint64_t[newBucketCount];
284 std::copy_n(buckets, this->
bucketCount(), newBuckets);
287 newBuckets[this->
bucketCount() - 1] |= ((1ull << (64 - (bitCount & mod64mask))) - 1ull);
294 buckets = newBuckets;
295 bitCount = newLength;
299 buckets[this->
bucketCount() - 1] |= ((1ull << (64 - (bitCount & mod64mask))) - 1ull);
301 bitCount = newLength;
303 truncateLastBucket();
305 uint64_t newBucketCount = newLength >> 6;
306 if ((newLength & mod64mask) != 0) {
313 uint64_t* newBuckets =
new uint64_t[newBucketCount];
314 std::copy_n(buckets, newBucketCount, newBuckets);
316 buckets = newBuckets;
317 bitCount = newLength;
319 bitCount = newLength;
320 truncateLastBucket();
325 STORM_LOG_ASSERT(
size() % 64 == 0,
"We expect the length of the left bitvector to be a multiple of 64.");
342 if (minimumLength > bitCount) {
344 uint64_t newLength = std::max(
static_cast<uint64_t
>(64), bitCount);
346 while (newLength < minimumLength) {
347 newLength = newLength << 1;
354 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
356 std::transform(this->buckets, this->buckets + this->
bucketCount(), other.buckets, result.buckets,
357 [](uint64_t
const& a, uint64_t
const& b) { return a & b; });
362 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
363 std::transform(this->buckets, this->buckets + this->
bucketCount(), other.buckets, this->buckets,
364 [](uint64_t
const& a, uint64_t
const& b) { return a & b; });
369 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
371 std::transform(this->buckets, this->buckets + this->
bucketCount(), other.buckets, result.buckets,
372 [](uint64_t
const& a, uint64_t
const& b) { return a | b; });
377 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
378 std::transform(this->buckets, this->buckets + this->
bucketCount(), other.buckets, this->buckets,
379 [](uint64_t
const& a, uint64_t
const& b) { return a | b; });
384 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
386 std::transform(this->buckets, this->buckets + this->
bucketCount(), other.buckets, result.buckets,
387 [](uint64_t
const& a, uint64_t
const& b) { return a ^ b; });
392 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
393 std::transform(this->buckets, this->buckets + this->
bucketCount(), other.buckets, this->buckets,
394 [](uint64_t
const& a, uint64_t
const& b) { return a ^ b; });
399 STORM_LOG_ASSERT(bitCount == filter.bitCount,
"Length of the bit vectors does not match.");
406 uint64_t position = 0;
407 for (uint64_t bit : filter) {
409 result.
set(position);
416 for (uint64_t bit : (*
this)) {
428 std::transform(this->buckets, this->buckets + this->
bucketCount(), result.buckets, [](uint64_t
const& a) { return ~a; });
429 result.truncateLastBucket();
434 std::transform(this->buckets, this->buckets + this->
bucketCount(), this->buckets, [](uint64_t
const& a) {
return ~a; });
435 truncateLastBucket();
442 if (firstUnsetIndex == this->bitCount) {
446 uint64_t bucketIndex = firstUnsetIndex >> 6;
447 std::fill_n(buckets, bucketIndex, 0);
450 uint64_t& bucket = this->buckets[bucketIndex];
451 uint64_t indexInBucket = firstUnsetIndex & mod64mask;
452 if (indexInBucket > 0) {
454 uint64_t mask = ~(-1ull << (64 - indexInBucket));
459 uint64_t mask = 1ull << (63 - indexInBucket);
465 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
468 std::transform(this->buckets, this->buckets + this->
bucketCount(), other.buckets, result.buckets,
469 [](uint64_t
const& a, uint64_t
const& b) { return (~a | b); });
470 result.truncateLastBucket();
475 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
477 uint64_t
const* it1 = buckets;
479 uint64_t
const* it2 = other.buckets;
481 for (; it1 != ite1; ++it1, ++it2) {
482 if ((*it1 & *it2) != *it1) {
490 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
492 uint64_t
const* it1 = buckets;
494 uint64_t
const* it2 = other.buckets;
496 for (; it1 != ite1; ++it1, ++it2) {
497 if ((*it1 & *it2) != 0) {
505 STORM_LOG_ASSERT((bitIndex & mod64mask) == 0,
"Bit index must be a multiple of 64.");
509 uint64_t index = bitIndex >> 6;
511 uint64_t
const* first1 = buckets + index;
512 uint64_t
const* first2 = other.buckets;
513 uint64_t
const* last2 = other.buckets + other.
bucketCount();
515 for (; first2 != last2; ++first1, ++first2) {
516 if (*first1 != *first2) {
525 for (uint64_t
i = 0;
i < this->
size(); ++
i) {
526 if (this->
get(inversePermutation[
i])) {
534 STORM_LOG_ASSERT(inversePermutation.size() == rowGroupIndices.size() - 1,
"Inverse permutation and row group indices do not match.");
536 uint64_t targetIndex = 0u;
537 for (
auto const sourceGroupIndex : inversePermutation) {
538 for (uint64_t sourceIndex = rowGroupIndices[sourceGroupIndex]; sourceIndex < rowGroupIndices[sourceGroupIndex + 1]; ++sourceIndex, ++targetIndex) {
539 if (this->
get(sourceIndex)) {
540 result.
set(targetIndex,
true);
544 STORM_LOG_ASSERT(targetIndex == result.
size(),
"Target index does not match the size of the result.");
549 STORM_LOG_ASSERT((bitIndex & mod64mask) == 0,
"Bit index must be a multiple of 64.");
553 uint64_t index = bitIndex >> 6;
555 uint64_t* first1 = buckets + index;
556 uint64_t
const* first2 = other.buckets;
557 uint64_t
const* last2 = other.buckets + other.
bucketCount();
559 for (; first2 != last2; ++first1, ++first2) {
566 uint64_t endPos = std::min(bitIndex + nrOfBits, bitCount);
567 for (uint64_t tmpIndex = bitIndex; tmpIndex < endPos; ++tmpIndex) {
568 set(tmpIndex, newValue);
573 uint64_t numberOfBuckets = numberOfBits >> 6;
574 uint64_t index = bitIndex >> 6;
578 std::copy(this->buckets + index, this->buckets + index + numberOfBuckets, result.buckets);
579 result.truncateLastBucket();
584 if (numberOfBits == 0) {
588 uint64_t
const firstBucket = bitIndex >> 6;
589 uint8_t
const bitIndexInFirstBucket = bitIndex & mod64mask;
590 uint8_t
const availableBitsInFirstBucket =
static_cast<uint8_t
>(64 - bitIndexInFirstBucket);
593 uint64_t result = buckets[firstBucket] << bitIndexInFirstBucket;
595 if (availableBitsInFirstBucket < numberOfBits) {
596 result |= buckets[firstBucket + 1] >> availableBitsInFirstBucket;
599 return result >> (64 - numberOfBits);
605 uint64_t bucket = bitIndex >> 6;
606 uint64_t bitIndexInBucket = bitIndex & mod64mask;
609 if (bitIndexInBucket == 0) {
612 mask = (1ull << (64 - bitIndexInBucket)) - 1ull;
615 if (bitIndexInBucket < 62) {
617 mask &= ~((1ull << (62 - (bitIndexInBucket))) - 1ull);
618 return (buckets[bucket] & mask) >> (62 - bitIndexInBucket);
621 return buckets[bucket] & mask;
628 "Integer value (" << value <<
") too large to fit in the given number of bits (" << numberOfBits <<
").");
630 uint64_t bucket = bitIndex >> 6;
631 uint64_t bitIndexInBucket = bitIndex & mod64mask;
634 if (bitIndexInBucket == 0) {
637 mask = (1ull << (64 - bitIndexInBucket)) - 1ull;
640 if (bitIndexInBucket + numberOfBits < 64) {
642 mask &= ~((1ull << (64 - (bitIndexInBucket + numberOfBits))) - 1ull);
643 buckets[bucket] = (buckets[bucket] & ~mask) | (value << (64 - (bitIndexInBucket + numberOfBits)));
644 }
else if (bitIndexInBucket + numberOfBits > 64) {
646 buckets[bucket] = (buckets[bucket] & ~mask) | (value >> (numberOfBits + (bitIndexInBucket - 64)));
650 numberOfBits -= (64 - bitIndexInBucket);
653 value <<= (64 - numberOfBits);
656 mask = ((1ull << (64 - numberOfBits)) - 1ull);
657 buckets[bucket] = (buckets[bucket] & mask) | value;
659 buckets[bucket] = (buckets[bucket] & ~mask) | value;
665 uint64_t* it = std::find_if(buckets, last, [](uint64_t
const& a) {
return a != 0; });
675 for (uint64_t
const* it = buckets; it < last; ++it) {
682 uint64_t mask = ~((1ull << (64 - (bitCount & mod64mask))) - 1ull);
683 if ((*last & mask) != mask) {
695 truncateLastBucket();
703 STORM_LOG_ASSERT(index <= bitCount,
"Invalid call to BitVector::getNumberOfSetBitsBeforeIndex: read index " << index <<
" out of bounds.");
704 uint64_t
const lastBucketIndex = index >> 6;
708 for (uint64_t
i = 0;
i < lastBucketIndex; ++
i) {
709 result += std::popcount(buckets[
i]);
713 uint8_t
const endIndexInLastBucket = index & mod64mask;
714 if (endIndexInLastBucket != 0) {
715 result += std::popcount(buckets[lastBucketIndex] >> (64 - endIndexInLastBucket));
722 std::vector<uint64_t> bitsSetBeforeIndices;
723 bitsSetBeforeIndices.reserve(this->
size());
724 uint64_t lastIndex = 0;
725 uint64_t currentNumberOfSetBits = 0;
726 for (uint64_t index : *
this) {
727 while (lastIndex <= index) {
728 bitsSetBeforeIndices.push_back(currentNumberOfSetBits);
731 ++currentNumberOfSetBits;
733 while (lastIndex < this->
size()) {
734 bitsSetBeforeIndices.push_back(currentNumberOfSetBits);
737 return bitsSetBeforeIndices;
745 return static_cast<size_t>(bitCount);
749 return sizeof(*this) +
sizeof(uint64_t) *
bucketCount();
753 size_t result = (bitCount >> 6);
754 if ((bitCount & mod64mask) != 0) {
761 STORM_LOG_ASSERT(bucketIndex <
bucketCount(),
"Invalid call to BitVector::setBucket: bucket index " << bucketIndex <<
" out of bounds.");
762 buckets[bucketIndex] = value;
764 truncateLastBucket();
769 STORM_LOG_ASSERT(bucketIndex <
bucketCount(),
"Invalid call to BitVector::getBucket: bucket index " << bucketIndex <<
" out of bounds.");
770 STORM_LOG_ASSERT(bucketIndex <
bucketCount() - 1 || (bitCount & mod64mask) == 0ull || (buckets[bucketIndex] << (bitCount & mod64mask)) == 0ull,
771 "Bitvector in invalid state: last bucket contains bits beyond bitCount.");
773 return buckets[bucketIndex] & ~((1ll << (64 - (bitCount & mod64mask))) - 1ll);
775 return buckets[bucketIndex];
802 return getNextIndexWithValue<true>(buckets, startingIndex, bitCount);
806#ifdef ASSERT_BITVECTOR
808 "The result is inconsistent with the next set index of the complement of this bitvector");
810 return getNextIndexWithValue<false>(buckets, startingIndex, bitCount);
814 return getNextIndexWithValue<true, true>(buckets, 0, endIndex);
818#ifdef ASSERT_BITVECTOR
820 "The result is inconsistent with the next set index of the complement of this bitvector");
822 return getNextIndexWithValue<false, true>(buckets, 0, endIndex);
825template<
bool Value,
bool Backward>
826uint64_t BitVector::getNextIndexWithValue(uint64_t
const* dataPtr, uint64_t startingIndex, uint64_t endIndex) {
827 if (startingIndex >= endIndex) {
828 return Backward ? startingIndex : endIndex;
831 uint64_t currentBucketIndexOffset = Backward ? endIndex - 1 : startingIndex;
832 uint_fast8_t currentBitInBucket = currentBucketIndexOffset & mod64mask;
833 uint64_t
const* bucketIt = dataPtr + (currentBucketIndexOffset >> 6);
834 currentBucketIndexOffset = (currentBucketIndexOffset >> 6 << 6);
837 uint64_t relevantBitsInBucket;
838 if constexpr (Backward) {
839 relevantBitsInBucket = -1ull << (63 - currentBitInBucket);
841 relevantBitsInBucket = -1ull >> currentBitInBucket;
843 uint64_t currentBucket = Value ? (*bucketIt & relevantBitsInBucket) : (*bucketIt | ~relevantBitsInBucket);
846 if (currentBucket == (Value ? 0ull : -1ull)) {
851 if (currentBucketIndexOffset <= startingIndex) {
853 return startingIndex;
856 currentBucketIndexOffset -= 64;
859 currentBucketIndexOffset += 64;
860 if (currentBucketIndexOffset >= endIndex) {
866 }
while ((*bucketIt) == (Value ? 0ull : -1ull));
868 currentBucket = *bucketIt;
869 currentBitInBucket =
Backward ? 63u : 0u;
872 if constexpr (!Value) {
873 currentBucket = ~currentBucket;
876 STORM_LOG_ASSERT(currentBucket != 0ull,
"Bitvector's getNextIndexWithValue method in invalid state.");
880 return std::max<uint64_t>(startingIndex,
881 currentBucketIndexOffset + 64ull - std::countr_zero(currentBucket));
884 return std::min<uint64_t>(endIndex, currentBucketIndexOffset + std::countl_zero(currentBucket));
888storm::storage::BitVector BitVector::getAsBitVector(uint64_t start, uint64_t length)
const {
890#ifdef ASSERT_BITVECTOR
893 storm::storage::BitVector result(length,
false);
895 uint64_t offset = start % 64;
896 uint64_t*
getBucket = buckets + (start / 64);
897 uint64_t* insertBucket = result.buckets;
903 for (; noBits + 64 <= length; ++
getBucket, ++insertBucket, noBits += 64) {
910 noBits += (64 - offset);
914 for (; noBits + 64 <= length; ++
getBucket, ++insertBucket, noBits += 64) {
925 uint64_t remainingBits = length - noBits;
928 getValue = (*
getBucket >> (64 - remainingBits)) << (64 - remainingBits);
931 STORM_LOG_ASSERT(insertBucket != result.buckets + result.bucketCount(),
"Bucket index incorrect.");
933 *insertBucket = getValue;
937 if (remainingBits > offset) {
941 STORM_LOG_ASSERT(insertBucket != result.buckets + result.bucketCount(),
"Bucket index incorrect.");
946#ifdef ASSERT_BITVECTOR
948 for (uint64_t
i = 0;
i < length; ++
i) {
949 if (result.get(
i) !=
get(start +
i)) {
951 STORM_LOG_ERROR(
"Getting from " << start <<
" with length " << length);
952 std::stringstream stream;
955 result.printBits(stream);
960 for (uint64_t
i = 0;
i < bitCount; ++
i) {
962 if (original.get(
i) !=
get(
i)) {
964 STORM_LOG_ERROR(
"Getting from " << start <<
" with length " << length);
965 std::stringstream stream;
968 original.printBits(stream);
979void BitVector::setFromBitVector(uint64_t start,
BitVector const& other) {
980#ifdef ASSERT_BITVECTOR
985 uint64_t offset = start % 64;
986 uint64_t* insertBucket = buckets + (start / 64);
993 for (; noBits + 64 <= other.bitCount; ++insertBucket, ++
getBucket, noBits += 64) {
999 writeValue = (*insertBucket >> (64 - offset)) << (64 - offset);
1002 noBits += (64 - offset);
1006 for (; noBits + 64 <= other.bitCount; ++insertBucket, noBits += 64) {
1018 uint64_t remainingBits = other.bitCount - noBits;
1025 getValue = getValue << (64 - offset);
1028 writeValue = (*insertBucket << remainingBits) >> remainingBits;
1029 if (remainingBits > offset && offset > 0) {
1039#ifdef ASSERT_BITVECTOR
1041 for (uint64_t
i = 0;
i < other.bitCount; ++
i) {
1042 if (other.get(
i) !=
get(start +
i)) {
1044 STORM_LOG_ERROR(
"Setting from " << start <<
" with length " << other.bitCount);
1045 std::stringstream stream;
1048 other.printBits(stream);
1053 for (uint64_t
i = 0;
i < bitCount; ++
i) {
1055 if (original.get(
i) !=
get(
i)) {
1057 STORM_LOG_ERROR(
"Setting from " << start <<
" with length " << other.bitCount);
1058 std::stringstream stream;
1061 original.printBits(stream);
1073 uint64_t elem1 =
getAsInt(start1, length);
1074 uint64_t elem2 =
getAsInt(start2, length);
1075 if (elem1 < elem2) {
1084 BitVector elem1 = getAsBitVector(start1, length);
1085 BitVector elem2 = getAsBitVector(start2, length);
1087 if (!(elem1 < elem2)) {
1089#ifdef ASSERT_BITVECTOR
1091 for (uint64_t
i = 0;
i < length; ++
i) {
1092 if (
get(start1 +
i) >
get(start2 +
i)) {
1095 STORM_LOG_ASSERT(
get(start1 +
i) >=
get(start2 +
i),
"Bit vector not sorted for indices " << start1 +
i <<
" and " << start2 +
i);
1101#ifdef ASSERT_BITVECTOR
1106 setFromBitVector(start1, elem2);
1107 setFromBitVector(start2, elem1);
1109#ifdef ASSERT_BITVECTOR
1112 for (uint64_t
i = 0;
i < length; ++
i) {
1113 tmp = check.get(
i + start1);
1114 check.set(
i + start1, check.get(
i + start2));
1115 check.set(
i + start2, tmp);
1120 for (uint64_t
i = 0;
i < length; ++
i) {
1121 if (
get(start1 +
i) >
get(start2 +
i)) {
1124 STORM_LOG_ASSERT(
get(start1 +
i) >=
get(start2 +
i),
"Bit vector not sorted for indices " << start1 +
i <<
" and " << start2 +
i);
1132void BitVector::truncateLastBucket() {
1133 if ((bitCount & mod64mask) != 0) {
1134 buckets[
bucketCount() - 1] &= ~((1ll << (64 - (bitCount & mod64mask))) - 1ll);
1139 out <<
"bit vector(" << bitvector.
getNumberOfSetBits() <<
"/" << bitvector.bitCount <<
") [";
1140 for (uint64_t index : bitvector) {
1141 out << index <<
" ";
1148void BitVector::printBits(std::ostream& out)
const {
1151 for (; index * 64 + 64 <= bitCount; ++index) {
1152 std::bitset<64> tmp(buckets[index]);
1157 if (index * 64 < bitCount) {
1159 std::bitset<64> tmp(buckets[index]);
1160 for (
size_t i = 0;
i + index * 64 < bitCount; ++
i) {
1169 std::size_t seed = 14695981039346656037ull;
1171 uint8_t* it =
reinterpret_cast<uint8_t*
>(bv.buckets);
1178 seed += (seed << 1) + (seed << 4) + (seed << 5) + (seed << 7) + (seed << 8) + (seed << 40);
1194inline __attribute__((always_inline)) uint64_t fmix64(uint64_t k) {
1196 k *= 0xff51afd7ed558ccdull;
1198 k *= 0xc4ceb9fe1a85ec53ull;
1204inline uint32_t
rotl32(uint32_t x, int8_t r) {
1205 return (x << r) | (x >> (32 - r));
1208inline uint64_t
rotl64(uint64_t x, int8_t r) {
1209 return (x << r) | (x >> (64 - r));
1216inline __attribute__((always_inline)) uint32_t getblock64(uint64_t
const* p,
int i) {
1224 uint8_t
const* data =
reinterpret_cast<uint8_t const*
>(bv.buckets);
1231 const uint32_t c1 = 0xcc9e2d51;
1232 const uint32_t c2 = 0x1b873593;
1237 const uint32_t* blocks =
reinterpret_cast<uint32_t const*
>(data +
static_cast<std::ptrdiff_t
>(nblocks) * 4);
1239 for (
int i = -nblocks;
i;
i++) {
1240 uint32_t k1 = getblock32(blocks,
i);
1248 h1 = h1 * 5 + 0xe6546b64;
1263 uint8_t
const* data =
reinterpret_cast<uint8_t const*
>(bv.buckets);
1270 const uint64_t c1 = 0x87c37b91114253d5ull;
1271 const uint64_t c2 = 0x4cf5ad432745937full;
1276 uint64_t
const* blocks = bv.buckets;
1278 for (
int i = 0;
i < nblocks;
i++) {
1279 uint64_t k1 = getblock64(blocks,
i * 2 + 0);
1280 uint64_t k2 = getblock64(blocks,
i * 2 + 1);
1289 h1 = h1 * 5 + 0x52dce729;
1298 h2 = h2 * 5 + 0x38495ab5;
1304 uint8_t
const* tail =
reinterpret_cast<uint8_t const*
>(data +
static_cast<std::ptrdiff_t
>(nblocks) * 16);
1312 k2 ^= ((uint64_t)tail[14]) << 48;
1315 k2 ^= ((uint64_t)tail[13]) << 40;
1318 k2 ^= ((uint64_t)tail[12]) << 32;
1321 k2 ^= ((uint64_t)tail[11]) << 24;
1324 k2 ^= ((uint64_t)tail[10]) << 16;
1327 k2 ^= ((uint64_t)tail[9]) << 8;
1330 k2 ^= ((uint64_t)tail[8]) << 0;
1338 k1 ^= ((uint64_t)tail[7]) << 56;
1341 k1 ^= ((uint64_t)tail[6]) << 48;
1344 k1 ^= ((uint64_t)tail[5]) << 40;
1347 k1 ^= ((uint64_t)tail[4]) << 32;
1350 k1 ^= ((uint64_t)tail[3]) << 24;
1353 k1 ^= ((uint64_t)tail[2]) << 16;
1356 k1 ^= ((uint64_t)tail[1]) << 8;
1359 k1 ^= ((uint64_t)tail[0]) << 0;
1392 os <<
" " << buckets[
i];
1397 std::vector<std::string> splitted;
1398 std::stringstream ss(description);
1399 ss >> std::noskipws;
1404 splitted.push_back(field);
1405 }
else if (ss.eof()) {
1408 splitted.push_back(std::string());
1414 for (uint64_t
i = 0;
i < splitted.size() - 1; ++
i) {
1415 bv.buckets[
i] = std::stoul(splitted[
i + 1]);
1421template BitVector::BitVector(uint64_t length, std::vector<uint64_t>::iterator begin, std::vector<uint64_t>::iterator end);
1422template BitVector::BitVector(uint64_t length, std::vector<uint64_t>::const_iterator begin, std::vector<uint64_t>::const_iterator end);
1425template void BitVector::set(std::vector<uint64_t>::iterator begin, std::vector<uint64_t>::iterator end,
bool value);
1426template void BitVector::set(std::vector<uint64_t>::const_iterator begin, std::vector<uint64_t>::const_iterator end,
bool value);
1437 return boost::hash_range(bitvector.buckets, bitvector.buckets + bitvector.
bucketCount());
A class that enables iterating over the indices of the bit vector whose corresponding bits are set to...
uint64_t operator*() const
Returns the index of the current bit to which this iterator points.
const_iterator & operator++()
Increases the position of the iterator to the position of the next bit that is set to true in the und...
bool operator==(const_iterator const &other) const
Compares the iterator with another iterator for equality.
const_iterator & operator+=(size_t n)
Increases the position of the iterator to the position of the n'th next bit that is set to true in th...
const_iterator & operator=(const_iterator const &other)
Assigns the contents of the given iterator to the current one via copying the former's contents.
bool operator!=(const_iterator const &other) const
Compares the iterator with another iterator for inequality.
A class that enables iterating over the indices of the bit vector whose corresponding bits are set to...
bool operator==(const_reverse_iterator const &other) const
Compares the iterator with another iterator for equality.
uint64_t operator*() const
Returns the index of the current bit to which this iterator points.
const_reverse_iterator()
Constructs a reverse iterator over the indices of the set bits in the given bit vector,...
const_reverse_iterator & operator+=(size_t n)
Lets the iterator point to the n'th previous bit with value 1.
const_reverse_iterator & operator++()
Lets the iterator point to the previous bit with value 1.
const_reverse_iterator & operator=(const_reverse_iterator const &other)
bool operator!=(const_reverse_iterator const &other) const
Compares the iterator with another iterator for inequality.
A bit vector that is internally represented as a vector of 64-bit values.
~BitVector()
Deconstructs a bit vector by deleting the underlying storage.
void complement()
Negates all bits in the bit vector.
BitVector & operator|=(BitVector const &other)
Performs a logical "or" with the given bit vector and assigns the result to the current bit vector.
uint64_t getBucket(uint64_t bucketIndex) const
Gets the bits in the given bucket.
BitVector operator^(BitVector const &other) const
Performs a logical "xor" with the given bit vector.
void setMultiple(uint64_t bitIndex, uint64_t nrOfBits, bool newValue=true)
Sets multiple bits to the given value.
bool operator<(BitVector const &other) const
Retrieves whether the current bit vector is (in some order) smaller than the given one.
const_reverse_iterator rbegin() const
Returns a reverse iterator to the indices of the set bits in the bit vector.
void fill()
Sets all bits from the bit vector.
uint64_t getNextSetIndex(uint64_t startingIndex) const
Retrieves the index of the bit that is the next bit set to true in the bit vector.
uint64_t getTwoBitsAligned(uint64_t bitIndex) const
bool isDisjointFrom(BitVector const &other) const
Checks whether none of the bits that are set in the current bit vector are also set in the given bit ...
bool full() const
Retrieves whether all bits are set in this bit vector.
std::vector< uint64_t > getNumberOfSetBitsBeforeIndices() const
Retrieves a vector that holds at position i the number of bits set before index i.
const_reverse_iterator rend() const
Returns a reverse iterator pointing at the element past the front of the bit vector.
bool hasUniqueSetBit() const
BitVector()
Constructs an empty bit vector of length 0.
const_iterator end() const
Returns an iterator pointing at the element past the back of the bit vector.
void grow(uint64_t minimumLength, bool init=false)
Enlarges the bit vector such that it holds at least the given number of bits (but possibly more).
void store(std::ostream &) const
BitVector operator%(BitVector const &filter) const
Computes a bit vector that contains only the values of the bits given by the filter.
BitVector operator|(BitVector const &other) const
Performs a logical "or" with the given bit vector.
BitVector & operator^=(BitVector const &other)
Performs a logical "xor" with the given bit vector and assigns the result to the current bit vector.
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
std::size_t getSizeInBytes() const
Returns (an approximation of) the size of the bit vector measured in bytes.
void clear()
Removes all set bits from the bit vector.
bool isSubsetOf(BitVector const &other) const
Checks whether all bits that are set in the current bit vector are also set in the given bit vector.
BitVector implies(BitVector const &other) const
Performs a logical "implies" with the given bit vector.
BitVector & operator=(BitVector const &other)
Assigns the contents of the given bit vector to the current bit vector via a deep copy.
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
uint64_t getNextUnsetIndex(uint64_t startingIndex) const
Retrieves the index of the bit that is the next bit set to false in the bit vector.
bool compareAndSwap(uint64_t start1, uint64_t start2, uint64_t length)
Compare two intervals [start1, start1+length] and [start2, start2+length] and swap them if the second...
BitVector operator&(BitVector const &other) const
Performs a logical "and" with the given bit vector.
void setFromInt(uint64_t bitIndex, uint64_t numberOfBits, uint64_t value)
Sets the selected number of lowermost bits of the provided value at the given bit index.
BitVector permute(std::vector< uint64_t > const &inversePermutation) const
Apply a permutation of entries.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
void increment()
Increments the (unsigned) number represented by this BitVector by one.
size_t bucketCount() const
Retrieves the number of buckets of the underlying storage.
bool matches(uint64_t bitIndex, BitVector const &other) const
Checks whether the given bit vector matches the bits starting from the given index in the current bit...
const_iterator begin() const
Returns an iterator to the indices of the set bits in the bit vector.
uint64_t getStartOfZeroSequenceBefore(uint64_t endIndex) const
Retrieves the smallest index i such that all bits in the range [i,endIndex) are 0.
uint64_t getAsInt(uint64_t bitIndex, uint64_t numberOfBits) const
Retrieves the content of the current bit vector at the given index for the given number of bits as an...
BitVector operator~() const
Performs a logical "not" on the bit vector.
void setBucket(uint64_t bucketIndex, uint64_t value)
Sets the bits in the given bucket to the given value.
bool operator!=(BitVector const &other) const
Compares the given bit vector with the current one.
size_t size() const
Retrieves the number of bits this bit vector can store.
void resize(uint64_t newLength, bool init=false)
Resizes the bit vector to hold the given new number of bits.
BitVector & operator&=(BitVector const &other)
Performs a logical "and" with the given bit vector and assigns the result to the current bit vector.
static BitVector load(std::string const &description)
void expandSize(bool init=false)
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
bool operator==(BitVector const &other) const
Compares the given bit vector with the current one.
uint64_t getNumberOfSetBitsBeforeIndex(uint64_t index) const
Retrieves the number of bits set in this bit vector with an index strictly smaller than the given one...
BitVector permuteGroupedVector(std::vector< uint64_t > const &inversePermutation, std::vector< uint64_t > const &rowGroupIndices) const
Apply a permutation of entries assuming a grouped vector.
uint64_t getStartOfOneSequenceBefore(uint64_t endIndex) const
Retrieves the smallest index i such that all bits in the range [i,endIndex) are 1.
bool operator[](uint64_t index) const
Retrieves the truth value of the bit at the given index.
void concat(BitVector const &extension)
Concatenate this bitvector with another bitvector.
#define STORM_LOG_ERROR(message)
#define STORM_LOG_ASSERT(cond, message)
void writeValue(std::ostream &os, ValueType value, std::unordered_map< ValueType, std::string > const &placeholders)
Write value to stream while using the placeholders.
boost::container::flat_set< Key, std::less< Key >, boost::container::new_allocator< Key > > FlatSet
Redefinition of flat_set was needed, because from Boost 1.70 on the default allocator is set to void.
uint32_t rotl32(uint32_t x, int8_t r)
uint64_t rotl64(uint64_t x, int8_t r)
__attribute__((always_inline)) uint32_t fmix32(uint32_t h)
std::ostream & operator<<(std::ostream &out, ParameterRegion< ParametricType > const ®ion)
std::size_t operator()(storm::storage::BitVector const &bv) const
StateType operator()(storm::storage::BitVector const &bv) const