00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "CATMatrix.h"
00014
00015
00016 CATMatrix::CATMatrix(CATUInt32 w, CATUInt32 h)
00017 {
00018 fWidth = w;
00019 fHeight = h;
00020 fMatrix = new CATFloat64[w*h];
00021 this->ZeroMatrix();
00022 }
00023
00024
00025 CATMatrix::CATMatrix(const CATMatrix& matrix)
00026 {
00027 this->fWidth = matrix.fWidth;
00028 this->fHeight = matrix.fHeight;
00029 fMatrix = new CATFloat64[this->fWidth * this->fHeight];
00030 for (CATUInt32 x = 0; x < fWidth; x++)
00031 {
00032 for (CATUInt32 y=0; y < fHeight; y++)
00033 {
00034 this->Val(x,y) = matrix.cVal(x,y);
00035 }
00036 }
00037 }
00038
00039
00040 CATMatrix::~CATMatrix()
00041 {
00042 if (fMatrix != 0)
00043 {
00044 delete [] fMatrix;
00045 fMatrix = 0;
00046 }
00047 }
00048
00049
00050 CATFloat64& CATMatrix::Val(CATUInt32 x, CATUInt32 y)
00051 {
00052 CATASSERT( (y < fHeight) && (y >= 0) && (x >= 0) && (x < fWidth), "Invalid position in matrix!");
00053 return fMatrix[x+y*fWidth];
00054 }
00055
00056
00057 CATFloat64 CATMatrix::cVal(CATUInt32 x, CATUInt32 y) const
00058 {
00059 CATASSERT( (y < fHeight) && (y >= 0) && (x >= 0) && (x < fWidth), "Invalid position in matrix!");
00060 return fMatrix[x+y*fWidth];
00061 }
00062
00063
00064
00065 void CATMatrix::SetToIdentity()
00066 {
00067 for (CATUInt32 x=0; x<fWidth; x++)
00068 {
00069 for (CATUInt32 y=0; y<fHeight; y++)
00070 {
00071 if (x == y)
00072 {
00073 this->Val(x,y) = 1;
00074 }
00075 else
00076 {
00077 this->Val(x,y) = 0.0;
00078 }
00079 }
00080 }
00081 }
00082
00083
00084 void CATMatrix::ZeroMatrix()
00085 {
00086 for (CATUInt32 x=0; x<fWidth; x++)
00087 {
00088 for (CATUInt32 y=0; y<fHeight; y++)
00089 {
00090 this->Val(x,y) = 0.0;
00091 }
00092 }
00093 }
00094
00095
00096 bool CATMatrix::IsNullMatrix() const
00097 {
00098 for (CATUInt32 x=0; x<fWidth; x++)
00099 {
00100 for (CATUInt32 y=0; y< fHeight; y++)
00101 {
00102 if (this->cVal(x,y) != 0)
00103 {
00104 return false;
00105 }
00106 }
00107 }
00108 return true;
00109 }
00110
00111
00112 bool CATMatrix::IsIdentityMatrix() const
00113 {
00114 for (CATUInt32 x=0; x<fWidth; x++)
00115 {
00116 for (CATUInt32 y=0; y<fHeight; y++)
00117 {
00118 if (x == y)
00119 {
00120 if (this->cVal(x,y) != 1)
00121 {
00122 return false;
00123 }
00124 }
00125 else
00126 {
00127 if (this->cVal(x,y) != 0.0)
00128 {
00129 return false;
00130 }
00131 }
00132 }
00133 }
00134
00135 return true;
00136 }
00137
00138
00139 bool CATMatrix::operator==(const CATMatrix& matrix) const
00140 {
00141 if ((matrix.fWidth != this->fWidth) ||
00142 (matrix.fHeight != this->fHeight))
00143 {
00144 return false;
00145 }
00146
00147 for (CATUInt32 x=0; x < fWidth; x++)
00148 {
00149 for (CATUInt32 y=0; y < fHeight; y++)
00150 {
00151 if (this->cVal(x,y) != matrix.cVal(x,y))
00152 {
00153 return false;
00154 }
00155 }
00156 }
00157
00158 return true;
00159 }
00160
00161
00162 CATMatrix CATMatrix::operator+ (const CATMatrix& matrix) const
00163 {
00164 if (!this->SameOrder(matrix))
00165 {
00166 CATASSERT(false,"Can't add two matricies of differing orders.");
00167 throw;
00168 }
00169
00170 CATMatrix sum(fWidth,fHeight);
00171 sum.ZeroMatrix();
00172
00173 for (CATUInt32 i = 0; i < this->fWidth; i++)
00174 {
00175 for (CATUInt32 j = 0; j < this->fHeight; j++)
00176 {
00177 sum.Val(i,j) = this->cVal(i,j) + matrix.cVal(i,j);
00178 }
00179 }
00180
00181 return sum;
00182 }
00183
00184
00185
00186 CATMatrix CATMatrix::operator- (const CATMatrix& matrix) const
00187 {
00188
00189 if (!this->SameOrder(matrix))
00190 {
00191 CATASSERT(false,"Can't add two matricies of differing orders.");
00192 throw;
00193 }
00194
00195 CATMatrix sum(fWidth,fHeight);
00196
00197 for (CATUInt32 i = 0; i < this->fWidth; i++)
00198 {
00199 for (CATUInt32 j = 0; j < this->fHeight; j++)
00200 {
00201 sum.Val(i,j) = this->cVal(i,j) - matrix.cVal(i,j);
00202 }
00203 }
00204
00205 return sum;
00206 }
00207
00208
00209 bool CATMatrix::IsConformable(const CATMatrix& matrix) const
00210 {
00211 if (this->fWidth != matrix.fHeight)
00212 {
00213 return false;
00214 }
00215
00216 return true;
00217 }
00218
00219
00220 CATMatrix CATMatrix::operator* (const CATMatrix& matrix) const
00221 {
00222 CATMatrix product(matrix.fWidth, this->fHeight);
00223 product.ZeroMatrix();
00224
00225 CATASSERT( this->fWidth == matrix.fHeight, "Can only multiply matricies where 1st matrix's width == 2nd matrix's height");
00226 if (fWidth != matrix.fHeight)
00227 {
00228 return product;
00229 }
00230
00231 for (CATUInt32 x = 0; x < matrix.fWidth; x++)
00232 {
00233 for (CATUInt32 y=0; y < this->fHeight; y++)
00234 {
00235 for (CATUInt32 i = 0; i < this->fWidth; i++)
00236 {
00237 product.Val(x,y) = product.cVal(x,y) + this->cVal(i,y) * matrix.cVal(x,i);
00238 }
00239 }
00240 }
00241
00242 return product;
00243 }
00244
00245
00246 CATMatrix CATMatrix::operator* (const CATFloat64 scalar) const
00247 {
00248
00249 CATMatrix product(fWidth,fHeight);
00250
00251 for (CATUInt32 i = 0; i < this->fWidth; i++)
00252 {
00253 for (CATUInt32 j = 0; j < this->fHeight; j++)
00254 {
00255 product.Val(i,j) = this->cVal(i,j) * scalar;
00256 }
00257 }
00258
00259 return product;
00260 }
00261
00262
00263 bool CATMatrix::SameOrder(const CATMatrix& matrix) const
00264 {
00265 if ((this->fWidth != matrix.fWidth) || (this->fHeight != matrix.fHeight))
00266 {
00267 return false;
00268 }
00269
00270 return true;
00271 }
00272
00273 CATFloat64 CATMatrix::GetDeterminant() const
00274 {
00275
00276 CATASSERT(fWidth == fHeight, "Determinants may only be gotten from square matricies...");
00277 CATASSERT(fWidth > 1, "Determinants may only be gotten from square matricies of at least 2x2");
00278
00279
00280 if (fWidth != fHeight)
00281 {
00282 return 0.0;
00283 }
00284 if (fWidth < 2)
00285 {
00286 return 0.0;
00287 }
00288
00289 CATUInt32 n = fWidth;
00290
00291
00292
00293 if (n == 2)
00294 {
00295 return (this->cVal(0,0) * this->cVal(1,1)) -
00296 (this->cVal(1,0) * this->cVal(0,1));
00297 }
00298
00299
00300 CATFloat64 determ = 0;
00301
00302 for ( CATUInt32 j1 = 0; j1 < n; j1++)
00303 {
00304 CATMatrix m(n-1,n-1);
00305
00306 for (CATUInt32 i=1; i < n; i++)
00307 {
00308 CATUInt32 j2 = 0;
00309
00310 for (CATUInt32 j=0;j<n;j++)
00311 {
00312 if (j != j1)
00313 {
00314 m.Val(i - 1, j2) = this->cVal(i,j);
00315 j2++;
00316 }
00317 }
00318 }
00319
00320 determ += pow(-1.0,(CATFloat64)j1) * this->cVal(0,j1) * m.GetDeterminant();
00321 }
00322
00323 return(determ);
00324 }
00325
00326
00327 CATMatrix CATMatrix::GetInverted() const
00328 {
00329 CATMatrix inversion(fWidth,fHeight);
00330
00331
00332 CATFloat64 determ = this->GetDeterminant();
00333 CATUInt32 i,j;
00334
00335
00336 for (i = 0; i < fWidth; i++)
00337 {
00338 for (j = 0; j < fHeight; j++)
00339 {
00340 CATUInt32 i1, j1, i2, j2;
00341
00342
00343 CATMatrix m(fWidth-1,fHeight-1);
00344 i2 = 0;
00345 for (i1 = 0; i1 < fWidth; i1++)
00346 {
00347 if (i1 != i)
00348 {
00349 j2 = 0;
00350 for (j1 = 0; j1 < fHeight; j1++)
00351 {
00352 if (j1 != j)
00353 {
00354 m.Val(i2,j2) = this->cVal(i1,j1);
00355 j2++;
00356 }
00357 }
00358 i2++;
00359 }
00360 }
00361
00362
00363 inversion.Val(j,i) = pow(-1.0,(CATFloat64)i+j) * (m.GetDeterminant() / determ);
00364 }
00365 }
00366
00367 return inversion;
00368 }
00369
00370
00371
00372 void CATMatrix::DebugDump() const
00373 {
00374 CATWChar matrixTmp[100];
00375 wsprintf(matrixTmp,L"\nMatrix: (%d,%d):\n",fWidth,fHeight);
00376 ::OutputDebugString(matrixTmp);
00377 for (CATUInt32 y=0; y<fHeight; y++)
00378 {
00379 for (CATUInt32 x=0; x<fWidth; x++)
00380 {
00381 wsprintf(matrixTmp,L"%f ",this->cVal(x,y));
00382 ::OutputDebugString(matrixTmp);
00383 }
00384 ::OutputDebugString(L"\n");
00385 }
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 CATMatrix CATMatrix::GetTransposed() const
00401 {
00402 CATMatrix newMatrix(this->fHeight, this->fWidth);
00403
00404 for (CATUInt32 x=0; x < this->fWidth; x++)
00405 {
00406 for (CATUInt32 y=0; y<this->fHeight; y++)
00407 {
00408 newMatrix.Val(y,x) = this->cVal(x,y);
00409 }
00410 }
00411
00412 return newMatrix;
00413 }
00414
00415
00416
00417 CATMatrix CATMatrix::GetPseudoInverse() const
00418 {
00419
00420 CATMatrix transposed = this->GetTransposed();
00421
00422
00423 CATMatrix product = transposed * (*this);
00424
00425
00426 CATMatrix inverted = product.GetInverted();
00427
00428
00429 CATMatrix result = inverted * transposed;
00430
00431 return result;
00432 }