13#define ASSERT_BITVECTOR
22 : dataPtr(dataPtr), endIndex(endIndex) {
25 currentIndex = getNextIndexWithValue<true>(dataPtr, startIndex, endIndex);
27 currentIndex = startIndex;
38 dataPtr = other.dataPtr;
39 currentIndex = other.currentIndex;
40 endIndex = other.endIndex;
46 currentIndex = getNextIndexWithValue<true>(dataPtr, ++currentIndex, endIndex);
57 for (
size_t i = 0;
i < n; ++
i) {
58 currentIndex = getNextIndexWithValue<true>(dataPtr, ++currentIndex, endIndex);
68 return currentIndex != other.currentIndex;
72 return currentIndex == other.currentIndex;
78 : dataPtr(dataPtr), lowerBound(lowerBound) {
81 currentIndex = getNextIndexWithValue<true, true>(dataPtr, lowerBound, upperBound);
83 currentIndex = upperBound;
88 : dataPtr(other.dataPtr), currentIndex(other.currentIndex), lowerBound(other.lowerBound) {
95 dataPtr = other.dataPtr;
96 currentIndex = other.currentIndex;
97 lowerBound = other.lowerBound;
103 currentIndex = getNextIndexWithValue<true, true>(dataPtr, lowerBound, --currentIndex);
113 for (
size_t i = 0;
i < n; ++
i) {
114 currentIndex = getNextIndexWithValue<true, true>(dataPtr, lowerBound, --currentIndex);
120 return currentIndex - 1;
124 return currentIndex != other.currentIndex;
128 return currentIndex == other.currentIndex;
137 uint_fast64_t bucketCount = length >> 6;
138 if ((length & mod64mask) != 0) {
144 buckets =
new uint64_t[bucketCount];
145 std::fill_n(buckets, bucketCount, -1ull);
146 truncateLastBucket();
148 buckets =
new uint64_t[bucketCount]();
156template<
typename InputIterator>
165BitVector::BitVector(uint_fast64_t bucketCount, uint_fast64_t bitCount) : bitCount(bitCount), buckets(nullptr) {
166 STORM_LOG_ASSERT((bucketCount << 6) == bitCount,
"Bit count does not match number of buckets.");
167 buckets =
new uint64_t[bucketCount]();
171 buckets =
new uint64_t[other.bucketCount()];
172 std::copy_n(other.buckets, other.bucketCount(), buckets);
177 if (
this != &other) {
178 if (buckets && bucketCount() != other.bucketCount()) {
182 bitCount = other.bitCount;
184 buckets =
new uint64_t[other.bucketCount()];
186 std::copy_n(other.buckets, other.bucketCount(), buckets);
194 }
else if (this->
size() > other.
size()) {
198 uint64_t* first1 = this->buckets;
199 uint64_t* last1 = this->buckets + this->bucketCount();
200 uint64_t* first2 = other.buckets;
202 for (; first1 != last1; ++first1, ++first2) {
203 if (*first1 < *first2) {
205 }
else if (*first1 > *first2) {
214 other.buckets =
nullptr;
219 if (
this != &other) {
220 bitCount = other.bitCount;
222 delete[] this->buckets;
223 this->buckets = other.buckets;
224 other.buckets =
nullptr;
232 if (this->bitCount != other.bitCount)
236 return std::equal(this->buckets, this->buckets + this->bucketCount(), other.buckets);
240 return !(*
this == other);
244 STORM_LOG_ASSERT(index < bitCount,
"Invalid call to BitVector::set: written index " << index <<
" out of bounds.");
245 uint64_t bucket = index >> 6;
247 uint64_t mask = 1ull << (63 - (index & mod64mask));
249 buckets[bucket] |= mask;
251 buckets[bucket] &= ~mask;
255template<
typename InputIterator>
257 for (InputIterator it =
begin; it !=
end; ++it) {
258 this->
set(*it, value);
263 uint64_t bucket = index >> 6;
264 uint64_t mask = 1ull << (63 - (index & mod64mask));
265 return (this->buckets[bucket] & mask) == mask;
269 STORM_LOG_ASSERT(index < bitCount,
"Invalid call to BitVector::get: read index " << index <<
" out of bounds.");
270 return (*
this)[index];
274 if (newLength > bitCount) {
275 uint_fast64_t newBucketCount = newLength >> 6;
276 if ((newLength & mod64mask) != 0) {
280 if (newBucketCount > this->bucketCount()) {
281 uint64_t* newBuckets =
new uint64_t[newBucketCount];
282 std::copy_n(buckets, this->bucketCount(), newBuckets);
284 if (this->bucketCount() > 0) {
285 newBuckets[this->bucketCount() - 1] |= ((1ull << (64 - (bitCount & mod64mask))) - 1ull);
287 std::fill_n(newBuckets + this->bucketCount(), newBucketCount - this->bucketCount(), -1ull);
289 std::fill_n(newBuckets + this->bucketCount(), newBucketCount - this->bucketCount(), 0);
292 buckets = newBuckets;
293 bitCount = newLength;
297 buckets[this->bucketCount() - 1] |= ((1ull << (64 - (bitCount & mod64mask))) - 1ull);
299 bitCount = newLength;
301 truncateLastBucket();
303 uint_fast64_t newBucketCount = newLength >> 6;
304 if ((newLength & mod64mask) != 0) {
310 if (newBucketCount < this->bucketCount()) {
311 uint64_t* newBuckets =
new uint64_t[newBucketCount];
312 std::copy_n(buckets, newBucketCount, newBuckets);
314 buckets = newBuckets;
315 bitCount = newLength;
317 bitCount = newLength;
318 truncateLastBucket();
323 STORM_LOG_ASSERT(
size() % 64 == 0,
"We expect the length of the left bitvector to be a multiple of 64.");
333 bitCount = bucketCount() * 64;
340 if (minimumLength > bitCount) {
342 uint_fast64_t newLength = std::max(
static_cast<uint_fast64_t
>(64), bitCount);
344 while (newLength < minimumLength) {
345 newLength = newLength << 1;
352 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
354 std::transform(this->buckets, this->buckets + this->bucketCount(), other.buckets, result.buckets,
355 [](uint64_t
const& a, uint64_t
const& b) { return a & b; });
360 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
361 std::transform(this->buckets, this->buckets + this->bucketCount(), other.buckets, this->buckets,
362 [](uint64_t
const& a, uint64_t
const& b) { return a & b; });
367 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
369 std::transform(this->buckets, this->buckets + this->bucketCount(), other.buckets, result.buckets,
370 [](uint64_t
const& a, uint64_t
const& b) { return a | b; });
375 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
376 std::transform(this->buckets, this->buckets + this->bucketCount(), other.buckets, this->buckets,
377 [](uint64_t
const& a, uint64_t
const& b) { return a | b; });
382 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
384 std::transform(this->buckets, this->buckets + this->bucketCount(), other.buckets, result.buckets,
385 [](uint64_t
const& a, uint64_t
const& b) { return a ^ b; });
386 result.truncateLastBucket();
391 STORM_LOG_ASSERT(bitCount == filter.bitCount,
"Length of the bit vectors does not match.");
398 uint_fast64_t position = 0;
399 for (
auto bit : filter) {
401 result.
set(position);
408 for (
auto bit : (*this)) {
420 std::transform(this->buckets, this->buckets + this->bucketCount(), result.buckets, [](uint64_t
const& a) { return ~a; });
421 result.truncateLastBucket();
426 std::transform(this->buckets, this->buckets + this->bucketCount(), this->buckets, [](uint64_t
const& a) {
return ~a; });
427 truncateLastBucket();
434 if (firstUnsetIndex == this->bitCount) {
438 uint64_t bucketIndex = firstUnsetIndex >> 6;
439 std::fill_n(buckets, bucketIndex, 0);
442 uint64_t& bucket = this->buckets[bucketIndex];
443 uint64_t indexInBucket = firstUnsetIndex & mod64mask;
444 if (indexInBucket > 0) {
446 uint64_t mask = ~(-1ull << (64 - indexInBucket));
451 uint64_t mask = 1ull << (63 - indexInBucket);
457 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
460 std::transform(this->buckets, this->buckets + this->bucketCount(), other.buckets, result.buckets,
461 [](uint64_t
const& a, uint64_t
const& b) { return (~a | b); });
462 result.truncateLastBucket();
467 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
469 uint64_t
const* it1 = buckets;
470 uint64_t
const* ite1 = buckets + bucketCount();
471 uint64_t
const* it2 = other.buckets;
473 for (; it1 != ite1; ++it1, ++it2) {
474 if ((*it1 & *it2) != *it1) {
482 STORM_LOG_ASSERT(bitCount == other.bitCount,
"Length of the bit vectors does not match.");
484 uint64_t
const* it1 = buckets;
485 uint64_t
const* ite1 = buckets + bucketCount();
486 uint64_t
const* it2 = other.buckets;
488 for (; it1 != ite1; ++it1, ++it2) {
489 if ((*it1 & *it2) != 0) {
497 STORM_LOG_ASSERT((bitIndex & mod64mask) == 0,
"Bit index must be a multiple of 64.");
501 uint64_t index = bitIndex >> 6;
503 uint64_t
const* first1 = buckets + index;
504 uint64_t
const* first2 = other.buckets;
505 uint64_t
const* last2 = other.buckets + other.bucketCount();
507 for (; first2 != last2; ++first1, ++first2) {
508 if (*first1 != *first2) {
517 for (uint64_t
i = 0;
i < this->
size(); ++
i) {
518 if (this->
get(inversePermutation[
i])) {
526 STORM_LOG_ASSERT(inversePermutation.size() == rowGroupIndices.size() - 1,
"Inverse permutation and row group indices do not match.");
528 uint64_t targetIndex = 0u;
529 for (
auto const sourceGroupIndex : inversePermutation) {
530 for (uint64_t sourceIndex = rowGroupIndices[sourceGroupIndex]; sourceIndex < rowGroupIndices[sourceGroupIndex + 1]; ++sourceIndex, ++targetIndex) {
531 if (this->
get(sourceIndex)) {
532 result.
set(targetIndex,
true);
536 STORM_LOG_ASSERT(targetIndex == result.
size(),
"Target index does not match the size of the result.");
541 STORM_LOG_ASSERT((bitIndex & mod64mask) == 0,
"Bit index must be a multiple of 64.");
545 uint64_t index = bitIndex >> 6;
547 uint64_t* first1 = buckets + index;
548 uint64_t
const* first2 = other.buckets;
549 uint64_t
const* last2 = other.buckets + other.bucketCount();
551 for (; first2 != last2; ++first1, ++first2) {
558 uint64_t endPos = std::min(bitIndex + nrOfBits, bitCount);
559 for (uint64_t tmpIndex = bitIndex; tmpIndex < endPos; ++tmpIndex) {
560 set(tmpIndex, newValue);
565 uint64_t numberOfBuckets = numberOfBits >> 6;
566 uint64_t index = bitIndex >> 6;
567 STORM_LOG_ASSERT(index + numberOfBuckets <= this->bucketCount(),
"Argument is out-of-range.");
570 std::copy(this->buckets + index, this->buckets + index + numberOfBuckets, result.buckets);
571 result.truncateLastBucket();
577 uint64_t bucket = bitIndex >> 6;
578 uint64_t bitIndexInBucket = bitIndex & mod64mask;
581 if (bitIndexInBucket == 0) {
584 mask = (1ull << (64 - bitIndexInBucket)) - 1ull;
587 if (bitIndexInBucket + numberOfBits < 64) {
589 mask &= ~((1ull << (64 - (bitIndexInBucket + numberOfBits))) - 1ull);
590 return (buckets[bucket] & mask) >> (64 - (bitIndexInBucket + numberOfBits));
591 }
else if (bitIndexInBucket + numberOfBits > 64) {
593 uint64_t result = (buckets[bucket] & mask);
597 numberOfBits -= (64 - bitIndexInBucket);
600 result <<= numberOfBits;
604 mask = ~((1ull << (64 - numberOfBits)) - 1ull);
605 uint64_t lowerBits = buckets[bucket] & mask;
606 result |= (lowerBits >> (64 - numberOfBits));
611 return buckets[bucket] & mask;
618 uint64_t bucket = bitIndex >> 6;
619 uint64_t bitIndexInBucket = bitIndex & mod64mask;
622 if (bitIndexInBucket == 0) {
625 mask = (1ull << (64 - bitIndexInBucket)) - 1ull;
628 if (bitIndexInBucket < 62) {
630 mask &= ~((1ull << (62 - (bitIndexInBucket))) - 1ull);
631 return (buckets[bucket] & mask) >> (62 - bitIndexInBucket);
634 return buckets[bucket] & mask;
641 "Integer value (" << value <<
") too large to fit in the given number of bits (" << numberOfBits <<
").");
643 uint64_t bucket = bitIndex >> 6;
644 uint64_t bitIndexInBucket = bitIndex & mod64mask;
647 if (bitIndexInBucket == 0) {
650 mask = (1ull << (64 - bitIndexInBucket)) - 1ull;
653 if (bitIndexInBucket + numberOfBits < 64) {
655 mask &= ~((1ull << (64 - (bitIndexInBucket + numberOfBits))) - 1ull);
656 buckets[bucket] = (buckets[bucket] & ~mask) | (value << (64 - (bitIndexInBucket + numberOfBits)));
657 }
else if (bitIndexInBucket + numberOfBits > 64) {
659 buckets[bucket] = (buckets[bucket] & ~mask) | (value >> (numberOfBits + (bitIndexInBucket - 64)));
663 numberOfBits -= (64 - bitIndexInBucket);
666 value <<= (64 - numberOfBits);
669 mask = ((1ull << (64 - numberOfBits)) - 1ull);
670 buckets[bucket] = (buckets[bucket] & mask) | value;
672 buckets[bucket] = (buckets[bucket] & ~mask) | value;
677 uint64_t* last = buckets + bucketCount();
678 uint64_t* it = std::find_if(buckets, last, [](uint64_t
const& a) {
return a != 0; });
687 uint64_t* last = buckets + bucketCount() - 1;
688 for (uint64_t
const* it = buckets; it < last; ++it) {
695 uint64_t mask = ~((1ull << (64 - (bitCount & mod64mask))) - 1ull);
696 if ((*last & mask) != mask) {
703 std::fill_n(buckets, this->bucketCount(), 0);
707 std::fill_n(buckets, this->bucketCount(), -1ull);
708 truncateLastBucket();
716 uint_fast64_t result = 0;
719 uint_fast64_t bucket = index >> 6;
720 for (uint_fast64_t
i = 0;
i < bucket; ++
i) {
722#if (defined(__GNUG__) || defined(__clang__))
723 result += __builtin_popcountll(buckets[
i]);
725#include <nmmintrin.h>
727 result += _mm_popcnt_u64(bucketVector[
i]);
730 uint_fast64_t bitset = buckets[
i];
731 for (cnt = 0; bitset; cnt++) {
732 bitset &= bitset - 1;
739 uint64_t tmp = index & mod64mask;
741 tmp = ~((1ll << (64 - (tmp & mod64mask))) - 1ll);
742 tmp &= buckets[bucket];
744#if (defined(__GNUG__) || defined(__clang__))
745 result += __builtin_popcountll(tmp);
748 uint64_t bitset = tmp;
749 for (cnt = 0; bitset; cnt++) {
750 bitset &= bitset - 1;
760 std::vector<uint_fast64_t> bitsSetBeforeIndices;
761 bitsSetBeforeIndices.reserve(this->
size());
762 uint_fast64_t lastIndex = 0;
763 uint_fast64_t currentNumberOfSetBits = 0;
764 for (
auto index : *
this) {
765 while (lastIndex <= index) {
766 bitsSetBeforeIndices.push_back(currentNumberOfSetBits);
769 ++currentNumberOfSetBits;
771 return bitsSetBeforeIndices;
775 return static_cast<size_t>(bitCount);
779 return sizeof(*this) +
sizeof(uint64_t) * bucketCount();
806 return getNextIndexWithValue<true>(buckets, startingIndex, bitCount);
810#ifdef ASSERT_BITVECTOR
812 "The result is inconsistent with the next set index of the complement of this bitvector");
814 return getNextIndexWithValue<false>(buckets, startingIndex, bitCount);
818 return getNextIndexWithValue<true, true>(buckets, 0, endIndex);
822#ifdef ASSERT_BITVECTOR
824 "The result is inconsistent with the next set index of the complement of this bitvector");
826 return getNextIndexWithValue<false, true>(buckets, 0, endIndex);
829template<
bool Value,
bool Backward>
830uint_fast64_t BitVector::getNextIndexWithValue(uint64_t
const* dataPtr, uint64_t startingIndex, uint64_t endIndex) {
831 if (startingIndex >= endIndex) {
832 return Backward ? startingIndex : endIndex;
835 uint64_t currentBucketIndexOffset = Backward ? endIndex - 1 : startingIndex;
836 uint_fast8_t currentBitInBucket = currentBucketIndexOffset & mod64mask;
837 uint64_t
const* bucketIt = dataPtr + (currentBucketIndexOffset >> 6);
838 currentBucketIndexOffset = (currentBucketIndexOffset >> 6 << 6);
841 uint64_t relevantBitsInBucket;
842 if constexpr (Backward) {
843 relevantBitsInBucket = -1ull << (63 - currentBitInBucket);
845 relevantBitsInBucket = -1ull >> currentBitInBucket;
847 uint64_t currentBucket = Value ? (*bucketIt & relevantBitsInBucket) : (*bucketIt | ~relevantBitsInBucket);
850 if (currentBucket == (Value ? 0ull : -1ull)) {
854 if constexpr (Backward) {
855 if (currentBucketIndexOffset <= startingIndex) {
857 return startingIndex;
860 currentBucketIndexOffset -= 64;
863 currentBucketIndexOffset += 64;
864 if (currentBucketIndexOffset >= endIndex) {
870 }
while ((*bucketIt) == (Value ? 0ull : -1ull));
872 currentBucket = *bucketIt;
873 currentBitInBucket = Backward ? 63u : 0u;
876 if constexpr (!Value) {
877 currentBucket = ~currentBucket;
880 STORM_LOG_ASSERT(currentBucket != 0ull,
"Bitvector's getNextIndexWithValue method in invalid state.");
882#if (defined(__GNUG__) || defined(__clang__))
884 if constexpr (Backward) {
886 return std::max<uint64_t>(startingIndex,
887 currentBucketIndexOffset + 64ull - __builtin_ctzll(currentBucket));
890 return std::min<uint64_t>(endIndex, currentBucketIndexOffset + __builtin_clzll(currentBucket));
894 uint64_t compareMask = 1ull << (63 - currentBitInBucket);
895 while (!
static_cast<bool>(currentBucket & compareMask)) {
896 if constexpr (Backward) {
897 compareMask <<= 1ull;
898 --currentBitInBucket;
900 compareMask >>= 1ull;
901 ++currentBitInBucket;
904 if constexpr (Backward) {
905 return std::max(startingIndex, currentBucketIndexOffset + currentBitInBucket + 1ull);
907 return std::min(endIndex, currentBucketIndexOffset + currentBitInBucket);
914#ifdef ASSERT_BITVECTOR
919 uint_fast64_t offset = start % 64;
920 uint64_t* getBucket = buckets + (start / 64);
921 uint64_t* insertBucket = result.buckets;
922 uint_fast64_t getValue;
923 uint_fast64_t writeValue = 0;
924 uint_fast64_t noBits = 0;
927 for (; noBits + 64 <= length; ++getBucket, ++insertBucket, noBits += 64) {
928 *insertBucket = *getBucket;
932 getValue = *getBucket;
933 writeValue = (getValue << offset);
934 noBits += (64 - offset);
938 for (; noBits + 64 <= length; ++getBucket, ++insertBucket, noBits += 64) {
939 getValue = *getBucket;
941 writeValue |= (getValue >> (64 - offset));
942 *insertBucket = writeValue;
944 writeValue = (getValue << offset);
949 uint_fast64_t remainingBits = length - noBits;
950 STORM_LOG_ASSERT(getBucket != buckets + bucketCount(),
"Bucket index incorrect.");
952 getValue = (*getBucket >> (64 - remainingBits)) << (64 - remainingBits);
955 STORM_LOG_ASSERT(insertBucket != result.buckets + result.bucketCount(),
"Bucket index incorrect.");
957 *insertBucket = getValue;
961 if (remainingBits > offset) {
965 STORM_LOG_ASSERT(insertBucket != result.buckets + result.bucketCount(),
"Bucket index incorrect.");
970#ifdef ASSERT_BITVECTOR
972 for (uint_fast64_t
i = 0;
i < length; ++
i) {
973 if (result.get(
i) !=
get(start +
i)) {
975 STORM_LOG_ERROR(
"Getting from " << start <<
" with length " << length);
976 std::stringstream stream;
979 result.printBits(stream);
984 for (uint_fast64_t
i = 0;
i < bitCount; ++
i) {
985 if (i < start || i >= start + length) {
986 if (original.get(
i) !=
get(
i)) {
988 STORM_LOG_ERROR(
"Getting from " << start <<
" with length " << length);
989 std::stringstream stream;
992 original.printBits(stream);
1003void BitVector::setFromBitVector(uint_fast64_t start, BitVector
const& other) {
1004#ifdef ASSERT_BITVECTOR
1009 uint_fast64_t offset = start % 64;
1010 uint64_t* insertBucket = buckets + (start / 64);
1011 uint64_t* getBucket = other.buckets;
1012 uint_fast64_t getValue;
1014 uint_fast64_t noBits = 0;
1017 for (; noBits + 64 <= other.bitCount; ++insertBucket, ++getBucket, noBits += 64) {
1018 *insertBucket = *getBucket;
1022 getValue = *getBucket;
1023 writeValue = (*insertBucket >> (64 - offset)) << (64 - offset);
1026 noBits += (64 - offset);
1030 for (; noBits + 64 <= other.bitCount; ++insertBucket, noBits += 64) {
1035 getValue = *getBucket;
1042 uint_fast64_t remainingBits = other.bitCount - noBits;
1044 STORM_LOG_ASSERT(insertBucket != buckets + bucketCount(),
"Bucket index incorrect.");
1045 STORM_LOG_ASSERT(getBucket != other.buckets + other.bucketCount(),
"Bucket index incorrect.");
1047 getValue = *getBucket;
1049 getValue = getValue << (64 - offset);
1052 writeValue = (*insertBucket << remainingBits) >> remainingBits;
1053 if (remainingBits > offset && offset > 0) {
1056 STORM_LOG_ASSERT(getBucket != other.buckets + other.bucketCount(),
"Bucket index incorrect.");
1057 getValue |= *getBucket >> offset;
1063#ifdef ASSERT_BITVECTOR
1065 for (uint_fast64_t
i = 0;
i < other.bitCount; ++
i) {
1066 if (other.get(
i) !=
get(start +
i)) {
1068 STORM_LOG_ERROR(
"Setting from " << start <<
" with length " << other.bitCount);
1069 std::stringstream stream;
1072 other.printBits(stream);
1077 for (uint_fast64_t
i = 0;
i < bitCount; ++
i) {
1078 if (i < start || i >= start + other.bitCount) {
1079 if (original.get(
i) !=
get(
i)) {
1081 STORM_LOG_ERROR(
"Setting from " << start <<
" with length " << other.bitCount);
1082 std::stringstream stream;
1085 original.printBits(stream);
1097 uint_fast64_t elem1 =
getAsInt(start1, length);
1098 uint_fast64_t elem2 =
getAsInt(start2, length);
1099 if (elem1 < elem2) {
1108 BitVector elem1 = getAsBitVector(start1, length);
1109 BitVector elem2 = getAsBitVector(start2, length);
1111 if (!(elem1 < elem2)) {
1113#ifdef ASSERT_BITVECTOR
1115 for (uint_fast64_t
i = 0;
i < length; ++
i) {
1116 if (
get(start1 +
i) >
get(start2 +
i)) {
1119 STORM_LOG_ASSERT(
get(start1 +
i) >=
get(start2 +
i),
"Bit vector not sorted for indices " << start1 +
i <<
" and " << start2 +
i);
1125#ifdef ASSERT_BITVECTOR
1130 setFromBitVector(start1, elem2);
1131 setFromBitVector(start2, elem1);
1133#ifdef ASSERT_BITVECTOR
1136 for (uint_fast64_t
i = 0;
i < length; ++
i) {
1137 tmp = check.get(
i + start1);
1138 check.set(
i + start1, check.get(
i + start2));
1139 check.set(
i + start2, tmp);
1144 for (uint_fast64_t
i = 0;
i < length; ++
i) {
1145 if (
get(start1 +
i) >
get(start2 +
i)) {
1148 STORM_LOG_ASSERT(
get(start1 +
i) >=
get(start2 +
i),
"Bit vector not sorted for indices " << start1 +
i <<
" and " << start2 +
i);
1156void BitVector::truncateLastBucket() {
1157 if ((bitCount & mod64mask) != 0) {
1158 buckets[bucketCount() - 1] &= ~((1ll << (64 - (bitCount & mod64mask))) - 1ll);
1162size_t BitVector::bucketCount()
const {
1163 size_t result = (bitCount >> 6);
1164 if ((bitCount & mod64mask) != 0) {
1171 out <<
"bit vector(" << bitvector.
getNumberOfSetBits() <<
"/" << bitvector.bitCount <<
") [";
1172 for (
auto index : bitvector) {
1173 out << index <<
" ";
1180void BitVector::printBits(std::ostream& out)
const {
1182 uint_fast64_t index = 0;
1183 for (; index * 64 + 64 <= bitCount; ++index) {
1184 std::bitset<64> tmp(buckets[index]);
1189 if (index * 64 < bitCount) {
1191 std::bitset<64> tmp(buckets[index]);
1192 for (
size_t i = 0;
i + index * 64 < bitCount; ++
i) {
1201 std::size_t seed = 14695981039346656037ull;
1203 uint8_t* it =
reinterpret_cast<uint8_t*
>(bv.buckets);
1204 uint8_t
const* ite = it + 8 * bv.bucketCount();
1210 seed += (seed << 1) + (seed << 4) + (seed << 5) + (seed << 7) + (seed << 8) + (seed << 40);
1226inline __attribute__((always_inline)) uint64_t fmix64(uint64_t k) {
1228 k *= 0xff51afd7ed558ccdull;
1230 k *= 0xc4ceb9fe1a85ec53ull;
1236inline uint32_t
rotl32(uint32_t x, int8_t r) {
1237 return (x << r) | (x >> (32 - r));
1240inline uint64_t
rotl64(uint64_t x, int8_t r) {
1241 return (x << r) | (x >> (64 - r));
1248inline __attribute__((always_inline)) uint32_t getblock64(uint64_t
const* p,
int i) {
1254 uint8_t
const* data =
reinterpret_cast<uint8_t const*
>(bv.buckets);
1255 uint32_t len = bv.bucketCount() * 8;
1256 const int nblocks = bv.bucketCount() * 2;
1261 const uint32_t c1 = 0xcc9e2d51;
1262 const uint32_t c2 = 0x1b873593;
1267 const uint32_t* blocks =
reinterpret_cast<uint32_t const*
>(data + nblocks * 4);
1269 for (
int i = -nblocks;
i;
i++) {
1270 uint32_t k1 = getblock32(blocks,
i);
1278 h1 = h1 * 5 + 0xe6546b64;
1293 uint8_t
const* data =
reinterpret_cast<uint8_t const*
>(bv.buckets);
1294 uint64_t len = bv.bucketCount() * 8;
1295 const int nblocks = bv.bucketCount() / 2;
1300 const uint64_t c1 = 0x87c37b91114253d5ull;
1301 const uint64_t c2 = 0x4cf5ad432745937full;
1306 const uint64_t* blocks = (
const uint64_t*)(data);
1308 for (
int i = 0;
i < nblocks;
i++) {
1309 uint64_t k1 = getblock64(blocks,
i * 2 + 0);
1310 uint64_t k2 = getblock64(blocks,
i * 2 + 1);
1319 h1 = h1 * 5 + 0x52dce729;
1328 h2 = h2 * 5 + 0x38495ab5;
1334 uint8_t
const* tail =
reinterpret_cast<uint8_t const*
>(data + nblocks * 16);
1342 k2 ^= ((uint64_t)tail[14]) << 48;
1345 k2 ^= ((uint64_t)tail[13]) << 40;
1348 k2 ^= ((uint64_t)tail[12]) << 32;
1351 k2 ^= ((uint64_t)tail[11]) << 24;
1354 k2 ^= ((uint64_t)tail[10]) << 16;
1357 k2 ^= ((uint64_t)tail[9]) << 8;
1360 k2 ^= ((uint64_t)tail[8]) << 0;
1368 k1 ^= ((uint64_t)tail[7]) << 56;
1371 k1 ^= ((uint64_t)tail[6]) << 48;
1374 k1 ^= ((uint64_t)tail[5]) << 40;
1377 k1 ^= ((uint64_t)tail[4]) << 32;
1380 k1 ^= ((uint64_t)tail[3]) << 24;
1383 k1 ^= ((uint64_t)tail[2]) << 16;
1386 k1 ^= ((uint64_t)tail[1]) << 8;
1389 k1 ^= ((uint64_t)tail[0]) << 0;
1417 for (uint64_t
i = 0;
i < bucketCount(); ++
i) {
1418 os <<
" " << buckets[
i];
1423 std::vector<std::string> splitted;
1424 std::stringstream ss(description);
1425 ss >> std::noskipws;
1430 splitted.push_back(field);
1434 splitted.push_back(std::string());
1439 for (uint64_t
i = 0;
i < splitted.size() - 1; ++
i) {
1440 bv.buckets[
i] = std::stoul(splitted[
i + 1]);
1446template BitVector::BitVector(uint_fast64_t length, std::vector<uint_fast64_t>::iterator begin, std::vector<uint_fast64_t>::iterator end);
1447template BitVector::BitVector(uint_fast64_t length, std::vector<uint_fast64_t>::const_iterator begin, std::vector<uint_fast64_t>::const_iterator end);
1452template void BitVector::set(std::vector<uint_fast64_t>::iterator begin, std::vector<uint_fast64_t>::iterator end,
bool value);
1453template void BitVector::set(std::vector<uint_fast64_t>::const_iterator begin, std::vector<uint_fast64_t>::const_iterator end,
bool value);
1465 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...
uint_fast64_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.
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)
uint_fast64_t operator*() const
Returns the index of the current bit to which this iterator points.
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.
bool compareAndSwap(uint_fast64_t start1, uint_fast64_t start2, uint_fast64_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 "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.
bool operator[](uint_fast64_t index) const
Retrieves the truth value of the bit at the given index.
bool matches(uint_fast64_t bitIndex, BitVector const &other) const
Checks whether the given bit vector matches the bits starting from the given index in the current bit...
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 ...
uint_fast64_t getTwoBitsAligned(uint_fast64_t bitIndex) const
bool full() const
Retrieves whether all bits are set in this bit vector.
const_reverse_iterator rend() const
Returns a reverse iterator pointing at the element past the front of the bit vector.
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.
uint_fast64_t getNextSetIndex(uint_fast64_t startingIndex) const
Retrieves the index of the bit that is the next bit set to true in the bit vector.
void store(std::ostream &) const
void setFromInt(uint_fast64_t bitIndex, uint_fast64_t numberOfBits, uint64_t value)
Sets the selected number of lowermost bits of the provided value at the given bit index.
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.
BitVector operator&(BitVector const &other) const
Performs a logical "and" with the given bit vector.
void resize(uint_fast64_t newLength, bool init=false)
Resizes the bit vector to hold the given new number of bits.
BitVector permute(std::vector< uint64_t > const &inversePermutation) const
Apply a permutation of entries.
void increment()
Increments the (unsigned) number represented by this BitVector by one.
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.
BitVector operator~() const
Performs a logical "not" on the bit vector.
bool operator!=(BitVector const &other) const
Compares the given bit vector with the current one.
void set(uint_fast64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
uint_fast64_t getNextUnsetIndex(uint_fast64_t startingIndex) const
Retrieves the index of the bit that is the next bit set to false in the bit vector.
BitVector & operator&=(BitVector const &other)
Performs a logical "and" with the given bit vector and assigns the result to the current bit vector.
uint_fast64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
void grow(uint_fast64_t minimumLength, bool init=false)
Enlarges the bit vector such that it holds at least the given number of bits (but possibly more).
uint_fast64_t getAsInt(uint_fast64_t bitIndex, uint_fast64_t numberOfBits) const
Retrieves the content of the current bit vector at the given index for the given number of bits as an...
static BitVector load(std::string const &description)
std::vector< uint_fast64_t > getNumberOfSetBitsBeforeIndices() const
Retrieves a vector that holds at position i the number of bits set before index i.
void expandSize(bool init=false)
bool get(uint_fast64_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.
BitVector permuteGroupedVector(std::vector< uint64_t > const &inversePermutation, std::vector< uint64_t > const &rowGroupIndices) const
Apply a permutation of entries assuming a grouped vector.
uint_fast64_t getNumberOfSetBitsBeforeIndex(uint_fast64_t index) const
Retrieves the number of bits set in this bit vector with an index strictly smaller than the given one...
uint64_t getStartOfOneSequenceBefore(uint64_t endIndex) const
Retrieves the smallest index i such that all bits in the range [i,endIndex) are 1.
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::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