Eigen  3.4.90 (git rev 5a9f66fb35d03a4da9ef8976e67a61b30aa16dcf)
 
Loading...
Searching...
No Matches
SparseLU_panel_dfs.h
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 <[email protected]>
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
10/*
11
12 * NOTE: This file is the modified version of [s,d,c,z]panel_dfs.c file in SuperLU
13
14 * -- SuperLU routine (version 2.0) --
15 * Univ. of California Berkeley, Xerox Palo Alto Research Center,
16 * and Lawrence Berkeley National Lab.
17 * November 15, 1997
18 *
19 * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
20 *
21 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
22 * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
23 *
24 * Permission is hereby granted to use or copy this program for any
25 * purpose, provided the above notices are retained on all copies.
26 * Permission to modify the code and to distribute modified code is
27 * granted, provided the above notices are retained, and a notice that
28 * the code was modified is included with the above copyright notice.
29 */
30#ifndef SPARSELU_PANEL_DFS_H
31#define SPARSELU_PANEL_DFS_H
32
33// IWYU pragma: private
34#include "./InternalHeaderCheck.h"
35
36namespace Eigen {
37
38namespace internal {
39
40template <typename IndexVector>
41struct panel_dfs_traits {
42 typedef typename IndexVector::Scalar StorageIndex;
43 panel_dfs_traits(Index jcol, StorageIndex* marker) : m_jcol(jcol), m_marker(marker) {}
44 bool update_segrep(Index krep, StorageIndex jj) {
45 if (m_marker[krep] < m_jcol) {
46 m_marker[krep] = jj;
47 return true;
48 }
49 return false;
50 }
51 void mem_expand(IndexVector& /*glu.lsub*/, Index /*nextl*/, Index /*chmark*/) {}
52 enum { ExpandMem = false };
53 Index m_jcol;
54 StorageIndex* m_marker;
55};
56
57template <typename Scalar, typename StorageIndex>
58template <typename Traits>
59void SparseLUImpl<Scalar, StorageIndex>::dfs_kernel(const StorageIndex jj, IndexVector& perm_r, Index& nseg,
60 IndexVector& panel_lsub, IndexVector& segrep,
61 Ref<IndexVector> repfnz_col, IndexVector& xprune,
62 Ref<IndexVector> marker, IndexVector& parent, IndexVector& xplore,
63 GlobalLU_t& glu, Index& nextl_col, Index krow, Traits& traits) {
64 StorageIndex kmark = marker(krow);
65
66 // For each unmarked krow of jj
67 marker(krow) = jj;
68 StorageIndex kperm = perm_r(krow);
69 if (kperm == emptyIdxLU) {
70 // krow is in L : place it in structure of L(*, jj)
71 panel_lsub(nextl_col++) = StorageIndex(krow); // krow is indexed into A
72
73 traits.mem_expand(panel_lsub, nextl_col, kmark);
74 } else {
75 // krow is in U : if its supernode-representative krep
76 // has been explored, update repfnz(*)
77 // krep = supernode representative of the current row
78 StorageIndex krep = glu.xsup(glu.supno(kperm) + 1) - 1;
79 // First nonzero element in the current column:
80 StorageIndex myfnz = repfnz_col(krep);
81
82 if (myfnz != emptyIdxLU) {
83 // Representative visited before
84 if (myfnz > kperm) repfnz_col(krep) = kperm;
85
86 } else {
87 // Otherwise, perform dfs starting at krep
88 StorageIndex oldrep = emptyIdxLU;
89 parent(krep) = oldrep;
90 repfnz_col(krep) = kperm;
91 StorageIndex xdfs = glu.xlsub(krep);
92 Index maxdfs = xprune(krep);
93
94 StorageIndex kpar;
95 do {
96 // For each unmarked kchild of krep
97 while (xdfs < maxdfs) {
98 StorageIndex kchild = glu.lsub(xdfs);
99 xdfs++;
100 StorageIndex chmark = marker(kchild);
101
102 if (chmark != jj) {
103 marker(kchild) = jj;
104 StorageIndex chperm = perm_r(kchild);
105
106 if (chperm == emptyIdxLU) {
107 // case kchild is in L: place it in L(*, j)
108 panel_lsub(nextl_col++) = kchild;
109 traits.mem_expand(panel_lsub, nextl_col, chmark);
110 } else {
111 // case kchild is in U :
112 // chrep = its supernode-rep. If its rep has been explored,
113 // update its repfnz(*)
114 StorageIndex chrep = glu.xsup(glu.supno(chperm) + 1) - 1;
115 myfnz = repfnz_col(chrep);
116
117 if (myfnz != emptyIdxLU) { // Visited before
118 if (myfnz > chperm) repfnz_col(chrep) = chperm;
119 } else { // Cont. dfs at snode-rep of kchild
120 xplore(krep) = xdfs;
121 oldrep = krep;
122 krep = chrep; // Go deeper down G(L)
123 parent(krep) = oldrep;
124 repfnz_col(krep) = chperm;
125 xdfs = glu.xlsub(krep);
126 maxdfs = xprune(krep);
127
128 } // end if myfnz != -1
129 } // end if chperm == -1
130
131 } // end if chmark !=jj
132 } // end while xdfs < maxdfs
133
134 // krow has no more unexplored nbrs :
135 // Place snode-rep krep in postorder DFS, if this
136 // segment is seen for the first time. (Note that
137 // "repfnz(krep)" may change later.)
138 // Baktrack dfs to its parent
139 if (traits.update_segrep(krep, jj))
140 // if (marker1(krep) < jcol )
141 {
142 segrep(nseg) = krep;
143 ++nseg;
144 // marker1(krep) = jj;
145 }
146
147 kpar = parent(krep); // Pop recursion, mimic recursion
148 if (kpar == emptyIdxLU) break; // dfs done
149 krep = kpar;
150 xdfs = xplore(krep);
151 maxdfs = xprune(krep);
152
153 } while (kpar != emptyIdxLU); // Do until empty stack
154
155 } // end if (myfnz = -1)
156
157 } // end if (kperm == -1)
158}
159
196template <typename Scalar, typename StorageIndex>
197void SparseLUImpl<Scalar, StorageIndex>::panel_dfs(const Index m, const Index w, const Index jcol, MatrixType& A,
198 IndexVector& perm_r, Index& nseg, ScalarVector& dense,
199 IndexVector& panel_lsub, IndexVector& segrep, IndexVector& repfnz,
200 IndexVector& xprune, IndexVector& marker, IndexVector& parent,
201 IndexVector& xplore, GlobalLU_t& glu) {
202 Index nextl_col; // Next available position in panel_lsub[*,jj]
203
204 // Initialize pointers
205 VectorBlock<IndexVector> marker1(marker, m, m);
206 nseg = 0;
207
208 panel_dfs_traits<IndexVector> traits(jcol, marker1.data());
209
210 // For each column in the panel
211 for (StorageIndex jj = StorageIndex(jcol); jj < jcol + w; jj++) {
212 nextl_col = (jj - jcol) * m;
213
214 VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero location in each row
215 VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Accumulate a column vector here
216
217 // For each nnz in A[*, jj] do depth first search
218 for (typename MatrixType::InnerIterator it(A, jj); it; ++it) {
219 Index krow = it.row();
220 dense_col(krow) = it.value();
221
222 StorageIndex kmark = marker(krow);
223 if (kmark == jj) continue; // krow visited before, go to the next nonzero
224
225 dfs_kernel(jj, perm_r, nseg, panel_lsub, segrep, repfnz_col, xprune, marker, parent, xplore, glu, nextl_col, krow,
226 traits);
227 } // end for nonzeros in column jj
228
229 } // end for column jj
230}
231
232} // end namespace internal
233} // end namespace Eigen
234
235#endif // SPARSELU_PANEL_DFS_H
Namespace containing all symbols from the Eigen library.
Definition Core:137