File indexing completed on 2026-08-06 09:24:28
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #ifndef _BOOST_UBLAS_EXPM_
0039 #define _BOOST_UBLAS_EXPM_
0040 #include <complex>
0041 #include <boost/numeric/ublas/vector.hpp>
0042 #include <boost/numeric/ublas/matrix.hpp>
0043 #include <boost/numeric/ublas/lu.hpp>
0044
0045 namespace boost { namespace numeric { namespace ublas {
0046
0047 template<typename MATRIX> MATRIX expm_pad(const MATRIX &H, const int p = 6) {
0048 typedef typename MATRIX::value_type value_type;
0049 typedef typename MATRIX::size_type size_type;
0050 typedef double real_value_type;
0051 assert(H.size1() == H.size2());
0052 const size_type n = H.size1();
0053 const identity_matrix<value_type> I(n);
0054 matrix<value_type> U(n,n),H2(n,n),P(n,n),Q(n,n);
0055 real_value_type norm = 0.0;
0056
0057
0058 vector<real_value_type> c(p+2);
0059 c(1)=1;
0060 for(size_type i = 1; i <= p; ++i)
0061 c(i+1) = c(i) * ((p + 1.0 - i)/(i * (2.0 * p + 1 - i)));
0062
0063 for(size_type i=0; i<n; ++i)
0064 {
0065 real_value_type temp = 0.0;
0066 for(size_type j=0;j<n;j++)
0067 temp += std::abs<real_value_type>(H(j,i));
0068 norm = std::max<real_value_type>(norm, temp);
0069 }
0070 if (norm == 0.0)
0071 {
0072 boost::throw_exception(boost::numeric::ublas::bad_argument());
0073 std::cerr<<"Error! Null input in the routine EXPM_PAD.\n";
0074 exit(0);
0075 }
0076
0077 int s = 0;
0078 real_value_type scale = 1.0;
0079 if(norm > 0.5) {
0080 s = std::max<int>(0, static_cast<int>((log(norm) / log(2.0) + 2.0)));
0081 scale /= static_cast<real_value_type>(std::pow(2.0, s));
0082 U.assign(scale * H);
0083 }
0084 else
0085 U.assign(H);
0086
0087
0088 H2.assign( prod(U, U) );
0089 Q.assign( c(p+1)*I );
0090 P.assign( c(p)*I );
0091 size_type odd = 1;
0092 for( size_type k = p - 1; k > 0; --k)
0093 {
0094 if( odd == 1)
0095 {
0096 Q = ( prod(Q, H2) + c(k) * I );
0097 }
0098 else
0099 {
0100 P = ( prod(P, H2) + c(k) * I );
0101 }
0102 odd = 1 - odd;
0103 }
0104 if( odd == 1)
0105 {
0106 Q = ( prod(Q, U) );
0107 Q -= P ;
0108
0109 }
0110 else
0111 {
0112 P = (prod(P, U));
0113 Q -= P;
0114
0115 }
0116
0117
0118
0119
0120
0121
0122 permutation_matrix<size_type> pm(n);
0123 int res = lu_factorize(Q, pm);
0124 if( res != 0)
0125 {
0126 std::cerr << "Error in the matrix inversion in template expm_pad.\n";
0127 exit(0);
0128 }
0129 H2 = I;
0130
0131 lu_substitute(Q, pm, H2);
0132 if( odd == 1)
0133 U.assign( -(I + 2.0 * prod(H2, P)));
0134 else
0135 U.assign( I + 2.0 * prod(H2, P));
0136
0137 for(size_t i = 0; i < s; ++i)
0138 {
0139 U = (prod(U,U));
0140 }
0141 return U;
0142 }
0143
0144 }}}
0145
0146
0147 #endif