File: cs_rowcnt_mex.c

package info (click to toggle)
ufsparse 1.2-7
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 27,536 kB
  • ctags: 5,848
  • sloc: ansic: 89,328; makefile: 4,721; fortran: 1,991; csh: 207; sed: 162; awk: 33; java: 30; sh: 8
file content (102 lines) | stat: -rw-r--r-- 3,178 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/* Compute the row counts of the Cholesky factor L of the matrix A.  Uses
 * the lower triangular part of A. */

#include "cs_mex.h"

static
void firstdesc (int n, int *parent, int *post, int *first, int *level)
{
    int len, i, k, r, s ;
    for (i = 0 ; i < n ; i++) first [i] = -1 ;
    for (k = 0 ; k < n ; k++)
    {
	i = post [k] ;	    /* node i of etree is kth postordered node */
	len = 0 ;	    /* traverse from i towards the root */
	for (r = i ; r != -1 && first [r] == -1 ; r = parent [r], len++)
	    first [r] = k ;
	len += (r == -1) ? (-1) : level [r] ;	/* end of path, or root node */
	for (s = i ; s != r ; s = parent [s]) level [s] = len-- ;
    }
}

static
int *rowcnt (cs *A, int *parent, int *post) /* return rowcount [0..n-1] */
{
    int *Ap, *Ai, *maxfirst, *ancestor, *prevleaf, *w, *first, *level, *rowcount;
    int i, j, k, len, s, p, jprev, q, n, sparent ;
    n = A->n ; Ap = A->p ; Ai = A->i ;			/* get A */
    w = cs_malloc (5*n, sizeof (int)) ; first = w+3*n ; /* get workspace */
    ancestor = w ; maxfirst = w+n ; prevleaf = w+2*n ; level = w+4*n ;
    rowcount = cs_malloc (n, sizeof (int)) ;	/* allocate result */
    firstdesc (n, parent, post, first, level) ;	/* find first and level */
    for (i = 0 ; i < n ; i++)
    {
	rowcount [i] = 1 ;	/* count the diagonal of L */
	prevleaf [i] = -1 ;	/* no previous leaf of the ith row subtree */
	maxfirst [i] = -1 ;	/* max first[j] for node j in ith subtree */
	ancestor [i] = i ;	/* every node is in its own set, by itself */
    }
    for (k = 0 ; k < n ; k++)
    {
	j = post [k] ;		/* j is the kth node in the postordered etree */
	for (p = Ap [j] ; p < Ap [j+1] ; p++)
	{
	    i = Ai [p] ;		/* get next leaf of ith row subtree */
	    if (i <= j || first [j] <= maxfirst [i]) continue ;
	    maxfirst [i] = first [j] ;	/* update max first[j] seen so far */
	    jprev = prevleaf [i] ;	/* j is a leaf of the ith subtree */
	    if (jprev == -1)
	    {
		q = i ;			/* j is first leaf of ith subtree */
	    }
	    else
	    {
		/* q = least common ancestor of jprev and j */
		for (q = jprev ; q != ancestor [q] ; q = ancestor [q]) ;
		for (s = jprev ; s != q ; s = sparent)
		{
		    sparent = ancestor [s] ;	/* path compression */
		    ancestor [s] = q ;
		}
	    }
	    rowcount [i] += (level [j] - level [q]) ;
	    prevleaf [i] = j ;	    /* j is now previous leaf of ith subtree */
	}
	if (parent [j] != -1) ancestor [j] = parent [j] ;
    }
    cs_free (w) ;
    return (rowcount) ;
}

void mexFunction
(
    int nargout,
    mxArray *pargout [ ],
    int nargin,
    const mxArray *pargin [ ]
)
{
    cs *A, Amatrix ;
    double *x ;
    int i, m, n, *parent, *post, *rowcount ;

    if (nargout > 1 || nargin != 3)
    {
	mexErrMsgTxt ("Usage: r = rowcnt(A,parent,post)") ;
    }

    /* get inputs */
    A = cs_get_sparse (&Amatrix, 1, 0, pargin [0]) ;
    n = A->n ;

    parent = cs_get_int (n, pargin [1], &i, 0) ;
    post = cs_get_int (n, pargin [2], &i, 1) ;

    rowcount = rowcnt (A, parent, post) ;

    pargout [0] = mxCreateDoubleMatrix (1, n, mxREAL) ;
    x = mxGetPr (pargout [0]) ;
    for (i = 0 ; i < n ; i++) x [i] = rowcount [i] ;

    cs_free (rowcount) ;
}