34 #include <Eigen/Eigenvalues> 35 #include <Eigen/Householder> 46 assert(U.rows() == 2 && U.cols() == 2);
88 double z = (p / scale) * p + (bc_max / scale) * bc_mis;
95 T(1, 1) = d - (bc_max / z) * bc_mis;
110 double sigma = b +
c;
113 double u_sin = -(p / (tau * u_cos)) *
util::sign(1, sigma);
119 T = U.transpose() * T * U;
121 double temp = 0.5 * (T(0, 0) + T(1, 1));
146 double cos1 = sab * tau;
147 double sin1 = sac * tau;
149 temp = U(0, 0) * cos1 - U(1, 0) * sin1;
150 U(1, 0) = U(0, 0) * sin1 + U(1, 0) * cos1;
174 assert(p > 0 && p < 3);
175 assert(q > 0 && q < 3);
176 assert(ra11 + p + q <= T.rows());
180 Eigen::MatrixXd BACKUP = T;
182 const int na = p +
q;
208 const double gamma = 1e3 * std::numeric_limits<double>::epsilon() * T.block(ra11, ra11, na, na).norm();
211 if (!
SylvesterContinuous::solve(T.block(ra11, ra11, p, p), -T.block(ra22, ra22, q, q), -gamma * T.block(ra11, ra22, p, q),
X))
return false;
213 Eigen::MatrixXd G(p + q, q);
214 G.block(0, 0, p, q) = -
X;
215 G.block(p, 0, q, q).setIdentity();
216 G.block(p, 0, q, q) *= gamma;
219 double A_infnorm = T.block(ra11, ra11, na, na).lpNorm<
Eigen::Infinity>();
231 T.block(ra11, ra11, na, T.cols() - ra11).applyOnTheLeft(qr_dec.householderQ().transpose());
232 T.block(0, ra11, ra22 + q, na).applyOnTheRight(qr_dec.householderQ());
233 Q.block(0, ra11, Q.rows(), na).applyOnTheRight(qr_dec.householderQ());
238 constexpr
const double threshold = std::numeric_limits<double>::epsilon() * 2;
239 const double stability_crit = 10.0 * threshold * A_infnorm;
241 if (A21_norm < stability_crit)
244 T.block(ra22, ra11, p, q).setZero();
249 PRINT_WARNING(
"swap_blocks_schur_form(): numerical instability detected: " << A21_norm <<
"/" << stability_crit <<
",\nA21:\n" 250 << T.block(ra22, ra11, q, p));
262 T.block(ra11, ra22, q, T.cols() - ra22).applyOnTheLeft(U.transpose());
265 for (
int i = 0; i < ra11; ++i)
270 map.applyOnTheLeft(U.transpose());
274 for (
int i = 0; i < Q.rows(); ++i)
277 map.applyOnTheLeft(U.transpose());
288 if (T.cols() > ra22 + p) T.block(ra22, ra22 + p, p, T.cols() - ra22 - p).applyOnTheLeft(U.transpose());
291 for (
int i = 0; i < ra22; ++i)
296 map.applyOnTheLeft(U.transpose());
300 for (
int i = 0; i < Q.rows(); ++i)
303 map.applyOnTheLeft(U.transpose());
EIGEN_DEVICE_FUNC Index outerStride() const
bool have_equal_size(const Eigen::MatrixBase< DerivedA > &matrix1, const Eigen::MatrixBase< DerivedB > &matrix2)
Determine if two matrices exhibit equal sizes/dimensions.
#define PRINT_WARNING(msg)
Print msg-stream.
A matrix or vector expression mapping an existing array of data.
EIGEN_DEVICE_FUNC const SqrtReturnType sqrt() const
bool swap_schur_blocks(Eigen::Ref< Eigen::MatrixXd > T, int ra11, int p, int q, Eigen::Ref< Eigen::MatrixXd > Q, bool standardize)
bool is_square(const Eigen::MatrixBase< Derived > &matrix)
Determine if a given matrix is square.
static bool solve(const Eigen::Ref< const Eigen::MatrixXd > &A, const Eigen::Ref< const Eigen::MatrixXd > &B, const Eigen::Ref< const Eigen::MatrixXd > &C, Eigen::MatrixXd &X)
Solve continuous-time Sylvester equation.
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const AbsReturnType abs() const
void schur_decomposition_2d(Eigen::Ref< Eigen::Matrix2d > T, Eigen::Ref< Eigen::Matrix2d > U)
Perform the 2D Real Schur decompositionIn contrast to Eigen::RealSchur this function enforces diagona...
double l2_norm_2d(double a, double b)
Compute the l2 norm of a 2d vector [a,b] as sqrt(a*a+b*b)
Convenience specialization of Stride to specify only an inner stride See class Map for some examples...
EIGEN_DEVICE_FUNC const Scalar & q
A matrix or vector expression mapping an existing expression.
Householder QR decomposition of a matrix.
bool approx_zero(double val, double epsilon=1e-10)
Check if a double is appoximately zero.
bool essentially_equal(double a, double b, double epsilon=1e-6)
Check if two doubles are essentially equal.
int sign(T val)
Signum function.