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 #ifndef EIGEN_MATRIX_EXPONENTIAL
00026 #define EIGEN_MATRIX_EXPONENTIAL
00027
00028 #ifdef _MSC_VER
00029 template <typename Scalar> Scalar log2(Scalar v) { return std::log(v)/std::log(Scalar(2)); }
00030 #endif
00031
00032
00038 template <typename MatrixType>
00039 class MatrixExponential {
00040
00041 public:
00042
00050 MatrixExponential(const MatrixType &M);
00051
00056 template <typename ResultType>
00057 void compute(ResultType &result);
00058
00059 private:
00060
00061
00062 MatrixExponential(const MatrixExponential&);
00063 MatrixExponential& operator=(const MatrixExponential&);
00064
00072 void pade3(const MatrixType &A);
00073
00081 void pade5(const MatrixType &A);
00082
00090 void pade7(const MatrixType &A);
00091
00099 void pade9(const MatrixType &A);
00100
00108 void pade13(const MatrixType &A);
00109
00123 void computeUV(double);
00124
00129 void computeUV(float);
00130
00131 typedef typename internal::traits<MatrixType>::Scalar Scalar;
00132 typedef typename NumTraits<Scalar>::Real RealScalar;
00133
00135 typename internal::nested<MatrixType>::type m_M;
00136
00138 MatrixType m_U;
00139
00141 MatrixType m_V;
00142
00144 MatrixType m_tmp1;
00145
00147 MatrixType m_tmp2;
00148
00150 MatrixType m_Id;
00151
00153 int m_squarings;
00154
00156 float m_l1norm;
00157 };
00158
00159 template <typename MatrixType>
00160 MatrixExponential<MatrixType>::MatrixExponential(const MatrixType &M) :
00161 m_M(M),
00162 m_U(M.rows(),M.cols()),
00163 m_V(M.rows(),M.cols()),
00164 m_tmp1(M.rows(),M.cols()),
00165 m_tmp2(M.rows(),M.cols()),
00166 m_Id(MatrixType::Identity(M.rows(), M.cols())),
00167 m_squarings(0),
00168 m_l1norm(static_cast<float>(M.cwiseAbs().colwise().sum().maxCoeff()))
00169 {
00170
00171 }
00172
00173 template <typename MatrixType>
00174 template <typename ResultType>
00175 void MatrixExponential<MatrixType>::compute(ResultType &result)
00176 {
00177 computeUV(RealScalar());
00178 m_tmp1 = m_U + m_V;
00179 m_tmp2 = -m_U + m_V;
00180 result = m_tmp2.partialPivLu().solve(m_tmp1);
00181 for (int i=0; i<m_squarings; i++)
00182 result *= result;
00183 }
00184
00185 template <typename MatrixType>
00186 EIGEN_STRONG_INLINE void MatrixExponential<MatrixType>::pade3(const MatrixType &A)
00187 {
00188 const Scalar b[] = {120., 60., 12., 1.};
00189 m_tmp1.noalias() = A * A;
00190 m_tmp2 = b[3]*m_tmp1 + b[1]*m_Id;
00191 m_U.noalias() = A * m_tmp2;
00192 m_V = b[2]*m_tmp1 + b[0]*m_Id;
00193 }
00194
00195 template <typename MatrixType>
00196 EIGEN_STRONG_INLINE void MatrixExponential<MatrixType>::pade5(const MatrixType &A)
00197 {
00198 const Scalar b[] = {30240., 15120., 3360., 420., 30., 1.};
00199 MatrixType A2 = A * A;
00200 m_tmp1.noalias() = A2 * A2;
00201 m_tmp2 = b[5]*m_tmp1 + b[3]*A2 + b[1]*m_Id;
00202 m_U.noalias() = A * m_tmp2;
00203 m_V = b[4]*m_tmp1 + b[2]*A2 + b[0]*m_Id;
00204 }
00205
00206 template <typename MatrixType>
00207 EIGEN_STRONG_INLINE void MatrixExponential<MatrixType>::pade7(const MatrixType &A)
00208 {
00209 const Scalar b[] = {17297280., 8648640., 1995840., 277200., 25200., 1512., 56., 1.};
00210 MatrixType A2 = A * A;
00211 MatrixType A4 = A2 * A2;
00212 m_tmp1.noalias() = A4 * A2;
00213 m_tmp2 = b[7]*m_tmp1 + b[5]*A4 + b[3]*A2 + b[1]*m_Id;
00214 m_U.noalias() = A * m_tmp2;
00215 m_V = b[6]*m_tmp1 + b[4]*A4 + b[2]*A2 + b[0]*m_Id;
00216 }
00217
00218 template <typename MatrixType>
00219 EIGEN_STRONG_INLINE void MatrixExponential<MatrixType>::pade9(const MatrixType &A)
00220 {
00221 const Scalar b[] = {17643225600., 8821612800., 2075673600., 302702400., 30270240.,
00222 2162160., 110880., 3960., 90., 1.};
00223 MatrixType A2 = A * A;
00224 MatrixType A4 = A2 * A2;
00225 MatrixType A6 = A4 * A2;
00226 m_tmp1.noalias() = A6 * A2;
00227 m_tmp2 = b[9]*m_tmp1 + b[7]*A6 + b[5]*A4 + b[3]*A2 + b[1]*m_Id;
00228 m_U.noalias() = A * m_tmp2;
00229 m_V = b[8]*m_tmp1 + b[6]*A6 + b[4]*A4 + b[2]*A2 + b[0]*m_Id;
00230 }
00231
00232 template <typename MatrixType>
00233 EIGEN_STRONG_INLINE void MatrixExponential<MatrixType>::pade13(const MatrixType &A)
00234 {
00235 const Scalar b[] = {64764752532480000., 32382376266240000., 7771770303897600.,
00236 1187353796428800., 129060195264000., 10559470521600., 670442572800.,
00237 33522128640., 1323241920., 40840800., 960960., 16380., 182., 1.};
00238 MatrixType A2 = A * A;
00239 MatrixType A4 = A2 * A2;
00240 m_tmp1.noalias() = A4 * A2;
00241 m_V = b[13]*m_tmp1 + b[11]*A4 + b[9]*A2;
00242 m_tmp2.noalias() = m_tmp1 * m_V;
00243 m_tmp2 += b[7]*m_tmp1 + b[5]*A4 + b[3]*A2 + b[1]*m_Id;
00244 m_U.noalias() = A * m_tmp2;
00245 m_tmp2 = b[12]*m_tmp1 + b[10]*A4 + b[8]*A2;
00246 m_V.noalias() = m_tmp1 * m_tmp2;
00247 m_V += b[6]*m_tmp1 + b[4]*A4 + b[2]*A2 + b[0]*m_Id;
00248 }
00249
00250 template <typename MatrixType>
00251 void MatrixExponential<MatrixType>::computeUV(float)
00252 {
00253 if (m_l1norm < 4.258730016922831e-001) {
00254 pade3(m_M);
00255 } else if (m_l1norm < 1.880152677804762e+000) {
00256 pade5(m_M);
00257 } else {
00258 const float maxnorm = 3.925724783138660f;
00259 m_squarings = std::max(0, (int)ceil(log2(m_l1norm / maxnorm)));
00260 MatrixType A = m_M / std::pow(Scalar(2), Scalar(static_cast<RealScalar>(m_squarings)));
00261 pade7(A);
00262 }
00263 }
00264
00265 template <typename MatrixType>
00266 void MatrixExponential<MatrixType>::computeUV(double)
00267 {
00268 if (m_l1norm < 1.495585217958292e-002) {
00269 pade3(m_M);
00270 } else if (m_l1norm < 2.539398330063230e-001) {
00271 pade5(m_M);
00272 } else if (m_l1norm < 9.504178996162932e-001) {
00273 pade7(m_M);
00274 } else if (m_l1norm < 2.097847961257068e+000) {
00275 pade9(m_M);
00276 } else {
00277 const double maxnorm = 5.371920351148152;
00278 m_squarings = std::max(0, (int)ceil(log2(m_l1norm / maxnorm)));
00279 MatrixType A = m_M / std::pow(Scalar(2), Scalar(m_squarings));
00280 pade13(A);
00281 }
00282 }
00283
00296 template<typename Derived> struct MatrixExponentialReturnValue
00297 : public ReturnByValue<MatrixExponentialReturnValue<Derived> >
00298 {
00299 typedef typename Derived::Index Index;
00300 public:
00306 MatrixExponentialReturnValue(const Derived& src) : m_src(src) { }
00307
00313 template <typename ResultType>
00314 inline void evalTo(ResultType& result) const
00315 {
00316 const typename Derived::PlainObject srcEvaluated = m_src.eval();
00317 MatrixExponential<typename Derived::PlainObject> me(srcEvaluated);
00318 me.compute(result);
00319 }
00320
00321 Index rows() const { return m_src.rows(); }
00322 Index cols() const { return m_src.cols(); }
00323
00324 protected:
00325 const Derived& m_src;
00326 private:
00327 MatrixExponentialReturnValue& operator=(const MatrixExponentialReturnValue&);
00328 };
00329
00330 namespace internal {
00331 template<typename Derived>
00332 struct traits<MatrixExponentialReturnValue<Derived> >
00333 {
00334 typedef typename Derived::PlainObject ReturnType;
00335 };
00336 }
00337
00338 template <typename Derived>
00339 const MatrixExponentialReturnValue<Derived> MatrixBase<Derived>::exp() const
00340 {
00341 eigen_assert(rows() == cols());
00342 return MatrixExponentialReturnValue<Derived>(derived());
00343 }
00344
00345 #endif // EIGEN_MATRIX_EXPONENTIAL