11#ifndef EIGEN_TRIANGULARINPLACE_H
12#define EIGEN_TRIANGULARINPLACE_H
15#include "./InternalHeaderCheck.h"
34constexpr Index kTriangularInverseMinBlocked = 64;
35constexpr Index kTriangularInverseMinBlockSize = 24;
36constexpr Index kAdjointSquareMinBlocked = 128;
37constexpr Index kAdjointSquareMinBlockSize = 48;
39EIGEN_DEVICE_FUNC
inline Index triangular_in_place_block_size(Index size, Index min_block_size) {
40 const Index block_size = ((size / 8) / 8) * 8;
41 return numext::mini(numext::maxi(block_size, min_block_size), Index(128));
44template <
typename MatrixType>
45struct triangular_in_place_workspace {
46 using type = Matrix<
typename MatrixType::Scalar, Dynamic, Dynamic,
54template <
unsigned int Mode,
typename MatrixType,
typename VectorType>
55EIGEN_DEVICE_FUNC
void triangular_inverse_unblocked(MatrixType& mat, VectorType& tmp) {
56 using Scalar =
typename MatrixType::Scalar;
57 constexpr bool kUnitDiag = (Mode &
UnitDiag) != 0;
58 const Index n = mat.rows();
59 eigen_internal_assert(n < 2 || tmp.size() >= n - 1);
60 for (Index j = n - 1; j >= 0; --j) {
61 Scalar xj = Scalar(1);
62 EIGEN_IF_CONSTEXPR (!kUnitDiag) {
63 xj = Scalar(1) / mat.coeff(j, j);
64 mat.coeffRef(j, j) = xj;
66 const Index rs = n - j - 1;
67 if (rs == 0)
continue;
68 tmp.head(rs).noalias() = mat.block(j + 1, j + 1, rs, rs).template triangularView<Mode>() * mat.col(j).tail(rs);
69 mat.col(j).tail(rs) = -xj * tmp.head(rs);
77template <
unsigned int Mode,
typename MatrixType>
78EIGEN_DEVICE_FUNC
void triangular_inverse_lower(MatrixType& mat) {
79 eigen_assert(mat.rows() == mat.cols());
80 const Index n = mat.rows();
81 if (n < kTriangularInverseMinBlocked) {
82 using Scalar =
typename MatrixType::Scalar;
83 ei_declare_aligned_stack_constructed_variable(Scalar, tmp_data, numext::maxi(n, Index(1)), 0);
84 Map<Matrix<Scalar, Dynamic, 1> > tmp(tmp_data, n);
85 triangular_inverse_unblocked<Mode>(mat, tmp);
88 const Index block_size = triangular_in_place_block_size(n, kTriangularInverseMinBlockSize);
91 typename triangular_in_place_workspace<MatrixType>::type work(block_size, block_size);
92 for (Index k = ((n - 1) / block_size) * block_size; k >= 0; k -= block_size) {
93 const Index bs = numext::mini(block_size, n - k);
94 const Index rs = n - k - bs;
95 Block<MatrixType, Dynamic, Dynamic> L11(mat, k, k, bs, bs);
97 Block<MatrixType, Dynamic, Dynamic> L21(mat, k + bs, k, rs, bs);
98 Block<MatrixType, Dynamic, Dynamic> X22(mat, k + bs, k + bs, rs, rs);
101 for (Index r_end = rs; r_end > 0; r_end -= block_size) {
102 const Index r = numext::maxi(Index(0), r_end - block_size);
103 const Index h = r_end - r;
104 work.topLeftCorner(h, bs) = L21.middleRows(r, h);
105 L21.middleRows(r, h).noalias() =
106 X22.block(r, r, h, h).template triangularView<Mode>() * work.topLeftCorner(h, bs);
107 if (r > 0) L21.middleRows(r, h).noalias() += X22.block(r, 0, h, r) * L21.topRows(r);
109 L11.template triangularView<Mode>().template solveInPlace<OnTheRight>(L21);
112 auto tmp = work.col(0);
113 triangular_inverse_unblocked<Mode>(L11, tmp);
117template <
unsigned int Mode,
bool IsLower = (
int(Mode) &
int(Lower)) != 0>
118struct triangular_inverse_selector {
119 template <
typename MatrixType>
120 EIGEN_DEVICE_FUNC
static void run(MatrixType& mat) {
121 triangular_inverse_lower<Mode>(mat);
125template <
unsigned int Mode>
126struct triangular_inverse_selector<Mode, false> {
127 template <
typename MatrixType>
128 EIGEN_DEVICE_FUNC
static void run(MatrixType& mat) {
129 Transpose<MatrixType> matt(mat);
130 triangular_inverse_lower<(int(Mode) & int(UnitDiag)) | int(Lower)>(matt);
136template <
typename MatrixType>
137void triangular_adjoint_square_unblocked(MatrixType& mat) {
138 using Scalar =
typename MatrixType::Scalar;
139 const Index n = mat.rows();
140 for (Index i = 0; i < n; ++i) {
141 const Scalar lii = mat.coeff(i, i);
142 const Index rs = n - i - 1;
143 mat.coeffRef(i, i) = Scalar(mat.col(i).tail(n - i).squaredNorm());
145 mat.row(i).head(i) *= numext::conj(lii);
146 if (rs > 0) mat.row(i).head(i).noalias() += mat.col(i).tail(rs).adjoint() * mat.bottomLeftCorner(rs, i);
153template <
typename MatrixType>
154void triangular_adjoint_square_lower(MatrixType& mat) {
155 eigen_assert(mat.rows() == mat.cols());
156 const Index n = mat.rows();
157 if (n < kAdjointSquareMinBlocked) {
158 triangular_adjoint_square_unblocked(mat);
161 const Index block_size = triangular_in_place_block_size(n, kAdjointSquareMinBlockSize);
162 typename triangular_in_place_workspace<MatrixType>::type work(block_size, block_size);
163 for (Index k = 0; k < n; k += block_size) {
164 const Index bs = numext::mini(block_size, n - k);
165 const Index rs = n - k - bs;
166 Block<MatrixType, Dynamic, Dynamic> L11(mat, k, k, bs, bs);
170 Block<MatrixType, Dynamic, Dynamic> B(mat, k, 0, bs, k);
171 for (Index c = 0; c < k; c += block_size) {
172 const Index w = numext::mini(block_size, k - c);
173 work.topLeftCorner(bs, w) = B.middleCols(c, w);
174 B.middleCols(c, w).noalias() = L11.adjoint().template triangularView<Upper>() * work.topLeftCorner(bs, w);
176 if (rs > 0) B.noalias() += mat.block(k + bs, k, rs, bs).adjoint() * mat.block(k + bs, 0, rs, k);
178 triangular_adjoint_square_unblocked(L11);
180 L11.template selfadjointView<Lower>().rankUpdate(mat.block(k + bs, k, rs, bs).adjoint());
182 EIGEN_IF_CONSTEXPR (NumTraits<typename MatrixType::Scalar>::IsComplex) {
183 L11.diagonal() = L11.diagonal().real().template cast<typename MatrixType::Scalar>();
189template <
int UpLo,
bool IsLower = (
int(UpLo) &
int(Lower)) != 0>
190struct triangular_adjoint_square_selector {
191 template <
typename MatrixType>
192 static void run(MatrixType& mat) {
193 triangular_adjoint_square_lower(mat);
198struct triangular_adjoint_square_selector<UpLo, false> {
199 template <
typename MatrixType>
200 static void run(MatrixType& mat) {
201 Transpose<MatrixType> matt(mat);
202 triangular_adjoint_square_lower(matt);
209template <
int UpLo,
typename MatrixType>
210void triangular_adjoint_square_in_place(MatrixType& mat) {
211 triangular_adjoint_square_selector<UpLo>::run(mat);
216#ifndef EIGEN_PARSED_BY_DOXYGEN
217template <
typename MatrixType,
unsigned int Mode>
218EIGEN_DEVICE_FUNC
void TriangularViewImpl<MatrixType, Mode, Dense>::inverseInPlace() {
219 EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
220 EIGEN_STATIC_ASSERT((
int(Mode) &
int(
Upper |
Lower)) != 0 && (
int(Mode) &
int(
ZeroDiag)) == 0, PROGRAMMING_ERROR)
221 eigen_assert(derived().rows() == derived().cols());
222 internal::triangular_inverse_selector<Mode>::run(derived().nestedExpression());
@ UnitDiag
Definition Constants.h:216
@ ZeroDiag
Definition Constants.h:218
@ Lower
Definition Constants.h:212
@ Upper
Definition Constants.h:214
@ ColMajor
Definition Constants.h:319
@ RowMajor
Definition Constants.h:321
constexpr unsigned int RowMajorBit
Definition Constants.h:71