673 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			673 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
/* ========================================================================== */
 | 
						|
/* === Core/cholmod_common ================================================== */
 | 
						|
/* ========================================================================== */
 | 
						|
 | 
						|
/* -----------------------------------------------------------------------------
 | 
						|
 * CHOLMOD/Core Module.  Copyright (C) 2005-2006,
 | 
						|
 * Univ. of Florida.  Author: Timothy A. Davis
 | 
						|
 * The CHOLMOD/Core Module is licensed under Version 2.1 of the GNU
 | 
						|
 * Lesser General Public License.  See lesser.txt for a text of the license.
 | 
						|
 * CHOLMOD is also available under other licenses; contact authors for details.
 | 
						|
 * http://www.cise.ufl.edu/research/sparse
 | 
						|
 * -------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/* Core utility routines for the cholmod_common object:
 | 
						|
 *
 | 
						|
 * Primary routines:
 | 
						|
 * -----------------
 | 
						|
 * cholmod_start		the first call to CHOLMOD
 | 
						|
 * cholmod_finish		the last call to CHOLMOD
 | 
						|
 *
 | 
						|
 * Secondary routines:
 | 
						|
 * -------------------
 | 
						|
 * cholmod_defaults		restore (most) default control parameters
 | 
						|
 * cholmod_allocate_work	allocate (or reallocate) workspace in Common
 | 
						|
 * cholmod_free_work		free workspace in Common
 | 
						|
 * cholmod_clear_flag		clear Common->Flag in workspace
 | 
						|
 * cholmod_maxrank		column dimension of Common->Xwork workspace
 | 
						|
 *
 | 
						|
 * The Common object is unique.  It cannot be allocated or deallocated by
 | 
						|
 * CHOLMOD, since it contains the definition of the memory management routines
 | 
						|
 * used (pointers to malloc, free, realloc, and calloc, or their equivalent).
 | 
						|
 * The Common object contains workspace that is used between calls to
 | 
						|
 * CHOLMOD routines.  This workspace allocated by CHOLMOD as needed, by
 | 
						|
 * cholmod_allocate_work and cholmod_free_work.
 | 
						|
 */
 | 
						|
 | 
						|
#include "cholmod_internal.h"
 | 
						|
#include "cholmod_core.h"
 | 
						|
 | 
						|
/* ========================================================================== */
 | 
						|
/* === cholmod_start ======================================================== */
 | 
						|
/* ========================================================================== */
 | 
						|
 | 
						|
/* Initialize Common default parameters and statistics.  Sets workspace
 | 
						|
 * pointers to NULL.
 | 
						|
 *
 | 
						|
 * This routine must be called just once, prior to calling any other CHOLMOD
 | 
						|
 * routine.  Do not call this routine after any other CHOLMOD routine (except
 | 
						|
 * cholmod_finish, to start a new CHOLMOD session), or a memory leak will
 | 
						|
 * occur.
 | 
						|
 *
 | 
						|
 * workspace: none
 | 
						|
 */
 | 
						|
 | 
						|
int CHOLMOD(start)
 | 
						|
(
 | 
						|
    cholmod_common *Common
 | 
						|
)
 | 
						|
{
 | 
						|
    int k ;
 | 
						|
 | 
						|
    if (Common == NULL)
 | 
						|
    {
 | 
						|
	return (FALSE) ;
 | 
						|
    }
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* user error handling routine */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
    Common->error_handler = NULL ;
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* integer and numerical types */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
    Common->itype = ITYPE ;
 | 
						|
    Common->dtype = DTYPE ;
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* default control parameters */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
    cholmod_l_defaults(Common) ;
 | 
						|
    Common->try_catch = FALSE ;
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* memory management routines */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
    /* The user can replace cholmod's memory management routines by redefining
 | 
						|
     * these function pointers. */
 | 
						|
 | 
						|
#ifndef NMALLOC
 | 
						|
    /* stand-alone ANSI C program */
 | 
						|
    Common->malloc_memory  = malloc ;
 | 
						|
    Common->free_memory    = free ;
 | 
						|
    Common->realloc_memory = realloc ;
 | 
						|
    Common->calloc_memory  = calloc ;
 | 
						|
#else
 | 
						|
    /* no memory manager defined at compile-time; MUST define one at run-time */
 | 
						|
    Common->malloc_memory  = NULL ;
 | 
						|
    Common->free_memory    = NULL ;
 | 
						|
    Common->realloc_memory = NULL ;
 | 
						|
    Common->calloc_memory  = NULL ;
 | 
						|
#endif
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* complex arithmetic routines */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
//    Common->complex_divide = CHOLMOD(divcomplex) ;
 | 
						|
//    Common->hypotenuse = CHOLMOD(hypot) ;
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* print routine */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
#ifndef NPRINT
 | 
						|
    /* stand-alone ANSI C program */
 | 
						|
    Common->print_function = printf ;
 | 
						|
#else
 | 
						|
    /* printing disabled */
 | 
						|
    Common->print_function = NULL ;
 | 
						|
#endif
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* workspace */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
    /* This code assumes the workspace held in Common is not initialized.  If
 | 
						|
     * it is, then a memory leak will occur because the pointers are
 | 
						|
     * overwritten with NULL. */
 | 
						|
 | 
						|
    Common->nrow = 0 ;
 | 
						|
    Common->mark = EMPTY ;
 | 
						|
    Common->xworksize = 0 ;
 | 
						|
    Common->iworksize = 0 ;
 | 
						|
    Common->Flag = NULL ;
 | 
						|
    Common->Head = NULL ;
 | 
						|
    Common->Iwork = NULL ;
 | 
						|
    Common->Xwork = NULL ;
 | 
						|
    Common->no_workspace_reallocate = FALSE ;
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* statistics */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
    /* fl and lnz are computed in cholmod_analyze and cholmod_rowcolcounts */
 | 
						|
    Common->fl = EMPTY ;
 | 
						|
    Common->lnz = EMPTY ;
 | 
						|
 | 
						|
    /* modfl is computed in cholmod_updown, cholmod_rowadd, and cholmod_rowdel*/
 | 
						|
    Common->modfl = EMPTY ;
 | 
						|
 | 
						|
    /* all routines use status as their error-report code */
 | 
						|
    Common->status = CHOLMOD_OK ;
 | 
						|
 | 
						|
    Common->malloc_count = 0 ;	/* # calls to malloc minus # calls to free */
 | 
						|
    Common->memory_usage = 0 ;	/* peak memory usage (in bytes) */
 | 
						|
    Common->memory_inuse = 0 ;	/* current memory in use (in bytes) */
 | 
						|
 | 
						|
    Common->nrealloc_col = 0 ;
 | 
						|
    Common->nrealloc_factor = 0 ;
 | 
						|
    Common->ndbounds_hit = 0 ;
 | 
						|
    Common->rowfacfl = 0 ;
 | 
						|
    Common->aatfl = EMPTY ;
 | 
						|
 | 
						|
    /* Common->called_nd is TRUE if cholmod_analyze called or NESDIS */
 | 
						|
    Common->called_nd = FALSE ;
 | 
						|
 | 
						|
    Common->blas_ok = TRUE ;    /* false if BLAS int overflow occurs */
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* default SuiteSparseQR knobs and statististics */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
    for (k = 0 ; k < 4  ; k++) Common->SPQR_xstat [k] = 0 ;
 | 
						|
    for (k = 0 ; k < 10 ; k++) Common->SPQR_istat [k] = 0 ;
 | 
						|
    Common->SPQR_grain = 1 ;    /* no Intel TBB multitasking, by default */
 | 
						|
    Common->SPQR_small = 1e6 ;  /* target min task size for TBB */
 | 
						|
    Common->SPQR_shrink = 1 ;   /* controls SPQR shrink realloc */
 | 
						|
    Common->SPQR_nthreads = 0 ; /* 0: let TBB decide how many threads to use */
 | 
						|
 | 
						|
    DEBUG_INIT ("cholmod start", Common) ;
 | 
						|
    return (TRUE) ;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* ========================================================================== */
 | 
						|
/* === cholmod_defaults ===================================================== */
 | 
						|
/* ========================================================================== */
 | 
						|
 | 
						|
/* Set Common default parameters, except for the function pointers.
 | 
						|
 *
 | 
						|
 * workspace: none
 | 
						|
 */
 | 
						|
 | 
						|
int CHOLMOD(defaults)
 | 
						|
(
 | 
						|
    cholmod_common *Common
 | 
						|
)
 | 
						|
{
 | 
						|
    Int i ;
 | 
						|
 | 
						|
    RETURN_IF_NULL_COMMON (FALSE) ;
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* default control parameters */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
    Common->dbound = 0.0 ;
 | 
						|
    Common->grow0 = 1.2 ;
 | 
						|
    Common->grow1 = 1.2 ;
 | 
						|
    Common->grow2 = 5 ;
 | 
						|
    Common->maxrank = 8 ;
 | 
						|
 | 
						|
    Common->final_asis = TRUE ;
 | 
						|
    Common->final_super = TRUE ;
 | 
						|
    Common->final_ll = FALSE ;
 | 
						|
    Common->final_pack = TRUE ;
 | 
						|
    Common->final_monotonic = TRUE ;
 | 
						|
    Common->final_resymbol = FALSE ;
 | 
						|
 | 
						|
    /* use simplicial factorization if flop/nnz(L) < 40, supernodal otherwise */
 | 
						|
    Common->supernodal = CHOLMOD_AUTO ;
 | 
						|
    Common->supernodal_switch = 40 ;
 | 
						|
 | 
						|
    Common->nrelax [0] = 4 ;
 | 
						|
    Common->nrelax [1] = 16 ;
 | 
						|
    Common->nrelax [2] = 48 ;
 | 
						|
    Common->zrelax [0] = 0.8 ;
 | 
						|
    Common->zrelax [1] = 0.1 ;
 | 
						|
    Common->zrelax [2] = 0.05 ;
 | 
						|
 | 
						|
    Common->prefer_zomplex = FALSE ;
 | 
						|
    Common->prefer_upper = TRUE ;
 | 
						|
    Common->prefer_binary = FALSE ;
 | 
						|
    Common->quick_return_if_not_posdef = FALSE ;
 | 
						|
 | 
						|
    /* METIS workarounds */
 | 
						|
    Common->metis_memory = 0.0 ;    /* > 0 for memory guard (2 is reasonable) */
 | 
						|
    Common->metis_nswitch = 3000 ;
 | 
						|
    Common->metis_dswitch = 0.66 ;
 | 
						|
 | 
						|
    Common->print = 3 ;
 | 
						|
    Common->precise = FALSE ;
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* default ordering methods */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
    /* Note that if the Partition module is not installed, the CHOLMOD_METIS
 | 
						|
     * and CHOLMOD_NESDIS methods will not be available.  cholmod_analyze will
 | 
						|
     * report the CHOLMOD_NOT_INSTALLED error, and safely skip over them.
 | 
						|
     */
 | 
						|
 | 
						|
#if (CHOLMOD_MAXMETHODS < 9)
 | 
						|
#error "CHOLMOD_MAXMETHODS must be 9 or more (defined in cholmod_core.h)."
 | 
						|
#endif
 | 
						|
 | 
						|
    /* default strategy: try given, AMD, and then METIS if AMD reports high
 | 
						|
     * fill-in.  NESDIS can be used instead, if Common->default_nesdis is TRUE.
 | 
						|
     */
 | 
						|
    Common->nmethods = 0 ;		/* use default strategy */
 | 
						|
    Common->default_nesdis = FALSE ;	/* use METIS in default strategy */
 | 
						|
 | 
						|
    Common->current = 0 ;	/* current method being tried */
 | 
						|
    Common->selected = 0 ;	/* the best method selected */
 | 
						|
 | 
						|
    /* first, fill each method with default parameters */
 | 
						|
    for (i = 0 ; i <= CHOLMOD_MAXMETHODS ; i++)
 | 
						|
    {
 | 
						|
	/* CHOLMOD's default method is AMD for A or AA' */
 | 
						|
	Common->method [i].ordering = CHOLMOD_AMD ;
 | 
						|
 | 
						|
	/* CHOLMOD nested dissection and minimum degree parameter */
 | 
						|
	Common->method [i].prune_dense = 10.0 ;	/* dense row/col control */
 | 
						|
 | 
						|
	/* min degree parameters (AMD, COLAMD, SYMAMD, CAMD, CCOLAMD, CSYMAMD)*/
 | 
						|
	Common->method [i].prune_dense2 = -1 ;	/* COLAMD dense row control */
 | 
						|
	Common->method [i].aggressive = TRUE ;	/* aggressive absorption */
 | 
						|
	Common->method [i].order_for_lu = FALSE ;/* order for Cholesky not LU */
 | 
						|
 | 
						|
	/* CHOLMOD's nested dissection (METIS + constrained AMD) */
 | 
						|
	Common->method [i].nd_small = 200 ;	/* small graphs aren't cut */
 | 
						|
	Common->method [i].nd_compress = TRUE ;	/* compress graph & subgraphs */
 | 
						|
	Common->method [i].nd_camd = 1 ;	/* use CAMD */
 | 
						|
	Common->method [i].nd_components = FALSE ;  /* lump connected comp. */
 | 
						|
	Common->method [i].nd_oksep = 1.0 ;	/* sep ok if < oksep*n */
 | 
						|
 | 
						|
	/* statistics for each method are not yet computed */
 | 
						|
	Common->method [i].fl = EMPTY ;
 | 
						|
	Common->method [i].lnz = EMPTY ;
 | 
						|
    }
 | 
						|
 | 
						|
    Common->postorder = TRUE ;	/* follow ordering with weighted postorder */
 | 
						|
 | 
						|
    /* Next, define some methods.  The first five use default parameters. */
 | 
						|
    Common->method [0].ordering = CHOLMOD_GIVEN ;   /* skip if UserPerm NULL */
 | 
						|
    Common->method [1].ordering = CHOLMOD_AMD ;
 | 
						|
    Common->method [2].ordering = CHOLMOD_METIS ;
 | 
						|
    Common->method [3].ordering = CHOLMOD_NESDIS ;
 | 
						|
    Common->method [4].ordering = CHOLMOD_NATURAL ;
 | 
						|
 | 
						|
    /* CHOLMOD's nested dissection with large leaves of separator tree */
 | 
						|
    Common->method [5].ordering = CHOLMOD_NESDIS ;
 | 
						|
    Common->method [5].nd_small = 20000 ;
 | 
						|
 | 
						|
    /* CHOLMOD's nested dissection with tiny leaves, and no AMD ordering */
 | 
						|
    Common->method [6].ordering = CHOLMOD_NESDIS ;
 | 
						|
    Common->method [6].nd_small = 4 ;
 | 
						|
    Common->method [6].nd_camd = 0 ;		/* no CSYMAMD or CAMD */
 | 
						|
 | 
						|
    /* CHOLMOD's nested dissection with no dense node removal */
 | 
						|
    Common->method [7].ordering = CHOLMOD_NESDIS ;
 | 
						|
    Common->method [7].prune_dense = -1. ;
 | 
						|
 | 
						|
    /* COLAMD for A*A', AMD for A */
 | 
						|
    Common->method [8].ordering = CHOLMOD_COLAMD ;
 | 
						|
 | 
						|
    return (TRUE) ;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* ========================================================================== */
 | 
						|
/* === cholmod_finish ======================================================= */
 | 
						|
/* ========================================================================== */
 | 
						|
 | 
						|
/* The last call to CHOLMOD must be cholmod_finish.  You may call this routine
 | 
						|
 * more than once, and can safely call any other CHOLMOD routine after calling
 | 
						|
 * it (including cholmod_start).
 | 
						|
 *
 | 
						|
 * The statistics and parameter settings in Common are preserved.  The
 | 
						|
 * workspace in Common is freed.  This routine is just another name for
 | 
						|
 * cholmod_free_work.
 | 
						|
 */
 | 
						|
 | 
						|
int CHOLMOD(finish)
 | 
						|
(
 | 
						|
    cholmod_common *Common
 | 
						|
)
 | 
						|
{
 | 
						|
    return (CHOLMOD(free_work) (Common)) ;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* ========================================================================== */
 | 
						|
/* === cholmod_allocate_work ================================================ */
 | 
						|
/* ========================================================================== */
 | 
						|
 | 
						|
/* Allocate and initialize workspace for CHOLMOD routines, or increase the size
 | 
						|
 * of already-allocated workspace.  If enough workspace is already allocated,
 | 
						|
 * then nothing happens.
 | 
						|
 *
 | 
						|
 * workspace: Flag (nrow), Head (nrow+1), Iwork (iworksize), Xwork (xworksize)
 | 
						|
 */
 | 
						|
 | 
						|
int CHOLMOD(allocate_work)
 | 
						|
(
 | 
						|
    /* ---- input ---- */
 | 
						|
    size_t nrow,	/* # of rows in the matrix A */
 | 
						|
    size_t iworksize,	/* size of Iwork */
 | 
						|
    size_t xworksize,	/* size of Xwork */
 | 
						|
    /* --------------- */
 | 
						|
    cholmod_common *Common
 | 
						|
)
 | 
						|
{
 | 
						|
    double *W ;
 | 
						|
    Int *Head ;
 | 
						|
    Int i ;
 | 
						|
    size_t nrow1 ;
 | 
						|
    int ok = TRUE ;
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* get inputs */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
    RETURN_IF_NULL_COMMON (FALSE) ;
 | 
						|
    Common->status = CHOLMOD_OK ;
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* Allocate Flag (nrow) and Head (nrow+1) */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
    nrow = MAX (1, nrow) ;
 | 
						|
 | 
						|
    /* nrow1 = nrow + 1 */
 | 
						|
    nrow1 = CHOLMOD(add_size_t) (nrow, 1, &ok) ;
 | 
						|
    if (!ok)
 | 
						|
    {
 | 
						|
	/* nrow+1 causes size_t overflow ; problem is too large */
 | 
						|
	Common->status = CHOLMOD_TOO_LARGE ;
 | 
						|
	CHOLMOD(free_work) (Common) ;
 | 
						|
	return (FALSE) ;
 | 
						|
    }
 | 
						|
 | 
						|
    if (nrow > Common->nrow)
 | 
						|
    {
 | 
						|
 | 
						|
	if (Common->no_workspace_reallocate)
 | 
						|
	{
 | 
						|
	    /* CHOLMOD is not allowed to change the workspace here */
 | 
						|
	    Common->status = CHOLMOD_INVALID ;
 | 
						|
	    return (FALSE) ;
 | 
						|
	}
 | 
						|
 | 
						|
	/* free the old workspace (if any) and allocate new space */
 | 
						|
	Common->Flag = CHOLMOD(free) (Common->nrow,  sizeof (Int), Common->Flag,
 | 
						|
		Common) ;
 | 
						|
	Common->Head = CHOLMOD(free) (Common->nrow+1,sizeof (Int), Common->Head,
 | 
						|
		Common) ;
 | 
						|
	Common->Flag = CHOLMOD(malloc) (nrow,   sizeof (Int), Common) ;
 | 
						|
	Common->Head = CHOLMOD(malloc) (nrow1, sizeof (Int), Common) ;
 | 
						|
 | 
						|
	/* record the new size of Flag and Head */
 | 
						|
	Common->nrow = nrow ;
 | 
						|
 | 
						|
	if (Common->status < CHOLMOD_OK)
 | 
						|
	{
 | 
						|
	    CHOLMOD(free_work) (Common) ;
 | 
						|
	    return (FALSE) ;
 | 
						|
	}
 | 
						|
 | 
						|
	/* initialize Flag and Head */
 | 
						|
	Common->mark = EMPTY ;
 | 
						|
	CHOLMOD(clear_flag) (Common) ;
 | 
						|
	Head = Common->Head ;
 | 
						|
	for (i = 0 ; i <= (Int) (nrow) ; i++)
 | 
						|
	{
 | 
						|
	    Head [i] = EMPTY ;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* Allocate Iwork (iworksize) */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
    iworksize = MAX (1, iworksize) ;
 | 
						|
    if (iworksize > Common->iworksize)
 | 
						|
    {
 | 
						|
 | 
						|
	if (Common->no_workspace_reallocate)
 | 
						|
	{
 | 
						|
	    /* CHOLMOD is not allowed to change the workspace here */
 | 
						|
	    Common->status = CHOLMOD_INVALID ;
 | 
						|
	    return (FALSE) ;
 | 
						|
	}
 | 
						|
 | 
						|
	/* free the old workspace (if any) and allocate new space.
 | 
						|
	 * integer overflow safely detected in cholmod_malloc */
 | 
						|
	CHOLMOD(free) (Common->iworksize, sizeof (Int), Common->Iwork, Common) ;
 | 
						|
	Common->Iwork = CHOLMOD(malloc) (iworksize, sizeof (Int), Common) ;
 | 
						|
 | 
						|
	/* record the new size of Iwork */
 | 
						|
	Common->iworksize = iworksize ;
 | 
						|
 | 
						|
	if (Common->status < CHOLMOD_OK)
 | 
						|
	{
 | 
						|
	    CHOLMOD(free_work) (Common) ;
 | 
						|
	    return (FALSE) ;
 | 
						|
	}
 | 
						|
 | 
						|
	/* note that Iwork does not need to be initialized */
 | 
						|
    }
 | 
						|
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
    /* Allocate Xwork (xworksize) and set it to ((double) 0.) */
 | 
						|
    /* ---------------------------------------------------------------------- */
 | 
						|
 | 
						|
    /* make sure xworksize is >= 1 */
 | 
						|
    xworksize = MAX (1, xworksize) ;
 | 
						|
    if (xworksize > Common->xworksize)
 | 
						|
    {
 | 
						|
 | 
						|
	if (Common->no_workspace_reallocate)
 | 
						|
	{
 | 
						|
	    /* CHOLMOD is not allowed to change the workspace here */
 | 
						|
	    Common->status = CHOLMOD_INVALID ;
 | 
						|
	    return (FALSE) ;
 | 
						|
	}
 | 
						|
 | 
						|
	/* free the old workspace (if any) and allocate new space */
 | 
						|
	CHOLMOD(free) (Common->xworksize, sizeof (double), Common->Xwork,
 | 
						|
		Common) ;
 | 
						|
	Common->Xwork = CHOLMOD(malloc) (xworksize, sizeof (double), Common) ;
 | 
						|
 | 
						|
	/* record the new size of Xwork */
 | 
						|
	Common->xworksize = xworksize ;
 | 
						|
 | 
						|
	if (Common->status < CHOLMOD_OK)
 | 
						|
	{
 | 
						|
	    CHOLMOD(free_work) (Common) ;
 | 
						|
	    return (FALSE) ;
 | 
						|
	}
 | 
						|
 | 
						|
	/* initialize Xwork */
 | 
						|
	W = Common->Xwork ;
 | 
						|
	for (i = 0 ; i < (Int) xworksize ; i++)
 | 
						|
	{
 | 
						|
	    W [i] = 0. ;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    return (TRUE) ;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* ========================================================================== */
 | 
						|
/* === cholmod_free_work ==================================================== */
 | 
						|
/* ========================================================================== */
 | 
						|
 | 
						|
/* Deallocate the CHOLMOD workspace.
 | 
						|
 *
 | 
						|
 * workspace: deallocates all workspace in Common
 | 
						|
 */
 | 
						|
 | 
						|
int CHOLMOD(free_work)
 | 
						|
(
 | 
						|
    cholmod_common *Common
 | 
						|
)
 | 
						|
{
 | 
						|
    RETURN_IF_NULL_COMMON (FALSE) ;
 | 
						|
    Common->Flag  = CHOLMOD(free) (Common->nrow, sizeof (Int),
 | 
						|
	    Common->Flag, Common) ;
 | 
						|
    Common->Head  = CHOLMOD(free) (Common->nrow+1, sizeof (Int),
 | 
						|
	    Common->Head, Common) ;
 | 
						|
    Common->Iwork = CHOLMOD(free) (Common->iworksize, sizeof (Int),
 | 
						|
	    Common->Iwork, Common) ;
 | 
						|
    Common->Xwork = CHOLMOD(free) (Common->xworksize, sizeof (double),
 | 
						|
	    Common->Xwork, Common) ;
 | 
						|
    Common->nrow = 0 ;
 | 
						|
    Common->iworksize = 0 ;
 | 
						|
    Common->xworksize = 0 ;
 | 
						|
    return (TRUE) ;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* ========================================================================== */
 | 
						|
/* === cholmod_clear_flag =================================================== */
 | 
						|
/* ========================================================================== */
 | 
						|
 | 
						|
/* Increment mark to ensure Flag [0..nrow-1] < mark.  If integer overflow
 | 
						|
 * occurs, or mark was initially negative, reset the entire array.  This is
 | 
						|
 * not an error condition, but an intended function of the Flag workspace.
 | 
						|
 *
 | 
						|
 * workspace: Flag (nrow).  Does not modify Flag if nrow is zero.
 | 
						|
 */
 | 
						|
 | 
						|
UF_long cholmod_l_clear_flag
 | 
						|
(
 | 
						|
    cholmod_common *Common
 | 
						|
)
 | 
						|
{
 | 
						|
    Int i, nrow, *Flag ;
 | 
						|
 | 
						|
    RETURN_IF_NULL_COMMON (-1) ;
 | 
						|
 | 
						|
    Common->mark++ ;
 | 
						|
    if (Common->mark <= 0)
 | 
						|
    {
 | 
						|
	nrow = Common->nrow ;
 | 
						|
	Flag = Common->Flag ;
 | 
						|
	PRINT2 (("reset Flag: nrow "ID"\n", nrow)) ;
 | 
						|
	PRINT2 (("reset Flag: mark %ld\n", Common->mark)) ;
 | 
						|
	for (i = 0 ; i < nrow ; i++)
 | 
						|
	{
 | 
						|
	    Flag [i] = EMPTY ;
 | 
						|
	}
 | 
						|
	Common->mark = 0 ;
 | 
						|
    }
 | 
						|
    return (Common->mark) ;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* ========================================================================== */
 | 
						|
/* ==== cholmod_maxrank ===================================================== */
 | 
						|
/* ========================================================================== */
 | 
						|
 | 
						|
/* Find a valid value of Common->maxrank.  Returns 0 if error, or 2, 4, or 8
 | 
						|
 * if successful. */
 | 
						|
 | 
						|
size_t cholmod_l_maxrank	/* returns validated value of Common->maxrank */
 | 
						|
(
 | 
						|
    /* ---- input ---- */
 | 
						|
    size_t n,		/* A and L will have n rows */
 | 
						|
    /* --------------- */
 | 
						|
    cholmod_common *Common
 | 
						|
)
 | 
						|
{
 | 
						|
    size_t maxrank ;
 | 
						|
    RETURN_IF_NULL_COMMON (0) ;
 | 
						|
    maxrank = Common->maxrank ;
 | 
						|
    if (n > 0)
 | 
						|
    {
 | 
						|
	/* Ensure maxrank*n*sizeof(double) does not result in integer overflow.
 | 
						|
	 * If n is so large that 2*n*sizeof(double) results in integer overflow
 | 
						|
	 * (n = 268,435,455 if an Int is 32 bits), then maxrank will be 0 or 1,
 | 
						|
	 * but maxrank will be set to 2 below.  2*n will not result in integer
 | 
						|
	 * overflow, and CHOLMOD will run out of memory or safely detect integer
 | 
						|
	 * overflow elsewhere.
 | 
						|
	 */
 | 
						|
	maxrank = MIN (maxrank, Size_max / (n * sizeof (double))) ;
 | 
						|
    }
 | 
						|
    if (maxrank <= 2)
 | 
						|
    {
 | 
						|
	maxrank = 2 ;
 | 
						|
    }
 | 
						|
    else if (maxrank <= 4)
 | 
						|
    {
 | 
						|
	maxrank = 4 ;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	maxrank = 8 ;
 | 
						|
    }
 | 
						|
    return (maxrank) ;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* ========================================================================== */
 | 
						|
/* === cholmod_dbound ======================================================= */
 | 
						|
/* ========================================================================== */
 | 
						|
 | 
						|
/* Ensure the absolute value of a diagonal entry, D (j,j), is greater than
 | 
						|
 * Common->dbound.  This routine is not meant for the user to call.  It is used
 | 
						|
 * by the various LDL' factorization and update/downdate routines.  The
 | 
						|
 * default value of Common->dbound is zero, and in that case this routine is not
 | 
						|
 * called at all.  No change is made if D (j,j) is NaN.  CHOLMOD does not call
 | 
						|
 * this routine if Common->dbound is NaN.
 | 
						|
 */
 | 
						|
 | 
						|
double cholmod_l_dbound	/* returns modified diagonal entry of D */
 | 
						|
(
 | 
						|
    /* ---- input ---- */
 | 
						|
    double dj,		/* diagonal entry of D, for LDL' factorization */
 | 
						|
    /* --------------- */
 | 
						|
    cholmod_common *Common
 | 
						|
)
 | 
						|
{
 | 
						|
    double dbound ;
 | 
						|
    RETURN_IF_NULL_COMMON (0) ;
 | 
						|
    if (!IS_NAN (dj))
 | 
						|
    {
 | 
						|
	dbound = Common->dbound ;
 | 
						|
	if (dj < 0)
 | 
						|
	{
 | 
						|
	    if (dj > -dbound)
 | 
						|
	    {
 | 
						|
		dj = -dbound ;
 | 
						|
		Common->ndbounds_hit++ ;
 | 
						|
		if (Common->status == CHOLMOD_OK)
 | 
						|
		{
 | 
						|
		    ERROR (CHOLMOD_DSMALL, "diagonal below threshold") ;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    if (dj < dbound)
 | 
						|
	    {
 | 
						|
		dj = dbound ;
 | 
						|
		Common->ndbounds_hit++ ;
 | 
						|
		if (Common->status == CHOLMOD_OK)
 | 
						|
		{
 | 
						|
		    ERROR (CHOLMOD_DSMALL, "diagonal below threshold") ;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return (dj) ;
 | 
						|
}
 |