lasd/librerie/exercise5/matrix/csr/matrixcsr.cpp

310 lines
8.7 KiB
C++
Raw Permalink Normal View History

namespace lasd {
/* ************************************************************************** */
2021-05-28 12:43:27 +02:00
template <typename Data>
MatrixCSR<Data>::MatrixCSR(){
2021-05-31 11:26:27 +02:00
R.Resize(1);
2021-05-28 12:43:27 +02:00
R[0] = &head;
}
template <typename Data>
2021-05-31 11:26:27 +02:00
MatrixCSR<Data>::MatrixCSR(const ulong r, const ulong c){
2021-05-28 12:43:27 +02:00
rows = r;
columns = c;
R.Resize(rows+1);
for(ulong i=0 ; i<R.Size() ; ++i){
R[i] = &head;
}
}
// copy constructor
template <typename Data>
MatrixCSR<Data>::MatrixCSR(const MatrixCSR& toCopy) : MatrixCSR(toCopy.rows, toCopy.columns) {
/*
For each element in the "R" vector, insert it in the matrix (represented as a list)
in this way:
The row index is represented by "i" (the variable that iterates over the R array),
meanwhile the column index is represented by the second element in the pair of the node.
2021-06-13 12:07:06 +02:00
The current element is stored in the first element in the pair of the node.
2021-05-28 12:43:27 +02:00
The update of the newely created R array is left to operator()().
*/
for(ulong i=0 ; i < (toCopy.R.Size()-1) ; ++i){
for(Node** ptr = toCopy.R[i] ; ptr!=toCopy.R[i+1] ; ptr = &( (*(*ptr)).next ) ){
2021-05-31 11:26:27 +02:00
(*this)(i , ((*ptr)->value).second) = ((*ptr)->value).first;
2021-05-28 12:43:27 +02:00
}
}
}
template <typename Data>
2021-05-28 23:16:37 +02:00
MatrixCSR<Data>::MatrixCSR(MatrixCSR&& toMove) noexcept{
2021-05-28 12:43:27 +02:00
std::swap(rows, toMove.rows);
std::swap(columns, toMove.columns);
std::swap(size, toMove.size);
std::swap(head, toMove.head);
std::swap(R, toMove.R);
2021-06-09 08:13:58 +02:00
toMove.R.Resize(1); // the moved matrix must be empty
2021-05-28 12:43:27 +02:00
toMove.R[0] = &toMove.head;
Node** oldHead = R[0];
for(ulong i=0 ; i<R.Size() && R[i]==oldHead; ++i){
R[i] = &head;
}
}
template <typename Data>
MatrixCSR<Data>::~MatrixCSR(){
Clear();
}
template <typename Data>
2021-06-02 21:03:10 +02:00
MatrixCSR<Data>& MatrixCSR<Data>::operator=(const MatrixCSR<Data>& toCopy){
MatrixCSR<Data> tmp(toCopy);
std::swap(tmp, *this);
2021-05-28 12:43:27 +02:00
return *this;
}
template <typename Data>
2021-06-02 21:03:10 +02:00
MatrixCSR<Data>& MatrixCSR<Data>::operator=(MatrixCSR<Data>&& toMove) noexcept{
std::swap(rows, toMove.rows);
std::swap(columns, toMove.columns);
std::swap(size, toMove.size);
std::swap(head, toMove.head);
std::swap(R, toMove.R);
2021-06-10 18:04:44 +02:00
// Fix of the R vector after the swap, both in (*this) and in toMove
Node** oldHead;
oldHead = R[0];
2021-06-02 21:03:10 +02:00
for(ulong i=0 ; i<R.Size() && R[i]==oldHead; ++i){
R[i] = &head;
}
2021-06-10 18:04:44 +02:00
oldHead = toMove.R[0];
for(ulong j=0 ; j<toMove.R.Size() && toMove.R[j]==oldHead ; ++j){
toMove.R[j] = &(toMove.head);
}
2021-05-28 12:43:27 +02:00
return *this;
}
template <typename Data>
bool MatrixCSR<Data>::operator==(const MatrixCSR& toCompare) const noexcept{
2021-05-31 11:26:27 +02:00
/*
* Check the # of rows, of columns and of elements.
* For each row, check if the nodes in that row have the same value (data and column).
* If one row ends before the other one, return false.
*/
2021-05-28 23:16:37 +02:00
if(columns == toCompare.columns && rows == toCompare.rows && size==toCompare.size){
for(ulong i=0 ; i<(R.Size()-1) ; ++i){
2021-05-31 11:26:27 +02:00
for(Node** ptr1 = R[i] , **ptr2 = (toCompare.R)[i] ; ptr1!=R[i+1] && ptr2!=toCompare.R[i+1] ; ptr1 = &( (*(*ptr1)).next ) , ptr2 = &( (*(*ptr2)).next ) ){
2021-05-28 12:43:27 +02:00
2021-05-28 23:16:37 +02:00
if( ( ((*ptr1)->value).first != ((*ptr2)->value).first ) || ( ((*ptr1)->value).second != ((*ptr2)->value).second )) return false;
2021-05-31 11:26:27 +02:00
if( (&((*(*ptr1)).next)==R[i+1] && &((*(*ptr2)).next) != toCompare.R[i+1]) || (&((*(*ptr1)).next)!=R[i+1] && &((*(*ptr2)).next) == toCompare.R[i+1])){
2021-05-28 23:16:37 +02:00
return false;
}
}
}
return true;
}else{
return false;
}
2021-05-28 12:43:27 +02:00
}
template <typename Data>
bool MatrixCSR<Data>::operator!=(const MatrixCSR& toCompare) const noexcept{
return !(*this == toCompare);
}
template <typename Data>
2021-05-28 23:16:37 +02:00
void MatrixCSR<Data>::RowResize(const ulong& new_row_size){
2021-06-05 14:25:22 +02:00
if(new_row_size > rows){
2021-05-28 23:16:37 +02:00
R.Resize(new_row_size+1);
2021-06-02 10:02:21 +02:00
for(ulong i=rows+1 ; i<R.Size(); ++i){
2021-05-28 23:16:37 +02:00
R[i] = R[rows];
}
rows = new_row_size;
2021-05-31 11:26:27 +02:00
}else if(new_row_size < rows){
Node* toDelete;
Node* tmp;
2021-05-28 23:16:37 +02:00
toDelete = *R[new_row_size];
while(toDelete!=nullptr){
tmp = toDelete->next;
delete toDelete;
toDelete = tmp;
--size;
}
*(R[new_row_size]) = nullptr;
R.Resize(new_row_size+1);
rows = new_row_size;
}
}
template <typename Data>
void MatrixCSR<Data>::ColumnResize(const ulong& new_column_size){
2021-06-05 14:25:22 +02:00
if(new_column_size < columns){
2021-06-13 12:07:06 +02:00
Node** prev; // in case an element must be deleted, this is its previous element.
2021-05-31 11:26:27 +02:00
Node* toDelete;
2021-06-02 11:50:40 +02:00
Node** toModify;
2021-06-02 10:02:21 +02:00
for(ulong i=0 ; i<R.Size()-1 ; ++i){ // iterate over the R array
2021-06-13 12:07:06 +02:00
prev = R[i];
2021-06-02 11:50:40 +02:00
for(Node** ptr = R[i] ; ptr!=R[i+1] ; ){
2021-05-31 11:26:27 +02:00
if(((*ptr)->value).second < new_column_size){
2021-06-13 12:07:06 +02:00
prev = &( (*(*ptr)).next ); // This, alongside line 157 is redundant, but maybe it gives more clarity
2021-06-02 11:50:40 +02:00
ptr = &( (*(*ptr)).next);
2021-05-31 11:26:27 +02:00
}else{
toDelete = *ptr;
2021-06-02 11:50:40 +02:00
toModify = &( (*(*ptr)).next );
2021-05-31 11:26:27 +02:00
*ptr = (*(*ptr)).next;
delete toDelete;
--size;
2021-06-02 10:02:21 +02:00
for(ulong j=i+1 ; j<R.Size() ; ++j){
2021-06-02 11:50:40 +02:00
if(R[j] == toModify){
R[j] = prev;
2021-06-02 10:02:21 +02:00
}
else break;
}
2021-05-31 11:26:27 +02:00
}
2021-05-28 23:16:37 +02:00
}
}
}
2021-06-02 10:02:21 +02:00
columns = new_column_size;
2021-05-28 23:16:37 +02:00
}
template <typename Data>
2021-05-31 11:26:27 +02:00
bool MatrixCSR<Data>::ExistsCell(const ulong& r, const ulong& c) const noexcept{
if(r>=rows || c>=columns) return false;
2021-05-28 23:16:37 +02:00
Node** ptr = R[r];
while(ptr != R[r+1]){
if( (**ptr).value.second == c ) return true;
ptr = &((**ptr).next);
}
return false;
}
template <typename Data>
2021-06-02 10:02:21 +02:00
const Data& MatrixCSR<Data>::operator()(const ulong r, const ulong c) const{
2021-05-31 11:26:27 +02:00
if(r>=rows || c>=columns) throw std::out_of_range("Tried to access an invalid position!");
2021-05-28 23:16:37 +02:00
else{
Node** ptr = R[r];
while(ptr != R[r+1]){
2021-06-02 10:02:21 +02:00
if( (**ptr).value.second == c ){
return (**ptr).value.first;
}
2021-05-28 23:16:37 +02:00
ptr = &((**ptr).next);
}
throw std::length_error("The element does not exist!");
}
}
template <typename Data>
2021-06-02 10:02:21 +02:00
Data& MatrixCSR<Data>::operator()(const ulong r, const ulong c){
2021-05-31 11:26:27 +02:00
if(r>=rows || c>=columns) throw std::out_of_range("Tried to access an invalid position!");
2021-05-28 23:16:37 +02:00
else{
Node** ptr = R[r];
2021-05-31 11:26:27 +02:00
Node** last = R[r+1]; // pointer to the pointer inside the last element of the r-th cell
while(ptr != R[r+1] && ((**ptr).value.second <= c)){
2021-05-28 23:16:37 +02:00
if((**ptr).value.second == c){
return (**ptr).value.first;
}
else if( (**ptr).value.second < c ){
ptr = &((**ptr).next);
}
2021-05-31 11:26:27 +02:00
}
2021-06-02 10:02:21 +02:00
Node* newNode = new Node();
Node* nextNode = *ptr;
2021-05-31 11:26:27 +02:00
*ptr = newNode;
newNode->next = nextNode;
2021-05-31 17:46:48 +02:00
(newNode->value).second = c;
2021-06-02 10:02:21 +02:00
++size;
2021-05-31 11:26:27 +02:00
if(last == ptr){ // the newely inserted element is the last one in its row
for(ulong i=r+1 ; i<R.Size() ; ++i){ // then for each next row
2021-06-02 10:02:21 +02:00
if(R[i] == last){ // check if it pointed to last (it was empty)
R[i] = &(newNode->next); // assign the address of the pointer of the next node
2021-05-31 11:26:27 +02:00
}
else break;
2021-05-28 23:16:37 +02:00
}
}
2021-06-02 10:02:21 +02:00
return (newNode->value).first;
2021-05-28 12:43:27 +02:00
}
}
2021-05-31 11:26:27 +02:00
template <typename Data>
void MatrixCSR<Data>::Clear(){
List<std::pair<Data,ulong>>::Clear();
columns = 0;
rows = 0;
size = 0;
R.Resize(1);
2021-06-02 10:02:21 +02:00
R[0] = &head;
2021-05-31 11:26:27 +02:00
}
template <typename Data>
void MatrixCSR<Data>::MapPreOrder(const typename MappableContainer<Data>::MapFunctor fun, void* par){
List<std::pair<Data,ulong>>::MapPreOrder(
[&fun](std::pair<Data,ulong>& datx, void* parx){fun(datx.first, parx); }
, par);
}
template <typename Data>
void MatrixCSR<Data>::MapPostOrder(const typename MappableContainer<Data>::MapFunctor fun, void* par){
List<std::pair<Data,ulong>>::MapPostOrder(
[&fun](std::pair<Data,ulong>& datx, void* parx){fun(datx.first, parx); }
, par);
}
template <typename Data>
void MatrixCSR<Data>::FoldPreOrder(const typename FoldableContainer<Data>::FoldFunctor fun, const void* par, void* acc) const{
List<std::pair<Data,ulong>>::FoldPreOrder(
[&fun](const std::pair<Data,ulong>& datx, const void* parx, void* accx) {fun(datx.first, parx, accx); }
, par , acc);
}
template <typename Data>
void MatrixCSR<Data>::FoldPostOrder(const typename FoldableContainer<Data>::FoldFunctor fun, const void* par, void* acc) const{
List<std::pair<Data,ulong>>::FoldPostOrder(
[&fun](const std::pair<Data,ulong>& datx, const void* parx, void* accx) {fun(datx.first, parx, accx); }
, par , acc);
}
2021-06-02 10:02:21 +02:00
template <typename Data>
void MatrixCSR<Data>::debug(){
std::cout<<std::endl;
2021-05-31 11:26:27 +02:00
2021-06-02 21:03:10 +02:00
std::cout<<"rows: "<<rows<<" columns: "<<columns<<" size: "<<size<<"\n\n";
Node* tmp = head;
while(tmp!=nullptr){
std::cout<<(tmp->value).first<<"|"<< (tmp->value).second;
std::cout<<std::endl;
std::cout<<&(tmp->next);
std::cout<<std::endl;
std::cout<<std::endl;
tmp = tmp->next;
}
2021-06-04 22:16:34 +02:00
std::cout << "\nR VECTOR:" << '\n';
2021-06-02 21:03:10 +02:00
for(ulong i=0; i<R.Size();++i){
std::cout << R[i] << '\n';
}
std::cout<<std::endl;
std::cout<<std::endl;
2021-06-02 10:02:21 +02:00
}
2021-05-31 11:26:27 +02:00
/* ************************************************************************** */
}