ML Reference
|
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