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*));
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
00021
00022
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
00070
00071
00072
00073
00074
00075
00076
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();
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
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
00186
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
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
00451 void Matrixmxn::SetValues(const int m, const int n, const double data)
00452 {
00453 values[m][n] = data;
00454 }
00455
00456
00457 bool Matrixmxn::Resize(const int m, const int n)
00458 {
00459 if(m*n == 0)
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 }