Coverage Report

Created: 2026-10-05 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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