ISIS Core Library 0.7.2 (api 3.0.0)

/scr/tee1/isis/lib/Core/CoreUtils/matrix.hpp

Go to the documentation of this file.
00001 /*
00002     <one line to give the program's name and a brief idea of what it does.>
00003     Copyright (C) 2011  <copyright holder> <email>
00004 
00005     This program is free software: you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation, either version 3 of the License, or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 */
00018 
00019 
00020 #ifndef ISIS_MATRIX_HPP
00021 #define ISIS_MATRIX_HPP
00022 
00023 #include "vector.hpp"
00024 
00025 #include <boost/numeric/ublas/matrix.hpp>
00026 #include <boost/numeric/ublas/lu.hpp>
00027 #include <boost/typeof/typeof.hpp>
00028 #include <iomanip>
00029 
00030 
00031 namespace isis
00032 {
00033 namespace util
00034 {
00035 
00036 template < typename TYPE, size_t COLS, size_t ROWS, typename CONTAINER = typename FixedVector<TYPE, ROWS *COLS>::container_type >
00037 class FixedMatrix : public FixedVector<TYPE, ROWS *COLS, CONTAINER>
00038 {
00039 public:
00040     template<typename A, typename B> struct result_of_mult {
00041         typedef BOOST_TYPEOF_TPL( A() * B() ) type;
00042     };
00043     static const size_t rows = ROWS;
00044     static const size_t columns = COLS;
00045 
00046     typedef TYPE value_type;
00047 
00048     template<typename TYPE2, typename CONTAINER2>
00049     void copyFrom( const FixedVector<TYPE2, COLS, CONTAINER2> src[ROWS] ) {
00050         for( size_t r = 0; r < ROWS; r++ ) {
00051             const TYPE2 *ptr = &src[r][0];
00052             std::copy( ptr, ptr + COLS, &elem( 0, r ) );
00053         }
00054     }
00055 
00056     FixedMatrix() {}
00057 
00058     template<typename TYPE2>
00059     FixedMatrix( const TYPE2 src[ROWS *COLS] ): FixedVector<TYPE, ROWS *COLS, CONTAINER>( src ) {}
00060 
00061     template<typename TYPE2, typename CONTAINER2>
00062     FixedMatrix( const FixedVector<TYPE2, COLS, CONTAINER2> src[ROWS] ) {copyFrom( src );}
00063 
00064     FixedMatrix( const boost::numeric::ublas::matrix<TYPE> &boost_matrix ) throw ( std::logic_error & ) {
00065         if( boost_matrix.size1() == ROWS && boost_matrix.size2() == COLS ) {
00066             for( size_t m = 0; m < ROWS; m++ ) {
00067                 for( size_t n = 0; n < COLS; n++ ) {
00068                     this->elem( n, m ) = boost_matrix( m, n );
00069                 }
00070             }
00071         } else {
00072             LOG( Runtime, error ) << "The size of the boost matrix ("
00073                                   << boost_matrix.size1() << ", " << boost_matrix.size2()
00074                                   << ") does not coincide with the size of the isis matrix (" << ROWS << ", " << COLS << ").";
00075             throw( std::logic_error( "Size mismatch" ) );
00076         }
00077     };
00078 
00079     TYPE &elem( size_t column, size_t row ) {return ( *this )[column + row * COLS];}
00080     const TYPE &elem( size_t column, size_t row )const {return ( *this )[column + row * COLS];}
00081 
00082     boost::numeric::ublas::matrix<TYPE> getBoostMatrix() const {
00083         boost::numeric::ublas::matrix<TYPE> ret = boost::numeric::ublas::matrix<TYPE>( ROWS, COLS );
00084 
00085         for( size_t m = 0; m < ROWS; m++ ) {
00086             for( size_t n = 0; n < COLS; n++ ) {
00087                 ret( m, n ) = this->elem( n, m );
00088             }
00089         }
00090 
00091         return ret;
00092     }
00093 
00094     FixedMatrix<TYPE, ROWS, COLS> transpose()const {
00095         FixedMatrix<TYPE, ROWS, COLS> ret;
00096 
00097         for( size_t m = 0; m < COLS; m++ )
00098             for( size_t n = 0; n < ROWS; n++ ) {
00099                 ret.elem( n, m ) = this->elem( m, n );
00100             }
00101 
00102         return ret;
00103     }
00104 
00105     FixedMatrix<TYPE, COLS, ROWS> inverse( bool &invertible )const throw ( std::logic_error & ) {
00106         if( COLS != ROWS ) {
00107             LOG( Runtime, error ) << "Matrix is not a square matrix so is not invertible!";
00108             throw( std::logic_error( "Matrix is not a square matrix so is not invertible!" ) );
00109         }
00110 
00111         using namespace boost::numeric::ublas;
00112         FixedMatrix<TYPE, COLS, ROWS> ret;
00113         matrix<TYPE> boost_matrix_in = this->getBoostMatrix();
00114         matrix<TYPE> boost_matrix_inverse = matrix<TYPE>( ROWS, COLS );
00115         permutation_matrix<TYPE> pm( boost_matrix_in.size1() );
00116         //check if det is 0 -> singular
00117         invertible = lu_factorize( boost_matrix_in, pm ) == 0;
00118 
00119         if( invertible ) {
00120             boost_matrix_inverse.assign( identity_matrix<TYPE>( boost_matrix_in.size1() ) ) ;
00121             lu_substitute( boost_matrix_in, pm, boost_matrix_inverse );
00122             return FixedMatrix<TYPE, COLS, ROWS>( boost_matrix_inverse );
00123         } else {
00124             LOG( Runtime, error ) << "Matrix is singular. Returning initial matrix.";
00125             return *this;
00126         }
00127     }
00128 
00129     template<typename TYPE2, size_t COLS2, typename CONTAINER2> FixedMatrix<typename result_of_mult<TYPE, TYPE2>::type, COLS2, ROWS>
00130     dot( const FixedMatrix<TYPE2, COLS2, COLS, CONTAINER2> &right )const {
00131         // transpose the right, so we can use columns as rows
00132         typedef typename result_of_mult<TYPE, TYPE2>::type result_type;
00133         const FixedMatrix<TYPE2, COLS, COLS2, CONTAINER2> rightT = right.transpose();
00134         const FixedMatrix<TYPE, COLS, ROWS, CONTAINER> &left = *this;
00135         FixedMatrix<result_type, COLS2, ROWS> ret;
00136 
00137         for( size_t c = 0; c < right.columns; c++ ) { //result has as much columns as right
00138             const TYPE2 *rstart = &rightT.elem( 0, c );
00139 
00140             for( size_t r = 0; r < left.rows; r++ ) { //result has as much rows as left
00141                 const TYPE *lstart = &left.elem( 0, r ), *lend = lstart + left.columns;
00142                 ret.elem( c, r ) = std::inner_product( lstart, lend, rstart, result_type() );
00143             }
00144         }
00145 
00146         return ret;
00147     }
00148 
00149 
00150     template<typename TYPE2, typename CONTAINER2> FixedVector<typename result_of_mult<TYPE, TYPE2>::type, COLS>
00151     dot( const FixedVector<TYPE2, COLS, CONTAINER2> &right )const {
00152         const FixedMatrix<TYPE, COLS, ROWS, CONTAINER> &left = *this;
00153         typedef typename result_of_mult<TYPE, TYPE2>::type result_type;
00154         FixedVector<result_type, ROWS> ret;
00155         const TYPE2 *rstart = &right[0];
00156 
00157         for( size_t r = 0; r < rows; r++ ) { //result has as much rows as left
00158             const TYPE *lstart = &elem( 0, r ), *lend = lstart + left.columns;
00159             ret[r] = std::inner_product( lstart, lend, rstart, result_type() );
00160         }
00161 
00162         return ret;
00163     }
00164 
00165     FixedVector<TYPE, COLS> getRow( size_t rownum )const {
00166         FixedVector<TYPE, COLS> ret;
00167         const typename FixedVector<TYPE, ROWS *COLS, CONTAINER>::const_iterator start = FixedVector<TYPE, ROWS * COLS, CONTAINER>::begin() + rownum * COLS;
00168         const typename FixedVector<TYPE, ROWS *COLS, CONTAINER>::const_iterator end = start + COLS;
00169         ret.copyFrom( start, end );
00170         return ret;
00171     }
00172 
00173 
00174 };
00175 
00176 template<typename TYPE, size_t ELEMS>
00177 class IdentityMatrix : public FixedMatrix<TYPE, ELEMS, ELEMS>
00178 {
00179 public:
00180     IdentityMatrix( TYPE value = 1 ) {
00181         for( size_t m = 0; m < ELEMS; m++ ) {
00182             for( size_t n = 0; n < ELEMS; n++ ) {
00183                 if( m == n ) {
00184                     this->elem( n, m ) = static_cast<TYPE>( value );
00185                 } else {
00186                     this->elem( n, m ) = static_cast<TYPE>( 0 );
00187                 }
00188             }
00189         }
00190     }
00191 };
00192 
00193 template<typename TYPE>
00194 class Matrix4x4: public FixedMatrix<TYPE, 4, 4>
00195 {
00196 public:
00197     Matrix4x4() {};
00198 
00199     Matrix4x4( const FixedMatrix<TYPE, 4, 4> &src ): FixedMatrix<TYPE, 4, 4>( src ) {}
00200 
00201     Matrix4x4( const TYPE src[16] ): FixedMatrix<TYPE, 4, 4>( src ) {}
00202     template<typename TYPE2> Matrix4x4(
00203         const FixedVector<TYPE2, 4> &row1,
00204         const FixedVector<TYPE2, 4> &row2,
00205         const FixedVector<TYPE2, 4> &row3 = vector4<TYPE2>( 0, 0, 1, 0 ),
00206         const FixedVector<TYPE2, 4> &row4 = vector4<TYPE2>( 0, 0, 0, 1 )
00207     ) {
00208         const vector4<TYPE2> src[4] = {row1, row2, row3, row4};
00209         FixedMatrix<TYPE, 4, 4>::copyFrom( src );
00210     }
00211 };
00212 
00213 template<typename TYPE>
00214 class Matrix3x3: public FixedMatrix<TYPE, 3, 3>
00215 {
00216 public:
00217     Matrix3x3() {};
00218 
00219     Matrix3x3( const FixedMatrix<TYPE, 3, 3> &src ): FixedMatrix<TYPE, 3, 3>( src ) {}
00220 
00221     Matrix3x3( const TYPE src[9] ): FixedMatrix<TYPE, 3, 3>( src ) {}
00222     template<typename TYPE2> Matrix3x3(
00223         const FixedVector<TYPE2, 3> &row1,
00224         const FixedVector<TYPE2, 3> &row2,
00225         const FixedVector<TYPE2, 3> &row3 = vector3<TYPE2>( 0, 0, 1 )
00226     ) {
00227         const vector3<TYPE2> src[3] = {row1, row2, row3};
00228         FixedMatrix<TYPE, 3, 3>::copyFrom( src );
00229     }
00230 };
00231 
00232 }
00233 }
00235 namespace std
00236 {
00237 
00238 template<typename charT, typename traits, typename TYPE, size_t COLS, size_t ROWS, typename CONTAINER > basic_ostream<charT, traits>&
00239 operator<<( basic_ostream<charT, traits> &out, const ::isis::util::FixedMatrix<TYPE, COLS, ROWS, CONTAINER>& m )
00240 {
00241     out << "FixedMatrix of size (" << m.columns << " columns, " << m.rows << " rows):" << std::endl;
00242 
00243     for( size_t row = 0; row < ROWS; row++ ) {
00244         out << "<";
00245 
00246         for( size_t col = 0; col < COLS; col++ ) {
00247             out << m.elem( col, row );
00248 
00249             if( col < COLS - 1 ) out << "\t";
00250         }
00251 
00252         out << ">" << std::endl;
00253     }
00254 
00255     return out;
00256 }
00257 }
00258 
00259 #endif // ISIS_MATRIX_HPP