Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_MATH_BIG_SVD_H
00002 #define OPENTISSUE_CORE_MATH_BIG_SVD_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #ifdef USE_ATLAS
00013 # include <OpenTissue/core/math/big/big_svd_impl_atlas.h>
00014 #else
00015 # include <OpenTissue/core/math/big/big_svd_impl1.h>
00016 #endif
00017 #include <OpenTissue/core/math/big/big_types.h>
00018 #include <OpenTissue/core/math/math_value_traits.h>
00019 #include <boost/cast.hpp>
00020 #include <cmath>
00021 #include <stdexcept>
00022
00023 namespace OpenTissue
00024 {
00025 namespace math
00026 {
00027 namespace big
00028 {
00029
00041 template<typename ME>
00042 inline void svd(
00043 ublas::matrix_expression<ME> const & A
00044 , ublas::matrix<typename ME::value_type> & U
00045 , ublas::vector<typename ME::value_type> & s
00046 , ublas::matrix<typename ME::value_type> & V
00047 )
00048 {
00049 #ifdef USE_ATLAS
00050 ublas::matrix<typename ME::value_type, ublas::column_major> VT;
00051 ublas::matrix<typename ME::value_type, ublas::column_major> UU;
00052
00053 details::svd_impl_atlas( A, UU, s, VT);
00054
00055 V.resize( VT.size1(), VT.size2() );
00056 V = ublas::trans( VT );
00057 U = UU;
00058 #else
00059 details::svd_impl1(A, U, s, V);
00060 #endif
00061 }
00062
00063
00078 template<typename matrix_type, typename vector_type>
00079 inline void svd( matrix_type const & A, vector_type & x, vector_type const & b )
00080 {
00081 using std::fabs;
00082
00083 typedef typename matrix_type::size_type size_type;
00084 typedef typename vector_type::value_type value_type;
00085 typedef ublas::matrix<value_type> row_major_matrix_type;
00086 typedef OpenTissue::math::ValueTraits<value_type> value_traits;
00087
00088 if(A.size1() <= 0 || A.size2() <= 0)
00089 throw std::invalid_argument("svd(): A was empty");
00090
00091 if(b.size() != A.size1())
00092 throw std::invalid_argument("svd(): The size of b must be the same as the number of rows in A");
00093
00094 if(x.size() != A.size2())
00095 throw std::invalid_argument("svd(): The size of x must be the same as the number of columns in A");
00096
00097
00098 static value_type const tiny = ::boost::numeric_cast<value_type>( 10e-4);
00099
00100
00101 size_type n = A.size2();
00102
00103
00104 row_major_matrix_type U;
00105 vector_type s;
00106 row_major_matrix_type V;
00107
00108 svd(A,U,s,V);
00109
00110
00111 for ( size_type i = 0; i < n; ++i )
00112 {
00113 if( fabs( s( i ) ) < tiny )
00114 s( i ) = value_traits::zero();
00115 else
00116 s( i ) = value_traits::one() / s( i );
00117 }
00118 vector_type y = ublas::prod( ublas::trans( U ), b );
00119 x = ublas::prod( V, ublas::element_prod( s, y) );
00120 }
00121
00122
00130 template<class matrix_type>
00131 inline void svd_invert(matrix_type const & A, matrix_type& invA)
00132 {
00133 using std::fabs;
00134
00135 typedef typename matrix_type::size_type size_type;
00136 typedef typename matrix_type::value_type value_type;
00137 typedef ublas::vector<value_type> vector_type;
00138 typedef OpenTissue::math::ValueTraits<value_type> value_traits;
00139 typedef ublas::matrix<value_type> row_major_matrix_type;
00140
00141 if(A.size1() <= 0 || A.size2() <= 0)
00142 throw std::invalid_argument("svd(): A was empty");
00143
00144 static value_type const tiny = ::boost::numeric_cast<value_type>( 10e-4);
00145
00146 size_type m = A.size1();
00147 size_type n = A.size2();
00148
00149 invA.resize(n,m,false);
00150
00151
00152 row_major_matrix_type U;
00153 vector_type s;
00154 row_major_matrix_type V;
00155 svd(A,U,s,V);
00156
00157
00158
00159
00160
00161 row_major_matrix_type D;
00162 D.resize(n,n);
00163 D.clear();
00164 for ( size_type i = 0; i < n; ++i )
00165 {
00166 if( fabs( s( i ) ) < tiny )
00167 D( i, i ) = value_traits::zero();
00168 else
00169 D( i, i ) = value_traits::one() / s( i );
00170 }
00171
00172 row_major_matrix_type tmp = ublas::prod( D, ublas::trans(U) );
00173 invA.assign( ublas::prod( V, tmp ) );
00174 }
00175
00176
00177 }
00178 }
00179 }
00180
00181
00182 #endif