1 | import { csMark } from './csMark'
|
2 | import { csMarked } from './csMarked'
|
3 |
|
4 | /**
|
5 | * Find nonzero pattern of Cholesky L(k,1:k-1) using etree and triu(A(:,k))
|
6 | *
|
7 | * @param {Matrix} a The A matrix
|
8 | * @param {Number} k The kth column in A
|
9 | * @param {Array} parent The parent vector from the symbolic analysis result
|
10 | * @param {Array} w The nonzero pattern xi[top] .. xi[n - 1], an array of size = 2 * n
|
11 | * The first n entries is the nonzero pattern, the last n entries is the stack
|
12 | *
|
13 | * @return {Number} The index for the nonzero pattern
|
14 | *
|
15 | * Reference: http://faculty.cse.tamu.edu/davis/publications.html
|
16 | */
|
17 | export function csEreach (a, k, parent, w) {
|
18 | // a arrays
|
19 | const aindex = a._index
|
20 | const aptr = a._ptr
|
21 | const asize = a._size
|
22 | // columns
|
23 | const n = asize[1]
|
24 | // initialize top
|
25 | let top = n
|
26 | // vars
|
27 | let p, p0, p1, len
|
28 | // mark node k as visited
|
29 | csMark(w, k)
|
30 | // loop values & index for column k
|
31 | for (p0 = aptr[k], p1 = aptr[k + 1], p = p0; p < p1; p++) {
|
32 | // A(i,k) is nonzero
|
33 | let i = aindex[p]
|
34 | // only use upper triangular part of A
|
35 | if (i > k) { continue }
|
36 | // traverse up etree
|
37 | for (len = 0; !csMarked(w, i); i = parent[i]) {
|
38 | // L(k,i) is nonzero, last n entries in w
|
39 | w[n + len++] = i
|
40 | // mark i as visited
|
41 | csMark(w, i)
|
42 | }
|
43 | while (len > 0) {
|
44 | // decrement top & len
|
45 | --top
|
46 | --len
|
47 | // push path onto stack, last n entries in w
|
48 | w[n + top] = w[n + len]
|
49 | }
|
50 | }
|
51 | // unmark all nodes
|
52 | for (p = top; p < n; p++) {
|
53 | // use stack value, last n entries in w
|
54 | csMark(w, w[n + p])
|
55 | }
|
56 | // unmark node k
|
57 | csMark(w, k)
|
58 | // s[top..n-1] contains pattern of L(k,:)
|
59 | return top
|
60 | }
|