diff --git a/.gitignore b/.gitignore index b883f1f..31decfc 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ +*.swp *.exe diff --git a/src/SparseMatrix/SparseMatrix.cpp b/src/SparseMatrix/SparseMatrix.cpp index b3d6e00..bbdbe4d 100644 --- a/src/SparseMatrix/SparseMatrix.cpp +++ b/src/SparseMatrix/SparseMatrix.cpp @@ -19,82 +19,82 @@ using namespace std; template SparseMatrix::SparseMatrix(int n) { - this->construct(n, n); + this->construct(n, n); } template SparseMatrix::SparseMatrix(int rows, int columns) { - this->construct(rows, columns); + this->construct(rows, columns); } template SparseMatrix::SparseMatrix(const SparseMatrix & matrix) { - this->deepCopy(matrix); + this->deepCopy(matrix); } template SparseMatrix & SparseMatrix::operator = (const SparseMatrix & matrix) { - if (&matrix != this) { - this->destruct(); - this->deepCopy(matrix); - } + if (&matrix != this) { + this->destruct(); + this->deepCopy(matrix); + } - return *this; + return *this; } template void SparseMatrix::deepCopy(const SparseMatrix & matrix) { - this->m = matrix.m; - this->n = matrix.n; - this->rows = new vector(*(matrix.rows)); - - if (matrix.vals != NULL) { - this->cols = new vector(*(matrix.cols)); - this->vals = new vector(*(matrix.vals)); - } + this->m = matrix.m; + this->n = matrix.n; + this->rows = new vector(*(matrix.rows)); + + if (matrix.vals != NULL) { + this->cols = new vector(*(matrix.cols)); + this->vals = new vector(*(matrix.vals)); + } } template SparseMatrix::~SparseMatrix(void) { - this->destruct(); + this->destruct(); } template void SparseMatrix::construct(int rows, int columns) { - if (rows < 1 || columns < 1) { - throw InvalidDimensionsException("Matrix dimensions cannot be zero or negative."); - } + if (rows < 1 || columns < 1) { + throw InvalidDimensionsException("Matrix dimensions cannot be zero or negative."); + } - this->m = rows; - this->n = columns; + this->m = rows; + this->n = columns; - this->vals = NULL; - this->cols = NULL; - this->rows = new vector(rows + 1, 1); + this->vals = NULL; + this->cols = NULL; + this->rows = new vector(rows + 1, 1); } template void SparseMatrix::destruct(void) { - if (this->vals != NULL) { - delete this->vals; - delete this->cols; - } + if (this->vals != NULL) { + delete this->vals; + delete this->cols; + } - delete this->rows; + delete this->rows; } @@ -103,14 +103,14 @@ void SparseMatrix::destruct(void) template int SparseMatrix::getRowCount(void) const { - return this->m; + return this->m; } template int SparseMatrix::getColumnCount(void) const { - return this->n; + return this->n; } @@ -119,54 +119,130 @@ int SparseMatrix::getColumnCount(void) const template T SparseMatrix::get(int row, int col) const { - this->validateCoordinates(row, col); + this->validateCoordinates(row, col); - int currCol; + int currCol; - for (int pos = (*(this->rows))[row - 1] - 1; pos < (*(this->rows))[row] - 1; ++pos) { - currCol = (*(this->cols))[pos]; - if (currCol == col) { - return (*(this->vals))[pos]; + for (int pos = this->rows->at(row - 1) - 1; pos < this->rows->at(row) - 1; pos++) + { + currCol = this->cols->at(pos); - } else if (currCol > col) { - break; - } - } + } else if (currCol > col) { + break; + } + } - return T(); + return T(); } +template +bool SparseMatrix::removeAnyEdge(int row, int& col) +{ + for (col = 1; col <= this->n; ++col) + { + this->validateCoordinates(row, col); + + int pos = this->rows->at(row - 1) - 1; + int currCol = 0; + for (; pos < this->rows->at(row) - 1; pos++) + { + currCol = this->cols->at(pos); + if (currCol >= col) + break; + } + + if (currCol == col) + { + this->remove(pos, row); + + return true; + } + } + return false; +} template -SparseMatrix & SparseMatrix::set(T val, int row, int col) + +bool SparseMatrix::removeEdge(int row, int col) { - this->validateCoordinates(row, col); + this->validateCoordinates(row, col); + + int currCol; + + for (int pos = this->rows->at(row - 1) - 1; pos < this->rows->at(row) - 1; pos++) + { + currCol = this->cols->at(pos); + + if (currCol == col) + { + remove(pos, row); + return true; + } + else if (currCol > col) + { + break; + } + } + + return false; +} + + + int pos = this->rows->at(row - 1) - 1; + int currCol = 0; + + for (; pos < this->rows->at(row) - 1; pos++) { + currCol = this->cols->at(pos); - int pos = (*(this->rows))[row - 1] - 1; - int currCol = 0; - for (; pos < (*(this->rows))[row] - 1; pos++) { - currCol = (*(this->cols))[pos]; - if (currCol >= col) { - break; - } - } + int currCol; - if (currCol != col) { - if (!(val == T())) { - this->insert(pos, row, col, val); - } - } else if (val == T()) { - this->remove(pos, row); - } else { - (*(this->vals))[pos] = val; - } + for (int pos = this->rows->at(row - 1) - 1; pos < this->rows->at(row) - 1; pos++) + { + currCol = this->cols->at(pos); - return *this; + + + } else { + this->vals->at(pos) = val; + } + + return neighbors; +} + +template +SparseMatrix & SparseMatrix::set(int row, int col, T val) +{ + this->validateCoordinates(row, col); + + int pos = this->rows->at(row - 1) - 1; + int currCol = 0; + + for (; pos < this->rows->at(row) - 1; pos++) { + currCol = this->cols->at(pos); + + if (currCol >= col) { + break; + } + } + + if (currCol != col) { + if (!(val == T())) { + this->insert(pos, row, col, val); + } + + } else if (val == T()) { + this->remove(pos, row); + + } else { + this->vals->at(pos) = val; + } + + return *this; } @@ -175,167 +251,189 @@ SparseMatrix & SparseMatrix::set(T val, int row, int col) template vector SparseMatrix::multiply(const vector & x) const { - if (this->n != (int) x.size()) { - throw InvalidDimensionsException("Cannot multiply: Matrix column count and vector size don't match."); - } + if (this->n != (int) x.size()) { + throw InvalidDimensionsException("Cannot multiply: Matrix column count and vector size don't match."); + } - vector result(this->m, T()); + vector result(this->m, T()); - if (this->vals != NULL) { // only if any value set - for (int i = 0; i < this->m; i++) { - T sum = T(); - for (int j = (*(this->rows))[i]; j < (*(this->rows))[i + 1]; j++) { - sum = sum + (*(this->vals))[j - 1] * x[(*(this->cols))[j - 1] - 1]; - } + if (this->vals != NULL) { // only if any value set + for (int i = 0; i < this->m; i++) { + T sum = T(); + for (int j = this->rows->at(i); j < this->rows->at(i + 1); j++) { + sum = sum + this->vals->at(j - 1) * x[this->cols->at(j - 1) - 1]; + } - result[i] = sum; - } - } + result[i] = sum; + } + } - return result; + return result; } template vector SparseMatrix::operator * (const vector & x) const { - return this->multiply(x); + return this->multiply(x); } template SparseMatrix SparseMatrix::multiply(const SparseMatrix & m) const { - if (this->n != m.m) { - throw InvalidDimensionsException("Cannot multiply: Left matrix column count and right matrix row count don't match."); - } + if (this->n != m.m) { + throw InvalidDimensionsException("Cannot multiply: Left matrix column count and right matrix row count don't match."); + } - SparseMatrix result(this->m, m.n); + SparseMatrix result(this->m, m.n); - T a; + T a; - // TODO: more efficient? - // @see http://www.math.tamu.edu/~srobertp/Courses/Math639_2014_Sp/CRSDescription/CRSStuff.pdf + // TODO: more efficient? + // @see http://www.math.tamu.edu/~srobertp/Courses/Math639_2014_Sp/CRSDescription/CRSStuff.pdf - for (int i = 1; i <= this->m; i++) { - for (int j = 1; j <= m.n; j++) { - a = T(); + for (int i = 1; i <= this->m; i++) { + for (int j = 1; j <= m.n; j++) { + a = T(); - for (int k = 1; k <= this->n; k++) { - a = a + this->get(i, k) * m.get(k, j); - } + for (int k = 1; k <= this->n; k++) { + a = a + this->get(i, k) * m.get(k, j); + } - result.set(a, i, j); - } - } + result.set(a, i, j); + } + } - return result; + return result; } template SparseMatrix SparseMatrix::operator * (const SparseMatrix & m) const { - return this->multiply(m); + return this->multiply(m); } template SparseMatrix SparseMatrix::add(const SparseMatrix & m) const { - if (this->m != m.m || this->n != m.n) { - throw InvalidDimensionsException("Cannot add: matrices dimensions don't match."); - } + if (this->m != m.m || this->n != m.n) { + throw InvalidDimensionsException("Cannot add: matrices dimensions don't match."); + } - SparseMatrix result(this->m, this->n); + SparseMatrix result(this->m, this->n); - // TODO: more efficient? - // @see http://www.math.tamu.edu/~srobertp/Courses/Math639_2014_Sp/CRSDescription/CRSStuff.pdf + // TODO: more efficient? + // @see http://www.math.tamu.edu/~srobertp/Courses/Math639_2014_Sp/CRSDescription/CRSStuff.pdf - for (int i = 1; i <= this->m; i++) { - for (int j = 1; j <= this->n; j++) { - result.set(this->get(i, j) + m.get(i, j), i, j); - } - } + for (int i = 1; i <= this->m; i++) { + for (int j = 1; j <= this->n; j++) { + result.set(this->get(i, j) + m.get(i, j), i, j); + } + } - return result; + return result; } template SparseMatrix SparseMatrix::operator + (const SparseMatrix & m) const { - return this->add(m); + return this->add(m); } template SparseMatrix SparseMatrix::subtract(const SparseMatrix & m) const { - if (this->m != m.m || this->n != m.n) { - throw InvalidDimensionsException("Cannot subtract: matrices dimensions don't match."); - } + if (this->m != m.m || this->n != m.n) { + throw InvalidDimensionsException("Cannot subtract: matrices dimensions don't match."); + } - SparseMatrix result(this->m, this->n); + SparseMatrix result(this->m, this->n); - // TODO: more efficient? - // @see http://www.math.tamu.edu/~srobertp/Courses/Math639_2014_Sp/CRSDescription/CRSStuff.pdf + // TODO: more efficient? + // @see http://www.math.tamu.edu/~srobertp/Courses/Math639_2014_Sp/CRSDescription/CRSStuff.pdf - for (int i = 1; i <= this->m; i++) { - for (int j = 1; j <= this->n; j++) { - result.set(this->get(i, j) - m.get(i, j), i, j); - } - } + for (int i = 1; i <= this->m; i++) { + for (int j = 1; j <= this->n; j++) { + result.set(this->get(i, j) - m.get(i, j), i, j); + } + } - return result; + return result; } template SparseMatrix SparseMatrix::operator - (const SparseMatrix & m) const { - return this->subtract(m); + return this->subtract(m); + +} + +template +int SparseMatrix::numberOfRowElement(int row) const +{ + validateCoordinates(row, 1); + return this->rows->at(row) - this->rows->at(row - 1); + + +} + +template +int SparseMatrix::numberOfRowElement(int row) const +{ + validateCoordinates(row, 1); + return this->rows->at(row) - this->rows->at(row - 1); + } + + + + // === HELPERS / VALIDATORS ============================================== template void SparseMatrix::validateCoordinates(int row, int col) const { - if (row < 1 || col < 1 || row > this->m || col > this->n) { - throw InvalidCoordinatesException("Coordinates out of range."); - } + if (row < 1 || col < 1 || row > this->m || col > this->n) { + throw InvalidCoordinatesException("Coordinates out of range."); + } } template void SparseMatrix::insert(int index, int row, int col, T val) { - if (this->vals == NULL) { - this->vals = new vector(1, val); - this->cols = new vector(1, col); - - } else { - this->vals->insert(this->vals->begin() + index, val); - this->cols->insert(this->cols->begin() + index, col); - } - - for (int i = row; i <= this->m; i++) { - (*(this->rows))[i] += 1; - } + if (this->vals == NULL) { + this->vals = new vector(1, val); + this->cols = new vector(1, col); + + } else { + this->vals->insert(this->vals->begin() + index, val); + this->cols->insert(this->cols->begin() + index, col); + } + + for (int i = row; i <= this->m; i++) { + this->rows->at(i) = this->rows->at(i) + 1; + } } template void SparseMatrix::remove(int index, int row) { - this->vals->erase(this->vals->begin() + index); - this->cols->erase(this->cols->begin() + index); + this->vals->erase(this->vals->begin() + index); + this->cols->erase(this->cols->begin() + index); - for (int i = row; i <= this->m; i++) { - (*(this->rows))[i] -= 1; - } + for (int i = row; i <= this->m; i++) { + this->rows->at(i) = this->rows->at(i) - 1; + } } @@ -344,37 +442,37 @@ void SparseMatrix::remove(int index, int row) template bool operator == (const SparseMatrix & a, const SparseMatrix & b) { - return ((a.vals == NULL && b.vals == NULL) - || (a.vals != NULL && b.vals != NULL && *(a.vals) == *(b.vals))) - && ((a.cols == NULL && b.cols == NULL) - || (a.cols != NULL && b.cols != NULL && *(a.cols) == *(b.cols))) - && *(a.rows) == *(b.rows); + return ((a.vals == NULL && b.vals == NULL) + || (a.vals != NULL && b.vals != NULL && *(a.vals) == *(b.vals))) + && ((a.cols == NULL && b.cols == NULL) + || (a.cols != NULL && b.cols != NULL && *(a.cols) == *(b.cols))) + && *(a.rows) == *(b.rows); } template bool operator != (const SparseMatrix & a, const SparseMatrix & b) { - return !(a == b); + return !(a == b); } template ostream & operator << (ostream & os, const SparseMatrix & matrix) { - for (int i = 1; i <= matrix.m; i++) { - for (int j = 1; j <= matrix.n; j++) { - if (j != 1) { - os << " "; - } + for (int i = 1; i <= matrix.m; i++) { + for (int j = 1; j <= matrix.n; j++) { + if (j != 1) { + os << " "; + } - os << matrix.get(i, j); - } + os << matrix.get(i, j); + } - if (i < matrix.m) { - os << endl; - } - } + if (i < matrix.m) { + os << endl; + } + } - return os; + return os; } diff --git a/src/SparseMatrix/SparseMatrix.h b/src/SparseMatrix/SparseMatrix.h index bce1769..6e06233 100644 --- a/src/SparseMatrix/SparseMatrix.h +++ b/src/SparseMatrix/SparseMatrix.h @@ -8,87 +8,97 @@ #ifndef __SPARSEMATRIX_H__ - #define __SPARSEMATRIX_H__ +#define __SPARSEMATRIX_H__ - #include - #include +#include +#include - using namespace std; +using namespace std; - template - class SparseMatrix - { +template +class SparseMatrix +{ - public: +public: - // === CREATION ============================================== + // === CREATION ============================================== - SparseMatrix(int n); // square matrix n×n - SparseMatrix(int rows, int columns); // general matrix + SparseMatrix(int n); // square matrix n×n + SparseMatrix(int rows, int columns); // general matrix - SparseMatrix(const SparseMatrix & m); // copy constructor - SparseMatrix & operator = (const SparseMatrix & m); + SparseMatrix(const SparseMatrix & m); // copy constructor + SparseMatrix & operator = (const SparseMatrix & m); - ~SparseMatrix(void); + ~SparseMatrix(void); - // === GETTERS / SETTERS ============================================== + // === GETTERS / SETTERS ============================================== - int getRowCount(void) const; - int getColumnCount(void) const; + int getRowCount(void) const; + int getColumnCount(void) const; - // === VALUES ============================================== + // === VALUES ============================================== - T get(int row, int col) const; - SparseMatrix & set(T val, int row, int col); + T get(int row, int col) const; + SparseMatrix & set(int row, int col, T val); - // === OPERATIONS ============================================== + // === OPERATIONS ============================================== - vector multiply(const vector & x) const; - vector operator * (const vector & x) const; + vector multiply(const vector & x) const; + vector operator * (const vector & x) const; - SparseMatrix multiply(const SparseMatrix & m) const; - SparseMatrix operator * (const SparseMatrix & m) const; + SparseMatrix multiply(const SparseMatrix & m) const; + SparseMatrix operator * (const SparseMatrix & m) const; - SparseMatrix add(const SparseMatrix & m) const; - SparseMatrix operator + (const SparseMatrix & m) const; + SparseMatrix add(const SparseMatrix & m) const; + SparseMatrix operator + (const SparseMatrix & m) const; - SparseMatrix subtract(const SparseMatrix & m) const; - SparseMatrix operator - (const SparseMatrix & m) const; + SparseMatrix subtract(const SparseMatrix & m) const; + SparseMatrix operator - (const SparseMatrix & m) const; - // === FRIEND FUNCTIONS ========================================= + // === FRIEND FUNCTIONS ========================================= - template - friend bool operator == (const SparseMatrix & a, const SparseMatrix & b); + template + friend bool operator == (const SparseMatrix & a, const SparseMatrix & b); - template - friend bool operator != (const SparseMatrix & a, const SparseMatrix & b); + template + friend bool operator != (const SparseMatrix & a, const SparseMatrix & b); - template - friend ostream & operator << (ostream & os, const SparseMatrix & matrix); + template + friend ostream & operator << (ostream & os, const SparseMatrix & matrix); + // === Number of row elements ========================================= - protected: + int numberOfRowElement(int row) const; - int m, n; - vector * vals; - vector * rows, * cols; + bool removeAnyEdge(int row, int& col); + bool removeEdge(int row, int col); - // === HELPERS / VALIDATORS ============================================== + vector getNeighbors(int row); +private: - void construct(int m, int n); - void destruct(void); - void deepCopy(const SparseMatrix & m); - void validateCoordinates(int row, int col) const; - void insert(int index, int row, int col, T val); - void remove(int index, int row); + int m, n; - }; + vector * vals; + vector * rows, * cols; + + + // === HELPERS / VALIDATORS ============================================== + + void construct(int m, int n); + void destruct(void); + void deepCopy(const SparseMatrix & m); + void validateCoordinates(int row, int col) const; + void insert(int index, int row, int col, T val); + void remove(int index, int row); + + +}; #endif diff --git a/src/SparseMatrix/exceptions.h b/src/SparseMatrix/exceptions.h index c05663a..378ed46 100644 --- a/src/SparseMatrix/exceptions.h +++ b/src/SparseMatrix/exceptions.h @@ -8,58 +8,58 @@ #ifndef __SPARSEMATRIX_EXCEPTIONS_H__ - #define __SPARSEMATRIX_EXCEPTIONS_H__ +#define __SPARSEMATRIX_EXCEPTIONS_H__ - #include +#include - using namespace std; +using namespace std; - class Exception : public exception - { +class Exception : public exception +{ - public: +public: - explicit Exception(const string & message) : exception(), message(message) - {} + explicit Exception(const string & message) : exception(), message(message) + {} - virtual ~Exception(void) throw () - {} + virtual ~Exception(void) throw () + {} - inline string getMessage(void) const - { - return this->message; - } + inline string getMessage(void) const + { + return this->message; + } - protected: +protected: - string message; + string message; - }; +}; - class InvalidDimensionsException : public Exception - { +class InvalidDimensionsException : public Exception +{ - public: +public: - InvalidDimensionsException(const string & message) : Exception(message) - {} + InvalidDimensionsException(const string & message) : Exception(message) + {} - }; +}; - class InvalidCoordinatesException : public Exception - { +class InvalidCoordinatesException : public Exception +{ - public: +public: - InvalidCoordinatesException(const string & message) : Exception(message) - {} + InvalidCoordinatesException(const string & message) : Exception(message) + {} - }; +}; -#endif \ No newline at end of file +#endif diff --git a/tests/cases/subtraction.h b/tests/cases/subtraction.h index c3ed5f6..f789690 100644 --- a/tests/cases/subtraction.h +++ b/tests/cases/subtraction.h @@ -71,7 +71,13 @@ void testSubtraction(void) SparseMatrixMock sparseMatrixB = SparseMatrixMock::fromVectors(classicMatrixB); // calculate result manually - vector > manualResult = subtractMatrices(classicMatrixA, classicMatrixB); + vector > manualResult(rows, vector(cols, 0)); + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + manualResult[i][j] += classicMatrixA[i][j] - classicMatrixB[i][j]; + } + } // method assertEquals, vector > >( diff --git a/tests/inc/helpers.h b/tests/inc/helpers.h index f7df40f..830f0b1 100644 --- a/tests/inc/helpers.h +++ b/tests/inc/helpers.h @@ -66,24 +66,6 @@ } - template - vector > subtractMatrices(const vector > & a, const vector > & b) - { - int rows = a.size(); - int cols = a.front().size(); - - vector > result(rows, vector(cols, 0)); - - for (int i = 0; i < rows; i++) { - for (int j = 0; j < cols; j++) { - result[i][j] = a[i][j] - b[i][j]; - } - } - - return result; - } - - template vector multiplyMatrixByVector(const vector > & m, const vector & v) {