sparse_matrix.hpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2009-2012, Willow Garage, Inc.
00006  *  Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho,
00007  *                      Johns Hopkins University
00008  *
00009  *  All rights reserved.
00010  *
00011  *  Redistribution and use in source and binary forms, with or without
00012  *  modification, are permitted provided that the following conditions
00013  *  are met:
00014  *
00015  *   * Redistributions of source code must retain the above copyright
00016  *     notice, this list of conditions and the following disclaimer.
00017  *   * Redistributions in binary form must reproduce the above
00018  *     copyright notice, this list of conditions and the following
00019  *     disclaimer in the documentation and/or other materials provided
00020  *     with the distribution.
00021  *   * Neither the name of Willow Garage, Inc. nor the names of its
00022  *     contributors may be used to endorse or promote products derived
00023  *     from this software without specific prior written permission.
00024  *
00025  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00026  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00027  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00028  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00029  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00030  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00031  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00032  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00033  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00034  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00035  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00036  *  POSSIBILITY OF SUCH DAMAGE.
00037  *
00038  * $Id: sparse_matrix.hpp 5036 2012-03-12 08:54:15Z rusu $
00039  *
00040  */
00041 
00042 #include <float.h>
00043 
00044 
00045 namespace pcl 
00046 {
00047   namespace poisson 
00048   {
00050     //  SparseMatrix //
00053     // Static Allocator Methods and Memebers //
00055     template<class T> int SparseMatrix<T>::UseAlloc=0;
00056     template<class T> Allocator<MatrixEntry<T> > SparseMatrix<T>::AllocatorMatrixEntry;
00057     template<class T> int SparseMatrix<T>::UseAllocator(void){return UseAlloc;}
00058     template<class T>
00059     void SparseMatrix<T>::SetAllocator(const int& blockSize){
00060       if(blockSize>0){
00061         UseAlloc=1;
00062         AllocatorMatrixEntry.set(blockSize);
00063       }
00064       else{UseAlloc=0;}
00065     }
00067     // SparseMatrix Methods and Memebers //
00069 
00071     template<class T>
00072     SparseMatrix<T>::SparseMatrix () : rows (0), rowSizes (NULL), m_ppElements (NULL)
00073     {
00074     }
00075 
00077     template<class T>
00078     SparseMatrix<T>::SparseMatrix (int rows) : rows (rows), rowSizes (NULL), m_ppElements (NULL)
00079     {
00080       Resize (rows);
00081     }
00082 
00084     template<class T>
00085     SparseMatrix<T>::SparseMatrix (const SparseMatrix& M) :
00086       rows (M.rows), rowSizes (M.rowSizes), m_ppElements (M.m_ppElements)
00087     {
00088       Resize (M.rows);
00089       for (int i = 0; i < rows; i++)
00090       {
00091         SetRowSize (i, M.rowSizes[i]);
00092         for (int j = 0; j < rowSizes[i]; j++)
00093           m_ppElements[i][j] = M.m_ppElements[i][j];
00094       }
00095     }
00096 
00098     template<class T> int 
00099     SparseMatrix<T>::Entries ()
00100     {
00101       int e = 0;
00102       for (int i = 0; i < rows; i++)
00103         e += int (rowSizes[i]);
00104 
00105       return (e);
00106     }
00107 
00109     template<class T>
00110     SparseMatrix<T>& SparseMatrix<T>::operator = (const SparseMatrix<T>& M)
00111     {
00112       Resize(M.rows);
00113       for (int i=0; i<rows; i++){
00114         SetRowSize(i,M.rowSizes[i]);
00115         for (int j=0; j<rowSizes[i]; j++){m_ppElements[i][j]=M.m_ppElements[i][j];}
00116       }
00117       return *this;
00118     }
00119 
00121     template<class T>
00122     SparseMatrix<T>::~SparseMatrix(){Resize(0);}
00123 
00125     template<class T> void 
00126     SparseMatrix<T>::Resize (int r)
00127     {
00128       int i;
00129       if(rows>0){
00130         if(!UseAlloc){for(i=0;i<rows;i++){if(rowSizes[i]){free(m_ppElements[i]);}}}
00131         free(m_ppElements);
00132         free(rowSizes);
00133       }
00134       rows=r;
00135       if (r)
00136       {
00137         rowSizes = reinterpret_cast<int*> (malloc (sizeof (int) * r));
00138         
00139         memset (rowSizes, 0, sizeof (int) * r);
00140         
00141         m_ppElements = reinterpret_cast<MatrixEntry<T>**> (malloc (sizeof (MatrixEntry<T>*) * r));
00142       }
00143     }
00144 
00146     template<class T> void 
00147     SparseMatrix<T>::SetRowSize (int row, int count)
00148     {
00149       if (row >= 0 && row < rows)
00150       {
00151         if (UseAlloc)
00152           m_ppElements[row] = AllocatorMatrixEntry.newElements (count);
00153         else
00154         {
00155           if (rowSizes[row])
00156             free (m_ppElements[row]);
00157           if (count > 0)
00158             m_ppElements[row] = reinterpret_cast<MatrixEntry<T>*> (malloc (sizeof (MatrixEntry<T>) * count));
00159         }
00160         rowSizes[row] = count;
00161       }
00162     }
00163 
00165     template<class T> void 
00166     SparseMatrix<T>::SetZero ()
00167     {
00168       Resize (this->m_N, this->m_M);
00169     }
00170 
00172     template<class T> void 
00173     SparseMatrix<T>::SetIdentity ()
00174     {
00175       SetZero();
00176       for(int ij=0; ij < Min( this->Rows(), this->Columns() ); ij++)
00177         (*this)(ij,ij) = T(1);
00178     }
00179 
00181     template<class T> SparseMatrix<T> 
00182     SparseMatrix<T>::operator * (const T& V) const
00183     {
00184       SparseMatrix<T> M(*this);
00185       M *= V;
00186       return M;
00187     }
00188 
00190     template<class T> SparseMatrix<T>& 
00191     SparseMatrix<T>::operator *= (const T& V)
00192     {
00193       for (int i=0; i<this->Rows(); i++)
00194       {
00195         for(int ii=0;ii<m_ppElements[i].size();i++){m_ppElements[i][ii].Value*=V;}
00196       }
00197       return *this;
00198     }
00199 
00201     template<class T> SparseMatrix<T> 
00202     SparseMatrix<T>::Multiply( const SparseMatrix<T>& M ) const
00203     {
00204       SparseMatrix<T> R( this->Rows(), M.Columns() );
00205       for(int i=0; i<R.Rows(); i++){
00206         for(int ii=0;ii<m_ppElements[i].size();ii++){
00207           int N=m_ppElements[i][ii].N;
00208           T Value=m_ppElements[i][ii].Value;
00209           for(int jj=0;jj<M.m_ppElements[N].size();jj++){
00210             R(i,M.m_ppElements[N][jj].N) += Value * M.m_ppElements[N][jj].Value;
00211           }
00212         }
00213       }
00214       return R;
00215     }
00216 
00218     template<class T> template<class T2> Vector<T2> 
00219     SparseMatrix<T>::Multiply( const Vector<T2>& V ) const
00220     {
00221       Vector<T2> R( rows );
00222 
00223       for (int i=0; i<rows; i++)
00224       {
00225         T2 temp=T2();
00226         for(int ii=0;ii<rowSizes[i];ii++){
00227           temp+=m_ppElements[i][ii].Value * V.m_pV[m_ppElements[i][ii].N];
00228         }
00229         R(i)=temp;
00230       }
00231       return R;
00232     }
00233 
00235     template<class T> template<class T2> void 
00236     SparseMatrix<T>::Multiply( const Vector<T2>& In,Vector<T2>& Out) const
00237     {
00238       for (int i=0; i<rows; i++){
00239         T2 temp=T2();
00240         for(int j=0;j<rowSizes[i];j++){temp+=m_ppElements[i][j].Value * In.m_pV[m_ppElements[i][j].N];}
00241         Out.m_pV[i]=temp;
00242       }
00243     }
00244 
00246     template<class T> SparseMatrix<T> 
00247     SparseMatrix<T>::operator * (const SparseMatrix<T>& M) const
00248     {
00249       return (Multiply (M));
00250     }
00251     
00253     template<class T> template<class T2> Vector<T2> 
00254     SparseMatrix<T>::operator * (const Vector<T2>& V) const
00255     {
00256       return (Multiply (V));
00257     }
00258 
00260     template<class T>
00261     SparseMatrix<T> SparseMatrix<T>::Transpose() const
00262     {
00263       SparseMatrix<T> M( this->Columns(), this->Rows() );
00264 
00265       for (int i=0; i<this->Rows(); i++)
00266       {
00267         for(int ii=0;ii<m_ppElements[i].size();ii++){
00268           M(m_ppElements[i][ii].N,i) = m_ppElements[i][ii].Value;
00269         }
00270       }
00271       return M;
00272     }
00273 
00275     template<class T> template<class T2> int 
00276     SparseMatrix<T>::SolveSymmetric(const SparseMatrix<T>& M,const Vector<T2>& b,const int& iters,Vector<T2>& solution,const T2 eps,const int& reset)
00277     {
00278       Vector<T2> d,r,Md;
00279       T2 alpha,beta,rDotR;
00280       Md.Resize(b.Dimensions());
00281       if(reset){
00282         solution.Resize(b.Dimensions());
00283         solution.SetZero();
00284       }
00285       d=r=b-M.Multiply(solution);
00286       rDotR=r.Dot(r);
00287       if(b.Dot(b)<=eps){
00288         solution.SetZero();
00289         return 0;
00290       }
00291 
00292       int i;
00293       for(i=0;i<iters;i++){
00294         T2 temp;
00295         M.Multiply(d,Md);
00296         temp=d.Dot(Md);
00297         if(temp<=eps){break;}
00298         alpha=rDotR/temp;
00299         r.SubtractScaled(Md,alpha);
00300         temp=r.Dot(r);
00301         if(temp/b.Dot(b)<=eps){break;}
00302         beta=temp/rDotR;
00303         solution.AddScaled(d,alpha);
00304         if(beta<=eps){break;}
00305         rDotR=temp;
00306         Vector<T2>::Add(d,beta,r,d);
00307       }
00308       return i;
00309     }
00310 
00312     // Solve for x s.t. M(x)=b by solving for x s.t. M^tM(x)=M^t(b)
00313     template<class T> int 
00314     SparseMatrix<T>::Solve(const SparseMatrix<T>& M,const Vector<T>& b,const int& iters,Vector<T>& solution,const T eps)
00315     {
00316       SparseMatrix mTranspose=M.Transpose();
00317       Vector<T> bb=mTranspose*b;
00318       Vector<T> d,r,Md;
00319       T alpha,beta,rDotR;
00320       int i;
00321 
00322       solution.Resize(M.Columns());
00323       solution.SetZero();
00324 
00325       d=r=bb;
00326       rDotR=r.Dot(r);
00327 
00328       for(i=0;i<iters && rDotR>eps;i++){
00329         T temp;
00330         Md=mTranspose*(M*d);
00331         alpha=rDotR/d.Dot(Md);
00332         solution+=d*alpha;
00333         r-=Md*alpha;
00334         temp=r.Dot(r);
00335         beta=temp/rDotR;
00336         rDotR=temp;
00337         d=r+d*beta;
00338       }
00339       return i;
00340     }
00341 
00343     //  SparseNMatrix //
00346     // Static Allocator Methods and Memebers //
00348     template<class T,int Dim> int SparseNMatrix<T,Dim>::UseAlloc=0;
00349     template<class T,int Dim> Allocator<NMatrixEntry<T,Dim> > SparseNMatrix<T,Dim>::AllocatorNMatrixEntry;
00350     template<class T,int Dim> int SparseNMatrix<T,Dim>::UseAllocator(void){return UseAlloc;}
00351     
00353     template<class T,int Dim> void 
00354     SparseNMatrix<T,Dim>::SetAllocator (const int& blockSize)
00355     {
00356       if (blockSize>0)
00357       {
00358         UseAlloc = 1;
00359         AllocatorNMatrixEntry.set (blockSize);
00360       }
00361       else
00362         UseAlloc = 0;
00363     }
00365     // SparseNMatrix Methods and Memebers //
00367 
00369     template<class T,int Dim>
00370     SparseNMatrix<T,Dim>::SparseNMatrix () : rows (0), rowSizes (NULL), m_ppElements (NULL)
00371     {
00372     }
00373 
00375     template<class T,int Dim>
00376     SparseNMatrix<T,Dim>::SparseNMatrix (int rows) : rows (rows), rowSizes (NULL), m_ppElements (NULL)
00377     {
00378       Resize (rows);
00379     }
00380 
00382     template<class T,int Dim>
00383     SparseNMatrix<T,Dim>::SparseNMatrix( const SparseNMatrix& M )
00384     {
00385       Resize (M.rows);
00386       for (int i = 0; i < rows; i++)
00387       {
00388         SetRowSize (i, M.rowSizes[i]);
00389         for (int j = 0; j < rowSizes[i]; j++)
00390           m_ppElements[i][j] = M.m_ppElements[i][j];
00391       }
00392     }
00393 
00395     template<class T,int Dim> int 
00396     SparseNMatrix<T,Dim>::Entries ()
00397     {
00398       int e = 0;
00399       for(int i = 0; i < rows; i++)
00400         e+=int (rowSizes[i]);
00401       return (e);
00402     }
00404     template<class T,int Dim>
00405     SparseNMatrix<T,Dim>& SparseNMatrix<T,Dim>::operator = (const SparseNMatrix<T,Dim>& M)
00406     {
00407       Resize(M.rows);
00408       for (int i = 0; i < rows; i++)
00409       {
00410         SetRowSize (i, M.rowSizes[i]);
00411         for (int j = 0; j < rowSizes[i]; j++)
00412           m_ppElements[i][j] = M.m_ppElements[i][j];
00413       }
00414       return (*this);
00415     }
00416 
00418     template<class T,int Dim>
00419     SparseNMatrix<T,Dim>::~SparseNMatrix ()
00420     {
00421       Resize (0);
00422     }
00423 
00425     template<class T,int Dim> void 
00426     SparseNMatrix<T,Dim>::Resize (int r)
00427     {
00428       int i;
00429       if (rows > 0)
00430       {
00431         if (!UseAlloc)
00432           for (i = 0; i < rows; i++)
00433             if (rowSizes[i])
00434               free (m_ppElements[i]);
00435         free (m_ppElements);
00436         free (rowSizes);
00437       }
00438       rows = r;
00439       if (r)
00440       {
00441         rowSizes = reinterpret_cast<int*> (malloc (sizeof (int) *r));
00442         memset (rowSizes, 0, sizeof (int) * r);
00443         m_ppElements = reinterpret_cast<NMatrixEntry<T,Dim>**> (malloc (sizeof (NMatrixEntry<T,Dim>*) * r));
00444       }
00445     }
00446 
00448     template<class T,int Dim> void 
00449     SparseNMatrix<T,Dim>::SetRowSize (int row,int count)
00450     {
00451       if (row >= 0 && row < rows)
00452       {
00453         if (UseAlloc)
00454           m_ppElements[row] = AllocatorNMatrixEntry.newElements (count);
00455         else
00456         {
00457           if (rowSizes[row])
00458             free (m_ppElements[row]);
00459           if (count>0)
00460             m_ppElements[row] = reinterpret_cast<NMatrixEntry<T,Dim>*> (malloc (sizeof (NMatrixEntry<T,Dim>) * count));
00461         }
00462         rowSizes[row]=count;
00463       }
00464     }
00465 
00467     template<class T,int Dim>
00468     SparseNMatrix<T,Dim> SparseNMatrix<T,Dim>::operator * (const T& V) const
00469     {
00470       SparseNMatrix<T,Dim> M (*this);
00471       M *= V;
00472       return (M);
00473     }
00474 
00476     template<class T,int Dim>
00477     SparseNMatrix<T,Dim>& SparseNMatrix<T,Dim>::operator *= (const T& V)
00478     {
00479       for (int i = 0; i < this->Rows (); i++)
00480         for (int ii = 0; ii < m_ppElements[i].size (); i++)
00481           for (int jj = 0; jj < Dim; jj++)
00482             m_ppElements[i][ii].Value[jj] *= V;
00483       return (*this);
00484     }
00485 
00487     template<class T,int Dim> template<class T2>
00488     NVector<T2,Dim> SparseNMatrix<T,Dim>::operator * (const Vector<T2>& V) const
00489     {
00490       NVector<T2,Dim> R (rows);
00491 
00492       for (int i = 0; i < rows; i++)
00493       {
00494         T2 temp[Dim];
00495         for (int ii = 0; ii < Dim; ii++)
00496           temp[ii] = T2 ();
00497         for (int ii = 0; ii < rowSizes[i]; ii++)
00498           for (int jj = 0; jj < Dim; jj++)
00499             temp[jj] += m_ppElements[i][ii].Value[jj] * V.m_pV[m_ppElements[i][jj].N];
00500         for (int ii = 0; ii < Dim; ii++)
00501           R[i][ii] = temp[ii];
00502       }
00503       return (R);
00504     }
00505 
00507     template<class T,int Dim> template<class T2> Vector<T2> 
00508     SparseNMatrix<T,Dim>::operator * (const NVector<T2,Dim>& V) const
00509     {
00510       Vector<T2> R (rows);
00511 
00512       for (int i=0; i<rows; i++)
00513       {
00514         T2 temp ();
00515         for (int ii = 0; ii < rowSizes[i]; ii++)
00516         {
00517           for (int jj = 0; jj < Dim; jj++)
00518           {
00519             temp += m_ppElements[i][ii].Value[jj] * V.m_pV[m_ppElements[i][ii].N][jj];
00520           }
00521         }
00522         R(i)  =temp;
00523       }
00524       return (R);
00525     }
00526 
00528     // SparseSymmetricMatrix //
00531     template<class T> template<class T2> Vector<T2> 
00532     SparseSymmetricMatrix<T>::operator * (const Vector<T2>& V) const 
00533     {
00534       return (Multiply (V));
00535     }
00536     
00538     template<class T> template<class T2> Vector<T2> 
00539     SparseSymmetricMatrix<T>::Multiply (const Vector<T2>& V) const
00540     {
00541       Vector<T2> R (this->rows);
00542 
00543       for (int i = 0; i < this->rows; i++)
00544       {
00545         for (int ii = 0; ii < this->rowSizes[i]; ii++)
00546         {
00547           int j = this->m_ppElements[i][ii].N;
00548           R(i) += this->m_ppElements[i][ii].Value * V.m_pV[j];
00549           R(j) += this->m_ppElements[i][ii].Value * V.m_pV[i];
00550         }
00551       }
00552       return (R);
00553     }
00554 
00556     template<class T> template<class T2> void 
00557     SparseSymmetricMatrix<T>::Multiply (const Vector<T2>& In,Vector<T2>& Out) const
00558     {
00559       Out.SetZero ();
00560       for (int i = 0; i < this->rows; i++)
00561       {
00562         MatrixEntry<T>* temp = this->m_ppElements[i];
00563         T2& in1 = In.m_pV[i];
00564         T2& out1 = Out.m_pV[i];
00565         int rs = this->rowSizes[i];
00566         for (int ii = 0; ii <rs; ii++)
00567         {
00568           MatrixEntry<T>& temp2 = temp[ii];
00569           int j = temp2.N;
00570           T2 v = temp2.Value;
00571           out1 += v * In.m_pV[j];
00572           Out.m_pV[j] += v * in1;
00573         }
00574       }
00575     }
00576 
00578     template<class T> template<class T2> int 
00579     SparseSymmetricMatrix<T>::Solve (
00580         const SparseSymmetricMatrix<T>& M,
00581         const Vector<T2>& b,
00582         const int& iters,
00583         Vector<T2>& solution,
00584         const T2 eps,
00585         const int& reset)
00586     {
00587       Vector<T2> d, r, Md;
00588       T2 alpha,beta,rDotR,bDotB;
00589       Md.Resize (b.Dimensions ());
00590       if (reset)
00591       {
00592         solution.Resize (b.Dimensions ());
00593         solution.SetZero ();
00594       }
00595       d = r = b - M.Multiply (solution);
00596       rDotR = r.Dot (r);
00597       bDotB = b.Dot (b);
00598       if (b.Dot (b) <= eps)
00599       {
00600         solution.SetZero ();
00601         return (0);
00602       }
00603       int i;
00604       for (i = 0; i < iters; i++)
00605       {
00606         T2 temp;
00607         M.Multiply (d, Md);
00608         temp = d.Dot (Md);
00609         if (fabs (temp) <= eps)
00610           break;
00611         alpha = rDotR / temp;
00612 
00613         r.SubtractScaled (Md, alpha);
00614         temp = r.Dot (r);
00615 
00616         if (temp / bDotB <= eps)
00617           break;
00618 
00619         beta = temp / rDotR;
00620         solution.AddScaled (d, alpha);
00621         if (beta<=eps)
00622           break;
00623         rDotR = temp;
00624         Vector<T2>::Add (d, beta, r, d);
00625       }
00626       return i;
00627     }
00628 
00630     template<class T> template<class T2> int 
00631     SparseSymmetricMatrix<T>::Solve (
00632         const SparseSymmetricMatrix<T>& M,
00633         const Vector<T>& diagonal,
00634         const Vector<T2>& b,
00635         const int& iters,
00636         Vector<T2>& solution,
00637         const T2 eps,
00638         const int& reset)
00639     {
00640       Vector<T2> d, r, Md;
00641 
00642       if (reset)
00643       {
00644         solution.Resize (b.Dimensions ());
00645         solution.SetZero ();
00646       }
00647       Md.Resize (M.rows);
00648       for (int i = 0; i <iters; i++)
00649       {
00650         M.Multiply (solution, Md);
00651         r = b - Md;
00652         for (int j = 0; j < int (M.rows); j++)
00653           solution[j] += r[j] / diagonal[j];
00654       }
00655       return (iters);
00656     }
00657   }
00658 }


pcl
Author(s): Open Perception
autogenerated on Mon Oct 6 2014 03:17:58