| // This file is part of Eigen, a lightweight C++ template library |
| // for linear algebra. |
| // |
| // Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com> |
| // Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr> |
| // |
| // This Source Code Form is subject to the terms of the Mozilla |
| // Public License v. 2.0. If a copy of the MPL was not distributed |
| // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| |
| #ifndef EIGEN_HOUSEHOLDER_H |
| #define EIGEN_HOUSEHOLDER_H |
| |
| // IWYU pragma: private |
| #include "./InternalHeaderCheck.h" |
| |
| namespace Eigen { |
| |
| namespace internal { |
| template <int n> |
| struct decrement_size { |
| enum { ret = n == Dynamic ? n : n - 1 }; |
| }; |
| } // namespace internal |
| |
| /** Computes the elementary reflector H such that: |
| * \f$ H *this = [ beta 0 ... 0]^T \f$ |
| * where the transformation H is: |
| * \f$ H = I - tau v v^*\f$ |
| * and the vector v is: |
| * \f$ v^T = [1 essential^T] \f$ |
| * |
| * The essential part of the vector \c v is stored in *this. |
| * |
| * On output: |
| * \param tau the scaling factor of the Householder transformation |
| * \param beta the result of H * \c *this |
| * |
| * \sa MatrixBase::makeHouseholder(), MatrixBase::applyHouseholderOnTheLeft(), |
| * MatrixBase::applyHouseholderOnTheRight() |
| */ |
| template <typename Derived> |
| EIGEN_DEVICE_FUNC void MatrixBase<Derived>::makeHouseholderInPlace(Scalar& tau, RealScalar& beta) { |
| VectorBlock<Derived, internal::decrement_size<Base::SizeAtCompileTime>::ret> essentialPart(derived(), 1, size() - 1); |
| makeHouseholder(essentialPart, tau, beta); |
| } |
| |
| /** Computes the elementary reflector H such that: |
| * \f$ H *this = [ beta 0 ... 0]^T \f$ |
| * where the transformation H is: |
| * \f$ H = I - tau v v^*\f$ |
| * and the vector v is: |
| * \f$ v^T = [1 essential^T] \f$ |
| * |
| * On output: |
| * \param essential the essential part of the vector \c v |
| * \param tau the scaling factor of the Householder transformation |
| * \param beta the result of H * \c *this |
| * |
| * \sa MatrixBase::makeHouseholderInPlace(), MatrixBase::applyHouseholderOnTheLeft(), |
| * MatrixBase::applyHouseholderOnTheRight() |
| */ |
| template <typename Derived> |
| template <typename EssentialPart> |
| EIGEN_DEVICE_FUNC void MatrixBase<Derived>::makeHouseholder(EssentialPart& essential, Scalar& tau, |
| RealScalar& beta) const { |
| using numext::conj; |
| using numext::sqrt; |
| |
| EIGEN_STATIC_ASSERT_VECTOR_ONLY(EssentialPart) |
| VectorBlock<const Derived, EssentialPart::SizeAtCompileTime> tail(derived(), 1, size() - 1); |
| |
| RealScalar tailSqNorm = size() == 1 ? RealScalar(0) : tail.squaredNorm(); |
| Scalar c0 = coeff(0); |
| const RealScalar tol = (std::numeric_limits<RealScalar>::min)(); |
| |
| if (tailSqNorm <= tol && numext::abs2(numext::imag(c0)) <= tol) { |
| tau = RealScalar(0); |
| beta = numext::real(c0); |
| essential.setZero(); |
| } else { |
| beta = sqrt(numext::abs2(c0) + tailSqNorm); |
| if (numext::real(c0) >= RealScalar(0)) beta = -beta; |
| essential = tail / (c0 - beta); |
| tau = conj((beta - c0) / beta); |
| } |
| } |
| |
| /** Apply the elementary reflector H given by |
| * \f$ H = I - tau v v^*\f$ |
| * with |
| * \f$ v^T = [1 essential^T] \f$ |
| * from the left to a vector or matrix. |
| * |
| * On input: |
| * \param essential the essential part of the vector \c v |
| * \param tau the scaling factor of the Householder transformation |
| * \param workspace a pointer to working space with at least |
| * this->cols() entries |
| * |
| * \sa MatrixBase::makeHouseholder(), MatrixBase::makeHouseholderInPlace(), |
| * MatrixBase::applyHouseholderOnTheRight() |
| */ |
| template <typename Derived> |
| template <typename EssentialPart> |
| EIGEN_DEVICE_FUNC void MatrixBase<Derived>::applyHouseholderOnTheLeft(const EssentialPart& essential, const Scalar& tau, |
| Scalar* workspace) { |
| if (rows() == 1) { |
| *this *= Scalar(1) - tau; |
| } else if (!numext::is_exactly_zero(tau)) { |
| Map<typename internal::plain_row_type<PlainObject>::type> tmp(workspace, cols()); |
| Block<Derived, EssentialPart::SizeAtCompileTime, Derived::ColsAtCompileTime> bottom(derived(), 1, 0, rows() - 1, |
| cols()); |
| tmp.noalias() = essential.adjoint() * bottom; |
| tmp += this->row(0); |
| this->row(0) -= tau * tmp; |
| bottom.noalias() -= tau * essential * tmp; |
| } |
| } |
| |
| /** Apply the elementary reflector H given by |
| * \f$ H = I - tau v v^*\f$ |
| * with |
| * \f$ v^T = [1 essential^T] \f$ |
| * from the right to a vector or matrix. |
| * |
| * On input: |
| * \param essential the essential part of the vector \c v |
| * \param tau the scaling factor of the Householder transformation |
| * \param workspace a pointer to working space with at least |
| * this->rows() entries |
| * |
| * \sa MatrixBase::makeHouseholder(), MatrixBase::makeHouseholderInPlace(), |
| * MatrixBase::applyHouseholderOnTheLeft() |
| */ |
| template <typename Derived> |
| template <typename EssentialPart> |
| EIGEN_DEVICE_FUNC void MatrixBase<Derived>::applyHouseholderOnTheRight(const EssentialPart& essential, |
| const Scalar& tau, Scalar* workspace) { |
| if (cols() == 1) { |
| *this *= Scalar(1) - tau; |
| } else if (!numext::is_exactly_zero(tau)) { |
| Map<typename internal::plain_col_type<PlainObject>::type> tmp(workspace, rows()); |
| Block<Derived, Derived::RowsAtCompileTime, EssentialPart::SizeAtCompileTime> right(derived(), 0, 1, rows(), |
| cols() - 1); |
| tmp.noalias() = right * essential; |
| tmp += this->col(0); |
| this->col(0) -= tau * tmp; |
| right.noalias() -= tau * tmp * essential.adjoint(); |
| } |
| } |
| |
| } // end namespace Eigen |
| |
| #endif // EIGEN_HOUSEHOLDER_H |