math/Matrixmxn.cpp

Go to the documentation of this file.
00001 
00002 #include <malloc.h>
00003 #include <memory.h>
00004 #include <math.h>
00005 #include <assert.h>
00006 #include "VectorN.h"
00007 #include "Matrixmxn.h"
00008 
00009 extern int svd(int m,int n, double **a,double *q,double **u,double **v);
00010 
00011 double** AllocateMatrix(int m, int n)
00012 {
00013         double **matrix=NULL;
00014     matrix = (double**) malloc(m*sizeof(double*));  // initializes elements to 0
00015         for (int i=0; i<m; i++)
00016         {
00017                 matrix[i] = (double*) calloc(n, sizeof(double));
00018                 if (matrix[i] == NULL)
00019                         return NULL;
00020                         //Actually, there would be some memory leak here,
00021                     //    supposedly, all memory allocate should be free before return;
00022                     //    same problems in the following section.
00023         }
00024 
00025         return matrix;
00026 }
00027 
00028 void FreeMatrix(int m, int n, double **matrix)
00029 {
00030         for(int i=0; i<m; i++)
00031         {
00032                 free(matrix[i]);
00033         }
00034         free(matrix);
00035 }
00036 
00037 bool Matrixmxn::AllocateMatrix()
00038 {
00039         assert(values == NULL);
00040 
00041         values = ::AllocateMatrix(m_nRows, m_nColumns);
00042 
00043         assert(values != NULL);
00044 
00045         if (values == NULL)
00046                 return false;
00047 
00048         return true;
00049 }
00050 
00051 bool Matrixmxn::ReallocateMatrix(int m, int n)
00052 {
00053         assert(values != NULL);
00054 
00055     if (m == m_nRows)
00056     {
00057         for (int i = 0; i < m; i++)
00058         {
00059             values[i] = (double*) realloc(values[i], n*sizeof(double));
00060             if (values[i] == NULL)
00061                                 return false;
00062         }
00063     }
00064     else
00065     {
00066 		::FreeMatrix(m_nRows, m_nColumns, values);
00067                 values = ::AllocateMatrix(m, n);
00068 
00069                 //values = (double**) realloc(values, m*sizeof(double*));
00070                 //if (values == NULL)
00071                 //      return false;
00072                 //for(int i = 0; i < m; i++)
00073                 //{
00074                 //      values[i] = (double*)calloc(n, sizeof(double));
00075                 //      if (values[i]==NULL)
00076                 //              return false;
00077                 //}       
00078     }
00079 
00080         m_nRows = m;
00081         m_nColumns = n;
00082         return true;
00083 }
00084 
00085 void Matrixmxn::FreeMatrix()
00086 {
00087 	::FreeMatrix(m_nRows, m_nColumns, values);
00088         values = NULL;
00089 }
00090 
00091 Matrixmxn::Matrixmxn(const int m, const int n)
00092 {
00093     m_nRows = m;
00094     m_nColumns = n;
00095 
00096         values = NULL;
00097         AllocateMatrix();
00098 
00099     if (m == n)
00100     {
00101         for (int i = 0; i < m; i++)
00102         {
00103             values[i][i] = 1;
00104         }
00105     }
00106 }
00107 
00108 Matrixmxn::Matrixmxn(const Matrixmxn& right)
00109 {
00110     m_nRows = right.m_nRows;
00111     m_nColumns = right.m_nColumns;
00112 
00113         values = NULL;
00114         AllocateMatrix();
00115 
00116         SetValues(right);
00117 
00118 }
00119 
00120 Matrixmxn::~Matrixmxn()
00121 {
00122         FreeMatrix();     //delete values;
00123 }
00124 
00125 
00126 Matrixmxn Matrixmxn::Transpose()
00127 {
00128     Matrixmxn returnMe(m_nColumns, m_nRows);
00129     for( int i = 0; i < m_nColumns; i++ )
00130     {
00131         for( int j = 0; j < m_nRows; j++ )
00132         {
00133             returnMe.values[i][j] = values[j][i] ;
00134         }
00135     }
00136     return returnMe ;
00137 }
00138 
00139 Matrixmxn Matrixmxn::Inverse()
00140 {
00141         Matrixmxn inv;
00142         Inverse(inv);
00143         return inv;
00144 }
00145 
00146 bool Matrixmxn::Inverse(Matrixmxn &inv)
00147 {
00148     int m=m_nRows;
00149     int n=m_nColumns;
00150 
00151         if (m<n)
00152         {
00153                 Matrixmxn matrixT = Transpose();
00154                 Matrixmxn matrixTInv;
00155                 matrixT.Inverse(matrixTInv);
00156                 inv = matrixTInv.Transpose();
00157                 return true;
00158         }
00159 
00160     double *w = (double *)malloc(n*sizeof(double));
00161     double **u = ::AllocateMatrix(m, m);
00162     double **v = ::AllocateMatrix(n, n);
00163     svd(m_nRows, m_nColumns, values, w, u, v);
00164 
00165     Matrixmxn matrixUT(n, m);
00166     Matrixmxn matrixWinv(n, n);
00167     Matrixmxn matrixV(n, n);
00168 
00169     matrixV.SetValues(n, n, v);
00170 	::FreeMatrix(n, n, v);
00171 
00172     //Transpose u:
00173     double **ut = ::AllocateMatrix(n, m);
00174     for( int i = 0; i < n; i++ )
00175     {
00176         for( int j = 0; j < m; j++ )
00177         {
00178             ut[i][j] = u[j][i] ;
00179         }
00180     }
00181     matrixUT.SetValues(n, m, ut);
00182  	::FreeMatrix(m, m, u);
00183     ::FreeMatrix(n, m, ut);
00184 
00185     // Because of round off, etc, need to zero w[i] values that are
00186     // negligible
00187     double wmax = 0.0;
00188     for (int j = 0; j < n; j++)
00189         if (fabs(w[j]) > wmax)
00190             wmax = fabs(w[j]);
00191     double wmin = wmax*1.0e-6;
00192     int rank = 0;
00193     for (j = 0; j < n; j++)
00194     {
00195         double winv = 0;
00196         if ((fabs(w[j]) < wmin)||(fabs(w[j]) < 1e-12))
00197         {
00198             w[j] = 0.0;
00199         }
00200         else
00201         {
00202             rank++;
00203             winv = 1/w[j];
00204         }
00205         matrixWinv.SetValues(j, j, winv);
00206     }
00207         free(w);
00208 
00209     // Back substitution - Taken from NR: x = V(W^-1)(U^T*b) (right to left)
00210         inv.Resize(n, m);
00211     inv.SetValues(matrixV);
00212     inv *= matrixWinv;
00213     inv *= matrixUT;
00214 
00215     return true;
00216 }
00217 
00218 double Matrixmxn::Determinant()
00219 {
00220     if (m_nRows != m_nColumns)
00221         return 0;
00222     if (m_nRows == 2)
00223     {
00224         return (values[0][0]*values[1][1]-values[1][0]*values[0][1]);
00225     }
00226     double det = 0;
00227     for (int i = 0; i < m_nColumns; i++)
00228     {
00229         if (values[0][i] == 0)
00230             continue;
00231         Matrixmxn subMatrix(m_nRows-1, m_nColumns-1);
00232         for (int j = 0, col = 1; j < m_nColumns; j++)
00233         {
00234             if (j == i)
00235                 continue;
00236             for (int k = 1; k < m_nRows; k++)
00237             {
00238                 subMatrix.SetValues(k, col, values[k][j]);
00239             }
00240             col++;
00241         }
00242         int sign = (i%2 != 0)?  -1:1;
00243         det += sign*values[0][i]*subMatrix.Determinant();
00244     }
00245     return det;
00246 }
00247 
00248 
00249 void Matrixmxn::SetValues (const Matrixmxn& right)
00250 {
00251         Resize(right.m_nRows, right.m_nColumns);
00252     for( int i = 0; i < m_nRows; i++ )
00253     {
00254         for( int j = 0; j < m_nColumns; j++ )
00255         {
00256             values[i][j] = right.values[i][j];
00257         }
00258     }
00259 }
00260 
00261 void Matrixmxn::SetValues(int m, int n, double **val)
00262 {
00263         Resize(m, n);
00264     for( int i = 0; i < m_nRows; i++ )
00265     {
00266         for( int j = 0; j < m_nColumns; j++ )
00267         {
00268             values[i][j] = val[i][j];
00269         }
00270     }
00271 }
00272 
00273 bool Matrixmxn::Compare (const Matrixmxn& right)
00274 {
00275     for ( int i = 0; i < m_nRows; i++ )
00276     {
00277         for ( int j = 0; j < m_nColumns; j++ )
00278         {
00279             double diff = values[i][j] - right.values[i][j];
00280             double tol = 1e-5;
00281             if ( ( diff > tol ) || ( diff < -tol ) )
00282             {
00283                 return false;
00284             }
00285         }
00286     }
00287 
00288     return true;
00289 }
00290 
00291 
00292 Matrixmxn Matrixmxn::operator + (const Matrixmxn& right) const
00293 {
00294     Matrixmxn returnMe(m_nRows, m_nColumns);
00295     for( int i = 0; i < m_nRows; i++ )
00296     {
00297         for( int j = 0; j < m_nColumns; j++ )
00298         {
00299             returnMe.values[i][j] = values[i][j] + right.values[i][j];
00300         }
00301     }
00302     return returnMe;
00303 }
00304 
00305 Matrixmxn Matrixmxn::operator - (const Matrixmxn& right) const
00306 {
00307     Matrixmxn returnMe(m_nRows, m_nColumns);
00308     for( int i = 0; i < m_nRows; i++ )
00309     {
00310         for( int j = 0; j < m_nColumns; j++ )
00311         {
00312             returnMe.values[i][j] = values[i][j] - right.values[i][j];
00313         }
00314     }
00315     return returnMe;
00316 }
00317 
00318 Matrixmxn Matrixmxn::operator * (const Matrixmxn& right) const
00319 {
00320     int rightCols = right.GetColumns();
00321     int rightRows = right.GetRows();
00322     assert(m_nColumns == rightRows);
00323     Matrixmxn returnMe(m_nRows, rightCols);
00324     for( int row = 0; row < m_nRows; row++ )
00325     {
00326         for( int col = 0; col < rightCols; col++ )
00327         {
00328             returnMe.values[ row ][ col ] = 0 ;
00329             for( int index = 0; index < m_nColumns ; index++ )
00330             {
00331                 returnMe.values[ row ][ col ] += values[ row ][ index ] * right.values[ index ][ col ] ;
00332             }
00333         }
00334     }
00335     return returnMe ;
00336 }
00337 
00338 Matrixmxn Matrixmxn::operator * (const double& right) const
00339 {
00340     Matrixmxn returnMe(m_nRows, m_nColumns);
00341     for( int i = 0; i < m_nRows; i++ )
00342     {
00343         for( int j = 0; j < m_nColumns; j++ )
00344         {
00345             returnMe = right*values[i][j];
00346         }
00347     }
00348     return returnMe;
00349 }
00350 
00351 VectorN Matrixmxn::operator *(const VectorN& right) const
00352 {
00353     int vectorLen = right.Length();
00354     assert(vectorLen == m_nColumns);
00355 
00356     VectorN returnMe;
00357     returnMe.SetLength(m_nRows);
00358     for( int i = 0; i < m_nRows; i++ )
00359     {
00360         returnMe[i] = 0;
00361         for( int j = 0; j < m_nColumns; j++ )
00362         {
00363             returnMe[i] += values[i][j] * right[j];
00364         }
00365     }
00366     return returnMe;
00367 }
00368 
00369 Matrixmxn& Matrixmxn::operator = (const Matrixmxn& right)
00370 {
00371     Resize(right.GetRows(), right.GetColumns());
00372     SetValues(right);
00373     return *this;
00374 }
00375 
00376 Matrixmxn& Matrixmxn::operator *= (const Matrixmxn& right)
00377 {
00378     int rightCols = right.GetColumns();
00379     double **result = ::AllocateMatrix(m_nRows, rightCols);
00380 
00381     for( int row = 0; row < m_nRows; row++ )
00382     {
00383         for( int col = 0; col < rightCols; col++ )
00384         {
00385             result[ row ][ col ] = 0 ;
00386             for( int index = 0; index < m_nColumns ; index++ )
00387             {
00388                 result[ row ][ col ] += values[ row ][ index ] * right.values[ index ][ col ] ;
00389             }
00390         }
00391     }
00392 
00393     SetValues(m_nRows, rightCols, result);
00394     ::FreeMatrix(m_nRows, rightCols, result);
00395     return *this;
00396 }
00397 
00398 Matrixmxn& Matrixmxn::operator *= (const double& right)
00399 {
00400     for( int row = 0; row < m_nRows; row++ )
00401     {
00402         for( int col = 0; col < m_nColumns; col++ )
00403         {
00404             values[ row ][ col ] *= right ;
00405         }
00406     }
00407 
00408     return *this;
00409 }
00410 
00411 Matrixmxn& Matrixmxn::operator += (const Matrixmxn& right)
00412 {
00413     for( int i = 0; i < m_nRows; i++ )
00414     {
00415         for( int j = 0; j < m_nColumns; j++ )
00416         {
00417             values[i][j] += right.values[i][j];
00418         }
00419     }
00420     return *this;
00421 }
00422 
00423 Matrixmxn& Matrixmxn::operator -= (const Matrixmxn& right)
00424 {
00425     for( int i = 0; i < m_nRows; i++ )
00426     {
00427         for( int j = 0; j < m_nColumns; j++ )
00428         {
00429             values[i][j] -= right.values[i][j];
00430         }
00431     }
00432     return *this;
00433 }
00434 
00435 bool Matrixmxn::operator == (const Matrixmxn& right)
00436 {
00437     return Compare(right);
00438 }
00439 
00440 double& Matrixmxn::operator ()(const unsigned int row, const unsigned int col)
00441 {
00442     return values[row][col];
00443 }
00444 
00445 double Matrixmxn::GetValues(const int m, const int n) const
00446 {
00447     return values[m][n];
00448 }
00449 
00450 // Set data in entry row m, column n
00451 void Matrixmxn::SetValues(const int m, const int n, const double data)
00452 {
00453     values[m][n] = data;
00454 }
00455 
00456 // Resize the matrix to m rows, n columns
00457 bool Matrixmxn::Resize(const int m, const int n)
00458 {
00459     if(m*n == 0)            // cannot allocate 0 size matrix
00460     {
00461         return false;
00462     }
00463     if ((m == m_nRows) && (n == m_nColumns))
00464     {
00465         return true;
00466     }
00467 
00468     if(values == NULL)
00469     {
00470         return false;
00471     }
00472 
00473         return ReallocateMatrix(m, n);
00474 }
00475 
00476 VectorN Matrixmxn::GetColumnVector(int col) const
00477 {
00478         VectorN returnMe;
00479         returnMe.SetLength(m_nRows);
00480         for (int i=0; i<m_nRows; i++)
00481         {
00482                 returnMe[i] = values[i][col];
00483         }
00484         return returnMe;
00485 }
00486 
00487 VectorN Matrixmxn::GetRowVector(int row) const
00488 {
00489         VectorN returnMe;
00490         returnMe.SetLength(m_nColumns);
00491         for (int i=0; i<m_nColumns; i++)
00492         {
00493                 returnMe[i] = values[row][i];
00494         }
00495         return returnMe;
00496 }

Generated on Sat Apr 1 21:30:38 2006 for Motion Planning Kernel by  doxygen 1.4.6-NO