SparseMatrix.h

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library 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 License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #ifndef SOFA_COMPONENT_LINEARSOLVER_SPARSEMATRIX_H
00026 #define SOFA_COMPONENT_LINEARSOLVER_SPARSEMATRIX_H
00027 
00028 #include <sofa/defaulttype/BaseMatrix.h>
00029 #include <sofa/simulation/common/MatrixLinearSolver.h>
00030 #include "FullVector.h"
00031 
00032 #include <map>
00033 
00034 namespace sofa
00035 {
00036 
00037 namespace component
00038 {
00039 
00040 namespace linearsolver
00041 {
00042 
00043 //#define SPARSEMATRIX_CHECK
00044 //#define SPARSEMATRIX_VERBOSE
00045 
00046 template<typename T>
00047 class SparseMatrix : public defaulttype::BaseMatrix
00048 {
00049 public:
00050     typedef T Real;
00051     typedef int Index;
00052     typedef std::map<Index,Real> Line;
00053     typedef std::map<Index,Line> Data;
00054     typedef typename Line::iterator LElementIterator;
00055     typedef typename Line::const_iterator LElementConstIterator;
00056     typedef typename Data::iterator LineIterator;
00057     typedef typename Data::const_iterator LineConstIterator;
00058 
00059 protected:
00060     Data data;
00061     Index nRow,nCol;
00062 
00063 public:
00064 
00065     SparseMatrix()
00066     : nRow(0), nCol(0)
00067     {
00068     }
00069 
00070     SparseMatrix(int nbRow, int nbCol)
00071     : nRow(nbRow), nCol(nbCol)
00072     {
00073     }
00074 
00075     LineIterator begin() { return data.begin(); }
00076     LineIterator end()   { return data.end();   }
00077     LineConstIterator begin() const { return data.begin(); }
00078     LineConstIterator end()   const { return data.end();   }
00079 
00080     Line& operator[](Index i)
00081     {
00082         return data[i];
00083     }
00084 
00085     const Line& operator[](Index i) const
00086     {
00087         static const Line empty;
00088         LineConstIterator it = data.find(i);
00089         if (it==data.end())
00090             return empty;
00091         else
00092             return it->second;
00093     }
00094 
00095     void resize(int nbRow, int nbCol)
00096     {
00097 #ifdef SPARSEMATRIX_VERBOSE
00098         if (nbRow != rowSize() || nbCol != colSize())
00099             std::cout << /* this->Name()  <<  */": resize("<<nbRow<<","<<nbCol<<")"<<std::endl;
00100 #endif
00101         data.clear();
00102         nRow = nbRow;
00103         nCol = nbCol;
00104     }
00105 
00106     int rowSize(void) const
00107     {
00108         return nRow;
00109     }
00110 
00111     int colSize(void) const
00112     {
00113         return nCol;
00114     }
00115 
00116     SReal element(int i, int j) const
00117     {
00118 #ifdef SPARSEMATRIX_CHECK
00119         if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00120         {
00121             std::cerr << "ERROR: invalid read access to element ("<<i<<","<<j<<") in "<</* this->Name() <<*/" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00122             return 0.0;
00123         }
00124 #endif
00125         LineConstIterator it = data.find(i);
00126         if (it==data.end())
00127             return 0.0;
00128         LElementConstIterator ite = it->second.find(j);
00129         if (ite == it->second.end())
00130             return 0.0;
00131         return ite->second;
00132     }
00133 
00134     void set(int i, int j, double v)
00135     {
00136 #ifdef SPARSEMATRIX_VERBOSE
00137         std::cout << /* this->Name()  <<  */"("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") = "<<v<<std::endl;
00138 #endif
00139 #ifdef SPARSEMATRIX_CHECK
00140         if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00141         {
00142             std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<</* this->Name() <<*/" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00143             return;
00144         }
00145 #endif
00146         data[i][j] = (Real)v;
00147     }
00148 
00149     void add(int i, int j, double v)
00150     {
00151 #ifdef SPARSEMATRIX_VERBOSE
00152         std::cout << /* this->Name()  <<  */"("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") += "<<v<<std::endl;
00153 #endif
00154 #ifdef SPARSEMATRIX_CHECK
00155         if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00156         {
00157             std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<</* this->Name() <<*/" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00158             return;
00159         }
00160 #endif
00161         data[i][j] += (Real)v;
00162     }
00163 
00164     void clear(int i, int j)
00165     {
00166 #ifdef SPARSEMATRIX_VERBOSE
00167         std::cout << /* this->Name()  <<  */"("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") = 0"<<std::endl;
00168 #endif
00169 #ifdef SPARSEMATRIX_CHECK
00170         if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00171         {
00172             std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<</* this->Name() <<*/" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00173             return;
00174         }
00175 #endif
00176         LineIterator it = data.find(i);
00177         if (it==data.end())
00178             return;
00179         LElementIterator ite = it->second.find(j);
00180         if (ite == it->second.end())
00181             return;
00182         it->second.erase(ite);
00183         if (it->second.empty())
00184             data.erase(it);
00185     }
00186 
00187     void clearRow(int i)
00188     {
00189 #ifdef SPARSEMATRIX_VERBOSE
00190         std::cout << /* this->Name()  <<  */"("<<rowSize()<<","<<colSize()<<"): row("<<i<<") = 0"<<std::endl;
00191 #endif
00192 #ifdef SPARSEMATRIX_CHECK
00193         if ((unsigned)i >= (unsigned)rowSize())
00194         {
00195             std::cerr << "ERROR: invalid write access to row "<<i<<" in "<</* this->Name() <<*/" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00196             return;
00197         }
00198 #endif
00199         LineIterator it = data.find(i);
00200         if (it==data.end())
00201             return;
00202         data.erase(it);
00203     }
00204 
00205     void clearCol(int j)
00206     {
00207 #ifdef SPARSEMATRIX_VERBOSE
00208         std::cout << /* this->Name()  <<  */"("<<rowSize()<<","<<colSize()<<"): col("<<j<<") = 0"<<std::endl;
00209 #endif
00210 #ifdef SPARSEMATRIX_CHECK
00211         if ((unsigned)j >= (unsigned)colSize())
00212         {
00213             std::cerr << "ERROR: invalid write access to column "<<j<<" in "<</* this->Name() <<*/" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00214             return;
00215         }
00216 #endif
00217         for(LineIterator it=data.begin(),itend=data.end();it!=itend;++it)
00218         {
00219             LElementIterator ite = it->second.find(j);
00220             if (ite != it->second.end())
00221                 it->second.erase(ite);
00222         }
00223     }
00224 
00225     void clearRowCol(int i)
00226     {
00227 #ifdef SPARSEMATRIX_VERBOSE
00228         std::cout << /* this->Name()  <<  */"("<<rowSize()<<","<<colSize()<<"): row("<<i<<") = 0 and col("<<i<<") = 0"<<std::endl;
00229 #endif
00230 #ifdef SPARSEMATRIX_CHECK
00231         if ((unsigned)i >= (unsigned)rowSize() || (unsigned)i >= (unsigned)colSize())
00232         {
00233             std::cerr << "ERROR: invalid write access to row and column "<<i<<" in "<</* this->Name() <<*/" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00234             return;
00235         }
00236 #endif
00237         clearRow(i);
00238         clearCol(i);
00239     }
00240 
00241     void clear() { data.clear(); }
00242     
00243     template<class Real2>
00244     void mul(FullVector<Real2>& res, const FullVector<Real2>& v) const
00245     {
00246         res.resize(rowSize());
00247         for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00248         {
00249             Real2 r = 0;
00250             for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00251                 r += (Real2)ite->second * v[ite->first];
00252             res[itl->first] = r;
00253         }
00254     }
00255     
00256     template<class Real2>
00257     void mulTranspose(FullVector<Real2>& res, const FullVector<Real2>& v) const
00258     {
00259         res.resize(colSize());
00260         for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00261         {
00262             Real2 vi = v[itl->first];
00263             for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00264                 res[ite->first] += (Real2)ite->second * vi;
00265         }
00266     }
00267     
00268     template<class Real2>
00269     void mul(FullVector<Real2>& res, const defaulttype::BaseVector* v) const
00270     {
00271         res.resize(rowSize());
00272         for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00273         {
00274             Real2 r = 0;
00275             for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00276                 r += (Real2)ite->second * (Real2)v->element(ite->first);
00277             res[itl->first] = r;
00278         }
00279     }
00280     
00281     template<class Real2>
00282     void mulTranspose(FullVector<Real2>& res, const defaulttype::BaseVector* v) const
00283     {
00284         res.resize(colSize());
00285         for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00286         {
00287             Real2 vi = v->element(itl->first);
00288             for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00289                 res[ite->first] += (Real2)ite->second * vi;
00290         }
00291     }
00292     
00293     template<class Real2>
00294     void mul(defaulttype::BaseVector* res, const FullVector<Real2>& v) const
00295     {
00296         res->resize(rowSize());
00297         for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00298         {
00299             Real2 r = 0;
00300             for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00301                 r += (Real2)ite->second * v[ite->first];
00302             res->set(itl->first, r);
00303         }
00304     }
00305     
00306     template<class Real2>
00307     void mulTranspose(defaulttype::BaseVector* res, const FullVector<Real2>& v) const
00308     {
00309         res->resize(colSize());
00310         for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00311         {
00312             Real2 vi = v[itl->first];
00313             for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00314                 res->add(ite->first, ite->second * vi);
00315         }
00316     }
00317     
00318     void mul(defaulttype::BaseVector* res, const defaulttype::BaseVector* v) const
00319     {
00320         res->resize(rowSize());
00321         for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00322         {
00323             Real r = 0;
00324             for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00325                 r += ite->second * (Real)v->element(ite->first);
00326             res->set(itl->first, r);
00327         }
00328     }
00329     
00330     void mulTranspose(defaulttype::BaseVector* res, const defaulttype::BaseVector* v) const
00331     {
00332         res->resize(colSize());
00333         for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00334         {
00335             Real vi = (Real)v->element(itl->first);
00336             for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00337                 res->add(ite->first, ite->second * vi);
00338         }
00339     }
00340     
00341     template<class Real2>
00342     FullVector<Real2> operator*(const FullVector<Real2>& v) const
00343     {
00344         FullVector<Real2> res;
00345         mul(res,v);
00346         return res;
00347     }
00348 
00349     friend std::ostream& operator << (std::ostream& out, const SparseMatrix<T>& v )
00350     {
00351         int nx = v.Ncols();
00352         int ny = v.Nrows();
00353         out << "[";
00354         for (int y=0;y<ny;++y)
00355         {
00356             out << "\n[";
00357             for (int x=0;x<nx;++x)
00358             {
00359                 out << " " << v.element(y,x);
00360             }
00361             out << " ]";
00362         }
00363         out << " ]";
00364         return out;
00365     }
00366 
00367     static const char* Name() { return "SparseMatrix"; }
00368 };
00369 
00370 } // namespace linearsolver
00371 
00372 } // namespace component
00373 
00374 } // namespace sofa
00375 
00376 #endif

Generated on Sun Nov 23 03:25:16 2008 for Sofa by  doxygen 1.5.7.1