ML Reference
MeVis/Foundation/Sources/MLLinearAlgebra/mlMatrix2.h
Go to the documentation of this file.
00001 // **InsertLicense** code 
00002 //=====================================================================================
00004 
00009 //=====================================================================================
00010 
00011 #ifndef __mlMatrix2_H
00012 #define __mlMatrix2_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 
00022 
00023 #ifndef __mlFloatingPointMatrix_H
00024 #include "mlFloatingPointMatrix.h"
00025 #endif
00026 
00027 #ifndef __mlVector2_H
00028 #include "mlVector2.h"
00029 #endif
00030 
00031 // All declarations of this header will be in the namespace of mlLinearAlgebra.
00032 ML_LA_START_NAMESPACE
00033 
00034 //---------------------------------------------------------------
00036 //---------------------------------------------------------------
00037 template <class DT>
00038 class Tmat2 : public FloatingPointMatrix<Tvec2<DT>, 2>
00039 {
00040 public:
00041   
00043   typedef DT ComponentType;
00044   
00045   //---------------------------------------------------------------
00046   // Constructors, set and get methods.
00047   //---------------------------------------------------------------
00048   // Construct matrix from 4 zero elements.
00049   Tmat2();
00050 
00051   // Construct matrix that has the argument at the diagonal values, zero otherwise
00052   Tmat2(const DT diagValue);
00053 
00054   // Composes a matrix from the two row vectors row0 and row1.
00055   Tmat2(const Tvec2<DT>& row0, 
00056         const Tvec2<DT>& row1);
00057   
00058   // Copy constructor from the Tmat2 mat.
00059   Tmat2(const Tmat2<DT>& mat);
00060   
00061   // Constructor from 4 floating point values in an array given by mat, row by row.
00062   Tmat2(const float mat[4]);
00063   
00064   // Constructor from 4 double values in an array given by mat, row by row.
00065   Tmat2(const double mat[4]);
00066   
00067   // Initialize all matrix elements explicitly with scalars,
00068   // filling it row by row.
00069   Tmat2(const DT in00, const DT in01,
00070         const DT in10, const DT in11);
00071   
00072   // Copy contents from float array mat into *this, row by row.
00073   void setValues(const float mat[4]);
00074   
00075   // Copy contents of *this into float array mat, row by row.
00076   // Note that range and precision of the float values may not be
00077   // sufficient for the DT matrix contents, written row by row.
00078   void getValues(float mat[4]) const;
00079   
00080   // Copy contents from DT array mat into *this, row by row.
00081   void setValues(const double mat[4]);
00082   
00083   // Copy contents of *this into DT array mat, row by row.
00084   void getValues(double mat[4]) const;
00085   
00086   // Return a matrix filled with values val.
00087   static Tmat2<DT> getMat(const DT val);
00088   
00089   // Set all values to val.
00090   void set(const DT val);
00091   
00092   // Return identity matrix. 
00093   static Tmat2<DT> getIdentity();
00094   
00095   // Set diagonal matrix with scale on diagonal.
00096   void setScaleMatrix(const DT scale);
00097   
00098   
00099   //---------------------------------------------------------------
00100   // Operators and indexing functionality.
00101   //---------------------------------------------------------------
00104   bool operator<(const Tmat2<DT> &) const { return false; }
00105   
00106   // Assignment from a Tmat2.
00107   const Tmat2<DT>& operator=(const Tmat2<DT>& m);
00108   
00109   // Incrementation by a Tmat2.
00110   const Tmat2<DT>& operator+=(const Tmat2<DT>& m);
00111   
00112   // Decrement by a Tmat2.
00113   const Tmat2<DT>& operator-=(const Tmat2<DT>& m);
00114   
00115   // Multiplication by a constant d.
00116   const Tmat2<DT>& operator*=(const DT d);
00117   
00118   // Division by a constant d. Division by zero is not handled and must be avoided by caller.
00119   const Tmat2<DT>& operator/=(const DT d);
00120   
00121   
00122   //---------------------------------------------------------------
00123   // Special functions
00124   //---------------------------------------------------------------
00125   // Determinant.
00126   DT det() const;
00127   
00128   // Transpose.
00129   Tmat2<DT> transpose() const;
00130   
00131   // Returns the inverse. 
00132   // If a non-NULL Boolean pointer is passed to isInvertible 
00133   // then true is returned in *isInvertible in the case of a 
00134   // successful inversion or false if the inversion is not possible
00135   // (function return is the identity then).
00136   // If a NULL pointer is passed as isInvertible the matrix must
00137   // be invertible, otherwise errors will occur.
00138   Tmat2<DT> inverse(bool* isInvertible=NULL) const;
00139   
00140   // Apply the function fct to each component.
00141   const Tmat2<DT>& apply(MLDblFuncPtr fct);
00142   
00143 }; // end of class *Tmat2*
00144 
00145 
00146 
00147 //---------------------------------------------------------------
00149 
00150 //---------------------------------------------------------------
00152 template <class DT>
00153 inline Tmat2<DT>::Tmat2()
00154 {
00155   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::Tmat2()");
00156   
00157   this->v[0] = this->v[1] = Tvec2<DT>(0);
00158 }
00159 
00160 // Construct matrix that has the argument at the diagonal values, zero otherwise
00161 template <class DT>
00162 inline Tmat2<DT>::Tmat2(const DT diagValue)
00163 {
00164   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::Tmat2(diagValue)");
00165   
00166   this->v[0][0] = this->v[1][1] = diagValue;
00167   this->v[1][0] = this->v[0][1] = 0;
00168 }
00169 
00170 
00172 template <class DT>
00173 inline Tmat2<DT>::Tmat2(const Tvec2<DT>& row0, 
00174                         const Tvec2<DT>& row1)
00175 {
00176   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::Tmat2(row1, row2)");
00177   
00178   this->v[0] = row0;
00179   this->v[1] = row1;
00180 }
00181 
00183 template <class DT>
00184 inline Tmat2<DT>::Tmat2(const Tmat2<DT>& mat)
00185 {
00186   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::Tmat2(const Tmat2<DT>& mat)");
00187   
00188   this->v[0] = mat.v[0];
00189   this->v[1] = mat.v[1];
00190 }
00191 
00193 template <class DT>
00194 inline Tmat2<DT>::Tmat2(const float mat[4])
00195 {
00196   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::Tmat2(const float mat[4])");
00197   
00198   setValues(mat);
00199 }
00200 
00202 template <class DT>
00203 inline Tmat2<DT>::Tmat2(const double mat[4])
00204 {
00205   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::Tmat2(const double mat[4])");
00206   
00207   setValues(mat);
00208 }
00209 
00211 template <class DT>
00212 inline Tmat2<DT>::Tmat2(const DT in00, const DT in01,
00213                         const DT in10, const DT in11)
00214 {
00215   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::Tmat2(in00, in01, in10, in11)");
00216   
00217   this->v[0][0] = in00; this->v[0][1] = in01;
00218   this->v[1][0] = in10; this->v[1][1] = in11;
00219 }
00220 
00222 template <class DT>
00223 inline void Tmat2<DT>::setValues(const float mat[4])
00224 {
00225   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::setValues(const float mat[4])");
00226   ML_TRY
00227   {
00228     this->v[0][0] = static_cast<DT>(mat[0]); this->v[0][1] = static_cast<DT>(mat[1]);
00229     this->v[1][0] = static_cast<DT>(mat[2]); this->v[1][1] = static_cast<DT>(mat[3]);
00230   }
00231   ML_CATCH_RETHROW;
00232 }
00233 
00235 template <class DT>
00236 inline void Tmat2<DT>::setValues(const double mat[4])
00237 {
00238   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::setValues(const double mat[4])");
00239   ML_TRY
00240   {
00241     this->v[0][0] = static_cast<DT>(mat[0]); this->v[0][1] = static_cast<DT>(mat[1]);
00242     this->v[1][0] = static_cast<DT>(mat[2]); this->v[1][1] = static_cast<DT>(mat[3]);
00243   }
00244   ML_CATCH_RETHROW;
00245 }
00246 
00250 template <class DT>
00251 inline void Tmat2<DT>::getValues(float mat[4]) const
00252 {
00253   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::getValues(float mat[4])");
00254   ML_TRY
00255   {
00256     mat[0] = static_cast<float>(this->v[0][0]); mat[1] = static_cast<float>(this->v[0][1]);
00257     mat[2] = static_cast<float>(this->v[1][0]); mat[3] = static_cast<float>(this->v[1][1]);
00258   }
00259   ML_CATCH_RETHROW;
00260 }
00261 
00265 template <class DT>
00266 inline void Tmat2<DT>::getValues(double mat[4]) const
00267 {
00268   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::getValues(double mat[4])");
00269   ML_TRY
00270   {
00271     mat[0] = static_cast<double>(this->v[0][0]); mat[1] = static_cast<double>(this->v[0][1]);
00272     mat[2] = static_cast<double>(this->v[1][0]); mat[3] = static_cast<double>(this->v[1][1]);
00273   }
00274   ML_CATCH_RETHROW;
00275 }
00276 
00278 template <class DT>
00279 inline Tmat2<DT> Tmat2<DT>::getMat(const DT val)
00280 {
00281   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::getMat()");
00282   
00283   return Tmat2(val, val,
00284                val, val);
00285 }
00286 
00288 template <class DT>
00289 inline void Tmat2<DT>::set(const DT val)
00290 {
00291   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::set()");
00292   
00293   this->v[0] = this->v[1] = Tvec2<DT>(val);
00294 }
00295 
00297 template <class DT>
00298 inline Tmat2<DT> Tmat2<DT>::getIdentity()
00299 {
00300   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::getIdentity()");
00301   
00302   return Tmat2<DT>(1, 0, 0, 1);
00303 }
00304 
00306 template <class DT>
00307 inline void Tmat2<DT>::setScaleMatrix(const DT scale)
00308 {
00309   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::setScaleMatrix(const DT scale)");
00310   
00311   this->v[0][0] = scale; this->v[0][1] = 0; 
00312   this->v[1][0] = 0;     this->v[1][1] = scale;
00313 }
00315 
00316 
00317 
00318 
00319 //---------------------------------------------------------------
00321 
00322 //---------------------------------------------------------------
00324 template <class DT>
00325 inline DT Tmat2<DT>::det() const
00326 {
00327   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::det()");
00328   
00329   return this->v[0][0]*this->v[1][1] - this->v[0][1]*this->v[1][0];
00330 }
00331 
00333 template <class DT>
00334 inline Tmat2<DT> Tmat2<DT>::transpose() const
00335 {
00336   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::transpose()");
00337   
00338   return Tmat2<DT>(Tvec2<DT>(this->v[0][0], this->v[1][0]), 
00339                    Tvec2<DT>(this->v[0][1], this->v[1][1]));
00340 }
00341 
00343 template <class DT>
00344 inline const Tmat2<DT>& Tmat2<DT>::apply(MLDblFuncPtr fct)
00345 {
00346   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::apply(MLDblFuncPtr fct)");
00347   
00348   this->v[0].apply(fct);
00349   this->v[1].apply(fct);
00350   return *this;
00351 }
00352 
00353 //--------------------------------------------------------------------
00354 // Returns the inverse. 
00355 // If a non-NULL Boolean pointer is passed to isInvertible 
00356 // then true is returned in *isInvertible in the case of a 
00357 // successful inversion or false if the inversion is not possible
00358 // (function return is the identity then).
00359 // If a NULL pointer is passed as isInvertible the matrix must
00360 // be invertible, otherwise errors will occur.
00361 //--------------------------------------------------------------------
00362 template <class DT>
00363 Tmat2<DT> Tmat2<DT>::inverse(bool* isInvertible) const
00364 {
00365   ML_TRACE_IN("Tmat2<DT>::inverse( )");
00366   
00367   // Matrix to be returned.
00368   Tmat2<DT> retMat;
00369   ML_TRY
00370   {
00371     // Determinant must be non-zero.
00372     DT determinant = det();
00373     if (MLValueIs0WOM(determinant)) {
00374       if (isInvertible == NULL){
00375         ML_PRINT_ERROR("Tmat2<DT> Tmat2<DT>::inverse() const, matrix not invertible",
00376                        ML_BAD_PARAMETER,
00377                        "Returning identity");
00378       }
00379       else{
00380         *isInvertible = false;
00381       }
00382       retMat = getIdentity();
00383     }
00384     else{
00385       // Get inverse to reduce number of expensive divisions.
00386       determinant = (static_cast<DT>(1))/determinant;
00387       retMat[0][0] =  static_cast<DT>(this->v[1][1]*determinant);
00388       
00389       retMat[1][0] =  this->v[1][0];
00390       retMat[1][0] *= static_cast<DT>(-determinant);
00391       
00392       retMat[0][1] =  this->v[0][1];
00393       retMat[0][1] *= static_cast<DT>(-determinant);
00394       
00395       retMat[1][1] =  static_cast<DT>(this->v[0][0]*determinant);
00396       
00397       // Set state and return inverse.
00398       if (isInvertible != NULL){ *isInvertible = true; }
00399     }
00400   }
00401   ML_CATCH_RETHROW;
00402   return retMat;
00403 }
00405 
00406 
00407 
00408 //---------------------------------------------------------------
00410 
00411 //---------------------------------------------------------------
00413 template <class DT>
00414 inline const Tmat2<DT>& Tmat2<DT>::operator=(const Tmat2<DT>& m)
00415 {
00416   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::operator=(const Tmat2<DT>& m)");
00417   
00418   if (&m != this){
00419     this->v[0] = m.v[0];
00420     this->v[1] = m.v[1];
00421   }
00422   return *this;
00423 }
00424 
00426 template <class DT>
00427 inline const Tmat2<DT>& Tmat2<DT>::operator+=(const Tmat2<DT>& m)
00428 {
00429   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::operator+=(const Tmat2<DT>& m)");
00430   
00431   this->v[0] += m.v[0];
00432   this->v[1] += m.v[1];
00433   return *this;
00434 }
00435 
00437 template <class DT>
00438 inline const Tmat2<DT>& Tmat2<DT>::operator-=(const Tmat2<DT>& m)
00439 {
00440   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::operator-=(const Tmat2<DT>& )");
00441   
00442   this->v[0] -= m.v[0];
00443   this->v[1] -= m.v[1];
00444   return *this;
00445 }
00446 
00448 template <class DT>
00449 inline const Tmat2<DT>& Tmat2<DT>::operator*=(const DT d)
00450 {
00451   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::operator*=(const DT d)");
00452   
00453   this->v[0] *= d;
00454   this->v[1] *= d;
00455   return *this;
00456 }
00457 
00459 template <class DT>
00460 inline const Tmat2<DT>& Tmat2<DT>::operator/=(const DT d)
00461 {
00462   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>::operator/=(const DT d)");
00463   
00464   ML_TRY
00465   {
00466     this->v[0] /= d;
00467     this->v[1] /= d;
00468   }
00469   ML_CATCH_RETHROW;
00470   return *this;
00471 }
00473 
00474 
00475 
00476 //---------------------------------------------------------------
00477 // Global operators and functions for class Tmat2
00478 //---------------------------------------------------------------
00480 
00481 
00482 #define _ML_MAT2_RC(i, j) a[i][0]*b[0][j] + a[i][1]*b[1][j]
00483 
00484 // a * b. Standard matrix multiplication.
00485 template <class DT>
00486 inline Tmat2<DT> operator*(const Tmat2<DT>& a, const Tmat2<DT>& b)
00487 {
00488   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>.h: operator*(const Tmat2<DT>& a, const Tmat2<DT>& b)");
00489   
00490   return Tmat2<DT>(
00491                    Tvec2<DT>(_ML_MAT2_RC(0,0), _ML_MAT2_RC(0,1)),
00492                    Tvec2<DT>(_ML_MAT2_RC(1,0), _ML_MAT2_RC(1,1))
00493                    );
00494 }
00495 #undef _ML_MAT2_RC
00496 
00498 template <class DT>
00499 inline bool operator==(const Tmat2<DT>& a, const Tmat2<DT>& b)
00500 {
00501   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>.h: operator==(const Tmat2<DT>& a, const Tmat2<DT>& b)");
00502   
00503   return ((a[0] == b[0]) &&
00504           (a[1] == b[1]));
00505 }
00506 
00508 template <class DT>
00509 inline bool operator!=(const Tmat2<DT>& a, const Tmat2<DT>& b)
00510 {
00511   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>.h: operator!=(const Tmat2<DT>& a, const Tmat2<DT>& b)");
00512   
00513   return !(a == b);
00514 }
00516 
00517 
00518 //---------------------------------------------------------------
00520 
00521 //---------------------------------------------------------------
00523 template <class DT>
00524 inline Tmat2<DT> operator-(const Tmat2<DT>& a)
00525 {
00526   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>.h: operator-(const Tmat2<DT>& a)");
00527   
00528   return Tmat2<DT>(a) *= static_cast<DT>(-1.0);
00529 }
00530 
00532 template <class DT>
00533 inline Tmat2<DT> operator+(const Tmat2<DT>& a, const Tmat2<DT>& b)
00534 {
00535   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>.h: operator+(const Tmat2<DT>& a, const Tmat2<DT>& )");
00536   
00537   return Tmat2<DT>(a) += b;
00538 }
00539 
00541 template <class DT>
00542 inline Tmat2<DT> operator-(const Tmat2<DT>& a, const Tmat2<DT>& b)
00543 {
00544   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>.h: operator-(const Tmat2<DT>& a, const Tmat2<DT>& )");
00545   
00546   return Tmat2<DT>(a) -= b;
00547 }
00548 
00550 template <class DT>
00551 inline Tmat2<DT> operator*(const Tmat2<DT>& a, DT d)
00552 {
00553   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>.h: operator*(const Tmat2<DT>& a, DT d)");
00554   
00555   return Tmat2<DT>(a) *= d;
00556 }
00557 
00559 template <class DT>
00560 inline Tmat2<DT> operator*(const DT d, const Tmat2<DT>& a)
00561 {
00562   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>.h: operator*(const DT d, const Tmat2<DT>& a)");
00563   
00564   return Tmat2<DT>(a) *= d;
00565 }
00566 
00569 template <class DT>
00570 inline Tmat2<DT> operator/(const Tmat2<DT>& a, const DT d)
00571 {
00572   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>.h: operator/(const Tmat2<DT>& a, const DT d)");
00573   
00574   Tmat2<DT> divi(a);
00575   ML_TRY
00576   {
00577     divi /= d;
00578   }
00579   ML_CATCH_RETHROW;
00580   return divi;
00581 }
00582 
00585 template <class DT>
00586 inline Tvec2<DT> operator*(const Tmat2<DT>& a, const Tvec2<DT>& v)
00587 {
00588   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>.h: operator*(const Tmat2<DT>& a, const Tvec2<DT>& v)");
00589   
00590   return Tvec2<DT>(a[0][0]*v[0] + a[0][1]*v[1], a[1][0]*v[0] + a[1][1]*v[1]);
00591 }
00592 
00595 template <class DT>
00596 inline Tvec2<DT> operator*(const Tvec2<DT>& v, const Tmat2<DT>& a)
00597 {
00598   ML_TRACE_IN_TIME_CRITICAL("Tmat2<DT>.h: operator*(const Tvec2<DT>& v, const Tmat2<DT>& a)");
00599   
00600   return a.transpose() * v;
00601 }
00603 
00604 //-----------------------------------------------------------------------------------
00606 
00607 //-----------------------------------------------------------------------------------
00608 
00610 typedef Tmat2<MLfloat>   Matrix2f;
00612 typedef Tmat2<MLdouble>  Matrix2d;
00614 typedef Tmat2<MLldouble> Matrix2ld;
00616 typedef Tmat2<MLdouble>  Matrix2;
00618 
00619 
00620 #ifdef ML_DEPRECATED
00621 
00623 
00624 
00628 ML_DEPRECATED typedef Tmat2<MLfloat>   matf2;
00632 ML_DEPRECATED typedef Tmat2<MLdouble>  matd2;
00636 ML_DEPRECATED typedef Tmat2<MLldouble> matld2;
00640 ML_DEPRECATED typedef Tmat2<MLdouble> mat2;
00642 
00643 
00644 #endif // ML_DEPRECATED
00645 
00646 
00647 
00648 ML_LA_END_NAMESPACE
00649 
00650 //-------------------------------------------------------------------
00651 // Support for standard IO streams.
00652 //-------------------------------------------------------------------
00653 namespace std 
00654 {
00656   template <class DT>
00657   inline std::ostream& operator<<(std::ostream& os, const ML_LA_NAMESPACE::Tmat2<DT> &m)
00658   {
00659     return os << m[0] << '\n' << m[1];
00660   }
00661   
00663   template <class DT>
00664   inline std::istream& operator>>(std::istream& is, ML_LA_NAMESPACE::Tmat2<DT>& m)
00665   {
00666     ML_LA_NAMESPACE::Tmat2<DT> m_tmp;
00667     is >> m_tmp[0] >> m_tmp[1];
00668     if (is){ m = m_tmp; }
00669     return is;
00670   }
00671 }
00672 
00673 #endif // __mlMatrix2_H
00674 
00675 
00676