TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/plugin/numeric/ublas/invert_matrix.hpp
Go to the documentation of this file.
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