10 #ifndef EIGEN_COMPANION_H
11 #define EIGEN_COMPANION_H
21 #ifndef EIGEN_PARSED_BY_DOXYGEN
24 T radix(){
return 2; }
27 T radix2(){
return radix<T>()*radix<T>(); }
30 struct decrement_if_fixed_size
33 ret = (Size == Dynamic) ? Dynamic : Size-1 };
38 template<
typename _Scalar,
int _Deg >
42 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Deg==Dynamic ? Dynamic : _Deg)
46 Deg_1=decrement_if_fixed_size<Deg>::ret
49 typedef _Scalar Scalar;
50 typedef typename NumTraits<Scalar>::Real RealScalar;
51 typedef Matrix<Scalar, Deg, 1> RightColumn;
53 typedef Matrix<Scalar, Deg_1, 1> BottomLeftDiagonal;
55 typedef Matrix<Scalar, Deg, Deg> DenseCompanionMatrixType;
56 typedef Matrix< Scalar, _Deg, Deg_1 > LeftBlock;
57 typedef Matrix< Scalar, Deg_1, Deg_1 > BottomLeftBlock;
58 typedef Matrix< Scalar, 1, Deg_1 > LeftBlockFirstRow;
60 typedef DenseIndex Index;
63 EIGEN_STRONG_INLINE
const _Scalar operator()(Index row, Index col )
const
65 if( m_bl_diag.rows() > col )
67 if( 0 < row ){
return m_bl_diag[col]; }
70 else{
return m_monic[row]; }
74 template<
typename VectorType>
75 void setPolynomial(
const VectorType& poly )
77 const Index deg = poly.size()-1;
78 m_monic = -1/poly[deg] * poly.head(deg);
80 m_bl_diag.setOnes(deg-1);
83 template<
typename VectorType>
84 companion(
const VectorType& poly ){
85 setPolynomial( poly ); }
88 DenseCompanionMatrixType denseMatrix()
const
90 const Index deg = m_monic.size();
91 const Index deg_1 = deg-1;
92 DenseCompanionMatrixType companion(deg,deg);
94 ( LeftBlock(deg,deg_1)
95 << LeftBlockFirstRow::Zero(1,deg_1),
96 BottomLeftBlock::Identity(deg-1,deg-1)*m_bl_diag.asDiagonal() ).finished()
110 bool balanced( Scalar colNorm, Scalar rowNorm,
111 bool& isBalanced, Scalar& colB, Scalar& rowB );
119 bool balancedR( Scalar colNorm, Scalar rowNorm,
120 bool& isBalanced, Scalar& colB, Scalar& rowB );
135 BottomLeftDiagonal m_bl_diag;
140 template<
typename _Scalar,
int _Deg >
142 bool companion<_Scalar,_Deg>::balanced( Scalar colNorm, Scalar rowNorm,
143 bool& isBalanced, Scalar& colB, Scalar& rowB )
145 if( Scalar(0) == colNorm || Scalar(0) == rowNorm ){
return true; }
153 rowB = rowNorm / radix<Scalar>();
155 const Scalar s = colNorm + rowNorm;
157 while (colNorm < rowB)
159 colB *= radix<Scalar>();
160 colNorm *= radix2<Scalar>();
163 rowB = rowNorm * radix<Scalar>();
165 while (colNorm >= rowB)
167 colB /= radix<Scalar>();
168 colNorm /= radix2<Scalar>();
172 if ((rowNorm + colNorm) < Scalar(0.95) * s * colB)
175 rowB = Scalar(1) / colB;
183 template<
typename _Scalar,
int _Deg >
185 bool companion<_Scalar,_Deg>::balancedR( Scalar colNorm, Scalar rowNorm,
186 bool& isBalanced, Scalar& colB, Scalar& rowB )
188 if( Scalar(0) == colNorm || Scalar(0) == rowNorm ){
return true; }
195 const _Scalar q = colNorm/rowNorm;
196 if( !isApprox( q, _Scalar(1) ) )
198 rowB = sqrt( colNorm/rowNorm );
199 colB = Scalar(1)/rowB;
210 template<
typename _Scalar,
int _Deg >
211 void companion<_Scalar,_Deg>::balance()
214 EIGEN_STATIC_ASSERT( Deg == Dynamic || 1 < Deg, YOU_MADE_A_PROGRAMMING_MISTAKE );
215 const Index deg = m_monic.size();
216 const Index deg_1 = deg-1;
218 bool hasConverged=
false;
219 while( !hasConverged )
222 Scalar colNorm,rowNorm;
227 colNorm = abs(m_bl_diag[0]);
228 rowNorm = abs(m_monic[0]);
231 if( !balanced( colNorm, rowNorm, hasConverged, colB, rowB ) )
233 m_bl_diag[0] *= colB;
239 for( Index i=1; i<deg_1; ++i )
242 colNorm = abs(m_bl_diag[i]);
245 rowNorm = abs(m_bl_diag[i-1]) + abs(m_monic[i]);
248 if( !balanced( colNorm, rowNorm, hasConverged, colB, rowB ) )
250 m_bl_diag[i] *= colB;
251 m_bl_diag[i-1] *= rowB;
258 const Index ebl = m_bl_diag.size()-1;
259 VectorBlock<RightColumn,Deg_1> headMonic( m_monic, 0, deg_1 );
260 colNorm = headMonic.array().abs().sum();
261 rowNorm = abs( m_bl_diag[ebl] );
264 if( !balanced( colNorm, rowNorm, hasConverged, colB, rowB ) )
267 m_bl_diag[ebl] *= rowB;
276 #endif // EIGEN_COMPANION_H