/* SparseMatrix.h Written by Matthew Fisher a sparse matrix structure. For now this assumes all matrix elements are of type T, defined in DenseMatrix.h. It should instead be templatized. */ // // Namespace for helper functions related to Vector, such as multiplying or adding two // vectors. // namespace RealVector { template static void Multiply(Vector &Result, T Scale, const Vector &V); template static void Multiply(Vector &Result, const Vector &V, T Scale); template static T DotProduct(const Vector &L, const Vector &R); template static void Add(Vector &Result, const Vector &L, const Vector &R); template static void Subtract(Vector &Result, const Vector &L, const Vector &R); } template struct SparseElement { int Col; T Entry; }; template struct SparseRow { SparseRow() {} SparseRow(const SparseRow &S) { Data = S.Data; } SparseRow& operator = (const SparseRow &S) { Data = S.Data; return *this; } ~SparseRow() { FreeMemory(); } void FreeMemory(); void PushElement(UINT Col, T Entry); bool FindElement(UINT Col, const SparseElement* &Output) const; bool FindElement(UINT Col, SparseElement* &Output); Vector > Data; }; template class SparseMatrix { public: // // Constructors // SparseMatrix(); explicit SparseMatrix(UINT Size); explicit SparseMatrix(UINT RowCount, UINT ColCount); SparseMatrix(const SparseMatrix &M); SparseMatrix& operator = (const SparseMatrix &M); // // Destructors // ~SparseMatrix(); void FreeMemory(); // // Memory // void Allocate(UINT Size); void Allocate(UINT _RowCount, UINT _ColCount); void Init(const Vector &DiagonalEntries); // // Helper functions // UINT TotalElements(); bool Square() const; bool Symmetric() const; SparseMatrix Transpose() const; SparseMatrix DiagonalInverse() const; T Compare(const SparseMatrix &In); // // Output // void Dump(ostream &os, bool Sparse); void MathematicaDump(ostream &os, bool Sparse) const; // // Modifiers // SparseMatrix& operator *= (T B); void PushElement(UINT Row, UINT Col, T Entry); __forceinline void PushDiagonalElement(UINT Row, T Entry) { PushElement(Row, Row, Entry); } // // Accessors // __forceinline UINT RowCount() const { return _RowCount; } __forceinline UINT ColCount() const { return _ColCount; } __forceinline Vector >& Rows() { return _Rows; } __forceinline const Vector >& Rows() const { return _Rows; } __forceinline T GetElement(UINT Row, UINT Col) const { Assert(Row < _RowCount && Col < _ColCount, "Invalid Element"); const SparseElement *Output; bool Found = _Rows[Row].FindElement(Col, Output); if(Found) { return Output->Entry; } else { return 0.0; } } // // Static helper functions for functional-style sparse matrix manipulation. Since the copy constructor // for a sparse matrix can be costly, this approach may be more efficient that using operator overloading. // static void Multiply(SparseMatrix &A, T C); static void Multiply(Vector &Output, const SparseMatrix &M, const Vector &V); static void MultiplyTranspose(SparseMatrix &Output, const SparseMatrix &A, const SparseMatrix &B); static void Multiply(SparseMatrix &Output, const SparseMatrix &A, const SparseMatrix &B); static T Multiply(const SparseRow &L, const Vector &R); static void Add(SparseMatrix &A, const SparseMatrix &B, const SparseMatrix &C); static void Subtract(SparseMatrix &A, const SparseMatrix &B, const SparseMatrix &C); private: Vector > _Rows; UINT _RowCount, _ColCount; }; template __forceinline SparseMatrix operator + (const SparseMatrix &A, const SparseMatrix &B) { SparseMatrix Result; SparseMatrix::Add(Result, A, B); return Result; } template __forceinline SparseMatrix operator - (const SparseMatrix &A, const SparseMatrix &B) { SparseMatrix Result; SparseMatrix::Subtract(Result, A, B); return Result; } template __forceinline SparseMatrix operator * (const SparseMatrix &A, const SparseMatrix &B) { SparseMatrix Result; SparseMatrix::Multiply(Result, A, B); return Result; } template __forceinline SparseMatrix operator * (const SparseMatrix &A, T B) { SparseMatrix Result; Result = A; SparseMatrix::Multiply(Result, B); return Result; } template __forceinline Vector operator * (const SparseMatrix &M, const Vector &V) { Vector Result(M.RowCount()); SparseMatrix::Multiply(Result, M, V); return Result; } template __forceinline Vector operator + (const Vector &L, const Vector &R) { Assert(L.Length() == R.Length(), "Invalid vector dimensions"); Vector Result(L.Length()); for(UINT i = 0; i < L.Length(); i++) { Result[i] = L[i] + R[i]; } return Result; } template __forceinline Vector operator - (const Vector &L, const Vector &R) { Assert(L.Length() == R.Length(), "Invalid vector dimensions"); Vector Result(L.Length()); for(UINT i = 0; i < L.Length(); i++) { Result[i] = L[i] - R[i]; } return Result; } #include "SparseMatrix.cpp"