21 : dataPtr(dataPtr), endIndex(endIndex) {
24 currentIndex = getNextIndexWithValue<true>(dataPtr, startIndex, endIndex);
26 currentIndex = startIndex;
37 dataPtr = other.dataPtr;
38 currentIndex = other.currentIndex;
39 endIndex = other.endIndex;
45 currentIndex = getNextIndexWithValue<true>(dataPtr, ++currentIndex, endIndex);
56 for (
size_t i = 0;
i < n; ++
i) {
57 currentIndex = getNextIndexWithValue<true>(dataPtr, ++currentIndex, endIndex);
67 return currentIndex != other.currentIndex;
71 return currentIndex == other.currentIndex;
77 : dataPtr(dataPtr), lowerBound(lowerBound) {
80 currentIndex = getNextIndexWithValue<true, true>(dataPtr, lowerBound, upperBound);
82 currentIndex = upperBound;
87 : dataPtr(other.dataPtr), currentIndex(other.currentIndex), lowerBound(other.lowerBound) {
94 dataPtr = other.dataPtr;
95 currentIndex = other.currentIndex;
96 lowerBound = other.lowerBound;
102 currentIndex = getNextIndexWithValue<true, true>(dataPtr, lowerBound, --currentIndex);
112 for (
size_t i = 0;
i < n; ++
i) {
113 currentIndex = getNextIndexWithValue<true, true>(dataPtr, lowerBound, --currentIndex);
119 return currentIndex - 1;
123 return currentIndex != other.currentIndex;
127 return currentIndex == other.currentIndex;
137 if ((length & mod64mask) != 0) {
145 truncateLastBucket();
155template<
typename InputIterator>
164BitVector::BitVector(uint64_t bucketCount, uint64_t bitCount) : bitCount(bitCount), buckets(nullptr) {
171 std::copy_n(other.buckets, other.
bucketCount(), buckets);
176 if (
this != &other) {
181 bitCount = other.bitCount;
185 std::copy_n(other.buckets, other.
bucketCount(), buckets);
193 }
else if (this->
size() > other.
size()) {
197 uint64_t* first1 = this->buckets;
198 uint64_t* last1 = this->buckets + this->
bucketCount();
199 uint64_t* first2 = other.buckets;
201 for (; first1 != last1; ++first1, ++first2) {
202 if (*first1 < *first2) {
204 }
else if (*first1 > *first2) {
213 other.buckets =
nullptr;
218 if (
this != &other) {
219 bitCount = other.bitCount;
221 delete[] this->buckets;
222 this->buckets = other.buckets;
223 other.buckets =
nullptr;
231 if (this->bitCount != other.bitCount)
235 return std::equal(this->buckets, this->buckets + this->
bucketCount(), other.buckets);
239 return !(*
this == other);
243 STORM_LOG_ASSERT(index < bitCount,
"Invalid call to BitVector::set: written index " << index <<
" out of bounds.");
244 uint64_t bucket = index >> 6;
246 uint64_t mask = 1ull << (63 - (index & mod64mask));
248 buckets[bucket] |= mask;
250 buckets[bucket] &= ~mask;
254template<
typename InputIterator>
256 for (InputIterator it =
begin; it !=
end; ++it) {
257 this->
set(*it, value);
262 uint64_t bucket = index >> 6;
263 uint64_t mask = 1ull << (63 - (index & mod64mask));
264 return (this->buckets[bucket] & mask) == mask;
268 STORM_LOG_ASSERT(index < bitCount,
"Invalid call to BitVector::get: read index " << index <<
" out of bounds.");
269 return (*
this)[index];
273 if (newLength > bitCount) {
274 uint64_t newBucketCount = newLength >> 6;
275 if ((newLength & mod64mask) != 0) {
280 uint64_t* newBuckets =
new uint64_t[newBucketCount];
281 std::copy_n(buckets, this->
bucketCount(), newBuckets);
284 newBuckets[this->
bucketCount() - 1] |= ((1ull << (64 - (bitCount & mod64mask))) - 1ull);
291 buckets = newBuckets;
292 bitCount = newLength;
296 buckets[this->
bucketCount() - 1] |= ((1ull << (64 - (bitCount & mod64mask))) - 1ull);
298 bitCount = newLength;
300 truncateLastBucket();
302 uint64_t newBucketCount = newLength >> 6;
303 if ((newLength & mod64mask) != 0) {
310 uint64_t* newBuckets =
new uint64_t[newBucketCount];
311 std::copy_n(buckets, newBucketCount, newBuckets);
313 buckets = newBuckets;
314 bitCount = newLength;
316 bitCount = newLength;
317 truncateLastBucket();
322 STORM_LOG_ASSERT(
size() % 64 == 0,
"We expect the length of the left bitvector to be a multiple of 64.");
339 if (minimumLength > bitCount) {
341 uint64_t newLength = std::max(
static_cast<uint64_t
>(64), bitCount);
343 while (newLength < minimumLength) {
344 newLength = newLength << 1;
351 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
353 std::transform(this->buckets, this->buckets + this->
bucketCount(), other.buckets, result.buckets,
354 [](uint64_t
const& a, uint64_t
const& b) { return a & b; });
359 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
360 std::transform(this->buckets, this->buckets + this->
bucketCount(), other.buckets, this->buckets,
361 [](uint64_t
const& a, uint64_t
const& b) { return a & b; });
366 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
368 std::transform(this->buckets, this->buckets + this->
bucketCount(), other.buckets, result.buckets,
369 [](uint64_t
const& a, uint64_t
const& b) { return a | b; });
374 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
375 std::transform(this->buckets, this->buckets + this->
bucketCount(), other.buckets, this->buckets,
376 [](uint64_t
const& a, uint64_t
const& b) { return a | b; });
381 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
383 std::transform(this->buckets, this->buckets + this->
bucketCount(), other.buckets, result.buckets,
384 [](uint64_t
const& a, uint64_t
const& b) { return a ^ b; });
385 result.truncateLastBucket();
390 STORM_LOG_ASSERT(bitCount == filter.bitCount,
"Length of the bit vectors does not match.");
397 uint64_t position = 0;
398 for (
auto bit : filter) {
400 result.
set(position);
407 for (
auto bit : (*this)) {
419 std::transform(this->buckets, this->buckets + this->
bucketCount(), result.buckets, [](uint64_t
const& a) { return ~a; });
420 result.truncateLastBucket();
425 std::transform(this->buckets, this->buckets + this->
bucketCount(), this->buckets, [](uint64_t
const& a) {
return ~a; });
426 truncateLastBucket();
433 if (firstUnsetIndex == this->bitCount) {
437 uint64_t bucketIndex = firstUnsetIndex >> 6;
438 std::fill_n(buckets, bucketIndex, 0);
441 uint64_t& bucket = this->buckets[bucketIndex];
442 uint64_t indexInBucket = firstUnsetIndex & mod64mask;
443 if (indexInBucket > 0) {
445 uint64_t mask = ~(-1ull << (64 - indexInBucket));
450 uint64_t mask = 1ull << (63 - indexInBucket);
456 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
459 std::transform(this->buckets, this->buckets + this->
bucketCount(), other.buckets, result.buckets,
460 [](uint64_t
const& a, uint64_t
const& b) { return (~a | b); });
461 result.truncateLastBucket();
466 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
468 uint64_t
const* it1 = buckets;
470 uint64_t
const* it2 = other.buckets;
472 for (; it1 != ite1; ++it1, ++it2) {
473 if ((*it1 & *it2) != *it1) {
481 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
483 uint64_t
const* it1 = buckets;
485 uint64_t
const* it2 = other.buckets;
487 for (; it1 != ite1; ++it1, ++it2) {
488 if ((*it1 & *it2) != 0) {
496 STORM_LOG_ASSERT((bitIndex & mod64mask) == 0,
"Bit index must be a multiple of 64.");
500 uint64_t index = bitIndex >> 6;
502 uint64_t
const* first1 = buckets + index;
503 uint64_t
const* first2 = other.buckets;
504 uint64_t
const* last2 = other.buckets + other.
bucketCount();
506 for (; first2 != last2; ++first1, ++first2) {
507 if (*first1 != *first2) {
516 for (uint64_t
i = 0;
i < this->
size(); ++
i) {
517 if (this->
get(inversePermutation[
i])) {
525 STORM_LOG_ASSERT(inversePermutation.size() == rowGroupIndices.size() - 1,
"Inverse permutation and row group indices do not match.");
527 uint64_t targetIndex = 0u;
528 for (
auto const sourceGroupIndex : inversePermutation) {
529 for (uint64_t sourceIndex = rowGroupIndices[sourceGroupIndex]; sourceIndex < rowGroupIndices[sourceGroupIndex + 1]; ++sourceIndex, ++targetIndex) {
530 if (this->
get(sourceIndex)) {
531 result.
set(targetIndex,
true);
535 STORM_LOG_ASSERT(targetIndex == result.
size(),
"Target index does not match the size of the result.");
540 STORM_LOG_ASSERT((bitIndex & mod64mask) == 0,
"Bit index must be a multiple of 64.");
544 uint64_t index = bitIndex >> 6;
546 uint64_t* first1 = buckets + index;
547 uint64_t
const* first2 = other.buckets;
548 uint64_t
const* last2 = other.buckets + other.
bucketCount();
550 for (; first2 != last2; ++first1, ++first2) {
557 uint64_t endPos = std::min(bitIndex + nrOfBits, bitCount);
558 for (uint64_t tmpIndex = bitIndex; tmpIndex < endPos; ++tmpIndex) {
559 set(tmpIndex, newValue);
564 uint64_t numberOfBuckets = numberOfBits >> 6;
565 uint64_t index = bitIndex >> 6;
569 std::copy(this->buckets + index, this->buckets + index + numberOfBuckets, result.buckets);
570 result.truncateLastBucket();
575 if (numberOfBits == 0) {
579 uint64_t
const firstBucket = bitIndex >> 6;
580 uint8_t
const bitIndexInFirstBucket = bitIndex & mod64mask;
581 uint8_t
const availableBitsInFirstBucket =
static_cast<uint8_t
>(64 - bitIndexInFirstBucket);
584 uint64_t result = buckets[firstBucket] << bitIndexInFirstBucket;
586 if (availableBitsInFirstBucket < numberOfBits) {
587 result |= buckets[firstBucket + 1] >> availableBitsInFirstBucket;
590 return result >> (64 - numberOfBits);
596 uint64_t bucket = bitIndex >> 6;
597 uint64_t bitIndexInBucket = bitIndex & mod64mask;
600 if (bitIndexInBucket == 0) {
603 mask = (1ull << (64 - bitIndexInBucket)) - 1ull;
606 if (bitIndexInBucket < 62) {
608 mask &= ~((1ull << (62 - (bitIndexInBucket))) - 1ull);
609 return (buckets[bucket] & mask) >> (62 - bitIndexInBucket);
612 return buckets[bucket] & mask;
619 "Integer value (" << value <<
") too large to fit in the given number of bits (" << numberOfBits <<
").");
621 uint64_t bucket = bitIndex >> 6;
622 uint64_t bitIndexInBucket = bitIndex & mod64mask;
625 if (bitIndexInBucket == 0) {
628 mask = (1ull << (64 - bitIndexInBucket)) - 1ull;
631 if (bitIndexInBucket + numberOfBits < 64) {
633 mask &= ~((1ull << (64 - (bitIndexInBucket + numberOfBits))) - 1ull);
634 buckets[bucket] = (buckets[bucket] & ~mask) | (value << (64 - (bitIndexInBucket + numberOfBits)));
635 }
else if (bitIndexInBucket + numberOfBits > 64) {
637 buckets[bucket] = (buckets[bucket] & ~mask) | (value >> (numberOfBits + (bitIndexInBucket - 64)));
641 numberOfBits -= (64 - bitIndexInBucket);
644 value <<= (64 - numberOfBits);
647 mask = ((1ull << (64 - numberOfBits)) - 1ull);
648 buckets[bucket] = (buckets[bucket] & mask) | value;
650 buckets[bucket] = (buckets[bucket] & ~mask) | value;
656 uint64_t* it = std::find_if(buckets, last, [](uint64_t
const& a) {
return a != 0; });
666 for (uint64_t
const* it = buckets; it < last; ++it) {
673 uint64_t mask = ~((1ull << (64 - (bitCount & mod64mask))) - 1ull);
674 if ((*last & mask) != mask) {
686 truncateLastBucket();
694 STORM_LOG_ASSERT(index <= bitCount,
"Invalid call to BitVector::getNumberOfSetBitsBeforeIndex: read index " << index <<
" out of bounds.");
695 uint64_t
const lastBucketIndex = index >> 6;
699 for (uint64_t
i = 0;
i < lastBucketIndex; ++
i) {
700 result += std::popcount(buckets[
i]);
704 uint8_t
const endIndexInLastBucket = index & mod64mask;
705 if (endIndexInLastBucket != 0) {
706 result += std::popcount(buckets[lastBucketIndex] >> (64 - endIndexInLastBucket));
713 std::vector<uint64_t> bitsSetBeforeIndices;
714 bitsSetBeforeIndices.reserve(this->
size());
715 uint64_t lastIndex = 0;
716 uint64_t currentNumberOfSetBits = 0;
717 for (
auto index : *
this) {
718 while (lastIndex <= index) {
719 bitsSetBeforeIndices.push_back(currentNumberOfSetBits);
722 ++currentNumberOfSetBits;
724 return bitsSetBeforeIndices;
732 return static_cast<size_t>(bitCount);
736 return sizeof(*this) +
sizeof(uint64_t) *
bucketCount();
740 size_t result = (bitCount >> 6);
741 if ((bitCount & mod64mask) != 0) {
748 STORM_LOG_ASSERT(bucketIndex <
bucketCount(),
"Invalid call to BitVector::setBucket: bucket index " << bucketIndex <<
" out of bounds.");
749 buckets[bucketIndex] = value;
751 truncateLastBucket();
756 STORM_LOG_ASSERT(bucketIndex <
bucketCount(),
"Invalid call to BitVector::getBucket: bucket index " << bucketIndex <<
" out of bounds.");
758 "Bitvector in invalid state: last bucket contains bits beyond bitCount.");
760 return buckets[bucketIndex] & ~((1ll << (64 - (bitCount & mod64mask))) - 1ll);
762 return buckets[bucketIndex];
789 return getNextIndexWithValue<true>(buckets, startingIndex, bitCount);
793#ifdef ASSERT_BITVECTOR
795 "The result is inconsistent with the next set index of the complement of this bitvector");
797 return getNextIndexWithValue<false>(buckets, startingIndex, bitCount);
801 return getNextIndexWithValue<true, true>(buckets, 0, endIndex);
805#ifdef ASSERT_BITVECTOR
807 "The result is inconsistent with the next set index of the complement of this bitvector");
809 return getNextIndexWithValue<false, true>(buckets, 0, endIndex);
812template<
bool Value,
bool Backward>
813uint64_t BitVector::getNextIndexWithValue(uint64_t
const* dataPtr, uint64_t startingIndex, uint64_t endIndex) {
814 if (startingIndex >= endIndex) {
815 return Backward ? startingIndex : endIndex;
818 uint64_t currentBucketIndexOffset = Backward ? endIndex - 1 : startingIndex;
819 uint_fast8_t currentBitInBucket = currentBucketIndexOffset & mod64mask;
820 uint64_t
const* bucketIt = dataPtr + (currentBucketIndexOffset >> 6);
821 currentBucketIndexOffset = (currentBucketIndexOffset >> 6 << 6);
824 uint64_t relevantBitsInBucket;
825 if constexpr (Backward) {
826 relevantBitsInBucket = -1ull << (63 - currentBitInBucket);
828 relevantBitsInBucket = -1ull >> currentBitInBucket;
830 uint64_t currentBucket = Value ? (*bucketIt & relevantBitsInBucket) : (*bucketIt | ~relevantBitsInBucket);
833 if (currentBucket == (Value ? 0ull : -1ull)) {
837 if constexpr (Backward) {
838 if (currentBucketIndexOffset <= startingIndex) {
840 return startingIndex;
843 currentBucketIndexOffset -= 64;
846 currentBucketIndexOffset += 64;
847 if (currentBucketIndexOffset >= endIndex) {
853 }
while ((*bucketIt) == (Value ? 0ull : -1ull));
855 currentBucket = *bucketIt;
856 currentBitInBucket = Backward ? 63u : 0u;
859 if constexpr (!Value) {
860 currentBucket = ~currentBucket;
863 STORM_LOG_ASSERT(currentBucket != 0ull,
"Bitvector's getNextIndexWithValue method in invalid state.");
865#if (defined(__GNUG__) || defined(__clang__))
867 if constexpr (Backward) {
869 return std::max<uint64_t>(startingIndex,
870 currentBucketIndexOffset + 64ull - __builtin_ctzll(currentBucket));
873 return std::min<uint64_t>(endIndex, currentBucketIndexOffset + __builtin_clzll(currentBucket));
877 uint64_t compareMask = 1ull << (63 - currentBitInBucket);
878 while (!
static_cast<bool>(currentBucket & compareMask)) {
879 if constexpr (Backward) {
880 compareMask <<= 1ull;
881 --currentBitInBucket;
883 compareMask >>= 1ull;
884 ++currentBitInBucket;
887 if constexpr (Backward) {
888 return std::max(startingIndex, currentBucketIndexOffset + currentBitInBucket + 1ull);
890 return std::min(endIndex, currentBucketIndexOffset + currentBitInBucket);
897#ifdef ASSERT_BITVECTOR
902 uint64_t offset = start % 64;
903 uint64_t*
getBucket = buckets + (start / 64);
904 uint64_t* insertBucket = result.buckets;
910 for (; noBits + 64 <= length; ++
getBucket, ++insertBucket, noBits += 64) {
917 noBits += (64 - offset);
921 for (; noBits + 64 <= length; ++
getBucket, ++insertBucket, noBits += 64) {
932 uint64_t remainingBits = length - noBits;
935 getValue = (*
getBucket >> (64 - remainingBits)) << (64 - remainingBits);
938 STORM_LOG_ASSERT(insertBucket != result.buckets + result.bucketCount(),
"Bucket index incorrect.");
940 *insertBucket = getValue;
944 if (remainingBits > offset) {
948 STORM_LOG_ASSERT(insertBucket != result.buckets + result.bucketCount(),
"Bucket index incorrect.");
953#ifdef ASSERT_BITVECTOR
955 for (uint64_t
i = 0;
i < length; ++
i) {
956 if (result.get(
i) !=
get(start +
i)) {
958 STORM_LOG_ERROR(
"Getting from " << start <<
" with length " << length);
959 std::stringstream stream;
962 result.printBits(stream);
967 for (uint64_t
i = 0;
i < bitCount; ++
i) {
968 if (i < start || i >= start + length) {
969 if (original.get(
i) !=
get(
i)) {
971 STORM_LOG_ERROR(
"Getting from " << start <<
" with length " << length);
972 std::stringstream stream;
975 original.printBits(stream);
986void BitVector::setFromBitVector(uint64_t start, BitVector
const& other) {
987#ifdef ASSERT_BITVECTOR
992 uint64_t offset = start % 64;
993 uint64_t* insertBucket = buckets + (start / 64);
1000 for (; noBits + 64 <= other.bitCount; ++insertBucket, ++
getBucket, noBits += 64) {
1006 writeValue = (*insertBucket >> (64 - offset)) << (64 - offset);
1009 noBits += (64 - offset);
1013 for (; noBits + 64 <= other.bitCount; ++insertBucket, noBits += 64) {
1025 uint64_t remainingBits = other.bitCount - noBits;
1032 getValue = getValue << (64 - offset);
1035 writeValue = (*insertBucket << remainingBits) >> remainingBits;
1036 if (remainingBits > offset && offset > 0) {
1046#ifdef ASSERT_BITVECTOR
1048 for (uint64_t
i = 0;
i < other.bitCount; ++
i) {
1049 if (other.get(
i) !=
get(start +
i)) {
1051 STORM_LOG_ERROR(
"Setting from " << start <<
" with length " << other.bitCount);
1052 std::stringstream stream;
1055 other.printBits(stream);
1060 for (uint64_t
i = 0;
i < bitCount; ++
i) {
1061 if (i < start || i >= start + other.bitCount) {
1062 if (original.get(
i) !=
get(
i)) {
1064 STORM_LOG_ERROR(
"Setting from " << start <<
" with length " << other.bitCount);
1065 std::stringstream stream;
1068 original.printBits(stream);
1080 uint64_t elem1 =
getAsInt(start1, length);
1081 uint64_t elem2 =
getAsInt(start2, length);
1082 if (elem1 < elem2) {
1091 BitVector elem1 = getAsBitVector(start1, length);
1092 BitVector elem2 = getAsBitVector(start2, length);
1094 if (!(elem1 < elem2)) {
1096#ifdef ASSERT_BITVECTOR
1098 for (uint64_t
i = 0;
i < length; ++
i) {
1099 if (
get(start1 +
i) >
get(start2 +
i)) {
1102 STORM_LOG_ASSERT(
get(start1 +
i) >=
get(start2 +
i),
"Bit vector not sorted for indices " << start1 +
i <<
" and " << start2 +
i);
1108#ifdef ASSERT_BITVECTOR
1113 setFromBitVector(start1, elem2);
1114 setFromBitVector(start2, elem1);
1116#ifdef ASSERT_BITVECTOR
1119 for (uint64_t
i = 0;
i < length; ++
i) {
1120 tmp = check.get(
i + start1);
1121 check.set(
i + start1, check.get(
i + start2));
1122 check.set(
i + start2, tmp);
1127 for (uint64_t
i = 0;
i < length; ++
i) {
1128 if (
get(start1 +
i) >
get(start2 +
i)) {
1131 STORM_LOG_ASSERT(
get(start1 +
i) >=
get(start2 +
i),
"Bit vector not sorted for indices " << start1 +
i <<
" and " << start2 +
i);
1139void BitVector::truncateLastBucket() {
1140 if ((bitCount & mod64mask) != 0) {
1141 buckets[
bucketCount() - 1] &= ~((1ll << (64 - (bitCount & mod64mask))) - 1ll);
1145std::ostream& operator<<(std::ostream& out,
BitVector const& bitvector) {
1146 out <<
"bit vector(" << bitvector.
getNumberOfSetBits() <<
"/" << bitvector.bitCount <<
") [";
1147 for (
auto index : bitvector) {
1148 out << index <<
" ";
1155void BitVector::printBits(std::ostream& out)
const {
1158 for (; index * 64 + 64 <= bitCount; ++index) {
1159 std::bitset<64> tmp(buckets[index]);
1164 if (index * 64 < bitCount) {
1166 std::bitset<64> tmp(buckets[index]);
1167 for (
size_t i = 0;
i + index * 64 < bitCount; ++
i) {
1176 std::size_t seed = 14695981039346656037ull;
1178 uint8_t* it =
reinterpret_cast<uint8_t*
>(bv.buckets);
1185 seed += (seed << 1) + (seed << 4) + (seed << 5) + (seed << 7) + (seed << 8) + (seed << 40);
1201inline __attribute__((always_inline)) uint64_t fmix64(uint64_t k) {
1203 k *= 0xff51afd7ed558ccdull;
1205 k *= 0xc4ceb9fe1a85ec53ull;
1211inline uint32_t
rotl32(uint32_t x, int8_t r) {
1212 return (x << r) | (x >> (32 - r));
1215inline uint64_t
rotl64(uint64_t x, int8_t r) {
1216 return (x << r) | (x >> (64 - r));
1223inline __attribute__((always_inline)) uint32_t getblock64(uint64_t
const* p,
int i) {
1229 uint8_t
const* data =
reinterpret_cast<uint8_t const*
>(bv.buckets);
1236 const uint32_t c1 = 0xcc9e2d51;
1237 const uint32_t c2 = 0x1b873593;
1242 const uint32_t* blocks =
reinterpret_cast<uint32_t const*
>(data + nblocks * 4);
1244 for (
int i = -nblocks;
i;
i++) {
1245 uint32_t k1 = getblock32(blocks,
i);
1253 h1 = h1 * 5 + 0xe6546b64;
1268 uint8_t
const* data =
reinterpret_cast<uint8_t const*
>(bv.buckets);
1275 const uint64_t c1 = 0x87c37b91114253d5ull;
1276 const uint64_t c2 = 0x4cf5ad432745937full;
1281 const uint64_t* blocks = (
const uint64_t*)(data);
1283 for (
int i = 0;
i < nblocks;
i++) {
1284 uint64_t k1 = getblock64(blocks,
i * 2 + 0);
1285 uint64_t k2 = getblock64(blocks,
i * 2 + 1);
1294 h1 = h1 * 5 + 0x52dce729;
1303 h2 = h2 * 5 + 0x38495ab5;
1309 uint8_t
const* tail =
reinterpret_cast<uint8_t const*
>(data + nblocks * 16);
1317 k2 ^= ((uint64_t)tail[14]) << 48;
1320 k2 ^= ((uint64_t)tail[13]) << 40;
1323 k2 ^= ((uint64_t)tail[12]) << 32;
1326 k2 ^= ((uint64_t)tail[11]) << 24;
1329 k2 ^= ((uint64_t)tail[10]) << 16;
1332 k2 ^= ((uint64_t)tail[9]) << 8;
1335 k2 ^= ((uint64_t)tail[8]) << 0;
1343 k1 ^= ((uint64_t)tail[7]) << 56;
1346 k1 ^= ((uint64_t)tail[6]) << 48;
1349 k1 ^= ((uint64_t)tail[5]) << 40;
1352 k1 ^= ((uint64_t)tail[4]) << 32;
1355 k1 ^= ((uint64_t)tail[3]) << 24;
1358 k1 ^= ((uint64_t)tail[2]) << 16;
1361 k1 ^= ((uint64_t)tail[1]) << 8;
1364 k1 ^= ((uint64_t)tail[0]) << 0;
1393 os <<
" " << buckets[
i];
1398 std::vector<std::string> splitted;
1399 std::stringstream ss(description);
1400 ss >> std::noskipws;
1405 splitted.push_back(field);
1409 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.
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.
uint32_t rotl32(uint32_t x, int8_t r)
uint64_t rotl64(uint64_t x, int8_t r)
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.
__attribute__((always_inline)) uint32_t fmix32(uint32_t h)
std::size_t operator()(storm::storage::BitVector const &bv) const
StateType operator()(storm::storage::BitVector const &bv) const