ML Reference
MeVis/Foundation/Sources/MLLinearAlgebra/mlMatrix3.h
Go to the documentation of this file.
00001 // **InsertLicense** code 
00002 //=====================================================================================
00004 
00009 //=====================================================================================
00010 
00011 #ifndef __mlMatrix3_H
00012 #define __mlMatrix3_H
00013 
00014 // Include system independency file and project settings.
00015 #ifndef __mlLinearAlgebraSystem_H
00016 #include "mlLinearAlgebraSystem.h"
00017 #endif
00018 #ifndef __mlLinearAlgebraDefs_H
00019 #include "mlLinearAlgebraDefs.h"
00020 #endif
00021 #ifndef __mlLinearAlgebraTools_H
00022 #include "mlLinearAlgebraTools.h"
00023 #endif
00024 
00025 #ifndef __mlFloatingPointMatrix_H
00026 #include "mlFloatingPointMatrix.h"
00027 #endif
00028 
00029 #ifndef __mlMatrix2_H
00030 #include "mlMatrix2.h"
00031 #endif
00032 #ifndef __mlVector3_H
00033 #include "mlVector3.h"
00034 #endif
00035 
00036 // All declarations of this header will be in the ML_LA_NAMESPACE namespace.
00037 ML_LA_START_NAMESPACE
00038 
00039 //--------------------------------------------------------------------
00041 //--------------------------------------------------------------------
00042 template <class DT>
00043 class Tmat3 : public FloatingPointMatrix<Tvec3<DT>, 3>
00044 {
00045   
00046 public:
00047   
00049   typedef DT ComponentType;
00050   
00051   // Build 3x3 matrix from 9 zero elements.
00052   Tmat3();
00053   
00054   // Build matrix that has the argument at the diagonal values, zero otherwise
00055   Tmat3(const DT diagValue);
00056 
00057   // Build matrix of the three row vectors row0, row1, row2.
00058   Tmat3(const Tvec3<DT> &row0, const Tvec3<DT> &row1, const Tvec3<DT> &row2);
00059   
00060   // Copy constructor from the Tmat3 mat.
00061   Tmat3(const Tmat3<DT> &mat);
00062   
00063   // Constructor from 9 floating point values in an array given by mat, row by row.
00064   Tmat3(const float mat[9]);
00065   
00066   // Constructor from 9 double values in an array given by mat, row by row.
00067   Tmat3(const double mat[9]);
00068   
00069   // Initialize all matrix elements explicitly with scalars,
00070   // filling it row by row.
00071   Tmat3(const double in00, const double in01, const double in02,
00072         const double in10, const double in11, const double in12,
00073         const double in20, const double in21, const double in22);
00074   
00075   // Copy contents from float array mat into *this, row by row.
00076   void setValues(const float mat[9]);
00077   
00078   // Copy contents of *this into float array mat, row by row.
00079   // Note that range and precision of the float values may not be
00080   // sufficient for the double matrix contents.
00081   void getValues(float mat[9]) const;
00082   
00083   // Copy contents from double array mat into *this, row by row.
00084   void setValues(const double mat[9]);
00085   
00086   // Copy contents of *this into double array mat, row by row.
00087   void getValues(double mat[9]) const;
00088   
00089   // Set diagonal matrix with scale on diagonal.
00090   void setScaleMatrix(const DT scale);
00091   
00092   // Return a matrix filled with values val.
00093   static Tmat3<DT> getMat(const double val);
00094   
00095   // Set all values to val.
00096   void set(DT val);
00097   
00100   bool operator<(const Tmat3<DT> &) const { return false; }
00101   
00102   // Assignment from a Tmat3
00103   const Tmat3<DT> &operator=(const Tmat3<DT> &m);
00104   
00105   // Incrementation by a Tmat3.
00106   const Tmat3<DT> &operator+=(const Tmat3<DT> &m);
00107   
00108   // Decrement by a Tmat3
00109   const Tmat3<DT> &operator-=(const Tmat3<DT> &m);
00110   
00111   // Multiplication by a scalar constant
00112   const Tmat3<DT> &operator*=(const DT d);
00113   
00114   // Division by a scalar constant. 
00115   // Division by zero is not handled and must be avoided by caller.
00116   const Tmat3<DT> &operator/=(const DT d);
00117   
00118   //-------------------------------------------------
00119   // Special functions
00120   //-------------------------------------------------
00121   // Determinant.
00122   DT det() const;
00123   
00124   // Transpose.
00125   Tmat3 transpose() const;
00126   
00127   // Return identity matrix.
00128   static Tmat3 getIdentity();
00129   
00130   // Returns the inverse. Gauss-Jordan elimination with partial pivoting.
00131   // If a non-NULL Boolean pointer is passed to isInvertible 
00132   // then true is returned in *isInvertible in the case of a 
00133   // successful inversion or false if the inversion is not possible
00134   // (function return is the identity then).
00135   // If a NULL pointer is passed as isInvertible the matrix must
00136   // be invertible, otherwise errors will occur.
00137   Tmat3 inverse(bool* isInvertible=NULL) const;
00138   
00139   // Apply the function fct to each component.
00140   const Tmat3<DT> &apply(MLDblFuncPtr fct);
00141   
00142   // Calculate Jacobi-Decomposition of 3x3 matrix.
00143   Tmat3 jacobi(Tvec3<DT> &eVal, int &rots) const;
00144   
00145 }; // end of class *Tmat3*
00146 
00147 
00148 
00149 //---------------------------------------------------------------------
00151 
00152 //---------------------------------------------------------------------
00154 template <class DT>
00155 inline Tmat3<DT>::Tmat3()
00156 {
00157   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::Tmat3())");
00158   
00159   this->v[0] = this->v[1] = this->v[2] = Tvec3<DT>(0);
00160 }
00161 
00162 // Construct matrix that has the argument at the diagonal values, zero otherwise
00163 template <class DT>
00164 inline Tmat3<DT>::Tmat3(const DT diagValue)
00165 {
00166   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::Tmat3(diagValue)");
00167   
00168   this->v[0][0] = this->v[1][1] = this->v[2][2] = diagValue;
00169   this->v[1][0] = this->v[2][0] = this->v[2][1] = 0;
00170   this->v[0][1] = this->v[0][2] = this->v[1][2] = 0;
00171 }
00172 
00174 template <class DT>
00175 inline Tmat3<DT>::Tmat3(const Tvec3<DT> &row0, const Tvec3<DT> &row1, const Tvec3<DT> &row2)
00176 {
00177   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::Tmat3(const Tvec3<DT> &row0, const Tvec3<DT> &row1, const Tvec3<DT> &row2)");
00178   
00179   this->v[0] = row0; 
00180   this->v[1] = row1; 
00181   this->v[2] = row2;
00182 }
00183 
00185 template <class DT>
00186 inline Tmat3<DT>::Tmat3(const Tmat3<DT> &mat)
00187 {
00188   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::Tmat3(const Tmat3<DT> &mat)");
00189   
00190   this->v[0] = mat.v[0]; 
00191   this->v[1] = mat.v[1]; 
00192   this->v[2] = mat.v[2];
00193 }
00194 
00196 template <class DT>
00197 inline Tmat3<DT>::Tmat3(const float mat[9])
00198 {
00199   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::Tmat3(const float mat[9]))");
00200   
00201   setValues(mat);
00202 }
00203 
00205 template <class DT>
00206 inline Tmat3<DT>::Tmat3(const double mat[9])
00207 {
00208   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::Tmat3(const double mat[9])");
00209   
00210   setValues(mat);
00211 }
00212 
00214 template <class DT>
00215 inline Tmat3<DT> Tmat3<DT>::getMat(const double val)
00216 {
00217   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::getMat(const double val)");
00218   
00219   return Tmat3<DT>(val, val, val,
00220                    val, val, val,
00221                    val, val, val);
00222 }
00223 
00225 template <class DT>
00226 inline void Tmat3<DT>::set(DT val)
00227 {
00228   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::set(DT val)");
00229   
00230   this->v[0] = this->v[1] = this->v[2] = Tvec3<DT>(val);
00231 }
00232 
00234 template <class DT>
00235 inline const Tmat3<DT>  &Tmat3<DT>::operator=(const Tmat3<DT> &m)
00236 {
00237   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::operator=(const Tmat3<DT> &m)");
00238   
00239   if (&m != this){   
00240     this->v[0] = m.v[0]; 
00241     this->v[1] = m.v[1]; 
00242     this->v[2] = m.v[2];
00243   }
00244   
00245   return *this;
00246 }
00247 
00249 template <class DT>
00250 inline const Tmat3<DT>  &Tmat3<DT>::operator+=(const Tmat3<DT> &m)
00251 {
00252   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::operator+=(const Tmat3<DT> &m)");
00253   
00254   this->v[0] += m.v[0]; 
00255   this->v[1] += m.v[1]; 
00256   this->v[2] += m.v[2];
00257   
00258   return *this;
00259 }
00260 
00262 template <class DT>
00263 inline const Tmat3<DT>  &Tmat3<DT>::operator-=(const Tmat3<DT> &m)
00264 {
00265   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::operator-=(const Tmat3<DT> &m)");
00266   
00267   this->v[0] -= m.v[0]; 
00268   this->v[1] -= m.v[1]; 
00269   this->v[2] -= m.v[2];
00270   
00271   return *this;
00272 }
00273 
00275 template <class DT>
00276 inline const Tmat3<DT>  &Tmat3<DT>::operator*=(const DT d)
00277 {
00278   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::operator*=(const DT d)");
00279   
00280   this->v[0] *= d; 
00281   this->v[1] *= d; 
00282   this->v[2] *= d;
00283   
00284   return *this;
00285 }
00286 
00288 template <class DT>
00289 inline const Tmat3<DT>  &Tmat3<DT>::operator/=(const DT d)
00290 {
00291   ML_TRACE_IN("Tmat3<DT>::operator/=(const DT d)");
00292   ML_TRY
00293   {
00294     this->v[0] /= d; 
00295     this->v[1] /= d; 
00296     this->v[2] /= d;
00297   }
00298   ML_CATCH_RETHROW;
00299   return *this;
00300 }
00302 
00303 
00304 //====================================================================
00306 
00307 //====================================================================
00309 template <class DT>
00310 inline Tmat3<DT> operator-(const Tmat3<DT> &a)
00311 {
00312   ML_TRACE_IN_TIME_CRITICAL("mlMatrix3.h: operator-(const Tmat3<DT> &a)");
00313   
00314   return Tmat3<DT>(a) *= static_cast<DT>(-1.0);
00315 }
00316 
00318 template <class DT>
00319 inline Tmat3<DT> operator+(const Tmat3<DT> &a, const Tmat3<DT> &b)
00320 {
00321   ML_TRACE_IN_TIME_CRITICAL("mlMatrix3.h: operator+(const Tmat3<DT> &a, const Tmat3<DT> &b)");
00322   
00323   return Tmat3<DT>(a) += b;
00324 }
00325 
00327 template <class DT>
00328 inline Tmat3<DT> operator-(const Tmat3<DT> &a, const Tmat3<DT> &b)
00329 {
00330   ML_TRACE_IN_TIME_CRITICAL("mlMatrix3.h: operator-(const Tmat3<DT> &a, const Tmat3<DT> &b)");
00331   
00332   return Tmat3<DT>(a) -= b;
00333 }
00334 
00336 template <class DT>
00337 inline Tmat3<DT> operator*(const Tmat3<DT> &a, const DT d)
00338 {
00339   ML_TRACE_IN_TIME_CRITICAL("mlMatrix3.h: operator*(const Tmat3<DT> &a, const DT d)");
00340   
00341   return Tmat3<DT>(a) *= d;
00342 }
00343 
00345 template <class DT>
00346 inline Tmat3<DT> operator*(const DT d, const Tmat3<DT> &a)
00347 {
00348   ML_TRACE_IN_TIME_CRITICAL("mlMatrix3.h: operator*(const DT d, const Tmat3<DT> &a)");
00349   
00350   return Tmat3<DT>(a) *= d;
00351 }
00352 
00355 template <class DT>
00356 inline Tmat3<DT> operator/(const Tmat3<DT>  &a, const DT d)
00357 {
00358   ML_TRACE_IN_TIME_CRITICAL("mlMatrix3.h: operator/(const Tmat3<DT>  &a, const DT d)");
00359   
00360   Tmat3<DT> retVal(a);
00361   ML_TRY
00362   {
00363     retVal /= d;
00364   }
00365   ML_CATCH_RETHROW;
00366   return retVal;
00367 }
00369 
00370 
00371 //-------------------------------------------------------------------
00372 //
00374 
00375 //
00376 //-------------------------------------------------------------------
00377 
00378 //-------------------------------------------------------------------
00381 //-------------------------------------------------------------------
00382 template <class DT>
00383 inline Tmat3<DT>::Tmat3(const double in00, const double in01, const double in02,
00384                         const double in10, const double in11, const double in12,
00385                         const double in20, const double in21, const double in22)
00386 {
00387   ML_TRACE_IN("Tmat3<DT>::Tmat3( )");
00388   
00389   this->v[0][0]=static_cast<DT>(in00); this->v[0][1]=static_cast<DT>(in01); this->v[0][2]=static_cast<DT>(in02);
00390   this->v[1][0]=static_cast<DT>(in10); this->v[1][1]=static_cast<DT>(in11); this->v[1][2]=static_cast<DT>(in12);
00391   this->v[2][0]=static_cast<DT>(in20); this->v[2][1]=static_cast<DT>(in21); this->v[2][2]=static_cast<DT>(in22);
00392 }
00393 
00394 
00395 //--------------------------------------------------------------------
00397 //--------------------------------------------------------------------
00398 template <class DT>
00399 inline void Tmat3<DT>::setValues(const float mat[9])
00400 {
00401   ML_TRACE_IN("Tmat3<DT>::setValues( )");
00402   ML_TRY
00403   {
00404     this->v[0][0] = static_cast<DT>(mat[0]); this->v[0][1] = static_cast<DT>(mat[1]); this->v[0][2] = static_cast<DT>(mat[2]);
00405     this->v[1][0] = static_cast<DT>(mat[3]); this->v[1][1] = static_cast<DT>(mat[4]); this->v[1][2] = static_cast<DT>(mat[5]);
00406     this->v[2][0] = static_cast<DT>(mat[6]); this->v[2][1] = static_cast<DT>(mat[7]); this->v[2][2] = static_cast<DT>(mat[8]);
00407   }
00408   ML_CATCH_RETHROW;
00409 }
00410 
00411 //--------------------------------------------------------------------
00415 //--------------------------------------------------------------------
00416 template <class DT>
00417 inline void Tmat3<DT>::getValues(float mat[9]) const
00418 {
00419   ML_TRACE_IN("Tmat3<DT>::setValues( )");
00420   ML_TRY
00421   {
00422     mat[0] = static_cast<float>(this->v[0][0]); mat[1] = static_cast<float>(this->v[0][1]); mat[2] = static_cast<float>(this->v[0][2]);
00423     mat[3] = static_cast<float>(this->v[1][0]); mat[4] = static_cast<float>(this->v[1][1]); mat[5] = static_cast<float>(this->v[1][2]);
00424     mat[6] = static_cast<float>(this->v[2][0]); mat[7] = static_cast<float>(this->v[2][1]); mat[8] = static_cast<float>(this->v[2][2]);
00425   }
00426   ML_CATCH_RETHROW;
00427 }
00428 
00429 //--------------------------------------------------------------------
00431 //--------------------------------------------------------------------
00432 template <class DT>
00433 inline void Tmat3<DT>::setValues(const double mat[9])
00434 {
00435   ML_TRACE_IN("Tmat3<DT>::setValues( )");
00436   ML_TRY
00437   {
00438     this->v[0][0] = static_cast<DT>(mat[0]); this->v[0][1] = static_cast<DT>(mat[1]); this->v[0][2] = static_cast<DT>(mat[2]);
00439     this->v[1][0] = static_cast<DT>(mat[3]); this->v[1][1] = static_cast<DT>(mat[4]); this->v[1][2] = static_cast<DT>(mat[5]);
00440     this->v[2][0] = static_cast<DT>(mat[6]); this->v[2][1] = static_cast<DT>(mat[7]); this->v[2][2] = static_cast<DT>(mat[8]);
00441   }
00442   ML_CATCH_RETHROW;
00443 }
00444 
00445 //--------------------------------------------------------------------
00449 //--------------------------------------------------------------------
00450 template <class DT>
00451 inline void Tmat3<DT>::getValues(double mat[9]) const
00452 {
00453   ML_TRACE_IN("Tmat3<DT>::setValues( )");
00454   ML_TRY
00455   {
00456     mat[0] = static_cast<double>(this->v[0][0]); mat[1] = static_cast<double>(this->v[0][1]); mat[2] = static_cast<double>(this->v[0][2]);
00457     mat[3] = static_cast<double>(this->v[1][0]); mat[4] = static_cast<double>(this->v[1][1]); mat[5] = static_cast<double>(this->v[1][2]);
00458     mat[6] = static_cast<double>(this->v[2][0]); mat[7] = static_cast<double>(this->v[2][1]); mat[8] = static_cast<double>(this->v[2][2]);
00459   }
00460   ML_CATCH_RETHROW;
00461 }
00462 
00463 
00464 //-------------------------------------------------------------------
00466 //-------------------------------------------------------------------
00467 template <class DT>
00468 inline void Tmat3<DT>::setScaleMatrix(const DT scale)
00469 {
00470   ML_TRACE_IN("Tmat3<DT>::setScaleMatrix( )");
00471   
00472   this->v[0][0]=scale; this->v[0][1]=0;     this->v[0][2]=0;
00473   this->v[1][0]=0;     this->v[1][1]=scale; this->v[1][2]=0;
00474   this->v[2][0]=0;     this->v[2][1]=0;     this->v[2][2]=scale;
00475 }
00477 
00478 
00479 //-------------------------------------------------------------------
00481 
00482 //-------------------------------------------------------------------
00483 
00485 #define DET3(A,B,C,D,E,F,G,H,I) ((A*E*I + B*F*G + C*D*H) - (A*F*H + B*D*I + C*E*G))
00486 //-------------------------------------------------------------------
00488 //-------------------------------------------------------------------
00489 template <class DT>
00490 DT Tmat3<DT>::det() const
00491 {
00492   ML_TRACE_IN("Tmat3<DT>::det( )");
00493   
00494   return DET3(this->v[0][0], this->v[0][1], this->v[0][2],
00495               this->v[1][0], this->v[1][1], this->v[1][2],
00496               this->v[2][0], this->v[2][1], this->v[2][2]);
00497 }
00498 #undef DET3
00499 
00500 //-------------------------------------------------------------------
00502 //-------------------------------------------------------------------
00503 template <class DT>
00504 inline Tmat3<DT> Tmat3<DT>::transpose() const
00505 {
00506   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::transpose()");
00507   
00508   return Tmat3<DT>(Tvec3<DT>(this->v[0][0], this->v[1][0], this->v[2][0]),
00509                    Tvec3<DT>(this->v[0][1], this->v[1][1], this->v[2][1]),
00510                    Tvec3<DT>(this->v[0][2], this->v[1][2], this->v[2][2]));
00511 }
00512 
00513 //-------------------------------------------------------------------
00515 //-------------------------------------------------------------------
00516 template <class DT>
00517 inline Tmat3<DT> Tmat3<DT>::getIdentity()
00518 {
00519   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::getIdentity()");
00520   
00521   return Tmat3<DT>(Tvec3<DT>(1,0,0),
00522                    Tvec3<DT>(0,1,0),
00523                    Tvec3<DT>(0,0,1));
00524 }
00525 
00526 //-------------------------------------------------------------------
00528 //-------------------------------------------------------------------
00529 template <class DT>
00530 inline const Tmat3<DT>  &Tmat3<DT>::apply(MLDblFuncPtr fct)
00531 {
00532   ML_TRACE_IN_TIME_CRITICAL("Tmat3<DT>::apply(MLDblFuncPtr fct)");
00533   ML_TRY
00534   {
00535     this->v[0].apply(fct);
00536     this->v[1].apply(fct);
00537     this->v[2].apply(fct);
00538   }
00539   ML_CATCH_RETHROW;
00540   return *this;
00541 }
00542 
00544 #define _ML_MAT3_RC(i, j) a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j]
00545 //-------------------------------------------------------------------
00547 //-------------------------------------------------------------------
00548 template <class DT>
00549 inline Tmat3<DT> operator*(const Tmat3<DT> &a, const Tmat3<DT> &b)
00550 {
00551   ML_TRACE_IN_TIME_CRITICAL("mlMatrix3.h: operator*(const Tmat3<DT> &a, const Tmat3<DT> &b)");
00552   
00553   return Tmat3<DT>(Tvec3<DT>(_ML_MAT3_RC(0,0), _ML_MAT3_RC(0,1), _ML_MAT3_RC(0,2)),
00554                    Tvec3<DT>(_ML_MAT3_RC(1,0), _ML_MAT3_RC(1,1), _ML_MAT3_RC(1,2)),
00555                    Tvec3<DT>(_ML_MAT3_RC(2,0), _ML_MAT3_RC(2,1), _ML_MAT3_RC(2,2)));
00556   
00557 }
00558 #undef _ML_MAT3_RC
00559 
00560 //-------------------------------------------------------------------
00562 //-------------------------------------------------------------------
00563 template <class DT>
00564 inline bool operator==(const Tmat3<DT> &a, const Tmat3<DT> &b)
00565 {
00566   ML_TRACE_IN_TIME_CRITICAL("mlMatrix3.h: operator==(const Tmat3<DT> &a, const Tmat3<DT> &b)");
00567   
00568   return (a[0] == b[0]) &&
00569   (a[1] == b[1]) &&
00570   (a[2] == b[2]);
00571 }
00572 
00573 //-------------------------------------------------------------------
00575 //-------------------------------------------------------------------
00576 template <class DT>
00577 inline bool operator!=(const Tmat3<DT> &a, const Tmat3<DT> &b)
00578 {
00579   ML_TRACE_IN_TIME_CRITICAL("mlMatrix3.h: operator!=(const Tmat3<DT> &a, const Tmat3<DT> &b)");
00580   
00581   return !(a == b);
00582 }
00583 
00584 //-------------------------------------------------------------------
00585 //
00586 //       Special global 2D functions and 3D functions
00587 //
00588 //-------------------------------------------------------------------
00589 
00590 //--------------------------------------------------------------------
00593 //--------------------------------------------------------------------
00594 template <class DT>
00595 Tmat3<DT> identity2D()
00596 {
00597   ML_TRACE_IN_TIME_CRITICAL("mlMatrix3.h: identity2D()");
00598   
00599   return Tmat3<DT>::getIdentity();
00600 }
00601 
00602 //-------------------------------------------------------------------
00605 //-------------------------------------------------------------------
00606 template <class DT>
00607 inline Tmat3<DT> translation2D(const Tvec2<DT> &v)
00608 {
00609   ML_TRACE_IN("mlMatrix3.h: translation2D(const Tvec2<DT> &v)");
00610   
00611   return Tmat3<DT>(Tvec3<DT>(1.0, 0.0, v[0]),
00612                    Tvec3<DT>(0.0, 1.0, v[1]),
00613                    Tvec3<DT>(0.0, 0.0, 1.0));
00614 }
00615 
00616 //-------------------------------------------------------------------
00619 //-------------------------------------------------------------------
00620 template <class DT>
00621 Tmat3<DT> rotation2D(const Tvec2<DT> &Center, const DT angleDeg)
00622 {
00623   ML_TRACE_IN("mlMatrix3.h: rotation2D(const Tvec2<DT> &Center, const DT angleDeg)");
00624   
00625   DT  angleRad = angleDeg * M_PI / 180.0;
00626   DT  c = cos(angleRad);
00627   DT  s = sin(angleRad);
00628   
00629   return Tmat3<DT>(Tvec3<DT>(c, -s, Center[0] * (1.0-c) + Center[1] * s),
00630                    Tvec3<DT>(s,  c, Center[1] * (1.0-c) - Center[0] * s),
00631                    Tvec3<DT>(0.0, 0.0, 1.0));
00632 }
00633 
00634 //-------------------------------------------------------------------
00636 //-------------------------------------------------------------------
00637 template <class DT>
00638 inline Tmat3<DT> scaling2D(const Tvec2<DT> &scaleVector)
00639 {
00640   ML_TRACE_IN("mlMatrix3.h: scaling2D(const Tvec2<DT> &scaleVector)");
00641   
00642   return Tmat3<DT>(Tvec3<DT>(scaleVector[0], 0.0, 0.0),
00643                    Tvec3<DT>(0.0, scaleVector[1], 0.0),
00644                    Tvec3<DT>(0.0, 0.0, 1.0));
00645 }
00646 
00647 
00648 
00649 //-------------------------------------------------------------------
00661 //-------------------------------------------------------------------
00662 template <class DT>
00663 Tmat3<DT> Tmat3<DT>::jacobi(Tvec3<DT> &evalues, int &rots) const
00664 {
00665   ML_TRACE_IN("Tmat3<DT>::jacobi( )");
00666   
00667   Tmat3<DT> evectors (getIdentity());
00668   ML_TRY
00669   {
00670     // TODO: Further documentation of the algorithm required!
00671     
00672     DT  sm = 0;               // smallest entry
00673     DT  theta = 0;            // angle for Jacobi rotation
00674     DT  c = 0, s = 0, t = 0;  // cosine, sine, tangent of theta
00675     DT  tau = 0;              // sine / (1 + cos)
00676     DT  h = 0, g = 0;         // two scrap values
00677     DT  thresh = 0;           // threshold below which no rotation done
00678     
00679     int   p = 0, q = 0, i = 0, j = 0;
00680     
00681     // Initialization
00682     Tvec3<DT> b (this->v[0][0], this->v[1][1], this->v[2][2]);      // diagonal elements
00683     Tvec3<DT> z (0, 0, 0);
00684     evalues = b;
00685     
00686     Tmat3<DT> a (*this);
00687     
00688     rots = 0;
00689     for (i = 0; i < 50; i++){           // typical matrices require 6 to 10 sweeps to achieve convergence - hence 50 gives some safety margin
00690       sm = 0.0;
00691       for (p = 0; p < 2; p++){
00692         for (q = p+1; q < 3; q++){
00693           sm += ML_ABS(a.v[p][q]);         // sum off-diagonal elements
00694         }
00695       }
00696       
00697       if (sm == 0.0){
00698         return evectors;
00699       }
00700       
00701       thresh = (i < 3 ? (.2 * sm / 9) : 0.0);
00702       
00703       for (p = 0; p < 2; p++) {
00704         for (q = p+1; q < 3; q++) {    // compute on sweep, i.e. one rotation for each of-diagonal element of the matrix
00705           
00706           g = 100.0 * ML_ABS(a.v[p][q]);
00707           
00708           if ((i > 3) && 
00709               (ML_ABS(evalues[p]) + g == ML_ABS(evalues[p])) &&
00710               (ML_ABS(evalues[q]) + g == ML_ABS(evalues[q]))){
00711             a.v[p][q] = 0.0;          // after three sweeps, skip rotation of small off diagonal elements
00712           }
00713           else if (ML_ABS(a.v[p][q]) > thresh) {
00714             h = evalues[q] - evalues[p];
00715             if (ML_ABS(h) + g == ML_ABS(h)){
00716               t = a.v[p][q] / h;
00717             }
00718             else {
00719               theta = .5 * h / a.v[p][q];
00720               t = 1.0 / (ML_ABS(theta) + sqrt(1 + theta * theta));
00721               if (theta < 0.0){  
00722                 t = -t;
00723               }
00724             }
00725             // End of computing tangent of rotation angle
00726             
00727             c = 1.0 / sqrt(1.0 + t*t);
00728             s = t * c;
00729             tau = s / (1.0 + c);
00730             h = t * a.v[p][q];
00731             z[p]    -= h;
00732             z[q]    += h;
00733             evalues[p] -= h;
00734             evalues[q] += h;
00735             a.v[p][q] = 0.0;
00736             
00737             for (j = 0; j < p; j++) {
00738               g = a.v[j][p];
00739               h = a.v[j][q];
00740               a.v[j][p] = g - s * (h + g * tau);
00741               a.v[j][q] = h + s * (g - h * tau);
00742             }
00743             
00744             for (j = p+1; j < q; j++) {
00745               g = a.v[p][j];
00746               h = a.v[j][q];
00747               a.v[p][j] = g - s * (h + g * tau);
00748               a.v[j][q] = h + s * (g - h * tau);
00749             }
00750             
00751             for (j = q+1; j < 3; j++) {
00752               g = a.v[p][j];
00753               h = a.v[q][j];
00754               a.v[p][j] = g - s * (h + g * tau);
00755               a.v[q][j] = h + s * (g - h * tau);
00756             }
00757             
00758             for (j = 0; j < 3; j++) {
00759               g = evectors.v[j][p];
00760               h = evectors.v[j][q];
00761               evectors.v[j][p] = g - s * (h + g * tau);
00762               evectors.v[j][q] = h + s * (g - h * tau);
00763             }
00764           } // else if (ML_ABS(a.v[p][q]) > thresh)
00765           
00766           rots++;
00767           
00768         } // for (q = p+1; q < 3; q++) 
00769       } // for (p = 0; p < 2; p++) 
00770       
00771       for (p = 0; p < 3; p++) {
00772         evalues[p] = b[p] += z[p];
00773         z[p] = 0;
00774       }
00775       
00776     } // for (i = 0; i < 50; i++)
00777     ML_PRINT_ERROR("Tmat3 Tmat3<DT>::jacobi(Tvec3<DT> &evalues, int &rots) const, matrix not complete decomposed", 
00778                    ML_BAD_PARAMETER, 
00779                    "Returning incomplete decomposition");
00780   }
00781   ML_CATCH_RETHROW;
00782   return evectors;
00783 }
00784 
00785 //-------------------------------------------------------------------
00793 //-------------------------------------------------------------------
00794 template <class DT>
00795 Tmat3<DT> Tmat3<DT>::inverse(bool* isInvertible) const
00796 {
00797   ML_TRACE_IN("Tmat3<DT>::inverse( )");
00798   
00799   Tmat3<DT> retVal;
00800   ML_TRY
00801   {
00802     // Epsilon for comparison with 0 in inversion process.
00803     static const DT Epsilon = static_cast<DT>(0.);
00804     
00805     // Use helper function from tools to invert the matrix.
00806     retVal = MLInverseMatHelper(*this,
00807                                 isInvertible, 
00808                                 Epsilon,
00809                                 "Tmat3<DT> Tmat3<DT>::inverse(bool* isInvertible) const, matrix not invertable",
00810                                 getIdentity(),
00811                                 3);
00812   }
00813   ML_CATCH_RETHROW;
00814   return retVal;
00815 }
00816 
00817 //-----------------------------------------------------------------------------------
00819 
00820 //-----------------------------------------------------------------------------------
00821 
00823 typedef Tmat3<MLfloat>   Matrix3f;
00825 typedef Tmat3<MLdouble>  Matrix3d;
00827 typedef Tmat3<MLldouble> Matrix3ld;
00829 typedef Tmat3<MLdouble>  Matrix3;
00831 
00832 
00833 #ifdef ML_DEPRECATED
00834 
00836 
00837 
00841 ML_DEPRECATED typedef Tmat3<MLfloat>   matf3;
00845 ML_DEPRECATED typedef Tmat3<MLdouble>  matd3;
00849 ML_DEPRECATED typedef Tmat3<MLldouble> matld3;
00853 ML_DEPRECATED typedef Tmat3<MLdouble> mat3;
00855 
00856 
00857 #endif // ML_DEPRECATED
00858 
00859 
00860 
00861 ML_LA_END_NAMESPACE
00862 
00863 namespace std
00864 {
00865   //-------------------------------------------------------------------
00867   //-------------------------------------------------------------------
00868   template <class DT>
00869   inline std::ostream &operator<<(std::ostream &os, const ML_LA_NAMESPACE::Tmat3<DT> &m)
00870   {
00871     return os << m[0] << '\n' << m[1] << '\n' << m[2];
00872   }
00873   
00874   //-------------------------------------------------------------------
00876   //-------------------------------------------------------------------
00877   template <class DT>
00878   inline std::istream &operator>>(std::istream &is, ML_LA_NAMESPACE::Tmat3<DT> &m)
00879   {
00880     ML_LA_NAMESPACE::Tmat3<DT> m_tmp;
00881     
00882     is >> m_tmp[0] >> m_tmp[1] >> m_tmp[2];
00883     if (is){ m = m_tmp; }
00884     return is;
00885   }
00886 }
00887 
00888 
00889 #endif // __mlMatrix3_H
00890 
00891