Browse Source

Added conversion routines from/to Eigen Sparse Matrix Format

Added tests for aforementioned conversion routines.
Changed call parameters for sparse/static_sparse_matrix.h
Minor ICL 13.x changes.
tempestpy_adaptions
PBerger 12 years ago
parent
commit
a4f5794419
  1. 6
      resources/3rdparty/eigen/Eigen/src/SparseCore/SparseMatrixBase.h
  2. 4
      resources/3rdparty/stlsoft-1.9.116/include/stlsoft/stlsoft.h
  3. 4
      src/parser/read_tra_file.cpp
  4. 362
      src/sparse/static_sparse_matrix.h
  5. 196
      test/sparse/static_sparse_matrix_test.cpp

6
resources/3rdparty/eigen/Eigen/src/SparseCore/SparseMatrixBase.h

@ -164,7 +164,11 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
/** \returns the size of the inner dimension according to the storage order,
* i.e., the number of rows for a columns major matrix, and the number of cols otherwise */
Index innerSize() const { return (int(Flags)&RowMajorBit) ? this->cols() : this->rows(); }
bool isRowMajorMatrix() const {
return (int(Flags)&RowMajorBit);
}
bool isRValue() const { return m_isRValue; }
Derived& markAsRValue() { m_isRValue = true; return derived(); }

4
resources/3rdparty/stlsoft-1.9.116/include/stlsoft/stlsoft.h

@ -554,8 +554,10 @@
# define STLSOFT_COMPILER_VERSION_STRING "Intel C/C++ 11.0"
# elif (__INTEL_COMPILER >= 1200) && (__INTEL_COMPILER < 1300)
# define STLSOFT_COMPILER_VERSION_STRING "Intel C/C++ 12.x"
# elif (__INTEL_COMPILER >= 1300) && (__INTEL_COMPILER < 1400)
# define STLSOFT_COMPILER_VERSION_STRING "Intel C/C++ 13.x"
# else /* ? __INTEL_COMPILER */
# error Only Intel C++ Compiler versions 6.0, 7.0(/7.1), 8.0, 9.0, 10.0, 11.0 and 12.x currently supported by the STLSoft libraries
# error Only Intel C++ Compiler versions 6.0, 7.0(/7.1), 8.0, 9.0, 10.0, 11.0, 12.x and 13.x currently supported by the STLSoft libraries
# endif /* __INTEL_COMPILER */
#elif defined(__MWERKS__)

4
src/parser/read_tra_file.cpp

@ -135,12 +135,12 @@ sparse::StaticSparseMatrix<double> * 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<double>(rows,non_zero);
sp = new sparse::StaticSparseMatrix<double>(rows);
if ( NULL == sp ) {
throw std::bad_alloc();
return NULL;
}
sp->initialize();
sp->initialize(non_zero);
//Reading transitions (one per line) and saving the results in the matrix
while (NULL != fgets(s, BUFFER_SIZE, p )) {

362
src/sparse/static_sparse_matrix.h

@ -13,6 +13,7 @@
#include "src/exceptions/out_of_range.h"
#include "Eigen/Sparse"
#include "src/sparse/eigen_sparse_additions.h"
namespace mrmc {
@ -46,13 +47,13 @@ class StaticSparseMatrix {
//! Constructor
/*!
\param rows Row-Count and therefore column-count of the symmetric matrix
\param non_zero_entries The exact count of entries that will be submitted through addNextValue *excluding* those on the diagonal (A_{i,j} with i = j)
\param rows Row-Count and therefore column-count of the square matrix
*/
StaticSparseMatrix(uint_fast32_t rows, uint_fast32_t non_zero_entries) {
setState(MatrixStatus::UnInitialized);
StaticSparseMatrix(uint_fast32_t rows) {
// Using direct access instead of setState() because of undefined initialization value
// setState() stays in Error should Error be the current value
internal_status = MatrixStatus::UnInitialized;
current_size = 0;
storage_size = 0;
value_storage = NULL;
diagonal_storage = NULL;
@ -60,7 +61,7 @@ class StaticSparseMatrix {
row_indications = NULL;
row_count = rows;
non_zero_entry_count = non_zero_entries;
non_zero_entry_count = 0;
//initialize(rows, non_zero_entries);
}
@ -85,98 +86,123 @@ class StaticSparseMatrix {
}
}
//! Getter for saving matrix entry A_{row,col} to target
/*!
Getter function for the matrix. This function does not check the internal status for errors for performance reasons.
\param row 1-based index of the requested row
\param col 1-based index of the requested column
\param target pointer to where the result will be stored
\return True iff the value was set, false otherwise. On false, 0 will be written to *target.
*/
inline bool getValue(uint_fast32_t row, uint_fast32_t col, T* const target) {
if (row == col) {
// storage is row_count + 1 large for direct access without the -1
*target = diagonal_storage[row];
return true;
}
if ((row > row_count) || (col > row_count) || (row == 0) || (col == 0)) {
throw mrmc::exceptions::out_of_range("mrmc::StaticSparseMatrix::getValue: row or col not in 1 .. rows");
}
uint_fast32_t row_start = row_indications[row - 1];
uint_fast32_t row_end = row_indications[row];
while (row_start < row_end) {
if (column_indications[row_start] == col) {
*target = value_storage[row_start];
return true;
}
if (column_indications[row_start] > col) {
break;
}
row_start++;
}
*target = 0;
return false;
}
//! Mandatory initialization of the matrix
//! Mandatory initialization of the matrix, variant for initialize(), addNextValue() and finalize()
/*!
Mandatory initialization of the matrix, must be called before using any other member function.
This version is to be used together with addNextValue().
For initialization from a Eigen SparseMatrix, use initialize(Eigen::SparseMatrix<T> &).
\param non_zero_entries The exact count of entries that will be submitted through addNextValue *excluding* those on the diagonal (A_{i,j} with i = j)
*/
void initialize() {
void initialize(uint_fast32_t non_zero_entries) {
if (internal_status != MatrixStatus::UnInitialized) {
triggerErrorState();
pantheios::log_ERROR("StaticSparseMatrix::initialize: Throwing invalid state for status flag != 0 (is ", pantheios::integer(internal_status)," - Already initialized?");
throw mrmc::exceptions::invalid_state("StaticSparseMatrix::initialize: Invalid state for status flag != 0 - Already initialized?");
triggerErrorState();
} else if (row_count == 0) {
triggerErrorState();
pantheios::log_ERROR("StaticSparseMatrix::initialize: Throwing invalid_argument for row_count = 0");
throw mrmc::exceptions::invalid_argument("mrmc::StaticSparseMatrix::initialize: Matrix with 0 rows is not reasonable");
} else if (((row_count * row_count) - row_count) < non_zero_entries) {
triggerErrorState();
} else if (((row_count * row_count) - row_count) < non_zero_entry_count) {
pantheios::log_ERROR("StaticSparseMatrix::initialize: Throwing invalid_argument: More non-zero entries than entries in target matrix");
throw mrmc::exceptions::invalid_argument("mrmc::StaticSparseMatrix::initialize: More non-zero entries than entries in target matrix");
triggerErrorState();
} else {
storage_size = non_zero_entry_count;
non_zero_entry_count = non_zero_entries;
last_row = 0;
//value_storage = static_cast<T*>(calloc(storage_size, sizeof(*value_storage)));
value_storage = new (std::nothrow) T[storage_size]();
//column_indications = static_cast<uint_fast32_t*>(calloc(storage_size, sizeof(*column_indications)));
column_indications = new (std::nothrow) uint_fast32_t[storage_size]();
//row_indications = static_cast<uint_fast32_t*>(calloc(row_count + 1, sizeof(*row_indications)));
row_indications = new (std::nothrow) uint_fast32_t[row_count + 1]();
// row_count + 1 so that access with 1-based indices can be direct without the overhead of a -1 each time
//diagonal_storage = static_cast<T*>(calloc(row_count + 1, sizeof(*diagonal_storage)));
diagonal_storage = new (std::nothrow) T[row_count + 1]();
if ((value_storage == NULL) || (column_indications == NULL) || (row_indications == NULL) || (diagonal_storage == NULL)) {
if (!prepareInternalStorage()) {
triggerErrorState();
pantheios::log_ERROR("StaticSparseMatrix::initialize: Throwing bad_alloc: memory allocation failed");
throw std::bad_alloc();
triggerErrorState();
} else {
setState(MatrixStatus::Initialized);
}
}
}
//! Mandatory initialization of the matrix, variant for initialize(), addNextValue() and finalize()
/*!
Mandatory initialization of the matrix, must be called before using any other member function.
This version is to be used for initialization from a Eigen SparseMatrix, use initialize(uint_fast32_t) for addNextValue.
\param eigen_sparse_matrix The Eigen Sparse Matrix to be copied/ initialized from. MUST BE in compressed form!
*/
template<typename _Scalar, int _Options, typename _Index>
void initialize(const Eigen::SparseMatrix<_Scalar, _Options, _Index> &eigen_sparse_matrix) {
if (!eigen_sparse_matrix.isCompressed()) {
triggerErrorState();
pantheios::log_ERROR("StaticSparseMatrix::initialize: Throwing invalid_argument: eigen_sparse_matrix is not in Compressed form.");
throw mrmc::exceptions::invalid_argument("StaticSparseMatrix::initialize: Throwing invalid_argument: eigen_sparse_matrix is not in Compressed form.");
}
non_zero_entry_count = getEigenSparseMatrixCorrectNonZeroEntryCount(eigen_sparse_matrix);
last_row = 0;
if (!prepareInternalStorage()) {
triggerErrorState();
pantheios::log_ERROR("StaticSparseMatrix::initialize: Throwing bad_alloc: memory allocation failed");
throw std::bad_alloc();
} else {
// easy case, we can simply copy the data
// RowMajor: Easy, ColMajor: Hmm. But how to detect?
const T* valuePtr = eigen_sparse_matrix.valuePtr();
const int_fast32_t* indexPtr = eigen_sparse_matrix.innerIndexPtr();
const int_fast32_t* outerPtr = eigen_sparse_matrix.outerIndexPtr();
const int_fast32_t entryCount = eigen_sparse_matrix.nonZeros();
const int_fast32_t outerCount = eigen_sparse_matrix.outerSize();
if (isEigenRowMajor(eigen_sparse_matrix)) {
// Easy case, all data can be copied with some minor changes.
// We have to separate diagonal entries from others
for (int row = 1; row <= outerCount; ++row) {
for (int col = outerPtr[row - 1]; col < outerPtr[row]; ++col) {
addNextValue(row, indexPtr[col] + 1, valuePtr[col]);
}
}
} else {
// temp copies, anyone?
const int eigen_col_count = eigen_sparse_matrix.cols();
const int eigen_row_count = eigen_sparse_matrix.rows();
// initialise all column-start positions to known lower boundarys
int_fast32_t* positions = new int_fast32_t[eigen_col_count]();
for (int i = 0; i < eigen_col_count; ++i) {
positions[i] = outerPtr[i];
}
int i = 0;
int currentRow = 0;
int currentColumn = 0;
while (i < entryCount) {
if ((positions[currentColumn] < outerPtr[currentColumn + 1]) && (indexPtr[positions[currentColumn]] == currentRow)) {
addNextValue(currentRow + 1, currentColumn + 1, valuePtr[positions[currentColumn]]);
// one more found
++i;
// mark this position as "used"
++positions[currentColumn];
}
// advance to next column
++currentColumn;
if (currentColumn == eigen_col_count) {
currentColumn = 0;
++currentRow;
}
}
}
setState(MatrixStatus::Initialized);
}
}
//! Linear Setter for matrix entry A_{row, col} to value
/*!
Linear Setter function for matrix entry A_{row, col} to value. Must be called consecutively for each element in a row in ascending order of columns AND in ascending order of rows.
Diagonal entries may be set at any time.
*/
void addNextValue(const uint_fast32_t row, const uint_fast32_t col, const T value) {
void addNextValue(const uint_fast32_t row, const uint_fast32_t col, const T &value) {
if ((row > row_count) || (col > row_count) || (row == 0) || (col == 0)) {
pantheios::log_ERROR("StaticSparseMatrix::addNextValue: Throwing out_of_range: row or col not in 1 .. rows");
throw mrmc::exceptions::out_of_range("mrmc::StaticSparseMatrix::addNextValue: row or col not in 1 .. rows");
triggerErrorState();
pantheios::log_ERROR("StaticSparseMatrix::addNextValue: Throwing out_of_range: row or col not in 1 .. rows (is ", pantheios::integer(row), " x ", pantheios::integer(col), ", max is ", pantheios::integer(row_count), " x ", pantheios::integer(row_count), ").");
throw mrmc::exceptions::out_of_range("StaticSparseMatrix::addNextValue: row or col not in 1 .. rows");
}
if (row == col) {
@ -199,13 +225,13 @@ class StaticSparseMatrix {
void finalize() {
if (!isInitialized()) {
triggerErrorState();
pantheios::log_ERROR("StaticSparseMatrix::finalize: Throwing invalid state for internal state not Initialized (is ", pantheios::integer(internal_status)," - Already finalized?");
throw mrmc::exceptions::invalid_state("StaticSparseMatrix::finalize: Invalid state for internal state not Initialized - Already finalized?");
} else if (current_size != non_zero_entry_count) {
triggerErrorState();
} else if (storage_size != current_size) {
pantheios::log_ERROR("StaticSparseMatrix::finalize: Throwing invalid_state: Wrong call count for addNextValue");
throw mrmc::exceptions::invalid_state("mrmc::StaticSparseMatrix::finalize: Wrong call count for addNextValue");
triggerErrorState();
throw mrmc::exceptions::invalid_state("StaticSparseMatrix::finalize: Wrong call count for addNextValue");
} else {
if (last_row != row_count) {
for (uint_fast32_t i = last_row; i < row_count; ++i) {
@ -213,12 +239,52 @@ class StaticSparseMatrix {
}
}
row_indications[row_count] = storage_size;
row_indications[row_count] = non_zero_entry_count;
setState(MatrixStatus::ReadReady);
}
}
//! Getter for saving matrix entry A_{row,col} to target
/*!
Getter function for the matrix. This function does not check the internal status for errors for performance reasons.
\param row 1-based index of the requested row
\param col 1-based index of the requested column
\param target pointer to where the result will be stored
\return True iff the value was set, false otherwise. On false, 0 will be written to *target.
*/
inline bool getValue(uint_fast32_t row, uint_fast32_t col, T* const target) {
if (row == col) {
// storage is row_count + 1 large for direct access without the -1
*target = diagonal_storage[row];
return true;
}
if ((row > row_count) || (col > row_count) || (row == 0) || (col == 0)) {
pantheios::log_ERROR("StaticSparseMatrix::getValue: row or col not in 1 .. rows (is ", pantheios::integer(row), " x ", pantheios::integer(col), ", max is ", pantheios::integer(row_count), " x ", pantheios::integer(row_count), ").");
throw mrmc::exceptions::out_of_range("StaticSparseMatrix::getValue: row or col not in 1 .. rows");
return false;
}
uint_fast32_t row_start = row_indications[row - 1];
uint_fast32_t row_end = row_indications[row];
while (row_start < row_end) {
if (column_indications[row_start] == col) {
*target = value_storage[row_start];
return true;
}
if (column_indications[row_start] > col) {
break;
}
row_start++;
}
*target = 0;
return false;
}
uint_fast32_t getRowCount() const {
return row_count;
}
@ -243,16 +309,24 @@ class StaticSparseMatrix {
return (internal_status == MatrixStatus::Error);
}
//! Converts this matrix to an equivalent sparse matrix in Eigens format.
/*!
Exports this sparse matrix to Eigens SparseMatrix format.
Required this matrix to be in the ReadReady state.
@return The Eigen SparseMatrix
*/
Eigen::SparseMatrix<T> toEigenSparseMatrix() {
Eigen::SparseMatrix<T> mat(row_count, row_count);
if (!isReadReady()) {
triggerErrorState();
pantheios::log_ERROR("StaticSparseMatrix::toEigenSparseMatrix: Throwing invalid state for internal state not ReadReady (is ", pantheios::integer(internal_status),").");
throw mrmc::exceptions::invalid_state("StaticSparseMatrix::toEigenSparseMatrix: Invalid state for internal state not ReadReady.");
triggerErrorState();
} else {
typedef Eigen::Triplet<double> ETd;
std::vector<ETd> tripletList;
typedef Eigen::Triplet<int> IntTriplet;
std::vector<IntTriplet> tripletList;
tripletList.reserve(non_zero_entry_count + row_count);
uint_fast32_t row_start;
@ -261,12 +335,12 @@ class StaticSparseMatrix {
row_start = row_indications[row - 1];
row_end = row_indications[row];
while (row_start < row_end) {
tripletList.push_back(ETd(row - 1, column_indications[row_start] - 1, value_storage[row_start]));
tripletList.push_back(IntTriplet(row - 1, column_indications[row_start] - 1, value_storage[row_start]));
++row_start;
}
}
for (uint_fast32_t i = 1; i <= row_count; ++i) {
tripletList.push_back(ETd(i, i, diagonal_storage[i]));
tripletList.push_back(IntTriplet(i, i, diagonal_storage[i]));
}
mat.setFromTriplets(tripletList.begin(), tripletList.end());
@ -276,8 +350,72 @@ class StaticSparseMatrix {
return mat;
}
//! Alternative way to initialize this matrix instead of using initialize(), addNextValue() and finalize().
/*!
Initializes the matrix from the given eigen_sparse_matrix. Replaces the calls to initialize(), addNextValue() and finalize().
Requires eigen_sparse_matrix to have at most a size of rows x rows and not more than non_zero_entries on non-diagonal fields.
To calculate the non-zero-entry count on only non-diagonal fields, you may use getEigenSparseMatrixCorrectNonZeroEntryCount().
In most cases, it may be easier to use the alternative constructor StaticSparseMatrix(const Eigen::SparseMatrix<T> eigen_sparse_matrix).
@param eigen_sparse_matrix the Eigen Sparse Matrix from which this matrix should be initalized.
@see getEigenSparseMatrixCorrectNonZeroEntryCount()
@see StaticSparseMatrix(const Eigen::SparseMatrix<T>)
*/
bool fromEigenSparseMatrix(const Eigen::SparseMatrix<T> eigen_sparse_matrix) {
if (getState() != MatrixStatus::UnInitialized) {
triggerErrorState();
pantheios::log_ERROR("StaticSparseMatrix::fromEigenSparseMatrix: Throwing invalid state for internal state not UnInitialized (is ", pantheios::integer(internal_status),").");
throw mrmc::exceptions::invalid_state("StaticSparseMatrix::fromEigenSparseMatrix: Invalid state for internal state not UnInitialized.");
return false;
}
int_fast32_t eigen_row_count = eigen_sparse_matrix.rows();
int_fast32_t eigen_col_count = eigen_sparse_matrix.cols();
if ((eigen_row_count > row_count) || (eigen_col_count > row_count)) {
triggerErrorState();
pantheios::log_ERROR("StaticSparseMatrix::fromEigenSparseMatrix: Throwing invalid argument for eigenSparseMatrix is too big to fit (is ", pantheios::integer(eigen_row_count)," x ", pantheios::integer(eigen_col_count), ", max is ", pantheios::integer(row_count)," x ", pantheios::integer(row_count), ").");
throw mrmc::exceptions::invalid_argument("StaticSparseMatrix::fromEigenSparseMatrix: Invalid argument for eigenSparseMatrix is too big to fit.");
return false;
}
uint_fast32_t eigen_non_zero_entries = mrmc::sparse::getEigenSparseMatrixCorrectNonZeroEntryCount(eigen_sparse_matrix);
if (eigen_non_zero_entries > non_zero_entry_count) {
triggerErrorState();
pantheios::log_ERROR("StaticSparseMatrix::fromEigenSparseMatrix: Throwing invalid argument for eigenSparseMatrix has too many non-zero entries to fit (is ", pantheios::integer(eigen_non_zero_entries),", max is ", pantheios::integer(non_zero_entry_count),").");
throw mrmc::exceptions::invalid_argument("StaticSparseMatrix::fromEigenSparseMatrix: Invalid argument for eigenSparseMatrix has too many non-zero entries to fit.");
return false;
}
// make compressed
eigen_sparse_matrix.makeCompressed();
if (eigen_sparse_matrix.IsRowMajor()) {
// inner Index
int_fast32_t* eigenInnerIndex = eigen_sparse_matrix.innerIndexPtr();
T* eigenValuePtr = eigen_sparse_matrix.valuePtr();
}
for (int k = 0; k < tempESM.outerSize(); ++k) {
for (SparseMatrix<T>::InnerIterator it(tempESM, k); it; ++it) {
if (eigen_non_zero_entries >= non_zero_entry_count) {
// too many non zero entries for us.
}
addNextValue(it.row() - 1, it.col() - 1, it.value());
if (it.row() != it.col()) {
++eigen_non_zero_entries;
}
/*it.value();
it.row(); // row index
it.col(); // col index (here it is equal to k)
it.index(); // inner index, here it is equal to it.row()*/
}
}
}
private:
uint_fast32_t storage_size;
uint_fast32_t current_size;
uint_fast32_t row_count;
@ -309,6 +447,74 @@ class StaticSparseMatrix {
void setState(const MatrixStatus new_state) {
internal_status = (internal_status == MatrixStatus::Error) ? internal_status : new_state;
}
/*!
Prepares the internal CSR storage.
Requires non_zero_entry_count and row_count to be set.
@return true on success, false otherwise (allocation failed).
*/
bool prepareInternalStorage() {
value_storage = new (std::nothrow) T[non_zero_entry_count]();
column_indications = new (std::nothrow) uint_fast32_t[non_zero_entry_count]();
row_indications = new (std::nothrow) uint_fast32_t[row_count + 1]();
// row_count + 1 so that access with 1-based indices can be direct without the overhead of a -1 each time
diagonal_storage = new (std::nothrow) T[row_count + 1]();
return ((value_storage != NULL) && (column_indications != NULL) && (row_indications != NULL) && (diagonal_storage != NULL));
}
template <typename _Scalar, typename _Index>
bool isEigenRowMajor(Eigen::SparseMatrix<_Scalar, Eigen::RowMajor, _Index>) {
return true;
}
template <typename _Scalar, typename _Index>
bool isEigenRowMajor(Eigen::SparseMatrix<_Scalar, Eigen::ColMajor, _Index>) {
return false;
}
template<typename _Scalar, int _Options, typename _Index>
uint_fast32_t getEigenSparseMatrixCorrectNonZeroEntryCount(const Eigen::SparseMatrix<_Scalar, _Options, _Index> &eigen_sparse_matrix) {
const int_fast32_t* indexPtr = eigen_sparse_matrix.innerIndexPtr();
const int_fast32_t* outerPtr = eigen_sparse_matrix.outerIndexPtr();
const int_fast32_t entryCount = eigen_sparse_matrix.nonZeros();
const int_fast32_t outerCount = eigen_sparse_matrix.outerSize();
uint_fast32_t diag_non_zeros = 0;
// for RowMajor, row is the current Row and col the column
// for ColMajor, row is the current Col and col the row
int_fast32_t innerStart = 0;
int_fast32_t innerEnd = 0;
int_fast32_t innerMid = 0;
for (int row = 0; row < outerCount; ++row) {
innerStart = outerPtr[row];
innerEnd = outerPtr[row + 1] - 1;
// Now with super fancy binary search, deferred equality detection
while (innerStart < innerEnd) {
innerMid = innerStart + ((innerEnd - innerStart) / 2);
if (indexPtr[innerMid] < row) {
innerStart = innerMid + 1;
} else {
innerEnd = innerMid;
}
}
if ((innerStart == innerEnd) && (indexPtr[innerStart] == row)) {
// found a diagonal entry
++diag_non_zeros;
}
}
return static_cast<uint_fast32_t>(entryCount - diag_non_zeros);
}
};
} // namespace sparse

196
test/sparse/static_sparse_matrix_test.cpp

@ -3,52 +3,70 @@
#include "src/exceptions/invalid_argument.h"
TEST(StaticSparseMatrixTest, ZeroRowsTest) {
mrmc::sparse::StaticSparseMatrix<int> *ssm = new mrmc::sparse::StaticSparseMatrix<int>(0, 50);
mrmc::sparse::StaticSparseMatrix<int> *ssm = new mrmc::sparse::StaticSparseMatrix<int>(0);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::UnInitialized);
ASSERT_THROW(ssm->initialize(), mrmc::exceptions::invalid_argument);
ASSERT_THROW(ssm->initialize(50), mrmc::exceptions::invalid_argument);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::Error);
delete ssm;
}
TEST(StaticSparseMatrixTest, TooManyEntriesTest) {
mrmc::sparse::StaticSparseMatrix<int> *ssm = new mrmc::sparse::StaticSparseMatrix<int>(2, 10);
mrmc::sparse::StaticSparseMatrix<int> *ssm = new mrmc::sparse::StaticSparseMatrix<int>(2);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::UnInitialized);
ASSERT_THROW(ssm->initialize(), mrmc::exceptions::invalid_argument);
ASSERT_THROW(ssm->initialize(10), mrmc::exceptions::invalid_argument);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::Error);
delete ssm;
}
TEST(StaticSparseMatrixTest, addNextValueTest) {
mrmc::sparse::StaticSparseMatrix<int> *ssm = new mrmc::sparse::StaticSparseMatrix<int>(5, 1);
mrmc::sparse::StaticSparseMatrix<int> *ssm = new mrmc::sparse::StaticSparseMatrix<int>(5);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::UnInitialized);
ASSERT_NO_THROW(ssm->initialize());
ASSERT_NO_THROW(ssm->initialize(1));
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::Initialized);
ASSERT_THROW(ssm->addNextValue(0, 1, 1), mrmc::exceptions::out_of_range);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::Error);
ASSERT_THROW(ssm->addNextValue(1, 0, 1), mrmc::exceptions::out_of_range);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::Error);
ASSERT_THROW(ssm->addNextValue(6, 1, 1), mrmc::exceptions::out_of_range);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::Error);
ASSERT_THROW(ssm->addNextValue(1, 6, 1), mrmc::exceptions::out_of_range);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::Error);
delete ssm;
}
TEST(StaticSparseMatrixTest, finalizeTest) {
mrmc::sparse::StaticSparseMatrix<int> *ssm = new mrmc::sparse::StaticSparseMatrix<int>(5, 5);
mrmc::sparse::StaticSparseMatrix<int> *ssm = new mrmc::sparse::StaticSparseMatrix<int>(5);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::UnInitialized);
ASSERT_NO_THROW(ssm->initialize());
ASSERT_NO_THROW(ssm->initialize(5));
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::Initialized);
ASSERT_NO_THROW(ssm->addNextValue(1, 2, 1));
ASSERT_NO_THROW(ssm->addNextValue(1, 3, 1));
ASSERT_NO_THROW(ssm->addNextValue(1, 4, 1));
ASSERT_NO_THROW(ssm->addNextValue(1, 5, 1));
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::Initialized);
ASSERT_THROW(ssm->finalize(), mrmc::exceptions::invalid_state);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::Error);
delete ssm;
}
TEST(StaticSparseMatrixTest, Test) {
// 25 rows, 50 non zero entries
mrmc::sparse::StaticSparseMatrix<int> *ssm = new mrmc::sparse::StaticSparseMatrix<int>(25, 50);
mrmc::sparse::StaticSparseMatrix<int> *ssm = new mrmc::sparse::StaticSparseMatrix<int>(25);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::UnInitialized);
int values[50] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
@ -76,13 +94,16 @@ TEST(StaticSparseMatrixTest, Test) {
14, 15, 16, 17, 18, 19, 20, 21, 22, 23 /* second to last row */
};
ASSERT_NO_THROW(ssm->initialize());
ASSERT_NO_THROW(ssm->initialize(50));
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::Initialized);
for (int i = 0; i < 50; ++i) {
ASSERT_NO_THROW(ssm->addNextValue(position_row[i], position_col[i], values[i]));
}
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::Initialized);
ASSERT_NO_THROW(ssm->finalize());
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::ReadReady);
int target;
for (int i = 0; i < 50; ++i) {
@ -103,6 +124,161 @@ TEST(StaticSparseMatrixTest, Test) {
ASSERT_EQ(0, target);
}
}
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::ReadReady);
delete ssm;
}
TEST(StaticSparseMatrixTest, ConversionFromDenseEigen_ColMajor_SparseMatrixTest) {
// 10 rows, 100 non zero entries
mrmc::sparse::StaticSparseMatrix<int> *ssm = new mrmc::sparse::StaticSparseMatrix<int>(10);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::UnInitialized);
Eigen::SparseMatrix<int> esm(10, 10);
for (int row = 0; row < 10; ++row) {
for (int col = 0; col < 10; ++col) {
esm.insert(row, col) = row * 10 + col;
}
}
// make compressed, important for initialize()
esm.makeCompressed();
ASSERT_NO_THROW(ssm->initialize(esm));
ASSERT_NO_THROW(ssm->finalize());
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::ReadReady);
int target = -1;
for (int row = 1; row <= 10; ++row) {
for (int col = 1; col <= 10; ++col) {
ASSERT_TRUE(ssm->getValue(row, col, &target));
ASSERT_EQ(target, (row - 1) * 10 + col - 1);
}
}
}
TEST(StaticSparseMatrixTest, ConversionFromDenseEigen_RowMajor_SparseMatrixTest) {
// 10 rows, 100 non zero entries
mrmc::sparse::StaticSparseMatrix<int> *ssm = new mrmc::sparse::StaticSparseMatrix<int>(10);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::UnInitialized);
Eigen::SparseMatrix<int, Eigen::RowMajor> esm(10, 10);
for (int row = 0; row < 10; ++row) {
for (int col = 0; col < 10; ++col) {
esm.insert(row, col) = row * 10 + col;
}
}
// make compressed, important for initialize()
esm.makeCompressed();
ASSERT_NO_THROW(ssm->initialize(esm));
ASSERT_NO_THROW(ssm->finalize());
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::ReadReady);
int target = -1;
for (int row = 1; row <= 10; ++row) {
for (int col = 1; col <= 10; ++col) {
ASSERT_TRUE(ssm->getValue(row, col, &target));
ASSERT_EQ(target, (row - 1) * 10 + col - 1);
}
}
}
TEST(StaticSparseMatrixTest, ConversionFromSparseEigen_ColMajor_SparseMatrixTest) {
// 10 rows, 15 non zero entries
mrmc::sparse::StaticSparseMatrix<int> *ssm = new mrmc::sparse::StaticSparseMatrix<int>(10);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::UnInitialized);
Eigen::SparseMatrix<int> esm(10, 10);
typedef Eigen::Triplet<int> IntTriplet;
std::vector<IntTriplet> tripletList;
tripletList.reserve(15);
tripletList.push_back(IntTriplet(1, 0, 0));
tripletList.push_back(IntTriplet(1, 1, 1));
tripletList.push_back(IntTriplet(1, 2, 2));
tripletList.push_back(IntTriplet(1, 3, 3));
tripletList.push_back(IntTriplet(1, 4, 4));
tripletList.push_back(IntTriplet(1, 5, 5));
tripletList.push_back(IntTriplet(1, 6, 6));
tripletList.push_back(IntTriplet(1, 7, 7));
tripletList.push_back(IntTriplet(1, 8, 8));
tripletList.push_back(IntTriplet(1, 9, 9));
tripletList.push_back(IntTriplet(4, 3, 10));
tripletList.push_back(IntTriplet(4, 6, 11));
tripletList.push_back(IntTriplet(4, 9, 12));
tripletList.push_back(IntTriplet(6, 0, 13));
tripletList.push_back(IntTriplet(8, 9, 14));
esm.setFromTriplets(tripletList.begin(), tripletList.end());
// make compressed, important for initialize()
esm.makeCompressed();
ASSERT_NO_THROW(ssm->initialize(esm));
ASSERT_NO_THROW(ssm->finalize());
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::ReadReady);
int target = -1;
for (auto &coeff: tripletList) {
ASSERT_TRUE(ssm->getValue(coeff.row() + 1, coeff.col() + 1, &target));
ASSERT_EQ(target, coeff.value());
}
}
TEST(StaticSparseMatrixTest, ConversionFromSparseEigen_RowMajor_SparseMatrixTest) {
// 10 rows, 15 non zero entries
mrmc::sparse::StaticSparseMatrix<int> *ssm = new mrmc::sparse::StaticSparseMatrix<int>(10);
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::UnInitialized);
Eigen::SparseMatrix<int, Eigen::RowMajor> esm(10, 10);
typedef Eigen::Triplet<int> IntTriplet;
std::vector<IntTriplet> tripletList;
tripletList.reserve(15);
tripletList.push_back(IntTriplet(1, 0, 0));
tripletList.push_back(IntTriplet(1, 1, 1));
tripletList.push_back(IntTriplet(1, 2, 2));
tripletList.push_back(IntTriplet(1, 3, 3));
tripletList.push_back(IntTriplet(1, 4, 4));
tripletList.push_back(IntTriplet(1, 5, 5));
tripletList.push_back(IntTriplet(1, 6, 6));
tripletList.push_back(IntTriplet(1, 7, 7));
tripletList.push_back(IntTriplet(1, 8, 8));
tripletList.push_back(IntTriplet(1, 9, 9));
tripletList.push_back(IntTriplet(4, 3, 10));
tripletList.push_back(IntTriplet(4, 6, 11));
tripletList.push_back(IntTriplet(4, 9, 12));
tripletList.push_back(IntTriplet(6, 0, 13));
tripletList.push_back(IntTriplet(8, 9, 14));
esm.setFromTriplets(tripletList.begin(), tripletList.end());
// make compressed, important for initialize()
esm.makeCompressed();
ASSERT_NO_THROW(ssm->initialize(esm));
ASSERT_NO_THROW(ssm->finalize());
ASSERT_EQ(ssm->getState(), mrmc::sparse::StaticSparseMatrix<int>::MatrixStatus::ReadReady);
int target = -1;
for (auto &coeff: tripletList) {
ASSERT_TRUE(ssm->getValue(coeff.row() + 1, coeff.col() + 1, &target));
ASSERT_EQ(target, coeff.value());
}
}
Loading…
Cancel
Save