TuttleOFX
1
|
00001 // FROM http://ljk.imag.fr/membres/Pierre.Saramito/rheolef/source_html/ublas-invert_8h-source.html 00002 00003 #ifndef _TUTTLE_COMMON_INVERT_MATRIX_HPP_ 00004 #define _TUTTLE_COMMON_INVERT_MATRIX_HPP_ 00005 // 00006 // The following code inverts the matrix input using LU-decomposition 00007 // with backsubstitution of unit vectors. 00008 // Reference: Numerical Recipies in C, 2nd ed., by Press, Teukolsky, Vetterling & Flannery. 00009 // 00010 // http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?action=browse&diff=1&id=LU_Matrix_Inversion 00011 // Hope someone finds this useful. Regards, Fredrik Orderud. 00012 // 00013 // Last edited September 4, 2007 5:23 am 00014 // 00015 #include <boost/numeric/ublas/vector.hpp> 00016 #include <boost/numeric/ublas/vector_proxy.hpp> 00017 #include <boost/numeric/ublas/matrix.hpp> 00018 #include <boost/numeric/ublas/triangular.hpp> 00019 #include <boost/numeric/ublas/lu.hpp> 00020 #include <boost/numeric/ublas/io.hpp> 00021 00022 template<class Matrix> 00023 bool invert_3x3( const Matrix& A, Matrix& result ) 00024 { 00025 using namespace boost::numeric::ublas; 00026 typedef typename Matrix::value_type T; 00027 T determinant = ( +A( 0, 0 ) * ( A( 1, 1 ) * A( 2, 2 ) - A( 2, 1 ) * A( 1, 2 ) ) 00028 - A( 0, 1 ) * ( A( 1, 0 ) * A( 2, 2 ) - A( 1, 2 ) * A( 2, 0 ) ) 00029 + A( 0, 2 ) * ( A( 1, 0 ) * A( 2, 1 ) - A( 1, 1 ) * A( 2, 0 ) ) ); 00030 00031 if( determinant == 0 ) 00032 return false; 00033 00034 result( 0, 0 ) = ( A( 1, 1 ) * A( 2, 2 ) - A( 1, 2 ) * A( 2, 1 ) ) / determinant; 00035 result( 1, 0 ) = ( -A( 1, 0 ) * A( 2, 2 ) + A( 2, 0 ) * A( 1, 2 ) ) / determinant; 00036 result( 2, 0 ) = ( A( 1, 0 ) * A( 2, 1 ) - A( 2, 0 ) * A( 1, 1 ) ) / determinant; 00037 result( 0, 1 ) = ( -A( 0, 1 ) * A( 2, 2 ) + A( 2, 1 ) * A( 0, 2 ) ) / determinant; 00038 result( 1, 1 ) = ( A( 0, 0 ) * A( 2, 2 ) - A( 2, 0 ) * A( 0, 2 ) ) / determinant; 00039 result( 2, 1 ) = ( -A( 0, 0 ) * A( 2, 1 ) + A( 2, 0 ) * A( 0, 1 ) ) / determinant; 00040 result( 0, 2 ) = ( A( 0, 1 ) * A( 1, 2 ) - A( 1, 1 ) * A( 0, 2 ) ) / determinant; 00041 result( 1, 2 ) = ( -A( 0, 0 ) * A( 1, 2 ) + A( 1, 0 ) * A( 0, 2 ) ) / determinant; 00042 result( 2, 2 ) = ( A( 0, 0 ) * A( 1, 1 ) - A( 1, 0 ) * A( 0, 1 ) ) / determinant; 00043 return true; 00044 } 00045 00046 // Matrix inversion routine. 00047 // Uses lu_factorize and lu_substitute in uBLAS to invert a matrix 00048 template<class Matrix> 00049 bool invert( const Matrix& input, Matrix& inverse ) 00050 { 00051 using namespace boost::numeric; 00052 typedef typename Matrix::value_type T; 00053 typedef ublas::permutation_matrix<std::size_t> pmatrix; 00054 00055 // create a working copy of the input 00056 Matrix A( input ); 00057 // create a permutation matrix for the LU-factorization 00058 pmatrix pm( A.size1() ); 00059 00060 // perform LU-factorization 00061 int res = ublas::lu_factorize( A, pm ); 00062 if( res != 0 ) 00063 return false; 00064 00065 // create identity matrix of "inverse" 00066 inverse.assign( ublas::identity_matrix<T>( A.size1() ) ); 00067 00068 // backsubstitute to get the inverse 00069 ublas::lu_substitute( A, pm, inverse ); 00070 00071 return true; 00072 } 00073 00074 /** 00075 * Generic matrix inverter' specialization for square matrix of size 3. 00076 */ 00077 template<typename T> 00078 bool invert( const boost::numeric::ublas::bounded_matrix<T, 3, 3>& A, 00079 boost::numeric::ublas::bounded_matrix<T, 3, 3>& result ) 00080 { 00081 return invert_3x3( A, result ); 00082 } 00083 00084 template<class Matrix> 00085 Matrix invert( const Matrix& m, bool& is_singular ) 00086 { 00087 Matrix inv_m( m.size1(), m.size2() ); 00088 00089 is_singular = !invert( m, inv_m ); 00090 return inv_m; 00091 } 00092 00093 // http://archives.free.net.ph/message/20080909.064313.59c122c4.fr.html 00094 template<class Matrix> 00095 double determinant( boost::numeric::ublas::matrix_expression<Matrix> const& mat_r ) 00096 { 00097 using namespace boost::numeric; 00098 00099 double det = 1.0; 00100 Matrix mLu( mat_r() ); 00101 ublas::permutation_matrix<std::size_t> pivots( mat_r().size1() ); 00102 bool is_singular = ublas::lu_factorize( mLu, pivots ); 00103 if( !is_singular ) 00104 { 00105 for( std::size_t i = 0; i < pivots.size(); ++i ) 00106 { 00107 if( pivots( i ) != i ) 00108 { 00109 det *= -1.0; 00110 } 00111 det *= mLu( i, i ); 00112 } 00113 } 00114 else 00115 { 00116 det = 0.0; 00117 } 00118 return det; 00119 } 00120 00121 #endif