/src/eigen/Eigen/src/SparseLU/SparseLU_panel_bmod.h
Line | Count | Source |
1 | | // This file is part of Eigen, a lightweight C++ template library |
2 | | // for linear algebra. |
3 | | // |
4 | | // Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr> |
5 | | // Copyright (C) 2012 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 | | // SPDX-License-Identifier: MPL-2.0 |
11 | | |
12 | | /* |
13 | | |
14 | | * NOTE: This file is the modified version of [s,d,c,z]panel_bmod.c file in SuperLU |
15 | | |
16 | | * -- SuperLU routine (version 3.0) -- |
17 | | * Univ. of California Berkeley, Xerox Palo Alto Research Center, |
18 | | * and Lawrence Berkeley National Lab. |
19 | | * October 15, 2003 |
20 | | * |
21 | | * Copyright (c) 1994 by Xerox Corporation. All rights reserved. |
22 | | * |
23 | | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY |
24 | | * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. |
25 | | * |
26 | | * Permission is hereby granted to use or copy this program for any |
27 | | * purpose, provided the above notices are retained on all copies. |
28 | | * Permission to modify the code and to distribute modified code is |
29 | | * granted, provided the above notices are retained, and a notice that |
30 | | * the code was modified is included with the above copyright notice. |
31 | | */ |
32 | | #ifndef SPARSELU_PANEL_BMOD_H |
33 | | #define SPARSELU_PANEL_BMOD_H |
34 | | |
35 | | // IWYU pragma: private |
36 | | #include "./InternalHeaderCheck.h" |
37 | | |
38 | | namespace Eigen { |
39 | | namespace internal { |
40 | | |
41 | | /** |
42 | | * \brief Performs numeric block updates (sup-panel) in topological order. |
43 | | * |
44 | | * Before entering this routine, the original nonzeros in the panel |
45 | | * were already copied into the spa[m,w] |
46 | | * |
47 | | * \param m number of rows in the matrix |
48 | | * \param w Panel size |
49 | | * \param jcol Starting column of the panel |
50 | | * \param nseg Number of segments in the U part |
51 | | * \param dense Store the full representation of the panel |
52 | | * \param tempv working array |
53 | | * \param segrep segment representative... first row in the segment |
54 | | * \param repfnz First nonzero rows |
55 | | * \param glu Global LU data. |
56 | | * |
57 | | * |
58 | | */ |
59 | | template <typename Scalar, typename StorageIndex> |
60 | | void SparseLUImpl<Scalar, StorageIndex>::panel_bmod(const Index m, const Index w, const Index jcol, const Index nseg, |
61 | | ScalarVector& dense, ScalarVector& tempv, IndexVector& segrep, |
62 | 4.05k | IndexVector& repfnz, GlobalLU_t& glu) { |
63 | 4.05k | Index ksub, jj, nextl_col; |
64 | 4.05k | Index fsupc, nsupc, nsupr, nrow; |
65 | 4.05k | Index krep, kfnz; |
66 | 4.05k | Index lptr; // points to the row subscripts of a supernode |
67 | 4.05k | Index luptr; // ... |
68 | 4.05k | Index segsize, no_zeros; |
69 | | // For each nonz supernode segment of U[*,j] in topological order |
70 | 4.05k | Index k = nseg - 1; |
71 | 4.05k | const Index PacketSize = internal::packet_traits<Scalar>::size; |
72 | | |
73 | 5.56k | for (ksub = 0; ksub < nseg; ksub++) { // For each updating supernode |
74 | | /* krep = representative of current k-th supernode |
75 | | * fsupc = first supernodal column |
76 | | * nsupc = number of columns in a supernode |
77 | | * nsupr = number of rows in a supernode |
78 | | */ |
79 | 1.51k | krep = segrep(k); |
80 | 1.51k | k--; |
81 | 1.51k | fsupc = glu.xsup(glu.supno(krep)); |
82 | 1.51k | nsupc = krep - fsupc + 1; |
83 | 1.51k | nsupr = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc); |
84 | 1.51k | nrow = nsupr - nsupc; |
85 | 1.51k | lptr = glu.xlsub(fsupc); |
86 | | |
87 | | // loop over the panel columns to detect the actual number of columns and rows |
88 | 1.51k | Index u_rows = 0; |
89 | 1.51k | Index u_cols = 0; |
90 | 12.4k | for (jj = jcol; jj < jcol + w; jj++) { |
91 | 10.9k | nextl_col = (jj - jcol) * m; |
92 | 10.9k | VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row |
93 | | |
94 | 10.9k | kfnz = repfnz_col(krep); |
95 | 10.9k | if (kfnz == emptyIdxLU) continue; // skip any zero segment |
96 | | |
97 | 5.72k | segsize = krep - kfnz + 1; |
98 | 5.72k | u_cols++; |
99 | 5.72k | u_rows = (std::max)(segsize, u_rows); |
100 | 5.72k | } |
101 | | |
102 | 1.51k | if (nsupc >= 2) { |
103 | 624 | Index ldu = internal::first_multiple<Index>(u_rows, PacketSize); |
104 | 624 | Map<ScalarMatrix, Aligned, OuterStride<> > U(tempv.data(), u_rows, u_cols, OuterStride<>(ldu)); |
105 | | |
106 | | // gather U |
107 | 624 | Index u_col = 0; |
108 | 5.26k | for (jj = jcol; jj < jcol + w; jj++) { |
109 | 4.64k | nextl_col = (jj - jcol) * m; |
110 | 4.64k | VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row |
111 | 4.64k | VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here |
112 | | |
113 | 4.64k | kfnz = repfnz_col(krep); |
114 | 4.64k | if (kfnz == emptyIdxLU) continue; // skip any zero segment |
115 | | |
116 | 2.69k | segsize = krep - kfnz + 1; |
117 | 2.69k | luptr = glu.xlusup(fsupc); |
118 | 2.69k | no_zeros = kfnz - fsupc; |
119 | | |
120 | 2.69k | Index isub = lptr + no_zeros; |
121 | 2.69k | Index off = u_rows - segsize; |
122 | 3.00k | for (Index i = 0; i < off; i++) U(i, u_col) = Scalar(0); |
123 | 7.69k | for (Index i = 0; i < segsize; i++) { |
124 | 5.00k | Index irow = glu.lsub(isub); |
125 | 5.00k | U(i + off, u_col) = dense_col(irow); |
126 | 5.00k | ++isub; |
127 | 5.00k | } |
128 | 2.69k | u_col++; |
129 | 2.69k | } |
130 | | // solve U = A^-1 U |
131 | 624 | luptr = glu.xlusup(fsupc); |
132 | 624 | Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc); |
133 | 624 | no_zeros = (krep - u_rows + 1) - fsupc; |
134 | 624 | luptr += lda * no_zeros + no_zeros; |
135 | 624 | MappedMatrixBlock A(glu.lusup.data() + luptr, u_rows, u_rows, OuterStride<>(lda)); |
136 | 624 | U = A.template triangularView<UnitLower>().solve(U); |
137 | | |
138 | | // update |
139 | 624 | luptr += u_rows; |
140 | 624 | MappedMatrixBlock B(glu.lusup.data() + luptr, nrow, u_rows, OuterStride<>(lda)); |
141 | 624 | eigen_assert(tempv.size() > w * ldu + nrow * w + 1); |
142 | | |
143 | 624 | Index ldl = internal::first_multiple<Index>(nrow, PacketSize); |
144 | 624 | Index offset = (PacketSize - internal::first_default_aligned(B.data(), PacketSize)) % PacketSize; |
145 | 624 | MappedMatrixBlock L(tempv.data() + w * ldu + offset, nrow, u_cols, OuterStride<>(ldl)); |
146 | | |
147 | 624 | L.noalias() = B * U; |
148 | | |
149 | | // scatter U and L |
150 | 624 | u_col = 0; |
151 | 5.26k | for (jj = jcol; jj < jcol + w; jj++) { |
152 | 4.64k | nextl_col = (jj - jcol) * m; |
153 | 4.64k | VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row |
154 | 4.64k | VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here |
155 | | |
156 | 4.64k | kfnz = repfnz_col(krep); |
157 | 4.64k | if (kfnz == emptyIdxLU) continue; // skip any zero segment |
158 | | |
159 | 2.69k | segsize = krep - kfnz + 1; |
160 | 2.69k | no_zeros = kfnz - fsupc; |
161 | 2.69k | Index isub = lptr + no_zeros; |
162 | | |
163 | 2.69k | Index off = u_rows - segsize; |
164 | 7.69k | for (Index i = 0; i < segsize; i++) { |
165 | 5.00k | Index irow = glu.lsub(isub++); |
166 | 5.00k | dense_col(irow) = U.coeff(i + off, u_col); |
167 | 5.00k | U.coeffRef(i + off, u_col) = Scalar(0); |
168 | 5.00k | } |
169 | | |
170 | | // Scatter l into SPA dense[] |
171 | 8.45k | for (Index i = 0; i < nrow; i++) { |
172 | 5.76k | Index irow = glu.lsub(isub++); |
173 | 5.76k | dense_col(irow) -= L.coeff(i, u_col); |
174 | 5.76k | L.coeffRef(i, u_col) = Scalar(0); |
175 | 5.76k | } |
176 | 2.69k | u_col++; |
177 | 2.69k | } |
178 | 624 | } else // level 2 only |
179 | 887 | { |
180 | | // Sequence through each column in the panel |
181 | 7.17k | for (jj = jcol; jj < jcol + w; jj++) { |
182 | 6.29k | nextl_col = (jj - jcol) * m; |
183 | 6.29k | VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row |
184 | 6.29k | VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here |
185 | | |
186 | 6.29k | kfnz = repfnz_col(krep); |
187 | 6.29k | if (kfnz == emptyIdxLU) continue; // skip any zero segment |
188 | | |
189 | 3.03k | segsize = krep - kfnz + 1; |
190 | 3.03k | luptr = glu.xlusup(fsupc); |
191 | | |
192 | 3.03k | Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc); // nsupr |
193 | | |
194 | | // Perform a triangular solve and block update, |
195 | | // then scatter the result of sup-col update to dense[] |
196 | 3.03k | no_zeros = kfnz - fsupc; |
197 | 3.03k | if (segsize == 1) |
198 | 3.03k | LU_kernel_bmod<1>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros); |
199 | 0 | else if (segsize == 2) |
200 | 0 | LU_kernel_bmod<2>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros); |
201 | 0 | else if (segsize == 3) |
202 | 0 | LU_kernel_bmod<3>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros); |
203 | 0 | else |
204 | 0 | LU_kernel_bmod<Dynamic>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, |
205 | 0 | no_zeros); |
206 | 3.03k | } // End for each column in the panel |
207 | 887 | } |
208 | | |
209 | 1.51k | } // End for each updating supernode |
210 | 4.05k | } // end panel bmod Eigen::internal::SparseLUImpl<float, int>::panel_bmod(long, long, long, long, Eigen::Matrix<float, -1, 1, 0, -1, 1>&, Eigen::Matrix<float, -1, 1, 0, -1, 1>&, Eigen::Matrix<int, -1, 1, 0, -1, 1>&, Eigen::Matrix<int, -1, 1, 0, -1, 1>&, Eigen::internal::LU_GlobalLU_t<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, 1, 0, -1, 1> >&) Line | Count | Source | 62 | 2.19k | IndexVector& repfnz, GlobalLU_t& glu) { | 63 | 2.19k | Index ksub, jj, nextl_col; | 64 | 2.19k | Index fsupc, nsupc, nsupr, nrow; | 65 | 2.19k | Index krep, kfnz; | 66 | 2.19k | Index lptr; // points to the row subscripts of a supernode | 67 | 2.19k | Index luptr; // ... | 68 | 2.19k | Index segsize, no_zeros; | 69 | | // For each nonz supernode segment of U[*,j] in topological order | 70 | 2.19k | Index k = nseg - 1; | 71 | 2.19k | const Index PacketSize = internal::packet_traits<Scalar>::size; | 72 | | | 73 | 2.98k | for (ksub = 0; ksub < nseg; ksub++) { // For each updating supernode | 74 | | /* krep = representative of current k-th supernode | 75 | | * fsupc = first supernodal column | 76 | | * nsupc = number of columns in a supernode | 77 | | * nsupr = number of rows in a supernode | 78 | | */ | 79 | 786 | krep = segrep(k); | 80 | 786 | k--; | 81 | 786 | fsupc = glu.xsup(glu.supno(krep)); | 82 | 786 | nsupc = krep - fsupc + 1; | 83 | 786 | nsupr = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc); | 84 | 786 | nrow = nsupr - nsupc; | 85 | 786 | lptr = glu.xlsub(fsupc); | 86 | | | 87 | | // loop over the panel columns to detect the actual number of columns and rows | 88 | 786 | Index u_rows = 0; | 89 | 786 | Index u_cols = 0; | 90 | 6.52k | for (jj = jcol; jj < jcol + w; jj++) { | 91 | 5.73k | nextl_col = (jj - jcol) * m; | 92 | 5.73k | VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row | 93 | | | 94 | 5.73k | kfnz = repfnz_col(krep); | 95 | 5.73k | if (kfnz == emptyIdxLU) continue; // skip any zero segment | 96 | | | 97 | 2.90k | segsize = krep - kfnz + 1; | 98 | 2.90k | u_cols++; | 99 | 2.90k | u_rows = (std::max)(segsize, u_rows); | 100 | 2.90k | } | 101 | | | 102 | 786 | if (nsupc >= 2) { | 103 | 313 | Index ldu = internal::first_multiple<Index>(u_rows, PacketSize); | 104 | 313 | Map<ScalarMatrix, Aligned, OuterStride<> > U(tempv.data(), u_rows, u_cols, OuterStride<>(ldu)); | 105 | | | 106 | | // gather U | 107 | 313 | Index u_col = 0; | 108 | 2.67k | for (jj = jcol; jj < jcol + w; jj++) { | 109 | 2.36k | nextl_col = (jj - jcol) * m; | 110 | 2.36k | VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row | 111 | 2.36k | VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here | 112 | | | 113 | 2.36k | kfnz = repfnz_col(krep); | 114 | 2.36k | if (kfnz == emptyIdxLU) continue; // skip any zero segment | 115 | | | 116 | 1.33k | segsize = krep - kfnz + 1; | 117 | 1.33k | luptr = glu.xlusup(fsupc); | 118 | 1.33k | no_zeros = kfnz - fsupc; | 119 | | | 120 | 1.33k | Index isub = lptr + no_zeros; | 121 | 1.33k | Index off = u_rows - segsize; | 122 | 1.49k | for (Index i = 0; i < off; i++) U(i, u_col) = Scalar(0); | 123 | 3.83k | for (Index i = 0; i < segsize; i++) { | 124 | 2.50k | Index irow = glu.lsub(isub); | 125 | 2.50k | U(i + off, u_col) = dense_col(irow); | 126 | 2.50k | ++isub; | 127 | 2.50k | } | 128 | 1.33k | u_col++; | 129 | 1.33k | } | 130 | | // solve U = A^-1 U | 131 | 313 | luptr = glu.xlusup(fsupc); | 132 | 313 | Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc); | 133 | 313 | no_zeros = (krep - u_rows + 1) - fsupc; | 134 | 313 | luptr += lda * no_zeros + no_zeros; | 135 | 313 | MappedMatrixBlock A(glu.lusup.data() + luptr, u_rows, u_rows, OuterStride<>(lda)); | 136 | 313 | U = A.template triangularView<UnitLower>().solve(U); | 137 | | | 138 | | // update | 139 | 313 | luptr += u_rows; | 140 | 313 | MappedMatrixBlock B(glu.lusup.data() + luptr, nrow, u_rows, OuterStride<>(lda)); | 141 | 313 | eigen_assert(tempv.size() > w * ldu + nrow * w + 1); | 142 | | | 143 | 313 | Index ldl = internal::first_multiple<Index>(nrow, PacketSize); | 144 | 313 | Index offset = (PacketSize - internal::first_default_aligned(B.data(), PacketSize)) % PacketSize; | 145 | 313 | MappedMatrixBlock L(tempv.data() + w * ldu + offset, nrow, u_cols, OuterStride<>(ldl)); | 146 | | | 147 | 313 | L.noalias() = B * U; | 148 | | | 149 | | // scatter U and L | 150 | 313 | u_col = 0; | 151 | 2.67k | for (jj = jcol; jj < jcol + w; jj++) { | 152 | 2.36k | nextl_col = (jj - jcol) * m; | 153 | 2.36k | VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row | 154 | 2.36k | VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here | 155 | | | 156 | 2.36k | kfnz = repfnz_col(krep); | 157 | 2.36k | if (kfnz == emptyIdxLU) continue; // skip any zero segment | 158 | | | 159 | 1.33k | segsize = krep - kfnz + 1; | 160 | 1.33k | no_zeros = kfnz - fsupc; | 161 | 1.33k | Index isub = lptr + no_zeros; | 162 | | | 163 | 1.33k | Index off = u_rows - segsize; | 164 | 3.83k | for (Index i = 0; i < segsize; i++) { | 165 | 2.50k | Index irow = glu.lsub(isub++); | 166 | 2.50k | dense_col(irow) = U.coeff(i + off, u_col); | 167 | 2.50k | U.coeffRef(i + off, u_col) = Scalar(0); | 168 | 2.50k | } | 169 | | | 170 | | // Scatter l into SPA dense[] | 171 | 4.34k | for (Index i = 0; i < nrow; i++) { | 172 | 3.01k | Index irow = glu.lsub(isub++); | 173 | 3.01k | dense_col(irow) -= L.coeff(i, u_col); | 174 | 3.01k | L.coeffRef(i, u_col) = Scalar(0); | 175 | 3.01k | } | 176 | 1.33k | u_col++; | 177 | 1.33k | } | 178 | 313 | } else // level 2 only | 179 | 473 | { | 180 | | // Sequence through each column in the panel | 181 | 3.84k | for (jj = jcol; jj < jcol + w; jj++) { | 182 | 3.37k | nextl_col = (jj - jcol) * m; | 183 | 3.37k | VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row | 184 | 3.37k | VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here | 185 | | | 186 | 3.37k | kfnz = repfnz_col(krep); | 187 | 3.37k | if (kfnz == emptyIdxLU) continue; // skip any zero segment | 188 | | | 189 | 1.57k | segsize = krep - kfnz + 1; | 190 | 1.57k | luptr = glu.xlusup(fsupc); | 191 | | | 192 | 1.57k | Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc); // nsupr | 193 | | | 194 | | // Perform a triangular solve and block update, | 195 | | // then scatter the result of sup-col update to dense[] | 196 | 1.57k | no_zeros = kfnz - fsupc; | 197 | 1.57k | if (segsize == 1) | 198 | 1.57k | LU_kernel_bmod<1>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros); | 199 | 0 | else if (segsize == 2) | 200 | 0 | LU_kernel_bmod<2>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros); | 201 | 0 | else if (segsize == 3) | 202 | 0 | LU_kernel_bmod<3>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros); | 203 | 0 | else | 204 | 0 | LU_kernel_bmod<Dynamic>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, | 205 | 0 | no_zeros); | 206 | 1.57k | } // End for each column in the panel | 207 | 473 | } | 208 | | | 209 | 786 | } // End for each updating supernode | 210 | 2.19k | } // end panel bmod |
Eigen::internal::SparseLUImpl<double, int>::panel_bmod(long, long, long, long, Eigen::Matrix<double, -1, 1, 0, -1, 1>&, Eigen::Matrix<double, -1, 1, 0, -1, 1>&, Eigen::Matrix<int, -1, 1, 0, -1, 1>&, Eigen::Matrix<int, -1, 1, 0, -1, 1>&, Eigen::internal::LU_GlobalLU_t<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >&) Line | Count | Source | 62 | 1.85k | IndexVector& repfnz, GlobalLU_t& glu) { | 63 | 1.85k | Index ksub, jj, nextl_col; | 64 | 1.85k | Index fsupc, nsupc, nsupr, nrow; | 65 | 1.85k | Index krep, kfnz; | 66 | 1.85k | Index lptr; // points to the row subscripts of a supernode | 67 | 1.85k | Index luptr; // ... | 68 | 1.85k | Index segsize, no_zeros; | 69 | | // For each nonz supernode segment of U[*,j] in topological order | 70 | 1.85k | Index k = nseg - 1; | 71 | 1.85k | const Index PacketSize = internal::packet_traits<Scalar>::size; | 72 | | | 73 | 2.58k | for (ksub = 0; ksub < nseg; ksub++) { // For each updating supernode | 74 | | /* krep = representative of current k-th supernode | 75 | | * fsupc = first supernodal column | 76 | | * nsupc = number of columns in a supernode | 77 | | * nsupr = number of rows in a supernode | 78 | | */ | 79 | 725 | krep = segrep(k); | 80 | 725 | k--; | 81 | 725 | fsupc = glu.xsup(glu.supno(krep)); | 82 | 725 | nsupc = krep - fsupc + 1; | 83 | 725 | nsupr = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc); | 84 | 725 | nrow = nsupr - nsupc; | 85 | 725 | lptr = glu.xlsub(fsupc); | 86 | | | 87 | | // loop over the panel columns to detect the actual number of columns and rows | 88 | 725 | Index u_rows = 0; | 89 | 725 | Index u_cols = 0; | 90 | 5.92k | for (jj = jcol; jj < jcol + w; jj++) { | 91 | 5.19k | nextl_col = (jj - jcol) * m; | 92 | 5.19k | VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row | 93 | | | 94 | 5.19k | kfnz = repfnz_col(krep); | 95 | 5.19k | if (kfnz == emptyIdxLU) continue; // skip any zero segment | 96 | | | 97 | 2.82k | segsize = krep - kfnz + 1; | 98 | 2.82k | u_cols++; | 99 | 2.82k | u_rows = (std::max)(segsize, u_rows); | 100 | 2.82k | } | 101 | | | 102 | 725 | if (nsupc >= 2) { | 103 | 311 | Index ldu = internal::first_multiple<Index>(u_rows, PacketSize); | 104 | 311 | Map<ScalarMatrix, Aligned, OuterStride<> > U(tempv.data(), u_rows, u_cols, OuterStride<>(ldu)); | 105 | | | 106 | | // gather U | 107 | 311 | Index u_col = 0; | 108 | 2.59k | for (jj = jcol; jj < jcol + w; jj++) { | 109 | 2.28k | nextl_col = (jj - jcol) * m; | 110 | 2.28k | VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row | 111 | 2.28k | VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here | 112 | | | 113 | 2.28k | kfnz = repfnz_col(krep); | 114 | 2.28k | if (kfnz == emptyIdxLU) continue; // skip any zero segment | 115 | | | 116 | 1.36k | segsize = krep - kfnz + 1; | 117 | 1.36k | luptr = glu.xlusup(fsupc); | 118 | 1.36k | no_zeros = kfnz - fsupc; | 119 | | | 120 | 1.36k | Index isub = lptr + no_zeros; | 121 | 1.36k | Index off = u_rows - segsize; | 122 | 1.51k | for (Index i = 0; i < off; i++) U(i, u_col) = Scalar(0); | 123 | 3.86k | for (Index i = 0; i < segsize; i++) { | 124 | 2.50k | Index irow = glu.lsub(isub); | 125 | 2.50k | U(i + off, u_col) = dense_col(irow); | 126 | 2.50k | ++isub; | 127 | 2.50k | } | 128 | 1.36k | u_col++; | 129 | 1.36k | } | 130 | | // solve U = A^-1 U | 131 | 311 | luptr = glu.xlusup(fsupc); | 132 | 311 | Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc); | 133 | 311 | no_zeros = (krep - u_rows + 1) - fsupc; | 134 | 311 | luptr += lda * no_zeros + no_zeros; | 135 | 311 | MappedMatrixBlock A(glu.lusup.data() + luptr, u_rows, u_rows, OuterStride<>(lda)); | 136 | 311 | U = A.template triangularView<UnitLower>().solve(U); | 137 | | | 138 | | // update | 139 | 311 | luptr += u_rows; | 140 | 311 | MappedMatrixBlock B(glu.lusup.data() + luptr, nrow, u_rows, OuterStride<>(lda)); | 141 | 311 | eigen_assert(tempv.size() > w * ldu + nrow * w + 1); | 142 | | | 143 | 311 | Index ldl = internal::first_multiple<Index>(nrow, PacketSize); | 144 | 311 | Index offset = (PacketSize - internal::first_default_aligned(B.data(), PacketSize)) % PacketSize; | 145 | 311 | MappedMatrixBlock L(tempv.data() + w * ldu + offset, nrow, u_cols, OuterStride<>(ldl)); | 146 | | | 147 | 311 | L.noalias() = B * U; | 148 | | | 149 | | // scatter U and L | 150 | 311 | u_col = 0; | 151 | 2.59k | for (jj = jcol; jj < jcol + w; jj++) { | 152 | 2.28k | nextl_col = (jj - jcol) * m; | 153 | 2.28k | VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row | 154 | 2.28k | VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here | 155 | | | 156 | 2.28k | kfnz = repfnz_col(krep); | 157 | 2.28k | if (kfnz == emptyIdxLU) continue; // skip any zero segment | 158 | | | 159 | 1.36k | segsize = krep - kfnz + 1; | 160 | 1.36k | no_zeros = kfnz - fsupc; | 161 | 1.36k | Index isub = lptr + no_zeros; | 162 | | | 163 | 1.36k | Index off = u_rows - segsize; | 164 | 3.86k | for (Index i = 0; i < segsize; i++) { | 165 | 2.50k | Index irow = glu.lsub(isub++); | 166 | 2.50k | dense_col(irow) = U.coeff(i + off, u_col); | 167 | 2.50k | U.coeffRef(i + off, u_col) = Scalar(0); | 168 | 2.50k | } | 169 | | | 170 | | // Scatter l into SPA dense[] | 171 | 4.11k | for (Index i = 0; i < nrow; i++) { | 172 | 2.74k | Index irow = glu.lsub(isub++); | 173 | 2.74k | dense_col(irow) -= L.coeff(i, u_col); | 174 | 2.74k | L.coeffRef(i, u_col) = Scalar(0); | 175 | 2.74k | } | 176 | 1.36k | u_col++; | 177 | 1.36k | } | 178 | 311 | } else // level 2 only | 179 | 414 | { | 180 | | // Sequence through each column in the panel | 181 | 3.33k | for (jj = jcol; jj < jcol + w; jj++) { | 182 | 2.91k | nextl_col = (jj - jcol) * m; | 183 | 2.91k | VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row | 184 | 2.91k | VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here | 185 | | | 186 | 2.91k | kfnz = repfnz_col(krep); | 187 | 2.91k | if (kfnz == emptyIdxLU) continue; // skip any zero segment | 188 | | | 189 | 1.46k | segsize = krep - kfnz + 1; | 190 | 1.46k | luptr = glu.xlusup(fsupc); | 191 | | | 192 | 1.46k | Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc); // nsupr | 193 | | | 194 | | // Perform a triangular solve and block update, | 195 | | // then scatter the result of sup-col update to dense[] | 196 | 1.46k | no_zeros = kfnz - fsupc; | 197 | 1.46k | if (segsize == 1) | 198 | 1.46k | LU_kernel_bmod<1>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros); | 199 | 0 | else if (segsize == 2) | 200 | 0 | LU_kernel_bmod<2>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros); | 201 | 0 | else if (segsize == 3) | 202 | 0 | LU_kernel_bmod<3>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros); | 203 | 0 | else | 204 | 0 | LU_kernel_bmod<Dynamic>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, | 205 | 0 | no_zeros); | 206 | 1.46k | } // End for each column in the panel | 207 | 414 | } | 208 | | | 209 | 725 | } // End for each updating supernode | 210 | 1.85k | } // end panel bmod |
|
211 | | |
212 | | } // end namespace internal |
213 | | |
214 | | } // end namespace Eigen |
215 | | |
216 | | #endif // SPARSELU_PANEL_BMOD_H |