├── Makefile ├── README.md ├── SparseMatrix.cpp ├── SparseMatrix.h ├── demo.cpp ├── license.txt └── test.cpp /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for SparseMatrix 2 | # Murtaza Gulamali (11/11/2011) 3 | 4 | CC = g++ 5 | LIBS = -lm -lpthread 6 | DEFS = 7 | 8 | CPPFLAGS += -I${GTEST_DIR}/include 9 | CXXFLAGS += -O3 -g -Wall -Wextra ${LIBS} ${DEFS} 10 | 11 | GTEST_DIR = ./gtest-1.6.0 12 | 13 | GTEST_HEADERS = ${GTEST_DIR}/include/gtest/*.h \ 14 | ${GTEST_DIR}/include/gtest/internal/*.h 15 | 16 | GTEST_SRCS_ = ${GTEST_DIR}/src/*.cc ${GTEST_DIR}/src/*.h ${GTEST_HEADERS} 17 | 18 | SOURCES = SparseMatrix.cpp 19 | 20 | .SUFFIXES: 21 | .SUFFIXES: .cpp .o 22 | 23 | OBJECTS = ${SOURCES:.cpp=.o} 24 | 25 | all: test demo 26 | 27 | .cpp.o: 28 | ${CC} -c ${CPPFLAGS} ${CXXFLAGS} $< 29 | 30 | test: gtest_main.a ${OBJECTS} 31 | ${CC} ${CPPFLAGS} ${CXXFLAGS} -o $@ ${OBJECTS} gtest_main.a test.cpp 32 | 33 | demo: ${OBJECTS} 34 | ${CC} ${CXXFLAGS} -o $@ ${OBJECTS} demo.cpp 35 | 36 | gtest-all.o: ${GTEST_SRCS_} 37 | ${CC} ${CPPFLAGS} -I${GTEST_DIR} ${CXXFLAGS} -c ${GTEST_DIR}/src/gtest-all.cc 38 | 39 | gtest_main.o: ${GTEST_SRCS_} 40 | ${CC} ${CPPFLAGS} -I${GTEST_DIR} ${CXXFLAGS} -c ${GTEST_DIR}/src/gtest_main.cc 41 | 42 | gtest.a: gtest-all.o 43 | ${AR} ${ARFLAGS} $@ $^ 44 | 45 | gtest_main.a: gtest-all.o gtest_main.o 46 | ${AR} ${ARFLAGS} $@ $^ 47 | 48 | clean: 49 | rm *.o *.a 50 | 51 | distclean: clean 52 | rm demo test 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SparseMatrix 2 | 3 | ## Synopsis 4 | 5 | SparseMatrix is a small C++ class to represent a sparse square matrix in 6 | compressed row format. It's very useful for FEM codes when coupled with a 7 | decent matrix solver (eg. Algebraic 8 | [Multigrid Method](http://en.wikipedia.org/wiki/Multigrid_method "Multigrid 9 | Method")). 10 | 11 | ## Explanation 12 | 13 | The SparseMatrix class stores matrix entries in compressed row format. That is, 14 | each each diagonal element is stored together with any non-zero off-diagonal 15 | elements. This makes it very memory efficient for storing large sparse matrices 16 | such as those used in the 17 | [finite element method](http://en.wikipedia.org/wiki/Finite_element_method 18 | "Finite Element Method"). 19 | 20 | I wrote this class as part of a job interview and thought I'd add open source it 21 | so that others might benefit. Much of the API is commented in 22 | [Doxygen](http://www.doxygen.org "Doxygen") format, and the class is templated 23 | for flexibility. A very basic solve method is also included for testing 24 | purposes. 25 | 26 | Testing is performed via [googletest](http://code.google.com/p/googletest/ "The 27 | Google C++ testing framework"), which you need to download and unzip into the 28 | main directory. 29 | 30 | Hope it helps! 31 | 32 | ## License 33 | 34 | This software is released under the terms and conditions of [The MIT 35 | License](http://www.opensource.org/licenses/mit-license.php "The MIT License"). 36 | Please see the license.txt file for more details. 37 | -------------------------------------------------------------------------------- /SparseMatrix.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SparseMatrix.cpp 3 | * SparseMatrix 4 | * Murtaza Gulamali (30/11/2006) 5 | * 6 | * This software is released under the terms and conditions of The MIT License: 7 | * http://www.opensource.org/licenses/mit-license.php 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "SparseMatrix.h" 15 | 16 | using namespace std; 17 | using namespace myg; 18 | 19 | // static const values 20 | 21 | //! zero 22 | template 23 | const fT SparseMatrix::zero_(0.0); 24 | 25 | //! epsilon: a very very small number number greater than zero 26 | template 27 | const fT SparseMatrix::eps_(1.0e-16); 28 | 29 | // constructors and destructors 30 | 31 | /** 32 | * default constructor creates identity matrix of specified dimension 33 | * @param dim dimension of matrix (default is 1) 34 | */ 35 | template 36 | SparseMatrix::SparseMatrix(iT dim) : 37 | nnu_(dim) 38 | { 39 | // reserve necessary memory 40 | ia_.reserve(dim+1); 41 | ja_.reserve(dim); 42 | a_.reserve(dim); 43 | 44 | // set to identity matrix 45 | for (iT i=0; i(1.)); 49 | } 50 | ia_.push_back(dim); 51 | } 52 | 53 | /** 54 | * copy constructor 55 | * @param m SparseMatrix object to copy 56 | */ 57 | template 58 | SparseMatrix::SparseMatrix(const SparseMatrix& m) : 59 | nnu_(m.Dim()), 60 | ia_(m.IA()), 61 | ja_(m.JA()), 62 | a_(m()) 63 | { } 64 | 65 | //! default destructor 66 | template 67 | SparseMatrix::~SparseMatrix() {} 68 | 69 | // accessors and mutators for matrix elements 70 | 71 | /** 72 | * return value at specified indices of matrix 73 | * @param row matrix row 74 | * @param col matrix column 75 | * @return value at specified matrix row and column 76 | */ 77 | template 78 | const fT& SparseMatrix::operator()(iT row, iT col) const { 79 | if (row==col) 80 | return a_.at(ia_.at(row)); 81 | 82 | const iT j = findIndex(row,col); 83 | if (j 96 | void SparseMatrix::operator()(iT row, iT col, fT val) { 97 | if (row==col) 98 | // set diagonal element 99 | a_.at(ia_.at(row)) = val; 100 | else { 101 | const iT j = findIndex(row,col); 102 | if (jeps_) { 105 | // change non-zero 106 | a_.at(j) = val; 107 | } else { 108 | // remove non-zero 109 | for (iT i=(row+1); i<=Dim(); i++) ia_.at(i)--; 110 | ja_.erase(ja_.begin()+j); 111 | a_.erase(a_.begin()+j); 112 | } 113 | } else { 114 | // zero at (row,col) 115 | if (fabs(val)>eps_) { 116 | // insert non-zero 117 | for (iT i=(row+1); i<=Dim(); i++) ia_.at(i)++; 118 | ja_.insert(ja_.begin()+(ia_.at(row+1)-1),col); 119 | a_.insert(a_.begin()+(ia_.at(row+1)-1),val); 120 | } 121 | } 122 | } 123 | } 124 | 125 | // matrix operator methods 126 | /** 127 | * matrix assignment 128 | * @param m assign this to m (ie. produce a "deep" copy) 129 | * @return copy 130 | */ 131 | template 132 | SparseMatrix& SparseMatrix::operator=(const SparseMatrix& m) { 133 | // don't assign to itself 134 | if (this != &m) { 135 | // perform copy 136 | Dim(m.Dim()); 137 | IA(m.IA()); 138 | JA(m.JA()); 139 | (*this)(m()); 140 | } 141 | 142 | // return reference 143 | return (*this); 144 | } 145 | 146 | /** 147 | * matrix addition 148 | * @param m matrix to add to this 149 | * @return result of matrix addition 150 | */ 151 | template 152 | SparseMatrix SparseMatrix::operator+(const SparseMatrix& m) const { 153 | // initialise local variables 154 | typename std::set > sp = m.sparsityPattern(); 155 | SparseMatrix ret(*this); 156 | 157 | // perform addition 158 | for (typename std::set >::iterator i=sp.begin(); i!=sp.end(); i++) 159 | ret((*i).first,(*i).second, 160 | ret((*i).first,(*i).second) + m((*i).first,(*i).second)); 161 | 162 | // return result 163 | return ret; 164 | } 165 | 166 | /** 167 | * matrix subtraction 168 | * @param m matrix to subtract from this 169 | * @return result of matrix subtraction 170 | */ 171 | template 172 | SparseMatrix SparseMatrix::operator-(const SparseMatrix& m) const { 173 | // initialise local variables 174 | typename std::set > sp = m.sparsityPattern(); 175 | SparseMatrix ret(*this); 176 | 177 | // perform subtraction 178 | for (typename std::set >::iterator i=sp.begin(); i!=sp.end(); i++) 179 | ret((*i).first,(*i).second, 180 | ret((*i).first,(*i).second) - m((*i).first,(*i).second)); 181 | 182 | // return result 183 | return ret; 184 | } 185 | 186 | /** 187 | * multiply matrix elements by scalar 188 | * @param alpha scalar multiplier 189 | * @return result of scalar element multiplication 190 | */ 191 | template 192 | SparseMatrix SparseMatrix::operator*(fT alpha) const { 193 | // initalise local variables 194 | SparseMatrix ret(*this); 195 | 196 | // perform multiplication 197 | ret *= alpha; 198 | 199 | // return result 200 | return ret; 201 | } 202 | 203 | /** 204 | * multiply matrix by vector 205 | * @param v vector multiplier 206 | * @return result of vector multiplication 207 | */ 208 | template 209 | vector SparseMatrix::operator*(const vector v) const { 210 | // initialise local variables 211 | fT rowsum; 212 | vector ret; 213 | 214 | // check dimensions 215 | if (Dim() == v.size()) 216 | for (iT i=0; i 233 | SparseMatrix SparseMatrix::operator*(const SparseMatrix& m) const { 234 | // initialise local variables 235 | vector col; // column vector 236 | SparseMatrix ret(Dim()); 237 | 238 | // loop over columns 239 | for (iT j=0; j(m(i,j))); 244 | 245 | // perform multiplication 246 | col = (*this)*col; 247 | 248 | // insert results into return matrix 249 | for (iT i=0; i 263 | SparseMatrix SparseMatrix::operator/(fT alpha) const { 264 | // initalise local variables 265 | SparseMatrix ret(*this); 266 | 267 | // perform multiplication 268 | ret /= alpha; 269 | 270 | // return result 271 | return ret; 272 | } 273 | 274 | /** 275 | * matrix addition 276 | * @param m matrix to add to this 277 | * @return result of matrix addition 278 | */ 279 | template 280 | SparseMatrix& SparseMatrix::operator+=(const SparseMatrix& m) { 281 | // initialise local variables 282 | typename std::set > sp = m.sparsityPattern(); 283 | 284 | // perform addition 285 | for (typename std::set >::iterator i=sp.begin(); i!=sp.end(); i++) 286 | (*this)((*i).first,(*i).second, 287 | (*this)((*i).first,(*i).second) + m((*i).first,(*i).second)); 288 | 289 | // return result 290 | return (*this); 291 | } 292 | 293 | /** 294 | * matrix subtraction 295 | * @param m matrix to subtract from this 296 | * @return result of matrix subtraction 297 | */ 298 | template 299 | SparseMatrix& SparseMatrix::operator-=(const SparseMatrix& m) { 300 | // initialise local variables 301 | typename std::set > sp = m.sparsityPattern(); 302 | 303 | // perform subtraction 304 | for (typename std::set >::iterator i=sp.begin(); i!=sp.end(); i++) 305 | (*this)((*i).first,(*i).second, 306 | (*this)((*i).first,(*i).second) - m((*i).first,(*i).second)); 307 | 308 | // return result 309 | return (*this); 310 | } 311 | 312 | /** 313 | * multiply elements of this matrix by scalar 314 | * @param alpha scalar multiplier 315 | * @return result of scalar element multiplication 316 | */ 317 | template 318 | SparseMatrix& SparseMatrix::operator*=(fT alpha) { 319 | // loop over elements in the a vector and perform multiplication 320 | for (iT i=0; i 332 | SparseMatrix& SparseMatrix::operator/=(fT alpha) { 333 | // loop over elements in the a vector and perform division 334 | for (iT i=0; i 347 | vector SparseMatrix::solve(const vector b) const { 348 | // intialise local variables 349 | fT val, rowsum; 350 | vector ia, ja; 351 | vector a, ret = b; 352 | SparseMatrix m(*this); 353 | 354 | // loop over columns 355 | for (iT col=0; col(1.)/m(col,col); // get value of diagonal 357 | if (fabs(val)>eps_) { 358 | m.rowScale(col,val); // scale matrix row to make diagonal 1 359 | ret.at(col) *= val; // scale output vector 360 | for (iT row=(col+1); row=0; i--) { 380 | rowsum = zero_; 381 | for (iT j=(ia.at(i)+1); j 394 | void SparseMatrix::debug(ostream& os) const { 395 | iT i; 396 | fT total = zero_; 397 | 398 | os << "ia:"; 399 | for (i=0; i(ia_.size()); i++) 400 | os << "\t" << ia_.at(i); 401 | os << endl; 402 | 403 | os << "ja:"; 404 | for (i=0; i(ja_.size()); i++) 405 | os << "\t" << ja_.at(i); 406 | os << endl; 407 | 408 | os << "a:"; 409 | for (i=0; i(a_.size()); i++) { 410 | if (a_.at(i)>=eps_) total++; 411 | os << "\t" << a_.at(i); 412 | } 413 | os << endl << "Sparsity = " << 414 | static_cast((Dim()*Dim()-total)*100)/static_cast(Dim()*Dim()) << "\%"<< endl; 415 | } 416 | 417 | // protected methods 418 | /** 419 | * scale matrix row with specified scalar ie. row = alpha*row 420 | * @param row row to mutiply 421 | * @param alpha scalar multiplier 422 | */ 423 | template 424 | void SparseMatrix::rowScale(iT row, fT alpha) { 425 | for (iT j=ia_.at(row); j 437 | void SparseMatrix::rowOp(iT row_1, iT row_2, fT alpha) { 438 | for (iT j=ia_.at(row_2); j 450 | iT SparseMatrix::findIndex(iT row, iT col) const { 451 | typename vector::const_iterator jit = find(ja_.begin()+ia_.at(row), 452 | ja_.begin()+ia_.at(row+1),col); 453 | return static_cast(distance(ja_.begin(),jit)); 454 | } 455 | 456 | /** 457 | * output this matrix as a sparsity pattern 458 | * @return sparsity pattern (set of pairs, each pair contains row and column of non-zero element) 459 | */ 460 | template 461 | std::set > SparseMatrix::sparsityPattern(void) const { 462 | // initialise local variables 463 | std::set > ret; 464 | 465 | // loop over entries 466 | for (iT i=0; ieps_) ret.insert(make_pair(i,ja_.at(j))); 471 | 472 | // return sparsity pattern 473 | return ret; 474 | } 475 | 476 | /** 477 | * create this matrix from a sparsity pattern 478 | * @param sp sparsity pattern (set of pairs, each pair contains row and column of non-zero element) 479 | */ 480 | template 481 | void SparseMatrix::sparsityPattern(const std::set >& sp) { 482 | // initialise local variables 483 | typename std::set >::iterator it; 484 | 485 | // initialise data structure with zeros along diagonal 486 | ia_.clear(); 487 | ja_.clear(); 488 | a_.clear(); 489 | for (iT i=0; i(1.0)); 499 | } 500 | 501 | template class myg::SparseMatrix; 502 | template class myg::SparseMatrix; 503 | 504 | // global functions 505 | /** 506 | * overload << to output SparseMatrix object 507 | */ 508 | template 509 | ostream& operator<<(ostream& os, const SparseMatrix& m) { 510 | for (iT i=0; i& m); 519 | template ostream& operator<<(ostream& os, const SparseMatrix& m); 520 | -------------------------------------------------------------------------------- /SparseMatrix.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SparseMatrix.h 3 | * SparseMatrix 4 | * Murtaza Gulamali (30/11/2006) 5 | * 6 | * This software is released under the terms and conditions of The MIT License: 7 | * http://www.opensource.org/licenses/mit-license.php 8 | */ 9 | 10 | #ifndef SPARSEMATRIX_H 11 | #define SPARSEMATRIX_H 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace myg { 18 | 19 | //! SparseMatrix class 20 | template 21 | class SparseMatrix { 22 | 23 | public: 24 | //! zero 25 | static const fT zero_; 26 | 27 | //! epsilon: a very small number greater than zero 28 | static const fT eps_; 29 | 30 | //! default constructor 31 | SparseMatrix(iT dim=1); 32 | 33 | //! copy constructor 34 | SparseMatrix(const SparseMatrix& m); 35 | 36 | //! default destructor 37 | ~SparseMatrix(void); 38 | 39 | // accessors and mutators for class members 40 | iT Dim(void) const; 41 | void Dim(iT dim); 42 | std::vector& IA(void); 43 | const std::vector& IA(void) const; 44 | void IA(const std::vector& ia); 45 | std::vector& JA(void); 46 | const std::vector& JA(void) const; 47 | void JA(const std::vector& ja); 48 | std::vector& operator()(void); 49 | const std::vector& operator()(void) const; 50 | void operator()(const std::vector& a); 51 | 52 | // accessors and mutators for matrix elements 53 | const fT& operator()(iT row, iT col) const; 54 | void operator()(iT row, iT col, fT val); 55 | 56 | // matrix operator methods 57 | SparseMatrix& operator=(const SparseMatrix& m); 58 | SparseMatrix operator+(const SparseMatrix& m) const; 59 | SparseMatrix operator-(const SparseMatrix& m) const; 60 | SparseMatrix operator*(fT alpha) const; 61 | std::vector operator*(const std::vector v) const; 62 | SparseMatrix operator*(const SparseMatrix& m) const; 63 | SparseMatrix operator/(fT alpha) const; 64 | SparseMatrix& operator+=(const SparseMatrix& m); 65 | SparseMatrix& operator-=(const SparseMatrix& m); 66 | SparseMatrix& operator*=(fT alpha); 67 | SparseMatrix& operator/=(fT alpha); 68 | 69 | // helper methods 70 | std::vector solve(const std::vector b) const; 71 | void debug(std::ostream& os) const; 72 | 73 | protected: 74 | //! number of rows/columns (ie. dimension) of matrix 75 | iT nnu_; 76 | 77 | //! row index pointer vector, ia 78 | std::vector ia_; 79 | 80 | //! column index pointer vector, ja 81 | std::vector ja_; 82 | 83 | //! vector of non-zero elements and diagonal elements of matrix 84 | std::vector a_; 85 | 86 | // protected helper methods 87 | void rowScale(iT row, fT alpha); 88 | void rowOp(iT row_1, iT row_2, fT alpha); 89 | iT findIndex(iT row, iT col) const; 90 | std::set > sparsityPattern(void) const; 91 | void sparsityPattern(const std::set >& sp); 92 | 93 | }; // end of SparseMatrix class 94 | 95 | // inline methods for speed 96 | 97 | //! return matrix dimension 98 | template 99 | inline iT SparseMatrix::Dim(void) const { return nnu_; } 100 | 101 | //! set matrix dimension 102 | template 103 | inline void SparseMatrix::Dim(iT dim) { nnu_ = dim; } 104 | 105 | //! return row pointer vector 106 | template 107 | inline std::vector& SparseMatrix::IA(void) { return this->ia_; } 108 | 109 | //! return copy of row pointer vector 110 | template 111 | inline const std::vector& SparseMatrix::IA(void) const { return ia_; } 112 | 113 | //! set row pointer vector to specified vector 114 | template 115 | inline void SparseMatrix::IA(const std::vector& ia) { ia_ = ia; } 116 | 117 | //! return column pointer vector 118 | template 119 | inline std::vector& SparseMatrix::JA(void) { return this->ja_; } 120 | 121 | //! return copy of column pointer vector 122 | template 123 | inline const std::vector& SparseMatrix::JA(void) const { return ja_; } 124 | 125 | //! set column pointer vector to specified vector 126 | template 127 | inline void SparseMatrix::JA(const std::vector& ja) { ja_ = ja; } 128 | 129 | //! return vector of non-zero elements and diagonal elements of matrix 130 | template 131 | inline std::vector& SparseMatrix::operator()(void) { return this->a_; } 132 | 133 | //! return copy of vector of non-zero elements and diagonal elements of matrix 134 | template 135 | inline const std::vector& SparseMatrix::operator()(void) const { return a_; } 136 | 137 | //! set vector of non-zero elements and diagonal elements of matrix to specified vector 138 | template 139 | inline void SparseMatrix::operator()(const std::vector& a) { a_ = a; } 140 | 141 | } // end of namespace myg 142 | 143 | //! overload operator to allow output to a stream 144 | template 145 | std::ostream& operator<<(std::ostream& os,const myg::SparseMatrix& m); 146 | 147 | #endif 148 | -------------------------------------------------------------------------------- /demo.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SparseMatrixDemo.cpp 3 | * SparseMatrix 4 | * Murtaza Gulamali (02/12/2006) 5 | * 6 | * Simple demo to set up a sparse matrix object A and vector b, and use them 7 | * to solve the equation Ax = b for vector x. 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "SparseMatrix.h" 14 | 15 | using namespace std; 16 | using namespace myg; 17 | 18 | int main(int argc, char* argv[]) { 19 | /* setup matrix A 20 | * [[1 2 0 0 0 0]; 21 | * [7 4 3 0 0 0]; 22 | * [0 0 6 0 0 0]; 23 | * [9 0 0 1 0 2]; 24 | * [0 0 8 7 1 0]; 25 | * [0 0 0 1 0 1]] 26 | */ 27 | SparseMatrix A(6); // 6x6 identity matrix 28 | A(0,1,2.); 29 | A(1,0,7.); 30 | A(1,1,4.); 31 | A(1,2,3.); 32 | A(2,2,6.); 33 | A(3,0,9.); 34 | A(3,5,2.); 35 | A(4,2,8.); 36 | A(4,3,7.); 37 | A(5,3,1.); 38 | 39 | // setup vector b 40 | // [1 2 3 4 5 6]^T 41 | vector b; 42 | for (int i=1; i<=6; i++) 43 | b.push_back((double) i); 44 | 45 | // solve equation Ax = b for x 46 | vector x = A.solve(b); 47 | 48 | // output results to stdout 49 | cout << "Matrix A:" << "\n" << A << endl; 50 | cout << "Vector b:" << "\n"; 51 | for (unsigned int i=0; i 11 | #include 12 | #include 13 | #include "gtest/gtest.h" 14 | #include "SparseMatrix.h" 15 | 16 | using namespace std; 17 | using namespace myg; 18 | 19 | //! class to store fixture data for tests 20 | class SparseMatrixTest : public ::testing::Test { 21 | protected: 22 | SparseMatrixTest() : 23 | _a(SparseMatrix(4)), 24 | _b(SparseMatrix(4)) 25 | {} 26 | 27 | ~SparseMatrixTest() 28 | {} 29 | 30 | virtual void SetUp() { 31 | /* 32 | * [[0.5 0.0 0.0 0.0] 33 | * [1.0 2.0 0.0 0.0] 34 | * [0.0 0.0 0.5 1.5] 35 | * [0.0 0.0 0.0 0.5]] 36 | */ 37 | _a(1,0,2.0); 38 | _a(1,1,4.0); 39 | _a(2,3,3.0); 40 | _a /= 2.0; 41 | 42 | /* 43 | * [[2.0 4.0 0.0 0.0] 44 | * [0.0 2.0 0.0 6.0] 45 | * [0.0 0.0 2.0 0.0] 46 | * [0.0 0.0 0.0 2.0]] 47 | */ 48 | _b(0,1,2.0); 49 | _b(1,3,3.0); 50 | _b *= 2.0; 51 | } 52 | 53 | //virtual void TearDown() {} 54 | 55 | SparseMatrix _a; 56 | SparseMatrix _b; 57 | }; 58 | 59 | // TESTS! 60 | 61 | TEST_F(SparseMatrixTest,DefaultConstructor) { 62 | unsigned int dim(3); 63 | SparseMatrix x(dim); 64 | for (unsigned int i=0; i e(4), o(4); 87 | e(0,0,2.5); 88 | e(0,1,4.0); 89 | e(1,0,1.0); 90 | e(1,1,4.0); 91 | e(1,3,6.0); 92 | e(2,2,2.5); 93 | e(2,3,1.5); 94 | e(3,3,2.5); 95 | 96 | // perform matrix addition 97 | o = _a+_b; 98 | 99 | // perform test 100 | for (unsigned int i=0; i<4; i++) 101 | for (unsigned int j=0; j<4; j++) 102 | EXPECT_DOUBLE_EQ(e(i,j),o(i,j)); 103 | } 104 | 105 | TEST_F(SparseMatrixTest,MatrixSubtraction) { 106 | SparseMatrix e(4), o(4); 107 | e(0,0,-1.5); 108 | e(0,1,-4.0); 109 | e(1,0, 1.0); 110 | e(1,1, 0.0); 111 | e(1,3,-6.0); 112 | e(2,2,-1.5); 113 | e(2,3, 1.5); 114 | e(3,3,-1.5); 115 | 116 | // perform matrix subtraction 117 | o = _a-_b; 118 | 119 | // perform test 120 | for (unsigned int i=0; i<4; i++) 121 | for (unsigned int j=0; j<4; j++) 122 | EXPECT_DOUBLE_EQ(e(i,j),o(i,j)); 123 | } 124 | 125 | TEST_F(SparseMatrixTest,MatrixMultiplication) { 126 | SparseMatrix e(4), o(4); 127 | e(0,0, 1.0); 128 | e(0,1, 2.0); 129 | e(1,0, 2.0); 130 | e(1,1, 8.0); 131 | e(1,3,12.0); 132 | e(2,2, 1.0); 133 | e(2,3, 3.0); 134 | e(3,3, 1.0); 135 | 136 | // perform matrix multiplication 137 | o = _a*_b; 138 | 139 | // perform test 140 | for (unsigned int i=0; i<4; i++) 141 | for (unsigned int j=0; j<4; j++) 142 | EXPECT_DOUBLE_EQ(e(i,j),o(i,j)); 143 | } 144 | 145 | TEST_F(SparseMatrixTest,VectorSolve) { 146 | /* 147 | * [[1 2 0 0 0 0]; 148 | * [7 4 3 0 0 0]; 149 | * [0 0 6 0 0 0]; 150 | * [9 0 0 1 0 2]; 151 | * [0 0 8 7 1 0]; 152 | * [0 0 0 1 0 1]] 153 | */ 154 | SparseMatrix A(6); 155 | A(0,1,2.0); 156 | A(1,0,7.0); 157 | A(1,1,4.0); 158 | A(1,2,3.0); 159 | A(2,2,6.0); 160 | A(3,0,9.0); 161 | A(3,5,2.0); 162 | A(4,2,8.0); 163 | A(4,3,7.0); 164 | A(5,3,1.0); 165 | 166 | // [1 2 3 4 5 6].' 167 | vector b; 168 | for (unsigned int i=1; i<=6; i++) 169 | b.push_back((double) i); 170 | 171 | // solve equation Ax = b for x 172 | vector x = A.solve(b); 173 | 174 | // compute residual vector 175 | vector r = A*x; 176 | for (unsigned int i=0; i