Warning, file /include/eigen3/Eigen/src/SVD/UpperBidiagonalization.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef EIGEN_BIDIAGONALIZATION_H
0012 #define EIGEN_BIDIAGONALIZATION_H
0013
0014 namespace Eigen {
0015
0016 namespace internal {
0017
0018
0019
0020 template<typename _MatrixType> class UpperBidiagonalization
0021 {
0022 public:
0023
0024 typedef _MatrixType MatrixType;
0025 enum {
0026 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
0027 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
0028 ColsAtCompileTimeMinusOne = internal::decrement_size<ColsAtCompileTime>::ret
0029 };
0030 typedef typename MatrixType::Scalar Scalar;
0031 typedef typename MatrixType::RealScalar RealScalar;
0032 typedef Eigen::Index Index;
0033 typedef Matrix<Scalar, 1, ColsAtCompileTime> RowVectorType;
0034 typedef Matrix<Scalar, RowsAtCompileTime, 1> ColVectorType;
0035 typedef BandMatrix<RealScalar, ColsAtCompileTime, ColsAtCompileTime, 1, 0, RowMajor> BidiagonalType;
0036 typedef Matrix<Scalar, ColsAtCompileTime, 1> DiagVectorType;
0037 typedef Matrix<Scalar, ColsAtCompileTimeMinusOne, 1> SuperDiagVectorType;
0038 typedef HouseholderSequence<
0039 const MatrixType,
0040 const typename internal::remove_all<typename Diagonal<const MatrixType,0>::ConjugateReturnType>::type
0041 > HouseholderUSequenceType;
0042 typedef HouseholderSequence<
0043 const typename internal::remove_all<typename MatrixType::ConjugateReturnType>::type,
0044 Diagonal<const MatrixType,1>,
0045 OnTheRight
0046 > HouseholderVSequenceType;
0047
0048
0049
0050
0051
0052
0053
0054 UpperBidiagonalization() : m_householder(), m_bidiagonal(), m_isInitialized(false) {}
0055
0056 explicit UpperBidiagonalization(const MatrixType& matrix)
0057 : m_householder(matrix.rows(), matrix.cols()),
0058 m_bidiagonal(matrix.cols(), matrix.cols()),
0059 m_isInitialized(false)
0060 {
0061 compute(matrix);
0062 }
0063
0064 UpperBidiagonalization& compute(const MatrixType& matrix);
0065 UpperBidiagonalization& computeUnblocked(const MatrixType& matrix);
0066
0067 const MatrixType& householder() const { return m_householder; }
0068 const BidiagonalType& bidiagonal() const { return m_bidiagonal; }
0069
0070 const HouseholderUSequenceType householderU() const
0071 {
0072 eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized.");
0073 return HouseholderUSequenceType(m_householder, m_householder.diagonal().conjugate());
0074 }
0075
0076 const HouseholderVSequenceType householderV()
0077 {
0078 eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized.");
0079 return HouseholderVSequenceType(m_householder.conjugate(), m_householder.const_derived().template diagonal<1>())
0080 .setLength(m_householder.cols()-1)
0081 .setShift(1);
0082 }
0083
0084 protected:
0085 MatrixType m_householder;
0086 BidiagonalType m_bidiagonal;
0087 bool m_isInitialized;
0088 };
0089
0090
0091
0092 template<typename MatrixType>
0093 void upperbidiagonalization_inplace_unblocked(MatrixType& mat,
0094 typename MatrixType::RealScalar *diagonal,
0095 typename MatrixType::RealScalar *upper_diagonal,
0096 typename MatrixType::Scalar* tempData = 0)
0097 {
0098 typedef typename MatrixType::Scalar Scalar;
0099
0100 Index rows = mat.rows();
0101 Index cols = mat.cols();
0102
0103 typedef Matrix<Scalar,Dynamic,1,ColMajor,MatrixType::MaxRowsAtCompileTime,1> TempType;
0104 TempType tempVector;
0105 if(tempData==0)
0106 {
0107 tempVector.resize(rows);
0108 tempData = tempVector.data();
0109 }
0110
0111 for (Index k = 0; ; ++k)
0112 {
0113 Index remainingRows = rows - k;
0114 Index remainingCols = cols - k - 1;
0115
0116
0117 mat.col(k).tail(remainingRows)
0118 .makeHouseholderInPlace(mat.coeffRef(k,k), diagonal[k]);
0119
0120 mat.bottomRightCorner(remainingRows, remainingCols)
0121 .applyHouseholderOnTheLeft(mat.col(k).tail(remainingRows-1), mat.coeff(k,k), tempData);
0122
0123 if(k == cols-1) break;
0124
0125
0126 mat.row(k).tail(remainingCols)
0127 .makeHouseholderInPlace(mat.coeffRef(k,k+1), upper_diagonal[k]);
0128
0129 mat.bottomRightCorner(remainingRows-1, remainingCols)
0130 .applyHouseholderOnTheRight(mat.row(k).tail(remainingCols-1).adjoint(), mat.coeff(k,k+1), tempData);
0131 }
0132 }
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151 template<typename MatrixType>
0152 void upperbidiagonalization_blocked_helper(MatrixType& A,
0153 typename MatrixType::RealScalar *diagonal,
0154 typename MatrixType::RealScalar *upper_diagonal,
0155 Index bs,
0156 Ref<Matrix<typename MatrixType::Scalar, Dynamic, Dynamic,
0157 traits<MatrixType>::Flags & RowMajorBit> > X,
0158 Ref<Matrix<typename MatrixType::Scalar, Dynamic, Dynamic,
0159 traits<MatrixType>::Flags & RowMajorBit> > Y)
0160 {
0161 typedef typename MatrixType::Scalar Scalar;
0162 typedef typename MatrixType::RealScalar RealScalar;
0163 typedef typename NumTraits<RealScalar>::Literal Literal;
0164 enum { StorageOrder = traits<MatrixType>::Flags & RowMajorBit };
0165 typedef InnerStride<int(StorageOrder) == int(ColMajor) ? 1 : Dynamic> ColInnerStride;
0166 typedef InnerStride<int(StorageOrder) == int(ColMajor) ? Dynamic : 1> RowInnerStride;
0167 typedef Ref<Matrix<Scalar, Dynamic, 1>, 0, ColInnerStride> SubColumnType;
0168 typedef Ref<Matrix<Scalar, 1, Dynamic>, 0, RowInnerStride> SubRowType;
0169 typedef Ref<Matrix<Scalar, Dynamic, Dynamic, StorageOrder > > SubMatType;
0170
0171 Index brows = A.rows();
0172 Index bcols = A.cols();
0173
0174 Scalar tau_u, tau_u_prev(0), tau_v;
0175
0176 for(Index k = 0; k < bs; ++k)
0177 {
0178 Index remainingRows = brows - k;
0179 Index remainingCols = bcols - k - 1;
0180
0181 SubMatType X_k1( X.block(k,0, remainingRows,k) );
0182 SubMatType V_k1( A.block(k,0, remainingRows,k) );
0183
0184
0185 SubColumnType v_k = A.col(k).tail(remainingRows);
0186 v_k -= V_k1 * Y.row(k).head(k).adjoint();
0187 if(k) v_k -= X_k1 * A.col(k).head(k);
0188
0189
0190 v_k.makeHouseholderInPlace(tau_v, diagonal[k]);
0191
0192 if(k+1<bcols)
0193 {
0194 SubMatType Y_k ( Y.block(k+1,0, remainingCols, k+1) );
0195 SubMatType U_k1 ( A.block(0,k+1, k,remainingCols) );
0196
0197
0198
0199 A(k,k) = Scalar(1);
0200
0201
0202 {
0203 SubColumnType y_k( Y.col(k).tail(remainingCols) );
0204
0205
0206 SubColumnType tmp( Y.col(k).head(k) );
0207 y_k.noalias() = A.block(k,k+1, remainingRows,remainingCols).adjoint() * v_k;
0208 tmp.noalias() = V_k1.adjoint() * v_k;
0209 y_k.noalias() -= Y_k.leftCols(k) * tmp;
0210 tmp.noalias() = X_k1.adjoint() * v_k;
0211 y_k.noalias() -= U_k1.adjoint() * tmp;
0212 y_k *= numext::conj(tau_v);
0213 }
0214
0215
0216 SubRowType u_k( A.row(k).tail(remainingCols) );
0217 u_k = u_k.conjugate();
0218 {
0219 u_k -= Y_k * A.row(k).head(k+1).adjoint();
0220 if(k) u_k -= U_k1.adjoint() * X.row(k).head(k).adjoint();
0221 }
0222
0223
0224 u_k.makeHouseholderInPlace(tau_u, upper_diagonal[k]);
0225
0226
0227
0228 A(k,k+1) = Scalar(1);
0229
0230
0231 {
0232 SubColumnType x_k ( X.col(k).tail(remainingRows-1) );
0233
0234
0235
0236 SubColumnType tmp0 ( X.col(k).head(k) ),
0237 tmp1 ( X.col(k).head(k+1) );
0238
0239 x_k.noalias() = A.block(k+1,k+1, remainingRows-1,remainingCols) * u_k.transpose();
0240 tmp0.noalias() = U_k1 * u_k.transpose();
0241 x_k.noalias() -= X_k1.bottomRows(remainingRows-1) * tmp0;
0242 tmp1.noalias() = Y_k.adjoint() * u_k.transpose();
0243 x_k.noalias() -= A.block(k+1,0, remainingRows-1,k+1) * tmp1;
0244 x_k *= numext::conj(tau_u);
0245 tau_u = numext::conj(tau_u);
0246 u_k = u_k.conjugate();
0247 }
0248
0249 if(k>0) A.coeffRef(k-1,k) = tau_u_prev;
0250 tau_u_prev = tau_u;
0251 }
0252 else
0253 A.coeffRef(k-1,k) = tau_u_prev;
0254
0255 A.coeffRef(k,k) = tau_v;
0256 }
0257
0258 if(bs<bcols)
0259 A.coeffRef(bs-1,bs) = tau_u_prev;
0260
0261
0262 if(bcols>bs && brows>bs)
0263 {
0264 SubMatType A11( A.bottomRightCorner(brows-bs,bcols-bs) );
0265 SubMatType A10( A.block(bs,0, brows-bs,bs) );
0266 SubMatType A01( A.block(0,bs, bs,bcols-bs) );
0267 Scalar tmp = A01(bs-1,0);
0268 A01(bs-1,0) = Literal(1);
0269 A11.noalias() -= A10 * Y.topLeftCorner(bcols,bs).bottomRows(bcols-bs).adjoint();
0270 A11.noalias() -= X.topLeftCorner(brows,bs).bottomRows(brows-bs) * A01;
0271 A01(bs-1,0) = tmp;
0272 }
0273 }
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283 template<typename MatrixType, typename BidiagType>
0284 void upperbidiagonalization_inplace_blocked(MatrixType& A, BidiagType& bidiagonal,
0285 Index maxBlockSize=32,
0286 typename MatrixType::Scalar* = 0)
0287 {
0288 typedef typename MatrixType::Scalar Scalar;
0289 typedef Block<MatrixType,Dynamic,Dynamic> BlockType;
0290
0291 Index rows = A.rows();
0292 Index cols = A.cols();
0293 Index size = (std::min)(rows, cols);
0294
0295
0296 enum { StorageOrder = traits<MatrixType>::Flags & RowMajorBit };
0297 Matrix<Scalar,
0298 MatrixType::RowsAtCompileTime,
0299 Dynamic,
0300 StorageOrder,
0301 MatrixType::MaxRowsAtCompileTime> X(rows,maxBlockSize);
0302 Matrix<Scalar,
0303 MatrixType::ColsAtCompileTime,
0304 Dynamic,
0305 StorageOrder,
0306 MatrixType::MaxColsAtCompileTime> Y(cols,maxBlockSize);
0307 Index blockSize = (std::min)(maxBlockSize,size);
0308
0309 Index k = 0;
0310 for(k = 0; k < size; k += blockSize)
0311 {
0312 Index bs = (std::min)(size-k,blockSize);
0313 Index brows = rows - k;
0314 Index bcols = cols - k;
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330 BlockType B = A.block(k,k,brows,bcols);
0331
0332
0333
0334
0335
0336 if(k+bs==cols || bcols<48)
0337 {
0338 upperbidiagonalization_inplace_unblocked(B,
0339 &(bidiagonal.template diagonal<0>().coeffRef(k)),
0340 &(bidiagonal.template diagonal<1>().coeffRef(k)),
0341 X.data()
0342 );
0343 break;
0344 }
0345 else
0346 {
0347 upperbidiagonalization_blocked_helper<BlockType>( B,
0348 &(bidiagonal.template diagonal<0>().coeffRef(k)),
0349 &(bidiagonal.template diagonal<1>().coeffRef(k)),
0350 bs,
0351 X.topLeftCorner(brows,bs),
0352 Y.topLeftCorner(bcols,bs)
0353 );
0354 }
0355 }
0356 }
0357
0358 template<typename _MatrixType>
0359 UpperBidiagonalization<_MatrixType>& UpperBidiagonalization<_MatrixType>::computeUnblocked(const _MatrixType& matrix)
0360 {
0361 Index rows = matrix.rows();
0362 Index cols = matrix.cols();
0363 EIGEN_ONLY_USED_FOR_DEBUG(cols);
0364
0365 eigen_assert(rows >= cols && "UpperBidiagonalization is only for Arices satisfying rows>=cols.");
0366
0367 m_householder = matrix;
0368
0369 ColVectorType temp(rows);
0370
0371 upperbidiagonalization_inplace_unblocked(m_householder,
0372 &(m_bidiagonal.template diagonal<0>().coeffRef(0)),
0373 &(m_bidiagonal.template diagonal<1>().coeffRef(0)),
0374 temp.data());
0375
0376 m_isInitialized = true;
0377 return *this;
0378 }
0379
0380 template<typename _MatrixType>
0381 UpperBidiagonalization<_MatrixType>& UpperBidiagonalization<_MatrixType>::compute(const _MatrixType& matrix)
0382 {
0383 Index rows = matrix.rows();
0384 Index cols = matrix.cols();
0385 EIGEN_ONLY_USED_FOR_DEBUG(rows);
0386 EIGEN_ONLY_USED_FOR_DEBUG(cols);
0387
0388 eigen_assert(rows >= cols && "UpperBidiagonalization is only for Arices satisfying rows>=cols.");
0389
0390 m_householder = matrix;
0391 upperbidiagonalization_inplace_blocked(m_householder, m_bidiagonal);
0392
0393 m_isInitialized = true;
0394 return *this;
0395 }
0396
0397 #if 0
0398
0399
0400
0401
0402 template<typename Derived>
0403 const UpperBidiagonalization<typename MatrixBase<Derived>::PlainObject>
0404 MatrixBase<Derived>::bidiagonalization() const
0405 {
0406 return UpperBidiagonalization<PlainObject>(eval());
0407 }
0408 #endif
0409
0410 }
0411
0412 }
0413
0414 #endif