int main (void) { /* ====================================================================== */ /* input matrix A definition */ /* ====================================================================== */ Long A [ALEN] = { 0, 1, 4, /* row indices of nonzeros in column 0 */ 2, 4, /* row indices of nonzeros in column 1 */ 0, 1, 2, 3, /* row indices of nonzeros in column 2 */ 1, 3} ; /* row indices of nonzeros in column 3 */ Long p [ ] = { 0, /* column 0 is in A [0..2] */ 3, /* column 1 is in A [3..4] */ 5, /* column 2 is in A [5..8] */ 9, /* column 3 is in A [9..10] */ A_NNZ} ; /* number of nonzeros in A */ /* ====================================================================== */ /* input matrix B definition */ /* ====================================================================== */ Long B [ ] = { /* Note: only strictly lower triangular part */ /* is included, since symamd ignores the */ /* diagonal and upper triangular part of B. */ 1, /* row indices of nonzeros in column 0 */ 2, 3, /* row indices of nonzeros in column 1 */ /* row indices of nonzeros in column 2 (none) */ 4 /* row indices of nonzeros in column 3 */ } ; /* row indices of nonzeros in column 4 (none) */ Long q [ ] = { 0, /* column 0 is in B [0] */ 1, /* column 1 is in B [1..2] */ 3, /* column 2 is empty */ 3, /* column 3 is in B [3] */ 4, /* column 4 is empty */ B_NNZ} ; /* number of nonzeros in strictly lower B */ /* ====================================================================== */ /* other variable definitions */ /* ====================================================================== */ Long perm [B_N+1] ; /* note the size is N+1 */ Long stats [COLAMD_STATS] ; /* for colamd and symamd output statistics */ Long row, col, pp, length, ok ; /* ====================================================================== */ /* dump the input matrix A */ /* ====================================================================== */ printf ("colamd %d-by-%d input matrix:\n", A_NROW, A_NCOL) ; for (col = 0 ; col < A_NCOL ; col++) { length = p [col+1] - p [col] ; printf ("Column %ld, with %ld entries:\n", col, length) ; for (pp = p [col] ; pp < p [col+1] ; pp++) { row = A [pp] ; printf (" row %ld\n", row) ; } } /* ====================================================================== */ /* order the matrix. Note that this destroys A and overwrites p */ /* ====================================================================== */ ok = colamd_l (A_NROW, A_NCOL, ALEN, A, p, (double *) NULL, stats) ; colamd_l_report (stats) ; if (!ok) { printf ("colamd error!\n") ; exit (1) ; } /* ====================================================================== */ /* print the column ordering */ /* ====================================================================== */ printf ("colamd_l column ordering:\n") ; printf ("1st column: %ld\n", p [0]) ; printf ("2nd column: %ld\n", p [1]) ; printf ("3rd column: %ld\n", p [2]) ; printf ("4th column: %ld\n", p [3]) ; /* ====================================================================== */ /* dump the strictly lower triangular part of symmetric input matrix B */ /* ====================================================================== */ printf ("\n\nsymamd_l %d-by-%d input matrix:\n", B_N, B_N) ; printf ("Entries in strictly lower triangular part:\n") ; for (col = 0 ; col < B_N ; col++) { length = q [col+1] - q [col] ; printf ("Column %ld, with %ld entries:\n", col, length) ; for (pp = q [col] ; pp < q [col+1] ; pp++) { row = B [pp] ; printf (" row %ld\n", row) ; } } /* ====================================================================== */ /* order the matrix B. Note that this does not modify B or q. */ /* ====================================================================== */ ok = symamd_l (B_N, B, q, perm, (double *) NULL, stats, &calloc, &free) ; symamd_l_report (stats) ; if (!ok) { printf ("symamd error!\n") ; exit (1) ; } /* ====================================================================== */ /* print the symmetric ordering */ /* ====================================================================== */ printf ("symamd_l column ordering:\n") ; printf ("1st row/column: %ld\n", perm [0]) ; printf ("2nd row/column: %ld\n", perm [1]) ; printf ("3rd row/column: %ld\n", perm [2]) ; printf ("4th row/column: %ld\n", perm [3]) ; printf ("5th row/column: %ld\n", perm [4]) ; exit (0) ; }
int CHOLMOD(colamd) ( /* ---- input ---- */ cholmod_sparse *A, /* matrix to order */ Int *fset, /* subset of 0:(A->ncol)-1 */ size_t fsize, /* size of fset */ int postorder, /* if TRUE, follow with a coletree postorder */ /* ---- output --- */ Int *Perm, /* size A->nrow, output permutation */ /* --------------- */ cholmod_common *Common ) { double knobs [COLAMD_KNOBS] ; cholmod_sparse *C ; Int *NewPerm, *Parent, *Post, *Work2n ; Int k, nrow, ncol ; size_t s, alen ; int ok = TRUE ; /* ---------------------------------------------------------------------- */ /* check inputs */ /* ---------------------------------------------------------------------- */ RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (Perm, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; if (A->stype != 0) { ERROR (CHOLMOD_INVALID, "matrix must be unsymmetric") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; /* ---------------------------------------------------------------------- */ /* get inputs */ /* ---------------------------------------------------------------------- */ nrow = A->nrow ; ncol = A->ncol ; /* ---------------------------------------------------------------------- */ /* allocate workspace */ /* ---------------------------------------------------------------------- */ /* Note: this is less than the space used in cholmod_analyze, so if * cholmod_colamd is being called by that routine, no space will be * allocated. */ /* s = 4*nrow + ncol */ s = CHOLMOD(mult_size_t) (nrow, 4, &ok) ; s = CHOLMOD(add_size_t) (s, ncol, &ok) ; #ifdef LONG alen = colamd_l_recommended (A->nzmax, ncol, nrow) ; colamd_l_set_defaults (knobs) ; #else alen = colamd_recommended (A->nzmax, ncol, nrow) ; colamd_set_defaults (knobs) ; #endif if (!ok || alen == 0) { ERROR (CHOLMOD_TOO_LARGE, "matrix invalid or too large") ; return (FALSE) ; } CHOLMOD(allocate_work) (0, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } /* ---------------------------------------------------------------------- */ /* allocate COLAMD workspace */ /* ---------------------------------------------------------------------- */ /* colamd_printf is only available in colamd v2.4 or later */ colamd_printf = Common->print_function ; C = CHOLMOD(allocate_sparse) (ncol, nrow, alen, TRUE, TRUE, 0, CHOLMOD_PATTERN, Common) ; /* ---------------------------------------------------------------------- */ /* copy (and transpose) the input matrix A into the colamd workspace */ /* ---------------------------------------------------------------------- */ /* C = A (:,f)', which also packs A if needed. */ /* workspace: Iwork (nrow if no fset; MAX (nrow,ncol) if fset) */ ok = CHOLMOD(transpose_unsym) (A, 0, NULL, fset, fsize, C, Common) ; /* ---------------------------------------------------------------------- */ /* order the matrix (destroys the contents of C->i and C->p) */ /* ---------------------------------------------------------------------- */ /* get parameters */ if (Common->current < 0 || Common->current >= CHOLMOD_MAXMETHODS) { /* this is the CHOLMOD default, not the COLAMD default */ knobs [COLAMD_DENSE_ROW] = -1 ; } else { /* get the knobs from the Common parameters */ knobs [COLAMD_DENSE_COL] = Common->method[Common->current].prune_dense ; knobs [COLAMD_DENSE_ROW] = Common->method[Common->current].prune_dense2; knobs [COLAMD_AGGRESSIVE] = Common->method[Common->current].aggressive ; } if (ok) { Int *Cp ; Int stats [COLAMD_STATS] ; Cp = C->p ; #ifdef LONG colamd_l (ncol, nrow, alen, C->i, Cp, knobs, stats) ; #else colamd (ncol, nrow, alen, C->i, Cp, knobs, stats) ; #endif ok = stats [COLAMD_STATUS] ; ok = (ok == COLAMD_OK || ok == COLAMD_OK_BUT_JUMBLED) ; /* permutation returned in C->p, if the ordering succeeded */ for (k = 0 ; k < nrow ; k++) { Perm [k] = Cp [k] ; } } CHOLMOD(free_sparse) (&C, Common) ; /* ---------------------------------------------------------------------- */ /* column etree postordering */ /* ---------------------------------------------------------------------- */ if (postorder) { /* use the last 2*n space in Iwork for Parent and Post */ Work2n = Common->Iwork ; Work2n += 2*((size_t) nrow) + ncol ; Parent = Work2n ; /* size nrow (i/i/l) */ Post = Work2n + nrow ; /* size nrow (i/i/l) */ /* workspace: Iwork (2*nrow+ncol), Flag (nrow), Head (nrow+1) */ ok = ok && CHOLMOD(analyze_ordering) (A, CHOLMOD_COLAMD, Perm, fset, fsize, Parent, Post, NULL, NULL, NULL, Common) ; /* combine the colamd permutation with its postordering */ if (ok) { NewPerm = Common->Iwork ; /* size nrow (i/i/l) */ for (k = 0 ; k < nrow ; k++) { NewPerm [k] = Perm [Post [k]] ; } for (k = 0 ; k < nrow ; k++) { Perm [k] = NewPerm [k] ; } } } return (ok) ; }