|  |  | @ -13,24 +13,51 @@ | 
			
		
	
		
			
				
					|  |  |  | #include "src/exceptions/invalid_argument.h" | 
			
		
	
		
			
				
					|  |  |  | #include "src/exceptions/out_of_range.h" | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | #include <iostream> | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | namespace mrmc { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | namespace vector { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | //! A Boolean Array | 
			
		
	
		
			
				
					|  |  |  | /*!  | 
			
		
	
		
			
				
					|  |  |  | 	A bit vector for boolean fields or quick selection schemas on Matrix entries. | 
			
		
	
		
			
				
					|  |  |  | 	Does NOT perform index bound checks! | 
			
		
	
		
			
				
					|  |  |  |  A bit vector for boolean fields or quick selection schemas on Matrix entries. | 
			
		
	
		
			
				
					|  |  |  |  Does NOT perform index bound checks! | 
			
		
	
		
			
				
					|  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  | class BitVector { | 
			
		
	
		
			
				
					|  |  |  |  public: | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	class constIndexIterator { | 
			
		
	
		
			
				
					|  |  |  | 		constIndexIterator(uint_fast64_t* bucketPtr, uint_fast64_t* endBucketPtr) : bucketPtr(bucketPtr), endBucketPtr(endBucketPtr), offset(0), currentBitInByte(0) { } | 
			
		
	
		
			
				
					|  |  |  | 		constIndexIterator& operator++() { | 
			
		
	
		
			
				
					|  |  |  | 			do { | 
			
		
	
		
			
				
					|  |  |  | 				uint_fast64_t remainingInBucket = *bucketPtr >> ++currentBitInByte; | 
			
		
	
		
			
				
					|  |  |  | 				if (remainingInBucket != 0) { | 
			
		
	
		
			
				
					|  |  |  | 					while ((remainingInBucket & 1) == 0) { | 
			
		
	
		
			
				
					|  |  |  | 						remainingInBucket >>= 1; | 
			
		
	
		
			
				
					|  |  |  | 						++currentBitInByte; | 
			
		
	
		
			
				
					|  |  |  | 					} | 
			
		
	
		
			
				
					|  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  | 				offset <<= 6; ++bucketPtr; currentBitInByte = 0; | 
			
		
	
		
			
				
					|  |  |  | 			} while (bucketPtr != endBucketPtr); | 
			
		
	
		
			
				
					|  |  |  | 			return *this; | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t operator*() { return offset + currentBitInByte; } | 
			
		
	
		
			
				
					|  |  |  | 		bool operator!=(constIndexIterator& rhs) { return bucketPtr != rhs.bucketPtr; } | 
			
		
	
		
			
				
					|  |  |  | 	private: | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t* bucketPtr; | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t* endBucketPtr; | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t offset; | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast8_t currentBitInByte; | 
			
		
	
		
			
				
					|  |  |  | 	}; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | public: | 
			
		
	
		
			
				
					|  |  |  | 	//! Constructor | 
			
		
	
		
			
				
					|  |  |  | 	 /*! | 
			
		
	
		
			
				
					|  |  |  | 		\param initial_length The initial size of the boolean Array. Can be changed later on via BitVector::resize() | 
			
		
	
		
			
				
					|  |  |  | 	/*! | 
			
		
	
		
			
				
					|  |  |  | 	 \param initial_length The initial size of the boolean Array. Can be changed later on via BitVector::resize() | 
			
		
	
		
			
				
					|  |  |  | 	 */ | 
			
		
	
		
			
				
					|  |  |  | 	BitVector(uint_fast64_t initial_length) { | 
			
		
	
		
			
				
					|  |  |  | 		bucket_count = initial_length / 64; | 
			
		
	
		
			
				
					|  |  |  | 		if (initial_length % 64 != 0) { | 
			
		
	
		
			
				
					|  |  |  | 		bucket_count = initial_length >> 6; | 
			
		
	
		
			
				
					|  |  |  | 		if ((initial_length & mod64mask) != 0) { | 
			
		
	
		
			
				
					|  |  |  | 			++bucket_count; | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  | 		bucket_array = new uint_fast64_t[bucket_count](); | 
			
		
	
	
		
			
				
					|  |  | @ -43,14 +70,15 @@ class BitVector { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	//! Copy Constructor | 
			
		
	
		
			
				
					|  |  |  | 	/*! | 
			
		
	
		
			
				
					|  |  |  | 		Copy Constructor. Creates an exact copy of the source bit vector bv. Modification of either bit vector does not affect the other. | 
			
		
	
		
			
				
					|  |  |  | 		@param bv A reference to the bit vector that should be copied from | 
			
		
	
		
			
				
					|  |  |  | 	 Copy Constructor. Creates an exact copy of the source bit vector bv. Modification of either bit vector does not affect the other. | 
			
		
	
		
			
				
					|  |  |  | 	 @param bv A reference to the bit vector that should be copied from | 
			
		
	
		
			
				
					|  |  |  | 	 */ | 
			
		
	
		
			
				
					|  |  |  | 	BitVector(const BitVector &bv) : bucket_count(bv.bucket_count) | 
			
		
	
		
			
				
					|  |  |  | 	{ | 
			
		
	
		
			
				
					|  |  |  | 	BitVector(const BitVector &bv) : | 
			
		
	
		
			
				
					|  |  |  | 			bucket_count(bv.bucket_count) { | 
			
		
	
		
			
				
					|  |  |  | 		pantheios::log_DEBUG("BitVector::CopyCTor: Using Copy() Ctor."); | 
			
		
	
		
			
				
					|  |  |  | 		bucket_array = new uint_fast64_t[bucket_count](); | 
			
		
	
		
			
				
					|  |  |  | 		memcpy(bucket_array, bv.bucket_array, sizeof(uint_fast64_t) * bucket_count); | 
			
		
	
		
			
				
					|  |  |  | 		memcpy(bucket_array, bv.bucket_array, | 
			
		
	
		
			
				
					|  |  |  | 				sizeof(uint_fast64_t) * bucket_count); | 
			
		
	
		
			
				
					|  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	~BitVector() { | 
			
		
	
	
		
			
				
					|  |  | @ -63,11 +91,13 @@ class BitVector { | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t* tempArray = new uint_fast64_t[new_length](); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 		// 64 bit/entries per uint_fast64_t | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t copySize = (new_length <= (bucket_count * 64)) ? (new_length/64) : (bucket_count); | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t copySize = | 
			
		
	
		
			
				
					|  |  |  | 				(new_length <= (bucket_count << 6)) ? | 
			
		
	
		
			
				
					|  |  |  | 						(new_length >> 6) : (bucket_count); | 
			
		
	
		
			
				
					|  |  |  | 		memcpy(tempArray, bucket_array, sizeof(uint_fast64_t) * copySize); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 		bucket_count = new_length / 64; | 
			
		
	
		
			
				
					|  |  |  | 		if (new_length % 64 != 0) { | 
			
		
	
		
			
				
					|  |  |  | 		bucket_count = new_length >> 6; | 
			
		
	
		
			
				
					|  |  |  | 		if ((new_length & mod64mask) != 0) { | 
			
		
	
		
			
				
					|  |  |  | 			++bucket_count; | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -76,12 +106,12 @@ class BitVector { | 
			
		
	
		
			
				
					|  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	void set(const uint_fast64_t index, const bool value) { | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t bucket = index / 64; | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t bucket = index >> 6; | 
			
		
	
		
			
				
					|  |  |  | 		// Taking the step with mask is crucial as we NEED a 64bit shift, not a 32bit one. | 
			
		
	
		
			
				
					|  |  |  | 		// MSVC: C4334, use 1i64 or cast to __int64. | 
			
		
	
		
			
				
					|  |  |  | 		// result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?) | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t mask = 1; | 
			
		
	
		
			
				
					|  |  |  | 		mask = mask << (index % 64); | 
			
		
	
		
			
				
					|  |  |  | 		mask = mask << (index & mod64mask); | 
			
		
	
		
			
				
					|  |  |  | 		if (value) { | 
			
		
	
		
			
				
					|  |  |  | 			bucket_array[bucket] |= mask; | 
			
		
	
		
			
				
					|  |  |  | 		} else { | 
			
		
	
	
		
			
				
					|  |  | @ -90,19 +120,21 @@ class BitVector { | 
			
		
	
		
			
				
					|  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	bool get(const uint_fast64_t index) { | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t bucket = index / 64; | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t bucket = index >> 6; | 
			
		
	
		
			
				
					|  |  |  | 		// Taking the step with mask is crucial as we NEED a 64bit shift, not a 32bit one. | 
			
		
	
		
			
				
					|  |  |  | 		// MSVC: C4334, use 1i64 or cast to __int64. | 
			
		
	
		
			
				
					|  |  |  | 		// result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?) | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t mask = 1; | 
			
		
	
		
			
				
					|  |  |  | 		mask = mask << (index % 64); | 
			
		
	
		
			
				
					|  |  |  | 		mask = mask << (index & mod64mask); | 
			
		
	
		
			
				
					|  |  |  | 		return ((bucket_array[bucket] & mask) == mask); | 
			
		
	
		
			
				
					|  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	// Operators | 
			
		
	
		
			
				
					|  |  |  | 	BitVector operator &(BitVector const &bv) { | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t minSize = (bv.bucket_count < this->bucket_count) ? bv.bucket_count : this->bucket_count; | 
			
		
	
		
			
				
					|  |  |  | 		BitVector result(minSize * 64); | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t minSize = | 
			
		
	
		
			
				
					|  |  |  | 				(bv.bucket_count < this->bucket_count) ? | 
			
		
	
		
			
				
					|  |  |  | 						bv.bucket_count : this->bucket_count; | 
			
		
	
		
			
				
					|  |  |  | 		BitVector result(minSize << 6); | 
			
		
	
		
			
				
					|  |  |  | 		for (uint_fast64_t i = 0; i < minSize; ++i) { | 
			
		
	
		
			
				
					|  |  |  | 			result.bucket_array[i] = this->bucket_array[i] & bv.bucket_array[i]; | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
	
		
			
				
					|  |  | @ -110,8 +142,10 @@ class BitVector { | 
			
		
	
		
			
				
					|  |  |  | 		return result; | 
			
		
	
		
			
				
					|  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  | 	BitVector operator |(BitVector const &bv) { | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t minSize = (bv.bucket_count < this->bucket_count) ? bv.bucket_count : this->bucket_count; | 
			
		
	
		
			
				
					|  |  |  | 		BitVector result(minSize * 64); | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t minSize = | 
			
		
	
		
			
				
					|  |  |  | 				(bv.bucket_count < this->bucket_count) ? | 
			
		
	
		
			
				
					|  |  |  | 						bv.bucket_count : this->bucket_count; | 
			
		
	
		
			
				
					|  |  |  | 		BitVector result(minSize << 6); | 
			
		
	
		
			
				
					|  |  |  | 		for (uint_fast64_t i = 0; i < minSize; ++i) { | 
			
		
	
		
			
				
					|  |  |  | 			result.bucket_array[i] = this->bucket_array[i] | bv.bucket_array[i]; | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
	
		
			
				
					|  |  | @ -120,8 +154,10 @@ class BitVector { | 
			
		
	
		
			
				
					|  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	BitVector operator ^(BitVector const &bv) { | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t minSize = (bv.bucket_count < this->bucket_count) ? bv.bucket_count : this->bucket_count; | 
			
		
	
		
			
				
					|  |  |  | 		BitVector result(minSize * 64); | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t minSize = | 
			
		
	
		
			
				
					|  |  |  | 				(bv.bucket_count < this->bucket_count) ? | 
			
		
	
		
			
				
					|  |  |  | 						bv.bucket_count : this->bucket_count; | 
			
		
	
		
			
				
					|  |  |  | 		BitVector result(minSize << 6); | 
			
		
	
		
			
				
					|  |  |  | 		for (uint_fast64_t i = 0; i < minSize; ++i) { | 
			
		
	
		
			
				
					|  |  |  | 			result.bucket_array[i] = this->bucket_array[i] ^ bv.bucket_array[i]; | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
	
		
			
				
					|  |  | @ -130,7 +166,7 @@ class BitVector { | 
			
		
	
		
			
				
					|  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	BitVector operator ~() { | 
			
		
	
		
			
				
					|  |  |  | 		BitVector result(this->bucket_count * 64); | 
			
		
	
		
			
				
					|  |  |  | 		BitVector result(this->bucket_count << 6); | 
			
		
	
		
			
				
					|  |  |  | 		for (uint_fast64_t i = 0; i < this->bucket_count; ++i) { | 
			
		
	
		
			
				
					|  |  |  | 			result.bucket_array[i] = ~this->bucket_array[i]; | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
	
		
			
				
					|  |  | @ -138,15 +174,30 @@ class BitVector { | 
			
		
	
		
			
				
					|  |  |  | 		return result; | 
			
		
	
		
			
				
					|  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	BitVector implies(BitVector& other) { | 
			
		
	
		
			
				
					|  |  |  | 		if (other.getSize() != this->getSize()) { | 
			
		
	
		
			
				
					|  |  |  | 			pantheios::log_ERROR( | 
			
		
	
		
			
				
					|  |  |  | 					"BitVector::implies: Throwing invalid argument exception for connecting bit vectors of different size."); | 
			
		
	
		
			
				
					|  |  |  | 			throw mrmc::exceptions::invalid_argument(); | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  | 		BitVector result(this->bucket_count << 6); | 
			
		
	
		
			
				
					|  |  |  | 		for (uint_fast64_t i = 0; i < this->bucket_count; ++i) { | 
			
		
	
		
			
				
					|  |  |  | 			result.bucket_array[i] = ~this->bucket_array[i] | 
			
		
	
		
			
				
					|  |  |  | 					| other.bucket_array[i]; | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 		return result; | 
			
		
	
		
			
				
					|  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	/*! | 
			
		
	
		
			
				
					|  |  |  | 	 * Returns the number of bits that are set (to one) in this bit vector. | 
			
		
	
		
			
				
					|  |  |  | 	 * @return The number of bits that are set (to one) in this bit vector. | 
			
		
	
		
			
				
					|  |  |  | 	 */ | 
			
		
	
		
			
				
					|  |  |  | 	uint_fast64_t getNumberOfSetBits() { | 
			
		
	
		
			
				
					|  |  |  | 		uint_fast64_t set_bits = 0; | 
			
		
	
		
			
				
					|  |  |  | 		for (uint_fast64_t i = 0; i < bucket_count; i++) { | 
			
		
	
		
			
				
					|  |  |  | 		for (uint_fast64_t i = 0; i < bucket_count; ++i) { | 
			
		
	
		
			
				
					|  |  |  | #ifdef __GNUG__ // check if we are using g++ and use built-in function if available | 
			
		
	
		
			
				
					|  |  |  | 			set_bits += __builtin_popcount (this->bucket_array[i]); | 
			
		
	
		
			
				
					|  |  |  | 			set_bits += __builtin_popcountll(this->bucket_array[i]); | 
			
		
	
		
			
				
					|  |  |  | #else | 
			
		
	
		
			
				
					|  |  |  | 			uint_fast32_t cnt; | 
			
		
	
		
			
				
					|  |  |  | 			uint_fast64_t bitset = this->bucket_array[i]; | 
			
		
	
	
		
			
				
					|  |  | @ -159,6 +210,10 @@ class BitVector { | 
			
		
	
		
			
				
					|  |  |  | 		return set_bits; | 
			
		
	
		
			
				
					|  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	uint_fast64_t getSize() { | 
			
		
	
		
			
				
					|  |  |  | 		return bucket_count; | 
			
		
	
		
			
				
					|  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	/*! | 
			
		
	
		
			
				
					|  |  |  | 	 * Returns the size of the bit vector in memory measured in bytes. | 
			
		
	
		
			
				
					|  |  |  | 	 * @return The size of the bit vector in memory measured in bytes. | 
			
		
	
	
		
			
				
					|  |  | @ -167,12 +222,14 @@ class BitVector { | 
			
		
	
		
			
				
					|  |  |  | 		return sizeof(*this) + sizeof(uint_fast64_t) * bucket_count; | 
			
		
	
		
			
				
					|  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  private: | 
			
		
	
		
			
				
					|  |  |  | private: | 
			
		
	
		
			
				
					|  |  |  | 	uint_fast64_t bucket_count; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	/*! Array containing the boolean bits for each node, 64bits/64nodes per element */ | 
			
		
	
		
			
				
					|  |  |  | 	uint_fast64_t* bucket_array; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	static const uint_fast64_t mod64mask = (1 << 6) - 1; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | }; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | } // namespace vector | 
			
		
	
	
		
			
				
					|  |  | 
 |