00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 namespace Wm4
00018 {
00019
00020 template <class Real>
00021 GMatrix<Real>::GMatrix (int iRows, int iCols)
00022 {
00023 m_afData = 0;
00024 m_aafEntry = 0;
00025 SetSize(iRows,iCols);
00026 }
00027
00028 template <class Real>
00029 GMatrix<Real>::GMatrix (int iRows, int iCols, const Real* afEntry)
00030 {
00031 m_afData = 0;
00032 m_aafEntry = 0;
00033 SetMatrix(iRows,iCols,afEntry);
00034 }
00035
00036 template <class Real>
00037 GMatrix<Real>::GMatrix (int iRows, int iCols, const Real** aafMatrix)
00038 {
00039 m_afData = 0;
00040 m_aafEntry = 0;
00041 SetMatrix(iRows,iCols,aafMatrix);
00042 }
00043
00044 template <class Real>
00045 GMatrix<Real>::GMatrix (const GMatrix& rkM)
00046 {
00047 m_iRows = 0;
00048 m_iCols = 0;
00049 m_iQuantity = 0;
00050 m_afData = 0;
00051 m_aafEntry = 0;
00052 *this = rkM;
00053 }
00054
00055 template <class Real>
00056 GMatrix<Real>::~GMatrix ()
00057 {
00058 Deallocate();
00059 }
00060
00061 template <class Real>
00062 void GMatrix<Real>::Allocate (bool bSetToZero)
00063 {
00064
00065
00066 m_afData = WM4_NEW Real[m_iQuantity];
00067 if (bSetToZero)
00068 {
00069 memset(m_afData,0,m_iQuantity*sizeof(Real));
00070 }
00071
00072 m_aafEntry = WM4_NEW Real*[m_iRows];
00073 for (int iRow = 0; iRow < m_iRows; iRow++)
00074 {
00075 m_aafEntry[iRow] = &m_afData[iRow*m_iCols];
00076 }
00077 }
00078
00079 template <class Real>
00080 void GMatrix<Real>::Deallocate ()
00081 {
00082 WM4_DELETE[] m_afData;
00083 WM4_DELETE[] m_aafEntry;
00084 }
00085
00086 template <class Real>
00087 void GMatrix<Real>::SetSize (int iRows, int iCols)
00088 {
00089 Deallocate();
00090 if (iRows > 0 && iCols > 0)
00091 {
00092 m_iRows = iRows;
00093 m_iCols = iCols;
00094 m_iQuantity = m_iRows*m_iCols;
00095 Allocate(true);
00096 }
00097 else
00098 {
00099 m_iRows = 0;
00100 m_iCols = 0;
00101 m_iQuantity = 0;
00102 m_afData = 0;
00103 m_aafEntry = 0;
00104 }
00105 }
00106
00107 template <class Real>
00108 void GMatrix<Real>::GetSize (int& riRows, int& riCols) const
00109 {
00110 riRows = m_iRows;
00111 riCols = m_iCols;
00112 }
00113
00114 template <class Real>
00115 int GMatrix<Real>::GetRows () const
00116 {
00117 return m_iRows;
00118 }
00119
00120 template <class Real>
00121 int GMatrix<Real>::GetColumns () const
00122 {
00123 return m_iCols;
00124 }
00125
00126 template <class Real>
00127 int GMatrix<Real>::GetQuantity () const
00128 {
00129 return m_iQuantity;
00130 }
00131
00132 template <class Real>
00133 GMatrix<Real>::operator const Real* () const
00134 {
00135 return m_afData;
00136 }
00137
00138 template <class Real>
00139 GMatrix<Real>::operator Real* ()
00140 {
00141 return m_afData;
00142 }
00143
00144 template <class Real>
00145 const Real* GMatrix<Real>::operator[] (int iRow) const
00146 {
00147 assert(0 <= iRow && iRow < m_iRows);
00148 return m_aafEntry[iRow];
00149 }
00150
00151 template <class Real>
00152 Real* GMatrix<Real>::operator[] (int iRow)
00153 {
00154 assert(0 <= iRow && iRow < m_iRows);
00155 return m_aafEntry[iRow];
00156 }
00157
00158 template <class Real>
00159 Real GMatrix<Real>::operator() (int iRow, int iCol) const
00160 {
00161 return m_aafEntry[iRow][iCol];
00162 }
00163
00164 template <class Real>
00165 Real& GMatrix<Real>::operator() (int iRow, int iCol)
00166 {
00167 assert(0 <= iRow && iRow < m_iRows && 0 <= iCol && iCol <= m_iCols);
00168 return m_aafEntry[iRow][iCol];
00169 }
00170
00171 template <class Real>
00172 void GMatrix<Real>::SwapRows (int iRow0, int iRow1)
00173 {
00174 assert(0 <= iRow0 && iRow0 < m_iRows && 0 <= iRow1 && iRow1 < m_iRows);
00175 Real* afSave = m_aafEntry[iRow0];
00176 m_aafEntry[iRow0] = m_aafEntry[iRow1];
00177 m_aafEntry[iRow1] = afSave;
00178 }
00179
00180 template <class Real>
00181 void GMatrix<Real>::SetRow (int iRow, const GVector<Real>& rkV)
00182 {
00183 assert((0 <= iRow && iRow < m_iRows) && (rkV.GetSize() == m_iCols));
00184 for (int iCol = 0; iCol < m_iCols; iCol++)
00185 {
00186 m_aafEntry[iRow][iCol] = rkV[iCol];
00187 }
00188 }
00189
00190 template <class Real>
00191 GVector<Real> GMatrix<Real>::GetRow (int iRow) const
00192 {
00193 assert(0 <= iRow && iRow < m_iRows);
00194 GVector<Real> kV(m_iCols);
00195 for (int iCol = 0; iCol < m_iCols; iCol++)
00196 {
00197 kV[iCol] = m_aafEntry[iRow][iCol];
00198 }
00199 return kV;
00200 }
00201
00202 template <class Real>
00203 void GMatrix<Real>::SetColumn (int iCol, const GVector<Real>& rkV)
00204 {
00205 assert((0 <= iCol && iCol < m_iCols) && (rkV.GetSize() == m_iRows));
00206 for (int iRow = 0; iRow < m_iRows; iRow++)
00207 {
00208 m_aafEntry[iRow][iCol] = rkV[iRow];
00209 }
00210 }
00211
00212 template <class Real>
00213 GVector<Real> GMatrix<Real>::GetColumn (int iCol) const
00214 {
00215 assert(0 <= iCol && iCol < m_iCols);
00216 GVector<Real> kV(m_iRows);
00217 for (int iRow = 0; iRow < m_iRows; iRow++)
00218 {
00219 kV[iRow] = m_aafEntry[iRow][iCol];
00220 }
00221 return kV;
00222 }
00223
00224 template <class Real>
00225 void GMatrix<Real>::SetMatrix (int iRows, int iCols, const Real* afData)
00226 {
00227 Deallocate();
00228 if (iRows > 0 && iCols > 0)
00229 {
00230 m_iRows = iRows;
00231 m_iCols = iCols;
00232 m_iQuantity = m_iRows*m_iCols;
00233 Allocate(false);
00234 size_t uiSize = m_iQuantity*sizeof(Real);
00235 System::Memcpy(m_afData,uiSize,afData,uiSize);
00236 }
00237 else
00238 {
00239 m_iRows = 0;
00240 m_iCols = 0;
00241 m_iQuantity = 0;
00242 m_afData = 0;
00243 m_aafEntry = 0;
00244 }
00245 }
00246
00247 template <class Real>
00248 void GMatrix<Real>::SetMatrix (int iRows, int iCols, const Real** aafEntry)
00249 {
00250 Deallocate();
00251 if (iRows > 0 && iCols > 0)
00252 {
00253 m_iRows = iRows;
00254 m_iCols = iCols;
00255 m_iQuantity = m_iRows*m_iCols;
00256 Allocate(false);
00257 for (int iRow = 0; iRow < m_iRows; iRow++)
00258 {
00259 for (int iCol = 0; iCol < m_iCols; iCol++)
00260 {
00261 m_aafEntry[iRow][iCol] = aafEntry[iRow][iCol];
00262 }
00263 }
00264 }
00265 else
00266 {
00267 m_iRows = 0;
00268 m_iCols = 0;
00269 m_iQuantity = 0;
00270 m_afData = 0;
00271 m_aafEntry = 0;
00272 }
00273 }
00274
00275 template <class Real>
00276 void GMatrix<Real>::GetColumnMajor (Real* afCMajor) const
00277 {
00278 for (int iRow = 0, i = 0; iRow < m_iRows; iRow++)
00279 {
00280 for (int iCol = 0; iCol < m_iCols; iCol++)
00281 {
00282 afCMajor[i++] = m_aafEntry[iCol][iRow];
00283 }
00284 }
00285 }
00286
00287 template <class Real>
00288 GMatrix<Real>& GMatrix<Real>::operator= (const GMatrix& rkM)
00289 {
00290 if (rkM.m_iQuantity > 0)
00291 {
00292 if (m_iRows != rkM.m_iRows || m_iCols != rkM.m_iCols)
00293 {
00294 Deallocate();
00295 m_iRows = rkM.m_iRows;
00296 m_iCols = rkM.m_iCols;
00297 m_iQuantity = rkM.m_iQuantity;
00298 Allocate(false);
00299 }
00300 for (int iRow = 0; iRow < m_iRows; iRow++)
00301 {
00302 for (int iCol = 0; iCol < m_iCols; iCol++)
00303 {
00304 m_aafEntry[iRow][iCol] = rkM.m_aafEntry[iRow][iCol];
00305 }
00306 }
00307 }
00308 else
00309 {
00310 Deallocate();
00311 m_iRows = 0;
00312 m_iCols = 0;
00313 m_iQuantity = 0;
00314 m_afData = 0;
00315 m_aafEntry = 0;
00316 }
00317 return *this;
00318 }
00319
00320 template <class Real>
00321 int GMatrix<Real>::CompareArrays (const GMatrix& rkM) const
00322 {
00323 return memcmp(m_afData,rkM.m_afData,m_iQuantity*sizeof(Real));
00324 }
00325
00326 template <class Real>
00327 bool GMatrix<Real>::operator== (const GMatrix& rkM) const
00328 {
00329 return CompareArrays(rkM) == 0;
00330 }
00331
00332 template <class Real>
00333 bool GMatrix<Real>::operator!= (const GMatrix& rkM) const
00334 {
00335 return CompareArrays(rkM) != 0;
00336 }
00337
00338 template <class Real>
00339 bool GMatrix<Real>::operator< (const GMatrix& rkM) const
00340 {
00341 return CompareArrays(rkM) < 0;
00342 }
00343
00344 template <class Real>
00345 bool GMatrix<Real>::operator<= (const GMatrix& rkM) const
00346 {
00347 return CompareArrays(rkM) <= 0;
00348 }
00349
00350 template <class Real>
00351 bool GMatrix<Real>::operator> (const GMatrix& rkM) const
00352 {
00353 return CompareArrays(rkM) > 0;
00354 }
00355
00356 template <class Real>
00357 bool GMatrix<Real>::operator>= (const GMatrix& rkM) const
00358 {
00359 return CompareArrays(rkM) >= 0;
00360 }
00361
00362 template <class Real>
00363 GMatrix<Real> GMatrix<Real>::operator+ (const GMatrix& rkM) const
00364 {
00365 GMatrix<Real> kSum(rkM.m_iRows,rkM.m_iCols);
00366 for (int i = 0; i < m_iQuantity; i++)
00367 {
00368 kSum.m_afData[i] = m_afData[i] + rkM.m_afData[i];
00369 }
00370 return kSum;
00371 }
00372
00373 template <class Real>
00374 GMatrix<Real> GMatrix<Real>::operator- (const GMatrix& rkM) const
00375 {
00376 GMatrix<Real> kDiff(rkM.m_iRows,rkM.m_iCols);
00377 for (int i = 0; i < m_iQuantity; i++)
00378 {
00379 kDiff.m_afData[i] = m_afData[i] - rkM.m_afData[i];
00380 }
00381 return kDiff;
00382 }
00383
00384 template <class Real>
00385 GMatrix<Real> GMatrix<Real>::operator* (const GMatrix& rkM) const
00386 {
00387
00388 assert(m_iCols == rkM.m_iRows);
00389 GMatrix<Real> kProd(m_iRows,rkM.m_iCols);
00390 for (int iRow = 0; iRow < kProd.m_iRows; iRow++)
00391 {
00392 for (int iCol = 0; iCol < kProd.m_iCols; iCol++)
00393 {
00394 for (int iMid = 0; iMid < m_iCols; iMid++)
00395 {
00396 kProd.m_aafEntry[iRow][iCol] += m_aafEntry[iRow][iMid] *
00397 rkM.m_aafEntry[iMid][iCol];
00398 }
00399 }
00400 }
00401 return kProd;
00402 }
00403
00404 template <class Real>
00405 GMatrix<Real> GMatrix<Real>::operator* (Real fScalar) const
00406 {
00407 GMatrix<Real> kProd(m_iRows,m_iCols);
00408 for (int i = 0; i < m_iQuantity; i++)
00409 {
00410 kProd.m_afData[i] = fScalar*m_afData[i];
00411 }
00412 return kProd;
00413 }
00414
00415 template <class Real>
00416 GMatrix<Real> GMatrix<Real>::operator/ (Real fScalar) const
00417 {
00418 GMatrix<Real> kQuot(m_iRows,m_iCols);
00419 int i;
00420
00421 if (fScalar != (Real)0.0)
00422 {
00423 Real fInvScalar = ((Real)1.0)/fScalar;
00424 for (i = 0; i < m_iQuantity; i++)
00425 {
00426 kQuot.m_afData[i] = fInvScalar*m_afData[i];
00427 }
00428 }
00429 else
00430 {
00431 for (i = 0; i < m_iQuantity; i++)
00432 {
00433 kQuot.m_afData[i] = Math<Real>::MAX_REAL;
00434 }
00435 }
00436
00437 return kQuot;
00438 }
00439
00440 template <class Real>
00441 GMatrix<Real> GMatrix<Real>::operator- () const
00442 {
00443 GMatrix<Real> kNeg(m_iRows,m_iCols);
00444 for (int i = 0; i < m_iQuantity; i++)
00445 {
00446 kNeg.m_afData[i] = -m_afData[i];
00447 }
00448 return kNeg;
00449 }
00450
00451 template <class Real>
00452 GMatrix<Real> operator* (Real fScalar, const GMatrix<Real>& rkM)
00453 {
00454 GMatrix<Real> kProd(rkM.GetRows(),rkM.GetColumns());
00455 const Real* afMEntry = rkM;
00456 Real* afPEntry = kProd;
00457 for (int i = 0; i < rkM.GetQuantity(); i++)
00458 {
00459 afPEntry[i] = fScalar*afMEntry[i];
00460 }
00461 return kProd;
00462 }
00463
00464 template <class Real>
00465 GMatrix<Real>& GMatrix<Real>::operator+= (const GMatrix& rkM)
00466 {
00467 for (int i = 0; i < m_iQuantity; i++)
00468 {
00469 m_afData[i] += rkM.m_afData[i];
00470 }
00471 return *this;
00472 }
00473
00474 template <class Real>
00475 GMatrix<Real>& GMatrix<Real>::operator-= (const GMatrix& rkM)
00476 {
00477 for (int i = 0; i < m_iQuantity; i++)
00478 {
00479 m_afData[i] -= rkM.m_afData[i];
00480 }
00481 return *this;
00482 }
00483
00484 template <class Real>
00485 GMatrix<Real>& GMatrix<Real>::operator*= (Real fScalar)
00486 {
00487 for (int i = 0; i < m_iQuantity; i++)
00488 {
00489 m_afData[i] *= fScalar;
00490 }
00491 return *this;
00492 }
00493
00494 template <class Real>
00495 GMatrix<Real>& GMatrix<Real>::operator/= (Real fScalar)
00496 {
00497 int i;
00498
00499 if (fScalar != (Real)0.0)
00500 {
00501 Real fInvScalar = ((Real)1.0)/fScalar;
00502 for (i = 0; i < m_iQuantity; i++)
00503 {
00504 m_afData[i] *= fInvScalar;
00505 }
00506 }
00507 else
00508 {
00509 for (i = 0; i < m_iQuantity; i++)
00510 {
00511 m_afData[i] = Math<Real>::MAX_REAL;
00512 }
00513 }
00514
00515 return *this;
00516 }
00517
00518 template <class Real>
00519 GMatrix<Real> GMatrix<Real>::Transpose () const
00520 {
00521 GMatrix<Real> kTranspose(m_iCols,m_iRows);
00522 for (int iRow = 0; iRow < m_iRows; iRow++)
00523 {
00524 for (int iCol = 0; iCol < m_iCols; iCol++)
00525 {
00526 kTranspose.m_aafEntry[iCol][iRow] = m_aafEntry[iRow][iCol];
00527 }
00528 }
00529 return kTranspose;
00530 }
00531
00532 template <class Real>
00533 GMatrix<Real> GMatrix<Real>::TransposeTimes (const GMatrix& rkM) const
00534 {
00535
00536 assert(m_iRows == rkM.m_iRows);
00537 GMatrix<Real> kProd(m_iCols,rkM.m_iCols);
00538 for (int iRow = 0; iRow < kProd.m_iRows; iRow++)
00539 {
00540 for (int iCol = 0; iCol < kProd.m_iCols; iCol++)
00541 {
00542 for (int iMid = 0; iMid < m_iRows; iMid++)
00543 {
00544 kProd.m_aafEntry[iRow][iCol] += m_aafEntry[iMid][iRow] *
00545 rkM.m_aafEntry[iMid][iCol];
00546 }
00547 }
00548 }
00549 return kProd;
00550 }
00551
00552 template <class Real>
00553 GMatrix<Real> GMatrix<Real>::TimesTranspose (const GMatrix& rkM) const
00554 {
00555
00556 assert(m_iCols == rkM.m_iCols);
00557 GMatrix<Real> kProd(m_iRows,rkM.m_iRows);
00558 for (int iRow = 0; iRow < kProd.m_iRows; iRow++)
00559 {
00560 for (int iCol = 0; iCol < kProd.m_iCols; iCol++)
00561 {
00562 for (int iMid = 0; iMid < m_iCols; iMid++)
00563 {
00564 kProd.m_aafEntry[iRow][iCol] += m_aafEntry[iRow][iMid] *
00565 rkM.m_aafEntry[iCol][iMid];
00566 }
00567 }
00568 }
00569 return kProd;
00570 }
00571
00572 template <class Real>
00573 GVector<Real> GMatrix<Real>::operator* (const GVector<Real>& rkV) const
00574 {
00575 assert(rkV.GetSize() == m_iCols);
00576 GVector<Real> kProd(m_iRows);
00577 for (int iRow = 0; iRow < m_iRows; iRow++)
00578 {
00579 for (int iCol = 0; iCol < m_iCols; iCol++)
00580 {
00581 kProd[iRow] += m_aafEntry[iRow][iCol]*rkV[iCol];
00582 }
00583
00584 }
00585 return kProd;
00586 }
00587
00588 template <class Real>
00589 GVector<Real> operator* (const GVector<Real>& rkV, const GMatrix<Real>& rkM)
00590 {
00591 assert(rkV.GetSize() == rkM.GetRows());
00592 GVector<Real> kProd(rkM.GetColumns());
00593 Real* afPEntry = kProd;
00594 for (int iCol = 0; iCol < rkM.GetColumns(); iCol++)
00595 {
00596 for (int iRow = 0; iRow < rkM.GetRows(); iRow++)
00597 {
00598 afPEntry[iCol] += rkV[iRow]*rkM[iRow][iCol];
00599 }
00600 }
00601 return kProd;
00602 }
00603
00604 template <class Real>
00605 Real GMatrix<Real>::QForm (const GVector<Real>& rkU, const GVector<Real>& rkV)
00606 const
00607 {
00608 assert(rkU.GetSize() == m_iRows && rkV.GetSize() == m_iCols);
00609 return rkU.Dot((*this)*rkV);
00610 }
00611
00612 template <class Real>
00613 bool GMatrix<Real>::GetInverse (GMatrix<Real>& rkInverse) const
00614 {
00615
00616 if (GetRows() > 0 && GetRows() != GetColumns())
00617 {
00618 return false;
00619 }
00620
00621 int iSize = GetRows();
00622 rkInverse = *this;
00623
00624 int* aiColIndex = WM4_NEW int[iSize];
00625 int* aiRowIndex = WM4_NEW int[iSize];
00626 bool* abPivoted = WM4_NEW bool[iSize];
00627 memset(abPivoted,0,iSize*sizeof(bool));
00628
00629 int i1, i2, iRow = 0, iCol = 0;
00630 Real fSave;
00631
00632
00633 for (int i0 = 0; i0 < iSize; i0++)
00634 {
00635
00636 Real fMax = (Real)0.0;
00637 for (i1 = 0; i1 < iSize; i1++)
00638 {
00639 if (!abPivoted[i1])
00640 {
00641 for (i2 = 0; i2 < iSize; i2++)
00642 {
00643 if (!abPivoted[i2])
00644 {
00645 Real fAbs = Math<Real>::FAbs(rkInverse[i1][i2]);
00646 if (fAbs > fMax)
00647 {
00648 fMax = fAbs;
00649 iRow = i1;
00650 iCol = i2;
00651 }
00652 }
00653 }
00654 }
00655 }
00656
00657 if (fMax == (Real)0.0)
00658 {
00659
00660 WM4_DELETE[] aiColIndex;
00661 WM4_DELETE[] aiRowIndex;
00662 WM4_DELETE[] abPivoted;
00663 return false;
00664 }
00665
00666 abPivoted[iCol] = true;
00667
00668
00669 if (iRow != iCol)
00670 {
00671 rkInverse.SwapRows(iRow,iCol);
00672 }
00673
00674
00675 aiRowIndex[i0] = iRow;
00676 aiColIndex[i0] = iCol;
00677
00678
00679 Real fInv = ((Real)1.0)/rkInverse[iCol][iCol];
00680 rkInverse[iCol][iCol] = (Real)1.0;
00681 for (i2 = 0; i2 < iSize; i2++)
00682 {
00683 rkInverse[iCol][i2] *= fInv;
00684 }
00685
00686
00687 for (i1 = 0; i1 < iSize; i1++)
00688 {
00689 if (i1 != iCol)
00690 {
00691 fSave = rkInverse[i1][iCol];
00692 rkInverse[i1][iCol] = (Real)0.0;
00693 for (i2 = 0; i2 < iSize; i2++)
00694 {
00695 rkInverse[i1][i2] -= rkInverse[iCol][i2]*fSave;
00696 }
00697 }
00698 }
00699 }
00700
00701
00702 for (i1 = iSize-1; i1 >= 0; i1--)
00703 {
00704 if (aiRowIndex[i1] != aiColIndex[i1])
00705 {
00706 for (i2 = 0; i2 < iSize; i2++)
00707 {
00708 fSave = rkInverse[i2][aiRowIndex[i1]];
00709 rkInverse[i2][aiRowIndex[i1]] =
00710 rkInverse[i2][aiColIndex[i1]];
00711 rkInverse[i2][aiColIndex[i1]] = fSave;
00712 }
00713 }
00714 }
00715
00716 WM4_DELETE[] aiColIndex;
00717 WM4_DELETE[] aiRowIndex;
00718 WM4_DELETE[] abPivoted;
00719 return true;
00720 }
00721
00722 }