Eigen  5.0.1
 
Loading...
Searching...
No Matches
TriangularSolverVector.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
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// SPDX-License-Identifier: MPL-2.0
10
11#ifndef EIGEN_TRIANGULAR_SOLVER_VECTOR_H
12#define EIGEN_TRIANGULAR_SOLVER_VECTOR_H
13
14// IWYU pragma: private
15#include "../InternalHeaderCheck.h"
16
17namespace Eigen {
18
19namespace internal {
20
21template <typename LhsScalar, typename RhsScalar, typename Index, int Mode, bool Conjugate, int StorageOrder>
22struct triangular_solve_vector<LhsScalar, RhsScalar, Index, OnTheRight, Mode, Conjugate, StorageOrder> {
23 static void run(Index size, const LhsScalar* _lhs, Index lhsStride, RhsScalar* rhs) {
24 triangular_solve_vector<LhsScalar, RhsScalar, Index, OnTheLeft,
25 ((Mode & Upper) == Upper ? Lower : Upper) | (Mode & UnitDiag), Conjugate,
26 StorageOrder == RowMajor ? ColMajor : RowMajor>::run(size, _lhs, lhsStride, rhs);
27 }
28};
29
30// forward and backward substitution, row-major, rhs is a vector
31template <typename LhsScalar, typename RhsScalar, typename Index, int Mode, bool Conjugate>
32struct triangular_solve_vector<LhsScalar, RhsScalar, Index, OnTheLeft, Mode, Conjugate, RowMajor> {
33 enum { IsLower = ((Mode & Lower) == Lower) };
34 static void run(Index size, const LhsScalar* _lhs, Index lhsStride, RhsScalar* rhs) {
35 using LhsMap = Map<const Matrix<LhsScalar, Dynamic, Dynamic, RowMajor>, 0, OuterStride<> >;
36 const LhsMap lhs(_lhs, size, size, OuterStride<>(lhsStride));
37
38 using LhsMapper = const_blas_data_mapper<LhsScalar, Index, RowMajor>;
39 using RhsMapper = const_blas_data_mapper<RhsScalar, Index, ColMajor>;
40
41 std::conditional_t<Conjugate, const CwiseUnaryOp<typename internal::scalar_conjugate_op<LhsScalar>, LhsMap>,
42 const LhsMap&>
43 cjLhs(lhs);
44 static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
45 for (Index pi = IsLower ? 0 : size; IsLower ? pi < size : pi > 0; IsLower ? pi += PanelWidth : pi -= PanelWidth) {
46 Index actualPanelWidth = (std::min)(IsLower ? size - pi : pi, PanelWidth);
47
48 Index r = IsLower ? pi : size - pi; // remaining size
49 if (r > 0) {
50 // let's directly call the low level product function because:
51 // 1 - it is faster to compile
52 // 2 - it is slightly faster at runtime
53 Index startRow = IsLower ? pi : pi - actualPanelWidth;
54 Index startCol = IsLower ? 0 : pi;
55
56 general_matrix_vector_product<Index, LhsScalar, LhsMapper, RowMajor, Conjugate, RhsScalar, RhsMapper,
57 false>::run(actualPanelWidth, r,
58 LhsMapper(&lhs.coeffRef(startRow, startCol), lhsStride),
59 RhsMapper(rhs + startCol, 1), rhs + startRow, 1, RhsScalar(-1));
60 }
61
62 for (Index k = 0; k < actualPanelWidth; ++k) {
63 Index i = IsLower ? pi + k : pi - k - 1;
64 Index s = IsLower ? pi : i + 1;
65 if (k > 0)
66 rhs[i] -= (cjLhs.row(i).segment(s, k).transpose().cwiseProduct(
67 Map<const Matrix<RhsScalar, Dynamic, 1> >(rhs + s, k)))
68 .sum();
69
70 EIGEN_IF_CONSTEXPR (!(Mode & UnitDiag)) {
71 if (!is_identically_zero(rhs[i])) rhs[i] /= cjLhs(i, i);
72 }
73 }
74 }
75 }
76};
77
78// forward and backward substitution, column-major, rhs is a vector
79template <typename LhsScalar, typename RhsScalar, typename Index, int Mode, bool Conjugate>
80struct triangular_solve_vector<LhsScalar, RhsScalar, Index, OnTheLeft, Mode, Conjugate, ColMajor> {
81 enum { IsLower = ((Mode & Lower) == Lower) };
82 static void run(Index size, const LhsScalar* _lhs, Index lhsStride, RhsScalar* rhs) {
83 using LhsMap = Map<const Matrix<LhsScalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> >;
84 const LhsMap lhs(_lhs, size, size, OuterStride<>(lhsStride));
85 using LhsMapper = const_blas_data_mapper<LhsScalar, Index, ColMajor>;
86 using RhsMapper = const_blas_data_mapper<RhsScalar, Index, ColMajor>;
87 std::conditional_t<Conjugate, const CwiseUnaryOp<typename internal::scalar_conjugate_op<LhsScalar>, LhsMap>,
88 const LhsMap&>
89 cjLhs(lhs);
90 static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
91
92 for (Index pi = IsLower ? 0 : size; IsLower ? pi < size : pi > 0; IsLower ? pi += PanelWidth : pi -= PanelWidth) {
93 Index actualPanelWidth = (std::min)(IsLower ? size - pi : pi, PanelWidth);
94 Index startBlock = IsLower ? pi : pi - actualPanelWidth;
95 Index endBlock = IsLower ? pi + actualPanelWidth : 0;
96
97 for (Index k = 0; k < actualPanelWidth; ++k) {
98 Index i = IsLower ? pi + k : pi - k - 1;
99 if (!is_identically_zero(rhs[i])) {
100 EIGEN_IF_CONSTEXPR (!(Mode & UnitDiag)) rhs[i] /= cjLhs.coeff(i, i);
101
102 Index r = actualPanelWidth - k - 1; // remaining size
103 Index s = IsLower ? i + 1 : i - r;
104 if (r > 0) Map<Matrix<RhsScalar, Dynamic, 1> >(rhs + s, r) -= rhs[i] * cjLhs.col(i).segment(s, r);
105 }
106 }
107 Index r = IsLower ? size - endBlock : startBlock; // remaining size
108 if (r > 0) {
109 // let's directly call the low level product function because:
110 // 1 - it is faster to compile
111 // 2 - it is slightly faster at runtime
112 general_matrix_vector_product<Index, LhsScalar, LhsMapper, ColMajor, Conjugate, RhsScalar, RhsMapper,
113 false>::run(r, actualPanelWidth,
114 LhsMapper(&lhs.coeffRef(endBlock, startBlock), lhsStride),
115 RhsMapper(rhs + startBlock, 1), rhs + endBlock, 1, RhsScalar(-1));
116 }
117 }
118 }
119};
120
121} // end namespace internal
122
123} // end namespace Eigen
124
125#endif // EIGEN_TRIANGULAR_SOLVER_VECTOR_H
@ UnitDiag
Definition Constants.h:216
@ Lower
Definition Constants.h:212
@ Upper
Definition Constants.h:214
@ ColMajor
Definition Constants.h:319
@ RowMajor
Definition Constants.h:321
@ OnTheLeft
Definition Constants.h:332
@ OnTheRight
Definition Constants.h:334