Wm4Matrix3.inl

Go to the documentation of this file.
00001 // Wild Magic Source Code
00002 // David Eberly
00003 // http://www.geometrictools.com
00004 // Copyright (c) 1998-2007
00005 //
00006 // This library is free software; you can redistribute it and/or modify it
00007 // under the terms of the GNU Lesser General Public License as published by
00008 // the Free Software Foundation; either version 2.1 of the License, or (at
00009 // your option) any later version.  The license is available for reading at
00010 // either of the locations:
00011 //     http://www.gnu.org/copyleft/lgpl.html
00012 //     http://www.geometrictools.com/License/WildMagicLicense.pdf
00013 // The license applies to versions 0 through 4 of Wild Magic.
00014 //
00015 // Version: 4.0.2 (2006/09/05)
00016 
00017 namespace Wm4
00018 {
00019 //----------------------------------------------------------------------------
00020 template <class Real>
00021 Matrix3<Real>::Matrix3 (bool bZero)
00022 {
00023     if (bZero)
00024     {
00025         MakeZero();
00026     }
00027     else
00028     {
00029         MakeIdentity();
00030     }
00031 }
00032 //----------------------------------------------------------------------------
00033 template <class Real>
00034 Matrix3<Real>::Matrix3 (const Matrix3& rkM)
00035 {
00036     m_afEntry[0] = rkM.m_afEntry[0];
00037     m_afEntry[1] = rkM.m_afEntry[1];
00038     m_afEntry[2] = rkM.m_afEntry[2];
00039     m_afEntry[3] = rkM.m_afEntry[3];
00040     m_afEntry[4] = rkM.m_afEntry[4];
00041     m_afEntry[5] = rkM.m_afEntry[5];
00042     m_afEntry[6] = rkM.m_afEntry[6];
00043     m_afEntry[7] = rkM.m_afEntry[7];
00044     m_afEntry[8] = rkM.m_afEntry[8];
00045 }
00046 //----------------------------------------------------------------------------
00047 template <class Real>
00048 Matrix3<Real>::Matrix3 (Real fM00, Real fM01, Real fM02, Real fM10, Real fM11,
00049     Real fM12, Real fM20, Real fM21, Real fM22)
00050 {
00051     m_afEntry[0] = fM00;
00052     m_afEntry[1] = fM01;
00053     m_afEntry[2] = fM02;
00054     m_afEntry[3] = fM10;
00055     m_afEntry[4] = fM11;
00056     m_afEntry[5] = fM12;
00057     m_afEntry[6] = fM20;
00058     m_afEntry[7] = fM21;
00059     m_afEntry[8] = fM22;
00060 }
00061 //----------------------------------------------------------------------------
00062 template <class Real>
00063 Matrix3<Real>::Matrix3 (const Real afEntry[9], bool bRowMajor)
00064 {
00065     if (bRowMajor)
00066     {
00067         m_afEntry[0] = afEntry[0];
00068         m_afEntry[1] = afEntry[1];
00069         m_afEntry[2] = afEntry[2];
00070         m_afEntry[3] = afEntry[3];
00071         m_afEntry[4] = afEntry[4];
00072         m_afEntry[5] = afEntry[5];
00073         m_afEntry[6] = afEntry[6];
00074         m_afEntry[7] = afEntry[7];
00075         m_afEntry[8] = afEntry[8];
00076     }
00077     else
00078     {
00079         m_afEntry[0] = afEntry[0];
00080         m_afEntry[1] = afEntry[3];
00081         m_afEntry[2] = afEntry[6];
00082         m_afEntry[3] = afEntry[1];
00083         m_afEntry[4] = afEntry[4];
00084         m_afEntry[5] = afEntry[7];
00085         m_afEntry[6] = afEntry[2];
00086         m_afEntry[7] = afEntry[5];
00087         m_afEntry[8] = afEntry[8];
00088     }
00089 }
00090 //----------------------------------------------------------------------------
00091 template <class Real>
00092 Matrix3<Real>::Matrix3 (const Vector3<Real>& rkU, const Vector3<Real>& rkV,
00093     const Vector3<Real>& rkW, bool bColumns)
00094 {
00095     if (bColumns)
00096     {
00097         m_afEntry[0] = rkU[0];
00098         m_afEntry[1] = rkV[0];
00099         m_afEntry[2] = rkW[0];
00100         m_afEntry[3] = rkU[1];
00101         m_afEntry[4] = rkV[1];
00102         m_afEntry[5] = rkW[1];
00103         m_afEntry[6] = rkU[2];
00104         m_afEntry[7] = rkV[2];
00105         m_afEntry[8] = rkW[2];
00106     }
00107     else
00108     {
00109         m_afEntry[0] = rkU[0];
00110         m_afEntry[1] = rkU[1];
00111         m_afEntry[2] = rkU[2];
00112         m_afEntry[3] = rkV[0];
00113         m_afEntry[4] = rkV[1];
00114         m_afEntry[5] = rkV[2];
00115         m_afEntry[6] = rkW[0];
00116         m_afEntry[7] = rkW[1];
00117         m_afEntry[8] = rkW[2];
00118     }
00119 }
00120 //----------------------------------------------------------------------------
00121 template <class Real>
00122 Matrix3<Real>::Matrix3 (const Vector3<Real>* akV, bool bColumns)
00123 {
00124     if (bColumns)
00125     {
00126         m_afEntry[0] = akV[0][0];
00127         m_afEntry[1] = akV[1][0];
00128         m_afEntry[2] = akV[2][0];
00129         m_afEntry[3] = akV[0][1];
00130         m_afEntry[4] = akV[1][1];
00131         m_afEntry[5] = akV[2][1];
00132         m_afEntry[6] = akV[0][2];
00133         m_afEntry[7] = akV[1][2];
00134         m_afEntry[8] = akV[2][2];
00135     }
00136     else
00137     {
00138         m_afEntry[0] = akV[0][0];
00139         m_afEntry[1] = akV[0][1];
00140         m_afEntry[2] = akV[0][2];
00141         m_afEntry[3] = akV[1][0];
00142         m_afEntry[4] = akV[1][1];
00143         m_afEntry[5] = akV[1][2];
00144         m_afEntry[6] = akV[2][0];
00145         m_afEntry[7] = akV[2][1];
00146         m_afEntry[8] = akV[2][2];
00147     }
00148 }
00149 //----------------------------------------------------------------------------
00150 template <class Real>
00151 Matrix3<Real>::Matrix3 (Real fM00, Real fM11, Real fM22)
00152 {
00153     MakeDiagonal(fM00,fM11,fM22);
00154 }
00155 //----------------------------------------------------------------------------
00156 template <class Real>
00157 Matrix3<Real>::Matrix3 (const Vector3<Real>& rkAxis, Real fAngle)
00158 {
00159     FromAxisAngle(rkAxis,fAngle);
00160 }
00161 //----------------------------------------------------------------------------
00162 template <class Real>
00163 Matrix3<Real>::Matrix3 (const Vector3<Real>& rkU, const Vector3<Real>& rkV)
00164 {
00165     MakeTensorProduct(rkU,rkV);
00166 }
00167 //----------------------------------------------------------------------------
00168 template <class Real>
00169 Matrix3<Real>::operator const Real* () const
00170 {
00171     return m_afEntry;
00172 }
00173 //----------------------------------------------------------------------------
00174 template <class Real>
00175 Matrix3<Real>::operator Real* ()
00176 {
00177     return m_afEntry;
00178 }
00179 //----------------------------------------------------------------------------
00180 template <class Real>
00181 const Real* Matrix3<Real>::operator[] (int iRow) const
00182 {
00183     return &m_afEntry[3*iRow];
00184 }
00185 //----------------------------------------------------------------------------
00186 template <class Real>
00187 Real* Matrix3<Real>::operator[] (int iRow)
00188 {
00189     return &m_afEntry[3*iRow];
00190 }
00191 //----------------------------------------------------------------------------
00192 template <class Real>
00193 Real Matrix3<Real>::operator() (int iRow, int iCol) const
00194 {
00195     return m_afEntry[iCol+3*iRow];
00196 }
00197 //----------------------------------------------------------------------------
00198 template <class Real>
00199 Real& Matrix3<Real>::operator() (int iRow, int iCol)
00200 {
00201     return m_afEntry[iCol+3*iRow];
00202 }
00203 //----------------------------------------------------------------------------
00204 template <class Real>
00205 Matrix3<Real>& Matrix3<Real>::MakeZero ()
00206 {
00207     m_afEntry[0] = (Real)0.0;
00208     m_afEntry[1] = (Real)0.0;
00209     m_afEntry[2] = (Real)0.0;
00210     m_afEntry[3] = (Real)0.0;
00211     m_afEntry[4] = (Real)0.0;
00212     m_afEntry[5] = (Real)0.0;
00213     m_afEntry[6] = (Real)0.0;
00214     m_afEntry[7] = (Real)0.0;
00215     m_afEntry[8] = (Real)0.0;
00216     return *this;
00217 }
00218 //----------------------------------------------------------------------------
00219 template <class Real>
00220 Matrix3<Real>& Matrix3<Real>::MakeIdentity ()
00221 {
00222     m_afEntry[0] = (Real)1.0;
00223     m_afEntry[1] = (Real)0.0;
00224     m_afEntry[2] = (Real)0.0;
00225     m_afEntry[3] = (Real)0.0;
00226     m_afEntry[4] = (Real)1.0;
00227     m_afEntry[5] = (Real)0.0;
00228     m_afEntry[6] = (Real)0.0;
00229     m_afEntry[7] = (Real)0.0;
00230     m_afEntry[8] = (Real)1.0;
00231     return *this;
00232 }
00233 //----------------------------------------------------------------------------
00234 template <class Real>
00235 Matrix3<Real>& Matrix3<Real>::MakeDiagonal (Real fM00, Real fM11, Real fM22)
00236 {
00237     m_afEntry[0] = fM00;
00238     m_afEntry[1] = (Real)0.0;
00239     m_afEntry[2] = (Real)0.0;
00240     m_afEntry[3] = (Real)0.0;
00241     m_afEntry[4] = fM11;
00242     m_afEntry[5] = (Real)0.0;
00243     m_afEntry[6] = (Real)0.0;
00244     m_afEntry[7] = (Real)0.0;
00245     m_afEntry[8] = fM22;
00246     return *this;
00247 }
00248 //----------------------------------------------------------------------------
00249 template <class Real>
00250 Matrix3<Real>& Matrix3<Real>::FromAxisAngle (const Vector3<Real>& rkAxis,
00251     Real fAngle)
00252 {
00253     Real fCos = Math<Real>::Cos(fAngle);
00254     Real fSin = Math<Real>::Sin(fAngle);
00255     Real fOneMinusCos = ((Real)1.0)-fCos;
00256     Real fX2 = rkAxis[0]*rkAxis[0];
00257     Real fY2 = rkAxis[1]*rkAxis[1];
00258     Real fZ2 = rkAxis[2]*rkAxis[2];
00259     Real fXYM = rkAxis[0]*rkAxis[1]*fOneMinusCos;
00260     Real fXZM = rkAxis[0]*rkAxis[2]*fOneMinusCos;
00261     Real fYZM = rkAxis[1]*rkAxis[2]*fOneMinusCos;
00262     Real fXSin = rkAxis[0]*fSin;
00263     Real fYSin = rkAxis[1]*fSin;
00264     Real fZSin = rkAxis[2]*fSin;
00265     
00266     m_afEntry[0] = fX2*fOneMinusCos+fCos;
00267     m_afEntry[1] = fXYM-fZSin;
00268     m_afEntry[2] = fXZM+fYSin;
00269     m_afEntry[3] = fXYM+fZSin;
00270     m_afEntry[4] = fY2*fOneMinusCos+fCos;
00271     m_afEntry[5] = fYZM-fXSin;
00272     m_afEntry[6] = fXZM-fYSin;
00273     m_afEntry[7] = fYZM+fXSin;
00274     m_afEntry[8] = fZ2*fOneMinusCos+fCos;
00275 
00276     return *this;
00277 }
00278 //----------------------------------------------------------------------------
00279 template <class Real>
00280 Matrix3<Real>& Matrix3<Real>::MakeTensorProduct (const Vector3<Real>& rkU,
00281     const Vector3<Real>& rkV)
00282 {
00283     m_afEntry[0] = rkU[0]*rkV[0];
00284     m_afEntry[1] = rkU[0]*rkV[1];
00285     m_afEntry[2] = rkU[0]*rkV[2];
00286     m_afEntry[3] = rkU[1]*rkV[0];
00287     m_afEntry[4] = rkU[1]*rkV[1];
00288     m_afEntry[5] = rkU[1]*rkV[2];
00289     m_afEntry[6] = rkU[2]*rkV[0];
00290     m_afEntry[7] = rkU[2]*rkV[1];
00291     m_afEntry[8] = rkU[2]*rkV[2];
00292     return *this;
00293 }
00294 //----------------------------------------------------------------------------
00295 template <class Real>
00296 void Matrix3<Real>::SetRow (int iRow, const Vector3<Real>& rkV)
00297 {
00298     int i0 = 3*iRow, i1 = i0+1, i2 = i1+1;
00299     m_afEntry[i0] = rkV[0];
00300     m_afEntry[i1] = rkV[1];
00301     m_afEntry[i2] = rkV[2];
00302 }
00303 //----------------------------------------------------------------------------
00304 template <class Real>
00305 Vector3<Real> Matrix3<Real>::GetRow (int iRow) const
00306 {
00307     int i0 = 3*iRow, i1 = i0+1, i2 = i1+1;
00308     return Vector3<Real>(m_afEntry[i0],m_afEntry[i1],m_afEntry[i2]);
00309 }
00310 //----------------------------------------------------------------------------
00311 template <class Real>
00312 void Matrix3<Real>::SetColumn (int iCol, const Vector3<Real>& rkV)
00313 {
00314     m_afEntry[iCol] = rkV[0];
00315     m_afEntry[iCol+3] = rkV[1];
00316     m_afEntry[iCol+6] = rkV[2];
00317 }
00318 //----------------------------------------------------------------------------
00319 template <class Real>
00320 Vector3<Real> Matrix3<Real>::GetColumn (int iCol) const
00321 {
00322     return Vector3<Real>(m_afEntry[iCol],m_afEntry[iCol+3],m_afEntry[iCol+6]);
00323 }
00324 //----------------------------------------------------------------------------
00325 template <class Real>
00326 void Matrix3<Real>::GetColumnMajor (Real* afCMajor) const
00327 {
00328     afCMajor[0] = m_afEntry[0];
00329     afCMajor[1] = m_afEntry[3];
00330     afCMajor[2] = m_afEntry[6];
00331     afCMajor[3] = m_afEntry[1];
00332     afCMajor[4] = m_afEntry[4];
00333     afCMajor[5] = m_afEntry[7];
00334     afCMajor[6] = m_afEntry[2];
00335     afCMajor[7] = m_afEntry[5];
00336     afCMajor[8] = m_afEntry[8];
00337 }
00338 //----------------------------------------------------------------------------
00339 template <class Real>
00340 Matrix3<Real>& Matrix3<Real>::operator= (const Matrix3& rkM)
00341 {
00342     m_afEntry[0] = rkM.m_afEntry[0];
00343     m_afEntry[1] = rkM.m_afEntry[1];
00344     m_afEntry[2] = rkM.m_afEntry[2];
00345     m_afEntry[3] = rkM.m_afEntry[3];
00346     m_afEntry[4] = rkM.m_afEntry[4];
00347     m_afEntry[5] = rkM.m_afEntry[5];
00348     m_afEntry[6] = rkM.m_afEntry[6];
00349     m_afEntry[7] = rkM.m_afEntry[7];
00350     m_afEntry[8] = rkM.m_afEntry[8];
00351     return *this;
00352 }
00353 //----------------------------------------------------------------------------
00354 template <class Real>
00355 int Matrix3<Real>::CompareArrays (const Matrix3& rkM) const
00356 {
00357     return memcmp(m_afEntry,rkM.m_afEntry,9*sizeof(Real));
00358 }
00359 //----------------------------------------------------------------------------
00360 template <class Real>
00361 bool Matrix3<Real>::operator== (const Matrix3& rkM) const
00362 {
00363     return CompareArrays(rkM) == 0;
00364 }
00365 //----------------------------------------------------------------------------
00366 template <class Real>
00367 bool Matrix3<Real>::operator!= (const Matrix3& rkM) const
00368 {
00369     return CompareArrays(rkM) != 0;
00370 }
00371 //----------------------------------------------------------------------------
00372 template <class Real>
00373 bool Matrix3<Real>::operator<  (const Matrix3& rkM) const
00374 {
00375     return CompareArrays(rkM) < 0;
00376 }
00377 //----------------------------------------------------------------------------
00378 template <class Real>
00379 bool Matrix3<Real>::operator<= (const Matrix3& rkM) const
00380 {
00381     return CompareArrays(rkM) <= 0;
00382 }
00383 //----------------------------------------------------------------------------
00384 template <class Real>
00385 bool Matrix3<Real>::operator>  (const Matrix3& rkM) const
00386 {
00387     return CompareArrays(rkM) > 0;
00388 }
00389 //----------------------------------------------------------------------------
00390 template <class Real>
00391 bool Matrix3<Real>::operator>= (const Matrix3& rkM) const
00392 {
00393     return CompareArrays(rkM) >= 0;
00394 }
00395 //----------------------------------------------------------------------------
00396 template <class Real>
00397 Matrix3<Real> Matrix3<Real>::operator+ (const Matrix3& rkM) const
00398 {
00399     return Matrix3<Real>(
00400         m_afEntry[0] + rkM.m_afEntry[0],
00401         m_afEntry[1] + rkM.m_afEntry[1],
00402         m_afEntry[2] + rkM.m_afEntry[2],
00403         m_afEntry[3] + rkM.m_afEntry[3],
00404         m_afEntry[4] + rkM.m_afEntry[4],
00405         m_afEntry[5] + rkM.m_afEntry[5],
00406         m_afEntry[6] + rkM.m_afEntry[6],
00407         m_afEntry[7] + rkM.m_afEntry[7],
00408         m_afEntry[8] + rkM.m_afEntry[8]);
00409 }
00410 //----------------------------------------------------------------------------
00411 template <class Real>
00412 Matrix3<Real> Matrix3<Real>::operator- (const Matrix3& rkM) const
00413 {
00414     return Matrix3<Real>(
00415         m_afEntry[0] - rkM.m_afEntry[0],
00416         m_afEntry[1] - rkM.m_afEntry[1],
00417         m_afEntry[2] - rkM.m_afEntry[2],
00418         m_afEntry[3] - rkM.m_afEntry[3],
00419         m_afEntry[4] - rkM.m_afEntry[4],
00420         m_afEntry[5] - rkM.m_afEntry[5],
00421         m_afEntry[6] - rkM.m_afEntry[6],
00422         m_afEntry[7] - rkM.m_afEntry[7],
00423         m_afEntry[8] - rkM.m_afEntry[8]);
00424 }
00425 //----------------------------------------------------------------------------
00426 template <class Real>
00427 Matrix3<Real> Matrix3<Real>::operator* (const Matrix3& rkM) const
00428 {
00429     return Matrix3<Real>(
00430         m_afEntry[0]*rkM.m_afEntry[0] +
00431         m_afEntry[1]*rkM.m_afEntry[3] +
00432         m_afEntry[2]*rkM.m_afEntry[6],
00433 
00434         m_afEntry[0]*rkM.m_afEntry[1] +
00435         m_afEntry[1]*rkM.m_afEntry[4] +
00436         m_afEntry[2]*rkM.m_afEntry[7],
00437 
00438         m_afEntry[0]*rkM.m_afEntry[2] +
00439         m_afEntry[1]*rkM.m_afEntry[5] +
00440         m_afEntry[2]*rkM.m_afEntry[8],
00441 
00442         m_afEntry[3]*rkM.m_afEntry[0] +
00443         m_afEntry[4]*rkM.m_afEntry[3] +
00444         m_afEntry[5]*rkM.m_afEntry[6],
00445 
00446         m_afEntry[3]*rkM.m_afEntry[1] +
00447         m_afEntry[4]*rkM.m_afEntry[4] +
00448         m_afEntry[5]*rkM.m_afEntry[7],
00449 
00450         m_afEntry[3]*rkM.m_afEntry[2] +
00451         m_afEntry[4]*rkM.m_afEntry[5] +
00452         m_afEntry[5]*rkM.m_afEntry[8],
00453 
00454         m_afEntry[6]*rkM.m_afEntry[0] +
00455         m_afEntry[7]*rkM.m_afEntry[3] +
00456         m_afEntry[8]*rkM.m_afEntry[6],
00457 
00458         m_afEntry[6]*rkM.m_afEntry[1] +
00459         m_afEntry[7]*rkM.m_afEntry[4] +
00460         m_afEntry[8]*rkM.m_afEntry[7],
00461 
00462         m_afEntry[6]*rkM.m_afEntry[2] +
00463         m_afEntry[7]*rkM.m_afEntry[5] +
00464         m_afEntry[8]*rkM.m_afEntry[8]);
00465 }
00466 //----------------------------------------------------------------------------
00467 template <class Real>
00468 Matrix3<Real> Matrix3<Real>::operator* (Real fScalar) const
00469 {
00470     return Matrix3<Real>(
00471         fScalar*m_afEntry[0],
00472         fScalar*m_afEntry[1],
00473         fScalar*m_afEntry[2],
00474         fScalar*m_afEntry[3],
00475         fScalar*m_afEntry[4],
00476         fScalar*m_afEntry[5],
00477         fScalar*m_afEntry[6],
00478         fScalar*m_afEntry[7],
00479         fScalar*m_afEntry[8]);
00480 }
00481 //----------------------------------------------------------------------------
00482 template <class Real>
00483 Matrix3<Real> Matrix3<Real>::operator/ (Real fScalar) const
00484 {
00485     if (fScalar != (Real)0.0)
00486     {
00487         Real fInvScalar = ((Real)1.0)/fScalar;
00488         return Matrix3<Real>(
00489             fInvScalar*m_afEntry[0],
00490             fInvScalar*m_afEntry[1],
00491             fInvScalar*m_afEntry[2],
00492             fInvScalar*m_afEntry[3],
00493             fInvScalar*m_afEntry[4],
00494             fInvScalar*m_afEntry[5],
00495             fInvScalar*m_afEntry[6],
00496             fInvScalar*m_afEntry[7],
00497             fInvScalar*m_afEntry[8]);
00498     }
00499 
00500     return Matrix3<Real>(
00501         Math<Real>::MAX_REAL,
00502         Math<Real>::MAX_REAL,
00503         Math<Real>::MAX_REAL,
00504         Math<Real>::MAX_REAL,
00505         Math<Real>::MAX_REAL,
00506         Math<Real>::MAX_REAL,
00507         Math<Real>::MAX_REAL,
00508         Math<Real>::MAX_REAL,
00509         Math<Real>::MAX_REAL);
00510 }
00511 //----------------------------------------------------------------------------
00512 template <class Real>
00513 Matrix3<Real> Matrix3<Real>::operator- () const
00514 {
00515     return Matrix3<Real>(
00516         -m_afEntry[0],
00517         -m_afEntry[1],
00518         -m_afEntry[2],
00519         -m_afEntry[3],
00520         -m_afEntry[4],
00521         -m_afEntry[5],
00522         -m_afEntry[6],
00523         -m_afEntry[7],
00524         -m_afEntry[8]);
00525 }
00526 //----------------------------------------------------------------------------
00527 template <class Real>
00528 Matrix3<Real>& Matrix3<Real>::operator+= (const Matrix3& rkM)
00529 {
00530     m_afEntry[0] += rkM.m_afEntry[0];
00531     m_afEntry[1] += rkM.m_afEntry[1];
00532     m_afEntry[2] += rkM.m_afEntry[2];
00533     m_afEntry[3] += rkM.m_afEntry[3];
00534     m_afEntry[4] += rkM.m_afEntry[4];
00535     m_afEntry[5] += rkM.m_afEntry[5];
00536     m_afEntry[6] += rkM.m_afEntry[6];
00537     m_afEntry[7] += rkM.m_afEntry[7];
00538     m_afEntry[8] += rkM.m_afEntry[8];
00539     return *this;
00540 }
00541 //----------------------------------------------------------------------------
00542 template <class Real>
00543 Matrix3<Real>& Matrix3<Real>::operator-= (const Matrix3& rkM)
00544 {
00545     m_afEntry[0] -= rkM.m_afEntry[0];
00546     m_afEntry[1] -= rkM.m_afEntry[1];
00547     m_afEntry[2] -= rkM.m_afEntry[2];
00548     m_afEntry[3] -= rkM.m_afEntry[3];
00549     m_afEntry[4] -= rkM.m_afEntry[4];
00550     m_afEntry[5] -= rkM.m_afEntry[5];
00551     m_afEntry[6] -= rkM.m_afEntry[6];
00552     m_afEntry[7] -= rkM.m_afEntry[7];
00553     m_afEntry[8] -= rkM.m_afEntry[8];
00554     return *this;
00555 }
00556 //----------------------------------------------------------------------------
00557 template <class Real>
00558 Matrix3<Real>& Matrix3<Real>::operator*= (Real fScalar)
00559 {
00560     m_afEntry[0] *= fScalar;
00561     m_afEntry[1] *= fScalar;
00562     m_afEntry[2] *= fScalar;
00563     m_afEntry[3] *= fScalar;
00564     m_afEntry[4] *= fScalar;
00565     m_afEntry[5] *= fScalar;
00566     m_afEntry[6] *= fScalar;
00567     m_afEntry[7] *= fScalar;
00568     m_afEntry[8] *= fScalar;
00569     return *this;
00570 }
00571 //----------------------------------------------------------------------------
00572 template <class Real>
00573 Matrix3<Real>& Matrix3<Real>::operator/= (Real fScalar)
00574 {
00575     if (fScalar != (Real)0.0)
00576     {
00577         Real fInvScalar = ((Real)1.0)/fScalar;
00578         m_afEntry[0] *= fInvScalar;
00579         m_afEntry[1] *= fInvScalar;
00580         m_afEntry[2] *= fInvScalar;
00581         m_afEntry[3] *= fInvScalar;
00582         m_afEntry[4] *= fInvScalar;
00583         m_afEntry[5] *= fInvScalar;
00584         m_afEntry[6] *= fInvScalar;
00585         m_afEntry[7] *= fInvScalar;
00586         m_afEntry[8] *= fInvScalar;
00587     }
00588     else
00589     {
00590         m_afEntry[0] = Math<Real>::MAX_REAL;
00591         m_afEntry[1] = Math<Real>::MAX_REAL;
00592         m_afEntry[2] = Math<Real>::MAX_REAL;
00593         m_afEntry[3] = Math<Real>::MAX_REAL;
00594         m_afEntry[4] = Math<Real>::MAX_REAL;
00595         m_afEntry[5] = Math<Real>::MAX_REAL;
00596         m_afEntry[6] = Math<Real>::MAX_REAL;
00597         m_afEntry[7] = Math<Real>::MAX_REAL;
00598         m_afEntry[8] = Math<Real>::MAX_REAL;
00599     }
00600 
00601     return *this;
00602 }
00603 //----------------------------------------------------------------------------
00604 template <class Real>
00605 Vector3<Real> Matrix3<Real>::operator* (const Vector3<Real>& rkV) const
00606 {
00607     return Vector3<Real>(
00608         m_afEntry[0]*rkV[0] + m_afEntry[1]*rkV[1] + m_afEntry[2]*rkV[2],
00609         m_afEntry[3]*rkV[0] + m_afEntry[4]*rkV[1] + m_afEntry[5]*rkV[2],
00610         m_afEntry[6]*rkV[0] + m_afEntry[7]*rkV[1] + m_afEntry[8]*rkV[2]);
00611 }
00612 //----------------------------------------------------------------------------
00613 template <class Real>
00614 Matrix3<Real> Matrix3<Real>::Transpose () const
00615 {
00616     return Matrix3<Real>(
00617         m_afEntry[0],
00618         m_afEntry[3],
00619         m_afEntry[6],
00620         m_afEntry[1],
00621         m_afEntry[4],
00622         m_afEntry[7],
00623         m_afEntry[2],
00624         m_afEntry[5],
00625         m_afEntry[8]);
00626 }
00627 //----------------------------------------------------------------------------
00628 template <class Real>
00629 Matrix3<Real> Matrix3<Real>::TransposeTimes (const Matrix3& rkM) const
00630 {
00631     // P = A^T*B
00632     return Matrix3<Real>(
00633         m_afEntry[0]*rkM.m_afEntry[0] +
00634         m_afEntry[3]*rkM.m_afEntry[3] +
00635         m_afEntry[6]*rkM.m_afEntry[6],
00636 
00637         m_afEntry[0]*rkM.m_afEntry[1] +
00638         m_afEntry[3]*rkM.m_afEntry[4] +
00639         m_afEntry[6]*rkM.m_afEntry[7],
00640 
00641         m_afEntry[0]*rkM.m_afEntry[2] +
00642         m_afEntry[3]*rkM.m_afEntry[5] +
00643         m_afEntry[6]*rkM.m_afEntry[8],
00644 
00645         m_afEntry[1]*rkM.m_afEntry[0] +
00646         m_afEntry[4]*rkM.m_afEntry[3] +
00647         m_afEntry[7]*rkM.m_afEntry[6],
00648 
00649         m_afEntry[1]*rkM.m_afEntry[1] +
00650         m_afEntry[4]*rkM.m_afEntry[4] +
00651         m_afEntry[7]*rkM.m_afEntry[7],
00652 
00653         m_afEntry[1]*rkM.m_afEntry[2] +
00654         m_afEntry[4]*rkM.m_afEntry[5] +
00655         m_afEntry[7]*rkM.m_afEntry[8],
00656 
00657         m_afEntry[2]*rkM.m_afEntry[0] +
00658         m_afEntry[5]*rkM.m_afEntry[3] +
00659         m_afEntry[8]*rkM.m_afEntry[6],
00660 
00661         m_afEntry[2]*rkM.m_afEntry[1] +
00662         m_afEntry[5]*rkM.m_afEntry[4] +
00663         m_afEntry[8]*rkM.m_afEntry[7],
00664 
00665         m_afEntry[2]*rkM.m_afEntry[2] +
00666         m_afEntry[5]*rkM.m_afEntry[5] +
00667         m_afEntry[8]*rkM.m_afEntry[8]);
00668 }
00669 //----------------------------------------------------------------------------
00670 template <class Real>
00671 Matrix3<Real> Matrix3<Real>::TimesTranspose (const Matrix3& rkM) const
00672 {
00673     // P = A*B^T
00674     return Matrix3<Real>(
00675         m_afEntry[0]*rkM.m_afEntry[0] +
00676         m_afEntry[1]*rkM.m_afEntry[1] +
00677         m_afEntry[2]*rkM.m_afEntry[2],
00678 
00679         m_afEntry[0]*rkM.m_afEntry[3] +
00680         m_afEntry[1]*rkM.m_afEntry[4] +
00681         m_afEntry[2]*rkM.m_afEntry[5],
00682 
00683         m_afEntry[0]*rkM.m_afEntry[6] +
00684         m_afEntry[1]*rkM.m_afEntry[7] +
00685         m_afEntry[2]*rkM.m_afEntry[8],
00686 
00687         m_afEntry[3]*rkM.m_afEntry[0] +
00688         m_afEntry[4]*rkM.m_afEntry[1] +
00689         m_afEntry[5]*rkM.m_afEntry[2],
00690 
00691         m_afEntry[3]*rkM.m_afEntry[3] +
00692         m_afEntry[4]*rkM.m_afEntry[4] +
00693         m_afEntry[5]*rkM.m_afEntry[5],
00694 
00695         m_afEntry[3]*rkM.m_afEntry[6] +
00696         m_afEntry[4]*rkM.m_afEntry[7] +
00697         m_afEntry[5]*rkM.m_afEntry[8],
00698 
00699         m_afEntry[6]*rkM.m_afEntry[0] +
00700         m_afEntry[7]*rkM.m_afEntry[1] +
00701         m_afEntry[8]*rkM.m_afEntry[2],
00702 
00703         m_afEntry[6]*rkM.m_afEntry[3] +
00704         m_afEntry[7]*rkM.m_afEntry[4] +
00705         m_afEntry[8]*rkM.m_afEntry[5],
00706 
00707         m_afEntry[6]*rkM.m_afEntry[6] +
00708         m_afEntry[7]*rkM.m_afEntry[7] +
00709         m_afEntry[8]*rkM.m_afEntry[8]);
00710 }
00711 //----------------------------------------------------------------------------
00712 template <class Real>
00713 Matrix3<Real> Matrix3<Real>::Inverse () const
00714 {
00715     // Invert a 3x3 using cofactors.  This is faster than using a generic
00716     // Gaussian elimination because of the loop overhead of such a method.
00717 
00718     Matrix3 kInverse;
00719 
00720     kInverse.m_afEntry[0] =
00721         m_afEntry[4]*m_afEntry[8] - m_afEntry[5]*m_afEntry[7];
00722     kInverse.m_afEntry[1] =
00723         m_afEntry[2]*m_afEntry[7] - m_afEntry[1]*m_afEntry[8];
00724     kInverse.m_afEntry[2] =
00725         m_afEntry[1]*m_afEntry[5] - m_afEntry[2]*m_afEntry[4];
00726     kInverse.m_afEntry[3] =
00727         m_afEntry[5]*m_afEntry[6] - m_afEntry[3]*m_afEntry[8];
00728     kInverse.m_afEntry[4] =
00729         m_afEntry[0]*m_afEntry[8] - m_afEntry[2]*m_afEntry[6];
00730     kInverse.m_afEntry[5] =
00731         m_afEntry[2]*m_afEntry[3] - m_afEntry[0]*m_afEntry[5];
00732     kInverse.m_afEntry[6] =
00733         m_afEntry[3]*m_afEntry[7] - m_afEntry[4]*m_afEntry[6];
00734     kInverse.m_afEntry[7] =
00735         m_afEntry[1]*m_afEntry[6] - m_afEntry[0]*m_afEntry[7];
00736     kInverse.m_afEntry[8] =
00737         m_afEntry[0]*m_afEntry[4] - m_afEntry[1]*m_afEntry[3];
00738 
00739     Real fDet =
00740         m_afEntry[0]*kInverse.m_afEntry[0] +
00741         m_afEntry[1]*kInverse.m_afEntry[3] +
00742         m_afEntry[2]*kInverse.m_afEntry[6];
00743 
00744     if (Math<Real>::FAbs(fDet) <= Math<Real>::ZERO_TOLERANCE)
00745     {
00746         return ZERO;
00747     }
00748 
00749     Real fInvDet = ((Real)1.0)/fDet;
00750     kInverse.m_afEntry[0] *= fInvDet;
00751     kInverse.m_afEntry[1] *= fInvDet;
00752     kInverse.m_afEntry[2] *= fInvDet;
00753     kInverse.m_afEntry[3] *= fInvDet;
00754     kInverse.m_afEntry[4] *= fInvDet;
00755     kInverse.m_afEntry[5] *= fInvDet;
00756     kInverse.m_afEntry[6] *= fInvDet;
00757     kInverse.m_afEntry[7] *= fInvDet;
00758     kInverse.m_afEntry[8] *= fInvDet;
00759     return kInverse;
00760 }
00761 //----------------------------------------------------------------------------
00762 template <class Real>
00763 Matrix3<Real> Matrix3<Real>::Adjoint () const
00764 {
00765     return Matrix3<Real>(
00766         m_afEntry[4]*m_afEntry[8] - m_afEntry[5]*m_afEntry[7],
00767         m_afEntry[2]*m_afEntry[7] - m_afEntry[1]*m_afEntry[8],
00768         m_afEntry[1]*m_afEntry[5] - m_afEntry[2]*m_afEntry[4],
00769         m_afEntry[5]*m_afEntry[6] - m_afEntry[3]*m_afEntry[8],
00770         m_afEntry[0]*m_afEntry[8] - m_afEntry[2]*m_afEntry[6],
00771         m_afEntry[2]*m_afEntry[3] - m_afEntry[0]*m_afEntry[5],
00772         m_afEntry[3]*m_afEntry[7] - m_afEntry[4]*m_afEntry[6],
00773         m_afEntry[1]*m_afEntry[6] - m_afEntry[0]*m_afEntry[7],
00774         m_afEntry[0]*m_afEntry[4] - m_afEntry[1]*m_afEntry[3]);
00775 }
00776 //----------------------------------------------------------------------------
00777 template <class Real>
00778 Real Matrix3<Real>::Determinant () const
00779 {
00780     Real fCo00 = m_afEntry[4]*m_afEntry[8] - m_afEntry[5]*m_afEntry[7];
00781     Real fCo10 = m_afEntry[5]*m_afEntry[6] - m_afEntry[3]*m_afEntry[8];
00782     Real fCo20 = m_afEntry[3]*m_afEntry[7] - m_afEntry[4]*m_afEntry[6];
00783     Real fDet = m_afEntry[0]*fCo00 + m_afEntry[1]*fCo10 + m_afEntry[2]*fCo20;
00784     return fDet;
00785 }
00786 //----------------------------------------------------------------------------
00787 template <class Real>
00788 Real Matrix3<Real>::QForm (const Vector3<Real>& rkU, const Vector3<Real>& rkV)
00789     const
00790 {
00791     return rkU.Dot((*this)*rkV);
00792 }
00793 //----------------------------------------------------------------------------
00794 template <class Real>
00795 Matrix3<Real> Matrix3<Real>::TimesDiagonal (const Vector3<Real>& rkDiag) const
00796 {
00797     return Matrix3<Real>(
00798         m_afEntry[0]*rkDiag[0],m_afEntry[1]*rkDiag[1],m_afEntry[2]*rkDiag[2],
00799         m_afEntry[3]*rkDiag[0],m_afEntry[4]*rkDiag[1],m_afEntry[5]*rkDiag[2],
00800         m_afEntry[6]*rkDiag[0],m_afEntry[7]*rkDiag[1],m_afEntry[8]*rkDiag[2]);
00801 }
00802 //----------------------------------------------------------------------------
00803 template <class Real>
00804 Matrix3<Real> Matrix3<Real>::DiagonalTimes (const Vector3<Real>& rkDiag) const
00805 {
00806     return Matrix3<Real>(
00807         rkDiag[0]*m_afEntry[0],rkDiag[0]*m_afEntry[1],rkDiag[0]*m_afEntry[2],
00808         rkDiag[1]*m_afEntry[3],rkDiag[1]*m_afEntry[4],rkDiag[1]*m_afEntry[5],
00809         rkDiag[2]*m_afEntry[6],rkDiag[2]*m_afEntry[7],rkDiag[2]*m_afEntry[8]);
00810 }
00811 //----------------------------------------------------------------------------
00812 template <class Real>
00813 void Matrix3<Real>::ToAxisAngle (Vector3<Real>& rkAxis, Real& rfAngle) const
00814 {
00815     // Let (x,y,z) be the unit-length axis and let A be an angle of rotation.
00816     // The rotation matrix is R = I + sin(A)*P + (1-cos(A))*P^2 where
00817     // I is the identity and
00818     //
00819     //       +-        -+
00820     //   P = |  0 -z +y |
00821     //       | +z  0 -x |
00822     //       | -y +x  0 |
00823     //       +-        -+
00824     //
00825     // If A > 0, R represents a counterclockwise rotation about the axis in
00826     // the sense of looking from the tip of the axis vector towards the
00827     // origin.  Some algebra will show that
00828     //
00829     //   cos(A) = (trace(R)-1)/2  and  R - R^t = 2*sin(A)*P
00830     //
00831     // In the event that A = pi, R-R^t = 0 which prevents us from extracting
00832     // the axis through P.  Instead note that R = I+2*P^2 when A = pi, so
00833     // P^2 = (R-I)/2.  The diagonal entries of P^2 are x^2-1, y^2-1, and
00834     // z^2-1.  We can solve these for axis (x,y,z).  Because the angle is pi,
00835     // it does not matter which sign you choose on the square roots.
00836 
00837     Real fTrace = m_afEntry[0] + m_afEntry[4] + m_afEntry[8];
00838     Real fCos = ((Real)0.5)*(fTrace-(Real)1.0);
00839     rfAngle = Math<Real>::ACos(fCos);  // in [0,PI]
00840 
00841     if (rfAngle > (Real)0.0)
00842     {
00843         if (rfAngle < Math<Real>::PI)
00844         {
00845             rkAxis[0] = m_afEntry[7]-m_afEntry[5];
00846             rkAxis[1] = m_afEntry[2]-m_afEntry[6];
00847             rkAxis[2] = m_afEntry[3]-m_afEntry[1];
00848             rkAxis.Normalize();
00849         }
00850         else
00851         {
00852             // angle is PI
00853             Real fHalfInverse;
00854             if (m_afEntry[0] >= m_afEntry[4])
00855             {
00856                 // r00 >= r11
00857                 if (m_afEntry[0] >= m_afEntry[8])
00858                 {
00859                     // r00 is maximum diagonal term
00860                     rkAxis[0] = ((Real)0.5)*Math<Real>::Sqrt(m_afEntry[0] -
00861                         m_afEntry[4] - m_afEntry[8] + (Real)1.0);
00862                     fHalfInverse = ((Real)0.5)/rkAxis[0];
00863                     rkAxis[1] = fHalfInverse*m_afEntry[1];
00864                     rkAxis[2] = fHalfInverse*m_afEntry[2];
00865                 }
00866                 else
00867                 {
00868                     // r22 is maximum diagonal term
00869                     rkAxis[2] = ((Real)0.5)*Math<Real>::Sqrt(m_afEntry[8] -
00870                         m_afEntry[0] - m_afEntry[4] + (Real)1.0);
00871                     fHalfInverse = ((Real)0.5)/rkAxis[2];
00872                     rkAxis[0] = fHalfInverse*m_afEntry[2];
00873                     rkAxis[1] = fHalfInverse*m_afEntry[5];
00874                 }
00875             }
00876             else
00877             {
00878                 // r11 > r00
00879                 if (m_afEntry[4] >= m_afEntry[8])
00880                 {
00881                     // r11 is maximum diagonal term
00882                     rkAxis[1] = ((Real)0.5)*Math<Real>::Sqrt(m_afEntry[4] -
00883                         m_afEntry[0] - m_afEntry[8] + (Real)1.0);
00884                     fHalfInverse  = ((Real)0.5)/rkAxis[1];
00885                     rkAxis[0] = fHalfInverse*m_afEntry[1];
00886                     rkAxis[2] = fHalfInverse*m_afEntry[5];
00887                 }
00888                 else
00889                 {
00890                     // r22 is maximum diagonal term
00891                     rkAxis[2] = ((Real)0.5)*Math<Real>::Sqrt(m_afEntry[8] -
00892                         m_afEntry[0] - m_afEntry[4] + (Real)1.0);
00893                     fHalfInverse = ((Real)0.5)/rkAxis[2];
00894                     rkAxis[0] = fHalfInverse*m_afEntry[2];
00895                     rkAxis[1] = fHalfInverse*m_afEntry[5];
00896                 }
00897             }
00898         }
00899     }
00900     else
00901     {
00902         // The angle is 0 and the matrix is the identity.  Any axis will
00903         // work, so just use the x-axis.
00904         rkAxis[0] = (Real)1.0;
00905         rkAxis[1] = (Real)0.0;
00906         rkAxis[2] = (Real)0.0;
00907     }
00908 }
00909 //----------------------------------------------------------------------------
00910 template <class Real>
00911 void Matrix3<Real>::Orthonormalize ()
00912 {
00913     // Algorithm uses Gram-Schmidt orthogonalization.  If 'this' matrix is
00914     // M = [m0|m1|m2], then orthonormal output matrix is Q = [q0|q1|q2],
00915     //
00916     //   q0 = m0/|m0|
00917     //   q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0|
00918     //   q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1|
00919     //
00920     // where |V| indicates length of vector V and A*B indicates dot
00921     // product of vectors A and B.
00922 
00923     // compute q0
00924     Real fInvLength = Math<Real>::InvSqrt(m_afEntry[0]*m_afEntry[0] +
00925         m_afEntry[3]*m_afEntry[3] + m_afEntry[6]*m_afEntry[6]);
00926 
00927     m_afEntry[0] *= fInvLength;
00928     m_afEntry[3] *= fInvLength;
00929     m_afEntry[6] *= fInvLength;
00930 
00931     // compute q1
00932     Real fDot0 = m_afEntry[0]*m_afEntry[1] + m_afEntry[3]*m_afEntry[4] +
00933         m_afEntry[6]*m_afEntry[7];
00934 
00935     m_afEntry[1] -= fDot0*m_afEntry[0];
00936     m_afEntry[4] -= fDot0*m_afEntry[3];
00937     m_afEntry[7] -= fDot0*m_afEntry[6];
00938 
00939     fInvLength = Math<Real>::InvSqrt(m_afEntry[1]*m_afEntry[1] +
00940         m_afEntry[4]*m_afEntry[4] + m_afEntry[7]*m_afEntry[7]);
00941 
00942     m_afEntry[1] *= fInvLength;
00943     m_afEntry[4] *= fInvLength;
00944     m_afEntry[7] *= fInvLength;
00945 
00946     // compute q2
00947     Real fDot1 = m_afEntry[1]*m_afEntry[2] + m_afEntry[4]*m_afEntry[5] +
00948         m_afEntry[7]*m_afEntry[8];
00949 
00950     fDot0 = m_afEntry[0]*m_afEntry[2] + m_afEntry[3]*m_afEntry[5] +
00951         m_afEntry[6]*m_afEntry[8];
00952 
00953     m_afEntry[2] -= fDot0*m_afEntry[0] + fDot1*m_afEntry[1];
00954     m_afEntry[5] -= fDot0*m_afEntry[3] + fDot1*m_afEntry[4];
00955     m_afEntry[8] -= fDot0*m_afEntry[6] + fDot1*m_afEntry[7];
00956 
00957     fInvLength = Math<Real>::InvSqrt(m_afEntry[2]*m_afEntry[2] +
00958         m_afEntry[5]*m_afEntry[5] + m_afEntry[8]*m_afEntry[8]);
00959 
00960     m_afEntry[2] *= fInvLength;
00961     m_afEntry[5] *= fInvLength;
00962     m_afEntry[8] *= fInvLength;
00963 }
00964 //----------------------------------------------------------------------------
00965 template <class Real>
00966 void Matrix3<Real>::EigenDecomposition (Matrix3& rkRot, Matrix3& rkDiag) const
00967 {
00968     // Factor M = R*D*R^T.  The columns of R are the eigenvectors.  The
00969     // diagonal entries of D are the corresponding eigenvalues.
00970     Real afDiag[3], afSubd[2];
00971     rkRot = *this;
00972     bool bReflection = rkRot.Tridiagonalize(afDiag,afSubd);
00973     bool bConverged = rkRot.QLAlgorithm(afDiag,afSubd);
00974     if (!bConverged) throw std::exception();
00975     assert(bConverged);
00976 
00977     // (insertion) sort eigenvalues in increasing order, d0 <= d1 <= d2
00978     int i;
00979     Real fSave;
00980 
00981     if (afDiag[1] < afDiag[0])
00982     {
00983         // swap d0 and d1
00984         fSave = afDiag[0];
00985         afDiag[0] = afDiag[1];
00986         afDiag[1] = fSave;
00987 
00988         // swap V0 and V1
00989         for (i = 0; i < 3; i++)
00990         {
00991             fSave = rkRot[i][0];
00992             rkRot[i][0] = rkRot[i][1];
00993             rkRot[i][1] = fSave;
00994         }
00995         bReflection = !bReflection;
00996     }
00997 
00998     if (afDiag[2] < afDiag[1])
00999     {
01000         // swap d1 and d2
01001         fSave = afDiag[1];
01002         afDiag[1] = afDiag[2];
01003         afDiag[2] = fSave;
01004 
01005         // swap V1 and V2
01006         for (i = 0; i < 3; i++)
01007         {
01008             fSave = rkRot[i][1];
01009             rkRot[i][1] = rkRot[i][2];
01010             rkRot[i][2] = fSave;
01011         }
01012         bReflection = !bReflection;
01013     }
01014 
01015     if (afDiag[1] < afDiag[0])
01016     {
01017         // swap d0 and d1
01018         fSave = afDiag[0];
01019         afDiag[0] = afDiag[1];
01020         afDiag[1] = fSave;
01021 
01022         // swap V0 and V1
01023         for (i = 0; i < 3; i++)
01024         {
01025             fSave = rkRot[i][0];
01026             rkRot[i][0] = rkRot[i][1];
01027             rkRot[i][1] = fSave;
01028         }
01029         bReflection = !bReflection;
01030     }
01031 
01032     rkDiag.MakeDiagonal(afDiag[0],afDiag[1],afDiag[2]);
01033 
01034     if (bReflection)
01035     {
01036         // The orthogonal transformation that diagonalizes M is a reflection.
01037         // Make the eigenvectors a right--handed system by changing sign on
01038         // the last column.
01039         rkRot[0][2] = -rkRot[0][2];
01040         rkRot[1][2] = -rkRot[1][2];
01041         rkRot[2][2] = -rkRot[2][2];
01042     }
01043 }
01044 //----------------------------------------------------------------------------
01045 template <class Real>
01046 Matrix3<Real>& Matrix3<Real>::FromEulerAnglesXYZ (Real fXAngle, Real fYAngle,
01047     Real fZAngle)
01048 {
01049     Real fCos, fSin;
01050 
01051     fCos = Math<Real>::Cos(fXAngle);
01052     fSin = Math<Real>::Sin(fXAngle);
01053     Matrix3 kXMat(
01054         (Real)1.0,(Real)0.0,(Real)0.0,
01055         (Real)0.0,fCos,-fSin,
01056         (Real)0.0,fSin,fCos);
01057 
01058     fCos = Math<Real>::Cos(fYAngle);
01059     fSin = Math<Real>::Sin(fYAngle);
01060     Matrix3 kYMat(
01061         fCos,(Real)0.0,fSin,
01062         (Real)0.0,(Real)1.0,(Real)0.0,
01063         -fSin,(Real)0.0,fCos);
01064 
01065     fCos = Math<Real>::Cos(fZAngle);
01066     fSin = Math<Real>::Sin(fZAngle);
01067     Matrix3 kZMat(
01068         fCos,-fSin,(Real)0.0,
01069         fSin,fCos,(Real)0.0,
01070         (Real)0.0,(Real)0.0,(Real)1.0);
01071 
01072     *this = kXMat*(kYMat*kZMat);
01073     return *this;
01074 }
01075 //----------------------------------------------------------------------------
01076 template <class Real>
01077 Matrix3<Real>& Matrix3<Real>::FromEulerAnglesXZY (Real fXAngle, Real fZAngle,
01078     Real fYAngle)
01079 {
01080     Real fCos, fSin;
01081 
01082     fCos = Math<Real>::Cos(fXAngle);
01083     fSin = Math<Real>::Sin(fXAngle);
01084     Matrix3 kXMat(
01085         (Real)1.0,(Real)0.0,(Real)0.0,
01086         (Real)0.0,fCos,-fSin,
01087         (Real)0.0,fSin,fCos);
01088 
01089     fCos = Math<Real>::Cos(fZAngle);
01090     fSin = Math<Real>::Sin(fZAngle);
01091     Matrix3 kZMat(
01092         fCos,-fSin,(Real)0.0,
01093         fSin,fCos,(Real)0.0,
01094         (Real)0.0,(Real)0.0,(Real)1.0);
01095 
01096     fCos = Math<Real>::Cos(fYAngle);
01097     fSin = Math<Real>::Sin(fYAngle);
01098     Matrix3 kYMat(
01099         fCos,(Real)0.0,fSin,
01100         (Real)0.0,(Real)1.0,(Real)0.0,
01101         -fSin,(Real)0.0,fCos);
01102 
01103     *this = kXMat*(kZMat*kYMat);
01104     return *this;
01105 }
01106 //----------------------------------------------------------------------------
01107 template <class Real>
01108 Matrix3<Real>& Matrix3<Real>::FromEulerAnglesYXZ (Real fYAngle, Real fXAngle,
01109     Real fZAngle)
01110 {
01111     Real fCos, fSin;
01112 
01113     fCos = Math<Real>::Cos(fYAngle);
01114     fSin = Math<Real>::Sin(fYAngle);
01115     Matrix3 kYMat(
01116         fCos,(Real)0.0,fSin,
01117         (Real)0.0,(Real)1.0,(Real)0.0,
01118         -fSin,(Real)0.0,fCos);
01119 
01120     fCos = Math<Real>::Cos(fXAngle);
01121     fSin = Math<Real>::Sin(fXAngle);
01122     Matrix3 kXMat(
01123         (Real)1.0,(Real)0.0,(Real)0.0,
01124         (Real)0.0,fCos,-fSin,
01125         (Real)0.0,fSin,fCos);
01126 
01127     fCos = Math<Real>::Cos(fZAngle);
01128     fSin = Math<Real>::Sin(fZAngle);
01129     Matrix3 kZMat(
01130         fCos,-fSin,(Real)0.0,
01131         fSin,fCos,(Real)0.0,
01132         (Real)0.0,(Real)0.0,(Real)1.0);
01133 
01134     *this = kYMat*(kXMat*kZMat);
01135     return *this;
01136 }
01137 //----------------------------------------------------------------------------
01138 template <class Real>
01139 Matrix3<Real>& Matrix3<Real>::FromEulerAnglesYZX (Real fYAngle, Real fZAngle,
01140     Real fXAngle)
01141 {
01142     Real fCos, fSin;
01143 
01144     fCos = Math<Real>::Cos(fYAngle);
01145     fSin = Math<Real>::Sin(fYAngle);
01146     Matrix3 kYMat(
01147         fCos,(Real)0.0,fSin,
01148         (Real)0.0,(Real)1.0,(Real)0.0,
01149         -fSin,(Real)0.0,fCos);
01150 
01151     fCos = Math<Real>::Cos(fZAngle);
01152     fSin = Math<Real>::Sin(fZAngle);
01153     Matrix3 kZMat(
01154         fCos,-fSin,(Real)0.0,
01155         fSin,fCos,(Real)0.0,
01156         (Real)0.0,(Real)0.0,(Real)1.0);
01157 
01158     fCos = Math<Real>::Cos(fXAngle);
01159     fSin = Math<Real>::Sin(fXAngle);
01160     Matrix3 kXMat(
01161         (Real)1.0,(Real)0.0,(Real)0.0,
01162         (Real)0.0,fCos,-fSin,
01163         (Real)0.0,fSin,fCos);
01164 
01165     *this = kYMat*(kZMat*kXMat);
01166     return *this;
01167 }
01168 //----------------------------------------------------------------------------
01169 template <class Real>
01170 Matrix3<Real>& Matrix3<Real>::FromEulerAnglesZXY (Real fZAngle, Real fXAngle,
01171     Real fYAngle)
01172 {
01173     Real fCos, fSin;
01174 
01175     fCos = Math<Real>::Cos(fZAngle);
01176     fSin = Math<Real>::Sin(fZAngle);
01177     Matrix3 kZMat(
01178         fCos,-fSin,(Real)0.0,
01179         fSin,fCos,(Real)0.0,
01180         (Real)0.0,(Real)0.0,(Real)1.0);
01181 
01182     fCos = Math<Real>::Cos(fXAngle);
01183     fSin = Math<Real>::Sin(fXAngle);
01184     Matrix3 kXMat(
01185         (Real)1.0,(Real)0.0,(Real)0.0,
01186         (Real)0.0,fCos,-fSin,
01187         (Real)0.0,fSin,fCos);
01188 
01189     fCos = Math<Real>::Cos(fYAngle);
01190     fSin = Math<Real>::Sin(fYAngle);
01191     Matrix3 kYMat(
01192         fCos,(Real)0.0,fSin,
01193         (Real)0.0,(Real)1.0,(Real)0.0,
01194         -fSin,(Real)0.0,fCos);
01195 
01196     *this = kZMat*(kXMat*kYMat);
01197     return *this;
01198 }
01199 //----------------------------------------------------------------------------
01200 template <class Real>
01201 Matrix3<Real>& Matrix3<Real>::FromEulerAnglesZYX (Real fZAngle, Real fYAngle,
01202     Real fXAngle)
01203 {
01204     Real fCos, fSin;
01205 
01206     fCos = Math<Real>::Cos(fZAngle);
01207     fSin = Math<Real>::Sin(fZAngle);
01208     Matrix3 kZMat(
01209         fCos,-fSin,(Real)0.0,
01210         fSin,fCos,(Real)0.0,
01211         (Real)0.0,(Real)0.0,(Real)1.0);
01212 
01213     fCos = Math<Real>::Cos(fYAngle);
01214     fSin = Math<Real>::Sin(fYAngle);
01215     Matrix3 kYMat(
01216         fCos,(Real)0.0,fSin,
01217         (Real)0.0,(Real)1.0,(Real)0.0,
01218         -fSin,(Real)0.0,fCos);
01219 
01220     fCos = Math<Real>::Cos(fXAngle);
01221     fSin = Math<Real>::Sin(fXAngle);
01222     Matrix3 kXMat(
01223         (Real)1.0,(Real)0.0,(Real)0.0,
01224         (Real)0.0,fCos,-fSin,
01225         (Real)0.0,fSin,fCos);
01226 
01227     *this = kZMat*(kYMat*kXMat);
01228     return *this;
01229 }
01230 //----------------------------------------------------------------------------
01231 template <class Real>
01232 bool Matrix3<Real>::ToEulerAnglesXYZ (Real& rfXAngle, Real& rfYAngle,
01233     Real& rfZAngle) const
01234 {
01235     // rot =  cy*cz          -cy*sz           sy
01236     //        cz*sx*sy+cx*sz  cx*cz-sx*sy*sz -cy*sx
01237     //       -cx*cz*sy+sx*sz  cz*sx+cx*sy*sz  cx*cy
01238 
01239     if (m_afEntry[2] < (Real)1.0)
01240     {
01241         if (m_afEntry[2] > -(Real)1.0)
01242         {
01243             rfXAngle = Math<Real>::ATan2(-m_afEntry[5],m_afEntry[8]);
01244             rfYAngle = (Real)asin((double)m_afEntry[2]);
01245             rfZAngle = Math<Real>::ATan2(-m_afEntry[1],m_afEntry[0]);
01246             return true;
01247         }
01248         else
01249         {
01250             // WARNING.  Not unique.  XA - ZA = -atan2(r10,r11)
01251             rfXAngle = -Math<Real>::ATan2(m_afEntry[3],m_afEntry[4]);
01252             rfYAngle = -Math<Real>::HALF_PI;
01253             rfZAngle = (Real)0.0;
01254             return false;
01255         }
01256     }
01257     else
01258     {
01259         // WARNING.  Not unique.  XAngle + ZAngle = atan2(r10,r11)
01260         rfXAngle = Math<Real>::ATan2(m_afEntry[3],m_afEntry[4]);
01261         rfYAngle = Math<Real>::HALF_PI;
01262         rfZAngle = (Real)0.0;
01263         return false;
01264     }
01265 }
01266 //----------------------------------------------------------------------------
01267 template <class Real>
01268 bool Matrix3<Real>::ToEulerAnglesXZY (Real& rfXAngle, Real& rfZAngle,
01269     Real& rfYAngle) const
01270 {
01271     // rot =  cy*cz          -sz              cz*sy
01272     //        sx*sy+cx*cy*sz  cx*cz          -cy*sx+cx*sy*sz
01273     //       -cx*sy+cy*sx*sz  cz*sx           cx*cy+sx*sy*sz
01274 
01275     if (m_afEntry[1] < (Real)1.0)
01276     {
01277         if (m_afEntry[1] > -(Real)1.0)
01278         {
01279             rfXAngle = Math<Real>::ATan2(m_afEntry[7],m_afEntry[4]);
01280             rfZAngle = (Real)asin(-(double)m_afEntry[1]);
01281             rfYAngle = Math<Real>::ATan2(m_afEntry[2],m_afEntry[0]);
01282             return true;
01283         }
01284         else
01285         {
01286             // WARNING.  Not unique.  XA - YA = atan2(r20,r22)
01287             rfXAngle = Math<Real>::ATan2(m_afEntry[6],m_afEntry[8]);
01288             rfZAngle = Math<Real>::HALF_PI;
01289             rfYAngle = (Real)0.0;
01290             return false;
01291         }
01292     }
01293     else
01294     {
01295         // WARNING.  Not unique.  XA + YA = atan2(-r20,r22)
01296         rfXAngle = Math<Real>::ATan2(-m_afEntry[6],m_afEntry[8]);
01297         rfZAngle = -Math<Real>::HALF_PI;
01298         rfYAngle = (Real)0.0;
01299         return false;
01300     }
01301 }
01302 //----------------------------------------------------------------------------
01303 template <class Real>
01304 bool Matrix3<Real>::ToEulerAnglesYXZ (Real& rfYAngle, Real& rfXAngle,
01305     Real& rfZAngle) const
01306 {
01307     // rot =  cy*cz+sx*sy*sz  cz*sx*sy-cy*sz  cx*sy
01308     //        cx*sz           cx*cz          -sx
01309     //       -cz*sy+cy*sx*sz  cy*cz*sx+sy*sz  cx*cy
01310 
01311     if (m_afEntry[5] < (Real)1.0)
01312     {
01313         if (m_afEntry[5] > -(Real)1.0)
01314         {
01315             rfYAngle = Math<Real>::ATan2(m_afEntry[2],m_afEntry[8]);
01316             rfXAngle = (Real)asin(-(double)m_afEntry[5]);
01317             rfZAngle = Math<Real>::ATan2(m_afEntry[3],m_afEntry[4]);
01318             return true;
01319         }
01320         else
01321         {
01322             // WARNING.  Not unique.  YA - ZA = atan2(r01,r00)
01323             rfYAngle = Math<Real>::ATan2(m_afEntry[1],m_afEntry[0]);
01324             rfXAngle = Math<Real>::HALF_PI;
01325             rfZAngle = (Real)0.0;
01326             return false;
01327         }
01328     }
01329     else
01330     {
01331         // WARNING.  Not unique.  YA + ZA = atan2(-r01,r00)
01332         rfYAngle = Math<Real>::ATan2(-m_afEntry[1],m_afEntry[0]);
01333         rfXAngle = -Math<Real>::HALF_PI;
01334         rfZAngle = (Real)0.0;
01335         return false;
01336     }
01337 }
01338 //----------------------------------------------------------------------------
01339 template <class Real>
01340 bool Matrix3<Real>::ToEulerAnglesYZX (Real& rfYAngle, Real& rfZAngle,
01341     Real& rfXAngle) const
01342 {
01343     // rot =  cy*cz           sx*sy-cx*cy*sz  cx*sy+cy*sx*sz
01344     //        sz              cx*cz          -cz*sx
01345     //       -cz*sy           cy*sx+cx*sy*sz  cx*cy-sx*sy*sz
01346 
01347     if (m_afEntry[3] < (Real)1.0)
01348     {
01349         if (m_afEntry[3] > -(Real)1.0)
01350         {
01351             rfYAngle = Math<Real>::ATan2(-m_afEntry[6],m_afEntry[0]);
01352             rfZAngle = (Real)asin((double)m_afEntry[3]);
01353             rfXAngle = Math<Real>::ATan2(-m_afEntry[5],m_afEntry[4]);
01354             return true;
01355         }
01356         else
01357         {
01358             // WARNING.  Not unique.  YA - XA = -atan2(r21,r22);
01359             rfYAngle = -Math<Real>::ATan2(m_afEntry[7],m_afEntry[8]);
01360             rfZAngle = -Math<Real>::HALF_PI;
01361             rfXAngle = (Real)0.0;
01362             return false;
01363         }
01364     }
01365     else
01366     {
01367         // WARNING.  Not unique.  YA + XA = atan2(r21,r22)
01368         rfYAngle = Math<Real>::ATan2(m_afEntry[7],m_afEntry[8]);
01369         rfZAngle = Math<Real>::HALF_PI;
01370         rfXAngle = (Real)0.0;
01371         return false;
01372     }
01373 }
01374 //----------------------------------------------------------------------------
01375 template <class Real>
01376 bool Matrix3<Real>::ToEulerAnglesZXY (Real& rfZAngle, Real& rfXAngle,
01377     Real& rfYAngle) const
01378 {
01379     // rot =  cy*cz-sx*sy*sz -cx*sz           cz*sy+cy*sx*sz
01380     //        cz*sx*sy+cy*sz  cx*cz          -cy*cz*sx+sy*sz
01381     //       -cx*sy           sx              cx*cy
01382 
01383     if (m_afEntry[7] < (Real)1.0)
01384     {
01385         if (m_afEntry[7] > -(Real)1.0)
01386         {
01387             rfZAngle = Math<Real>::ATan2(-m_afEntry[1],m_afEntry[4]);
01388             rfXAngle = (Real)asin((double)m_afEntry[7]);
01389             rfYAngle = Math<Real>::ATan2(-m_afEntry[6],m_afEntry[8]);
01390             return true;
01391         }
01392         else
01393         {
01394             // WARNING.  Not unique.  ZA - YA = -atan(r02,r00)
01395             rfZAngle = -Math<Real>::ATan2(m_afEntry[2],m_afEntry[0]);
01396             rfXAngle = -Math<Real>::HALF_PI;
01397             rfYAngle = (Real)0.0;
01398             return false;
01399         }
01400     }
01401     else
01402     {
01403         // WARNING.  Not unique.  ZA + YA = atan2(r02,r00)
01404         rfZAngle = Math<Real>::ATan2(m_afEntry[2],m_afEntry[0]);
01405         rfXAngle = Math<Real>::HALF_PI;
01406         rfYAngle = (Real)0.0;
01407         return false;
01408     }
01409 }
01410 //----------------------------------------------------------------------------
01411 template <class Real>
01412 bool Matrix3<Real>::ToEulerAnglesZYX (Real& rfZAngle, Real& rfYAngle,
01413     Real& rfXAngle) const
01414 {
01415     // rot =  cy*cz           cz*sx*sy-cx*sz  cx*cz*sy+sx*sz
01416     //        cy*sz           cx*cz+sx*sy*sz -cz*sx+cx*sy*sz
01417     //       -sy              cy*sx           cx*cy
01418 
01419     if (m_afEntry[6] < (Real)1.0)
01420     {
01421         if (m_afEntry[6] > -(Real)1.0)
01422         {
01423             rfZAngle = Math<Real>::ATan2(m_afEntry[3],m_afEntry[0]);
01424             rfYAngle = (Real)asin(-(double)m_afEntry[6]);
01425             rfXAngle = Math<Real>::ATan2(m_afEntry[7],m_afEntry[8]);
01426             return true;
01427         }
01428         else
01429         {
01430             // WARNING.  Not unique.  ZA - XA = -atan2(r01,r02)
01431             rfZAngle = -Math<Real>::ATan2(m_afEntry[1],m_afEntry[2]);
01432             rfYAngle = Math<Real>::HALF_PI;
01433             rfXAngle = (Real)0.0;
01434             return false;
01435         }
01436     }
01437     else
01438     {
01439         // WARNING.  Not unique.  ZA + XA = atan2(-r01,-r02)
01440         rfZAngle = Math<Real>::ATan2(-m_afEntry[1],-m_afEntry[2]);
01441         rfYAngle = -Math<Real>::HALF_PI;
01442         rfXAngle = (Real)0.0;
01443         return false;
01444     }
01445 }
01446 //----------------------------------------------------------------------------
01447 template <class Real>
01448 Matrix3<Real>& Matrix3<Real>::Slerp (Real fT, const Matrix3& rkR0,
01449     const Matrix3& rkR1)
01450 {
01451     Vector3<Real> kAxis;
01452     Real fAngle;
01453     Matrix3 kProd = rkR0.TransposeTimes(rkR1);
01454     kProd.ToAxisAngle(kAxis,fAngle);
01455     FromAxisAngle(kAxis,fT*fAngle);
01456     return *this;
01457 }
01458 //----------------------------------------------------------------------------
01459 template <class Real>
01460 bool Matrix3<Real>::Tridiagonalize (Real afDiag[3], Real afSubd[2])
01461 {
01462     // Householder reduction T = Q^t M Q
01463     //   Input:   
01464     //     mat, symmetric 3x3 matrix M
01465     //   Output:  
01466     //     mat, orthogonal matrix Q (a reflection)
01467     //     diag, diagonal entries of T
01468     //     subd, subdiagonal entries of T (T is symmetric)
01469 
01470     Real fM00 = m_afEntry[0];
01471     Real fM01 = m_afEntry[1];
01472     Real fM02 = m_afEntry[2];
01473     Real fM11 = m_afEntry[4];
01474     Real fM12 = m_afEntry[5];
01475     Real fM22 = m_afEntry[8];
01476 
01477     afDiag[0] = fM00;
01478     if (Math<Real>::FAbs(fM02) >= Math<Real>::ZERO_TOLERANCE)
01479     {
01480         afSubd[0] = Math<Real>::Sqrt(fM01*fM01+fM02*fM02);
01481         Real fInvLength = ((Real)1.0)/afSubd[0];
01482         fM01 *= fInvLength;
01483         fM02 *= fInvLength;
01484         Real fTmp = ((Real)2.0)*fM01*fM12+fM02*(fM22-fM11);
01485         afDiag[1] = fM11+fM02*fTmp;
01486         afDiag[2] = fM22-fM02*fTmp;
01487         afSubd[1] = fM12-fM01*fTmp;
01488 
01489         m_afEntry[0] = (Real)1.0;
01490         m_afEntry[1] = (Real)0.0;
01491         m_afEntry[2] = (Real)0.0;
01492         m_afEntry[3] = (Real)0.0;
01493         m_afEntry[4] = fM01;
01494         m_afEntry[5] = fM02;
01495         m_afEntry[6] = (Real)0.0;
01496         m_afEntry[7] = fM02;
01497         m_afEntry[8] = -fM01;
01498         return true;
01499     }
01500     else
01501     {
01502         afDiag[1] = fM11;
01503         afDiag[2] = fM22;
01504         afSubd[0] = fM01;
01505         afSubd[1] = fM12;
01506 
01507         m_afEntry[0] = (Real)1.0;
01508         m_afEntry[1] = (Real)0.0;
01509         m_afEntry[2] = (Real)0.0;
01510         m_afEntry[3] = (Real)0.0;
01511         m_afEntry[4] = (Real)1.0;
01512         m_afEntry[5] = (Real)0.0;
01513         m_afEntry[6] = (Real)0.0;
01514         m_afEntry[7] = (Real)0.0;
01515         m_afEntry[8] = (Real)1.0;
01516         return false;
01517     }
01518 }
01519 //----------------------------------------------------------------------------
01520 template <class Real>
01521 bool Matrix3<Real>::QLAlgorithm (Real afDiag[3], Real afSubd[2])
01522 {
01523     // This is an implementation of the symmetric QR algorithm from the book
01524     // "Matrix Computations" by Gene H. Golub and Charles F. Van Loan, second
01525     // edition.  The algorithm is 8.2.3.  The implementation has a slight
01526     // variation to actually make it a QL algorithm, and it traps the case
01527     // when either of the subdiagonal terms s0 or s1 is zero and reduces the
01528     // 2-by-2 subblock directly.
01529 
01530     const int iMax = 32;
01531     for (int i = 0; i < iMax; i++)
01532     {
01533         Real fSum, fDiff, fDiscr, fEValue0, fEValue1, fCos, fSin, fTmp;
01534         int iRow;
01535 
01536         fSum = Math<Real>::FAbs(afDiag[0]) + Math<Real>::FAbs(afDiag[1]);
01537         if (Math<Real>::FAbs(afSubd[0]) + fSum == fSum)
01538         {
01539             // The matrix is effectively
01540             //       +-        -+
01541             //   M = | d0  0  0 |
01542             //       | 0  d1 s1 |
01543             //       | 0  s1 d2 |
01544             //       +-        -+
01545 
01546             // Compute the eigenvalues as roots of a quadratic equation.
01547             fSum = afDiag[1] + afDiag[2];
01548             fDiff = afDiag[1] - afDiag[2];
01549             fDiscr = Math<Real>::Sqrt(fDiff*fDiff +
01550                 ((Real)4.0)*afSubd[1]*afSubd[1]);
01551             fEValue0 = ((Real)0.5)*(fSum - fDiscr);
01552             fEValue1 = ((Real)0.5)*(fSum + fDiscr);
01553 
01554             // Compute the Givens rotation.
01555             if (fDiff >= (Real)0.0)
01556             {
01557                 fCos = afSubd[1];
01558                 fSin = afDiag[1] - fEValue0;
01559             }
01560             else
01561             {
01562                 fCos = afDiag[2] - fEValue0;
01563                 fSin = afSubd[1];
01564             }
01565             fTmp = Math<Real>::InvSqrt(fCos*fCos + fSin*fSin);
01566             fCos *= fTmp;
01567             fSin *= fTmp;
01568 
01569             // Postmultiply the current orthogonal matrix with the Givens
01570             // rotation.
01571             for (iRow = 0; iRow < 3; iRow++)
01572             {
01573                 fTmp = m_afEntry[2+3*iRow];
01574                 m_afEntry[2+3*iRow] = fSin*m_afEntry[1+3*iRow] + fCos*fTmp;
01575                 m_afEntry[1+3*iRow] = fCos*m_afEntry[1+3*iRow] - fSin*fTmp;
01576             }
01577 
01578             // Update the tridiagonal matrix.
01579             afDiag[1] = fEValue0;
01580             afDiag[2] = fEValue1;
01581             afSubd[0] = (Real)0.0;
01582             afSubd[1] = (Real)0.0;
01583             return true;
01584         }
01585 
01586         fSum = Math<Real>::FAbs(afDiag[1]) + Math<Real>::FAbs(afDiag[2]);
01587         if (Math<Real>::FAbs(afSubd[1]) + fSum == fSum)
01588         {
01589             // The matrix is effectively
01590             //       +-         -+
01591             //   M = | d0  s0  0 |
01592             //       | s0  d1  0 |
01593             //       | 0   0  d2 |
01594             //       +-         -+
01595 
01596             // Compute the eigenvalues as roots of a quadratic equation.
01597             fSum = afDiag[0] + afDiag[1];
01598             fDiff = afDiag[0] - afDiag[1];
01599             fDiscr = Math<Real>::Sqrt(fDiff*fDiff +
01600                 ((Real)4.0)*afSubd[0]*afSubd[0]);
01601             fEValue0 = ((Real)0.5)*(fSum - fDiscr);
01602             fEValue1 = ((Real)0.5)*(fSum + fDiscr);
01603 
01604             // Compute the Givens rotation.
01605             if (fDiff >= (Real)0.0)
01606             {
01607                 fCos = afSubd[0];
01608                 fSin = afDiag[0] - fEValue0;
01609             }
01610             else
01611             {
01612                 fCos = afDiag[1] - fEValue0;
01613                 fSin = afSubd[0];
01614             }
01615             fTmp = Math<Real>::InvSqrt(fCos*fCos + fSin*fSin);
01616             fCos *= fTmp;
01617             fSin *= fTmp;
01618 
01619             // Postmultiply the current orthogonal matrix with the Givens
01620             // rotation.
01621             for (iRow = 0; iRow < 3; iRow++)
01622             {
01623                 fTmp = m_afEntry[1+3*iRow];
01624                 m_afEntry[1+3*iRow] = fSin*m_afEntry[0+3*iRow] + fCos*fTmp;
01625                 m_afEntry[0+3*iRow] = fCos*m_afEntry[0+3*iRow] - fSin*fTmp;
01626             }
01627 
01628             // Update the tridiagonal matrix.
01629             afDiag[0] = fEValue0;
01630             afDiag[1] = fEValue1;
01631             afSubd[0] = (Real)0.0;
01632             afSubd[1] = (Real)0.0;
01633             return true;
01634         }
01635 
01636         // The matrix is
01637         //       +-        -+
01638         //   M = | d0 s0  0 |
01639         //       | s0 d1 s1 |
01640         //       | 0  s1 d2 |
01641         //       +-        -+
01642 
01643         // Set up the parameters for the first pass of the QL step.  The
01644         // value for A is the difference between diagonal term D[2] and the
01645         // implicit shift suggested by Wilkinson.
01646         Real fRatio = (afDiag[1]-afDiag[0])/(((Real)2.0f)*afSubd[0]);
01647         Real fRoot = Math<Real>::Sqrt((Real)1.0 + fRatio*fRatio);
01648         Real fB = afSubd[1];
01649         Real fA = afDiag[2] - afDiag[0];
01650         if (fRatio >= (Real)0.0)
01651         {
01652             fA += afSubd[0]/(fRatio + fRoot);
01653         }
01654         else
01655         {
01656             fA += afSubd[0]/(fRatio - fRoot);
01657         }
01658 
01659         // Compute the Givens rotation for the first pass.
01660         if (Math<Real>::FAbs(fB) >= Math<Real>::FAbs(fA))
01661         {
01662             fRatio = fA/fB;
01663             fSin = Math<Real>::InvSqrt((Real)1.0 + fRatio*fRatio);
01664             fCos = fRatio*fSin;
01665         }
01666         else
01667         {
01668             fRatio = fB/fA;
01669             fCos = Math<Real>::InvSqrt((Real)1.0 + fRatio*fRatio);
01670             fSin = fRatio*fCos;
01671         }
01672 
01673         // Postmultiply the current orthogonal matrix with the Givens
01674         // rotation.
01675         for (iRow = 0; iRow < 3; iRow++)
01676         {
01677             fTmp = m_afEntry[2+3*iRow];
01678             m_afEntry[2+3*iRow] = fSin*m_afEntry[1+3*iRow]+fCos*fTmp;
01679             m_afEntry[1+3*iRow] = fCos*m_afEntry[1+3*iRow]-fSin*fTmp;
01680         }
01681 
01682         // Set up the parameters for the second pass of the QL step.  The
01683         // values tmp0 and tmp1 are required to fully update the tridiagonal
01684         // matrix at the end of the second pass.
01685         Real fTmp0 = (afDiag[1] - afDiag[2])*fSin +
01686             ((Real)2.0)*afSubd[1]*fCos;
01687         Real fTmp1 = fCos*afSubd[0];
01688         fB = fSin*afSubd[0];
01689         fA = fCos*fTmp0 - afSubd[1];
01690         fTmp0 *= fSin;
01691 
01692         // Compute the Givens rotation for the second pass.  The subdiagonal
01693         // term S[1] in the tridiagonal matrix is updated at this time.
01694         if (Math<Real>::FAbs(fB) >= Math<Real>::FAbs(fA))
01695         {
01696             fRatio = fA/fB;
01697             fRoot = Math<Real>::Sqrt((Real)1.0 + fRatio*fRatio);
01698             afSubd[1] = fB*fRoot;
01699             fSin = ((Real)1.0)/fRoot;
01700             fCos = fRatio*fSin;
01701         }
01702         else
01703         {
01704             fRatio = fB/fA;
01705             fRoot = Math<Real>::Sqrt((Real)1.0 + fRatio*fRatio);
01706             afSubd[1] = fA*fRoot;
01707             fCos = ((Real)1.0)/fRoot;
01708             fSin = fRatio*fCos;
01709         }
01710 
01711         // Postmultiply the current orthogonal matrix with the Givens
01712         // rotation.
01713         for (iRow = 0; iRow < 3; iRow++)
01714         {
01715             fTmp = m_afEntry[1+3*iRow];
01716             m_afEntry[1+3*iRow] = fSin*m_afEntry[0+3*iRow]+fCos*fTmp;
01717             m_afEntry[0+3*iRow] = fCos*m_afEntry[0+3*iRow]-fSin*fTmp;
01718         }
01719 
01720         // Complete the update of the tridiagonal matrix.
01721         Real fTmp2 = afDiag[1] - fTmp0;
01722         afDiag[2] += fTmp0;
01723         fTmp0 = (afDiag[0] - fTmp2)*fSin + ((Real)2.0)*fTmp1*fCos;
01724         afSubd[0] = fCos*fTmp0 - fTmp1;
01725         fTmp0 *= fSin;
01726         afDiag[1] = fTmp2 + fTmp0;
01727         afDiag[0] -= fTmp0;
01728     }
01729     return false;
01730 }
01731 //----------------------------------------------------------------------------
01732 template <class Real>
01733 void Matrix3<Real>::Bidiagonalize (Matrix3& rkA, Matrix3& rkL, Matrix3& rkR)
01734 {
01735     Real afV[3], afW[3];
01736     Real fLength, fSign, fT1, fInvT1, fT2;
01737     bool bIdentity;
01738 
01739     // map first column to (*,0,0)
01740     fLength = Math<Real>::Sqrt(rkA[0][0]*rkA[0][0] + rkA[1][0]*rkA[1][0] +
01741         rkA[2][0]*rkA[2][0]);
01742     if (fLength > (Real)0.0)
01743     {
01744         fSign = (rkA[0][0] > (Real)0.0 ? (Real)1.0 : -(Real)1.0);
01745         fT1 = rkA[0][0] + fSign*fLength;
01746         fInvT1 = ((Real)1.0)/fT1;
01747         afV[1] = rkA[1][0]*fInvT1;
01748         afV[2] = rkA[2][0]*fInvT1;
01749 
01750         fT2 = -((Real)2.0)/(((Real)1.0)+afV[1]*afV[1]+afV[2]*afV[2]);
01751         afW[0] = fT2*(rkA[0][0]+rkA[1][0]*afV[1]+rkA[2][0]*afV[2]);
01752         afW[1] = fT2*(rkA[0][1]+rkA[1][1]*afV[1]+rkA[2][1]*afV[2]);
01753         afW[2] = fT2*(rkA[0][2]+rkA[1][2]*afV[1]+rkA[2][2]*afV[2]);
01754         rkA[0][0] += afW[0];
01755         rkA[0][1] += afW[1];
01756         rkA[0][2] += afW[2];
01757         rkA[1][1] += afV[1]*afW[1];
01758         rkA[1][2] += afV[1]*afW[2];
01759         rkA[2][1] += afV[2]*afW[1];
01760         rkA[2][2] += afV[2]*afW[2];
01761 
01762         rkL[0][0] = ((Real)1.0)+fT2;
01763         rkL[0][1] = fT2*afV[1];
01764         rkL[1][0] = rkL[0][1];
01765         rkL[0][2] = fT2*afV[2];
01766         rkL[2][0] = rkL[0][2];
01767         rkL[1][1] = ((Real)1.0)+fT2*afV[1]*afV[1];
01768         rkL[1][2] = fT2*afV[1]*afV[2];
01769         rkL[2][1] = rkL[1][2];
01770         rkL[2][2] = ((Real)1.0)+fT2*afV[2]*afV[2];
01771         bIdentity = false;
01772     }
01773     else
01774     {
01775         rkL = Matrix3::IDENTITY;
01776         bIdentity = true;
01777     }
01778 
01779     // map first row to (*,*,0)
01780     fLength = Math<Real>::Sqrt(rkA[0][1]*rkA[0][1]+rkA[0][2]*rkA[0][2]);
01781     if (fLength > (Real)0.0)
01782     {
01783         fSign = (rkA[0][1] > (Real)0.0 ? (Real)1.0 : -(Real)1.0);
01784         fT1 = rkA[0][1] + fSign*fLength;
01785         afV[2] = rkA[0][2]/fT1;
01786 
01787         fT2 = -((Real)2.0)/(((Real)1.0)+afV[2]*afV[2]);
01788         afW[0] = fT2*(rkA[0][1]+rkA[0][2]*afV[2]);
01789         afW[1] = fT2*(rkA[1][1]+rkA[1][2]*afV[2]);
01790         afW[2] = fT2*(rkA[2][1]+rkA[2][2]*afV[2]);
01791         rkA[0][1] += afW[0];
01792         rkA[1][1] += afW[1];
01793         rkA[1][2] += afW[1]*afV[2];
01794         rkA[2][1] += afW[2];
01795         rkA[2][2] += afW[2]*afV[2];
01796         
01797         rkR[0][0] = (Real)1.0;
01798         rkR[0][1] = (Real)0.0;
01799         rkR[1][0] = (Real)0.0;
01800         rkR[0][2] = (Real)0.0;
01801         rkR[2][0] = (Real)0.0;
01802         rkR[1][1] = ((Real)1.0)+fT2;
01803         rkR[1][2] = fT2*afV[2];
01804         rkR[2][1] = rkR[1][2];
01805         rkR[2][2] = ((Real)1.0)+fT2*afV[2]*afV[2];
01806     }
01807     else
01808     {
01809         rkR = Matrix3::IDENTITY;
01810     }
01811 
01812     // map second column to (*,*,0)
01813     fLength = Math<Real>::Sqrt(rkA[1][1]*rkA[1][1]+rkA[2][1]*rkA[2][1]);
01814     if (fLength > (Real)0.0)
01815     {
01816         fSign = (rkA[1][1] > (Real)0.0 ? (Real)1.0 : -(Real)1.0);
01817         fT1 = rkA[1][1] + fSign*fLength;
01818         afV[2] = rkA[2][1]/fT1;
01819 
01820         fT2 = -((Real)2.0)/(((Real)1.0)+afV[2]*afV[2]);
01821         afW[1] = fT2*(rkA[1][1]+rkA[2][1]*afV[2]);
01822         afW[2] = fT2*(rkA[1][2]+rkA[2][2]*afV[2]);
01823         rkA[1][1] += afW[1];
01824         rkA[1][2] += afW[2];
01825         rkA[2][2] += afV[2]*afW[2];
01826 
01827         Real fA = ((Real)1.0)+fT2;
01828         Real fB = fT2*afV[2];
01829         Real fC = ((Real)1.0)+fB*afV[2];
01830 
01831         if (bIdentity)
01832         {
01833             rkL[0][0] = (Real)1.0;
01834             rkL[0][1] = (Real)0.0;
01835             rkL[1][0] = (Real)0.0;
01836             rkL[0][2] = (Real)0.0;
01837             rkL[2][0] = (Real)0.0;
01838             rkL[1][1] = fA;
01839             rkL[1][2] = fB;
01840             rkL[2][1] = fB;
01841             rkL[2][2] = fC;
01842         }
01843         else
01844         {
01845             for (int iRow = 0; iRow < 3; iRow++)
01846             {
01847                 Real fTmp0 = rkL[iRow][1];
01848                 Real fTmp1 = rkL[iRow][2];
01849                 rkL[iRow][1] = fA*fTmp0+fB*fTmp1;
01850                 rkL[iRow][2] = fB*fTmp0+fC*fTmp1;
01851             }
01852         }
01853     }
01854 }
01855 //----------------------------------------------------------------------------
01856 template <class Real>
01857 void Matrix3<Real>::GolubKahanStep (Matrix3& rkA, Matrix3& rkL, Matrix3& rkR)
01858 {
01859     Real fT11 = rkA[0][1]*rkA[0][1]+rkA[1][1]*rkA[1][1];
01860     Real fT22 = rkA[1][2]*rkA[1][2]+rkA[2][2]*rkA[2][2];
01861     Real fT12 = rkA[1][1]*rkA[1][2];
01862     Real fTrace = fT11+fT22;
01863     Real fDiff = fT11-fT22;
01864     Real fDiscr = Math<Real>::Sqrt(fDiff*fDiff+((Real)4.0)*fT12*fT12);
01865     Real fRoot1 = ((Real)0.5)*(fTrace+fDiscr);
01866     Real fRoot2 = ((Real)0.5)*(fTrace-fDiscr);
01867 
01868     // adjust right
01869     Real fY = rkA[0][0] - (Math<Real>::FAbs(fRoot1-fT22) <=
01870         Math<Real>::FAbs(fRoot2-fT22) ? fRoot1 : fRoot2);
01871     Real fZ = rkA[0][1];
01872     Real fInvLength = Math<Real>::InvSqrt(fY*fY+fZ*fZ);
01873     Real fSin = fZ*fInvLength;
01874     Real fCos = -fY*fInvLength;
01875 
01876     Real fTmp0 = rkA[0][0];
01877     Real fTmp1 = rkA[0][1];
01878     rkA[0][0] = fCos*fTmp0-fSin*fTmp1;
01879     rkA[0][1] = fSin*fTmp0+fCos*fTmp1;
01880     rkA[1][0] = -fSin*rkA[1][1];
01881     rkA[1][1] *= fCos;
01882 
01883     int iRow;
01884     for (iRow = 0; iRow < 3; iRow++)
01885     {
01886         fTmp0 = rkR[0][iRow];
01887         fTmp1 = rkR[1][iRow];
01888         rkR[0][iRow] = fCos*fTmp0-fSin*fTmp1;
01889         rkR[1][iRow] = fSin*fTmp0+fCos*fTmp1;
01890     }
01891 
01892     // adjust left
01893     fY = rkA[0][0];
01894     fZ = rkA[1][0];
01895     fInvLength = Math<Real>::InvSqrt(fY*fY+fZ*fZ);
01896     fSin = fZ*fInvLength;
01897     fCos = -fY*fInvLength;
01898 
01899     rkA[0][0] = fCos*rkA[0][0]-fSin*rkA[1][0];
01900     fTmp0 = rkA[0][1];
01901     fTmp1 = rkA[1][1];
01902     rkA[0][1] = fCos*fTmp0-fSin*fTmp1;
01903     rkA[1][1] = fSin*fTmp0+fCos*fTmp1;
01904     rkA[0][2] = -fSin*rkA[1][2];
01905     rkA[1][2] *= fCos;
01906 
01907     int iCol;
01908     for (iCol = 0; iCol < 3; iCol++)
01909     {
01910         fTmp0 = rkL[iCol][0];
01911         fTmp1 = rkL[iCol][1];
01912         rkL[iCol][0] = fCos*fTmp0-fSin*fTmp1;
01913         rkL[iCol][1] = fSin*fTmp0+fCos*fTmp1;
01914     }
01915 
01916     // adjust right
01917     fY = rkA[0][1];
01918     fZ = rkA[0][2];
01919     fInvLength = Math<Real>::InvSqrt(fY*fY+fZ*fZ);
01920     fSin = fZ*fInvLength;
01921     fCos = -fY*fInvLength;
01922 
01923     rkA[0][1] = fCos*rkA[0][1]-fSin*rkA[0][2];
01924     fTmp0 = rkA[1][1];
01925     fTmp1 = rkA[1][2];
01926     rkA[1][1] = fCos*fTmp0-fSin*fTmp1;
01927     rkA[1][2] = fSin*fTmp0+fCos*fTmp1;
01928     rkA[2][1] = -fSin*rkA[2][2];
01929     rkA[2][2] *= fCos;
01930 
01931     for (iRow = 0; iRow < 3; iRow++)
01932     {
01933         fTmp0 = rkR[1][iRow];
01934         fTmp1 = rkR[2][iRow];
01935         rkR[1][iRow] = fCos*fTmp0-fSin*fTmp1;
01936         rkR[2][iRow] = fSin*fTmp0+fCos*fTmp1;
01937     }
01938 
01939     // adjust left
01940     fY = rkA[1][1];
01941     fZ = rkA[2][1];
01942     fInvLength = Math<Real>::InvSqrt(fY*fY+fZ*fZ);
01943     fSin = fZ*fInvLength;
01944     fCos = -fY*fInvLength;
01945 
01946     rkA[1][1] = fCos*rkA[1][1]-fSin*rkA[2][1];
01947     fTmp0 = rkA[1][2];
01948     fTmp1 = rkA[2][2];
01949     rkA[1][2] = fCos*fTmp0-fSin*fTmp1;
01950     rkA[2][2] = fSin*fTmp0+fCos*fTmp1;
01951 
01952     for (iCol = 0; iCol < 3; iCol++)
01953     {
01954         fTmp0 = rkL[iCol][1];
01955         fTmp1 = rkL[iCol][2];
01956         rkL[iCol][1] = fCos*fTmp0-fSin*fTmp1;
01957         rkL[iCol][2] = fSin*fTmp0+fCos*fTmp1;
01958     }
01959 }
01960 //----------------------------------------------------------------------------
01961 template <class Real>
01962 void Matrix3<Real>::SingularValueDecomposition (Matrix3& rkL, Matrix3& rkS,
01963     Matrix3& rkR) const
01964 {
01965     int iRow, iCol;
01966 
01967     Matrix3 kA = *this;
01968     Bidiagonalize(kA,rkL,rkR);
01969     rkS.MakeZero();
01970 
01971     const int iMax = 32;
01972     const Real fEpsilon = (Real)1e-04;
01973     for (int i = 0; i < iMax; i++)
01974     {
01975         Real fTmp, fTmp0, fTmp1;
01976         Real fSin0, fCos0, fTan0;
01977         Real fSin1, fCos1, fTan1;
01978 
01979         bool bTest1 = (Math<Real>::FAbs(kA[0][1]) <=
01980             fEpsilon*(Math<Real>::FAbs(kA[0][0]) +
01981             Math<Real>::FAbs(kA[1][1])));
01982         bool bTest2 = (Math<Real>::FAbs(kA[1][2]) <=
01983             fEpsilon*(Math<Real>::FAbs(kA[1][1]) +
01984             Math<Real>::FAbs(kA[2][2])));
01985         if (bTest1)
01986         {
01987             if (bTest2)
01988             {
01989                 rkS[0][0] = kA[0][0];
01990                 rkS[1][1] = kA[1][1];
01991                 rkS[2][2] = kA[2][2];
01992                 break;
01993             }
01994             else
01995             {
01996                 // 2x2 closed form factorization
01997                 fTmp = (kA[1][1]*kA[1][1] - kA[2][2]*kA[2][2] +
01998                     kA[1][2]*kA[1][2])/(kA[1][2]*kA[2][2]);
01999                 fTan0 = ((Real)0.5)*(fTmp + Math<Real>::Sqrt(fTmp*fTmp +
02000                     ((Real)4.0)));
02001                 fCos0 = Math<Real>::InvSqrt(((Real)1.0)+fTan0*fTan0);
02002                 fSin0 = fTan0*fCos0;
02003 
02004                 for (iCol = 0; iCol < 3; iCol++)
02005                 {
02006                     fTmp0 = rkL[iCol][1];
02007                     fTmp1 = rkL[iCol][2];
02008                     rkL[iCol][1] = fCos0*fTmp0-fSin0*fTmp1;
02009                     rkL[iCol][2] = fSin0*fTmp0+fCos0*fTmp1;
02010                 }
02011                 
02012                 fTan1 = (kA[1][2]-kA[2][2]*fTan0)/kA[1][1];
02013                 fCos1 = Math<Real>::InvSqrt(((Real)1.0)+fTan1*fTan1);
02014                 fSin1 = -fTan1*fCos1;
02015 
02016                 for (iRow = 0; iRow < 3; iRow++)
02017                 {
02018                     fTmp0 = rkR[1][iRow];
02019                     fTmp1 = rkR[2][iRow];
02020                     rkR[1][iRow] = fCos1*fTmp0-fSin1*fTmp1;
02021                     rkR[2][iRow] = fSin1*fTmp0+fCos1*fTmp1;
02022                 }
02023 
02024                 rkS[0][0] = kA[0][0];
02025                 rkS[1][1] = fCos0*fCos1*kA[1][1] -
02026                     fSin1*(fCos0*kA[1][2]-fSin0*kA[2][2]);
02027                 rkS[2][2] = fSin0*fSin1*kA[1][1] +
02028                     fCos1*(fSin0*kA[1][2]+fCos0*kA[2][2]);
02029                 break;
02030             }
02031         }
02032         else 
02033         {
02034             if (bTest2)
02035             {
02036                 // 2x2 closed form factorization 
02037                 fTmp = (kA[0][0]*kA[0][0] + kA[1][1]*kA[1][1] -
02038                     kA[0][1]*kA[0][1])/(kA[0][1]*kA[1][1]);
02039                 fTan0 = ((Real)0.5)*(-fTmp + Math<Real>::Sqrt(fTmp*fTmp +
02040                     ((Real)4.0)));
02041                 fCos0 = Math<Real>::InvSqrt(((Real)1.0)+fTan0*fTan0);
02042                 fSin0 = fTan0*fCos0;
02043 
02044                 for (iCol = 0; iCol < 3; iCol++)
02045                 {
02046                     fTmp0 = rkL[iCol][0];
02047                     fTmp1 = rkL[iCol][1];
02048                     rkL[iCol][0] = fCos0*fTmp0-fSin0*fTmp1;
02049                     rkL[iCol][1] = fSin0*fTmp0+fCos0*fTmp1;
02050                 }
02051                 
02052                 fTan1 = (kA[0][1]-kA[1][1]*fTan0)/kA[0][0];
02053                 fCos1 = Math<Real>::InvSqrt(((Real)1.0)+fTan1*fTan1);
02054                 fSin1 = -fTan1*fCos1;
02055 
02056                 for (iRow = 0; iRow < 3; iRow++)
02057                 {
02058                     fTmp0 = rkR[0][iRow];
02059                     fTmp1 = rkR[1][iRow];
02060                     rkR[0][iRow] = fCos1*fTmp0-fSin1*fTmp1;
02061                     rkR[1][iRow] = fSin1*fTmp0+fCos1*fTmp1;
02062                 }
02063 
02064                 rkS[0][0] = fCos0*fCos1*kA[0][0] -
02065                     fSin1*(fCos0*kA[0][1]-fSin0*kA[1][1]);
02066                 rkS[1][1] = fSin0*fSin1*kA[0][0] +
02067                     fCos1*(fSin0*kA[0][1]+fCos0*kA[1][1]);
02068                 rkS[2][2] = kA[2][2];
02069                 break;
02070             }
02071             else
02072             {
02073                 GolubKahanStep(kA,rkL,rkR);
02074             }
02075         }
02076     }
02077 
02078     // positize diagonal
02079     for (iRow = 0; iRow < 3; iRow++)
02080     {
02081         if (rkS[iRow][iRow] < (Real)0.0)
02082         {
02083             rkS[iRow][iRow] = -rkS[iRow][iRow];
02084             for (iCol = 0; iCol < 3; iCol++)
02085                 rkR[iRow][iCol] = -rkR[iRow][iCol];
02086         }
02087     }
02088 }
02089 //----------------------------------------------------------------------------
02090 template <class Real>
02091 void Matrix3<Real>::SingularValueComposition (const Matrix3& rkL,
02092     const Matrix3& rkS, const Matrix3& rkR)
02093 {
02094     *this = rkL*(rkS*rkR);
02095 }
02096 //----------------------------------------------------------------------------
02097 template <class Real>
02098 void Matrix3<Real>::QDUDecomposition (Matrix3& rkQ, Matrix3& rkD,
02099     Matrix3& rkU) const
02100 {
02101     // Factor M = QR = QDU where Q is orthogonal (rotation), D is diagonal
02102     // (scaling),  and U is upper triangular with ones on its diagonal
02103     // (shear).  Algorithm uses Gram-Schmidt orthogonalization (the QR
02104     // algorithm).
02105     //
02106     // If M = [ m0 | m1 | m2 ] and Q = [ q0 | q1 | q2 ], then
02107     //
02108     //   q0 = m0/|m0|
02109     //   q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0|
02110     //   q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1|
02111     //
02112     // where |V| indicates length of vector V and A*B indicates dot
02113     // product of vectors A and B.  The matrix R has entries
02114     //
02115     //   r00 = q0*m0  r01 = q0*m1  r02 = q0*m2
02116     //   r10 = 0      r11 = q1*m1  r12 = q1*m2
02117     //   r20 = 0      r21 = 0      r22 = q2*m2
02118     //
02119     // so D = diag(r00,r11,r22) and U has entries u01 = r01/r00,
02120     // u02 = r02/r00, and u12 = r12/r11.
02121 
02122     // build orthogonal matrix Q
02123     Real fInvLength = Math<Real>::InvSqrt(m_afEntry[0]*m_afEntry[0] +
02124         m_afEntry[3]*m_afEntry[3] + m_afEntry[6]*m_afEntry[6]);
02125     rkQ[0][0] = m_afEntry[0]*fInvLength;
02126     rkQ[1][0] = m_afEntry[3]*fInvLength;
02127     rkQ[2][0] = m_afEntry[6]*fInvLength;
02128 
02129     Real fDot = rkQ[0][0]*m_afEntry[1] + rkQ[1][0]*m_afEntry[4] +
02130         rkQ[2][0]*m_afEntry[7];
02131     rkQ[0][1] = m_afEntry[1]-fDot*rkQ[0][0];
02132     rkQ[1][1] = m_afEntry[4]-fDot*rkQ[1][0];
02133     rkQ[2][1] = m_afEntry[7]-fDot*rkQ[2][0];
02134     fInvLength = Math<Real>::InvSqrt(rkQ[0][1]*rkQ[0][1] +
02135         rkQ[1][1]*rkQ[1][1] + rkQ[2][1]*rkQ[2][1]);
02136     rkQ[0][1] *= fInvLength;
02137     rkQ[1][1] *= fInvLength;
02138     rkQ[2][1] *= fInvLength;
02139 
02140     fDot = rkQ[0][0]*m_afEntry[2] + rkQ[1][0]*m_afEntry[5] +
02141         rkQ[2][0]*m_afEntry[8];
02142     rkQ[0][2] = m_afEntry[2]-fDot*rkQ[0][0];
02143     rkQ[1][2] = m_afEntry[5]-fDot*rkQ[1][0];
02144     rkQ[2][2] = m_afEntry[8]-fDot*rkQ[2][0];
02145     fDot = rkQ[0][1]*m_afEntry[2] + rkQ[1][1]*m_afEntry[5] +
02146         rkQ[2][1]*m_afEntry[8];
02147     rkQ[0][2] -= fDot*rkQ[0][1];
02148     rkQ[1][2] -= fDot*rkQ[1][1];
02149     rkQ[2][2] -= fDot*rkQ[2][1];
02150     fInvLength = Math<Real>::InvSqrt(rkQ[0][2]*rkQ[0][2] +
02151         rkQ[1][2]*rkQ[1][2] + rkQ[2][2]*rkQ[2][2]);
02152     rkQ[0][2] *= fInvLength;
02153     rkQ[1][2] *= fInvLength;
02154     rkQ[2][2] *= fInvLength;
02155 
02156     // guarantee that orthogonal matrix has determinant 1 (no reflections)
02157     Real fDet = rkQ[0][0]*rkQ[1][1]*rkQ[2][2] + rkQ[0][1]*rkQ[1][2]*rkQ[2][0]
02158         +  rkQ[0][2]*rkQ[1][0]*rkQ[2][1] - rkQ[0][2]*rkQ[1][1]*rkQ[2][0]
02159         -  rkQ[0][1]*rkQ[1][0]*rkQ[2][2] - rkQ[0][0]*rkQ[1][2]*rkQ[2][1];
02160 
02161     if (fDet < (Real)0.0)
02162     {
02163         for (int iRow = 0; iRow < 3; iRow++)
02164         {
02165             for (int iCol = 0; iCol < 3; iCol++)
02166             {
02167                 rkQ[iRow][iCol] = -rkQ[iRow][iCol];
02168             }
02169         }
02170     }
02171 
02172     // build "right" matrix R
02173     Matrix3 kR;
02174     kR[0][0] = rkQ[0][0]*m_afEntry[0] + rkQ[1][0]*m_afEntry[3] +
02175         rkQ[2][0]*m_afEntry[6];
02176     kR[0][1] = rkQ[0][0]*m_afEntry[1] + rkQ[1][0]*m_afEntry[4] +
02177         rkQ[2][0]*m_afEntry[7];
02178     kR[1][1] = rkQ[0][1]*m_afEntry[1] + rkQ[1][1]*m_afEntry[4] +
02179         rkQ[2][1]*m_afEntry[7];
02180     kR[0][2] = rkQ[0][0]*m_afEntry[2] + rkQ[1][0]*m_afEntry[5] +
02181         rkQ[2][0]*m_afEntry[8];
02182     kR[1][2] = rkQ[0][1]*m_afEntry[2] + rkQ[1][1]*m_afEntry[5] +
02183         rkQ[2][1]*m_afEntry[8];
02184     kR[2][2] = rkQ[0][2]*m_afEntry[2] + rkQ[1][2]*m_afEntry[5] +
02185         rkQ[2][2]*m_afEntry[8];
02186 
02187     // the scaling component
02188     rkD.MakeDiagonal(kR[0][0],kR[1][1],kR[2][2]);
02189 
02190     // the shear component
02191     Real fInvD0 = ((Real)1.0)/rkD[0][0];
02192     rkU[0][0] = (Real)1.0;
02193     rkU[0][1] = kR[0][1]*fInvD0;
02194     rkU[0][2] = kR[0][2]*fInvD0;
02195     rkU[1][0] = (Real)0.0;
02196     rkU[1][1] = (Real)1.0;
02197     rkU[1][2] = kR[1][2]/rkD[1][1];
02198     rkU[2][0] = (Real)0.0;
02199     rkU[2][1] = (Real)0.0;
02200     rkU[2][2] = (Real)1.0;
02201 }
02202 //----------------------------------------------------------------------------
02203 template <class Real>
02204 Matrix3<Real> operator* (Real fScalar, const Matrix3<Real>& rkM)
02205 {
02206     return rkM*fScalar;
02207 }
02208 //----------------------------------------------------------------------------
02209 template <class Real>
02210 Vector3<Real> operator* (const Vector3<Real>& rkV, const Matrix3<Real>& rkM)
02211 {
02212     return Vector3<Real>(
02213         rkV[0]*rkM[0][0] + rkV[1]*rkM[1][0] + rkV[2]*rkM[2][0],
02214         rkV[0]*rkM[0][1] + rkV[1]*rkM[1][1] + rkV[2]*rkM[2][1],
02215         rkV[0]*rkM[0][2] + rkV[1]*rkM[1][2] + rkV[2]*rkM[2][2]);
02216 }
02217 //----------------------------------------------------------------------------
02218 } //namespace Wm4

Generated on Wed Nov 23 19:01:05 2011 for FreeCAD by  doxygen 1.6.1