Click on sparsemat.h to get source.
#ifndef __sparsemat
#define __sparsemat
#include <vector> // STL vector
#include <list> // STL list
#include <utility> // STL pair
#include <iostream>
#include <iterator> // STL ostream_iterator
using namespace std;
template <class Field> class sparsemat; // forward declare template class,
// which is used in << and >>
template <class Field> // must declare before friend declaration in
// template class sparsemat
ostream& operator<<(ostream& os, const sparsemat<Field>& A) {
ostream_iterator< pair< int, Field > > out(os, " ");
for (int i = 1; i <= A.m; i++) {
os << "Row " << i << ": ";
os.flush();
copy(A.A[i].begin(), A.A[i].end(), out);
os << endl;
} // for (;;)
return os;
}// end operator<< sparsemat<Field>
template <class Field>
istream& operator>>(istream& is, sparsemat<Field>& A) {
// reads the elements of a sparse matrix by reading in
// a list of 3 items, first the row and column index and then a field element.
int i; int j;
Field a(0);
while (is >> i) {
// operator>> returns a reference to an istream
// then istream::operator void*() is called which
// returns !basic_ios::fail() [Stroutstrup, p.617, ???]
if(i < 0) break; // return also if row index is negative
is >> j >> a;
A.put_value(make_pair(i,j), a);
} // while-loop
return is;
} // operator>> sparsemat<Field>
template <class Field>
class sparsemat {
// specialized templates (in this case, with a template parameter type)
friend ostream& operator<< <> (ostream&, const sparsemat<Field>&);
friend istream& operator>> <> (istream&, sparsemat<Field>&);
vector< list< pair< int, Field > > > A; // sparse matrix data struct
// A[i], the i-th row, is an STL list< pair< int, Field > >.
// Each list entry is a column index/value pair
int m; // rowdimension from 1..m; the actual dimensions
int n; // coldimension from 1..n; the actual dimensions
typedef list< pair< int, Field > > row_type;
typedef typename list< pair< int, Field > >::iterator row_iter;
typedef typename list< pair< int, Field > >::const_iterator const_row_iter;
// shorthands:
// can write template member functions with sparsemat<Field>::row_type
// and sparsemat<Field>::row_iter (in put_value, e.g,),
// sparsemat<Field>::const_row_iter (in operator[])
class comp_w_col_ind {
public:
bool operator() (const pair< int, Field >& entry, int col_in)
{return entry.first < col_in; }
};
// used in lower_bound as function object
public:
sparsemat(int m_init, int n_init) :
// constructs a matrix of the given dimensions with all 0s
A(m_init+1, list< pair< int, Field > >() ),
// initialize each list in the vector as empty list
m(m_init), n(n_init)
// set the dimensions
{}
// note: the copy constructor and operator= will work as intended
// because of STL's container design
int get_rowdim() const {return m;}
int get_coldim() const {return n;}
Field operator[] (const pair<int, int>& ind) const;
// return: a copy of the element A[ind.first, ind.second]
// example: A[make_pair(3, 5)]
// exceptions: if the indices are out of range, an error is printed
// and Field(0) is returned
// note: unlike STL vector's operator[] this member does
// not return a reference to the Field element in the matrix
// it is therefore impossible to write
// A[make_pair(3, 5)] = Field(1);
// the reason is that zero entries have no memory where
// one could place the right side field element
void put_value (const pair<int, int>& ind, const Field& a);
// sets A[ind.first, ind.second] = a
// example: A.put_value(make_pair(3, 5), Field(-4))
// exceptions: if the indices are out of range, an error is printed
// note: if a==Field(0) no cell will be inserted
// and an already existing cell for the entry will be erased
sparsemat& linsolve(sparsemat& b);
// arguments: b must be an m by 1 matrix
// return: an n by 1 matrix x such that A * x = b
// exceptions: if the system does not have a unique solution,
// an error is printed and a zero matrix returned
// See: www.math.ncsu.edu/~kaltofen/courses/LinAlgebra/Maple/refpkg/Src/ref.mpl
// for a Maple row echelon form algorithm
void swaprow(int i, int j); // exchanges row i and j in A
// auxiliary member function to linsolve
// note: uses list< <int, Field> >::swap
void addrow(int i, int j, const Field& a);
// auxiliary member function to linsolve
// adds a*(row i) to (row j) in A
// ALTERNATIVE to linsolve: matrix times vector product
sparsemat& lintrafo(sparsemat& b);
// arguments: b must be an n by 1 matrix
// return: an m by 1 matrix y such that y = A * b
};// end template class sparsemat
namespace std {// peculiarity of overloading
// << is called from a member function in std, which already
// has operator<< declared, so it will not overload outside the std namespace
template <class Field>
ostream& operator<<(ostream& os, const pair< int, Field >& entry)
// needed in sparsemat<Field>::print
{os << "(" << entry.first << ", " << entry.second << ")";
return os;
}// end << pair< int, Field >
}// end namespace std
#endif