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) ; | ||
|  | } |