12#ifndef EIGEN_HOUSEHOLDER_H
13#define EIGEN_HOUSEHOLDER_H
16#include "./InternalHeaderCheck.h"
22struct decrement_size : std::integral_constant<int, N - 1> {};
24struct decrement_size<0> : std::integral_constant<int, 0> {};
26struct decrement_size<Dynamic> : std::integral_constant<int, Dynamic> {};
28template <
typename RealScalar>
29struct householder_norm_accumulator : stable_norm_accumulator<RealScalar> {};
32struct householder_norm_accumulator<float> {
38template <typename Scalar, typename Accumulator, bool IsComplex = NumTraits<Scalar>::IsComplex>
39struct householder_rescale;
41template <
typename Scalar,
typename Accumulator>
42struct householder_rescale<Scalar, Accumulator, false> {
43 EIGEN_DEVICE_FUNC
static Scalar run(
const Scalar& value,
const Accumulator& scale) {
44 return Scalar(Accumulator(value) / scale);
48 EIGEN_DEVICE_FUNC
static Scalar zero_tail_tau(
const Accumulator& scaledReal,
const Accumulator&,
49 const Scalar& scaledBeta) {
50 return Scalar(1) - Scalar(scaledReal) / scaledBeta;
53 template <
typename EssentialPart,
typename TailView>
54 EIGEN_DEVICE_FUNC
static void run(EssentialPart& essential,
const TailView& tail,
const Accumulator& scale,
55 const Scalar& denominator) {
56 essential = ((tail.template cast<Accumulator>().array() / scale) / Accumulator(denominator))
58 .template cast<Scalar>();
62template <
typename Scalar,
typename Accumulator>
63struct householder_rescale<Scalar, Accumulator, true> {
64 using RealScalar =
typename NumTraits<Scalar>::Real;
66 EIGEN_DEVICE_FUNC
static Scalar run(
const Scalar& value,
const Accumulator& scale) {
67 return Scalar(RealScalar(Accumulator(numext::real(value)) / scale),
68 RealScalar(Accumulator(numext::imag(value)) / scale));
71 EIGEN_DEVICE_FUNC
static Scalar zero_tail_tau(
const Accumulator& scaledReal,
const Accumulator& scaledImag,
72 const RealScalar& scaledBeta) {
73 return Scalar(RealScalar(1) - RealScalar(scaledReal) / scaledBeta, RealScalar(scaledImag) / scaledBeta);
76 template <
typename EssentialPart,
typename TailView>
77 EIGEN_DEVICE_FUNC
static void run(EssentialPart& essential,
const TailView& tail,
const Accumulator& scale,
78 const Scalar& denominator) {
79 run(essential, tail, scale, denominator, complex_array_access<Scalar>());
83 template <
typename EssentialPart,
typename TailView>
84 EIGEN_DEVICE_FUNC
static void run(EssentialPart& essential,
const TailView& tail,
const Accumulator& scale,
85 const Scalar& denominator, std::true_type) {
86 essential.realView().array() =
87 (tail.realView().array().
template cast<Accumulator>() / scale).template cast<RealScalar>();
88 essential.array() /= denominator;
91 template <
typename EssentialPart,
typename TailView>
92 EIGEN_DEVICE_FUNC
static void run(EssentialPart& essential,
const TailView& tail,
const Accumulator& scale,
93 const Scalar& denominator, std::false_type) {
94 for (Index i = 0; i < tail.size(); ++i) essential.coeffRef(i) = run(tail.coeff(i), scale) / denominator;
115template <
typename Derived>
137template <
typename Derived>
138template <
typename EssentialPart>
140 RealScalar& beta)
const {
143 EIGEN_STATIC_ASSERT_VECTOR_ONLY(EssentialPart)
146 const RealScalar tailSqNorm = size() == 1 ? RealScalar(0) :
tail.unwind().squaredNorm();
148 const RealScalar tol = (std::numeric_limits<RealScalar>::min)();
149 RealScalar unscaledNormThreshold = tol;
152 bool unscaledSqNormOverflows =
false;
153 EIGEN_IF_CONSTEXPR (!NumTraits<RealScalar>::IsInteger) {
154 const RealScalar precision = RealScalar(NumTraits<RealScalar>::epsilon());
159 const RealScalar componentCount = RealScalar(size() - 1) * RealScalar(NumTraits<Scalar>::IsComplex ? 2 : 1);
160 unscaledNormThreshold = (tol / precision) * componentCount;
167 const RealScalar sqNormBound = NumTraits<RealScalar>::highest() / RealScalar(2);
168 const RealScalar componentBound = numext::sqrt<RealScalar>(sqNormBound / RealScalar(2));
169 const RealScalar c0Max = numext::maxi(numext::abs(numext::real(c0)), numext::abs(numext::imag(c0)));
170 unscaledSqNormOverflows = !(c0Max <= componentBound) || !(tailSqNorm <= sqNormBound);
175 if ((tailSqNorm <= unscaledNormThreshold || unscaledSqNormOverflows) && !(numext::isnan)(c0)) {
176 using Accumulator =
typename internal::householder_norm_accumulator<RealScalar>::type;
177 const auto tailView =
tail.unwind();
178 const auto tailComponents = tailView.realView();
180 const Accumulator tailMax =
181 tailView.size() == 0 ? Accumulator(0) : Accumulator(tailComponents.cwiseAbs().maxCoeff());
182 if (numext::is_exactly_zero(tailMax) && numext::is_exactly_zero(numext::imag(c0))) {
184 beta = numext::real(c0);
188 const Accumulator c0RealAbs = numext::abs(Accumulator(numext::real(c0)));
189 const Accumulator c0ImagAbs = numext::abs(Accumulator(numext::imag(c0)));
190 const Accumulator c0Max = numext::maxi(c0RealAbs, c0ImagAbs);
191 const Accumulator scale = numext::maxi(c0Max, tailMax);
192 const RealScalar realScale = RealScalar(scale);
194 if (scale < Accumulator(tol) && numext::is_exactly_zero(realScale + realScale)) {
196 beta = numext::real(c0);
200 if (numext::is_exactly_zero(tailMax)) {
201 const Accumulator scaledReal = Accumulator(numext::real(c0)) / scale;
202 const Accumulator scaledImag = Accumulator(numext::imag(c0)) / scale;
203 RealScalar scaledBeta = RealScalar(numext::hypot(scaledReal, scaledImag));
204 if (numext::real(c0) >= RealScalar(0)) scaledBeta = -scaledBeta;
205 beta = RealScalar(scale * Accumulator(scaledBeta));
207 tau = internal::householder_rescale<Scalar, Accumulator>::zero_tail_tau(scaledReal, scaledImag, scaledBeta);
211 Accumulator scaledTailSqNorm;
212 EIGEN_IF_CONSTEXPR (std::is_same<RealScalar, float>::value) {
214 scaledTailSqNorm = tailComponents.template
cast<Accumulator>().squaredNorm() / (scale * scale);
216 scaledTailSqNorm = (tailComponents.template
cast<Accumulator>().array() / scale).matrix().squaredNorm();
218 if (numext::is_exactly_zero(RealScalar(tailMax / scale)) && numext::is_exactly_zero(numext::imag(c0))) {
220 beta = numext::real(c0);
224 const Scalar scaledC0 = internal::householder_rescale<Scalar, Accumulator>::run(c0, scale);
225 RealScalar scaledBeta =
226 RealScalar(numext::hypot(Accumulator(numext::abs(scaledC0)), numext::sqrt(scaledTailSqNorm)));
227 if (numext::real(c0) >= RealScalar(0)) scaledBeta = -scaledBeta;
228 beta = RealScalar(scale * Accumulator(scaledBeta));
229 internal::householder_rescale<Scalar, Accumulator>::run(essential, tailView, scale, scaledC0 - scaledBeta);
230 tau = conj(
Scalar(RealScalar(1)) - scaledC0 / scaledBeta);
233 beta = numext::sqrt<RealScalar>(numext::abs2(c0) + tailSqNorm);
234 if (numext::real(c0) >= RealScalar(0)) beta = -beta;
235 essential =
tail.unwind() / (c0 - beta);
236 tau = conj((beta - c0) / beta);
241template <
typename Derived,
typename EssentialPart,
242 bool Fused = !Derived::IsRowMajor && EssentialPart::ColsAtCompileTime == 1 &&
243 (EssentialPart::RowsAtCompileTime == 1 || EssentialPart::RowsAtCompileTime == 2)>
244struct householder_apply_left_impl {
245 using Scalar =
typename Derived::Scalar;
246 static EIGEN_DEVICE_FUNC
void run(
MatrixBase<Derived>& mat,
const EssentialPart& essential,
const Scalar& tau,
250 mat.rows() - 1, mat.cols());
251 tmp.noalias() = essential.adjoint() * bottom.unwind();
252 tmp = tau * (tmp + mat.
row(0));
254 bottom.unwind().noalias() -= essential * tmp;
260template <
typename Derived,
typename EssentialPart>
261struct householder_apply_left_impl<Derived, EssentialPart, true> {
262 using Scalar =
typename Derived::Scalar;
263 static EIGEN_DEVICE_FUNC
void run(MatrixBase<Derived>& mat,
const EssentialPart& essential,
const Scalar& tau,
266 const Matrix<Scalar, EssentialPart::RowsAtCompileTime, 1> v = essential;
267 const Scalar tauValue = tau;
268 Block<Derived, EssentialPart::RowsAtCompileTime, Derived::ColsAtCompileTime> bottom(mat.derived(), 1, 0,
269 mat.rows() - 1, mat.cols());
270 for (Index j = 0; j < mat.cols(); ++j) {
271 const Scalar tmp = tauValue * (v.dot(bottom.col(j)) + mat.coeff(0, j));
272 mat.coeffRef(0, j) -= tmp;
273 bottom.col(j) -= v * tmp;
278template <
typename Derived,
typename EssentialPart,
279 bool Fused = !Derived::IsRowMajor && bool(traits<Derived>::Flags &
DirectAccessBit) &&
280 inner_stride_at_compile_time<Derived>::value == 1 &&
281 packet_traits<typename Derived::Scalar>::Vectorizable && EssentialPart::ColsAtCompileTime == 1 &&
282 (EssentialPart::RowsAtCompileTime == 1 || EssentialPart::RowsAtCompileTime == 2)>
283struct householder_apply_right_impl {
284 using Scalar =
typename Derived::Scalar;
285 static EIGEN_DEVICE_FUNC
void run(MatrixBase<Derived>& mat,
const EssentialPart& essential,
const Scalar& tau,
287 Map<typename plain_col_type<typename Derived::PlainObject>::type> tmp(workspace, mat.rows());
288 Block<Derived, Derived::RowsAtCompileTime, EssentialPart::SizeAtCompileTime> right(mat.derived(), 0, 1, mat.rows(),
290 tmp.noalias() = right.unwind() * essential;
292 tmp = (tmp + mat.col(0)) * tau;
293 mat.col(0) = mat.col(0) - tmp;
294 right.unwind().noalias() -= tmp * essential.adjoint();
300template <
typename Derived,
typename EssentialPart>
301struct householder_apply_right_impl<Derived, EssentialPart, true> {
302 using Scalar =
typename Derived::Scalar;
303 using Packet =
typename packet_traits<Scalar>::type;
304 static constexpr int K = EssentialPart::RowsAtCompileTime;
306 static EIGEN_DEVICE_FUNC
void run(MatrixBase<Derived>& mat,
const EssentialPart& essential,
const Scalar& tau,
308 constexpr Index PacketSize = unpacket_traits<Packet>::size;
309 eigen_assert(mat.cols() == K + 1);
312 for (
int j = 0; j < K; ++j) {
313 v[j] = essential.coeff(j);
314 vc[j] = numext::conj(v[j]);
316 const Scalar tauValue = tau;
317 const Index rows = mat.rows();
319 for (
int j = 0; j <= K; ++j) col[j] = &mat.derived().coeffRef(0, j);
321 const Packet ptau = pset1<Packet>(tauValue);
322 Packet pv[K], pvc[K];
323 for (
int j = 0; j < K; ++j) {
324 pv[j] = pset1<Packet>(v[j]);
325 pvc[j] = pset1<Packet>(vc[j]);
327 const Index vectorEnd = numext::round_down(rows, PacketSize);
328 for (Index i = 0; i < vectorEnd; i += PacketSize) {
330 for (
int j = 0; j <= K; ++j) x[j] = ploadu<Packet>(col[j] + i);
332 for (
int j = 0; j < K; ++j) t = pmadd(x[j + 1], pv[j], t);
334 pstoreu(col[0] + i, psub(x[0], t));
335 for (
int j = 0; j < K; ++j) pstoreu(col[j + 1] + i, pnmadd(t, pvc[j], x[j + 1]));
337 for (Index i = vectorEnd; i < rows; ++i) {
338 Scalar t = col[0][i];
339 for (
int j = 0; j < K; ++j) t += col[j + 1][i] * v[j];
342 for (
int j = 0; j < K; ++j) col[j + 1][i] -= t * vc[j];
364template <
typename Derived>
365template <
typename EssentialPart>
370 *
this = (
Scalar(1) - tau) * *
this;
371 }
else if (!numext::is_exactly_zero(tau)) {
372 internal::householder_apply_left_impl<Derived, EssentialPart>::run(*
this, essential, tau, workspace);
391template <
typename Derived>
392template <
typename EssentialPart>
397 }
else if (!numext::is_exactly_zero(tau)) {
398 internal::householder_apply_right_impl<Derived, EssentialPart>::run(*
this, essential, tau, workspace);
Expression of a fixed-size or dynamic-size block.
Definition Block.h:111
constexpr FixedSegmentReturnType<... >::Type tail(NType n)
Definition DenseBase.h:1221
constexpr RowXpr row(Index i)
Definition DenseBase.h:1094
typename internal::traits< Derived >::Scalar Scalar
Definition DenseBase.h:63
constexpr CastXpr< NewType >::Type cast() const
Definition DenseBase.h:66
A matrix or vector expression mapping an existing array of data.
Definition Map.h:97
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
void makeHouseholder(EssentialPart &essential, Scalar &tau, RealScalar &beta) const
Definition Householder.h:139
void applyHouseholderOnTheLeft(const EssentialPart &essential, const Scalar &tau, Scalar *workspace)
Definition Householder.h:366
void applyHouseholderOnTheRight(const EssentialPart &essential, const Scalar &tau, Scalar *workspace)
Definition Householder.h:393
void makeHouseholderInPlace(Scalar &tau, RealScalar &beta)
Definition Householder.h:116
Expression of a fixed-size or dynamic-size sub-vector.
Definition VectorBlock.h:59
constexpr unsigned int DirectAccessBit
Definition Constants.h:160