#ifndef __sparsemat #define __sparsemat #include // STL vector #include // STL list #include // STL pair #include #include // STL ostream_iterator using namespace std; template class sparsemat { // specialized templates (in this case, with a template parameter type) friend ostream& operator<< <> (ostream&, const sparsemat&); friend istream& operator>> <> (istream&, sparsemat&); 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::row_type // and sparsemat::row_iter (in put_value, e.g,), // sparsemat::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& 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& 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< >::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 ostream& operator<<(ostream& os, const pair< int, Field >& entry) // needed in sparsemat::print {os << "(" << entry.first << ", " << entry.second << ")"; return os; }// end << pair< int, Field > }// end namespace std template ostream& operator<<(ostream& os, const sparsemat& 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 template istream& operator>>(istream& is, sparsemat& 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 #endif