QGpCoreTools/SparseMatrix.h
Go to the documentation of this file.
00001 /***************************************************************************
00002 **
00003 **  This file is part of QGpCoreTools.
00004 **
00005 **  This library is free software; you can redistribute it and/or
00006 **  modify it under the terms of the GNU Lesser General Public
00007 **  License as published by the Free Software Foundation; either
00008 **  version 2.1 of the License, or (at your option) any later version.
00009 **
00010 **  This file is distributed in the hope that it will be useful, but WITHOUT
00011 **  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 **  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
00013 **  License for more details.
00014 **
00015 **  You should have received a copy of the GNU Lesser General Public
00016 **  License along with this library; if not, write to the Free Software
00017 **  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018 **
00019 **  See http://www.geopsy.org for more information.
00020 **
00021 **  Created: 2013-02-12
00022 **  Authors:
00023 **    Marc Wathelet (ISTerre, Grenoble, France)
00024 **
00025 ***************************************************************************/
00026 
00027 #ifndef SPARSEMATRIX_H
00028 #define SPARSEMATRIX_H
00029 
00030 #include "Matrix.h"
00031 #include "QGpCoreToolsDLLExport.h"
00032 
00033 namespace QGpCoreTools {
00034 
00035   template <typename T> class QGPCORETOOLS_EXPORT SparseMatrix
00036   {
00037   public:
00038     SparseMatrix();
00039     SparseMatrix(int nrow, int ncol);
00040 
00041     bool operator==(const Matrix<T>& m) const;
00042 
00043     int rowCount() const {return _nrow;}
00044     int columnCount() const {return _ncol;}
00045     int realRowCount() const {return _values.count();}
00046     int valueCount() const;
00047 
00048     void clear();
00049     void setRowCount(int nrow);
00050     void setColumnCount(int ncol);
00051 
00052     T at(int row, int col) const;
00053     T& at(int row, int col);
00054 
00055     typedef QHash<int, T> Row;
00056     typedef typename QHash<int, Row>::ConstIterator ConstRowIterator;
00057     typedef typename QHash<int, Row>::Iterator RowIterator;
00058     typedef typename Row::ConstIterator ConstColumnIterator;
00059     typedef typename Row::Iterator ColumnIterator;
00060 
00061     Row& addRow(int row);
00062 
00063     ConstRowIterator begin() const {return _values.begin();}
00064     RowIterator begin() {return _values.begin();}
00065     ConstRowIterator end() const {return _values.end();}
00066     RowIterator end() {return _values.end();}
00067 
00068     Matrix<T> plainMatrix() const;
00069     void setPlainMatrix(const Matrix<T>& m);
00070 
00071     Matrix<T> operator*(const Matrix<T>& m) const;
00072 
00073     QString toUserString(int precision=6, char format='g') const;
00074   private:
00075     int _nrow, _ncol;
00076     QHash<int, Row> _values;
00077   };
00078 
00079   template <typename T> SparseMatrix<T>::SparseMatrix()
00080   {
00081     _nrow=0;
00082     _ncol=0;
00083   }
00084 
00085   template <typename T> SparseMatrix<T>::SparseMatrix(int nrow, int ncol)
00086   {
00087     _nrow=nrow;
00088     _ncol=ncol;
00089   }
00090 
00091   template <typename T> bool SparseMatrix<T>::operator==(const Matrix<T>& m) const
00092   {
00093     if(_nrow!=m.rowCount() || _ncol!=m.columnCount()) {
00094       return false;
00095     }
00096     for(int ir=0; ir<_nrow; ir++) {
00097       for(int ic=0; ic<_ncol; ic++) {
00098         const T& v=m.at(ir, ic);
00099         if(v!=0.0 && at(ir, ic)!=v) {
00100           return false;
00101         }
00102       }
00103     }
00104     return true;
00105   }
00106 
00107   template <typename T> Matrix<T> SparseMatrix<T>::plainMatrix() const
00108   {
00109     Matrix<T> m(_nrow, _ncol);
00110     for(int ir=0; ir<_nrow; ir++) {
00111       ConstRowIterator itr=_values.constFind(ir);
00112       if(itr!=_values.end()) {
00113         const Row& rowHash=itr.value();
00114         for(int ic=0; ic<_ncol; ic++) {
00115           ConstColumnIterator itc=rowHash.constFind(ic);
00116           if(itc!=rowHash.end()) {
00117             m.at(ir, ic)=itc.value();
00118           } else {
00119             m.at(ir, ic)=0.0;
00120           }
00121         }
00122       } else {
00123         for(int ic=0; ic<_ncol; ic++) {
00124           m.at(ir,ic)=0.0;
00125         }
00126       }
00127     }
00128     return m;
00129   }
00130 
00131   template <typename T> void SparseMatrix<T>::setPlainMatrix(const Matrix<T>& m)
00132   {
00133     clear();
00134     setRowCount(m.rowCount());
00135     setColumnCount(m.columnCount());
00136     for(int ir=0; ir<_nrow; ir++) {
00137       for(int ic=0; ic<_ncol; ic++) {
00138         const T& v=m.at(ir, ic);
00139         if(v!=0.0) {
00140           at(ir, ic)=v;
00141         }
00142       }
00143     }
00144   }
00145 
00146   template <typename T> int SparseMatrix<T>::valueCount() const
00147   {
00148     int n=0;
00149     for(ConstRowIterator itr=_values.begin(); itr!=_values.end(); itr++) {
00150       const Row& rowHash=itr.value();
00151       n+=rowHash.count();
00152     }
00153     return n;
00154   }
00155 
00156   template <typename T> Matrix<T> SparseMatrix<T>::operator*(const Matrix<T>& m) const
00157   {
00158     Matrix<T> r(_nrow, m.columnCount());
00159     for(int ir=0; ir<_nrow; ir++) {
00160      ConstRowIterator itr=_values.constFind(ir);
00161       if(itr!=_values.end()) {
00162         const Row& rowHash=itr.value();
00163         for(int ic=0; ic<m.columnCount(); ic++) {
00164           T s=0.0;
00165           for(ConstColumnIterator itc=rowHash.begin(); itc!=rowHash.end(); itc++) {
00166             s+=itc.value()*m.at(itc.key(), ic);
00167           }
00168           r.at(ir, ic)=s;
00169         }
00170       } else {
00171         for(int ic=0; ic<r.columnCount(); ic++) {
00172           r.at(ir,ic)=0.0;
00173         }
00174       }
00175     }
00176     return r;
00177   }
00178 
00179   template <typename T> void SparseMatrix<T>::clear()
00180   {
00181     _nrow=0;
00182     _ncol=0;
00183     _values.clear();
00184   }
00185 
00186   template <typename T> void SparseMatrix<T>::setRowCount(int nrow)
00187   {
00188     _nrow=nrow;
00189     for(RowIterator itr=_values.begin(); itr!=_values.end(); itr++) {
00190       if(itr.key()>=nrow) {
00191         _values.remove(itr.key());
00192       }
00193     }
00194   }
00195 
00196   template <typename T> void SparseMatrix<T>::setColumnCount(int ncol)
00197   {
00198     _ncol=ncol;
00199     for(RowIterator itr=_values.begin(); itr!=_values.end(); itr++) {
00200       Row& rowHash=itr.value();
00201       for(ColumnIterator itc=rowHash.begin(); itc!=rowHash.end(); itc++) {
00202         if(itc.key()>=ncol) {
00203           rowHash.remove(itc.key());
00204         }
00205       }
00206     }
00207   }
00208 
00209   template <typename T> typename SparseMatrix<T>::Row& SparseMatrix<T>::addRow(int row)
00210   {
00211     RowIterator itr=_values.insert(row, QHash<int, T>());
00212     return itr.value();
00213   }
00214 
00215   template <typename T> T SparseMatrix<T>::at(int row, int col) const
00216   {
00217     ConstRowIterator itr=_values.constFind(row);
00218     if(itr!=_values.end()) {
00219       const Row& rowHash=itr.value();
00220       ConstColumnIterator itc=rowHash.constFind(col);
00221       if(itc!=rowHash.end()) {
00222         return itc.value();
00223       } else {
00224         return 0.0;
00225       }
00226     } else {
00227       return 0.0;
00228     }
00229   }
00230 
00231   template <typename T> T& SparseMatrix<T>::at(int row, int col)
00232   {
00233     RowIterator itr=_values.find(row);
00234     if(itr!=_values.end()) {
00235       Row& rowHash=itr.value();
00236       ColumnIterator itc=rowHash.find(col);
00237       if(itc!=rowHash.end()) {
00238         return itc.value();
00239       } else {
00240         ColumnIterator itc=rowHash.insert(col, 0.0);
00241         return itc.value();
00242       }
00243     } else {
00244       Row& rowHash=addRow(row);
00245       ColumnIterator itc=rowHash.insert(col, 0.0);
00246       return itc.value();
00247     }
00248   }
00249 
00250   template <typename T> QString SparseMatrix<T>::toUserString(int precision, char format) const
00251   {
00252     QString str("    | ");
00253     for(int j=0; j<_ncol; j++) {
00254       str+=QString(" %1 |").arg(j, 12, 10, QChar(' '));
00255     }
00256     str+="\n----|-";
00257     for(int j=0; j<_ncol; j++) {
00258       str+="--------------|";
00259     }
00260     str+="\n";
00261     for(int i=0; i<_nrow; i++) {
00262       str+=QString("%1 | ").arg(i, 3, 10, QChar(' '));
00263       for(int j=0; j<_ncol; j++) {
00264         str+=QString(" %1 |").arg(Number::toDouble(at(i, j)), 12, format, precision, QChar(' '));
00265       }
00266       str+="\n";
00267     }
00268     str+="----|-";
00269     for(int j=0; j<_ncol; j++) {
00270       str+="--------------|";
00271     }
00272     str+="\n";
00273     return str;
00274   }
00275 
00276   template <typename T> QDataStream& operator<<(QDataStream& s, const SparseMatrix<T>& m)
00277   {
00278     s << m.rowCount() << m.columnCount();
00279     s << m.realRowCount();
00280     for(typename SparseMatrix<T>::ConstRowIterator itr=m.begin(); itr!=m.end(); itr++) {
00281       const typename SparseMatrix<T>::Row& rowHash=itr.value();
00282       s << itr.key() << rowHash.count();
00283       for(typename SparseMatrix<T>::ConstColumnIterator itc=rowHash.begin(); itc!=rowHash.end(); itc++) {
00284         s<< itc.key() << itc.value();
00285       }
00286     }
00287     return s;
00288   }
00289 
00290   template <typename T> QDataStream& operator>>(QDataStream& s, SparseMatrix<T>& m)
00291   {
00292     m.clear();
00293     int nrow, ncol;
00294     s >> nrow >> ncol;
00295     m.setRowCount(nrow);
00296     m.setColumnCount(ncol);
00297     s >> nrow;
00298     int index;
00299     T value;
00300     for(int ir=0; ir<nrow; ir++) {
00301       s >> index >> ncol;
00302       typename SparseMatrix<T>::Row& rowHash=m.addRow(index);
00303       for(int ic=0; ic<ncol; ic++) {
00304         s >> index >> value;
00305         rowHash.insert(index, value);
00306       }
00307     }
00308     return s;
00309   }
00310 
00311 } // namespace QGpCoreTools
00312 
00313 #endif // SPARSEMATRIX_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines