int cs_ereach(const cs *A, int k, const int *parent, int *s, int *w) { int i, p, n, len, top, *Ap, *Ai; if (!CS_CSC (A) || !parent || !s || !w) return (-1); /* check inputs */ top = n = A->n; Ap = A->p; Ai = A->i; CS_MARK (w, k); /* mark node k as visited */ for (p = Ap[k]; p < Ap[k + 1]; p++) { i = Ai[p]; /* A(i,k) is nonzero */ if (i > k) continue; /* only use upper triangular part of A */ for (len = 0; !CS_MARKED (w,i); i = parent[i]) /* traverse up etree*/ { s[len++] = i; /* L(k,i) is nonzero */ CS_MARK (w, i); /* mark i as visited */ } while (len > 0) s[--top] = s[--len]; /* push path onto stack */ } for (p = top; p < n; p++) CS_MARK (w, s [p]); /* unmark all nodes */ CS_MARK (w, k); /* unmark node k */ return (top); /* s [top..n-1] contains pattern of L(k,:)*/ }
int cs_dfs (int j, cs *G, int top, int *xi, int *pstack, const int *pinv) { int i, p, p2, done, jnew, head = 0, *Gp, *Gi ; if (!CS_CSC (G) || !xi || !pstack) return (-1) ; /* check inputs */ Gp = G->p ; Gi = G->i ; xi [0] = j ; /* initialize the recursion stack */ while (head >= 0) { j = xi [head] ; /* get j from the top of the recursion stack */ jnew = pinv ? (pinv [j]) : j ; if (!CS_MARKED (Gp, j)) { CS_MARK (Gp, j) ; /* mark node j as visited */ pstack [head] = (jnew < 0) ? 0 : CS_UNFLIP (Gp [jnew]) ; } done = 1 ; /* node j done if no unvisited neighbors */ p2 = (jnew < 0) ? 0 : CS_UNFLIP (Gp [jnew+1]) ; for (p = pstack [head] ; p < p2 ; p++) /* examine all neighbors of j */ { i = Gi [p] ; /* consider neighbor node i */ if (CS_MARKED (Gp, i)) continue ; /* skip visited node i */ pstack [head] = p ; /* pause depth-first search of node j */ xi [++head] = i ; /* start dfs at node i */ done = 0 ; /* node j is not done */ break ; /* break, to start dfs (i) */ } if (done) /* depth-first search at node j is done */ { head-- ; /* remove j from the recursion stack */ xi [--top] = j ; /* and place in the output stack */ } } return (top) ; }
/* xi [top...n-1] = nodes reachable from graph of G*P' via nodes in B(:,k). * xi [n...2n-1] used as workspace */ int csr_reach (csr *G, const csr *B, int k, int *xi, const int *pinv) { int p, m, top, *Bp, *Bj, *Gp ; if (!CS_CSC (G) || !CS_CSC (B) || !xi) return (-1) ; /* check inputs */ m = G->m ; Bp = B->p ; Bj = B->j ; Gp = G->p ; top = m ; for (p = Bp [k] ; p < Bp [k+1] ; p++) { if (!CS_MARKED (Gp, Bj [p])) /* start a dfs at unmarked node i */ { top = csr_dfs (Bj [p], G, top, xi, xi+m, pinv) ; } } for (p = top ; p < m ; p++) CS_MARK (Gp, xi [p]) ; /* restore G */ return (top) ; }
int cs_reach (cs *G, const cs *B, int k, int *xi, const int *pinv) { int p, n, top, *Bp, *Bi, *Gp ; if (!CS_CSC (G) || !CS_CSC (B) || !xi) return (-1) ; /* check inputs */ n = G->n ; Bp = B->p ; Bi = B->i ; Gp = G->p ; top = n ; for (p = Bp [k] ; p < Bp [k+1] ; p++) { if (!CS_MARKED (Gp, Bi [p])) /* start a dfs at unmarked node i */ { top = cs_dfs (Bi [p], G, top, xi, xi+n, pinv) ; } } for (p = top ; p < n ; p++) CS_MARK (Gp, xi [p]) ; /* restore G */ return (top) ; }
/* find the strongly connected components of a square matrix */ csd *cs_scc (cs *A) /* matrix A temporarily modified, then restored */ { int n, i, k, b, nb = 0, top, *xi, *pstack, *p, *r, *Ap, *ATp, *rcopy, *Blk ; cs *AT ; csd *D ; if (!CS_CSC (A)) return (NULL) ; /* check inputs */ n = A->n ; Ap = A->p ; D = cs_dalloc (n, 0) ; /* allocate result */ AT = cs_transpose (A, 0) ; /* AT = A' */ xi = cs_malloc (2*n+1, sizeof (int)) ; /* get workspace */ if (!D || !AT || !xi) return (cs_ddone (D, AT, xi, 0)) ; Blk = xi ; rcopy = pstack = xi + n ; p = D->p ; r = D->r ; ATp = AT->p ; top = n ; for (i = 0 ; i < n ; i++) /* first dfs(A) to find finish times (xi) */ { if (!CS_MARKED (Ap, i)) top = cs_dfs (i, A, top, xi, pstack, NULL) ; } for (i = 0 ; i < n ; i++) CS_MARK (Ap, i) ; /* restore A; unmark all nodes*/ top = n ; nb = n ; for (k = 0 ; k < n ; k++) /* dfs(A') to find strongly connnected comp */ { i = xi [k] ; /* get i in reverse order of finish times */ if (CS_MARKED (ATp, i)) continue ; /* skip node i if already ordered */ r [nb--] = top ; /* node i is the start of a component in p */ top = cs_dfs (i, AT, top, p, pstack, NULL) ; } r [nb] = 0 ; /* first block starts at zero; shift r up */ for (k = nb ; k <= n ; k++) r [k-nb] = r [k] ; D->nb = nb = n-nb ; /* nb = # of strongly connected components */ for (b = 0 ; b < nb ; b++) /* sort each block in natural order */ { for (k = r [b] ; k < r [b+1] ; k++) Blk [p [k]] = b ; } for (b = 0 ; b <= nb ; b++) rcopy [b] = r [b] ; for (i = 0 ; i < n ; i++) p [rcopy [Blk [i]]++] = i ; return (cs_ddone (D, AT, xi, 1)) ; }