示例#1
0
int CHOLMOD(pack_factor)
(
    /* ---- in/out --- */
    cholmod_factor *L,	/* factor to modify */
    /* --------------- */
    cholmod_common *Common
)
{
    double *Lx, *Lz ;
    Int *Lp, *Li, *Lnz, *Lnext ;
    Int pnew, j, k, pold, len, n, head, tail, grow2 ;

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

    RETURN_IF_NULL_COMMON (FALSE) ;
    RETURN_IF_NULL (L, FALSE) ;
    RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ;
    Common->status = CHOLMOD_OK ;
    DEBUG (CHOLMOD(dump_factor) (L, "start pack", Common)) ;
    PRINT1 (("PACK factor %d\n", L->is_super)) ;

    if (L->xtype == CHOLMOD_PATTERN || L->is_super)
    {
	/* nothing to do unless L is simplicial numeric */
	return (TRUE) ;
    }

    /* ---------------------------------------------------------------------- */
    /* pack */
    /* ---------------------------------------------------------------------- */

    grow2 = Common->grow2 ;
    PRINT1 (("\nPACK grow2 "ID"\n", grow2)) ;

    pnew = 0 ;
    n = L->n ;
    Lp = L->p ;
    Li = L->i ;
    Lx = L->x ;
    Lz = L->z ;
    Lnz = L->nz ;
    Lnext = L->next ;

    head = n+1 ;
    tail = n ;

    for (j = Lnext [head] ; j != tail ; j = Lnext [j])
    {
	/* pack column j */
	pold = Lp [j] ;
	len = Lnz [j] ;
	ASSERT (len > 0) ;
	PRINT2 (("col "ID" pnew "ID" pold "ID"\n", j, pnew, pold)) ;
	if (pnew < pold)
	{
	    PRINT2 (("    pack this column\n")) ;

	    for (k = 0 ; k < len ; k++)
	    {
		Li [pnew + k] = Li [pold + k] ;
	    }

	    if (L->xtype == CHOLMOD_REAL)
	    {
		for (k = 0 ; k < len ; k++)
		{
		    Lx [pnew + k] = Lx [pold + k] ;
		}
	    }
	    else if (L->xtype == CHOLMOD_COMPLEX)
	    {
		for (k = 0 ; k < len ; k++)
		{
		    Lx [2*(pnew + k)  ] = Lx [2*(pold + k)  ] ;
		    Lx [2*(pnew + k)+1] = Lx [2*(pold + k)+1] ;
		}
	    }
	    else if (L->xtype == CHOLMOD_ZOMPLEX)
	    {
		for (k = 0 ; k < len ; k++)
		{
		    Lx [pnew + k] = Lx [pold + k] ;
		    Lz [pnew + k] = Lz [pold + k] ;
		}
	    }

	    Lp [j] = pnew ;
	}
	len = MIN (len + grow2, n - j) ;
	pnew = MIN (Lp [j] + len, Lp [Lnext [j]]) ;
    }
    PRINT2 (("final pnew = "ID"\n", pnew)) ;
    return (TRUE) ;
}
示例#2
0
void cctest (cholmod_sparse *A)
{

    double knobs [CCOLAMD_KNOBS], knobs2 [CCOLAMD_KNOBS] ;
    Int *P, *Cmember, *Cp, *Ci, *Front_npivcol, *Front_nrows, *Front_ncols,
	*Front_parent, *Front_cols, *InFront, *Si, *Sp ;
    cholmod_sparse *C, *A2, *B, *S ;
    Int nrow, ncol, alen, ok, stats [CCOLAMD_STATS], csets, i, nfr, c, p ;
    size_t s ;

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

    my_srand (42) ;						/* RAND reset */

    printf ("\nCCOLAMD test\n") ;

    if (A == NULL)
    {
	return ;
    }

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

    nrow = B->nrow ;
    ncol = B->ncol ;
    Si = S->i ;
    Sp = S->p ;

    /* ---------------------------------------------------------------------- */
    /* allocate workspace and Cmember for ccolamd */
    /* ---------------------------------------------------------------------- */

    P = CHOLMOD(malloc) (nrow+1, sizeof (Int), cm) ;
    Cmember = CHOLMOD(malloc) (nrow, sizeof (Int), cm) ;
    Front_npivcol = CHOLMOD(malloc) (nrow+1, sizeof (Int), cm) ;
    Front_nrows   = CHOLMOD(malloc) (nrow+1, sizeof (Int), cm) ;
    Front_ncols   = CHOLMOD(malloc) (nrow+1, sizeof (Int), cm) ;
    Front_parent  = CHOLMOD(malloc) (nrow+1, sizeof (Int), cm) ;
    Front_cols    = CHOLMOD(malloc) (nrow+1, sizeof (Int), cm) ;
    InFront       = CHOLMOD(malloc) (ncol, sizeof (Int), cm) ;

    csets = MIN (6, nrow) ;
    for (i = 0 ; i < nrow ; i++)
    {
	Cmember [i] = nrand (csets) ;
    }

    CCOLAMD_set_defaults (knobs) ;
    CCOLAMD_set_defaults (knobs2) ;
    CCOLAMD_set_defaults (NULL) ;
    CCOLAMD_report (NULL) ;
    CSYMAMD_report (NULL) ;

    alen = CCOLAMD_recommended (B->nzmax, ncol, nrow) ;
    C = CHOLMOD(allocate_sparse) (ncol, nrow, alen, TRUE, TRUE, 0,
	    CHOLMOD_PATTERN, cm) ;
    Cp = C->p ;
    Ci = C->i ;

    /* ---------------------------------------------------------------------- */
    /* order with ccolamd */
    /* ---------------------------------------------------------------------- */

    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ; OK (ok) ;
    CHOLMOD(print_sparse) (C, "C for ccolamd", cm) ;
    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, NULL, stats, Cmember) ;
    CCOLAMD_report (stats) ;
    OK (ok) ;
    ok = stats [CCOLAMD_STATUS] ;
    ok = (ok == CCOLAMD_OK || ok == CCOLAMD_OK_BUT_JUMBLED) ;
    OK (ok) ;

    /* permutation returned in C->p, if the ordering succeeded */
    /* make sure P obeys the constraints */
    OK (check_constraints (Cp, Cmember, nrow)) ;

    /* ---------------------------------------------------------------------- */
    /* order with ccolamd2 */
    /* ---------------------------------------------------------------------- */

    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ; OK (ok) ;
    ok = CCOLAMD_2 (ncol, nrow, alen, Ci, Cp, NULL, stats,
	    Front_npivcol, Front_nrows, Front_ncols, Front_parent,
	    Front_cols, &nfr, InFront, Cmember) ;
    CCOLAMD_report (stats) ;
    OK (check_constraints (Cp, Cmember, nrow)) ;

    /* ---------------------------------------------------------------------- */
    /* with a small dense-row threshold */
    /* ---------------------------------------------------------------------- */

    knobs2 [CCOLAMD_DENSE_ROW] = 0 ;
    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ; OK (ok) ;
    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs2, stats, Cmember) ;
    CCOLAMD_report (stats) ;

    knobs2 [CCOLAMD_DENSE_ROW] = 0.625 ;
    knobs2 [CCOLAMD_DENSE_COL] = 0 ;
    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ; OK (ok) ;
    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs2, stats, Cmember) ;
    CCOLAMD_report (stats) ;

    knobs2 [CCOLAMD_DENSE_ROW] = 0.625 ;
    knobs2 [CCOLAMD_DENSE_COL] = -1 ;
    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ; OK (ok) ;
    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs2, stats, Cmember) ;
    CCOLAMD_report (stats) ;

    knobs2 [CCOLAMD_DENSE_COL] = 0 ;

    /* ---------------------------------------------------------------------- */
    /* duplicate entries */
    /* ---------------------------------------------------------------------- */

    if (ncol > 2 && nrow > 2)
    {
	ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ;
	OK (ok) ;
	if (Cp [1] - Cp [0] > 2)
	{
	    Ci [0] = Ci [1] ;
	}
	ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs2, stats, Cmember) ;
	CCOLAMD_report (stats) ;
	OK (CHOLMOD(print_perm) (Cp, nrow, nrow, "ccolamd perm", cm)) ;
    }

    /* ---------------------------------------------------------------------- */
    /* csymamd */
    /* ---------------------------------------------------------------------- */

    if (nrow == ncol)
    {
	Int n = nrow ;

	ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, stats,
		cm->calloc_memory, cm->free_memory, Cmember, A->stype) ;
	OK (ok) ;
	OK (check_constraints (P, Cmember, n)) ;
	CSYMAMD_report (stats) ;

	/* ------------------------------------------------------------------ */
	/* csymamd errors */
	/* ------------------------------------------------------------------ */

	ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, NULL, cm->calloc_memory,
		cm->free_memory, Cmember, A->stype) ;		       NOT (ok);

	ok = CSYMAMD_MAIN (n, NULL, Sp, P, NULL, stats, cm->calloc_memory,
		cm->free_memory, Cmember, A->stype) ;		       NOT (ok);
	CSYMAMD_report (stats) ;

	ok = CSYMAMD_MAIN (n, Si, NULL, P, NULL, stats, cm->calloc_memory,
		cm->free_memory, Cmember, A->stype) ;		       NOT (ok);
	CSYMAMD_report (stats) ;

	ok = CSYMAMD_MAIN (-1, Si, Sp, P, NULL, stats, cm->calloc_memory,
		cm->free_memory, Cmember, A->stype) ;		       NOT (ok);
	CSYMAMD_report (stats) ;

	p = Sp [n] ;
	Sp [n] = -1 ;
	ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, stats, cm->calloc_memory,
		cm->free_memory, Cmember, A->stype) ;		       NOT (ok);
	CSYMAMD_report (stats) ;
	Sp [n] = p ;

	Sp [0] = -1 ;
	ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, stats, cm->calloc_memory,
		cm->free_memory, Cmember, A->stype) ;		       NOT (ok);
	CSYMAMD_report (stats) ;
	Sp [0] = 0 ;

	if (n > 2 && Sp [n] > 3)
	{
	    p = Sp [1] ;
	    Sp [1] = -1 ;
	    ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, stats, cm->calloc_memory,
		    cm->free_memory, Cmember, A->stype) ;	       NOT (ok);
	    CSYMAMD_report (stats) ;
	    Sp [1] = p ;

	    i = Si [0] ;
	    Si [0] = -1 ;
	    ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, stats, cm->calloc_memory,
		    cm->free_memory, Cmember, A->stype) ;	       NOT (ok);
	    CSYMAMD_report (stats) ;
	    Si [0] = i ;

	    /* ok, but jumbled */
	    i = Si [0] ;
	    Si [0] = Si [1] ;
	    Si [1] = i ;
	    ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, stats, cm->calloc_memory,
		    cm->free_memory, Cmember, A->stype) ;	       OK (ok);
	    CSYMAMD_report (stats) ;
	    i = Si [0] ;
	    Si [0] = Si [1] ;
	    Si [1] = i ;

	    test_memory_handler ( ) ;
	    ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, stats, cm->calloc_memory,
		    cm->free_memory, Cmember, A->stype) ;	       NOT(ok);
	    CSYMAMD_report (stats) ;
	    normal_memory_handler ( ) ;
	}
    }

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

    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ;   OK (ok) ;
    ok = CCOLAMD_MAIN (ncol, nrow, 0, Ci, Cp, knobs, stats, Cmember) ;     NOT (ok) ;
    CCOLAMD_report (stats) ;

    ok = CCOLAMD_MAIN (ncol, nrow, alen, NULL, Cp, knobs, stats, Cmember); NOT (ok) ;
    CCOLAMD_report (stats) ;

    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, NULL, knobs, stats, Cmember); NOT (ok) ;
    CCOLAMD_report (stats) ;

    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs, NULL, Cmember) ;   NOT (ok) ;
    CCOLAMD_report (stats) ;

    ok = CCOLAMD_MAIN (-1, nrow, alen, Ci, Cp, knobs, stats, Cmember) ;    NOT (ok) ;
    CCOLAMD_report (stats) ;

    ok = CCOLAMD_MAIN (ncol, -1, alen, Ci, Cp, knobs, stats, Cmember) ;    NOT (ok) ;
    CCOLAMD_report (stats) ;

    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ; OK (ok) ;
    Cp [nrow] = -1 ;
    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs, stats, Cmember) ;  NOT (ok) ;
    CCOLAMD_report (stats) ;

    Cp [0] = 1 ;
    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs, stats, Cmember) ;  NOT (ok) ;
    CCOLAMD_report (stats) ;

    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ;   OK (ok) ;

    if (nrow > 0 && alen > 0 && Cp [1] > 0)
    {
	c = Cmember [0] ;
	Cmember [0] = -1 ;
	ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs, stats, Cmember) ;NOT(ok);
	CCOLAMD_report (stats) ;
	Cmember [0] = c ;

	p = Cp [1] ;
	Cp [1] = -1 ;
	ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs, stats, Cmember) ;NOT(ok);
	CCOLAMD_report (stats) ;
	Cp [1] = p ;

	i = Ci [0] ;
	Ci [0] = -1 ;
	ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs, stats, Cmember) ;NOT(ok);
	CCOLAMD_report (stats) ;
	Ci [0] = i ;
    }

    s = CCOLAMD_recommended (-1, 0, 0) ;
    OK (s == 0) ;

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

    CHOLMOD(free) (nrow+1, sizeof (Int), Front_npivcol, cm) ;
    CHOLMOD(free) (nrow+1, sizeof (Int), Front_nrows, cm) ;
    CHOLMOD(free) (nrow+1, sizeof (Int), Front_ncols, cm) ;
    CHOLMOD(free) (nrow+1, sizeof (Int), Front_parent, cm) ;
    CHOLMOD(free) (nrow+1, sizeof (Int), Front_cols, cm) ;
    CHOLMOD(free) (nrow+1, sizeof (Int), P, cm) ;
    CHOLMOD(free) (nrow, sizeof (Int), Cmember, cm) ;
    CHOLMOD(free) (ncol, sizeof (Int), InFront, cm) ;

    CHOLMOD(free_sparse) (&S, cm) ;
    CHOLMOD(free_sparse) (&A2, cm) ;
    CHOLMOD(free_sparse) (&C, cm) ;
    cm->print = 1 ;
}
示例#3
0
int CHOLMOD(row_lsubtree)
(
    /* ---- input ---- */
    cholmod_sparse *A,	/* matrix to analyze */
    Int *Fi, size_t fnz,    /* nonzero pattern of kth row of A', not required
			     * for the symmetric case.  Need not be sorted. */
    size_t krow,	/* row k of L */
    cholmod_factor *L,	/* the factor L from which parent(i) is derived */
    /* ---- output --- */
    cholmod_sparse *R,	/* pattern of L(k,:), 1-by-n with R->nzmax >= n */
    /* --------------- */
    cholmod_common *Common
)
{
    Int *Rp, *Stack, *Flag, *Ap, *Ai, *Anz, *Lp, *Li, *Lnz ;
    Int p, pend, parent, t, stype, nrow, k, pf, packed, sorted, top, len, i,
	mark ;

    /* ---------------------------------------------------------------------- */
    /* check inputs */
    /* ---------------------------------------------------------------------- */

    RETURN_IF_NULL_COMMON (FALSE) ;
    RETURN_IF_NULL (A, FALSE) ;
    RETURN_IF_NULL (R, FALSE) ;
    RETURN_IF_NULL (L, FALSE) ;
    RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ;
    RETURN_IF_XTYPE_INVALID (R, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ;
    RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ;
    stype = A->stype ;
    if (stype == 0)
    {
	RETURN_IF_NULL (Fi, FALSE) ;
    }
    if (krow >= A->nrow)
    {
	ERROR (CHOLMOD_INVALID, "lsubtree: k invalid") ;
	return (FALSE) ;
    }
    if (R->ncol != 1 || A->nrow != R->nrow || A->nrow > R->nzmax)
    {
	ERROR (CHOLMOD_INVALID, "lsubtree: R invalid") ;
	return (FALSE) ;
    }
    if (L->is_super)
    {
	ERROR (CHOLMOD_INVALID, "lsubtree: L invalid (cannot be supernodal)") ;
	return (FALSE) ;
    }
    Common->status = CHOLMOD_OK ;

    /* ---------------------------------------------------------------------- */
    /* allocate workspace */
    /* ---------------------------------------------------------------------- */

    nrow = A->nrow ;
    CHOLMOD(allocate_work) (nrow, 0, 0, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	return (FALSE) ;
    }
    ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, Common)) ;

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

    if (stype < 0)
    {
	/* symmetric lower triangular form not supported */
	ERROR (CHOLMOD_INVALID, "symmetric lower not supported") ;
	return (FALSE) ;
    }

    Ap = A->p ;
    Ai = A->i ;
    Anz = A->nz ;
    packed = A->packed ;
    sorted = A->sorted ;

    k = krow ;
    Stack = R->i ;

    Lp = L->p ;
    Li = L->i ;
    Lnz = L->nz ;

    /* ---------------------------------------------------------------------- */
    /* get workspace */
    /* ---------------------------------------------------------------------- */

    Flag = Common->Flag ;	/* size nrow, Flag [i] < mark must hold */
    mark = CHOLMOD(clear_flag) (Common) ;

    /* ---------------------------------------------------------------------- */
    /* compute the pattern of L(k,:) */
    /* ---------------------------------------------------------------------- */

    top = nrow ;		/* Stack is empty */
    Flag [k] = mark ;		/* do not include diagonal entry in Stack */

#define SCATTER			/* do not scatter numerical values */
#define PARENT(i) (Lnz [i] > 1) ? (Li [Lp [i] + 1]) : EMPTY

    if (stype != 0)
    {
	/* scatter kth col of triu (A), get pattern L(k,:) */
	p = Ap [k] ;
	pend = (packed) ? (Ap [k+1]) : (p + Anz [k]) ;
	SUBTREE ;
    }
    else
    {
	/* scatter kth col of triu (beta*I+AA'), get pattern L(k,:) */
	for (pf = 0 ; pf < (Int) fnz ; pf++)
	{
	    /* get nonzero entry F (t,k) */
	    t = Fi [pf] ;
	    p = Ap [t] ;
	    pend = (packed) ? (Ap [t+1]) : (p + Anz [t]) ;
	    SUBTREE ;
	}
    }

#undef SCATTER
#undef PARENT

    /* shift the stack upwards, to the first part of R */
    len = nrow - top ;
    for (i = 0 ; i < len ; i++)
    {
	Stack [i] = Stack [top + i] ;
    }

    Rp = R->p ;
    Rp [0] = 0 ;
    Rp [1] = len ;
    R->sorted = FALSE ;

    CHOLMOD(clear_flag) (Common) ;
    ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, Common)) ;
    return (TRUE) ;
}
int CHOLMOD(super_numeric)
(
    /* ---- input ---- */
    cholmod_sparse *A,	/* matrix to factorize */
    cholmod_sparse *F,	/* F = A' or A(:,f)' */
    double beta [2],	/* beta*I is added to diagonal of matrix to factorize */
    /* ---- in/out --- */
    cholmod_factor *L,	/* factorization */
    /* --------------- */
    cholmod_common *Common
)
{
    cholmod_dense *C ;
    Int *Super, *Map, *SuperMap ;
    size_t maxcsize ;
    Int nsuper, n, i, k, s, stype, nrow ;
    int ok = TRUE, symbolic ;
    size_t t, w ;

    /* ---------------------------------------------------------------------- */
    /* check inputs */
    /* ---------------------------------------------------------------------- */

    RETURN_IF_NULL_COMMON (FALSE) ;
    RETURN_IF_NULL (L, FALSE) ;
    RETURN_IF_NULL (A, FALSE) ;
    RETURN_IF_XTYPE_INVALID (A, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ;
    RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_COMPLEX, FALSE) ;
    stype = A->stype ;
    if (stype < 0)
    {
	if (A->nrow != A->ncol || A->nrow != L->n)
	{
	    ERROR (CHOLMOD_INVALID, "invalid dimensions") ;
	    return (FALSE) ;
	}
    }
    else if (stype == 0)
    {
	if (A->nrow != L->n)
	{
	    ERROR (CHOLMOD_INVALID, "invalid dimensions") ;
	    return (FALSE) ;
	}
	RETURN_IF_NULL (F, FALSE) ;
	RETURN_IF_XTYPE_INVALID (F, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ;
	if (A->nrow != F->ncol || A->ncol != F->nrow || F->stype != 0)
	{
	    ERROR (CHOLMOD_INVALID, "F invalid") ;
	    return (FALSE) ;
	}
	if (A->xtype != F->xtype)
	{
	    ERROR (CHOLMOD_INVALID, "A and F must have same xtype") ;
	    return (FALSE) ;
	}
    }
    else
    {
	/* symmetric upper case not suppored */
	ERROR (CHOLMOD_INVALID, "symmetric upper case not supported") ;
	return (FALSE) ;
    }
    if (!(L->is_super))
    {
	ERROR (CHOLMOD_INVALID, "L not supernodal") ;
	return (FALSE) ;
    }
    if (L->xtype != CHOLMOD_PATTERN)
    {
	if (! ((A->xtype == CHOLMOD_REAL    && L->xtype == CHOLMOD_REAL)
	    || (A->xtype == CHOLMOD_COMPLEX && L->xtype == CHOLMOD_COMPLEX)
	    || (A->xtype == CHOLMOD_ZOMPLEX && L->xtype == CHOLMOD_COMPLEX)))
	{
	    ERROR (CHOLMOD_INVALID, "complex type mismatch") ;
	    return (FALSE) ;
	}
    }
    Common->status = CHOLMOD_OK ;

    /* ---------------------------------------------------------------------- */
    /* allocate workspace in Common */
    /* ---------------------------------------------------------------------- */

    nsuper = L->nsuper ;
    maxcsize = L->maxcsize ;
    nrow = A->nrow ;
    n = nrow ;

    PRINT1 (("nsuper "ID" maxcsize %g\n", nsuper, (double) maxcsize)) ;
    ASSERT (nsuper >= 0 && maxcsize > 0) ;

    /* w = 2*n + 4*nsuper */
    w = CHOLMOD(mult_size_t) (n, 2, &ok) ;
    t = CHOLMOD(mult_size_t) (nsuper, 4, &ok) ;
    w = CHOLMOD(add_size_t) (w, t, &ok) ;
    if (!ok)
    {
	ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
	return (FALSE) ;
    }

    CHOLMOD(allocate_work) (n, w, 0, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	return (FALSE) ;
    }
    ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, Common)) ;

    /* ---------------------------------------------------------------------- */
    /* get the current factor L and allocate numerical part, if needed */
    /* ---------------------------------------------------------------------- */

    Super = L->super ;
    symbolic = (L->xtype == CHOLMOD_PATTERN) ;
    if (symbolic)
    {
	/* convert to supernodal numeric by allocating L->x */
	CHOLMOD(change_factor) (
		(A->xtype == CHOLMOD_REAL) ? CHOLMOD_REAL : CHOLMOD_COMPLEX,
		TRUE, TRUE, TRUE, TRUE, L, Common) ;
	if (Common->status < CHOLMOD_OK)
	{
	    /* the factor L remains in symbolic supernodal form */
	    return (FALSE) ;
	}
    }
    ASSERT (L->dtype == DTYPE) ;
    ASSERT (L->xtype == CHOLMOD_REAL || L->xtype == CHOLMOD_COMPLEX) ;

    /* supernodal LDL' is not supported */
    L->is_ll = TRUE ;

    /* ---------------------------------------------------------------------- */
    /* get more workspace */
    /* ---------------------------------------------------------------------- */

    C = CHOLMOD(allocate_dense) (maxcsize, 1, maxcsize, L->xtype, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	int status = Common->status ;
	if (symbolic)
	{
	    /* Change L back to symbolic, since the numeric values are not
	     * initialized.  This cannot fail. */
	    CHOLMOD(change_factor) (CHOLMOD_PATTERN, TRUE, TRUE, TRUE, TRUE,
		    L, Common) ;
	}
	/* the factor L is now back to the form it had on input */
	Common->status = status ;
	return (FALSE) ;
    }

    /* ---------------------------------------------------------------------- */
    /* get workspace */
    /* ---------------------------------------------------------------------- */

    SuperMap = Common->Iwork ;		/* size n (i/i/l) */
    Map = Common->Flag ;    /* size n, use Flag as workspace for Map array */
    for (i = 0 ; i < n ; i++)
    {
	Map [i] = EMPTY ;
    }

    /* ---------------------------------------------------------------------- */
    /* find the mapping of nodes to relaxed supernodes */
    /* ---------------------------------------------------------------------- */

    /* SuperMap [k] = s if column k is contained in supernode s */
    for (s = 0 ; s < nsuper ; s++)
    {
	PRINT1 (("Super ["ID"] "ID" ncols "ID"\n",
		    s, Super[s], Super[s+1]-Super[s]));
	for (k = Super [s] ; k < Super [s+1] ; k++)
	{
	    SuperMap [k] = s ;
	    PRINT2 (("relaxed SuperMap ["ID"] = "ID"\n", k, SuperMap [k])) ;
	}
    }

    /* ---------------------------------------------------------------------- */
    /* supernodal numerical factorization, using template routine */
    /* ---------------------------------------------------------------------- */

    switch (A->xtype)
    {
	case CHOLMOD_REAL:
	    ok = r_cholmod_super_numeric (A, F, beta, L, C, Common) ;
	    break ;

	case CHOLMOD_COMPLEX:
	    ok = c_cholmod_super_numeric (A, F, beta, L, C, Common) ;
	    break ;

	case CHOLMOD_ZOMPLEX:
	    /* This operates on complex L, not zomplex */
	    ok = z_cholmod_super_numeric (A, F, beta, L, C, Common) ;
	    break ;
    }

    /* ---------------------------------------------------------------------- */
    /* clear Common workspace, free temp workspace C, and return */
    /* ---------------------------------------------------------------------- */

    /* Flag array was used as workspace, clear it */
    Common->mark = EMPTY ;
    /* CHOLMOD(clear_flag) (Common) ; */
    CHOLMOD_CLEAR_FLAG (Common) ;
    ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, Common)) ;
    CHOLMOD(free_dense) (&C, Common) ;
    return (ok) ;
}
示例#5
0
cholmod_sparse *CHOLMOD(copy_sparse)
(
    /* ---- input ---- */
    cholmod_sparse *A,	/* matrix to copy */
    /* --------------- */
    cholmod_common *Common
)
{
    double *Ax, *Cx, *Az, *Cz ;
    Int *Ap, *Ai, *Anz, *Cp, *Ci, *Cnz ;
    cholmod_sparse *C ;
    Int p, pend, j, ncol, packed, nzmax, nz, xtype ;

    /* ---------------------------------------------------------------------- */
    /* check inputs */
    /* ---------------------------------------------------------------------- */

    RETURN_IF_NULL_COMMON (NULL) ;
    RETURN_IF_NULL (A, NULL) ;
    RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, NULL) ;
    if (A->stype != 0 && A->nrow != A->ncol)
    {
	ERROR (CHOLMOD_INVALID, "rectangular matrix with stype != 0 invalid") ;
	return (NULL) ;
    }
    Common->status = CHOLMOD_OK ;
    ASSERT (CHOLMOD(dump_sparse) (A, "A original", Common) >= 0) ;

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

    ncol = A->ncol ;
    nzmax = A->nzmax ;
    packed = A->packed ;
    Ap = A->p ;
    Ai = A->i ;
    Ax = A->x ;
    Az = A->z ;
    Anz = A->nz ;
    xtype = A->xtype ;

    /* ---------------------------------------------------------------------- */
    /* allocate the copy */
    /* ---------------------------------------------------------------------- */

    C = CHOLMOD(allocate_sparse) (A->nrow, A->ncol, A->nzmax, A->sorted,
	    A->packed, A->stype, A->xtype, Common) ;

    if (Common->status < CHOLMOD_OK)
    {
	return (NULL) ;	    /* out of memory */
    }

    Cp = C->p ;
    Ci = C->i ;
    Cx = C->x ;
    Cz = C->z ;
    Cnz = C->nz ;

    /* ---------------------------------------------------------------------- */
    /* copy the matrix */
    /* ---------------------------------------------------------------------- */

    for (j = 0 ; j <= ncol ; j++)
    {
	Cp [j] = Ap [j] ;
    }

    if (packed)
    {
	nz = Ap [ncol] ;
	for (p = 0 ; p < nz ; p++)
	{
	    Ci [p] = Ai [p] ;
	}

	switch (xtype)
	{
	    case CHOLMOD_REAL:
		for (p = 0 ; p < nz ; p++)
		{
		    Cx [p] = Ax [p] ;
		}
		break ;

	    case CHOLMOD_COMPLEX:
		for (p = 0 ; p < 2*nz ; p++)
		{
		    Cx [p] = Ax [p] ;
		}
		break ;

	    case CHOLMOD_ZOMPLEX:
		for (p = 0 ; p < nz ; p++)
		{
		    Cx [p] = Ax [p] ;
		    Cz [p] = Az [p] ;
		}
		break ;
	}

    }
    else
    {

	for (j = 0 ; j < ncol ; j++)
	{
	    Cnz [j] = Anz [j] ;
	}

	switch (xtype)
	{
	    case CHOLMOD_PATTERN:
		for (j = 0 ; j < ncol ; j++)
		{
		    p = Ap [j] ;
		    pend = p + Anz [j] ;
		    for ( ; p < pend ; p++)
		    {
			Ci [p] = Ai [p] ;
		    }
		}
		break ;

	    case CHOLMOD_REAL:
		for (j = 0 ; j < ncol ; j++)
		{
		    p = Ap [j] ;
		    pend = p + Anz [j] ;
		    for ( ; p < pend ; p++)
		    {
			Ci [p] = Ai [p] ;
			Cx [p] = Ax [p] ;
		    }
		}
		break ;

	    case CHOLMOD_COMPLEX:
		for (j = 0 ; j < ncol ; j++)
		{
		    p = Ap [j] ;
		    pend = p + Anz [j] ;
		    for ( ; p < pend ; p++)
		    {
			Ci [p] = Ai [p] ;
			Cx [2*p  ] = Ax [2*p  ] ;
			Cx [2*p+1] = Ax [2*p+1] ;
		    }
		}
		break ;

	    case CHOLMOD_ZOMPLEX:
		for (j = 0 ; j < ncol ; j++)
		{
		    p = Ap [j] ;
		    pend = p + Anz [j] ;
		    for ( ; p < pend ; p++)
		    {
			Ci [p] = Ai [p] ;
			Cx [p] = Ax [p] ;
			Cz [p] = Az [p] ;
		    }
		}
		break ;
	}
    }

    /* ---------------------------------------------------------------------- */
    /* return the result */
    /* ---------------------------------------------------------------------- */

    ASSERT (CHOLMOD(dump_sparse) (C, "C copy", Common) >= 0) ;
    return (C) ;
}
示例#6
0
cholmod_triplet *CHOLMOD(read_triplet)
(
    /* ---- input ---- */
    FILE *f,		/* file to read from, assumed to already be open */
    /* --------------- */
    cholmod_common *Common
)
{
    double x, z ;
    double *Tx ;
    Int *Ti, *Tj, *Rdeg, *Cdeg ;
    cholmod_triplet *T ;
    long l1, l2 ;
    Int nitems, nrow, ncol, nnz, stype, xtype, unknown, k, nshould, is_lower,
	is_upper, one_based, i, j, imax, jmax, ignore, skew_symmetric,
	extra, p ;

    /* ---------------------------------------------------------------------- */
    /* check inputs */
    /* ---------------------------------------------------------------------- */

    RETURN_IF_NULL_COMMON (NULL) ;
    RETURN_IF_NULL (f, NULL) ;
    Common->status = CHOLMOD_OK ;

    /* ---------------------------------------------------------------------- */
    /* read the header line */
    /* ---------------------------------------------------------------------- */

    stype = 999 ;
    nitems = get_line (f, &l1, &l2, &x, &z, &stype) ;
    nrow = l1 ;
    ncol = l2 ;
    nnz = x ;
    if (nrow != ncol)
    {
	stype = 0 ;
    }
    else if (nitems == 4)
    {
	/* first line contains: m n nnz stype */
	if (z < 0)
	{
	    stype = -1 ;
	}
	else if (z > 0)
	{
	    stype = 1 ;
	}
	else
	{
	    stype = 0 ;
	}
    }
    unknown = (stype == 999) ;

    if (nnz < 0 || nrow < 0 || ncol < 0 || nitems < 3)
    {
	/* invalid matrix */
	ERROR (CHOLMOD_INVALID, "invalid format") ;
	return (NULL) ;
    }

    if (nrow == 0 || ncol == 0 || nnz == 0)
    {
	/* return an empty matrix */
	return (CHOLMOD(allocate_triplet) (nrow, ncol, 0, 0, CHOLMOD_REAL,
		    Common)) ;
    }

    skew_symmetric = (stype == -2) ;
    extra = 0 ;
    if (stype < -1)
    {
	/* -2:  real or complex skew symmetric converted to unsymmetric */
	/* -3:  complex symmetric converted to unsymmetric */
	stype = 0 ;
	extra = nnz ;
    }

    /* ---------------------------------------------------------------------- */
    /* allocate workspace */
    /* ---------------------------------------------------------------------- */

    CHOLMOD(allocate_work) (0, nrow + ncol, 0, Common) ;
    Rdeg = Common->Iwork ;	/* size nrow */
    Cdeg = Rdeg + nrow ;	/* size ncol */

    /* ---------------------------------------------------------------------- */
    /* read the nonzero entries */
    /* ---------------------------------------------------------------------- */

    is_lower = TRUE ;
    is_upper = TRUE ;
    one_based = TRUE ;
    imax = 0 ;
    jmax = 0 ;

    Tx = NULL ;
    Ti = NULL ;
    Tj = NULL ;
    xtype = 999 ;
    nshould = 0 ;

    for (k = 0 ; k < nnz ; k++)
    {
	nitems = get_line (f, &l1, &l2, &x, &z, &ignore) ;

	i = l1 ;
	j = l2 ;

	/* ------------------------------------------------------------------ */
	/* for first entry: determine type and allocate triplet matrix */
	/* ------------------------------------------------------------------ */

	if (k == 0)
	{

	    if (nitems < 2 || nitems > 4)
	    {
		/* invalid matrix */
		ERROR (CHOLMOD_INVALID, "invalid format") ;
		return (NULL) ;
	    }
	    else if (nitems == 2)
	    {
		/* this will be converted into a real matrix later */
		xtype = CHOLMOD_PATTERN ;
	    }
	    else if (nitems == 3)
	    {
		xtype = CHOLMOD_REAL ;
	    }
	    else if (nitems == 4)
	    {
		xtype = CHOLMOD_COMPLEX ;
	    }

	    /* the rest of the lines should have the same number of entries */
	    nshould = nitems ;

	    T = CHOLMOD(allocate_triplet) (nrow, ncol, nnz+extra, stype,
		    (xtype == CHOLMOD_PATTERN ? CHOLMOD_REAL : xtype), Common) ;
	    if (Common->status < CHOLMOD_OK)
	    {
		/* out of memory */
		return (NULL) ;
	    }
	    Ti = T->i ;
	    Tj = T->j ;
	    Tx = T->x ;
	    T->nnz = nnz ;
	}

	/* ------------------------------------------------------------------ */
	/* save the entry in the triplet matrix */
	/* ------------------------------------------------------------------ */

	if (nitems != nshould || i < 0 || j < 0)
	{
	    /* wrong format, premature end-of-file, or negative indices */
	    CHOLMOD(free_triplet) (&T, Common) ;
	    ERROR (CHOLMOD_INVALID, "invalid matrix file") ;
	    return (NULL) ;
	}

	Ti [k] = i ;
	Tj [k] = j ;

	if (i < j)
	{
	    /* this entry is in the upper triangular part */
	    is_lower = FALSE ;
	}
	if (i > j)
	{
	    /* this entry is in the lower triangular part */
	    is_upper = FALSE ;
	}

	if (xtype == CHOLMOD_REAL)
	{
	    Tx [k] = x ;
	}
	else if (xtype == CHOLMOD_COMPLEX)
	{
	    Tx [2*k  ] = x ;	/* real part */
	    Tx [2*k+1] = z ;	/* imaginary part */
	}

	if (i == 0 || j == 0)
	{
	    one_based = FALSE ;
	}

	imax = MAX (i, imax) ;
	jmax = MAX (j, jmax) ;
    }

    /* ---------------------------------------------------------------------- */
    /* convert to zero-based */
    /* ---------------------------------------------------------------------- */

    if (one_based)
    {
	/* input matrix is one-based; convert matrix to zero-based */
	for (k = 0 ; k < nnz ; k++)
	{
	    Ti [k]-- ;
	    Tj [k]-- ;
	}
    }

    if (one_based ? (imax > nrow || jmax > ncol):(imax >= nrow || jmax >= ncol))
    {
	/* indices out of range */
	CHOLMOD(free_triplet) (&T, Common) ;
	ERROR (CHOLMOD_INVALID, "indices out of range") ;
	return (NULL) ;
    }

    /* ---------------------------------------------------------------------- */
    /* add the remainder of skew-symmetric or complex symmetric matrices */
    /* ---------------------------------------------------------------------- */

    if (extra > 0)
    {
	p = nnz ;
	for (k = 0 ; k < nnz ; k++)
	{
	    i = Ti [k] ;
	    j = Tj [k] ;
	    if (i != j)
	    {
		Ti [p] = j ;
		Tj [p] = i ;
		if (xtype == CHOLMOD_REAL)
		{
		    Tx [p] = skew_symmetric ? (-Tx [k]) : (Tx [k]) ;
		}
		else if (xtype == CHOLMOD_COMPLEX)
		{
		    Tx [2*p  ] = skew_symmetric ? (-Tx [2*k  ]) : (Tx [2*k  ]);
		    Tx [2*p+1] = skew_symmetric ? (-Tx [2*k+1]) : (Tx [2*k+1]);
		}
		p++ ;
	    }
	}
	T->nnz = p ;
	nnz = p ;
    }

    /* ---------------------------------------------------------------------- */
    /* determine the stype, if not yet known */
    /* ---------------------------------------------------------------------- */

    if (unknown)
    {
	if (is_lower && is_upper)
	{
	    /* diagonal matrix, symmetric with upper part present */
	    stype = 1 ;
	}
	else if (is_lower && !is_upper)
	{
	    /* symmetric, lower triangular part present */
	    stype = -1 ;
	}
	else if (!is_lower && is_upper)
	{
	    /* symmetric, upper triangular part present */
	    stype = 1 ;
	}
	else
	{
	    /* unsymmetric */
	    stype = 0 ;
	}
    }
    T->stype = stype ;

    /* ---------------------------------------------------------------------- */
    /* create values for a pattern-only matrix */
    /* ---------------------------------------------------------------------- */

    if (xtype == CHOLMOD_PATTERN)
    {
	if (stype == 0)
	{
	    /* unsymmetric case */
	    for (k = 0 ; k < nnz ; k++)
	    {
		Tx [k] = 1 ;
	    }
	}
	else
	{
	    /* compute the row and columm degrees (excluding the diagonal) */
	    for (i = 0 ; i < nrow ; i++)
	    {
		Rdeg [i] = 0 ;
	    }
	    for (j = 0 ; j < ncol ; j++)
	    {
		Cdeg [j] = 0 ;
	    }
	    for (k = 0 ; k < nnz ; k++)
	    {
		i = Ti [k] ;
		j = Tj [k] ;
		if ((stype < 0 && i > j) || (stype > 0 && i < j))
		{
		    /* both a(i,j) and a(j,i) appear in the matrix */
		    Rdeg [i]++ ;
		    Cdeg [j]++ ;
		    Rdeg [j]++ ;
		    Cdeg [i]++ ;
		}
	    }
	    /* assign the numerical values */
	    for (k = 0 ; k < nnz ; k++)
	    {
		i = Ti [k] ;
		j = Tj [k] ;
		Tx [k] = (i == j) ? (1 + MAX (Rdeg [i], Cdeg [j])) : (-1) ;
	    }
	}
    }
    return (T) ;
}
示例#7
0
int CHOLMOD(ccolamd)
(
    /* ---- input ---- */
    cholmod_sparse *A,	/* matrix to order */
    Int *fset,		/* subset of 0:(A->ncol)-1 */
    size_t fsize,	/* size of fset */
    Int *Cmember,	/* size A->nrow.  Cmember [i] = c if row i is in the
			 * constraint set c.  c must be >= 0.  The # of
			 * constraint sets is max (Cmember) + 1.  If Cmember is
			 * NULL, then it is interpretted as Cmember [i] = 0 for
			 * all i */
    /* ---- output --- */
    Int *Perm,		/* size A->nrow, output permutation */
    /* --------------- */
    cholmod_common *Common
)
{
    cholmod_sparse *C ;
    Int ok, nrow, ncol ;
    size_t alen ;

    /* ---------------------------------------------------------------------- */
    /* 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 */
    /* ---------------------------------------------------------------------- */

#ifdef LONG
    alen = ccolamd_l_recommended (A->nzmax, ncol, nrow) ;
#else
    alen = ccolamd_recommended (A->nzmax, ncol, nrow) ;
#endif

    if (alen == 0)
    {
	ERROR (CHOLMOD_TOO_LARGE, "matrix invalid or too large") ;
	return (FALSE) ;
    }

    CHOLMOD(allocate_work) (0, MAX (nrow,ncol), 0, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	return (FALSE) ;
    }

    C = CHOLMOD(allocate_sparse) (ncol, nrow, alen, TRUE, TRUE, 0,
	    CHOLMOD_PATTERN, Common) ;

    /* ---------------------------------------------------------------------- */
    /* order with ccolamd */
    /* ---------------------------------------------------------------------- */

    ok = ccolamd_interface (A, alen, Perm, Cmember, fset, fsize, C, Common) ;

    /* ---------------------------------------------------------------------- */
    /* free the workspace and return result */
    /* ---------------------------------------------------------------------- */

    CHOLMOD(free_sparse) (&C, Common) ;
    return (ok) ;
}
示例#8
0
cholmod_sparse *CHOLMOD(copy)
(
    /* ---- input ---- */
    cholmod_sparse *A,	/* matrix to copy */
    int stype,		/* requested stype of C */
    int mode,		/* >0: numerical, 0: pattern, <0: pattern (no diag) */
    /* --------------- */
    cholmod_common *Common
)
{
    cholmod_sparse *C ;
    Int nrow, ncol, up, lo, values, diag, astype ;

    /* ---------------------------------------------------------------------- */
    /* check inputs */
    /* ---------------------------------------------------------------------- */

    RETURN_IF_NULL_COMMON (NULL) ;
    RETURN_IF_NULL (A, NULL) ;
    values = (mode > 0) && (A->xtype != CHOLMOD_PATTERN) ;
    RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN,
	    values ? CHOLMOD_REAL : CHOLMOD_ZOMPLEX, NULL) ;
    nrow = A->nrow ;
    ncol = A->ncol ;
    if ((stype || A->stype) && nrow != ncol)
    {
	/* inputs invalid */
	ERROR (CHOLMOD_INVALID, "matrix invalid") ;
	return (NULL) ;
    }
    Common->status = CHOLMOD_OK ;

    /* ---------------------------------------------------------------------- */
    /* allocate workspace */
    /* ---------------------------------------------------------------------- */

    CHOLMOD(allocate_work) (0, MAX (nrow,ncol), 0, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	/* out of memory */
	return (NULL) ;
    }

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

    diag = (mode >= 0) ;
    astype = SIGN (A->stype) ;
    stype = SIGN (stype) ;
    up = (astype > 0) ;
    lo = (astype < 0) ;

    /* ---------------------------------------------------------------------- */
    /* copy the matrix */
    /* ---------------------------------------------------------------------- */

    if (astype == stype)
    {

	/* ------------------------------------------------------------------ */
	/* symmetry of A and C are the same */
	/* ------------------------------------------------------------------ */

	/* copy A into C, keeping the same symmetry.  If A is symmetric
	 * entries in the ignored part of A are not copied into C */
	C = CHOLMOD(band) (A, -nrow, ncol, mode, Common) ;

    }
    else if (!astype)
    {

	/* ------------------------------------------------------------------ */
	/* convert unsymmetric matrix A into a symmetric matrix C */
	/* ------------------------------------------------------------------ */

	if (stype > 0)
	{
	    /* C = triu (A) */
	    C = CHOLMOD(band) (A, 0, ncol, mode, Common) ;
	}
	else
	{
	    /* C = tril (A) */
	    C = CHOLMOD(band) (A, -nrow, 0, mode, Common) ;
	}
	if (Common->status < CHOLMOD_OK)
	{
	    /* out of memory */
	    return (NULL) ;
	}
	C->stype = stype ;

    }
    else if (astype == -stype)
    {

	/* ------------------------------------------------------------------ */
	/* transpose a symmetric matrix */
	/* ------------------------------------------------------------------ */

	/* converting upper to lower or lower to upper */
	/* workspace: Iwork (nrow) */
	C = CHOLMOD(transpose) (A, values, Common) ;
	if (!diag)
	{
	    /* remove diagonal, if requested */
	    CHOLMOD(band_inplace) (-nrow, ncol, -1, C, Common) ;
	}

    }
    else
    {

	/* ------------------------------------------------------------------ */
	/* create an unsymmetric copy of a symmetric matrix */
	/* ------------------------------------------------------------------ */

	C = copy_sym_to_unsym (A, mode, Common) ;
    }

    /* ---------------------------------------------------------------------- */
    /* return if error */
    /* ---------------------------------------------------------------------- */

    if (Common->status < CHOLMOD_OK)
    {
	/* out of memory */
	return (NULL) ;
    }

    /* ---------------------------------------------------------------------- */
    /* return the result */
    /* ---------------------------------------------------------------------- */

    DEBUG (diag = CHOLMOD(dump_sparse) (C, "copy", Common)) ;
    PRINT1 (("mode %d nnzdiag "ID"\n", mode, diag)) ;
    ASSERT (IMPLIES (mode < 0, diag == 0)) ;
    return (C) ;
}
示例#9
0
static cholmod_sparse *copy_sym_to_unsym
(
    /* ---- input ---- */
    cholmod_sparse *A,	/* matrix to copy */
    int mode,		/* >0: numerical, 0: pattern, <0: pattern (no diag)
			 * -2: pattern only, no diagonal, add 50% + n extra
			 * space to C */
    /* --------------- */
    cholmod_common *Common
)
{
    double aij ;
    double *Ax, *Cx ;
    Int *Ap, *Ai, *Anz, *Cp, *Ci, *Wj, *Iwork ;
    cholmod_sparse *C ;
    Int nrow, ncol, nz, packed, j, p, pend, i, pc, up, lo, values, diag,
	astype, extra ;

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

    nrow = A->nrow ;
    ncol = A->ncol ;
    Ap  = A->p ;
    Anz = A->nz ;
    Ai  = A->i ;
    Ax  = A->x ;
    packed = A->packed ;
    values = (mode > 0) && (A->xtype != CHOLMOD_PATTERN) ;
    diag = (mode >= 0) ;

    astype = SIGN (A->stype) ;
    up = (astype > 0) ;
    lo = (astype < 0) ;
    ASSERT (astype != 0) ;

    /* ---------------------------------------------------------------------- */
    /* create an unsymmetric copy of a symmetric matrix */
    /* ---------------------------------------------------------------------- */

    Iwork = Common->Iwork ;
    Wj = Iwork ;		    /* size ncol (i/i/l) */

    /* In MATLAB notation, for converting a symmetric/upper matrix:
     *	U = triu (A) ;
     *	L = tril (U',-1) ;
     *	C = L + U ;
     *
     * For converting a symmetric/lower matrix to unsymmetric:
     *	L = tril (A) ;
     *	U = triu (L',1) ;
     *	C = L + U ;
     */
    ASSERT (up || lo) ;
    PRINT1 (("copy: convert symmetric to unsym\n")) ;

    /* count the number of entries in each column of C */
    for (j = 0 ; j < ncol ; j++)
    {
	Wj [j] = 0 ;
    }
    for (j = 0 ; j < ncol ; j++)
    {
	p = Ap [j] ;
	pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
	for ( ; p < pend ; p++)
	{
	    i = Ai [p] ;
	    if (i == j)
	    {
		/* the diagonal entry A(i,i) will appear just once
		 * (unless it is excluded with mode < 0) */
		if (diag)
		{
		    Wj [j]++ ;
		}
	    }
	    else if ((up && i < j) || (lo && i > j))
	    {
		/* upper case:  A(i,j) is in the strictly upper part;
		 * A(j,i) will be added to the strictly lower part of C.
		 * lower case is the opposite. */
		Wj [j]++ ;
		Wj [i]++ ;
	    }
	}
    }
    nz = 0 ;
    for (j = 0 ; j < ncol ; j++)
    {
	nz += Wj [j] ;
    }

    extra = (mode == -2) ? (nz/2 + ncol) : 0 ;

    /* allocate C.  C is sorted if and only if A is sorted */
    C = CHOLMOD(allocate_sparse) (nrow, ncol, nz + extra, A->sorted, TRUE, 0,
	    values ? A->xtype : CHOLMOD_PATTERN, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	return (NULL) ;
    }

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

    /* construct the column pointers for C */
    p = 0 ;
    for (j = 0 ; j < ncol ; j++)
    {
	Cp [j] = p ;
	p += Wj [j] ;
    }
    Cp [ncol] = p ;
    for (j = 0 ; j < ncol ; j++)
    {
	Wj [j] = Cp [j] ;
    }

    /* construct C */
    if (values)
    {

	/* pattern and values */
	ASSERT (diag) ;
	for (j = 0 ; j < ncol ; j++)
	{
	    p = Ap [j] ;
	    pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
	    for ( ; p < pend ; p++)
	    {
		i = Ai [p] ;
		aij = Ax [p] ;
		if (i == j)
		{
		    /* add diagonal entry A(i,i) to column i */
		    pc = Wj [i]++ ;
		    Ci [pc] = i ;
		    Cx [pc] = aij ;
		}
		else if ((up && i < j) || (lo && i > j))
		{
		    /* add A(i,j) to column j */
		    pc = Wj [j]++ ;
		    Ci [pc] = i ;
		    Cx [pc] = aij ;
		    /* add A(j,i) to column i */
		    pc = Wj [i]++ ;
		    Ci [pc] = j ;
		    Cx [pc] = aij ;
		}
	    }
	}

    }
    else
    {

	/* pattern only, possibly excluding the diagonal */
	for (j = 0 ; j < ncol ; j++)
	{
	    p = Ap [j] ;
	    pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
	    for ( ; p < pend ; p++)
	    {
		i = Ai [p] ;
		if (i == j)
		{
		    /* add diagonal entry A(i,i) to column i
		     * (unless it is excluded with mode < 0) */
		    if (diag)
		    {
			Ci [Wj [i]++] = i ;
		    }
		}
		else if ((up && i < j) || (lo && i > j))
		{
		    /* add A(i,j) to column j */
		    Ci [Wj [j]++] = i ;
		    /* add A(j,i) to column i */
		    Ci [Wj [i]++] = j ;
		}
	    }
	}
    }

    /* ---------------------------------------------------------------------- */
    /* return the result */
    /* ---------------------------------------------------------------------- */

    DEBUG (i = CHOLMOD(dump_sparse) (C, "copy_sym_to_unsym", Common)) ;
    PRINT1 (("mode %d nnzdiag "ID"\n", mode, i)) ;
    ASSERT (IMPLIES (mode < 0, i == 0)) ;
    return (C) ;
}
void *CHOLMOD(realloc)	/* returns pointer to reallocated block */
(
    /* ---- input ---- */
    size_t nnew,	/* requested # of items in reallocated block */
    size_t size,	/* size of each item */
    /* ---- in/out --- */
    void *p,		/* block of memory to realloc */
    size_t *n,		/* current size on input, nnew on output if successful*/
    /* --------------- */
    cholmod_common *Common
)
{
    size_t nold = (*n) ;
    void *pnew ;
    size_t s ;
    int ok = TRUE ;

    RETURN_IF_NULL_COMMON (NULL) ;
    if (size == 0)
    {
	ERROR (CHOLMOD_INVALID, "sizeof(item) must be > 0") ;
	p = NULL ;
    }
    else if (p == NULL)
    {
	/* A fresh object is being allocated. */
	PRINT1 (("realloc fresh: %d %d\n", nnew, size)) ;
	p = CHOLMOD(malloc) (nnew, size, Common) ;
	*n = (p == NULL) ? 0 : nnew ;
    }
    else if (nold == nnew)
    {
	/* Nothing to do.  Do not change p or n. */
	PRINT1 (("realloc nothing: %d %d\n", nnew, size)) ;
    }
    else if (nnew >= (Size_max / size) || nnew >= Int_MAX)
    {
	/* failure: nnew is too big.  Do not change p or n. */
	ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
    }
    else
    {
	/* The object exists, and is changing to some other nonzero size. */
	/* call realloc, or its equivalent */
	PRINT1 (("realloc : %d to %d, %d\n", nold, nnew, size)) ;
	pnew = NULL ;

	s = CHOLMOD(mult_size_t) (MAX (1,nnew), size, &ok) ;
	pnew = ok ? ((Common->realloc_memory) (p, s)) : NULL ;

	if (pnew == NULL)
	{
	    /* Do not change p, since it still points to allocated memory */
	    if (nnew <= nold)
	    {
		/* The attempt to reduce the size of the block from n to
		 * nnew has failed.  The current block is not modified, so
		 * pretend to succeed, but do not change p.  Do change
		 * CHOLMOD's notion of the size of the block, however. */
		*n = nnew ;
		PRINTM (("nnew <= nold failed, pretend to succeed\n")) ;
		PRINTM (("cholmod_free %p %g cnt: %g inuse %g\n"
			 "cholmod_malloc %p %g cnt: %g inuse %g\n",
		    p, (double) nold*size, (double) Common->malloc_count-1,
		       (double) (Common->memory_inuse - nold*size),
		    p, (double) nnew*size, (double) Common->malloc_count,
		       (double) (Common->memory_inuse + (nnew-nold)*size))) ;
		Common->memory_inuse += ((nnew-nold) * size) ;
	    }
	    else
	    {
		/* Increasing the size of the block has failed.
		 * Do not change n. */
		ERROR (CHOLMOD_OUT_OF_MEMORY, "out of memory") ;
	    }
	}
	else
	{
	    /* success: return revised p and change the size of the block */
	    PRINTM (("cholmod_free %p %g cnt: %g inuse %g\n"
		     "cholmod_malloc %p %g cnt: %g inuse %g\n",
		p, (double) nold*size, (double) Common->malloc_count-1,
                   (double) (Common->memory_inuse - nold*size),
		pnew, (double) nnew*size, (double) Common->malloc_count,
                   (double) (Common->memory_inuse + (nnew-nold)*size))) ;
	    p = pnew ;
	    *n = nnew ;
	    Common->memory_inuse += ((nnew-nold) * size) ;
	}
	Common->memory_usage = MAX (Common->memory_usage, Common->memory_inuse);
    }

    return (p) ;
}
int CHOLMOD(realloc_multiple)
(
    /* ---- input ---- */
    size_t nnew,	/* requested # of items in reallocated blocks */
    int nint,		/* number of int/SuiteSparse_long blocks */
    int xtype,		/* CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX */
    /* ---- in/out --- */
    void **Iblock,	/* int or SuiteSparse_long block */
    void **Jblock,	/* int or SuiteSparse_long block */
    void **Xblock,	/* complex or double block */
    void **Zblock,	/* zomplex case only: double block */
    size_t *nold_p,	/* current size of the I,J,X,Z blocks on input,
			 * nnew on output if successful */
    /* --------------- */
    cholmod_common *Common
)
{
    double *xx, *zz ;
    size_t i, j, x, z, nold ;

    RETURN_IF_NULL_COMMON (FALSE) ;

    if (xtype < CHOLMOD_PATTERN || xtype > CHOLMOD_ZOMPLEX)
    {
	ERROR (CHOLMOD_INVALID, "invalid xtype") ;
	return (FALSE) ;
    }

    nold = *nold_p ;

    if (nint < 1 && xtype == CHOLMOD_PATTERN)
    {
	/* nothing to do */
	return (TRUE) ;
    }

    i = nold ;
    j = nold ;
    x = nold ;
    z = nold ;

    if (nint > 0)
    {
	*Iblock = CHOLMOD(realloc) (nnew, sizeof (Int), *Iblock, &i, Common) ;
    }
    if (nint > 1)
    {
	*Jblock = CHOLMOD(realloc) (nnew, sizeof (Int), *Jblock, &j, Common) ;
    }

    switch (xtype)
    {
	case CHOLMOD_REAL:
	    *Xblock = CHOLMOD(realloc) (nnew, sizeof (double), *Xblock, &x,
                    Common) ;
	    break ;

	case CHOLMOD_COMPLEX:
	    *Xblock = CHOLMOD(realloc) (nnew, 2*sizeof (double), *Xblock, &x,
                    Common) ;
	    break ;

	case CHOLMOD_ZOMPLEX:
	    *Xblock = CHOLMOD(realloc) (nnew, sizeof (double), *Xblock, &x,
                    Common) ;
	    *Zblock = CHOLMOD(realloc) (nnew, sizeof (double), *Zblock, &z,
                    Common) ;
	    break ;
    }

    if (Common->status < CHOLMOD_OK)
    {
	/* one or more realloc's failed.  Resize all back down to nold. */

	if (nold == 0)
	{

	    if (nint > 0)
	    {
		*Iblock = CHOLMOD(free) (i, sizeof (Int), *Iblock, Common) ;
	    }
	    if (nint > 1)
	    {
		*Jblock = CHOLMOD(free) (j, sizeof (Int), *Jblock, Common) ;
	    }

	    switch (xtype)
	    {
		case CHOLMOD_REAL:
		    *Xblock = CHOLMOD(free) (x, sizeof (double), *Xblock,
                            Common) ;
		    break ;

		case CHOLMOD_COMPLEX:
		    *Xblock = CHOLMOD(free) (x, 2*sizeof (double), *Xblock,
                            Common) ;
		    break ;

		case CHOLMOD_ZOMPLEX:
		    *Xblock = CHOLMOD(free) (x, sizeof (double), *Xblock,
                            Common) ;
		    *Zblock = CHOLMOD(free) (x, sizeof (double), *Zblock,
                            Common) ;
		    break ;
	    }

	}
	else
	{
	    if (nint > 0)
	    {
		*Iblock = CHOLMOD(realloc) (nold, sizeof (Int), *Iblock, &i,
                            Common) ;
	    }
	    if (nint > 1)
	    {
		*Jblock = CHOLMOD(realloc) (nold, sizeof (Int), *Jblock, &j,
                            Common) ;
	    }

	    switch (xtype)
	    {
		case CHOLMOD_REAL:
		    *Xblock = CHOLMOD(realloc) (nold, sizeof (double),
                            *Xblock, &x, Common) ;
		    break ;

		case CHOLMOD_COMPLEX:
		    *Xblock = CHOLMOD(realloc) (nold, 2*sizeof (double),
                            *Xblock, &x, Common) ;
		    break ;

		case CHOLMOD_ZOMPLEX:
		    *Xblock = CHOLMOD(realloc) (nold, sizeof (double),
                            *Xblock, &x, Common) ;
		    *Zblock = CHOLMOD(realloc) (nold, sizeof (double),
                            *Zblock, &z, Common) ;
		    break ;
	    }

	}

	return (FALSE) ;
    }

    if (nold == 0)
    {
	/* New space was allocated.  Clear the first entry so that valgrind
	 * doesn't complain about its access in change_complexity
	 * (Core/cholmod_complex.c). */
	xx = *Xblock ;
	zz = *Zblock ;
	switch (xtype)
	{
	    case CHOLMOD_REAL:
		xx [0] = 0 ;
		break ;

	    case CHOLMOD_COMPLEX:
		xx [0] = 0 ;
		xx [1] = 0 ;
		break ;

	    case CHOLMOD_ZOMPLEX:
		xx [0] = 0 ;
		zz [0] = 0 ;
		break ;
	}
    }

    /* all realloc's succeeded, change size to reflect realloc'ed size. */
    *nold_p = nnew ;
    return (TRUE) ;
}
示例#12
0
cholmod_factor *CHOLMOD(allocate_factor)
(
    /* ---- input ---- */
    size_t n,		/* L is n-by-n */
    /* --------------- */
    cholmod_common *Common
)
{
    Int j ;
    Int *Perm, *ColCount ;
    cholmod_factor *L ;
    int ok = TRUE ;

    RETURN_IF_NULL_COMMON (FALSE) ;
    Common->status = CHOLMOD_OK ;

    /* ensure the dimension does not cause integer overflow */
    (void) CHOLMOD(add_size_t) (n, 2, &ok) ;
    if (!ok || n > Int_max)
    {
	ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
	return (NULL) ;
    }

    L = CHOLMOD(malloc) (sizeof (cholmod_factor), 1, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	return (NULL) ;	    /* out of memory */
    }
    L->n = n ;
    L->is_ll = FALSE ;
    L->is_super = FALSE ;
    L->is_monotonic = TRUE ;
    L->itype = ITYPE ;
    L->xtype = CHOLMOD_PATTERN ;
    L->dtype = DTYPE ;

    /* allocate the purely symbolic part of L */
    L->ordering = CHOLMOD_NATURAL ;
    L->Perm = CHOLMOD(malloc) (n, sizeof (Int), Common) ;
    L->ColCount = CHOLMOD(malloc) (n, sizeof (Int), Common) ;

    /* simplicial part of L is empty */
    L->nzmax = 0 ;
    L->p = NULL ;
    L->i = NULL ;
    L->x = NULL ;
    L->z = NULL ;
    L->nz = NULL ;
    L->next = NULL ;
    L->prev = NULL ;

    /* supernodal part of L is also empty */
    L->nsuper = 0 ;
    L->ssize = 0 ;
    L->xsize = 0 ;
    L->maxesize = 0 ;
    L->maxcsize = 0 ;
    L->super = NULL ;
    L->pi = NULL ;
    L->px = NULL ;
    L->s = NULL ;

    /* L has not been factorized */
    L->minor = n ;

    if (Common->status < CHOLMOD_OK)
    {
	CHOLMOD(free_factor) (&L, Common) ;
	return (NULL) ;		/* out of memory */
    }

    /* initialize Perm and ColCount */
    Perm = L->Perm ;
    for (j = 0 ; j < ((Int) n) ; j++)
    {
	Perm [j] = j ;
    }
    ColCount = L->ColCount ;
    for (j = 0 ; j < ((Int) n) ; j++)
    {
	ColCount [j] = 1 ;
    }

    return (L) ;
}
示例#13
0
cholmod_factor *CHOLMOD(copy_factor)
(
    /* ---- input ---- */
    cholmod_factor *L,	/* factor to copy */
    /* --------------- */
    cholmod_common *Common
)
{
    cholmod_factor *L2 ;
    double *Lx, *L2x, *Lz, *L2z ;
    Int *Perm, *ColCount, *Lp, *Li, *Lnz, *Lnext, *Lprev, *Lsuper, *Lpi, *Lpx,
	*Ls, *Perm2, *ColCount2, *L2p, *L2i, *L2nz, *L2next, *L2prev, *L2super,
	*L2pi, *L2px, *L2s ;
    Int n, j, p, pend, s, xsize, ssize, nsuper ;

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

    RETURN_IF_NULL_COMMON (NULL) ;
    RETURN_IF_NULL (L, NULL) ;
    RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, NULL) ;
    Common->status = CHOLMOD_OK ;
    DEBUG (CHOLMOD(dump_factor) (L, "start copy", Common)) ;

    n = L->n ;

    /* ---------------------------------------------------------------------- */
    /* allocate a simplicial symbolic factor  */
    /* ---------------------------------------------------------------------- */

    /* allocates L2->Perm and L2->ColCount */
    L2 = CHOLMOD(allocate_factor) (n, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	return (NULL) ;	    /* out of memory */
    }
    ASSERT (L2->xtype == CHOLMOD_PATTERN && !(L2->is_super)) ;

    Perm = L->Perm ;
    ColCount = L->ColCount ;
    Perm2 = L2->Perm ;
    ColCount2 = L2->ColCount ;
    L2->ordering = L->ordering ;

    for (j = 0 ; j < n ; j++)
    {
	Perm2 [j] = Perm [j] ;
    }
    for (j = 0 ; j < n ; j++)
    {
	ColCount2 [j] = ColCount [j] ;
    }
    L2->is_ll = L->is_ll ;

    /* ---------------------------------------------------------------------- */
    /* copy the rest of the factor */
    /* ---------------------------------------------------------------------- */

    if (L->xtype != CHOLMOD_PATTERN && !(L->super))
    {

	/* ------------------------------------------------------------------ */
	/* allocate a simplicial numeric factor */
	/* ------------------------------------------------------------------ */

	/* allocate L2->p, L2->nz, L2->prev, L2->next, L2->i, and L2->x.
	 * packed = -1 so that cholmod_change_factor allocates space of
	 * size L2->nzmax */
	L2->nzmax = L->nzmax ;
	if (!CHOLMOD(change_factor) (L->xtype, L->is_ll, FALSE, -1, TRUE,
		    L2, Common))
	{
	    CHOLMOD(free_factor) (&L2, Common) ;
	    return (NULL) ;	/* out of memory */
	}
	ASSERT (MAX (1, L->nzmax) == L2->nzmax) ;

	/* ------------------------------------------------------------------ */
	/* copy the contents of a simplicial numeric factor */
	/* ------------------------------------------------------------------ */

	Lp = L->p ;
	Li = L->i ;
	Lx = L->x ;
	Lz = L->z ;
	Lnz = L->nz ;
	Lnext = L->next ;
	Lprev = L->prev ;

	L2p = L2->p ;
	L2i = L2->i ;
	L2x = L2->x ;
	L2z = L2->z ;
	L2nz = L2->nz ;
	L2next = L2->next ;
	L2prev = L2->prev ;
	L2->xtype = L->xtype ;
	L2->dtype = L->dtype ;

	for (j = 0 ; j <= n ; j++)
	{
	    L2p [j] = Lp [j] ;
	}

	for (j = 0 ; j < n+2 ; j++)
	{
	    L2prev [j] = Lprev [j] ;
	}

	for (j = 0 ; j < n+2 ; j++)
	{
	    L2next [j] = Lnext [j] ;
	}

	for (j = 0 ; j < n ; j++)
	{
	    L2nz [j] = Lnz [j] ;
	}

	for (j = 0 ; j < n ; j++)
	{
	    p = Lp [j] ;
	    pend = p + Lnz [j] ;
	    for ( ; p < pend ; p++)
	    {
		L2i [p] = Li [p] ;
	    }
	    p = Lp [j] ;

	    if (L->xtype == CHOLMOD_REAL)
	    {
		for ( ; p < pend ; p++)
		{
		    L2x [p] = Lx [p] ;
		}
	    }
	    else if (L->xtype == CHOLMOD_COMPLEX)
	    {
		for ( ; p < pend ; p++)
		{
		    L2x [2*p  ] = Lx [2*p  ] ;
		    L2x [2*p+1] = Lx [2*p+1] ;
		}
	    }
	    else if (L->xtype == CHOLMOD_ZOMPLEX)
	    {
		for ( ; p < pend ; p++)
		{
		    L2x [p] = Lx [p] ;
		    L2z [p] = Lz [p] ;
		}
	    }

	}

    }
    else if (L->is_super)
    {

	/* ------------------------------------------------------------------ */
	/* copy a supernodal factor */
	/* ------------------------------------------------------------------ */

	xsize = L->xsize ;
	ssize = L->ssize ;
	nsuper = L->nsuper ;

	L2->xsize = xsize ;
	L2->ssize = ssize ;
	L2->nsuper = nsuper ;

	/* allocate L2->super, L2->pi, L2->px, and L2->s.  Allocate L2->x if
	 * L is numeric */
	if (!CHOLMOD(change_factor) (L->xtype, TRUE, TRUE, TRUE, TRUE, L2,
		    Common))
	{
	    CHOLMOD(free_factor) (&L2, Common) ;
	    return (NULL) ;	/* out of memory */
	}

	ASSERT (L2->s != NULL) ;

	/* ------------------------------------------------------------------ */
	/* copy the contents of a supernodal factor */
	/* ------------------------------------------------------------------ */

	Lsuper = L->super ;
	Lpi = L->pi ;
	Lpx = L->px ;
	Ls = L->s ;
	Lx = L->x ;

	L2super = L2->super ;
	L2pi = L2->pi ;
	L2px = L2->px ;
	L2s = L2->s ;
	L2x = L2->x ;

	L2->maxcsize = L->maxcsize ;
	L2->maxesize = L->maxesize ;

	for (s = 0 ; s <= nsuper ; s++)
	{
	    L2super [s] = Lsuper [s] ;
	}
	for (s = 0 ; s <= nsuper ; s++)
	{
	    L2pi [s] = Lpi [s] ;
	}
	for (s = 0 ; s <= nsuper ; s++)
	{
	    L2px [s] = Lpx [s] ;
	}

	L2s [0] = 0 ;
	for (p = 0 ; p < ssize ; p++)
	{
	    L2s [p] = Ls [p] ;
	}

	if (L->xtype == CHOLMOD_REAL)
	{
	    for (p = 0 ; p < xsize ; p++)
	    {
		L2x [p] = Lx [p] ;
	    }
	}
	else if (L->xtype == CHOLMOD_COMPLEX)
	{
	    for (p = 0 ; p < 2*xsize ; p++)
	    {
		L2x [p] = Lx [p] ;
	    }
	}
    }

    L2->minor = L->minor ;
    L2->is_monotonic = L->is_monotonic ;

    DEBUG (CHOLMOD(dump_factor) (L2, "L2 got copied", Common)) ;
    ASSERT (L2->xtype == L->xtype && L2->is_super == L->is_super) ;
    return (L2) ;
}
示例#14
0
cholmod_sparse *CHOLMOD(factor_to_sparse)
(
    /* ---- in/out --- */
    cholmod_factor *L,	/* factor to copy, converted to symbolic on output */
    /* --------------- */
    cholmod_common *Common
)
{
    cholmod_sparse *Lsparse ;

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

    RETURN_IF_NULL_COMMON (NULL) ;
    RETURN_IF_NULL (L, NULL) ;
    RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, NULL) ;
    Common->status = CHOLMOD_OK ;
    DEBUG (CHOLMOD(dump_factor) (L, "start convert to matrix", Common)) ;

    /* ---------------------------------------------------------------------- */
    /* convert to packed, monotonic, simplicial, numeric */
    /* ---------------------------------------------------------------------- */

    /* leave as LL or LDL' */
    if (!CHOLMOD(change_factor) (L->xtype, L->is_ll, FALSE, TRUE, TRUE, L,
		Common))
    {
	ERROR (CHOLMOD_INVALID, "cannot convert L") ;
	return (NULL) ;
    }

    /* ---------------------------------------------------------------------- */
    /* create Lsparse */
    /* ---------------------------------------------------------------------- */

    /* allocate the header for Lsparse, the sparse matrix version of L */
    Lsparse = CHOLMOD(malloc) (sizeof (cholmod_sparse), 1, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	return (NULL) ;		/* out of memory */
    }

    /* transfer the contents from L to Lsparse */
    Lsparse->nrow = L->n ;
    Lsparse->ncol = L->n ;
    Lsparse->p = L->p ;
    Lsparse->i = L->i ;
    Lsparse->x = L->x ;
    Lsparse->z = L->z ;
    Lsparse->nz = NULL ;
    Lsparse->stype = 0 ;
    Lsparse->itype = L->itype ;
    Lsparse->xtype = L->xtype ;
    Lsparse->dtype = L->dtype ;
    Lsparse->sorted = TRUE ;
    Lsparse->packed = TRUE ;
    Lsparse->nzmax = L->nzmax ;
    ASSERT (CHOLMOD(dump_sparse) (Lsparse, "Lsparse", Common) >= 0) ;

    /* ---------------------------------------------------------------------- */
    /* convert L to symbolic, but do not free contents transfered to Lsparse */
    /* ---------------------------------------------------------------------- */

    L->p = NULL ;
    L->i = NULL ;
    L->x = NULL ;
    L->z = NULL ;
    L->xtype = CHOLMOD_PATTERN ;
    CHOLMOD(change_factor) (CHOLMOD_PATTERN, FALSE, FALSE, TRUE, TRUE, L,
	    Common) ;

    return (Lsparse) ;
}
示例#15
0
int CHOLMOD(write_sparse)
(
    /* ---- input ---- */
    FILE *f,		    /* file to write to, must already be open */
    cholmod_sparse *A,	    /* matrix to print */
    cholmod_sparse *Z,	    /* optional matrix with pattern of explicit zeros */
    char *comments,	    /* optional filename of comments to include */
    /* --------------- */
    cholmod_common *Common
)
{
    double x, z ;
    double *Ax, *Az ;
    Int *Ap, *Ai, *Anz, *Zp, *Zi, *Znz ;
    Int nrow, ncol, is_complex, symmetry, i, j, q, iz, p, nz, is_binary, stype,
	is_integer, asym, is_sym, xtype, apacked, zpacked, pend, qend, k, zsym ;
    int ok ;

    /* ---------------------------------------------------------------------- */
    /* check inputs */
    /* ---------------------------------------------------------------------- */

    RETURN_IF_NULL_COMMON (EMPTY) ;
    RETURN_IF_NULL (f, EMPTY) ;
    RETURN_IF_NULL (A, EMPTY) ;
    RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, EMPTY) ;
    if (Z != NULL && (Z->nrow == 0 || Z->ncol == 0))
    {
	/* Z is non-NULL but empty, so treat it as a NULL matrix */
	Z = NULL ;
    }
    if (Z != NULL)
    {
	RETURN_IF_XTYPE_INVALID (Z, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, EMPTY) ;
	if (Z->nrow != A->nrow || Z->ncol != A->ncol || Z->stype != A->stype)
	{
	    ERROR (CHOLMOD_INVALID, "dimension or type of A and Z mismatch") ;
	    return (EMPTY) ;
	}
    }
    Common->status = CHOLMOD_OK ;

    /* ---------------------------------------------------------------------- */
    /* get the A matrix */
    /* ---------------------------------------------------------------------- */

    Ap = A->p ;
    Ai = A->i ;
    Ax = A->x ;
    Az = A->z ;
    Anz = A->nz ;
    nrow = A->nrow ;
    ncol = A->ncol ;
    xtype = A->xtype ;
    apacked = A->packed ;

    if (xtype == CHOLMOD_PATTERN)
    {
	/* a CHOLMOD pattern matrix is printed as "pattern" in the file */
	is_binary = TRUE ;
	is_integer = FALSE ;
	is_complex = FALSE ;
    }
    else if (xtype == CHOLMOD_REAL)
    {
	/* determine if a real matrix is in fact binary or integer */
	is_binary = TRUE ;
	is_integer = TRUE ;
	is_complex = FALSE ;
	for (j = 0 ; (is_binary || is_integer) && j < ncol ; j++)
	{
	    p = Ap [j] ;
	    pend = (apacked) ? Ap [j+1] : p + Anz [j] ;
	    for ( ; (is_binary || is_integer) && p < pend ; p++)
	    {
		x = Ax [p] ;
		if (x != 1)
		{
		    is_binary = FALSE ;
		}
		/* convert to Int and then back to double */
		i = (Int) x ;
		z = (double) i ;
		if (z != x)
		{
		    is_integer = FALSE ;
		}
	    }
	}
    }
    else
    {
	/* a CHOLMOD complex matrix is printed as "complex" in the file */
	is_binary = FALSE ;
	is_integer = FALSE ;
	is_complex = TRUE ;
    }

    /* ---------------------------------------------------------------------- */
    /* get the Z matrix (only consider the pattern) */
    /* ---------------------------------------------------------------------- */

    Zp = NULL ;
    Zi = NULL ;
    Znz = NULL ;
    zpacked = TRUE ;
    if (Z != NULL)
    {
	Zp = Z->p ;
	Zi = Z->i ;
	Znz = Z->nz ;
	zpacked = Z->packed ;
    }

    /* ---------------------------------------------------------------------- */
    /* determine the symmetry of A and Z */
    /* ---------------------------------------------------------------------- */

    stype = A->stype ;
    if (A->nrow != A->ncol)
    {
	asym = CHOLMOD_MM_RECTANGULAR ;
    }
    else if (stype != 0)
    {
	/* CHOLMOD's A and Z matrices have a symmetric (and matching) stype.
	 * Note that the diagonal is not checked. */
	asym = is_complex ? CHOLMOD_MM_HERMITIAN : CHOLMOD_MM_SYMMETRIC ;
    }
    else if (!A->sorted)
    {
	/* A is in unsymmetric storage, but unsorted */
	asym = CHOLMOD_MM_UNSYMMETRIC ;
    }
    else
    {
	/* CHOLMOD's stype is zero (stored in unsymmetric form) */
	asym = EMPTY ;
	zsym = EMPTY ;

#ifndef NMATRIXOPS
	/* determine if the matrices are in fact symmetric or Hermitian */
	asym = CHOLMOD(symmetry) (A, 1, NULL, NULL, NULL, NULL, Common) ;
	zsym = (Z == NULL) ? 999 :
	       CHOLMOD(symmetry) (Z, 1, NULL, NULL, NULL, NULL, Common) ;
#endif

	if (asym == EMPTY || zsym <= CHOLMOD_MM_UNSYMMETRIC)
	{
	    /* not computed, out of memory, or Z is unsymmetric */
	    asym = CHOLMOD_MM_UNSYMMETRIC ;
	}
    }

    /* ---------------------------------------------------------------------- */
    /* write the Matrix Market header */
    /* ---------------------------------------------------------------------- */

    ok = fprintf (f, "%%%%MatrixMarket matrix coordinate") > 0 ;

    if (is_complex)
    {
	ok = ok && (fprintf (f, " complex") > 0) ;
    }
    else if (is_binary)
    {
	ok = ok && (fprintf (f, " pattern") > 0) ;
    }
    else if (is_integer)
    {
	ok = ok && (fprintf (f, " integer") > 0) ;
    }
    else
    {
	ok = ok && (fprintf (f, " real") > 0) ;
    }

    switch (asym)
    {
	case CHOLMOD_MM_RECTANGULAR:
	case CHOLMOD_MM_UNSYMMETRIC:
	    /* A is rectangular or unsymmetric */
	    ok = ok && (fprintf (f, " general\n") > 0) ;
	    is_sym = FALSE ;
	    symmetry = CHOLMOD_MM_UNSYMMETRIC ;
	    break ;

	case CHOLMOD_MM_SYMMETRIC:
	case CHOLMOD_MM_SYMMETRIC_POSDIAG:
	    /* A is symmetric */
	    ok = ok && (fprintf (f, " symmetric\n") > 0) ;
	    is_sym = TRUE ;
	    symmetry = CHOLMOD_MM_SYMMETRIC ;
	    break ;

	case CHOLMOD_MM_HERMITIAN:
	case CHOLMOD_MM_HERMITIAN_POSDIAG:
	    /* A is Hermitian */
	    ok = ok && (fprintf (f, " Hermitian\n") > 0) ;
	    is_sym = TRUE ;
	    symmetry = CHOLMOD_MM_HERMITIAN ;
	    break ;

	case CHOLMOD_MM_SKEW_SYMMETRIC:
	    /* A is skew symmetric */
	    ok = ok && (fprintf (f, " skew-symmetric\n") > 0) ;
	    is_sym = TRUE ;
	    symmetry = CHOLMOD_MM_SKEW_SYMMETRIC ;
	    break ;
    }

    /* ---------------------------------------------------------------------- */
    /* include the comments if present */
    /* ---------------------------------------------------------------------- */

    ok = ok && include_comments (f, comments) ;

    /* ---------------------------------------------------------------------- */
    /* write a sparse matrix (A and Z) */
    /* ---------------------------------------------------------------------- */

    nz = ntriplets (A, is_sym) + ntriplets (Z, is_sym) ;

    /* write the first data line, with nrow, ncol, and # of triplets */
    ok = ok && (fprintf (f, ID " " ID " " ID "\n", nrow, ncol, nz) > 0) ;

    for (j = 0 ; ok && j < ncol ; j++)
    {
	/* merge column of A and Z */
	p = Ap [j] ;
	pend = (apacked) ? Ap [j+1] : p + Anz [j] ;
	q = (Z == NULL) ? 0 : Zp [j] ;
	qend = (Z == NULL) ? 0 : ((zpacked) ? Zp [j+1] : q + Znz [j]) ;
	while (ok)
	{
	    /* get the next row index from A and Z */
	    i  = (p < pend) ? Ai [p] : (nrow+1) ;
	    iz = (q < qend) ? Zi [q] : (nrow+2) ;
	    if (i <= iz)
	    {
		/* get A(i,j), or quit if both A and Z are exhausted */
		if (i == nrow+1) break ;
		get_value (Ax, Az, p, xtype, &x, &z) ;
		p++ ;
	    }
	    else
	    {
		/* get Z(i,j) */
		i = iz ;
		x = 0 ;
		z = 0 ;
		q++ ;
	    }
	    if ((stype < 0 && i >= j) || (stype == 0 && (i >= j || !is_sym)))
	    {
		/* CHOLMOD matrix is symmetric-lower (and so is the file);
		 * or CHOLMOD matrix is unsymmetric and either A(i,j) is in
		 * the lower part or the file is unsymmetric. */
		ok = ok && print_triplet (f, is_binary, is_complex, is_integer,
		    i,j, x,z) ;
	    }
	    else if (stype > 0 && i <= j)
	    {
		/* CHOLMOD matrix is symmetric-upper, but the file is
		 * symmetric-lower.  Need to transpose the entry.   If the
		 * matrix is real, the complex part is ignored.  If the matrix
		 * is complex, it Hermitian.
		 */
		ASSERT (IMPLIES (is_complex, asym == CHOLMOD_MM_HERMITIAN)) ;
		if (z != 0)
		{
		    z = -z ;
		}
		ok = ok && print_triplet (f, is_binary, is_complex, is_integer,
		    j,i, x,z) ;
	    }
	}
    }

    if (!ok)
    {
	ERROR (CHOLMOD_INVALID, "error reading/writing file") ;
	return (EMPTY) ;
    }

    return (asym) ;
}
示例#16
0
cholmod_dense *CHOLMOD(allocate_dense)
(
    /* ---- input ---- */
    size_t nrow,	/* # of rows of matrix */
    size_t ncol,	/* # of columns of matrix */
    size_t d,		/* leading dimension */
    int xtype,		/* CHOLMOD_REAL, _COMPLEX, or _ZOMPLEX */
    /* --------------- */
    cholmod_common *Common
)
{
    cholmod_dense *X ;
    size_t nzmax, nzmax0 ;
    int ok = TRUE ;

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

    RETURN_IF_NULL_COMMON (NULL) ;
    if (d < nrow)
    {
	ERROR (CHOLMOD_INVALID, "leading dimension invalid") ;
	return (NULL) ;
    }
    if (xtype < CHOLMOD_REAL || xtype > CHOLMOD_ZOMPLEX)
    {
	ERROR (CHOLMOD_INVALID, "xtype invalid") ;
	return (NULL) ;
    }

    /* ensure the dimensions do not cause integer overflow */
    (void) CHOLMOD(add_size_t) (ncol, 2, &ok) ;

    /* nzmax = MAX (1, d*ncol) ; */
    nzmax = CHOLMOD(mult_size_t) (d, ncol, &ok) ;
    nzmax = MAX (1, nzmax) ;

    if (!ok || nrow > Int_max || ncol > Int_max || nzmax > Int_max)
    {
	ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
	return (NULL) ;
    }
    Common->status = CHOLMOD_OK ;

    /* ---------------------------------------------------------------------- */
    /* allocate header */
    /* ---------------------------------------------------------------------- */

    X = CHOLMOD(malloc) (sizeof (cholmod_dense), 1, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	return (NULL) ;	    /* out of memory */
    }

    PRINT1 (("cholmod_allocate_dense %d-by-%d nzmax %d xtype %d\n",
		nrow, ncol, nzmax, xtype)) ;

    X->nrow = nrow ;
    X->ncol = ncol ;
    X->nzmax = nzmax ;
    X->xtype = xtype ;
    X->dtype = DTYPE ;
    X->x = NULL ;
    X->z = NULL ;
    X->d = d ;

    /* ---------------------------------------------------------------------- */
    /* allocate the matrix itself */
    /* ---------------------------------------------------------------------- */

    nzmax0 = 0 ;
    CHOLMOD(realloc_multiple) (nzmax, 0, xtype, NULL, NULL, &(X->x), &(X->z),
	    &nzmax0, Common) ;

    if (Common->status < CHOLMOD_OK)
    {
	CHOLMOD(free_dense) (&X, Common) ;
	return (NULL) ;	    /* out of memory */
    }

    return (X) ;
}
示例#17
0
int CHOLMOD(csymamd)
(
    /* ---- input ---- */
    cholmod_sparse *A,	/* matrix to order */
    /* ---- output --- */
    Int *Cmember,	/* size nrow.  see cholmod_ccolamd.c for description */
    Int *Perm,		/* size A->nrow, output permutation */
    /* --------------- */
    cholmod_common *Common
)
{
    double knobs [CCOLAMD_KNOBS] ;
    Int *perm, *Head ;
    Int ok, i, nrow, stats [CCOLAMD_STATS] ;

    /* ---------------------------------------------------------------------- */
    /* 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) ;
    Common->status = CHOLMOD_OK ;

    if (A->nrow != A->ncol || !(A->packed))
    {
        ERROR (CHOLMOD_INVALID, "matrix must be square and packed") ;
        return (FALSE) ;
    }

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

    nrow = A->nrow ;

    /* ---------------------------------------------------------------------- */
    /* allocate workspace */
    /* ---------------------------------------------------------------------- */

    CHOLMOD(allocate_work) (nrow, 0, 0, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
        return (FALSE) ;
    }

    /* ---------------------------------------------------------------------- */
    /* order the matrix (does not affect A->p or A->i) */
    /* ---------------------------------------------------------------------- */

    perm = Common->Head ;	/* size nrow+1 (i/l/l) */

    /* get parameters */
#ifdef LONG
    amesos_ccolamd_l_set_defaults (knobs) ;
#else
    amesos_ccolamd_set_defaults (knobs) ;
#endif
    if (Common->current >= 0 && Common->current < CHOLMOD_MAXMETHODS)
    {
        /* get the knobs from the Common parameters */
        knobs [CCOLAMD_DENSE_ROW] =Common->method[Common->current].prune_dense ;
        knobs [CCOLAMD_AGGRESSIVE]=Common->method[Common->current].aggressive ;
    }

    {
#ifdef LONG
        amesos_csymamd_l (nrow, A->i, A->p, perm, knobs, stats, Common->calloc_memory,
                          Common->free_memory, Cmember, A->stype) ;
#else
        amesos_csymamd (nrow, A->i, A->p, perm, knobs, stats, Common->calloc_memory,
                        Common->free_memory, Cmember, A->stype) ;
#endif
        ok = stats [CCOLAMD_STATUS] ;
    }

    if (ok == CCOLAMD_ERROR_out_of_memory)
    {
        ERROR (CHOLMOD_OUT_OF_MEMORY, "out of memory") ;
    }
    ok = (ok == CCOLAMD_OK || ok == CCOLAMD_OK_BUT_JUMBLED) ;

    /* ---------------------------------------------------------------------- */
    /* free the workspace and return result */
    /* ---------------------------------------------------------------------- */

    /* permutation returned in perm [0..n-1] */
    for (i = 0 ; i < nrow ; i++)
    {
        Perm [i] = perm [i] ;
    }

    /* clear Head workspace (used for perm, in csymamd): */
    Head = Common->Head ;
    for (i = 0 ; i <= nrow ; i++)
    {
        Head [i] = EMPTY ;
    }

    return (ok) ;
}
示例#18
0
static int permute_matrices
(
    /* ---- input ---- */
    cholmod_sparse *A,	/* matrix to permute */
    Int ordering,	/* ordering method used */
    Int *Perm,		/* fill-reducing permutation */
    Int *fset,		/* subset of 0:(A->ncol)-1 */
    size_t fsize,	/* size of fset */
    Int do_rowcolcounts,/* if TRUE, compute both S and F.  If FALSE, only
			 * S is needed for the symmetric case, and only F for
			 * the unsymmetric case */
    /* ---- output --- */
    cholmod_sparse **A1_handle,	    /* see comments below for A1, A2, S, F */
    cholmod_sparse **A2_handle,
    cholmod_sparse **S_handle,
    cholmod_sparse **F_handle,
    /* --------------- */
    cholmod_common *Common
)
{
    cholmod_sparse *A1, *A2, *S, *F ;

    *A1_handle = NULL ;
    *A2_handle = NULL ;
    *S_handle = NULL ;
    *F_handle = NULL ;
    A1 = NULL ;
    A2 = NULL ;

    if (ordering == CHOLMOD_NATURAL)
    {

	/* ------------------------------------------------------------------ */
	/* natural ordering of A */
	/* ------------------------------------------------------------------ */

	if (A->stype < 0)
	{
	    /* symmetric lower case: A already in lower form, so S=A' */
	    /* workspace: Iwork (nrow) */
	    A2 = CHOLMOD(ptranspose) (A, 0, NULL, NULL, 0, Common) ;
	    F = A ;
	    S = A2 ;
	}
	else if (A->stype > 0)
	{
	    /* symmetric upper case: F = pattern of triu (A)', S = A */
	    /* workspace: Iwork (nrow) */
	    if (do_rowcolcounts)
	    {
		/* F not needed for symmetric case if do_rowcolcounts FALSE */
		A1 = CHOLMOD(ptranspose) (A, 0, NULL, fset, fsize, Common) ;
	    }
	    F = A1 ;
	    S = A ;
	}
	else
	{
	    /* unsymmetric case: F = pattern of A (:,f)',  S = A */
	    /* workspace: Iwork (nrow if no fset, MAX(nrow,ncol) if fset) */
	    A1 = CHOLMOD(ptranspose) (A, 0, NULL, fset, fsize, Common) ;
	    F = A1 ;
	    S = A ;
	}

    }
    else
    {

	/* ------------------------------------------------------------------ */
	/* A is permuted */
	/* ------------------------------------------------------------------ */

	if (A->stype < 0)
	{
	    /* symmetric lower case: S = tril (A (p,p))' and F = S' */
	    /* workspace: Iwork (2*nrow) */
	    A2 = CHOLMOD(ptranspose) (A, 0, Perm, NULL, 0, Common) ;
	    S = A2 ;
	    /* workspace: Iwork (nrow) */
	    if (do_rowcolcounts)
	    {
		/* F not needed for symmetric case if do_rowcolcounts FALSE */
		A1 = CHOLMOD(ptranspose) (A2, 0, NULL, NULL, 0, Common) ;
	    }
	    F = A1 ;
	}
	else if (A->stype > 0)
	{
	    /* symmetric upper case: F = triu (A (p,p))' and S = F' */
	    /* workspace: Iwork (2*nrow) */
	    A1 = CHOLMOD(ptranspose) (A, 0, Perm, NULL, 0, Common) ;
	    F = A1 ;
	    /* workspace: Iwork (nrow) */
	    A2 = CHOLMOD(ptranspose) (A1, 0, NULL, NULL, 0, Common) ;
	    S = A2 ;
	}
	else
	{
	    /* unsymmetric case:     F = A (p,f)'         and S = F' */
	    /* workspace: Iwork (nrow if no fset, MAX(nrow,ncol) if fset) */
	    A1 = CHOLMOD(ptranspose) (A, 0, Perm, fset, fsize, Common) ;
	    F = A1 ;
	    if (do_rowcolcounts)
	    {
		/* S not needed for unsymmetric case if do_rowcolcounts FALSE */
		/* workspace: Iwork (nrow) */
		A2 = CHOLMOD(ptranspose) (A1, 0, NULL, NULL, 0, Common) ;
	    }
	    S = A2 ;
	}
    }

    /* If any cholmod_*transpose fails, one or more matrices will be NULL */
    *A1_handle = A1 ;
    *A2_handle = A2 ;
    *S_handle = S ;
    *F_handle = F ;
    return (Common->status == CHOLMOD_OK) ;
}
示例#19
0
cholmod_sparse *CHOLMOD(add)
(
    /* ---- input ---- */
    cholmod_sparse *A,	    /* matrix to add */
    cholmod_sparse *B,	    /* matrix to add */
    double alpha [2],	    /* scale factor for A */
    double beta [2],	    /* scale factor for B */
    int values,		    /* if TRUE compute the numerical values of C */
    int sorted,		    /* if TRUE, sort columns of C */
    /* --------------- */
    cholmod_common *Common
)
{
    double *Ax, *Bx, *Cx, *W ;
    Int apacked, up, lo, nrow, ncol, bpacked, nzmax, pa, paend, pb, pbend, i,
	j, p, mark, nz ;
    Int *Ap, *Ai, *Anz, *Bp, *Bi, *Bnz, *Flag, *Cp, *Ci ;
    cholmod_sparse *A2, *B2, *C ;

    /* ---------------------------------------------------------------------- */
    /* check inputs */
    /* ---------------------------------------------------------------------- */

    RETURN_IF_NULL_COMMON (NULL) ;
    RETURN_IF_NULL (A, NULL) ;
    RETURN_IF_NULL (B, NULL) ;
    values = values &&
	(A->xtype != CHOLMOD_PATTERN) && (B->xtype != CHOLMOD_PATTERN) ;
    RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN,
	    values ? CHOLMOD_REAL : CHOLMOD_ZOMPLEX, NULL) ;
    RETURN_IF_XTYPE_INVALID (B, CHOLMOD_PATTERN,
	    values ? CHOLMOD_REAL : CHOLMOD_ZOMPLEX, NULL) ;
    if (A->nrow != B->nrow || A->ncol != B->ncol)
    {
	/* A and B must have the same dimensions */
	ERROR (CHOLMOD_INVALID, "A and B dimesions do not match") ;
	return (NULL) ;
    }
    /* A and B must have the same numerical type if values is TRUE (both must
     * be CHOLMOD_REAL, this is implicitly checked above) */

    Common->status = CHOLMOD_OK ;

    /* ---------------------------------------------------------------------- */
    /* allocate workspace */
    /* ---------------------------------------------------------------------- */

    nrow = A->nrow ;
    ncol = A->ncol ;
    CHOLMOD(allocate_work) (nrow, MAX (nrow,ncol), values ? nrow : 0, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	return (NULL) ;	    /* out of memory */
    }

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

    if (nrow <= 1)
    {
	/* C will be implicitly sorted, so no need to sort it here */
	sorted = FALSE ;
    }

    /* convert A or B to unsymmetric, if necessary */
    A2 = NULL ;
    B2 = NULL ;

    if (A->stype != B->stype)
    {
	if (A->stype)
	{
	    /* workspace: Iwork (max (nrow,ncol)) */
	    A2 = CHOLMOD(copy) (A, 0, values, Common) ;
	    if (Common->status < CHOLMOD_OK)
	    {
		return (NULL) ;	    /* out of memory */
	    }
	    A = A2 ;
	}
	if (B->stype)
	{
	    /* workspace: Iwork (max (nrow,ncol)) */
	    B2 = CHOLMOD(copy) (B, 0, values, Common) ;
	    if (Common->status < CHOLMOD_OK)
	    {
		CHOLMOD(free_sparse) (&A2, Common) ;
		return (NULL) ;	    /* out of memory */
	    }
	    B = B2 ;
	}
    }

    /* get the A matrix */
    ASSERT (A->stype == B->stype) ;
    up = (A->stype > 0) ;
    lo = (A->stype < 0) ;

    Ap  = A->p ;
    Anz = A->nz ;
    Ai  = A->i ;
    Ax  = A->x ;
    apacked = A->packed ;

    /* get the B matrix */
    Bp  = B->p ;
    Bnz = B->nz ;
    Bi  = B->i ;
    Bx  = B->x ;
    bpacked = B->packed ;

    /* get workspace */
    W = Common->Xwork ;	    /* size nrow, used if values is TRUE */
    Flag = Common->Flag ;   /* size nrow, Flag [0..nrow-1] < mark on input */

    /* ---------------------------------------------------------------------- */
    /* allocate the result C */
    /* ---------------------------------------------------------------------- */

    /* If integer overflow occurs, nzmax < 0 and the allocate fails properly
     * (likewise in most other matrix manipulation routines). */

    nzmax = CHOLMOD(nnz) (A, Common) + CHOLMOD(nnz) (B, Common) ;

    C = CHOLMOD(allocate_sparse) (nrow, ncol, nzmax, FALSE, TRUE,
	    SIGN (A->stype), values ? A->xtype : CHOLMOD_PATTERN, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	CHOLMOD(free_sparse) (&A2, Common) ;
	CHOLMOD(free_sparse) (&B2, Common) ;
	return (NULL) ;	    /* out of memory */
    }

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

    /* ---------------------------------------------------------------------- */
    /* compute C = alpha*A + beta*B */
    /* ---------------------------------------------------------------------- */

    nz = 0 ;
    for (j = 0 ; j < ncol ; j++)
    {
	Cp [j] = nz ;

	/* clear the Flag array */
	/* mark = CHOLMOD(clear_flag) (Common) ; */
	CHOLMOD_CLEAR_FLAG (Common) ;
	mark = Common->mark ;

	/* scatter B into W */
	pb = Bp [j] ;
	pbend = (bpacked) ? (Bp [j+1]) : (pb + Bnz [j]) ;
	for (p = pb ; p < pbend ; p++)
	{
	    i = Bi [p] ;
	    if ((up && i > j) || (lo && i < j))
	    {
		continue ;
	    }
	    Flag [i] = mark ;
	    if (values)
	    {
		W [i] = beta [0] * Bx [p] ;
	    }
	}

	/* add A and gather from W into C(:,j) */
	pa = Ap [j] ;
	paend = (apacked) ? (Ap [j+1]) : (pa + Anz [j]) ;
	for (p = pa ; p < paend ; p++)
	{
	    i = Ai [p] ;
	    if ((up && i > j) || (lo && i < j))
	    {
		continue ;
	    }
	    Flag [i] = EMPTY ;
	    Ci [nz] = i ;
	    if (values)
	    {
		Cx [nz] = W [i] + alpha [0] * Ax [p] ;
		W [i] = 0 ;
	    }
	    nz++ ;
	}

	/* gather remaining entries into C(:,j), using pattern of B */
	for (p = pb ; p < pbend ; p++)
	{
	    i = Bi [p] ;
	    if ((up && i > j) || (lo && i < j))
	    {
		continue ;
	    }
	    if (Flag [i] == mark)
	    {
		Ci [nz] = i ;
		if (values)
		{
		    Cx [nz] = W [i] ;
		    W [i] = 0 ;
		}
		nz++ ;
	    }
	}
    }

    Cp [ncol] = nz ;

    /* ---------------------------------------------------------------------- */
    /* reduce C in size and free temporary matrices */
    /* ---------------------------------------------------------------------- */

    ASSERT (MAX (1,nz) <= C->nzmax) ;
    CHOLMOD(reallocate_sparse) (nz, C, Common) ;
    ASSERT (Common->status >= CHOLMOD_OK) ;

    /* clear the Flag array */
    mark = CHOLMOD(clear_flag) (Common) ;

    CHOLMOD(free_sparse) (&A2, Common) ;
    CHOLMOD(free_sparse) (&B2, Common) ;

    /* ---------------------------------------------------------------------- */
    /* sort C, if requested */
    /* ---------------------------------------------------------------------- */

    if (sorted)
    {
	/* workspace: Iwork (max (nrow,ncol)) */
	if (!CHOLMOD(sort) (C, Common))
	{
	    CHOLMOD(free_sparse) (&C, Common) ;
	    if (Common->status < CHOLMOD_OK)
	    {
		return (NULL) ;		/* out of memory */
	    }
	}
    }

    /* ---------------------------------------------------------------------- */
    /* return result */
    /* ---------------------------------------------------------------------- */

    ASSERT (CHOLMOD(dump_sparse) (C, "add", Common) >= 0) ;
    return (C) ;
}
示例#20
0
int CHOLMOD(analyze_ordering)
(
    /* ---- input ---- */
    cholmod_sparse *A,	/* matrix to analyze */
    int ordering,	/* ordering method used */
    Int *Perm,		/* size n, fill-reducing permutation to analyze */
    Int *fset,		/* subset of 0:(A->ncol)-1 */
    size_t fsize,	/* size of fset */
    /* ---- output --- */
    Int *Parent,	/* size n, elimination tree */
    Int *Post,		/* size n, postordering of elimination tree */
    Int *ColCount,	/* size n, nnz in each column of L */
    /* ---- workspace  */
    Int *First,		/* size n workspace for cholmod_postorder */
    Int *Level,		/* size n workspace for cholmod_postorder */
    /* --------------- */
    cholmod_common *Common
)
{
    cholmod_sparse *A1, *A2, *S, *F ;
    Int n, ok, do_rowcolcounts ;

    /* check inputs */
    RETURN_IF_NULL_COMMON (FALSE) ;
    RETURN_IF_NULL (A, FALSE) ;

    n = A->nrow ;

    do_rowcolcounts = (ColCount != NULL) ;

    /* permute A according to Perm and fset */
    ok = permute_matrices (A, ordering, Perm, fset, fsize, do_rowcolcounts,
	    &A1, &A2, &S, &F, Common) ;

    /* find etree of S (symmetric upper/lower case) or F (unsym case) */
    /* workspace: symmmetric: Iwork (nrow), unsym: Iwork (nrow+ncol) */
    ok = ok && CHOLMOD(etree) (A->stype ? S:F, Parent, Common) ;

    /* postorder the etree (required by cholmod_rowcolcounts) */
    /* workspace: Iwork (2*nrow) */
    ok = ok && (CHOLMOD(postorder) (Parent, n, NULL, Post, Common) == n) ;

    /* cholmod_postorder doesn't set Common->status if it returns < n */
    Common->status = (!ok && Common->status == CHOLMOD_OK) ?
	CHOLMOD_INVALID : Common->status ;

    /* analyze LL'=S or SS' or S(:,f)*S(:,f)' */
    /* workspace:
     *	if symmetric:   Flag (nrow), Iwork (2*nrow)
     *	if unsymmetric: Flag (nrow), Iwork (2*nrow+ncol), Head (nrow+1)
     */
    if (do_rowcolcounts)
    {
	ok = ok && CHOLMOD(rowcolcounts) (A->stype ? F:S, fset, fsize, Parent,
	    Post, NULL, ColCount, First, Level, Common) ;
    }

    /* free temporary matrices and return result */
    CHOLMOD(free_sparse) (&A1, Common) ;
    CHOLMOD(free_sparse) (&A2, Common) ;
    return (ok) ;
}
示例#21
0
static int ccolamd_interface
(
    cholmod_sparse *A,
    size_t alen,
    Int *Perm,
    Int *Cmember,
    Int *fset,
    Int fsize,
    cholmod_sparse *C,
    cholmod_common *Common
)
{
    double knobs [CCOLAMD_KNOBS] ;
    Int *Cp = NULL ;
    Int ok, k, nrow, ncol, stats [CCOLAMD_STATS] ;

    nrow = A->nrow ;
    ncol = A->ncol ;

    /* ---------------------------------------------------------------------- */
    /* copy (and transpose) the input matrix A into the ccolamd workspace */
    /* ---------------------------------------------------------------------- */

    /* C = A (:,f)', which also packs A if needed. */
    /* workspace: Iwork (nrow if no fset; MAX (nrow,ncol) if fset non-NULL) */
    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 */
#ifdef LONG
    ccolamd_l_set_defaults (knobs) ;
#else
    ccolamd_set_defaults (knobs) ;
#endif

    if (Common->current < 0 || Common->current >= CHOLMOD_MAXMETHODS)
    {
	/* this is the CHOLMOD default, not the CCOLAMD default */
	knobs [CCOLAMD_DENSE_ROW] = -1 ;
    }
    else
    {
	/* get the knobs from the Common parameters */
	knobs [CCOLAMD_DENSE_COL] =Common->method[Common->current].prune_dense ;
	knobs [CCOLAMD_DENSE_ROW] =Common->method[Common->current].prune_dense2;
	knobs [CCOLAMD_AGGRESSIVE]=Common->method[Common->current].aggressive ;
	knobs [CCOLAMD_LU]        =Common->method[Common->current].order_for_lu;
    }

    if (ok)
    {

#ifdef LONG
	ccolamd_l (ncol, nrow, alen, C->i, C->p, knobs, stats, Cmember) ;
#else
	ccolamd (ncol, nrow, alen, C->i, C->p, knobs, stats, Cmember) ;
#endif

	ok = stats [CCOLAMD_STATUS] ;

	ok = (ok == CCOLAMD_OK || ok == CCOLAMD_OK_BUT_JUMBLED) ;
	/* permutation returned in C->p, if the ordering succeeded */
	Cp = C->p ;
	for (k = 0 ; k < nrow ; k++)
	{
	    Perm [k] = Cp [k] ;
	}
    }

    return (ok) ;
}
示例#22
0
cholmod_factor *CHOLMOD(analyze_p2)
(
    /* ---- input ---- */
    int for_cholesky,   /* if TRUE, then analyze for Cholesky; else for QR */
    cholmod_sparse *A,	/* matrix to order and analyze */
    Int *UserPerm,	/* user-provided permutation, size A->nrow */
    Int *fset,		/* subset of 0:(A->ncol)-1 */
    size_t fsize,	/* size of fset */
    /* --------------- */
    cholmod_common *Common
)
{
    double lnz_best ;
    Int *First, *Level, *Work4n, *Cmember, *CParent, *ColCount, *Lperm, *Parent,
	*Post, *Perm, *Lparent, *Lcolcount ;
    cholmod_factor *L ;
    Int k, n, ordering, method, nmethods, status, default_strategy, ncol, uncol,
	skip_analysis, skip_best ;
    Int amd_backup ;
    size_t s ;
    int ok = TRUE ;

    /* ---------------------------------------------------------------------- */
    /* check inputs */
    /* ---------------------------------------------------------------------- */

    RETURN_IF_NULL_COMMON (NULL) ;
    RETURN_IF_NULL (A, NULL) ;
    RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, NULL) ;
    Common->status = CHOLMOD_OK ;
    status = CHOLMOD_OK ;
    Common->selected = EMPTY ;
    Common->called_nd = FALSE ;

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

    n = A->nrow ;
    ncol = A->ncol ;
    uncol = (A->stype == 0) ? (A->ncol) : 0 ;

    /* ---------------------------------------------------------------------- */
    /* set the default strategy */
    /* ---------------------------------------------------------------------- */

    lnz_best = (double) EMPTY ;
    skip_best = FALSE ;
    nmethods = MIN (Common->nmethods, CHOLMOD_MAXMETHODS) ;
    nmethods = MAX (0, nmethods) ;
    PRINT1 (("nmethods "ID"\n", nmethods)) ;

    default_strategy = (nmethods == 0) ;
    if (default_strategy)
    {
	/* default strategy: try UserPerm, if given.  Try AMD for A, or AMD
	 * to order A*A'.  Try METIS for the symmetric case only if AMD reports
         * a high degree of fill-in and flop count.  METIS is not tried if the
         * Partition Module isn't installed.   If Common->default_nesdis is
         * TRUE, then NESDIS is used as the 3rd ordering instead. */
	Common->method [0].ordering = CHOLMOD_GIVEN ;/* skip if UserPerm NULL */
	Common->method [1].ordering = CHOLMOD_AMD ;
	Common->method [2].ordering = 
	    (Common->default_nesdis ? CHOLMOD_NESDIS : CHOLMOD_METIS) ;
        amd_backup = FALSE ;
#ifndef NPARTITION
	nmethods = 3 ;
#else
	nmethods = 2 ;
#endif
    }
    else
    {
        /* If only METIS and NESDIS are selected, or if 2 or more methods are
         * being tried, then enable AMD backup */
        amd_backup = (nmethods > 1) || (nmethods == 1 &&
            (Common->method [0].ordering == CHOLMOD_METIS ||
             Common->method [0].ordering == CHOLMOD_NESDIS)) ;
    }

#ifdef NSUPERNODAL
    /* CHOLMOD Supernodal module not installed, just do simplicial analysis */
    Common->supernodal = CHOLMOD_SIMPLICIAL ;
#endif

    /* ---------------------------------------------------------------------- */
    /* allocate workspace */
    /* ---------------------------------------------------------------------- */

    /* Note: enough space needs to be allocated here so that routines called by
     * cholmod_analyze do not reallocate the space.
     */

    /* s = 6*n + uncol */
    s = CHOLMOD(mult_size_t) (n, 6, &ok) ;
    s = CHOLMOD(add_size_t) (s, uncol, &ok) ;
    if (!ok)
    {
	ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
	return (NULL) ;
    }

    CHOLMOD(allocate_work) (n, s, 0, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	return (NULL) ;	    /* out of memory */
    }
    ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, Common)) ;

    /* ensure that subsequent routines, called by cholmod_analyze, do not
     * reallocate any workspace.  This is set back to FALSE in the
     * FREE_WORKSPACE_AND_RETURN macro, which is the only way this function
     * returns to its caller. */
    Common->no_workspace_reallocate = TRUE ;

    /* Use the last 4*n Int's in Iwork for Parent, First, Level, and Post, since
     * other CHOLMOD routines will use the first 2n+uncol space.  The ordering
     * routines (cholmod_amd, cholmod_colamd, cholmod_ccolamd, cholmod_metis)
     * are an exception.  They can use all 6n + ncol space, since the contents
     * of Parent, First, Level, and Post are not needed across calls to those
     * routines. */
    Work4n = Common->Iwork ;
    Work4n += 2*((size_t) n) + uncol ;
    Parent = Work4n ;
    First  = Work4n + n ;
    Level  = Work4n + 2*((size_t) n) ;
    Post   = Work4n + 3*((size_t) n) ;

    /* note that this assignment means that cholmod_nested_dissection,
     * cholmod_ccolamd, and cholmod_camd can use only the first 4n+uncol
     * space in Common->Iwork */
    Cmember = Post ;
    CParent = Level ;

    /* ---------------------------------------------------------------------- */
    /* allocate more workspace, and an empty simplicial symbolic factor */
    /* ---------------------------------------------------------------------- */

    L = CHOLMOD(allocate_factor) (n, Common) ;
    Lparent  = CHOLMOD(malloc) (n, sizeof (Int), Common) ;
    Perm     = CHOLMOD(malloc) (n, sizeof (Int), Common) ;
    ColCount = CHOLMOD(malloc) (n, sizeof (Int), Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	/* out of memory */
	FREE_WORKSPACE_AND_RETURN ;
    }
    Lperm = L->Perm ;
    Lcolcount = L->ColCount ;
    Common->anz = EMPTY ;

    /* ---------------------------------------------------------------------- */
    /* try all the requested ordering options and backup to AMD if needed */
    /* ---------------------------------------------------------------------- */

    /* turn off error handling [ */
    Common->try_catch = TRUE ;

    for (method = 0 ; method <= nmethods ; method++)
    {

	/* ------------------------------------------------------------------ */
	/* determine the method to try */
	/* ------------------------------------------------------------------ */

	Common->fl = EMPTY ;
	Common->lnz = EMPTY ;
	skip_analysis = FALSE ;

	if (method == nmethods)
	{
	    /* All methods failed: backup to AMD */
	    if (Common->selected == EMPTY && amd_backup)
	    {
		PRINT1 (("All methods requested failed: backup to AMD\n")) ;
		ordering = CHOLMOD_AMD ;
	    }
	    else
	    {
		break ;
	    }
	}
	else
	{
	    ordering = Common->method [method].ordering ;
	}
	Common->current = method ;
	PRINT1 (("method "ID": Try method: "ID"\n", method, ordering)) ;

	/* ------------------------------------------------------------------ */
	/* find the fill-reducing permutation */
	/* ------------------------------------------------------------------ */

	if (ordering == CHOLMOD_NATURAL)
	{

	    /* -------------------------------------------------------------- */
	    /* natural ordering */
	    /* -------------------------------------------------------------- */

	    for (k = 0 ; k < n ; k++)
	    {
		Perm [k] = k ;
	    }

	}
	else if (ordering == CHOLMOD_GIVEN)
	{

	    /* -------------------------------------------------------------- */
	    /* use given ordering of A, if provided */
	    /* -------------------------------------------------------------- */

	    if (UserPerm == NULL)
	    {
		/* this is not an error condition */
		PRINT1 (("skip, no user perm given\n")) ;
		continue ;
	    }
	    for (k = 0 ; k < n ; k++)
	    {
		/* UserPerm is checked in cholmod_ptranspose */
		Perm [k] = UserPerm [k] ;
	    }

	}
	else if (ordering == CHOLMOD_AMD)
	{

	    /* -------------------------------------------------------------- */
	    /* AMD ordering of A, A*A', or A(:,f)*A(:,f)' */
	    /* -------------------------------------------------------------- */

            amd_backup = FALSE ;    /* no need to try AMD twice ... */
	    CHOLMOD(amd) (A, fset, fsize, Perm, Common) ;
	    skip_analysis = TRUE ;

	}
	else if (ordering == CHOLMOD_COLAMD)
	{

	    /* -------------------------------------------------------------- */
	    /* AMD for symmetric case, COLAMD for A*A' or A(:,f)*A(:,f)' */
	    /* -------------------------------------------------------------- */

	    if (A->stype)
	    {
		CHOLMOD(amd) (A, fset, fsize, Perm, Common) ;
		skip_analysis = TRUE ;
	    }
	    else
	    {
		/* Alternative:
		CHOLMOD(ccolamd) (A, fset, fsize, NULL, Perm, Common) ;
		*/
		/* do not postorder, it is done later, below */
		/* workspace: Iwork (4*nrow+uncol), Flag (nrow), Head (nrow+1)*/
		CHOLMOD(colamd) (A, fset, fsize, FALSE, Perm, Common) ;
	    }

	}
	else if (ordering == CHOLMOD_METIS)
	{

	    /* -------------------------------------------------------------- */
	    /* use METIS_NodeND directly (via a CHOLMOD wrapper) */
	    /* -------------------------------------------------------------- */

#ifndef NPARTITION
	    /* postorder parameter is false, because it will be later, below */
	    /* workspace: Iwork (4*nrow+uncol), Flag (nrow), Head (nrow+1) */
	    Common->called_nd = TRUE ;
	    CHOLMOD(metis) (A, fset, fsize, FALSE, Perm, Common) ;
#else
	    Common->status = CHOLMOD_NOT_INSTALLED ;
#endif

	}
	else if (ordering == CHOLMOD_NESDIS)
	{

	    /* -------------------------------------------------------------- */
	    /* use CHOLMOD's nested dissection */
	    /* -------------------------------------------------------------- */

	    /* this method is based on METIS' node bissection routine
	     * (METIS_NodeComputeSeparator).  In contrast to METIS_NodeND,
	     * it calls CAMD or CCOLAMD on the whole graph, instead of MMD
	     * on just the leaves. */
#ifndef NPARTITION
	    /* workspace: Flag (nrow), Head (nrow+1), Iwork (2*nrow) */
	    Common->called_nd = TRUE ;
	    CHOLMOD(nested_dissection) (A, fset, fsize, Perm, CParent, Cmember,
		    Common) ;
#else
	    Common->status = CHOLMOD_NOT_INSTALLED ;
#endif

	}
	else
	{

	    /* -------------------------------------------------------------- */
	    /* invalid ordering method */
	    /* -------------------------------------------------------------- */

	    Common->status = CHOLMOD_INVALID ;
	    PRINT1 (("No such ordering: "ID"\n", ordering)) ;
	}

	ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, Common)) ;

	if (Common->status < CHOLMOD_OK)
	{
	    /* out of memory, or method failed */
	    status = MIN (status, Common->status) ;
	    Common->status = CHOLMOD_OK ;
	    continue ;
	}

	/* ------------------------------------------------------------------ */
	/* analyze the ordering */
	/* ------------------------------------------------------------------ */

	if (!skip_analysis)
	{
	    if (!CHOLMOD(analyze_ordering) (A, ordering, Perm, fset, fsize,
		    Parent, Post, ColCount, First, Level, Common))
	    {
		/* ordering method failed; clear status and try next method */
		status = MIN (status, Common->status) ;
		Common->status = CHOLMOD_OK ;
		continue ;
	    }
	}

	ASSERT (Common->fl >= 0 && Common->lnz >= 0) ;
	Common->method [method].fl  = Common->fl ;
	Common->method [method].lnz = Common->lnz ;
	PRINT1 (("lnz %g fl %g\n", Common->lnz, Common->fl)) ;

	/* ------------------------------------------------------------------ */
	/* pick the best method */
	/* ------------------------------------------------------------------ */

	/* fl.pt. compare, but lnz can never be NaN */
	if (Common->selected == EMPTY || Common->lnz < lnz_best)
	{
	    Common->selected = method ;
	    PRINT1 (("this is best so far, method "ID"\n", method)) ;
	    L->ordering = ordering ;
	    lnz_best = Common->lnz ;
	    for (k = 0 ; k < n ; k++)
	    {
		Lperm [k] = Perm [k] ;
	    }
	    /* save the results of cholmod_analyze_ordering, if it was called */
	    skip_best = skip_analysis ;
	    if (!skip_analysis)
	    {
		/* save the column count; becomes permanent part of L */
		for (k = 0 ; k < n ; k++)
		{
		    Lcolcount [k] = ColCount [k] ;
		}
		/* Parent is needed for weighted postordering and for supernodal
		 * analysis.  Does not become a permanent part of L */
		for (k = 0 ; k < n ; k++)
		{
		    Lparent [k] = Parent [k] ;
		}
	    }
	}

	/* ------------------------------------------------------------------ */
	/* determine if METIS is to be skipped */
	/* ------------------------------------------------------------------ */

	if (default_strategy && ordering == CHOLMOD_AMD)
	{
	    if ((Common->fl < 500 * Common->lnz) ||
		(Common->lnz < 5 * Common->anz))
	    {
		/* AMD found an ordering with less than 500 flops per nonzero in
		 * L, or one with a fill-in ratio (nnz(L)/nnz(A)) of less than
		 * 5.  This is pretty good, and it's unlikely that METIS will do
		 * better (this heuristic is based on tests on all symmetric
		 * positive definite matrices in the UF sparse matrix
		 * collection, and it works well across a wide range of
		 * problems).  METIS can take much more time than AMD. */
		break ;
	    }
	}
    }

    /* turn error printing back on ] */
    Common->try_catch = FALSE ;

    /* ---------------------------------------------------------------------- */
    /* return if no ordering method succeeded */
    /* ---------------------------------------------------------------------- */

    if (Common->selected == EMPTY)
    {
	/* All methods failed.  
	 * If two or more methods failed, they may have failed for different
	 * reasons.  Both would clear Common->status and skip to the next
	 * method.  Common->status needs to be restored here to the worst error
	 * obtained in any of the methods.  CHOLMOD_INVALID is worse
	 * than CHOLMOD_OUT_OF_MEMORY, since the former implies something may
	 * be wrong with the user's input.  CHOLMOD_OUT_OF_MEMORY is simply an
	 * indication of lack of resources. */
	ASSERT (status < CHOLMOD_OK) ;
	ERROR (status, "all methods failed") ;
	FREE_WORKSPACE_AND_RETURN ;
    }

    /* ---------------------------------------------------------------------- */
    /* do the analysis for AMD, if skipped */
    /* ---------------------------------------------------------------------- */

    Common->fl  = Common->method [Common->selected].fl  ;
    Common->lnz = Common->method [Common->selected].lnz ;
    ASSERT (Common->lnz >= 0) ;

    if (skip_best)
    {
	if (!CHOLMOD(analyze_ordering) (A, L->ordering, Lperm, fset, fsize,
		Lparent, Post, Lcolcount, First, Level, Common))
	{
	    /* out of memory, or method failed */
	    FREE_WORKSPACE_AND_RETURN ;
	}
    }

    /* ---------------------------------------------------------------------- */
    /* postorder the etree, weighted by the column counts */
    /* ---------------------------------------------------------------------- */

    if (Common->postorder)
    {
	/* combine the fill-reducing ordering with the weighted postorder */
	/* workspace: Iwork (2*nrow) */
	if (CHOLMOD(postorder) (Lparent, n, Lcolcount, Post, Common) == n)
	{
	    /* use First and Level as workspace [ */
	    Int *Wi = First, *InvPost = Level ;
	    Int newchild, oldchild, newparent, oldparent ;

	    for (k = 0 ; k < n ; k++)
	    {
		Wi [k] = Lperm [Post [k]] ;
	    }
	    for (k = 0 ; k < n ; k++)
	    {
		Lperm [k] = Wi [k] ;
	    }

	    for (k = 0 ; k < n ; k++)
	    {
		Wi [k] = Lcolcount [Post [k]] ;
	    }
	    for (k = 0 ; k < n ; k++)
	    {
		Lcolcount [k] = Wi [k] ;
	    }
	    for (k = 0 ; k < n ; k++)
	    {
		InvPost [Post [k]] = k ;
	    }

	    /* updated Lparent needed only for supernodal case */
	    for (newchild = 0 ; newchild < n ; newchild++)
	    {
		oldchild = Post [newchild] ;
		oldparent = Lparent [oldchild] ;
		newparent = (oldparent == EMPTY) ? EMPTY : InvPost [oldparent] ;
		Wi [newchild] = newparent ;
	    }
	    for (k = 0 ; k < n ; k++)
	    {
		Lparent [k] = Wi [k] ;
	    }
	    /* done using Iwork as workspace ] */

	    /* L is now postordered, no longer in natural ordering */
	    if (L->ordering == CHOLMOD_NATURAL)
	    {
		L->ordering = CHOLMOD_POSTORDERED ;
	    }
	}
    }

    /* ---------------------------------------------------------------------- */
    /* supernodal analysis, if requested or if selected automatically */
    /* ---------------------------------------------------------------------- */

#ifndef NSUPERNODAL
    if (Common->supernodal > CHOLMOD_AUTO
    || (Common->supernodal == CHOLMOD_AUTO &&
	Common->lnz > 0 &&
	(Common->fl / Common->lnz) >= Common->supernodal_switch))
    {
	cholmod_sparse *S, *F, *A2, *A1 ;

	permute_matrices (A, L->ordering, Lperm, fset, fsize, TRUE,
		&A1, &A2, &S, &F, Common) ;

	/* workspace: Flag (nrow), Head (nrow), Iwork (5*nrow) */
	CHOLMOD(super_symbolic2) (for_cholesky, S, F, Lparent, L, Common) ;
	PRINT1 (("status %d\n", Common->status)) ;

	CHOLMOD(free_sparse) (&A1, Common) ;
	CHOLMOD(free_sparse) (&A2, Common) ;
    }
#endif

    /* ---------------------------------------------------------------------- */
    /* free temporary matrices and workspace, and return result L */
    /* ---------------------------------------------------------------------- */

    FREE_WORKSPACE_AND_RETURN ;
}
示例#23
0
cholmod_sparse *CHOLMOD(speye)
(
    /* ---- input ---- */
    size_t nrow,	/* # of rows of A */
    size_t ncol,	/* # of columns of A */
    int xtype,		/* CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX */
    /* --------------- */
    cholmod_common *Common
)
{
    double *Ax, *Az ;
    cholmod_sparse *A ;
    Int *Ap, *Ai ;
    Int j, n ;

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

    RETURN_IF_NULL_COMMON (NULL) ;
    Common->status = CHOLMOD_OK ;

    /* ---------------------------------------------------------------------- */
    /* allocate the matrix */
    /* ---------------------------------------------------------------------- */

    n = MIN (nrow, ncol) ;
    A = CHOLMOD(allocate_sparse) (nrow, ncol, n, TRUE, TRUE, 0, xtype,
	    Common) ;

    if (Common->status < CHOLMOD_OK)
    {
	return (NULL) ;	    /* out of memory or inputs invalid */
    }

    /* ---------------------------------------------------------------------- */
    /* create the identity matrix */
    /* ---------------------------------------------------------------------- */

    Ap = A->p ;
    Ai = A->i ;
    Ax = A->x ;
    Az = A->z ;

    for (j = 0 ; j < n ; j++)
    {
	Ap [j] = j ;
    }
    for (j = n ; j <= ((Int) ncol) ; j++)
    {
	Ap [j] = n ;
    }
    for (j = 0 ; j < n ; j++)
    {
	Ai [j] = j ;
    }

    switch (xtype)
    {
	case CHOLMOD_REAL:
	    for (j = 0 ; j < n ; j++)
	    {
		Ax [j] = 1 ;
	    }
	    break ;

	case CHOLMOD_COMPLEX:
	    for (j = 0 ; j < n ; j++)
	    {
		Ax [2*j  ] = 1 ;
		Ax [2*j+1] = 0 ;
	    }
	    break ;

	case CHOLMOD_ZOMPLEX:
	    for (j = 0 ; j < n ; j++)
	    {
		Ax [j] = 1 ;
	    }
	    for (j = 0 ; j < n ; j++)
	    {
		Az [j] = 0 ;
	    }
	    break ;
    }

    return (A) ;
}
示例#24
0
cholmod_sparse *CHOLMOD(horzcat)
(
    /* ---- input ---- */
    cholmod_sparse *A,	/* left matrix to concatenate */
    cholmod_sparse *B,	/* right matrix to concatenate */
    int values,		/* if TRUE compute the numerical values of C */
    /* --------------- */
    cholmod_common *Common
)
{
    double *Ax, *Bx, *Cx ;
    Int *Ap, *Ai, *Anz, *Bp, *Bi, *Bnz, *Cp, *Ci ;
    cholmod_sparse *C, *A2, *B2 ;
    Int apacked, bpacked, ancol, bncol, ncol, nrow, anz, bnz, nz, j, p, pend,
	pdest ;

    /* ---------------------------------------------------------------------- */
    /* check inputs */
    /* ---------------------------------------------------------------------- */

    RETURN_IF_NULL_COMMON (NULL) ;
    RETURN_IF_NULL (A, NULL) ;
    RETURN_IF_NULL (B, NULL) ;
    values = values &&
	(A->xtype != CHOLMOD_PATTERN) && (B->xtype != CHOLMOD_PATTERN) ;
    RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN,
	    values ? CHOLMOD_REAL : CHOLMOD_ZOMPLEX, NULL) ;
    RETURN_IF_XTYPE_INVALID (B, CHOLMOD_PATTERN,
	    values ? CHOLMOD_REAL : CHOLMOD_ZOMPLEX, NULL) ;
    if (A->nrow != B->nrow)
    {
	/* A and B must have the same number of rows */
	ERROR (CHOLMOD_INVALID, "A and B must have same # rows") ;
	return (NULL) ;
    }
    /* A and B must have the same numerical type if values is TRUE (both must
     * be CHOLMOD_REAL, this is implicitly checked above) */

    Common->status = CHOLMOD_OK ;

    /* ---------------------------------------------------------------------- */
    /* allocate workspace */
    /* ---------------------------------------------------------------------- */

    ancol = A->ncol ;
    bncol = B->ncol ;
    nrow = A->nrow ;
    CHOLMOD(allocate_work) (0, MAX3 (nrow, ancol, bncol), 0, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	/* out of memory */
	return (NULL) ;
    }

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

    /* convert A to unsymmetric, if necessary */
    A2 = NULL ;
    if (A->stype != 0)
    {
	/* workspace: Iwork (max (A->nrow,A->ncol)) */
	A2 = CHOLMOD(copy) (A, 0, values, Common) ;
	if (Common->status < CHOLMOD_OK)
	{
	    /* out of memory */
	    return (NULL) ;
	}
	A = A2 ;
    }

    /* convert B to unsymmetric, if necessary */
    B2 = NULL ;
    if (B->stype != 0)
    {
	/* workspace: Iwork (max (B->nrow,B->ncol)) */
	B2 = CHOLMOD(copy) (B, 0, values, Common) ;
	if (Common->status < CHOLMOD_OK)
	{
	    /* out of memory */
	    CHOLMOD(free_sparse) (&A2, Common) ;
	    return (NULL) ;
	}
	B = B2 ;
    }

    Ap  = A->p ;
    Anz = A->nz ;
    Ai  = A->i ;
    Ax  = A->x ;
    apacked = A->packed ;

    Bp  = B->p ;
    Bnz = B->nz ;
    Bi  = B->i ;
    Bx  = B->x ;
    bpacked = B->packed ;

    /* ---------------------------------------------------------------------- */
    /* allocate C */
    /* ---------------------------------------------------------------------- */

    anz = CHOLMOD(nnz) (A, Common) ;
    bnz = CHOLMOD(nnz) (B, Common) ;
    ncol = ancol + bncol ;
    nz = anz + bnz ;

    C = CHOLMOD(allocate_sparse) (nrow, ncol, nz, A->sorted && B->sorted, TRUE,
	    0, values ? A->xtype : CHOLMOD_PATTERN, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	/* out of memory */
	CHOLMOD(free_sparse) (&A2, Common) ;
	CHOLMOD(free_sparse) (&B2, Common) ;
	return (NULL) ;
    }
    Cp = C->p ;
    Ci = C->i ;
    Cx = C->x ;

    /* ---------------------------------------------------------------------- */
    /* C = [A , B] */
    /* ---------------------------------------------------------------------- */

    pdest = 0 ;

    /* copy A as the first A->ncol columns of C */
    for (j = 0 ; j < ancol ; j++)
    {
	/* A(:,j) is the jth column of C */
	p = Ap [j] ;
	pend = (apacked) ? (Ap [j+1]) : (p + Anz [j]) ;
	Cp [j] = pdest ;
	for ( ; p < pend ; p++)
	{
	    Ci [pdest] = Ai [p] ;
	    if (values) Cx [pdest] = Ax [p] ;
	    pdest++ ;
	}
    }

    /* copy B as the next B->ncol columns of C */
    for (j = 0 ; j < bncol ; j++)
    {
	/* B(:,j) is the (ancol+j)th column of C */
	p = Bp [j] ;
	pend = (bpacked) ? (Bp [j+1]) : (p + Bnz [j]) ;
	Cp [ancol + j] = pdest ;
	for ( ; p < pend ; p++)
	{
	    Ci [pdest] = Bi [p] ;
	    if (values) Cx [pdest] = Bx [p] ;
	    pdest++ ;
	}
    }
    Cp [ncol] = pdest ;
    ASSERT (pdest == anz + bnz) ;

    /* ---------------------------------------------------------------------- */
    /* free the unsymmetric copies of A and B, and return C */
    /* ---------------------------------------------------------------------- */

    CHOLMOD(free_sparse) (&A2, Common) ;
    CHOLMOD(free_sparse) (&B2, Common) ;
    return (C) ;
}
示例#25
0
cholmod_sparse *CHOLMOD(allocate_sparse)
(
    /* ---- input ---- */
    size_t nrow,	/* # of rows of A */
    size_t ncol,	/* # of columns of A */
    size_t nzmax,	/* max # of nonzeros of A */
    int sorted,		/* TRUE if columns of A sorted, FALSE otherwise */
    int packed,		/* TRUE if A will be packed, FALSE otherwise */
    int stype,		/* stype of A */
    int xtype,		/* CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX */
    /* --------------- */
    cholmod_common *Common
)
{
    cholmod_sparse *A ;
    Int *Ap, *Anz ;
    size_t nzmax0 ;
    Int j ;
    int ok = TRUE ;

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

    RETURN_IF_NULL_COMMON (NULL) ;
    if (stype != 0 && nrow != ncol)
    {
	ERROR (CHOLMOD_INVALID, "rectangular matrix with stype != 0 invalid") ;
	return (NULL) ;
    }
    if (xtype < CHOLMOD_PATTERN || xtype > CHOLMOD_ZOMPLEX)
    {
	ERROR (CHOLMOD_INVALID, "xtype invalid") ;
	return (NULL) ;
    }
    /* ensure the dimensions do not cause integer overflow */
    (void) CHOLMOD(add_size_t) (ncol, 2, &ok) ;
    if (!ok || nrow > Int_max || ncol > Int_max || nzmax > Int_max)
    {
	ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
	return (NULL) ;
    }
    Common->status = CHOLMOD_OK ;

    /* ---------------------------------------------------------------------- */
    /* allocate header */
    /* ---------------------------------------------------------------------- */

    A = CHOLMOD(malloc) (sizeof (cholmod_sparse), 1, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	return (NULL) ;	    /* out of memory */
    }
    PRINT1 (("cholmod_allocate_sparse %d-by-%d nzmax %d sorted %d packed %d"
		" xtype %d\n", nrow, ncol, nzmax, sorted, packed, xtype)) ;

    nzmax = MAX (1, nzmax) ;

    A->nrow = nrow ;
    A->ncol = ncol ;
    A->nzmax = nzmax ;
    A->packed = packed ;    /* default is packed (A->nz not present) */
    A->stype = stype ;
    A->itype = ITYPE ;
    A->xtype = xtype ;
    A->dtype = DTYPE ;

    A->nz = NULL ;
    A->p = NULL ;
    A->i = NULL ;
    A->x = NULL ;
    A->z = NULL ;

    /* A 1-by-m matrix always has sorted columns */
    A->sorted = (nrow <= 1) ? TRUE : sorted ;

    /* ---------------------------------------------------------------------- */
    /* allocate the matrix itself */
    /* ---------------------------------------------------------------------- */

    /* allocate O(ncol) space */
    A->p = CHOLMOD(malloc) (((size_t) ncol)+1, sizeof (Int), Common) ;
    if (!packed)
    {
	A->nz = CHOLMOD(malloc) (ncol, sizeof (Int), Common) ;
    }

    /* allocate O(nz) space */
    nzmax0 = 0 ;
    CHOLMOD(realloc_multiple) (nzmax, 1, xtype, &(A->i), NULL, &(A->x), &(A->z),
	    &nzmax0, Common) ;

    if (Common->status < CHOLMOD_OK)
    {
	CHOLMOD(free_sparse) (&A, Common) ;
	return (NULL) ;	    /* out of memory */
    }

    /* ---------------------------------------------------------------------- */
    /* initialize A->p and A->nz so that A is an empty matrix */
    /* ---------------------------------------------------------------------- */

    Ap = A->p ;
    for (j = 0 ; j <= (Int) ncol ; j++)
    {
	Ap [j] = 0 ;
    }
    if (!packed)
    {
	Anz = A->nz ;
	for (j = 0 ; j < (Int) ncol ; j++)
	{
	    Anz [j] = 0 ;
	}
    }
    return (A) ;
}
static void NUMERIC (WDIM, r)
(
    int update,		/* TRUE for update, FALSE for downdate */
    cholmod_sparse *C,	/* in packed or unpacked, and sorted form */
			/* no empty columns */
    Int rank,		/* rank of the update/downdate */
    cholmod_factor *L,	/* with unit diagonal (diagonal not stored) */
			/* temporary workspaces: */
    double W [ ],	/* n-by-WDIM dense matrix, initially zero */
    Path_type Path [ ],
    Int npaths,
    Int mask [ ],	/* size n */
    Int maskmark,
    cholmod_common *Common
)
{
    double Alpha [8] ;
    double *Cx, *Wpath, *W1, *a ;
    Int i, j, p, ccol, pend, wfirst, e, path, packed ;
    Int *Ci, *Cp, *Cnz ;

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

    Ci = C->i ;
    Cx = C->x ;
    Cp = C->p ;
    Cnz = C->nz ;
    packed = C->packed ;
    ASSERT (IMPLIES (!packed, Cnz != NULL)) ;
    ASSERT (L->n == C->nrow) ;
    DEBUG (CHOLMOD(dump_real) ("num_d: in W:", W, WDIM, L->n, FALSE, 1,Common));

    /* ---------------------------------------------------------------------- */
    /* scatter C into W */
    /* ---------------------------------------------------------------------- */

    for (path = 0 ; path < rank ; path++)
    {
	/* W (:, path) = C (:, Path [path].col) */
	ccol = Path [path].ccol ;
	Wpath = W + path ;
	PRINT1 (("Ordered Columns [path = "ID"] = "ID"\n", path, ccol)) ;
	p = Cp [ccol] ;
	pend = (packed) ? (Cp [ccol+1]) : (p + Cnz [ccol]) ;
	/* column C can be empty */
	for ( ; p < pend ; p++)
	{
	    i = Ci [p] ;
	    ASSERT (i >= 0 && i < (Int) (C->nrow)) ;
	    if (mask == NULL || mask [i] < maskmark)
	    {
		Wpath [WDIM * i] = Cx [p] ;
	    }
	    PRINT1 (("    row "ID" : %g mask "ID"\n", i, Cx [p],
		    (mask) ? mask [i] : 0)) ;
	}
	Alpha [path] = 1.0 ;
    }
    DEBUG (CHOLMOD(dump_real) ("num_d: W:", W, WDIM, L->n, FALSE, 1,Common)) ;

    /* ---------------------------------------------------------------------- */
    /* numeric update/downdate of the paths */
    /* ---------------------------------------------------------------------- */

    /* for each disjoint subpath in Tbar in DFS order do */
    for (path = rank ; path < npaths ; path++)
    {

	/* determine which columns of W to use */
	wfirst = Path [path].wfirst ;
	e = Path [path].end ;
	j = Path [path].start ;
	ASSERT (e >= 0 && e < (Int) (L->n)) ;
	ASSERT (j >= 0 && j < (Int) (L->n)) ;

	W1 = W + wfirst ;	/* pointer to row 0, column wfirst of W */
	a = Alpha + wfirst ;	/* pointer to Alpha [wfirst] */

	PRINT1 (("Numerical update/downdate of path "ID"\n", path)) ;
	PRINT1 (("start "ID" end "ID" wfirst "ID" rank "ID" ccol "ID"\n", j, e,
		wfirst, Path [path].rank, Path [path].ccol)) ;

#if WDIM == 1
	NUMERIC (WDIM,1) (update, j, e, a, W1, L, Common) ;
#else

	switch (Path [path].rank)
	{
	    case 1:
		NUMERIC (WDIM,1) (update, j, e, a, W1, L, Common) ;
		break ;

#if WDIM >= 2
	    case 2:
		NUMERIC (WDIM,2) (update, j, e, a, W1, L, Common) ;
		break ;
#endif

#if WDIM >= 4
	    case 3:
		NUMERIC (WDIM,3) (update, j, e, a, W1, L, Common) ;
		break ;
	    case 4:
		NUMERIC (WDIM,4) (update, j, e, a, W1, L, Common) ;
		break ;
#endif

#if WDIM == 8
	    case 5:
		NUMERIC (WDIM,5) (update, j, e, a, W1, L, Common) ;
		break ;
	    case 6:
		NUMERIC (WDIM,6) (update, j, e, a, W1, L, Common) ;
		break ;
	    case 7:
		NUMERIC (WDIM,7) (update, j, e, a, W1, L, Common) ;
		break ;
	    case 8:
		NUMERIC (WDIM,8) (update, j, e, a, W1, L, Common) ;
		break ;
#endif

	}
#endif

    }
}
示例#27
0
int CHOLMOD(row_subtree)
(
    /* ---- input ---- */
    cholmod_sparse *A,	/* matrix to analyze */
    cholmod_sparse *F,	/* used for A*A' case only. F=A' or A(:,f)' */
    size_t krow,	/* row k of L */
    Int *Parent,	/* elimination tree */
    /* ---- output --- */
    cholmod_sparse *R,	/* pattern of L(k,:), 1-by-n with R->nzmax >= n */
    /* --------------- */
    cholmod_common *Common
)
{
    Int *Rp, *Stack, *Flag, *Ap, *Ai, *Anz, *Fp, *Fi, *Fnz ;
    Int p, pend, parent, t, stype, nrow, k, pf, pfend, Fpacked, packed,
	sorted, top, len, i, mark ;

    /* ---------------------------------------------------------------------- */
    /* check inputs */
    /* ---------------------------------------------------------------------- */

    RETURN_IF_NULL_COMMON (FALSE) ;
    RETURN_IF_NULL (A, FALSE) ;
    RETURN_IF_NULL (R, FALSE) ;
    RETURN_IF_NULL (Parent, FALSE) ;
    RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ;
    RETURN_IF_XTYPE_INVALID (R, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ;
    stype = A->stype ;
    if (stype == 0)
    {
	RETURN_IF_NULL (F, FALSE) ;
	RETURN_IF_XTYPE_INVALID (F, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ;
    }
    if (krow >= A->nrow)
    {
	ERROR (CHOLMOD_INVALID, "subtree: k invalid") ;
	return (FALSE) ;
    }
    if (R->ncol != 1 || A->nrow != R->nrow || A->nrow > R->nzmax)
    {
	ERROR (CHOLMOD_INVALID, "subtree: R invalid") ;
	return (FALSE) ;
    }
    Common->status = CHOLMOD_OK ;

    /* ---------------------------------------------------------------------- */
    /* allocate workspace */
    /* ---------------------------------------------------------------------- */

    nrow = A->nrow ;
    CHOLMOD(allocate_work) (nrow, 0, 0, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	return (FALSE) ;
    }
    ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, Common)) ;

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

    if (stype > 0)
    {
	/* symmetric upper case: F is not needed.  It may be NULL */
	Fp = NULL ;
	Fi = NULL ;
	Fnz = NULL ;
	Fpacked = TRUE ;
    }
    else if (stype == 0)
    {
	/* unsymmetric case: F is required. */
	Fp = F->p ;
	Fi = F->i ;
	Fnz = F->nz ;
	Fpacked = F->packed ;
    }
    else
    {
	/* symmetric lower triangular form not supported */
	ERROR (CHOLMOD_INVALID, "symmetric lower not supported") ;
	return (FALSE) ;
    }

    Ap = A->p ;
    Ai = A->i ;
    Anz = A->nz ;
    packed = A->packed ;
    sorted = A->sorted ;

    k = krow ;
    Stack = R->i ;

    /* ---------------------------------------------------------------------- */
    /* get workspace */
    /* ---------------------------------------------------------------------- */

    Flag = Common->Flag ;	/* size nrow, Flag [i] < mark must hold */
    /* mark = CHOLMOD(clear_flag) (Common) ; */
    CHOLMOD_CLEAR_FLAG (Common) ;
    mark = Common->mark ;

    /* ---------------------------------------------------------------------- */
    /* compute the pattern of L(k,:) */
    /* ---------------------------------------------------------------------- */

    top = nrow ;		/* Stack is empty */
    Flag [k] = mark ;		/* do not include diagonal entry in Stack */

#define SCATTER			/* do not scatter numerical values */
#define PARENT(i) Parent [i]	/* use Parent for etree */

    if (stype != 0)
    {
	/* scatter kth col of triu (A), get pattern L(k,:) */
	p = Ap [k] ;
	pend = (packed) ? (Ap [k+1]) : (p + Anz [k]) ;
	SUBTREE ;
    }
    else
    {
	/* scatter kth col of triu (beta*I+AA'), get pattern L(k,:) */
	pf = Fp [k] ;
	pfend = (Fpacked) ? (Fp [k+1]) : (pf + Fnz [k]) ;
	for ( ; pf < pfend ; pf++)
	{
	    /* get nonzero entry F (t,k) */
	    t = Fi [pf] ;
	    p = Ap [t] ;
	    pend = (packed) ? (Ap [t+1]) : (p + Anz [t]) ;
	    SUBTREE ;
	}
    }

#undef SCATTER
#undef PARENT

    /* shift the stack upwards, to the first part of R */
    len = nrow - top ;
    for (i = 0 ; i < len ; i++)
    {
	Stack [i] = Stack [top + i] ;
    }

    Rp = R->p ;
    Rp [0] = 0 ;
    Rp [1] = len ;
    R->sorted = FALSE ;

    CHOLMOD(clear_flag) (Common) ;
    ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, Common)) ;
    return (TRUE) ;
}
示例#28
0
void amdtest (cholmod_sparse *A)
{
    double Control [AMD_CONTROL], Info [AMD_INFO], alpha ;
    Int *P, *Cp, *Ci, *Sp, *Si, *Bp, *Bi, *Ep, *Ei, *Fp, *Fi,
	*Len, *Nv, *Next, *Head, *Elen, *Deg, *Wi, *W, *Flag ;
    cholmod_sparse *C, *B, *S, *E, *F ;
    Int i, j, n, nrow, ncol, ok, cnz, bnz, p, trial, sorted ;

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

    printf ("\nAMD 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 AMD_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) ;
    AMD_preprocess (n, Bp, Bi, Sp, Si, W, Flag) ;

    /* ---------------------------------------------------------------------- */
    /* allocate workspace for amd */
    /* ---------------------------------------------------------------------- */

    P = CHOLMOD(malloc) (n+1, sizeof (Int), cm) ;

    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, sizeof (Int), cm) ;

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

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

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

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

	/* ------------------------------------------------------------------ */
	/* order C with AMD_order */
	/* ------------------------------------------------------------------ */

	AMD_defaults (Control) ;
	AMD_defaults (NULL) ;
	AMD_control (Control) ;
	AMD_control (NULL) ;
	AMD_info (NULL) ;

	ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	printf ("amd return value: "ID"\n", ok) ;
	AMD_info (Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "AMD permutation", cm)) ;

	/* no dense rows/cols */
	alpha = Control [AMD_DENSE] ;
	Control [AMD_DENSE] = -1 ;
	AMD_control (Control) ;
	ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	printf ("amd return value: "ID"\n", ok) ;
	AMD_info (Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "AMD permutation (alpha=-1)", cm)) ;

	/* many dense rows/cols */
	Control [AMD_DENSE] = 0 ;
	AMD_control (Control) ;
	ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	printf ("amd return value: "ID"\n", ok) ;
	AMD_info (Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "AMD permutation (alpha=0)", cm)) ;
	Control [AMD_DENSE] = alpha ;

	/* no aggressive absorption */
	Control [AMD_AGGRESSIVE] = FALSE ;
	AMD_control (Control) ;
	ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	printf ("amd return value: "ID"\n", ok) ;
	AMD_info (Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "AMD permutation (no agg) ", cm)) ;
	Control [AMD_AGGRESSIVE] = TRUE ;

	/* ------------------------------------------------------------------ */
	/* order F with AMD_order */
	/* ------------------------------------------------------------------ */

	Fp = F->p ;
	Fi = F->i ;
	ok = AMD_order (n, Fp, Fi, P, Control, Info) ;
	printf ("amd return value: "ID"\n", ok) ;
	AMD_info (Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "F: AMD permutation", cm)) ;

	/* ------------------------------------------------------------------ */
	/* order S with AMD_order */
	/* ------------------------------------------------------------------ */

	ok = AMD_order (n, Sp, Si, P, Control, Info) ;
	printf ("amd return value: "ID"\n", ok) ;
	AMD_info (Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	OK (CHOLMOD(print_perm) (P, n, n, "AMD permutation", cm)) ;

	/* ------------------------------------------------------------------ */
	/* order E with AMD_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 AMD_2:\n") ;
	if (n > 0)
	{
	    AMD_2 (n, Ep, Ei, Len, E->nzmax, Ep [n], Nv, Next, P, Head, Elen,
		Deg, Wi, Control, Info) ;
	    AMD_info (Info) ;
	    OK (CHOLMOD(print_perm) (P, n, n, "AMD2 permutation", cm)) ;
	}

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

	ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	ok = AMD_order (-1, Cp, Ci, P, Control, Info) ;
	OK (ok == AMD_INVALID);
	ok = AMD_order (0, Cp, Ci, P, Control, Info) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	ok = AMD_order (n, NULL, Ci, P, Control, Info) ;
	OK (ok == AMD_INVALID);
	ok = AMD_order (n, Cp, NULL, P, Control, Info) ;
	OK (ok == AMD_INVALID);
	ok = AMD_order (n, Cp, Ci, NULL, Control, Info) ;
	OK (ok == AMD_INVALID);

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

	    p = Cp [n] ;
	    Cp [n] = -1 ;
	    ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	    OK (ok == AMD_INVALID) ;

	    if (Size_max/2 == Int_max)
	    {
		Cp [n] = Int_max ;
		ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
		printf ("AMD status is "ID"\n", ok) ;
		OK (ok == AMD_OUT_OF_MEMORY) ;
	    }

	    Cp [n] = p ;
	    ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	    OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	    if (Cp [n] > 0)
	    {
		printf ("Mangle column zero:\n") ;
		i = Ci [0] ;
		Ci [0] = -1 ;
		ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
		AMD_info (Info) ;
		OK (ok == AMD_INVALID) ;
		Ci [0] = i ;
	    }
	}

	ok = AMD_valid (n, n, Sp, Si) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	ok = AMD_valid (-1, n, Sp, Si) ;	    OK (ok == AMD_INVALID) ;
	ok = AMD_valid (n, -1, Sp, Si) ;	    OK (ok == AMD_INVALID) ;
	ok = AMD_valid (n, n, NULL, Si) ;	    OK (ok == AMD_INVALID) ;
	ok = AMD_valid (n, n, Sp, NULL) ;	    OK (ok == AMD_INVALID) ;

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

	    p = Sp [n] ;
	    Sp [n] = -1 ;
	    ok = AMD_valid (n, n, Sp, Si) ; OK (ok == AMD_INVALID) ;
	    Sp [n] = p ;

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

	    p = Sp [1] ;
	    Sp [1] = -1 ;
	    ok = AMD_valid (n, n, Sp, Si) ; OK (ok == AMD_INVALID) ;
	    Sp [1] = p ;

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

	}

	ok = AMD_valid (n, n, Sp, Si) ;
	OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;
	AMD_preprocess (n, Bp, Bi, Sp, Si, W, Flag) ;
	ok = AMD_valid (n, n, Sp, Si) ;
	OK (ok == AMD_OK) ;

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

	    p = Bp [n] ;
	    Bp [n] = -1 ;
	    ok = AMD_valid (n, n, Bp, Bi) ;	    OK (ok == AMD_INVALID) ;
	    Bp [n] = p ;


	    p = Bp [1] ;
	    Bp [1] = -1 ;
	    ok = AMD_valid (n, n, Bp, Bi) ;	    OK (ok == AMD_INVALID) ;
	    Bp [1] = p ;

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

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

	Info [AMD_STATUS] = 777 ;
	AMD_info (Info) ;

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

	if (n > 0)
	{

	    normal_memory_handler ( ) ;

	    ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
	    OK (sorted ? (ok == AMD_OK) : (ok >= AMD_OK)) ;

	    test_memory_handler ( ) ;

	    for (trial = 0 ; trial < 6 ; trial++)
	    {
		my_tries = trial ;
		printf ("AMD memory trial "ID"\n", trial) ;
		ok = AMD_order (n, Cp, Ci, P, Control, Info) ;
		AMD_info (Info) ;
		OK (ok == AMD_OUT_OF_MEMORY
		    || (sorted ? (ok == AMD_OK) : (ok >= AMD_OK))) ;
	    }
	    normal_memory_handler ( ) ;
	    OK (CHOLMOD(print_perm) (P, n, n, "AMD2 permutation", cm)) ;

	}

	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, sizeof (Int), Wi,   cm) ;

    CHOLMOD(free) (n+1, sizeof (Int), P, 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) ;
}
示例#29
0
int CHOLMOD(rowfac_mask)
(
    /* ---- input ---- */
    cholmod_sparse *A,	/* matrix to factorize */
    cholmod_sparse *F,	/* used for A*A' case only. F=A' or A(:,f)' */
    double beta [2],	/* factorize beta*I+A or beta*I+AA' */
    size_t kstart,	/* first row to factorize */
    size_t kend,	/* last row to factorize is kend-1 */
    Int *mask,		/* size A->nrow. if mask[i] >= 0 row i is set to zero */
    Int *RLinkUp,	/* size A->nrow. link list of rows to compute */
    /* ---- in/out --- */
    cholmod_factor *L,
    /* --------------- */
    cholmod_common *Common
)
{
    Int n ;
    size_t s ;
    int ok = TRUE ;

    /* ---------------------------------------------------------------------- */
    /* check inputs */
    /* ---------------------------------------------------------------------- */

    RETURN_IF_NULL_COMMON (FALSE) ;
    RETURN_IF_NULL (A, FALSE) ;
    RETURN_IF_NULL (L, FALSE) ;
    RETURN_IF_XTYPE_INVALID (A, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ;
    RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ;
    if (L->xtype != CHOLMOD_PATTERN && A->xtype != L->xtype)
    {
	ERROR (CHOLMOD_INVALID, "xtype of A and L do not match") ;
	return (FALSE) ;
    }
    if (L->is_super)
    {
	ERROR (CHOLMOD_INVALID, "can only do simplicial factorization");
	return (FALSE) ;
    }
    if (A->stype == 0)
    {
	RETURN_IF_NULL (F, FALSE) ;
	if (A->xtype != F->xtype)
	{
	    ERROR (CHOLMOD_INVALID, "xtype of A and F do not match") ;
	    return (FALSE) ;
	}
    }
    if (A->stype < 0)
    {
	/* symmetric lower triangular form not supported */
	ERROR (CHOLMOD_INVALID, "symmetric lower not supported") ;
	return (FALSE) ;
    }
    if (kend > L->n)
    {
	ERROR (CHOLMOD_INVALID, "kend invalid") ;
	return (FALSE) ;
    }
    if (A->nrow != L->n)
    {
	ERROR (CHOLMOD_INVALID, "dimensions of A and L do not match") ;
	return (FALSE) ;
    }
    Common->status = CHOLMOD_OK ;
    Common->rowfacfl = 0 ;

    /* ---------------------------------------------------------------------- */
    /* allocate workspace */
    /* ---------------------------------------------------------------------- */

    /* Xwork is of size n for the real case, 2*n for complex/zomplex */
    n = L->n  ;

    /* s = ((A->xtype != CHOLMOD_REAL) ? 2:1)*n */
    s = CHOLMOD(mult_size_t) (n, ((A->xtype != CHOLMOD_REAL) ? 2:1), &ok) ;
    if (!ok)
    {
	ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
	return (FALSE) ;
    }

    CHOLMOD(allocate_work) (n, n, s, Common) ;
    if (Common->status < CHOLMOD_OK)
    {
	return (FALSE) ;
    }
    ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, A->nrow, Common)) ;

    /* ---------------------------------------------------------------------- */
    /* factorize the matrix, using template routine */
    /* ---------------------------------------------------------------------- */

    if (RLinkUp == NULL)
    {

	switch (A->xtype)
	{
	    case CHOLMOD_REAL:
		ok = r_cholmod_rowfac (A, F, beta, kstart, kend, L, Common) ;
		break ;

	    case CHOLMOD_COMPLEX:
		ok = c_cholmod_rowfac (A, F, beta, kstart, kend, L, Common) ;
		break ;

	    case CHOLMOD_ZOMPLEX:
		ok = z_cholmod_rowfac (A, F, beta, kstart, kend, L, Common) ;
		break ;
	}

    }
    else
    {

	switch (A->xtype)
	{
	    case CHOLMOD_REAL:
		ok = r_cholmod_rowfac_mask (A, F, beta, kstart, kend,
		    mask, RLinkUp, L, Common) ;
		break ;

	    case CHOLMOD_COMPLEX:
		ok = c_cholmod_rowfac_mask (A, F, beta, kstart, kend,
		    mask, RLinkUp, L, Common) ;
		break ;

	    case CHOLMOD_ZOMPLEX:
		ok = z_cholmod_rowfac_mask (A, F, beta, kstart, kend,
		    mask, RLinkUp, L, Common) ;
		break ;
	}
    }

    return (ok) ;
}
示例#30
0
int CHOLMOD(reallocate_column)
(
    /* ---- input ---- */
    size_t j,		/* the column to reallocate */
    size_t need,	/* required size of column j */
    /* ---- in/out --- */
    cholmod_factor *L,	/* factor to modify */
    /* --------------- */
    cholmod_common *Common
)
{
    double xneed ;
    double *Lx, *Lz ;
    Int *Lp, *Lprev, *Lnext, *Li, *Lnz ;
    Int n, pold, pnew, len, k, tail ;

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

    RETURN_IF_NULL_COMMON (FALSE) ;
    RETURN_IF_NULL (L, FALSE) ;
    RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ;
    if (L->is_super)
    {
	ERROR (CHOLMOD_INVALID, "L must be simplicial") ;
	return (FALSE) ;
    }
    n = L->n ;
    if (j >= L->n || need == 0)
    {
	ERROR (CHOLMOD_INVALID, "j invalid") ;
	return (FALSE) ;	    /* j out of range */
    }
    Common->status = CHOLMOD_OK ;

    DEBUG (CHOLMOD(dump_factor) (L, "start colrealloc", Common)) ;

    /* ---------------------------------------------------------------------- */
    /* increase the size of L if needed */
    /* ---------------------------------------------------------------------- */

    /* head = n+1 ; */
    tail = n ;
    Lp = L->p ;
    Lnz = L->nz ;
    Lprev = L->prev ;
    Lnext = L->next ;

    ASSERT (Lnz != NULL) ;
    ASSERT (Lnext != NULL && Lprev != NULL) ;
    PRINT1 (("col %g need %g\n", (double) j, (double) need)) ;

    /* column j cannot have more than n-j entries if all entries are present */
    need = MIN (need, n-j) ;

    /* compute need in double to avoid integer overflow */
    if (Common->grow1 >= 1.0)
    {
	xneed = (double) need ;
	xneed = Common->grow1 * xneed + Common->grow2 ;
	xneed = MIN (xneed, n-j) ;
	need = (Int) xneed ;
    }
    PRINT1 (("really new need %g current %g\n", (double) need,
	    (double) (Lp [Lnext [j]] - Lp [j]))) ;
    ASSERT (need >= 1 && need <= n-j) ;

    if (Lp [Lnext [j]] - Lp [j] >= (Int) need)
    {
	/* no need to reallocate the column, it's already big enough */
	PRINT1 (("colrealloc: quick return %g %g\n",
	    (double) (Lp [Lnext [j]] - Lp [j]), (double) need)) ;
	return (TRUE) ;

    }

    if (Lp [tail] + need > L->nzmax)
    {
	/* use double to avoid integer overflow */
	xneed = (double) need ;
	if (Common->grow0 < 1.2)	    /* fl. pt. compare, false if NaN */
	{
	    /* if grow0 is less than 1.2 or NaN, don't use it */
	    xneed = 1.2 * (((double) L->nzmax) + xneed + 1) ;
	}
	else
	{
	    xneed = Common->grow0 * (((double) L->nzmax) + xneed + 1) ;
	}
	if (xneed > Size_max ||
		!CHOLMOD(reallocate_factor) ((Int) xneed, L, Common))
	{
	    /* out of memory, convert to simplicial symbolic */
	    CHOLMOD(change_factor) (CHOLMOD_PATTERN, L->is_ll, FALSE, TRUE,
		    TRUE, L, Common) ;
	    ERROR (CHOLMOD_OUT_OF_MEMORY, "out of memory; L now symbolic") ;
	    return (FALSE) ;	    /* out of memory */
	}
	PRINT1 (("\n=== GROW L from %g to %g\n",
		    (double) L->nzmax, (double) xneed)) ;
	/* pack all columns so that each column has at most grow2 free space */
	CHOLMOD(pack_factor) (L, Common) ;
	ASSERT (Common->status == CHOLMOD_OK) ;
	Common->nrealloc_factor++ ;
    }

    /* ---------------------------------------------------------------------- */
    /* reallocate the column */
    /* ---------------------------------------------------------------------- */

    Common->nrealloc_col++ ;

    Li = L->i ;
    Lx = L->x ;
    Lz = L->z ;

    /* remove j from its current position in the list */
    Lnext [Lprev [j]] = Lnext [j] ;
    Lprev [Lnext [j]] = Lprev [j] ;

    /* place j at the end of the list */
    Lnext [Lprev [tail]] = j ;
    Lprev [j] = Lprev [tail] ;
    Lnext [j] = n ;
    Lprev [tail] = j ;

    /* L is no longer monotonic; columns are out-of-order */
    L->is_monotonic = FALSE ;

    /* allocate space for column j */
    pold = Lp [j] ;
    pnew = Lp [tail] ;
    Lp [j] = pnew  ;
    Lp [tail] += need ;

    /* copy column j to the new space */
    len = Lnz [j] ;
    for (k = 0 ; k < len ; k++)
    {
	Li [pnew + k] = Li [pold + k] ;
    }

    if (L->xtype == CHOLMOD_REAL)
    {
	for (k = 0 ; k < len ; k++)
	{
	    Lx [pnew + k] = Lx [pold + k] ;
	}
    }
    else if (L->xtype == CHOLMOD_COMPLEX)
    {
	for (k = 0 ; k < len ; k++)
	{
	    Lx [2*(pnew + k)  ] = Lx [2*(pold + k)  ] ;
	    Lx [2*(pnew + k)+1] = Lx [2*(pold + k)+1] ;
	}
    }
    else if (L->xtype == CHOLMOD_ZOMPLEX)
    {
	for (k = 0 ; k < len ; k++)
	{
	    Lx [pnew + k] = Lx [pold + k] ;
	    Lz [pnew + k] = Lz [pold + k] ;
	}
    }

    DEBUG (CHOLMOD(dump_factor) (L, "colrealloc done", Common)) ;

    /* successful reallocation of column j of L */
    return (TRUE) ;
}