File indexing completed on 2025-01-18 09:57:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef EIGEN_COMPANION_H
0011 #define EIGEN_COMPANION_H
0012
0013
0014
0015
0016
0017 namespace Eigen {
0018
0019 namespace internal {
0020
0021 #ifndef EIGEN_PARSED_BY_DOXYGEN
0022
0023 template<int Size>
0024 struct decrement_if_fixed_size
0025 {
0026 enum {
0027 ret = (Size == Dynamic) ? Dynamic : Size-1 };
0028 };
0029
0030 #endif
0031
0032 template< typename _Scalar, int _Deg >
0033 class companion
0034 {
0035 public:
0036 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Deg==Dynamic ? Dynamic : _Deg)
0037
0038 enum {
0039 Deg = _Deg,
0040 Deg_1=decrement_if_fixed_size<Deg>::ret
0041 };
0042
0043 typedef _Scalar Scalar;
0044 typedef typename NumTraits<Scalar>::Real RealScalar;
0045 typedef Matrix<Scalar, Deg, 1> RightColumn;
0046
0047 typedef Matrix<Scalar, Deg_1, 1> BottomLeftDiagonal;
0048
0049 typedef Matrix<Scalar, Deg, Deg> DenseCompanionMatrixType;
0050 typedef Matrix< Scalar, _Deg, Deg_1 > LeftBlock;
0051 typedef Matrix< Scalar, Deg_1, Deg_1 > BottomLeftBlock;
0052 typedef Matrix< Scalar, 1, Deg_1 > LeftBlockFirstRow;
0053
0054 typedef DenseIndex Index;
0055
0056 public:
0057 EIGEN_STRONG_INLINE const _Scalar operator()(Index row, Index col ) const
0058 {
0059 if( m_bl_diag.rows() > col )
0060 {
0061 if( 0 < row ){ return m_bl_diag[col]; }
0062 else{ return 0; }
0063 }
0064 else{ return m_monic[row]; }
0065 }
0066
0067 public:
0068 template<typename VectorType>
0069 void setPolynomial( const VectorType& poly )
0070 {
0071 const Index deg = poly.size()-1;
0072 m_monic = -poly.head(deg)/poly[deg];
0073 m_bl_diag.setOnes(deg-1);
0074 }
0075
0076 template<typename VectorType>
0077 companion( const VectorType& poly ){
0078 setPolynomial( poly ); }
0079
0080 public:
0081 DenseCompanionMatrixType denseMatrix() const
0082 {
0083 const Index deg = m_monic.size();
0084 const Index deg_1 = deg-1;
0085 DenseCompanionMatrixType companMat(deg,deg);
0086 companMat <<
0087 ( LeftBlock(deg,deg_1)
0088 << LeftBlockFirstRow::Zero(1,deg_1),
0089 BottomLeftBlock::Identity(deg-1,deg-1)*m_bl_diag.asDiagonal() ).finished()
0090 , m_monic;
0091 return companMat;
0092 }
0093
0094
0095
0096 protected:
0097
0098
0099
0100
0101
0102
0103 bool balanced( RealScalar colNorm, RealScalar rowNorm,
0104 bool& isBalanced, RealScalar& colB, RealScalar& rowB );
0105
0106
0107
0108
0109
0110
0111
0112 bool balancedR( RealScalar colNorm, RealScalar rowNorm,
0113 bool& isBalanced, RealScalar& colB, RealScalar& rowB );
0114
0115 public:
0116
0117
0118
0119
0120
0121
0122
0123
0124 void balance();
0125
0126 protected:
0127 RightColumn m_monic;
0128 BottomLeftDiagonal m_bl_diag;
0129 };
0130
0131
0132
0133 template< typename _Scalar, int _Deg >
0134 inline
0135 bool companion<_Scalar,_Deg>::balanced( RealScalar colNorm, RealScalar rowNorm,
0136 bool& isBalanced, RealScalar& colB, RealScalar& rowB )
0137 {
0138 if( RealScalar(0) == colNorm || RealScalar(0) == rowNorm
0139 || !(numext::isfinite)(colNorm) || !(numext::isfinite)(rowNorm)){
0140 return true;
0141 }
0142 else
0143 {
0144
0145
0146
0147
0148
0149 const RealScalar radix = RealScalar(2);
0150 const RealScalar radix2 = RealScalar(4);
0151
0152 rowB = rowNorm / radix;
0153 colB = RealScalar(1);
0154 const RealScalar s = colNorm + rowNorm;
0155
0156
0157 RealScalar scout = colNorm;
0158 while (scout < rowB)
0159 {
0160 colB *= radix;
0161 scout *= radix2;
0162 }
0163
0164
0165
0166 scout = colNorm * (colB / radix) * colB;
0167 while (scout >= rowNorm)
0168 {
0169 colB /= radix;
0170 scout /= radix2;
0171 }
0172
0173
0174 if ((rowNorm + radix * scout) < RealScalar(0.95) * s * colB)
0175 {
0176 isBalanced = false;
0177 rowB = RealScalar(1) / colB;
0178 return false;
0179 }
0180 else
0181 {
0182 return true;
0183 }
0184 }
0185 }
0186
0187 template< typename _Scalar, int _Deg >
0188 inline
0189 bool companion<_Scalar,_Deg>::balancedR( RealScalar colNorm, RealScalar rowNorm,
0190 bool& isBalanced, RealScalar& colB, RealScalar& rowB )
0191 {
0192 if( RealScalar(0) == colNorm || RealScalar(0) == rowNorm ){ return true; }
0193 else
0194 {
0195
0196
0197
0198
0199 const RealScalar q = colNorm/rowNorm;
0200 if( !isApprox( q, _Scalar(1) ) )
0201 {
0202 rowB = sqrt( colNorm/rowNorm );
0203 colB = RealScalar(1)/rowB;
0204
0205 isBalanced = false;
0206 return false;
0207 }
0208 else{
0209 return true; }
0210 }
0211 }
0212
0213
0214 template< typename _Scalar, int _Deg >
0215 void companion<_Scalar,_Deg>::balance()
0216 {
0217 using std::abs;
0218 EIGEN_STATIC_ASSERT( Deg == Dynamic || 1 < Deg, YOU_MADE_A_PROGRAMMING_MISTAKE );
0219 const Index deg = m_monic.size();
0220 const Index deg_1 = deg-1;
0221
0222 bool hasConverged=false;
0223 while( !hasConverged )
0224 {
0225 hasConverged = true;
0226 RealScalar colNorm,rowNorm;
0227 RealScalar colB,rowB;
0228
0229
0230
0231 colNorm = abs(m_bl_diag[0]);
0232 rowNorm = abs(m_monic[0]);
0233
0234
0235 if( !balanced( colNorm, rowNorm, hasConverged, colB, rowB ) )
0236 {
0237 m_bl_diag[0] *= colB;
0238 m_monic[0] *= rowB;
0239 }
0240
0241
0242
0243 for( Index i=1; i<deg_1; ++i )
0244 {
0245
0246 colNorm = abs(m_bl_diag[i]);
0247
0248
0249 rowNorm = abs(m_bl_diag[i-1]) + abs(m_monic[i]);
0250
0251
0252 if( !balanced( colNorm, rowNorm, hasConverged, colB, rowB ) )
0253 {
0254 m_bl_diag[i] *= colB;
0255 m_bl_diag[i-1] *= rowB;
0256 m_monic[i] *= rowB;
0257 }
0258 }
0259
0260
0261
0262 const Index ebl = m_bl_diag.size()-1;
0263 VectorBlock<RightColumn,Deg_1> headMonic( m_monic, 0, deg_1 );
0264 colNorm = headMonic.array().abs().sum();
0265 rowNorm = abs( m_bl_diag[ebl] );
0266
0267
0268 if( !balanced( colNorm, rowNorm, hasConverged, colB, rowB ) )
0269 {
0270 headMonic *= colB;
0271 m_bl_diag[ebl] *= rowB;
0272 }
0273 }
0274 }
0275
0276 }
0277
0278 }
0279
0280 #endif