00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef _BOOST_UBLAS_EXPM_
00039 #define _BOOST_UBLAS_EXPM_
00040 #include <complex>
00041 #include <boost/numeric/ublas/vector.hpp>
00042 #include <boost/numeric/ublas/matrix.hpp>
00043 #include <boost/numeric/ublas/lu.hpp>
00044
00045 namespace boost { namespace numeric { namespace ublas {
00046
00047 template<typename MATRIX> MATRIX expm_pad(const MATRIX &H, const int p = 6)
00048 {
00049 typedef typename MATRIX::value_type value_type;
00050 typedef typename MATRIX::size_type size_type;
00051 typedef double real_value_type;
00052 assert(H.size1() == H.size2());
00053 const size_type n = H.size1();
00054 const identity_matrix<value_type> I(n);
00055 matrix<value_type> U(n,n),H2(n,n),P(n,n),Q(n,n);
00056 real_value_type norm = 0.0;
00057
00058
00059 vector<real_value_type> c(p+2);
00060 c(1)=1;
00061 for(size_type i = 1; i <= p; ++i)
00062 c(i+1) = c(i) * ((p + 1.0 - i)/(i * (2.0 * p + 1 - i)));
00063
00064 for(size_type i=0; i<n; ++i)
00065 {
00066 real_value_type temp = 0.0;
00067 for(size_type j=0;j<n;j++)
00068 temp += std::abs<real_value_type>(H(i,j));
00069 norm = std::max<real_value_type>(norm, temp);
00070 }
00071 if (norm == 0.0)
00072 {
00073 std::cerr<<"Error! Null input in the routine EXPM_PAD.\n";
00074 exit(0);
00075 }
00076
00077 int s = 0;
00078 real_value_type scale = 1.0;
00079 if(norm > 0.5)
00080 {
00081 s = std::max<int>(0, static_cast<int>((log(norm) / log(2.0) + 2.0)));
00082 scale /= static_cast<real_value_type>(std::pow(2.0, s));
00083 U.assign(scale * H);
00084 }
00085
00086
00087 H2.assign( prod(U, U) );
00088 Q.assign( c(p+1)*I );
00089 P.assign( c(p)*I );
00090 size_type odd = 1;
00091 for( size_type k = p - 1; k > 0; --k)
00092 {
00093 if( odd == 1)
00094 {
00095 Q = ( prod(Q, H2) + c(k) * I );
00096 }
00097 else
00098 {
00099 P = ( prod(P, H2) + c(k) * I );
00100 }
00101 odd = 1 - odd;
00102 }
00103 if( odd == 1)
00104 {
00105 Q = ( prod(Q, U) );
00106 Q -= P ;
00107
00108 }
00109 else
00110 {
00111 P = (prod(P, U));
00112 Q -= P;
00113
00114 }
00115
00116
00117
00118
00119
00121 permutation_matrix<size_type> pm(n);
00122 int res = lu_factorize(Q, pm);
00123 if( res != 0)
00124 {
00125 std::cerr << "Error in the matrix inversion in template expm_pad.\n";
00126 exit(0);
00127 }
00128 H2 = I;
00129 lu_substitute(Q, pm, H2);
00130 if( odd == 1)
00131 U.assign( -(I + 2.0 * prod(H2, P)));
00132 else
00133 U.assign( I + 2.0 * prod(H2, P));
00134
00135 for(size_t i = 0; i < s; ++i)
00136 {
00137 U = (prod(U,U));
00138 }
00139 return U;
00140 }
00141
00142 }}}
00143
00144
00145 #endif