@ -26,13 +26,31 @@ namespace sparse {
template < class T >
template < class T >
class StaticSparseMatrix {
class StaticSparseMatrix {
public :
public :
/ / ! Status enum
/*!
An Enum representing the internal state of the Matrix .
After creating the Matrix using the Constructor , the Object is in state UnInitialized . After calling initialize ( ) , that state changes to Initialized and after all entries have been entered and finalize ( ) has been called , to ReadReady .
Should a critical error occur in any of the former functions , the state will change to Error .
@ see getState ( )
@ see isReadReady ( )
@ see isInitialized ( )
@ see hasError ( )
*/
enum MatrixStatus {
Error = - 1 ,
UnInitialized = 0 ,
Initialized = 1 ,
ReadReady = 2 ,
} ;
/ / ! Constructor
/ / ! Constructor
/*!
/*!
\ param rows Row - Count and therefore column - count of the symmetric matrix
\ 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 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 )
*/
*/
StaticSparseMatrix ( uint_fast32_t rows , uint_fast32_t non_zero_entries ) {
StaticSparseMatrix ( uint_fast32_t rows , uint_fast32_t non_zero_entries ) {
setState ( MatrixStatus : : UnInitialized ) ;
current_size = 0 ;
current_size = 0 ;
storage_size = 0 ;
storage_size = 0 ;
@ -48,6 +66,7 @@ class StaticSparseMatrix {
}
}
~ StaticSparseMatrix ( ) {
~ StaticSparseMatrix ( ) {
setState ( MatrixStatus : : UnInitialized ) ;
if ( value_storage ! = NULL ) {
if ( value_storage ! = NULL ) {
/ / free ( value_storage ) ;
/ / free ( value_storage ) ;
delete [ ] value_storage ;
delete [ ] value_storage ;
@ -68,7 +87,7 @@ class StaticSparseMatrix {
/ / ! Getter for saving matrix entry A_ { row , col } to target
/ / ! Getter for saving matrix entry A_ { row , col } to target
/*!
/*!
Getter function for the matrix .
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 row 1 - based index of the requested row
\ param col 1 - based index of the requested column
\ param col 1 - based index of the requested column
\ param target pointer to where the result will be stored
\ param target pointer to where the result will be stored
@ -109,36 +128,42 @@ class StaticSparseMatrix {
Mandatory initialization of the matrix , must be called before using any other member function .
Mandatory initialization of the matrix , must be called before using any other member function .
*/
*/
void initialize ( ) {
void initialize ( ) {
if ( row_count = = 0 ) {
if ( internal_status ! = MatrixStatus : : UnInitialized ) {
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 ) {
pantheios : : log_ERROR ( " StaticSparseMatrix::initialize: Throwing invalid_argument for row_count = 0 " ) ;
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 " ) ;
throw mrmc : : exceptions : : invalid_argument ( " mrmc::StaticSparseMatrix::initialize: Matrix with 0 rows is not reasonable " ) ;
}
if ( ( ( row_count * row_count ) - row_count ) < non_zero_entry_count ) {
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 " ) ;
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 " ) ;
throw mrmc : : exceptions : : invalid_argument ( " mrmc::StaticSparseMatrix::initialize: More non-zero entries than entries in target matrix " ) ;
}
storage_size = non_zero_entry_count ;
last_row = 0 ;
triggerErrorState ( ) ;
} else {
storage_size = non_zero_entry_count ;
last_row = 0 ;
/ / value_storage = static_cast < T * > ( calloc ( storage_size , sizeof ( * value_storage ) ) ) ;
value_storage = new ( std : : nothrow ) T [ storage_size ] ( ) ;
/ / 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 ] ( ) ;
/ / 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_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 ] ( ) ;
/ / 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 ) ) {
pantheios : : log_ERROR ( " StaticSparseMatrix::initialize: Throwing bad_alloc: memory allocation failed " ) ;
throw std : : bad_alloc ( ) ;
if ( ( value_storage = = NULL ) | | ( column_indications = = NULL ) | | ( row_indications = = NULL ) | | ( diagonal_storage = = NULL ) ) {
pantheios : : log_ERROR ( " StaticSparseMatrix::initialize: Throwing bad_alloc: memory allocation failed " ) ;
throw std : : bad_alloc ( ) ;
triggerErrorState ( ) ;
} else {
setState ( MatrixStatus : : Initialized ) ;
}
}
}
}
}
@ -151,6 +176,7 @@ class StaticSparseMatrix {
if ( ( row > row_count ) | | ( col > row_count ) | | ( row = = 0 ) | | ( col = = 0 ) ) {
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 " ) ;
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 " ) ;
throw mrmc : : exceptions : : out_of_range ( " mrmc::StaticSparseMatrix::addNextValue: row or col not in 1 .. rows " ) ;
triggerErrorState ( ) ;
}
}
if ( row = = col ) {
if ( row = = col ) {
@ -172,18 +198,25 @@ class StaticSparseMatrix {
}
}
void finalize ( ) {
void finalize ( ) {
if ( storage_size ! = current_size ) {
if ( ! isInitialized ( ) ) {
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? " ) ;
triggerErrorState ( ) ;
} else if ( storage_size ! = current_size ) {
pantheios : : log_ERROR ( " StaticSparseMatrix::finalize: Throwing invalid_state: Wrong call count for addNextValue " ) ;
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 " ) ;
throw mrmc : : exceptions : : invalid_state ( " mrmc::StaticSparseMatrix::finalize: Wrong call count for addNextValue " ) ;
}
if ( last_row ! = row_count ) {
for ( uint_fast32_t i = last_row ; i < row_count ; + + i ) {
row_indications [ i ] = current_size ;
triggerErrorState ( ) ;
} else {
if ( last_row ! = row_count ) {
for ( uint_fast32_t i = last_row ; i < row_count ; + + i ) {
row_indications [ i ] = current_size ;
}
}
}
}
row_indications [ row_count ] = storage_size ;
row_indications [ row_count ] = storage_size ;
setState ( MatrixStatus : : ReadReady ) ;
}
}
}
uint_fast32_t getRowCount ( ) const {
uint_fast32_t getRowCount ( ) const {
@ -194,29 +227,52 @@ class StaticSparseMatrix {
return value_storage ;
return value_storage ;
}
}
Eigen : : SparseMatrix < T > toEigenSparseMatrix ( ) {
typedef Eigen : : Triplet < double > ETd ;
std : : vector < ETd > tripletList ;
tripletList . reserve ( non_zero_entry_count + row_count ) ;
uint_fast32_t row_start ;
uint_fast32_t row_end ;
for ( uint_fast32_t row = 1 ; row < = row_count ; + + row ) {
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 ] ) ) ;
+ + row_start ;
}
}
for ( uint_fast32_t i = 1 ; i < = row_count ; + + i ) {
tripletList . push_back ( ETd ( i , i , diagonal_storage [ i ] ) ) ;
}
bool isReadReady ( ) {
return ( internal_status = = MatrixStatus : : ReadReady ) ;
}
bool isInitialized ( ) {
return ( internal_status = = MatrixStatus : : Initialized | | internal_status = = MatrixStatus : : ReadReady ) ;
}
MatrixStatus getState ( ) {
return internal_status ;
}
bool hasError ( ) {
return ( internal_status = = MatrixStatus : : Error ) ;
}
Eigen : : SparseMatrix < T > toEigenSparseMatrix ( ) {
Eigen : : SparseMatrix < T > mat ( row_count , row_count ) ;
Eigen : : SparseMatrix < T > mat ( row_count , row_count ) ;
mat . setFromTriplets ( tripletList . begin ( ) , tripletList . end ( ) ) ;
mat . makeCompressed ( ) ;
if ( ! isReadReady ( ) ) {
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 ;
tripletList . reserve ( non_zero_entry_count + row_count ) ;
uint_fast32_t row_start ;
uint_fast32_t row_end ;
for ( uint_fast32_t row = 1 ; row < = row_count ; + + row ) {
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 ] ) ) ;
+ + row_start ;
}
}
for ( uint_fast32_t i = 1 ; i < = row_count ; + + i ) {
tripletList . push_back ( ETd ( i , i , diagonal_storage [ i ] ) ) ;
}
mat . setFromTriplets ( tripletList . begin ( ) , tripletList . end ( ) ) ;
mat . makeCompressed ( ) ;
}
return mat ;
return mat ;
}
}
@ -237,6 +293,22 @@ class StaticSparseMatrix {
uint_fast32_t * column_indications ;
uint_fast32_t * column_indications ;
/*! Array containing the row boundaries of valueStorage */
/*! Array containing the row boundaries of valueStorage */
uint_fast32_t * row_indications ;
uint_fast32_t * row_indications ;
/*! Internal status enum, 0 for constructed, 1 for initialized and 2 for finalized, -1 on errors */
MatrixStatus internal_status ;
/*! Sets the internal status to Error */
void triggerErrorState ( ) {
setState ( MatrixStatus : : Error ) ;
}
/*!
Sets the internal status to new_state iff the current state is not the Error state .
@ param new_state the new state to be switched to
*/
void setState ( const MatrixStatus new_state ) {
internal_status = ( internal_status = = MatrixStatus : : Error ) ? internal_status : new_state ;
}
} ;
} ;
} / / namespace sparse
} / / namespace sparse