diff --git a/SpMat.h b/SpMat.h index e10e353c182463acd541c42fe65f7b55ab0765f2..4e39924a80da00d34e8d82d34b4ab5aa0c5482f8 100644 --- a/SpMat.h +++ b/SpMat.h @@ -27,6 +27,7 @@ #include "newmat.h" #include "cg.h" #include "bicg.h" +#include "miscmaths.h" namespace MISCMATHS { @@ -92,6 +93,7 @@ public: SpMat(unsigned int m, unsigned int n) : _m(m), _n(n), _nz(0), _ri(n), _val(n) {} SpMat(unsigned int m, unsigned int n, const unsigned int *irp, const unsigned int *jcp, const double *sp); SpMat(const NEWMAT::GeneralMatrix& M); + SpMat(const std::string& fname); ~SpMat() {} unsigned int Nrows() const {return(_m);} @@ -360,6 +362,64 @@ SpMat<T>::SpMat(const NEWMAT::GeneralMatrix& M) } } +///////////////////////////////////////////////////////////////////// +// +// Constructs matrix from row col val format produced by +// Save/Print below. +// +///////////////////////////////////////////////////////////////////// + +template<class T> +SpMat<T>::SpMat(const std::string& fname) +: _m(0), _n(0), _nz(0), _ri(0), _val(0) +{ + // First read data into (nz+1)x3 NEWMAT matrix + NEWMAT::Matrix rcv; + try { + rcv = read_ascii_matrix(fname); + } + catch(...) { + throw SpMatException("SpMat::SpMat(string& fname): cannot read file given by fname"); + } + // Then interpret it + if (rcv(rcv.Nrows(),3)) throw SpMatException("SpMat::SpMat(string& fname): Last row must have zero value and indicate matrix size"); + _m = static_cast<unsigned int>(rcv(rcv.Nrows(),1)+0.5); + _n = static_cast<unsigned int>(rcv(rcv.Nrows(),2)+0.5); + // cout << "rcv = " << endl << rcv << endl << "_n = " << _n << endl; + _ri.resize(_n); + _val.resize(_n); + // First pass to see how many elements in each colum + std::vector<unsigned int> col_count(_n,0); + unsigned int col = static_cast<unsigned int>(rcv(1,2)+0.5); + for (unsigned int indx=1; indx<static_cast<unsigned int>(rcv.Nrows()); indx++) { + if (static_cast<unsigned int>(rcv(indx,2)+0.5) != col) { + if (static_cast<unsigned int>(rcv(indx,2)+0.5) < col) throw SpMatException("SpMat::SpMat(string& fname): Column index must be monotonously increasing"); + else col = static_cast<unsigned int>(rcv(indx,2)+0.5); + if (col > _n) throw SpMatException("SpMat::SpMat(string& fname): File internally inconsistent"); + } + // cout << "col = " << col << endl; + col_count[col-1]++; + } + // Second pass to allocate and fill vectors + unsigned int indx=1; + for (col=0; col<_n; col++) { + std::vector<unsigned int>& ri = _ri[col]; + std::vector<T>& val = _val[col]; + ri.resize(col_count[col]); + val.resize(col_count[col]); + for (unsigned int i=0; i<col_count[col]; i++, indx++) { + if (i && ri[i] >= static_cast<unsigned int>(rcv(indx,1)+0.5)) throw SpMatException("SpMat::SpMat(string& fname): Row index must be monotonously increasing"); + if (static_cast<unsigned int>(rcv(indx,1)+0.5) < 1 || static_cast<unsigned int>(rcv(indx,1)+0.5) > _m) { + throw SpMatException("SpMat::SpMat(string& fname): Row index outside 1 -- -m range"); + } + ri[i] = static_cast<unsigned int>(rcv(indx,1)+0.5) - 1; + val[i] = rcv(indx,3); + _nz++; + } + } +} + + ///////////////////////////////////////////////////////////////////// // // Returns matrix in NEWMAT matrix format. Useful for debugging