From 872f59fea509e8c8b65357a32e1a3733cf00ce21 Mon Sep 17 00:00:00 2001 From: dehnert Date: Thu, 22 Nov 2012 19:06:05 +0100 Subject: [PATCH 1/3] Added flag to CMakeLists.txt to enable setting the name of libboost_program_options as it has an additional suffix under Mac OS. --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 095283e69..98c97cdd1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,12 +117,15 @@ else() endif() if(Boost_FOUND) - set(BOOST_PROGRAM_OPTIONS_LIBRARY "boost_program_options") + if (NOT BOOST_PROGRAM_OPTIONS_LIBRARY) + set(BOOST_PROGRAM_OPTIONS_LIBRARY "boost_program_options") + endif() include_directories(${Boost_INCLUDE_DIRS}) if ((NOT Boost_LIBRARY_DIRS) OR ("${Boost_LIBRARY_DIRS}" STREQUAL "")) set(Boost_LIBRARY_DIRS "${Boost_INCLUDE_DIRS}/stage/lib") endif () + link_directories(${Boost_LIBRARY_DIRS}) endif(Boost_FOUND) From ee081fd570b375279f5f1874d7fa425effd9c2aa Mon Sep 17 00:00:00 2001 From: dehnert Date: Fri, 23 Nov 2012 11:31:17 +0100 Subject: [PATCH 2/3] Fixed a lot of memory access violations, memory leaks, warnings. Enabled -Werror for gcc, as there are currently no warnings. --- CMakeLists.txt | 2 +- src/models/atomic_propositions_labeling.h | 6 ++--- src/models/backward_transitions.h | 28 +++++++++++++---------- src/models/dtmc.h | 14 ++++++++++++ src/mrmc-cpp.cpp | 7 ++++-- src/parser/read_lab_file.cpp | 9 +++++--- src/parser/read_tra_file.cpp | 21 ++++++++++------- src/reward/reward_model.h | 2 +- src/sparse/static_sparse_matrix.h | 12 ++++------ 9 files changed, 62 insertions(+), 39 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f273e7f97..7065c87db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ endif() #Configurations for GCC if(CMAKE_COMPILER_IS_GNUCC) - set (CMAKE_CXX_FLAGS "-std=c++0x -Wall -pedantic") + set (CMAKE_CXX_FLAGS "-std=c++0x -Wall -Werror -pedantic") # Turn on popcnt instruction if possible if (USE_POPCNT) diff --git a/src/models/atomic_propositions_labeling.h b/src/models/atomic_propositions_labeling.h index 83b7ced16..86cb93e11 100644 --- a/src/models/atomic_propositions_labeling.h +++ b/src/models/atomic_propositions_labeling.h @@ -58,7 +58,7 @@ public: * @param state_count The number of states of the model. * @param ap_count The number of atomic propositions. */ - AtomicPropositionsLabeling(const uint_fast32_t state_count, const uint_fast32_t ap_count) + AtomicPropositionsLabeling(const uint_fast32_t state_count, const uint_fast32_t ap_count) : state_count(state_count), ap_count(ap_count), aps_current(0) { this->single_labelings = new SingleAtomicPropositionLabeling*[ap_count]; for (uint_fast32_t i = 0; i < ap_count; ++i) { @@ -78,8 +78,7 @@ public: name_to_labeling_map(atomic_propositions_labeling.name_to_labeling_map) { this->single_labelings = new SingleAtomicPropositionLabeling*[ap_count]; for (uint_fast32_t i = 0; i < ap_count; ++i) { - this->single_labelings[i] = new SingleAtomicPropositionLabeling( - *atomic_propositions_labeling.single_labelings[i]); + this->single_labelings[i] = new SingleAtomicPropositionLabeling(*atomic_propositions_labeling.single_labelings[i]); } } @@ -89,7 +88,6 @@ public: */ virtual ~AtomicPropositionsLabeling() { // delete all the single atomic proposition labelings in the map - MAP::iterator it; for (uint_fast32_t i = 0; i < ap_count; ++i) { delete this->single_labelings[i]; this->single_labelings[i] = NULL; diff --git a/src/models/backward_transitions.h b/src/models/backward_transitions.h index a99f0ae3e..2f6d3d49a 100644 --- a/src/models/backward_transitions.h +++ b/src/models/backward_transitions.h @@ -35,43 +35,47 @@ public: * @param transition_matrix The (0-based) matrix representing the transition * relation. */ - BackwardTransitions(mrmc::sparse::StaticSparseMatrix* transitionMatrix) - : numberOfStates(transitionMatrix->getRowCount()), - numberOfNonZeroTransitions(transitionMatrix->getNonZeroEntryCount()) { - this->state_indices_list = new uint_fast64_t[numberOfStates + 1]; + BackwardTransitions(mrmc::sparse::StaticSparseMatrix* transitionMatrix) { + numberOfNonZeroTransitions = transitionMatrix->getNonZeroEntryCount(); this->predecessor_list = new uint_fast64_t[numberOfNonZeroTransitions]; + + numberOfStates = transitionMatrix->getRowCount(); + this->state_indices_list = new uint_fast64_t[numberOfStates + 1]; // First, we need to count how many backward transitions each state has. // NOTE: We disregard the diagonal here, as we only consider "true" // predecessors. - for (uint_fast64_t i = 0; i <= numberOfStates; i++) { + for (uint_fast64_t i = 0; i < numberOfStates; i++) { for (auto rowIt = transitionMatrix->beginConstColumnNoDiagIterator(i); rowIt != transitionMatrix->endConstColumnNoDiagIterator(i); ++rowIt) { this->state_indices_list[*rowIt + 1]++; } } // Now compute the accumulated offsets. - for (uint_fast64_t i = 1; i <= numberOfStates; i++) { + for (uint_fast64_t i = 1; i < numberOfStates; i++) { this->state_indices_list[i] = this->state_indices_list[i - 1] + this->state_indices_list[i]; } // Put a sentinel element at the end of the indices list. This way, // for each state i the range of indices can be read off between // state_indices_list[i] and state_indices_list[i + 1]. - this->state_indices_list[numberOfStates + 1] = numberOfNonZeroTransitions; + this->state_indices_list[numberOfStates] = numberOfNonZeroTransitions; // Create an array that stores the next index for each state. Initially // this corresponds to the previously computed accumulated offsets. - uint_fast64_t* next_state_index_list = new uint_fast64_t[numberOfStates + 1]; - memcpy(next_state_index_list, state_indices_list, (numberOfStates + 1) * sizeof(uint_fast64_t)); + uint_fast64_t* next_state_index_list = new uint_fast64_t[numberOfStates]; + memcpy(next_state_index_list, state_indices_list, numberOfStates * sizeof(uint_fast64_t)); // Now we are ready to actually fill in the list of predecessors for // every state. Again, we start by considering all but the last row. - for (uint_fast64_t i = 0; i <= numberOfStates; i++) { + for (uint_fast64_t i = 0; i < numberOfStates; i++) { for (auto rowIt = transitionMatrix->beginConstColumnNoDiagIterator(i); rowIt != transitionMatrix->endConstColumnNoDiagIterator(i); ++rowIt) { this->predecessor_list[next_state_index_list[*rowIt]++] = i; } } + + // Now we can dispose of the auxiliary array. + delete[] next_state_index_list; } //! Destructor @@ -79,10 +83,10 @@ public: * Destructor. Frees the internal storage. */ ~BackwardTransitions() { - if (this->predecessor_list != NULL) { + if (this->predecessor_list != nullptr) { delete[] this->predecessor_list; } - if (this->state_indices_list != NULL) { + if (this->state_indices_list != nullptr) { delete[] this->state_indices_list; } } diff --git a/src/models/dtmc.h b/src/models/dtmc.h index afe4b3fd2..c01e341b1 100644 --- a/src/models/dtmc.h +++ b/src/models/dtmc.h @@ -55,6 +55,20 @@ public: pantheios::log_DEBUG("Copy constructor of DTMC invoked."); } + //! Destructor + /*! + * Destructor. Frees the matrix and labeling associated with this DTMC. + * + */ + ~Dtmc() { + if (this->probability_matrix != nullptr) { + delete this->probability_matrix; + } + if (this->state_labeling != nullptr) { + delete this->state_labeling; + } + } + /*! * Returns the state space size of the DTMC. * @return The size of the state space of the DTMC. diff --git a/src/mrmc-cpp.cpp b/src/mrmc-cpp.cpp index 2de514550..2dbee8c29 100644 --- a/src/mrmc-cpp.cpp +++ b/src/mrmc-cpp.cpp @@ -42,11 +42,12 @@ int main(const int argc, const char* argv[]) { try { - s = new mrmc::settings::Settings(argc, argv, NULL); + s = new mrmc::settings::Settings(argc, argv, nullptr); } catch (mrmc::exceptions::InvalidSettings) { std::cout << "Could not recover from settings error, terminating." << std::endl; + delete s; return 1; } @@ -65,7 +66,9 @@ int main(const int argc, const char* argv[]) { mrmc::models::AtomicPropositionsLabeling* labeling = mrmc::parser::read_lab_file(probMatrix->getRowCount(), s->getString("labfile").c_str()); mrmc::models::Dtmc dtmc(probMatrix, labeling); - + if (s != nullptr) { + delete s; + } return 0; } diff --git a/src/parser/read_lab_file.cpp b/src/parser/read_lab_file.cpp index 2a3742afe..35210d5a6 100644 --- a/src/parser/read_lab_file.cpp +++ b/src/parser/read_lab_file.cpp @@ -25,9 +25,12 @@ # define STRTOK_FUNC strtok_r #endif +// Only disable the warning if we are not using GCC, because +// GCC does not know this pragma and raises a warning +#ifndef __GNUG__ // Disable C4996 - This function or variable may be unsafe. #pragma warning(disable:4996) - +#endif namespace mrmc { @@ -150,7 +153,7 @@ mrmc::models::AtomicPropositionsLabeling * read_lab_file(int node_count, const c while (fgets(s, BUFFER_SIZE, P)) { char * token = NULL; - uint_fast32_t node = 0; + unsigned int node = 0; /* First token has to be a number identifying the node, * hence it is treated differently from the other tokens. */ @@ -167,7 +170,7 @@ mrmc::models::AtomicPropositionsLabeling * read_lab_file(int node_count, const c if (token == NULL) { break; } - result->addAtomicPropositionToState(token, node); + result->addAtomicPropositionToState(token, static_cast(node)); } while (token != NULL); } diff --git a/src/parser/read_tra_file.cpp b/src/parser/read_tra_file.cpp index 5d652758b..ca4a59cc5 100644 --- a/src/parser/read_tra_file.cpp +++ b/src/parser/read_tra_file.cpp @@ -26,8 +26,12 @@ namespace mrmc { namespace parser{ +// Only disable the warning if we are not using GCC, because +// GCC does not know this pragma and raises a warning +#ifndef __GNUG__ // Disable C4996 - This function or variable may be unsafe. #pragma warning(disable:4996) +#endif /*! * This method does the first pass through the .tra file and computes @@ -46,7 +50,7 @@ static uint_fast32_t make_first_pass(FILE* p) { throw exceptions::file_IO_exception ("make_first_pass: File not readable (this should be checked before calling this function!)"); } char s[BUFFER_SIZE]; //String buffer - uint_fast32_t rows=0, non_zero=0; + int rows=0, non_zero=0; //Reading No. of states if (fgets(s, BUFFER_SIZE, p) != NULL) { @@ -69,7 +73,7 @@ static uint_fast32_t make_first_pass(FILE* p) { //And increase number of transitions while (NULL != fgets( s, BUFFER_SIZE, p )) { - uint_fast32_t row=0, col=0; + int row=0, col=0; double val=0.0; if (sscanf( s, "%d%d%lf", &row, &col, &val ) != 3) { (void)fclose(p); @@ -80,7 +84,7 @@ static uint_fast32_t make_first_pass(FILE* p) { --non_zero; } } - return non_zero; + return static_cast(non_zero); } @@ -95,7 +99,8 @@ static uint_fast32_t make_first_pass(FILE* p) { sparse::StaticSparseMatrix * read_tra_file(const char * filename) { FILE *p = NULL; char s[BUFFER_SIZE]; - uint_fast32_t rows, non_zero; + uint_fast64_t non_zero = 0; + int rows = 0; sparse::StaticSparseMatrix *sp = NULL; p = fopen(filename, "r"); @@ -121,7 +126,7 @@ sparse::StaticSparseMatrix * read_tra_file(const char * filename) { * Note that the result is not used in this function as make_first_pass() * computes the relevant number (non_zero) */ - uint_fast32_t nnz=0; + int nnz = 0; if ((fgets(s, BUFFER_SIZE, p) == NULL) || (sscanf(s, "TRANSITIONS %d", &nnz) == 0)) { (void)fclose(p); throw mrmc::exceptions::wrong_file_format(); @@ -135,7 +140,7 @@ sparse::StaticSparseMatrix * read_tra_file(const char * filename) { * Memory for diagonal elements is automatically allocated, hence only the number of non-diagonal * non-zero elements has to be specified (which is non_zero, computed by make_first_pass) */ - sp = new sparse::StaticSparseMatrix(rows + 1); + sp = new sparse::StaticSparseMatrix(static_cast(rows) + 1); if ( NULL == sp ) { throw std::bad_alloc(); return NULL; @@ -144,7 +149,7 @@ sparse::StaticSparseMatrix * read_tra_file(const char * filename) { //Reading transitions (one per line) and saving the results in the matrix while (NULL != fgets(s, BUFFER_SIZE, p )) { - uint_fast32_t row=0, col=0; + int row=0, col=0; double val = 0.0; if (sscanf(s, "%d%d%lf", &row, &col, &val) != 3) { (void)fclose(p); @@ -158,7 +163,7 @@ sparse::StaticSparseMatrix * read_tra_file(const char * filename) { " to position ", pantheios::integer(row), " x ", pantheios::integer(col)); - sp->addNextValue(row,col,val); + sp->addNextValue(static_cast(row),static_cast(col),static_cast(val)); } (void)fclose(p); diff --git a/src/reward/reward_model.h b/src/reward/reward_model.h index 52b2039b0..45a4a77d6 100644 --- a/src/reward/reward_model.h +++ b/src/reward/reward_model.h @@ -27,7 +27,7 @@ class RewardModel { typedef const DataClass& crDataClass; public: - RewardModel(const uint_fast32_t state_count, const DataClass& null_value) : null_value(null_value), state_count(state_count) { + RewardModel(const uint_fast32_t state_count, const DataClass& null_value) : state_count(state_count), null_value(null_value) { this->reward_vector = new VectorImpl>(this->state_count); // init everything to zero diff --git a/src/sparse/static_sparse_matrix.h b/src/sparse/static_sparse_matrix.h index b778fd352..621c1a8a1 100644 --- a/src/sparse/static_sparse_matrix.h +++ b/src/sparse/static_sparse_matrix.h @@ -47,7 +47,7 @@ public: * @see hasError() */ enum MatrixStatus { - Error = -1, UnInitialized = 0, Initialized = 1, ReadReady = 2, + Error = -1, UnInitialized = 0, Initialized = 1, ReadReady = 2 }; //! Constructor @@ -56,11 +56,7 @@ public: * @param rows The number of rows of the matrix */ StaticSparseMatrix(uint_fast64_t rows) - : internalStatus(MatrixStatus::UnInitialized), - currentSize(0), lastRow(0), valueStorage(nullptr), - diagonalStorage(nullptr), columnIndications(nullptr), - rowIndications(nullptr), rowCount(rows), nonZeroEntryCount(0) { } - + : rowCount(rows), nonZeroEntryCount(0), valueStorage(nullptr), diagonalStorage(nullptr), columnIndications(nullptr), rowIndications(nullptr), internalStatus(MatrixStatus::UnInitialized), currentSize(0), lastRow(0) { } //! Copy Constructor /*! * Copy Constructor. Performs a deep copy of the given sparse matrix. @@ -322,7 +318,7 @@ public: // Fill in the missing entries in the row_indications array. // (Can happen because of empty rows at the end.) if (lastRow != rowCount) { - for (uint_fast64_t i = lastRow + 1; i <= rowCount; ++i) { + for (uint_fast64_t i = lastRow + 1; i < rowCount; ++i) { rowIndications[i] = currentSize; } } @@ -331,7 +327,7 @@ public: // array. This eases iteration work, as now the indices of row i // are always between row_indications[i] and row_indications[i + 1], // also for the first and last row. - rowIndications[rowCount + 1] = nonZeroEntryCount; + rowIndications[rowCount] = nonZeroEntryCount; setState(MatrixStatus::ReadReady); } From 5a8c2a8d0e55b4175b2058262611ffeaa7f58164 Mon Sep 17 00:00:00 2001 From: dehnert Date: Fri, 23 Nov 2012 13:05:09 +0100 Subject: [PATCH 3/3] Added iterator functionality to bit vector. Minor cosmetics here and there. --- src/models/backward_transitions.h | 1 - src/models/dtmc.h | 6 +- src/mrmc-cpp.cpp | 2 + src/parser/read_lab_file.cpp | 3 +- src/vector/bitvector.h | 125 ++++++++++++++++++++++-------- 5 files changed, 97 insertions(+), 40 deletions(-) diff --git a/src/models/backward_transitions.h b/src/models/backward_transitions.h index 2f6d3d49a..52311d3f5 100644 --- a/src/models/backward_transitions.h +++ b/src/models/backward_transitions.h @@ -100,7 +100,6 @@ public: return this->predecessor_list + this->state_indices_list[state]; } - /*! * Returns an iterator referring to the element after the predecessors of * the given state. diff --git a/src/models/dtmc.h b/src/models/dtmc.h index c01e341b1..5a2bb8fd0 100644 --- a/src/models/dtmc.h +++ b/src/models/dtmc.h @@ -38,9 +38,8 @@ public: * @param state_labeling The labeling that assigns a set of atomic * propositions to each state. */ - Dtmc(mrmc::sparse::StaticSparseMatrix* probability_matrix, - mrmc::models::AtomicPropositionsLabeling* state_labeling) : - backward_transitions(probability_matrix) { + Dtmc(mrmc::sparse::StaticSparseMatrix* probability_matrix, mrmc::models::AtomicPropositionsLabeling* state_labeling) + : backward_transitions(probability_matrix) { this->probability_matrix = probability_matrix; this->state_labeling = state_labeling; } @@ -58,7 +57,6 @@ public: //! Destructor /*! * Destructor. Frees the matrix and labeling associated with this DTMC. - * */ ~Dtmc() { if (this->probability_matrix != nullptr) { diff --git a/src/mrmc-cpp.cpp b/src/mrmc-cpp.cpp index 2dbee8c29..670920765 100644 --- a/src/mrmc-cpp.cpp +++ b/src/mrmc-cpp.cpp @@ -66,6 +66,8 @@ int main(const int argc, const char* argv[]) { mrmc::models::AtomicPropositionsLabeling* labeling = mrmc::parser::read_lab_file(probMatrix->getRowCount(), s->getString("labfile").c_str()); mrmc::models::Dtmc dtmc(probMatrix, labeling); + dtmc.printModelInformationToStream(std::cout); + if (s != nullptr) { delete s; } diff --git a/src/parser/read_lab_file.cpp b/src/parser/read_lab_file.cpp index 35210d5a6..99dfc6fa5 100644 --- a/src/parser/read_lab_file.cpp +++ b/src/parser/read_lab_file.cpp @@ -19,6 +19,8 @@ #include #include +#include + #ifdef WIN32 # define STRTOK_FUNC strtok_s #else @@ -172,7 +174,6 @@ mrmc::models::AtomicPropositionsLabeling * read_lab_file(int node_count, const c } result->addAtomicPropositionToState(token, static_cast(node)); } while (token != NULL); - } fclose(P); diff --git a/src/vector/bitvector.h b/src/vector/bitvector.h index 74fd0abf1..334b5ba78 100644 --- a/src/vector/bitvector.h +++ b/src/vector/bitvector.h @@ -13,24 +13,51 @@ #include "src/exceptions/invalid_argument.h" #include "src/exceptions/out_of_range.h" +#include + 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,47 +120,53 @@ 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]; } - + 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]; } - + 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]; } - + return result; } 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