Controlpp
Loading...
Searching...
No Matches
expm.hpp
Go to the documentation of this file.
1#pragma once
2
10#include "math.hpp"
11
12namespace controlpp{
31 template<class T, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
32 Eigen::Matrix<T, Rows, Cols, Options, MaxRows, MaxCols> expm_taylor(
33 const Eigen::Matrix<T, Rows, Cols, Options, MaxRows, MaxCols>& x,
34 int n
35 ){
36 Eigen::Matrix<T, Rows, Cols> result;
37 const auto I = Eigen::Matrix<T, Rows, Cols>::Identity();
38 result.setZero();
39 for(int i = n; i > 0; --i){
40 Eigen::Matrix<T, Rows, Cols> new_result = (result + I) * x / static_cast<T>(i);
41 result = new_result;
42 }
43 result += I;
44 return result;
45 }
46
73 template<class T, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
74 Eigen::Matrix<T, Rows, Cols, Options, MaxRows, MaxCols> expm_taylor_scaled(
75 const Eigen::Matrix<T, Rows, Cols, Options, MaxRows, MaxCols>& M,
76 int taylor_order = 8,
77 int scaling = 10
78 ){
79 using Matrix = Eigen::Matrix<T, Rows, Cols, Options, MaxRows, MaxCols>;
80 T s = static_cast<T>(1 << scaling);
81 Matrix scaled_M = M/s;
82 Matrix t = expm_taylor(scaled_M, taylor_order);
83 for(int i = 0; i < scaling; ++i){
84 const Matrix temp = t * t;
85 t = temp;
86 };
87 return t;
88 }
89
90
104 template<class T, int N, int Options, int MaxRows, int MaxCols>
105 Eigen::Matrix<T, N, N> expm_pade(
106 const Eigen::Matrix<T, N, N, Options, MaxRows, MaxCols>& A,
107 int Order = 5
108 ){
109 if(Order >= 32){
110 throw std::invalid_argument("expm_pade: Order must be less than 32");
111 }
112 const Eigen::Matrix<T, N, N> I = Eigen::Matrix<T, N, N>::Identity();
113 const Eigen::Matrix<T, N, N> A2 = A * A;
114
115 // even odd split of polynomials: allows to reuse results
116 Eigen::Matrix<T, N, N> even;
117 Eigen::Matrix<T, N, N> odd;
118 even.setZero();
119 odd.setZero();
120
121 // calculate pade parameters
122 T buffer[32];
123 pade_params(buffer, Order+1, Order, Order);
124
125 // horner chains to evaluate the polynomials
126 for(int k = Order; k >= 0; --k){
127 const bool is_first_iteration = (k == Order);
128 const T pk = static_cast<T>(buffer[k]);
129 if((k & 1) == 0){
130 // even
131 if(!is_first_iteration) even *= A2; // skipp on the first iteration
132 even += I * pk;
133 }else{
134 // odd
135 if(!is_first_iteration) odd *= A2; // skipp on the first iteration
136 odd += I * pk;
137 }
138 }
139 odd *= A;
140
141 const Eigen::Matrix<T, N, N> num = even + odd;
142 const Eigen::Matrix<T, N, N> den = even - odd;
143
144 const Eigen::Matrix<T, N, N> result = den.partialPivLu().solve(num);
145
146 return result;
147 }
148
161 template<class T, int N, int Options, int MaxRows, int MaxCols>
162 Eigen::Matrix<T, N, N> expm_pade_scaled(
163 const Eigen::Matrix<T, N, N, Options, MaxRows, MaxCols>& M,
164 int order,
165 int scaling
166 ){
167 Eigen::Matrix<T, N, N> scaled_M = M * std::ldexp(T(1), -scaling);
168 Eigen::Matrix<T, N, N> t = expm_pade(scaled_M, order);
169 for(int i = 0; i < scaling; ++i){
170 const Eigen::Matrix<T, N, N> temp = t * t;
171 t = temp;
172 };
173 return t;
174 }
175
180 int order;
182 };
183
197 template<class T, int N, int Options, int MaxRows, int MaxCols>
198 ExpmPadeParams expm_pade_params(const Eigen::Matrix<T, N, N, Options, MaxRows, MaxCols>& M){
199 const T norm = M.cwiseAbs().colwise().sum().maxCoeff();
200
201 // Theta values from Higham
202 constexpr T theta3 = T(1.495585217958292e-2);
203 constexpr T theta5 = T(2.539398330063230e-1);
204 constexpr T theta7 = T(9.504178996162932e-1);
205 constexpr T theta9 = T(2.097847961257068);
206 constexpr T theta13 = T(5.371920351148152);
207
208 if(norm <= theta3){
209 return {3, 0};
210 }
211
212 if(norm <= theta5){
213 return {5, 0};
214 }
215
216 if(norm <= theta7){
217 return {7, 0};
218 }
219
220 if(norm <= theta9){
221 return {9, 0};
222 }
223
224 if(norm <= theta13){
225 return {13, 0};
226 }
227
228 const double ratio = static_cast<double>(norm / theta13);
229 int scaling = 0;
230 if (ratio > 1.0) {
231 scaling = static_cast<int>(std::ceil(std::log2(ratio)));
232 if (scaling < 0) scaling = 0;
233 }
234 return {13, scaling};
235
236 }
237
248 template<class T, int N, int Options, int MaxRows, int MaxCols>
249 Eigen::Matrix<T, N, N> expm_pade_scaled(
250 const Eigen::Matrix<T, N, N, Options, MaxRows, MaxCols>& M
251 ){
252 const ExpmPadeParams params = expm_pade_params(M);
253 return expm_pade_scaled(M, params.order, params.scaling);
254 }
255
274 template<class T, int N, int Options, int MaxRows, int MaxCols>
275 Eigen::Matrix<T, N, N> expm(const Eigen::Matrix<T, N, N, Options, MaxRows, MaxCols>& M){
276 // actual exponent calculation
277 return expm_pade_scaled(M);
278 }
279}
The main namespace for the Control++ library.
Definition Bode.cpp:3
Eigen::Matrix< T, N, N > expm(const Eigen::Matrix< T, N, N, Options, MaxRows, MaxCols > &M)
Calculates the matrix exponent .
Definition expm.hpp:275
Eigen::Matrix< T, N, N > expm_pade_scaled(const Eigen::Matrix< T, N, N, Options, MaxRows, MaxCols > &M, int order, int scaling)
Applies scaling and squaring to the pade approximation of the matrix exponential.
Definition expm.hpp:162
Eigen::Matrix< T, N, N > expm_pade(const Eigen::Matrix< T, N, N, Options, MaxRows, MaxCols > &A, int Order=5)
Approximates using a pade fraction.
Definition expm.hpp:105
ExpmPadeParams expm_pade_params(const Eigen::Matrix< T, N, N, Options, MaxRows, MaxCols > &M)
Determines the order and scaling factor for the scaled pade approximation of the matrix exponential.
Definition expm.hpp:198
Eigen::Matrix< T, Rows, Cols, Options, MaxRows, MaxCols > expm_taylor_scaled(const Eigen::Matrix< T, Rows, Cols, Options, MaxRows, MaxCols > &M, int taylor_order=8, int scaling=10)
Calculates the matrix exponent .
Definition expm.hpp:74
constexpr void pade_params(T *params, std::size_t size, std::uint32_t m, std::uint32_t n)
Calculates all pade parameters up to the given size.
Definition math.hpp:131
Eigen::Matrix< T, Rows, Cols, Options, MaxRows, MaxCols > expm_taylor(const Eigen::Matrix< T, Rows, Cols, Options, MaxRows, MaxCols > &x, int n)
Exponential function with a taylor approximation.
Definition expm.hpp:32
Pade for the scaled pade matrix exponential.
Definition expm.hpp:179
int scaling
The scaling and squaring factor for the matrix.
Definition expm.hpp:181
int order
The order of the pade approximation.
Definition expm.hpp:180