You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
5.6 KiB

  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
  5. //
  6. // This Source Code Form is subject to the terms of the Mozilla
  7. // Public License v. 2.0. If a copy of the MPL was not distributed
  8. // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. #ifndef EIGEN_BIDIAGONALIZATION_H
  10. #define EIGEN_BIDIAGONALIZATION_H
  11. namespace Eigen {
  12. namespace internal {
  13. // UpperBidiagonalization will probably be replaced by a Bidiagonalization class, don't want to make it stable API.
  14. // At the same time, it's useful to keep for now as it's about the only thing that is testing the BandMatrix class.
  15. template<typename _MatrixType> class UpperBidiagonalization
  16. {
  17. public:
  18. typedef _MatrixType MatrixType;
  19. enum {
  20. RowsAtCompileTime = MatrixType::RowsAtCompileTime,
  21. ColsAtCompileTime = MatrixType::ColsAtCompileTime,
  22. ColsAtCompileTimeMinusOne = internal::decrement_size<ColsAtCompileTime>::ret
  23. };
  24. typedef typename MatrixType::Scalar Scalar;
  25. typedef typename MatrixType::RealScalar RealScalar;
  26. typedef typename MatrixType::Index Index;
  27. typedef Matrix<Scalar, 1, ColsAtCompileTime> RowVectorType;
  28. typedef Matrix<Scalar, RowsAtCompileTime, 1> ColVectorType;
  29. typedef BandMatrix<RealScalar, ColsAtCompileTime, ColsAtCompileTime, 1, 0> BidiagonalType;
  30. typedef Matrix<Scalar, ColsAtCompileTime, 1> DiagVectorType;
  31. typedef Matrix<Scalar, ColsAtCompileTimeMinusOne, 1> SuperDiagVectorType;
  32. typedef HouseholderSequence<
  33. const MatrixType,
  34. CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, const Diagonal<const MatrixType,0> >
  35. > HouseholderUSequenceType;
  36. typedef HouseholderSequence<
  37. const MatrixType,
  38. Diagonal<const MatrixType,1>,
  39. OnTheRight
  40. > HouseholderVSequenceType;
  41. /**
  42. * \brief Default Constructor.
  43. *
  44. * The default constructor is useful in cases in which the user intends to
  45. * perform decompositions via Bidiagonalization::compute(const MatrixType&).
  46. */
  47. UpperBidiagonalization() : m_householder(), m_bidiagonal(), m_isInitialized(false) {}
  48. UpperBidiagonalization(const MatrixType& matrix)
  49. : m_householder(matrix.rows(), matrix.cols()),
  50. m_bidiagonal(matrix.cols(), matrix.cols()),
  51. m_isInitialized(false)
  52. {
  53. compute(matrix);
  54. }
  55. UpperBidiagonalization& compute(const MatrixType& matrix);
  56. const MatrixType& householder() const { return m_householder; }
  57. const BidiagonalType& bidiagonal() const { return m_bidiagonal; }
  58. const HouseholderUSequenceType householderU() const
  59. {
  60. eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized.");
  61. return HouseholderUSequenceType(m_householder, m_householder.diagonal().conjugate());
  62. }
  63. const HouseholderVSequenceType householderV() // const here gives nasty errors and i'm lazy
  64. {
  65. eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized.");
  66. return HouseholderVSequenceType(m_householder, m_householder.const_derived().template diagonal<1>())
  67. .setLength(m_householder.cols()-1)
  68. .setShift(1);
  69. }
  70. protected:
  71. MatrixType m_householder;
  72. BidiagonalType m_bidiagonal;
  73. bool m_isInitialized;
  74. };
  75. template<typename _MatrixType>
  76. UpperBidiagonalization<_MatrixType>& UpperBidiagonalization<_MatrixType>::compute(const _MatrixType& matrix)
  77. {
  78. Index rows = matrix.rows();
  79. Index cols = matrix.cols();
  80. eigen_assert(rows >= cols && "UpperBidiagonalization is only for matrices satisfying rows>=cols.");
  81. m_householder = matrix;
  82. ColVectorType temp(rows);
  83. for (Index k = 0; /* breaks at k==cols-1 below */ ; ++k)
  84. {
  85. Index remainingRows = rows - k;
  86. Index remainingCols = cols - k - 1;
  87. // construct left householder transform in-place in m_householder
  88. m_householder.col(k).tail(remainingRows)
  89. .makeHouseholderInPlace(m_householder.coeffRef(k,k),
  90. m_bidiagonal.template diagonal<0>().coeffRef(k));
  91. // apply householder transform to remaining part of m_householder on the left
  92. m_householder.bottomRightCorner(remainingRows, remainingCols)
  93. .applyHouseholderOnTheLeft(m_householder.col(k).tail(remainingRows-1),
  94. m_householder.coeff(k,k),
  95. temp.data());
  96. if(k == cols-1) break;
  97. // construct right householder transform in-place in m_householder
  98. m_householder.row(k).tail(remainingCols)
  99. .makeHouseholderInPlace(m_householder.coeffRef(k,k+1),
  100. m_bidiagonal.template diagonal<1>().coeffRef(k));
  101. // apply householder transform to remaining part of m_householder on the left
  102. m_householder.bottomRightCorner(remainingRows-1, remainingCols)
  103. .applyHouseholderOnTheRight(m_householder.row(k).tail(remainingCols-1).transpose(),
  104. m_householder.coeff(k,k+1),
  105. temp.data());
  106. }
  107. m_isInitialized = true;
  108. return *this;
  109. }
  110. #if 0
  111. /** \return the Householder QR decomposition of \c *this.
  112. *
  113. * \sa class Bidiagonalization
  114. */
  115. template<typename Derived>
  116. const UpperBidiagonalization<typename MatrixBase<Derived>::PlainObject>
  117. MatrixBase<Derived>::bidiagonalization() const
  118. {
  119. return UpperBidiagonalization<PlainObject>(eval());
  120. }
  121. #endif
  122. } // end namespace internal
  123. } // end namespace Eigen
  124. #endif // EIGEN_BIDIAGONALIZATION_H