Ejemplo n.º 1
0
GLOBAL void CAMD_preprocess
(
    Int n,		/* input matrix: A is n-by-n */
    const Int Ap [ ],	/* size n+1 */
    const Int Ai [ ],	/* size nz = Ap [n] */

    /* output matrix R: */
    Int Rp [ ],		/* size n+1 */
    Int Ri [ ],		/* size nz (or less, if duplicates present) */

    Int W [ ],		/* workspace of size n */
    Int Flag [ ]	/* workspace of size n */
)
{

    /* --------------------------------------------------------------------- */
    /* local variables */
    /* --------------------------------------------------------------------- */

    Int i, j, p, p2 ;

    ASSERT (CAMD_valid (n, n, Ap, Ai) != CAMD_INVALID) ;

    /* --------------------------------------------------------------------- */
    /* count the entries in each row of A (excluding duplicates) */
    /* --------------------------------------------------------------------- */

    for (i = 0 ; i < n ; i++)
    {
	W [i] = 0 ;		/* # of nonzeros in row i (excl duplicates) */
	Flag [i] = EMPTY ;	/* Flag [i] = j if i appears in column j */
    }
    for (j = 0 ; j < n ; j++)
    {
	p2 = Ap [j+1] ;
	for (p = Ap [j] ; p < p2 ; p++)
	{
	    i = Ai [p] ;
	    if (Flag [i] != j)
	    {
		/* row index i has not yet appeared in column j */
		W [i]++ ;	    /* one more entry in row i */
		Flag [i] = j ;	    /* flag row index i as appearing in col j*/
	    }
	}
    }

    /* --------------------------------------------------------------------- */
    /* compute the row pointers for R */
    /* --------------------------------------------------------------------- */

    Rp [0] = 0 ;
    for (i = 0 ; i < n ; i++)
    {
	Rp [i+1] = Rp [i] + W [i] ;
    }
    for (i = 0 ; i < n ; i++)
    {
	W [i] = Rp [i] ;
	Flag [i] = EMPTY ;
    }

    /* --------------------------------------------------------------------- */
    /* construct the row form matrix R */
    /* --------------------------------------------------------------------- */

    /* R = row form of pattern of A */
    for (j = 0 ; j < n ; j++)
    {
	p2 = Ap [j+1] ;
	for (p = Ap [j] ; p < p2 ; p++)
	{
	    i = Ai [p] ;
	    if (Flag [i] != j)
	    {
		/* row index i has not yet appeared in column j */
		Ri [W [i]++] = j ;  /* put col j in row i */
		Flag [i] = j ;	    /* flag row index i as appearing in col j*/
	    }
	}
    }

#ifndef NDEBUG
    ASSERT (CAMD_valid (n, n, Rp, Ri) == CAMD_OK) ;
    for (j = 0 ; j < n ; j++)
    {
	ASSERT (W [j] == Rp [j+1]) ;
    }
#endif
}
Ejemplo n.º 2
0
GLOBAL Int CAMD_order
(
    Int n,
    const Int Ap [ ],
    const Int Ai [ ],
    Int P [ ],
    double Control [ ],
    double Info [ ],
    const Int C [ ]
)
{
    Int *Len, *S, nz, i, *Pinv, info, status, *Rp, *Ri, *Cp, *Ci, ok ;
    size_t nzaat, slen ;
    double mem = 0 ;

#ifndef NDEBUG
    CAMD_debug_init ("camd") ;
#endif

    /* clear the Info array, if it exists */
    info = Info != (double *) NULL ;
    if (info)
    {
	for (i = 0 ; i < CAMD_INFO ; i++)
	{
	    Info [i] = EMPTY ;
	}
	Info [CAMD_N] = n ;
	Info [CAMD_STATUS] = CAMD_OK ;
    }

    /* make sure inputs exist and n is >= 0 */
    if (Ai == (Int *) NULL || Ap == (Int *) NULL || P == (Int *) NULL || n < 0)
    {
	if (info) Info [CAMD_STATUS] = CAMD_INVALID ;
	return (CAMD_INVALID) ;	    /* arguments are invalid */
    }

    if (n == 0)
    {
	return (CAMD_OK) ;	    /* n is 0 so there's nothing to do */
    }

    nz = Ap [n] ;
    if (info)
    {
	Info [CAMD_NZ] = nz ;
    }
    if (nz < 0)
    {
	if (info) Info [CAMD_STATUS] = CAMD_INVALID ;
	return (CAMD_INVALID) ;
    }

    /* check if n or nz will cause size_t overflow */
    if ((size_t) n >= SIZE_T_MAX / sizeof (Int)
     || (size_t) nz >= SIZE_T_MAX / sizeof (Int))
    {
	if (info) Info [CAMD_STATUS] = CAMD_OUT_OF_MEMORY ;
	return (CAMD_OUT_OF_MEMORY) ;	    /* problem too large */
    }

    /* check the input matrix:	CAMD_OK, CAMD_INVALID, or CAMD_OK_BUT_JUMBLED */
    status = CAMD_valid (n, n, Ap, Ai) ;

    if (status == CAMD_INVALID)
    {
	if (info) Info [CAMD_STATUS] = CAMD_INVALID ;
	return (CAMD_INVALID) ;	    /* matrix is invalid */
    }

    /* allocate two size-n integer workspaces */
    Len = camd_malloc (n * sizeof (Int)) ;
    Pinv = camd_malloc (n * sizeof (Int)) ;
    mem += n ;
    mem += n ;
    if (!Len || !Pinv)
    {
	/* :: out of memory :: */
	camd_free (Len) ;
	camd_free (Pinv) ;
	if (info) Info [CAMD_STATUS] = CAMD_OUT_OF_MEMORY ;
	return (CAMD_OUT_OF_MEMORY) ;
    }

    if (status == CAMD_OK_BUT_JUMBLED)
    {
	/* sort the input matrix and remove duplicate entries */
	CAMD_DEBUG1 (("Matrix is jumbled\n")) ;
	Rp = camd_malloc ((n+1) * sizeof (Int)) ;
	Ri = camd_malloc (MAX (nz,1) * sizeof (Int)) ;
	mem += (n+1) ;
	mem += MAX (nz,1) ;
	if (!Rp || !Ri)
	{
	    /* :: out of memory :: */
	    camd_free (Rp) ;
	    camd_free (Ri) ;
	    camd_free (Len) ;
	    camd_free (Pinv) ;
	    if (info) Info [CAMD_STATUS] = CAMD_OUT_OF_MEMORY ;
	    return (CAMD_OUT_OF_MEMORY) ;
	}
	/* use Len and Pinv as workspace to create R = A' */
	CAMD_preprocess (n, Ap, Ai, Rp, Ri, Len, Pinv) ;
	Cp = Rp ;
	Ci = Ri ;
    }
    else
    {
	/* order the input matrix as-is.  No need to compute R = A' first */
	Rp = NULL ;
	Ri = NULL ;
	Cp = (Int *) Ap ;
	Ci = (Int *) Ai ;
    }

    /* --------------------------------------------------------------------- */
    /* determine the symmetry and count off-diagonal nonzeros in A+A' */
    /* --------------------------------------------------------------------- */

    nzaat = CAMD_aat (n, Cp, Ci, Len, P, Info) ;
    CAMD_DEBUG1 (("nzaat: %g\n", (double) nzaat)) ;
    ASSERT ((MAX (nz-n, 0) <= nzaat) && (nzaat <= 2 * (size_t) nz)) ;

    /* --------------------------------------------------------------------- */
    /* allocate workspace for matrix, elbow room, and 7 size-n vectors */
    /* --------------------------------------------------------------------- */

    S = NULL ;
    slen = nzaat ;			/* space for matrix */
    ok = ((slen + nzaat/5) >= slen) ;	/* check for size_t overflow */
    slen += nzaat/5 ;			/* add elbow room */
    for (i = 0 ; ok && i < 8 ; i++)
    {
	ok = ((slen + n+1) > slen) ;	/* check for size_t overflow */
	slen += (n+1) ;		/* size-n elbow room, 7 size-(n+1) workspace */
    }
    mem += slen ;
    ok = ok && (slen < SIZE_T_MAX / sizeof (Int)) ; /* check for overflow */
    ok = ok && (slen < Int_MAX) ;	/* S[i] for Int i must be OK */
    if (ok)
    {
	S = camd_malloc (slen * sizeof (Int)) ;
    }
    CAMD_DEBUG1 (("slen %g\n", (double) slen)) ;
    if (!S)
    {
	/* :: out of memory :: (or problem too large) */
	camd_free (Rp) ;
	camd_free (Ri) ;
	camd_free (Len) ;
	camd_free (Pinv) ;
	if (info) Info [CAMD_STATUS] = CAMD_OUT_OF_MEMORY ;
	return (CAMD_OUT_OF_MEMORY) ;
    }
    if (info)
    {
	/* memory usage, in bytes. */
	Info [CAMD_MEMORY] = mem * sizeof (Int) ;
    }

    /* --------------------------------------------------------------------- */
    /* order the matrix */
    /* --------------------------------------------------------------------- */

    CAMD_1 (n, Cp, Ci, P, Pinv, Len, slen, S, Control, Info, C) ;

    /* --------------------------------------------------------------------- */
    /* free the workspace */
    /* --------------------------------------------------------------------- */

    camd_free (Rp) ;
    camd_free (Ri) ;
    camd_free (Len) ;
    camd_free (Pinv) ;
    camd_free (S) ;
    if (info) Info [CAMD_STATUS] = status ;
    return (status) ;	    /* successful ordering */
}
Ejemplo n.º 3
0
void camdtest (cholmod_sparse *A)
{
    double Control [CAMD_CONTROL], Info [CAMD_INFO], alpha ;
    Int *P, *Cp, *Ci, *Sp, *Si, *Bp, *Bi, *Ep, *Ei, *Fp, *Fi,
	*Len, *Nv, *Next, *Head, *Elen, *Deg, *Wi, *W, *Flag, *BucketSet,
	*Constraint ;
    cholmod_sparse *C, *B, *S, *E, *F ;
    Int i, j, n, nrow, ncol, ok, cnz, bnz, p, trial, sorted ;

    /* ---------------------------------------------------------------------- */
    /* get inputs */
    /* ---------------------------------------------------------------------- */

    printf ("\nCAMD test\n") ;

    if (A == NULL)
    {
	return ;
    }

    if (A->stype)
    {
	B = CHOLMOD(copy) (A, 0, 0, cm) ;
    }
    else
    {
	B = CHOLMOD(aat) (A, NULL, 0, 0, cm) ;
    }

    if (A->nrow != A->ncol)
    {
	F = CHOLMOD(copy_sparse) (B, cm) ;
	OK (F->nrow == F->ncol) ;
	CHOLMOD(sort) (F, cm) ;
    }
    else
    {
	/* A is square and unsymmetric, and may have entries in A+A' that
	 * are not in A */
	F = CHOLMOD(copy_sparse) (A, cm) ;
	CHOLMOD(sort) (F, cm) ;
    }

    C = CHOLMOD(copy_sparse) (B, cm) ;

    nrow = C->nrow ;
    ncol = C->ncol ;
    n = nrow ;
    OK (nrow == ncol) ;

    Cp = C->p ;
    Ci = C->i ;

    Bp = B->p ;
    Bi = B->i ;

    /* ---------------------------------------------------------------------- */
    /* S = sorted form of B, using CAMD_preprocess */
    /* ---------------------------------------------------------------------- */

    cnz = CHOLMOD(nnz) (C, cm) ;
    S = CHOLMOD(allocate_sparse) (n, n, cnz, TRUE, TRUE, 0, CHOLMOD_PATTERN,
	    cm);
    Sp = S->p ;
    Si = S->i ;

    W = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    Flag = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    CAMD_preprocess (n, Bp, Bi, Sp, Si, W, Flag) ;

    /* ---------------------------------------------------------------------- */
    /* allocate workspace for camd */
    /* ---------------------------------------------------------------------- */

    P = CHOLMOD(malloc) (n+1, sizeof (Int), cm) ;
    Constraint = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    for (i = 0 ; i < n ; i++)
    {
	Constraint [i] = my_rand () % (MIN (n,6)) ;
    }

    ok = CAMD_cvalid (n, Constraint) ; OK (ok) ;
    if (n > 0)
    {
	Constraint [0] = -1 ;
	ok = CAMD_cvalid (n, Constraint) ; OK (!ok) ;
	Constraint [0] = 0 ;
    }
    ok = CAMD_cvalid (n, Constraint) ; OK (ok) ;
    ok = CAMD_cvalid (n, NULL) ; OK (ok) ;

    Len  = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    Nv   = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    Next = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    Head = CHOLMOD(malloc) (n+1, sizeof (Int), cm) ;
    Elen = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    Deg  = CHOLMOD(malloc) (n, sizeof (Int), cm) ;
    Wi   = CHOLMOD(malloc) (n+1, sizeof (Int), cm) ;
    BucketSet = CHOLMOD(malloc) (n, sizeof (Int), cm) ;

    /* ---------------------------------------------------------------------- */

    for (sorted = 0 ; sorted <= 1 ; sorted++)
    {

	if (sorted) CHOLMOD(sort) (C, cm) ;

	Cp = C->p ;
	Ci = C->i ;

	/* ------------------------------------------------------------------ */
	/* order C with CAMD_order */
	/* ------------------------------------------------------------------ */

	CAMD_defaults (Control) ;
	CAMD_defaults (NULL) ;
	CAMD_control (Control) ;
	CAMD_control (NULL) ;
	CAMD_info (NULL) ;

	ok = CAMD_order (n, Cp, Ci, P, Control, Info, Constraint) ;
	printf ("camd return value: "ID"\n", ok) ;
	CAMD_info (Info) ;
	OK (sorted ? (ok == CAMD_OK) : (ok >= CAMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "CAMD permutation", cm)) ;

	ok = CAMD_order (n, Cp, Ci, P, Control, Info, NULL) ;
	printf ("camd return value: "ID"\n", ok) ;
	CAMD_info (Info) ;
	OK (sorted ? (ok == CAMD_OK) : (ok >= CAMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "CAMD permutation", cm)) ;

	/* no dense rows/cols */
	alpha = Control [CAMD_DENSE] ;
	Control [CAMD_DENSE] = -1 ;
	CAMD_control (Control) ;
	ok = CAMD_order (n, Cp, Ci, P, Control, Info, NULL) ;
	printf ("camd return value: "ID"\n", ok) ;
	CAMD_info (Info) ;
	OK (sorted ? (ok == CAMD_OK) : (ok >= CAMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "CAMD permutation (alpha=-1)", cm)) ;

	/* many dense rows/cols */
	Control [CAMD_DENSE] = 0 ;
	CAMD_control (Control) ;
	ok = CAMD_order (n, Cp, Ci, P, Control, Info, NULL) ;
	printf ("camd return value: "ID"\n", ok) ;
	CAMD_info (Info) ;
	OK (sorted ? (ok == CAMD_OK) : (ok >= CAMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "CAMD permutation (alpha=0)", cm)) ;
	Control [CAMD_DENSE] = alpha ;

	/* no aggressive absorption */
	Control [CAMD_AGGRESSIVE] = FALSE ;
	CAMD_control (Control) ;
	ok = CAMD_order (n, Cp, Ci, P, Control, Info, NULL) ;
	printf ("camd return value: "ID"\n", ok) ;
	CAMD_info (Info) ;
	OK (sorted ? (ok == CAMD_OK) : (ok >= CAMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "CAMD permutation (no agg) ", cm)) ;
	Control [CAMD_AGGRESSIVE] = TRUE ;

	/* ------------------------------------------------------------------ */
	/* order F with CAMD_order */
	/* ------------------------------------------------------------------ */

	Fp = F->p ;
	Fi = F->i ;
	ok = CAMD_order (n, Fp, Fi, P, Control, Info, NULL) ;
	printf ("camd return value: "ID"\n", ok) ;
	CAMD_info (Info) ;
	OK (sorted ? (ok == CAMD_OK) : (ok >= CAMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "F: CAMD permutation", cm)) ;

	/* ------------------------------------------------------------------ */
	/* order S with CAMD_order */
	/* ------------------------------------------------------------------ */

	ok = CAMD_order (n, Sp, Si, P, Control, Info, NULL) ;
	printf ("camd return value: "ID"\n", ok) ;
	CAMD_info (Info) ;
	OK (sorted ? (ok == CAMD_OK) : (ok >= CAMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "CAMD permutation", cm)) ;

	/* ------------------------------------------------------------------ */
	/* order E with CAMD_2, which destroys its contents */
	/* ------------------------------------------------------------------ */

	E = CHOLMOD(copy) (B, 0, -1, cm) ;	/* remove diagonal entries */
	bnz = CHOLMOD(nnz) (E, cm) ;

	/* add the bare minimum extra space to E */
	ok = CHOLMOD(reallocate_sparse) (bnz + n, E, cm) ;
	OK (ok) ;
	Ep = E->p ;
	Ei = E->i ;

	for (j = 0 ; j < n ; j++)
	{
	    Len [j] = Ep [j+1] - Ep [j] ;
	}

	printf ("calling CAMD_2:\n") ;
	if (n > 0)
	{
	    CAMD_2 (n, Ep, Ei, Len, E->nzmax, Ep [n], Nv, Next, P, Head, Elen,
		Deg, Wi, NULL, Info, NULL, BucketSet) ;
	    CAMD_info (Info) ;
	    OK (CHOLMOD(print_perm) (P, n, n, "CAMD2 permutation", cm)) ;
	}

	/* ------------------------------------------------------------------ */
	/* error tests */
	/* ------------------------------------------------------------------ */

	ok = CAMD_order (n, Cp, Ci, P, Control, Info, NULL) ;
	OK (sorted ? (ok == CAMD_OK) : (ok >= CAMD_OK)) ;
	ok = CAMD_order (-1, Cp, Ci, P, Control, Info, NULL) ;
	OK (ok == CAMD_INVALID);
	ok = CAMD_order (0, Cp, Ci, P, Control, Info, NULL) ;
	OK (sorted ? (ok == CAMD_OK) : (ok >= CAMD_OK)) ;
	ok = CAMD_order (n, NULL, Ci, P, Control, Info, NULL) ;
	OK (ok == CAMD_INVALID);
	ok = CAMD_order (n, Cp, NULL, P, Control, Info, NULL) ;
	OK (ok == CAMD_INVALID);
	ok = CAMD_order (n, Cp, Ci, NULL, Control, Info, NULL) ;
	OK (ok == CAMD_INVALID);

	if (n > 0)
	{
	    printf ("CAMD error tests:\n") ;

	    p = Cp [n] ;
	    Cp [n] = -1 ;
	    ok = CAMD_order (n, Cp, Ci, P, Control, Info, NULL) ;
	    OK (ok == CAMD_INVALID) ;

	    if (Size_max/2 == Int_max)
	    {
		Cp [n] = Int_max ;
		ok = CAMD_order (n, Cp, Ci, P, Control, Info, NULL) ;
		printf ("CAMD status is %d\n", ok) ;
		OK (ok == CAMD_OUT_OF_MEMORY) ;
	    }

	    Cp [n] = p ;
	    ok = CAMD_order (n, Cp, Ci, P, Control, Info, NULL) ;
	    OK (sorted ? (ok == CAMD_OK) : (ok >= CAMD_OK)) ;
	    if (Cp [n] > 0)
	    {
		printf ("Mangle column zero:\n") ;
		i = Ci [0] ;
		Ci [0] = -1 ;
		ok = CAMD_order (n, Cp, Ci, P, Control, Info, NULL) ;
		CAMD_info (Info) ;
		OK (ok == CAMD_INVALID) ;
		Ci [0] = i ;
	    }
	}

	ok = CAMD_valid (n, n, Sp, Si) ;
	OK (sorted ? (ok == CAMD_OK) : (ok >= CAMD_OK)) ;
	ok = CAMD_valid (-1, n, Sp, Si) ;	    OK (ok == CAMD_INVALID) ;
	ok = CAMD_valid (n, -1, Sp, Si) ;	    OK (ok == CAMD_INVALID) ;
	ok = CAMD_valid (n, n, NULL, Si) ;	    OK (ok == CAMD_INVALID) ;
	ok = CAMD_valid (n, n, Sp, NULL) ;	    OK (ok == CAMD_INVALID) ;

	if (n > 0 && Sp [n] > 0)
	{

	    p = Sp [n] ;
	    Sp [n] = -1 ;
	    ok = CAMD_valid (n, n, Sp, Si) ; OK (ok == CAMD_INVALID) ;
	    Sp [n] = p ;

	    p = Sp [0] ;
	    Sp [0] = -1 ;
	    ok = CAMD_valid (n, n, Sp, Si) ; OK (ok == CAMD_INVALID) ;
	    Sp [0] = p ;

	    p = Sp [1] ;
	    Sp [1] = -1 ;
	    ok = CAMD_valid (n, n, Sp, Si) ; OK (ok == CAMD_INVALID) ;
	    Sp [1] = p ;

	    i = Si [0] ;
	    Si [0] = -1 ;
	    ok = CAMD_valid (n, n, Sp, Si) ; OK (ok == CAMD_INVALID) ;
	    Si [0] = i ;

	}

	ok = CAMD_valid (n, n, Sp, Si) ;
	OK (sorted ? (ok == CAMD_OK) : (ok >= CAMD_OK)) ;
	CAMD_preprocess (n, Bp, Bi, Sp, Si, W, Flag) ;
	ok = CAMD_valid (n, n, Sp, Si) ;
	OK (ok == CAMD_OK) ;

	if (n > 0 && Bp [n] > 0)
	{

	    p = Bp [n] ;
	    Bp [n] = -1 ;
	    ok = CAMD_valid (n, n, Bp, Bi) ;	    OK (ok == CAMD_INVALID) ;
	    Bp [n] = p ;


	    p = Bp [1] ;
	    Bp [1] = -1 ;
	    ok = CAMD_valid (n, n, Bp, Bi) ;	    OK (ok == CAMD_INVALID) ;
	    Bp [1] = p ;

	    i = Bi [0] ;
	    Bi [0] = -1 ;
	    ok = CAMD_valid (n, n, Bp, Bi) ;	    OK (ok == CAMD_INVALID) ;
	    Bi [0] = i ;
	}

	CAMD_preprocess (n, Bp, Bi, Sp, Si, W, Flag) ;

	Info [CAMD_STATUS] = 777 ;
	CAMD_info (Info) ;

	/* ------------------------------------------------------------------ */
	/* memory tests */
	/* ------------------------------------------------------------------ */

	if (n > 0)
	{
	    camd_malloc = cm->malloc_memory ;
	    camd_free = cm->free_memory ;
	    ok = CAMD_order (n, Cp, Ci, P, Control, Info, NULL) ;
	    OK (sorted ? (ok == CAMD_OK) : (ok >= CAMD_OK)) ;

	    test_memory_handler ( ) ;
	    camd_malloc = cm->malloc_memory ;
	    camd_free = cm->free_memory ;
	    for (trial = 0 ; trial < 6 ; trial++)
	    {
		my_tries = trial ;
		printf ("CAMD memory trial "ID"\n", trial) ;
		ok = CAMD_order (n, Cp, Ci, P, Control, Info, NULL) ;
		CAMD_info (Info) ;
		OK (ok == CAMD_OUT_OF_MEMORY
		    || (sorted ? (ok == CAMD_OK) : (ok >= CAMD_OK))) ;
	    }
	    normal_memory_handler ( ) ;
	    OK (CHOLMOD(print_perm) (P, n, n, "CAMD2 permutation", cm)) ;

	    camd_malloc = cm->malloc_memory ;
	    camd_free = cm->free_memory ;
	}

	CHOLMOD(free_sparse) (&E, cm) ;
    }

    /* ---------------------------------------------------------------------- */
    /* free everything */
    /* ---------------------------------------------------------------------- */

    CHOLMOD(free) (n, sizeof (Int), Len,  cm) ;
    CHOLMOD(free) (n, sizeof (Int), Nv,   cm) ;
    CHOLMOD(free) (n, sizeof (Int), Next, cm) ;
    CHOLMOD(free) (n+1, sizeof (Int), Head, cm) ;
    CHOLMOD(free) (n, sizeof (Int), Elen, cm) ;
    CHOLMOD(free) (n, sizeof (Int), Deg,  cm) ;
    CHOLMOD(free) (n+1, sizeof (Int), Wi, cm) ;
    CHOLMOD(free) (n, sizeof (Int), BucketSet, cm) ;

    CHOLMOD(free) (n+1, sizeof (Int), P, cm) ;
    CHOLMOD(free) (n, sizeof (Int), Constraint, cm) ;

    CHOLMOD(free) (n, sizeof (Int), W, cm) ;
    CHOLMOD(free) (n, sizeof (Int), Flag, cm) ;

    CHOLMOD(free_sparse) (&S, cm) ;
    CHOLMOD(free_sparse) (&B, cm) ;
    CHOLMOD(free_sparse) (&C, cm) ;
    CHOLMOD(free_sparse) (&F, cm) ;
}
Ejemplo n.º 4
0
GLOBAL void CAMD_1
(
    Int n,		/* n > 0 */
    const Int Ap [ ],	/* input of size n+1, not modified */
    const Int Ai [ ],	/* input of size nz = Ap [n], not modified */
    Int P [ ],		/* size n output permutation */
    Int Pinv [ ],	/* size n output inverse permutation */
    Int Len [ ],	/* size n input, undefined on output */
    Int slen,		/* slen >= sum (Len [0..n-1]) + 7n+2,
			 * ideally slen = 1.2 * sum (Len) + 8n+2 */
    Int S [ ],		/* size slen workspace */
    double Control [ ],	/* input array of size CAMD_CONTROL */
    double Info [ ],	/* output array of size CAMD_INFO */
    const Int C [ ]	/* Constraint set of size n */
)
{
    Int i, j, k, p, pfree, iwlen, pj, p1, p2, pj2, *Iw, *Pe, *Nv, *Head,
	*Elen, *Degree, *s, *W, *Sp, *Tp, *BucketSet ;

    /* --------------------------------------------------------------------- */
    /* construct the matrix for CAMD_2 */
    /* --------------------------------------------------------------------- */

    ASSERT (n > 0) ;

    iwlen = slen - (7*n+2) ;	/* allocate 7*n+2 workspace from S */
    s = S ;
    Pe = s ;	    s += n ;
    Nv = s ;	    s += n ;
    Head = s ;	    s += n+1 ;	/* NOTE: was size n in AMD; size n+1 in CAMD */
    Elen = s ;	    s += n ;
    Degree = s ;    s += n ;
    W = s ;	    s += n+1 ;	/* NOTE: was size n in AMD; size n+1 in CAMD */
    BucketSet = s ; s += n ;
    Iw = s ;	    s += iwlen ;

    ASSERT (CAMD_valid (n, n, Ap, Ai) == CAMD_OK) ;
    ASSERT (CAMD_cvalid (n, C)) ;

    /* construct the pointers for A+A' */
    Sp = Nv ;			/* use Nv and W as workspace for Sp and Tp [ */
    Tp = W ;
    pfree = 0 ;
    for (j = 0 ; j < n ; j++)
    {
	Pe [j] = pfree ;
	Sp [j] = pfree ;
	pfree += Len [j] ;
    }

    /* Note that this restriction on iwlen is slightly more restrictive than
     * what is strictly required in CAMD_2.  CAMD_2 can operate with no elbow
     * room at all, but it will be very slow.  For better performance, at
     * least size-n elbow room is enforced. */
    ASSERT (iwlen >= pfree + n) ;

#ifndef NDEBUG
    for (p = 0 ; p < iwlen ; p++) Iw [p] = EMPTY ;
#endif

    for (k = 0 ; k < n ; k++)
    {
	CAMD_DEBUG1 (("Construct row/column k= "ID" of A+A'\n", k))  ;
	p1 = Ap [k] ;
	p2 = Ap [k+1] ;

	/* construct A+A' */
	for (p = p1 ; p < p2 ; )
	{
	    /* scan the upper triangular part of A */
	    j = Ai [p] ;
	    ASSERT (j >= 0 && j < n) ;
	    if (j < k)
	    {
		/* entry A (j,k) in the strictly upper triangular part */
		ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ;
		ASSERT (Sp [k] < (k == n-1 ? pfree : Pe [k+1])) ;
		Iw [Sp [j]++] = k ;
		Iw [Sp [k]++] = j ;
		p++ ;
	    }
	    else if (j == k)
	    {
		/* skip the diagonal */
		p++ ;
		break ;
	    }
	    else /* j > k */
	    {
		/* first entry below the diagonal */
		break ;
	    }
	    /* scan lower triangular part of A, in column j until reaching
	     * row k.  Start where last scan left off. */
	    ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ;
	    pj2 = Ap [j+1] ;
	    for (pj = Tp [j] ; pj < pj2 ; )
	    {
		i = Ai [pj] ;
		ASSERT (i >= 0 && i < n) ;
		if (i < k)
		{
		    /* A (i,j) is only in the lower part, not in upper */
		    ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ;
		    ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ;
		    Iw [Sp [i]++] = j ;
		    Iw [Sp [j]++] = i ;
		    pj++ ;
		}
		else if (i == k)
		{
		    /* entry A (k,j) in lower part and A (j,k) in upper */
		    pj++ ;
		    break ;
		}
		else /* i > k */
		{
		    /* consider this entry later, when k advances to i */
		    break ;
		}
	    }
	    Tp [j] = pj ;
	}
	Tp [k] = p ;
    }

    /* clean up, for remaining mismatched entries */
    for (j = 0 ; j < n ; j++)
    {
	for (pj = Tp [j] ; pj < Ap [j+1] ; pj++)
	{
	    i = Ai [pj] ;
	    ASSERT (i >= 0 && i < n) ;
	    /* A (i,j) is only in the lower part, not in upper */
	    ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ;
	    ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ;
	    Iw [Sp [i]++] = j ;
	    Iw [Sp [j]++] = i ;
	}
    }

#ifndef NDEBUG
    for (j = 0 ; j < n-1 ; j++) ASSERT (Sp [j] == Pe [j+1]) ;
    ASSERT (Sp [n-1] == pfree) ;
#endif

    /* Tp and Sp no longer needed ] */

    /* --------------------------------------------------------------------- */
    /* order the matrix */
    /* --------------------------------------------------------------------- */

    CAMD_2 (n, Pe, Iw, Len, iwlen, pfree,
	Nv, Pinv, P, Head, Elen, Degree, W, Control, Info, C, BucketSet) ;
}