10#ifndef EIGEN_COMPANION_H
11#define EIGEN_COMPANION_H
18#include "./InternalHeaderCheck.h"
24#ifndef EIGEN_PARSED_BY_DOXYGEN
27struct decrement_if_fixed_size {
28 enum { ret = (Size ==
Dynamic) ? Dynamic : Size - 1 };
33template <
typename Scalar_,
int Deg_>
36 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar_, Deg_ == Dynamic ? Dynamic : Deg_)
38 enum { Deg = Deg_, Deg_1 = decrement_if_fixed_size<Deg>::ret };
40 typedef Scalar_ Scalar;
41 typedef typename NumTraits<Scalar>::Real RealScalar;
42 typedef Matrix<Scalar, Deg, 1> RightColumn;
44 typedef Matrix<Scalar, Deg_1, 1> BottomLeftDiagonal;
46 typedef Matrix<Scalar, Deg, Deg> DenseCompanionMatrixType;
47 typedef Matrix<Scalar, Deg_, Deg_1> LeftBlock;
48 typedef Matrix<Scalar, Deg_1, Deg_1> BottomLeftBlock;
49 typedef Matrix<Scalar, 1, Deg_1> LeftBlockFirstRow;
51 typedef DenseIndex
Index;
54 EIGEN_STRONG_INLINE
const Scalar_ operator()(Index row, Index col)
const {
55 if (m_bl_diag.rows() > col) {
57 return m_bl_diag[col];
67 template <
typename VectorType>
68 void setPolynomial(
const VectorType& poly) {
69 const Index deg = poly.size() - 1;
70 m_monic = -poly.head(deg) / poly[deg];
71 m_bl_diag.setOnes(deg - 1);
74 template <
typename VectorType>
75 companion(
const VectorType& poly) {
80 DenseCompanionMatrixType denseMatrix()
const {
81 const Index deg = m_monic.size();
82 const Index deg_1 = deg - 1;
83 DenseCompanionMatrixType companMat(deg, deg);
84 companMat << (LeftBlock(deg, deg_1) << LeftBlockFirstRow::Zero(1, deg_1),
85 BottomLeftBlock::Identity(deg - 1, deg - 1) * m_bl_diag.asDiagonal())
98 bool balanced(RealScalar colNorm, RealScalar rowNorm,
bool& isBalanced, RealScalar& colB, RealScalar& rowB);
106 bool balancedR(RealScalar colNorm, RealScalar rowNorm,
bool& isBalanced, RealScalar& colB, RealScalar& rowB);
121 BottomLeftDiagonal m_bl_diag;
124template <
typename Scalar_,
int Deg_>
125inline bool companion<Scalar_, Deg_>::balanced(RealScalar colNorm, RealScalar rowNorm,
bool& isBalanced,
126 RealScalar& colB, RealScalar& rowB) {
127 if (RealScalar(0) == colNorm || RealScalar(0) == rowNorm || !(numext::isfinite)(colNorm) ||
128 !(numext::isfinite)(rowNorm)) {
136 const RealScalar radix = RealScalar(2);
137 const RealScalar radix2 = RealScalar(4);
139 rowB = rowNorm / radix;
140 colB = RealScalar(1);
141 const RealScalar s = colNorm + rowNorm;
144 RealScalar scout = colNorm;
145 while (scout < rowB) {
152 scout = colNorm * (colB / radix) * colB;
153 while (scout >= rowNorm) {
159 if ((rowNorm + radix * scout) < RealScalar(0.95) * s * colB) {
161 rowB = RealScalar(1) / colB;
169template <
typename Scalar_,
int Deg_>
170inline bool companion<Scalar_, Deg_>::balancedR(RealScalar colNorm, RealScalar rowNorm,
bool& isBalanced,
171 RealScalar& colB, RealScalar& rowB) {
172 if (RealScalar(0) == colNorm || RealScalar(0) == rowNorm) {
179 const RealScalar q = colNorm / rowNorm;
180 if (!isApprox(q, Scalar_(1))) {
181 rowB =
sqrt(colNorm / rowNorm);
182 colB = RealScalar(1) / rowB;
192template <
typename Scalar_,
int Deg_>
193void companion<Scalar_, Deg_>::balance() {
195 EIGEN_STATIC_ASSERT(Deg == Dynamic || 1 < Deg, YOU_MADE_A_PROGRAMMING_MISTAKE);
196 const Index deg = m_monic.size();
197 const Index deg_1 = deg - 1;
199 bool hasConverged =
false;
200 while (!hasConverged) {
202 RealScalar colNorm, rowNorm;
203 RealScalar colB, rowB;
207 colNorm =
abs(m_bl_diag[0]);
208 rowNorm =
abs(m_monic[0]);
211 if (!balanced(colNorm, rowNorm, hasConverged, colB, rowB)) {
212 m_bl_diag[0] *= colB;
218 for (Index i = 1; i < deg_1; ++i) {
220 colNorm =
abs(m_bl_diag[i]);
223 rowNorm =
abs(m_bl_diag[i - 1]) +
abs(m_monic[i]);
226 if (!balanced(colNorm, rowNorm, hasConverged, colB, rowB)) {
227 m_bl_diag[i] *= colB;
228 m_bl_diag[i - 1] *= rowB;
235 const Index ebl = m_bl_diag.size() - 1;
236 VectorBlock<RightColumn, Deg_1> headMonic(m_monic, 0, deg_1);
237 colNorm = headMonic.array().abs().sum();
238 rowNorm =
abs(m_bl_diag[ebl]);
241 if (!balanced(colNorm, rowNorm, hasConverged, colB, rowB)) {
243 m_bl_diag[ebl] *= rowB;
Namespace containing all symbols from the Eigen library.
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_sqrt_op< typename Derived::Scalar >, const Derived > sqrt(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs_op< typename Derived::Scalar >, const Derived > abs(const Eigen::ArrayBase< Derived > &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index