ISIS Core Library 0.7.2 (api 3.0.0)
|
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