Householder.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. // Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
  6. //
  7. // This Source Code Form is subject to the terms of the Mozilla
  8. // Public License v. 2.0. If a copy of the MPL was not distributed
  9. // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  10. #ifndef EIGEN_HOUSEHOLDER_H
  11. #define EIGEN_HOUSEHOLDER_H
  12. namespace Eigen {
  13. namespace internal {
  14. template<int n> struct decrement_size
  15. {
  16. enum {
  17. ret = n==Dynamic ? n : n-1
  18. };
  19. };
  20. }
  21. /** Computes the elementary reflector H such that:
  22. * \f$ H *this = [ beta 0 ... 0]^T \f$
  23. * where the transformation H is:
  24. * \f$ H = I - tau v v^*\f$
  25. * and the vector v is:
  26. * \f$ v^T = [1 essential^T] \f$
  27. *
  28. * The essential part of the vector \c v is stored in *this.
  29. *
  30. * On output:
  31. * \param tau the scaling factor of the Householder transformation
  32. * \param beta the result of H * \c *this
  33. *
  34. * \sa MatrixBase::makeHouseholder(), MatrixBase::applyHouseholderOnTheLeft(),
  35. * MatrixBase::applyHouseholderOnTheRight()
  36. */
  37. template<typename Derived>
  38. void MatrixBase<Derived>::makeHouseholderInPlace(Scalar& tau, RealScalar& beta)
  39. {
  40. VectorBlock<Derived, internal::decrement_size<Base::SizeAtCompileTime>::ret> essentialPart(derived(), 1, size()-1);
  41. makeHouseholder(essentialPart, tau, beta);
  42. }
  43. /** Computes the elementary reflector H such that:
  44. * \f$ H *this = [ beta 0 ... 0]^T \f$
  45. * where the transformation H is:
  46. * \f$ H = I - tau v v^*\f$
  47. * and the vector v is:
  48. * \f$ v^T = [1 essential^T] \f$
  49. *
  50. * On output:
  51. * \param essential the essential part of the vector \c v
  52. * \param tau the scaling factor of the Householder transformation
  53. * \param beta the result of H * \c *this
  54. *
  55. * \sa MatrixBase::makeHouseholderInPlace(), MatrixBase::applyHouseholderOnTheLeft(),
  56. * MatrixBase::applyHouseholderOnTheRight()
  57. */
  58. template<typename Derived>
  59. template<typename EssentialPart>
  60. void MatrixBase<Derived>::makeHouseholder(
  61. EssentialPart& essential,
  62. Scalar& tau,
  63. RealScalar& beta) const
  64. {
  65. using std::sqrt;
  66. using numext::conj;
  67. EIGEN_STATIC_ASSERT_VECTOR_ONLY(EssentialPart)
  68. VectorBlock<const Derived, EssentialPart::SizeAtCompileTime> tail(derived(), 1, size()-1);
  69. RealScalar tailSqNorm = size()==1 ? RealScalar(0) : tail.squaredNorm();
  70. Scalar c0 = coeff(0);
  71. const RealScalar tol = (std::numeric_limits<RealScalar>::min)();
  72. if(tailSqNorm <= tol && numext::abs2(numext::imag(c0))<=tol)
  73. {
  74. tau = RealScalar(0);
  75. beta = numext::real(c0);
  76. essential.setZero();
  77. }
  78. else
  79. {
  80. beta = sqrt(numext::abs2(c0) + tailSqNorm);
  81. if (numext::real(c0)>=RealScalar(0))
  82. beta = -beta;
  83. essential = tail / (c0 - beta);
  84. tau = conj((beta - c0) / beta);
  85. }
  86. }
  87. /** Apply the elementary reflector H given by
  88. * \f$ H = I - tau v v^*\f$
  89. * with
  90. * \f$ v^T = [1 essential^T] \f$
  91. * from the left to a vector or matrix.
  92. *
  93. * On input:
  94. * \param essential the essential part of the vector \c v
  95. * \param tau the scaling factor of the Householder transformation
  96. * \param workspace a pointer to working space with at least
  97. * this->cols() * essential.size() entries
  98. *
  99. * \sa MatrixBase::makeHouseholder(), MatrixBase::makeHouseholderInPlace(),
  100. * MatrixBase::applyHouseholderOnTheRight()
  101. */
  102. template<typename Derived>
  103. template<typename EssentialPart>
  104. void MatrixBase<Derived>::applyHouseholderOnTheLeft(
  105. const EssentialPart& essential,
  106. const Scalar& tau,
  107. Scalar* workspace)
  108. {
  109. if(rows() == 1)
  110. {
  111. *this *= Scalar(1)-tau;
  112. }
  113. else if(tau!=Scalar(0))
  114. {
  115. Map<typename internal::plain_row_type<PlainObject>::type> tmp(workspace,cols());
  116. Block<Derived, EssentialPart::SizeAtCompileTime, Derived::ColsAtCompileTime> bottom(derived(), 1, 0, rows()-1, cols());
  117. tmp.noalias() = essential.adjoint() * bottom;
  118. tmp += this->row(0);
  119. this->row(0) -= tau * tmp;
  120. bottom.noalias() -= tau * essential * tmp;
  121. }
  122. }
  123. /** Apply the elementary reflector H given by
  124. * \f$ H = I - tau v v^*\f$
  125. * with
  126. * \f$ v^T = [1 essential^T] \f$
  127. * from the right to a vector or matrix.
  128. *
  129. * On input:
  130. * \param essential the essential part of the vector \c v
  131. * \param tau the scaling factor of the Householder transformation
  132. * \param workspace a pointer to working space with at least
  133. * this->cols() * essential.size() entries
  134. *
  135. * \sa MatrixBase::makeHouseholder(), MatrixBase::makeHouseholderInPlace(),
  136. * MatrixBase::applyHouseholderOnTheLeft()
  137. */
  138. template<typename Derived>
  139. template<typename EssentialPart>
  140. void MatrixBase<Derived>::applyHouseholderOnTheRight(
  141. const EssentialPart& essential,
  142. const Scalar& tau,
  143. Scalar* workspace)
  144. {
  145. if(cols() == 1)
  146. {
  147. *this *= Scalar(1)-tau;
  148. }
  149. else if(tau!=Scalar(0))
  150. {
  151. Map<typename internal::plain_col_type<PlainObject>::type> tmp(workspace,rows());
  152. Block<Derived, Derived::RowsAtCompileTime, EssentialPart::SizeAtCompileTime> right(derived(), 0, 1, rows(), cols()-1);
  153. tmp.noalias() = right * essential.conjugate();
  154. tmp += this->col(0);
  155. this->col(0) -= tau * tmp;
  156. right.noalias() -= tau * tmp * essential.transpose();
  157. }
  158. }
  159. } // end namespace Eigen
  160. #endif // EIGEN_HOUSEHOLDER_H