⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 colamd.c

📁 LU矩阵分解单机版最新版本
💻 C
📖 第 1 页 / 共 5 页
字号:
    int n_row,    int n_col,    Colamd_Row Row [],    Colamd_Col Col [],    int A [],    int n_col2) ;#else /* NDEBUG *//* === No debugging ========================================================= */#define DEBUG0(params) ;#define DEBUG1(params) ;#define DEBUG2(params) ;#define DEBUG3(params) ;#define DEBUG4(params) ;#define ASSERT(expression) ((void) 0)#endif /* NDEBUG *//* ========================================================================== *//* ========================================================================== *//* === USER-CALLABLE ROUTINES: ============================================== *//* ========================================================================== *//* ========================================================================== *//* === colamd_recommended =================================================== *//* ========================================================================== *//*    The colamd_recommended routine returns the suggested size for Alen.  This    value has been determined to provide good balance between the number of    garbage collections and the memory requirements for colamd.  If any    argument is negative, a -1 is returned as an error condition.  This    function is also available as a macro defined in colamd.h, so that you    can use it for a statically-allocated array size.*/PUBLIC int colamd_recommended	/* returns recommended value of Alen. */(    /* === Parameters ======================================================= */    int nnz,			/* number of nonzeros in A */    int n_row,			/* number of rows in A */    int n_col			/* number of columns in A */){    return (COLAMD_RECOMMENDED (nnz, n_row, n_col)) ; }/* ========================================================================== *//* === colamd_set_defaults ================================================== *//* ========================================================================== *//*    The colamd_set_defaults routine sets the default values of the user-    controllable parameters for colamd:	knobs [0]	rows with knobs[0]*n_col entries or more are removed			prior to ordering in colamd.  Rows and columns with			knobs[0]*n_col entries or more are removed prior to			ordering in symamd and placed last in the output			ordering.	knobs [1]	columns with knobs[1]*n_row entries or more are removed			prior to ordering in colamd, and placed last in the			column permutation.  Symamd ignores this knob.	knobs [2..19]	unused, but future versions might use this*/PUBLIC void colamd_set_defaults(    /* === Parameters ======================================================= */    double knobs [COLAMD_KNOBS]		/* knob array */){    /* === Local variables ================================================== */    int i ;    if (!knobs)    {	return ;			/* no knobs to initialize */    }    for (i = 0 ; i < COLAMD_KNOBS ; i++)    {	knobs [i] = 0 ;    }    knobs [COLAMD_DENSE_ROW] = 0.5 ;	/* ignore rows over 50% dense */    knobs [COLAMD_DENSE_COL] = 0.5 ;	/* ignore columns over 50% dense */}/* ========================================================================== *//* === symamd =============================================================== *//* ========================================================================== */PUBLIC int symamd			/* return TRUE if OK, FALSE otherwise */(    /* === Parameters ======================================================= */    int n,				/* number of rows and columns of A */    int A [],				/* row indices of A */    int p [],				/* column pointers of A */    int perm [],			/* output permutation, size n+1 */    double knobs [COLAMD_KNOBS],	/* parameters (uses defaults if NULL) */    int stats [COLAMD_STATS],		/* output statistics and error codes */    void * (*allocate) (size_t, size_t),    					/* pointer to calloc (ANSI C) or */					/* mxCalloc (for MATLAB mexFunction) */    void (*release) (void *)    					/* pointer to free (ANSI C) or */    					/* mxFree (for MATLAB mexFunction) */){    /* === Local variables ================================================== */    int *count ;		/* length of each column of M, and col pointer*/    int *mark ;			/* mark array for finding duplicate entries */    int *M ;			/* row indices of matrix M */    int Mlen ;			/* length of M */    int n_row ;			/* number of rows in M */    int nnz ;			/* number of entries in A */    int i ;			/* row index of A */    int j ;			/* column index of A */    int k ;			/* row index of M */     int mnz ;			/* number of nonzeros in M */    int pp ;			/* index into a column of A */    int last_row ;		/* last row seen in the current column */    int length ;		/* number of nonzeros in a column */    double cknobs [COLAMD_KNOBS] ;		/* knobs for colamd */    double default_knobs [COLAMD_KNOBS] ;	/* default knobs for colamd */    int cstats [COLAMD_STATS] ;			/* colamd stats */#ifndef NDEBUG    colamd_get_debug ("symamd") ;#endif /* NDEBUG */    /* === Check the input arguments ======================================== */    if (!stats)    {	DEBUG0 (("symamd: stats not present\n")) ;	return (FALSE) ;    }    for (i = 0 ; i < COLAMD_STATS ; i++)    {	stats [i] = 0 ;    }    stats [COLAMD_STATUS] = COLAMD_OK ;    stats [COLAMD_INFO1] = -1 ;    stats [COLAMD_INFO2] = -1 ;    if (!A)    {    	stats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ;	DEBUG0 (("symamd: A not present\n")) ;	return (FALSE) ;    }    if (!p)		/* p is not present */    {	stats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ;	DEBUG0 (("symamd: p not present\n")) ;    	return (FALSE) ;    }    if (n < 0)		/* n must be >= 0 */    {	stats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ;	stats [COLAMD_INFO1] = n ;	DEBUG0 (("symamd: n negative %d\n", n)) ;    	return (FALSE) ;    }    nnz = p [n] ;    if (nnz < 0)	/* nnz must be >= 0 */    {	stats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ;	stats [COLAMD_INFO1] = nnz ;	DEBUG0 (("symamd: number of entries negative %d\n", nnz)) ;	return (FALSE) ;    }    if (p [0] != 0)    {	stats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero ;	stats [COLAMD_INFO1] = p [0] ;	DEBUG0 (("symamd: p[0] not zero %d\n", p [0])) ;	return (FALSE) ;    }    /* === If no knobs, set default knobs =================================== */    if (!knobs)    {	colamd_set_defaults (default_knobs) ;	knobs = default_knobs ;    }    /* === Allocate count and mark ========================================== */    count = (int *) ((*allocate) (n+1, sizeof (int))) ;    if (!count)    {	stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ;	DEBUG0 (("symamd: allocate count (size %d) failed\n", n+1)) ;	return (FALSE) ;    }    mark = (int *) ((*allocate) (n+1, sizeof (int))) ;    if (!mark)    {	stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ;	(*release) ((void *) count) ;	DEBUG0 (("symamd: allocate mark (size %d) failed\n", n+1)) ;	return (FALSE) ;    }    /* === Compute column counts of M, check if A is valid ================== */    stats [COLAMD_INFO3] = 0 ;  /* number of duplicate or unsorted row indices*/    for (i = 0 ; i < n ; i++)    {    	mark [i] = -1 ;    }    for (j = 0 ; j < n ; j++)    {	last_row = -1 ;	length = p [j+1] - p [j] ;	if (length < 0)	{	    /* column pointers must be non-decreasing */	    stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ;	    stats [COLAMD_INFO1] = j ;	    stats [COLAMD_INFO2] = length ;	    (*release) ((void *) count) ;	    (*release) ((void *) mark) ;	    DEBUG0 (("symamd: col %d negative length %d\n", j, length)) ;	    return (FALSE) ;	}	for (pp = p [j] ; pp < p [j+1] ; pp++)	{	    i = A [pp] ;	    if (i < 0 || i >= n)	    {		/* row index i, in column j, is out of bounds */		stats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ;		stats [COLAMD_INFO1] = j ;		stats [COLAMD_INFO2] = i ;		stats [COLAMD_INFO3] = n ;		(*release) ((void *) count) ;		(*release) ((void *) mark) ;		DEBUG0 (("symamd: row %d col %d out of bounds\n", i, j)) ;		return (FALSE) ;	    }	    if (i <= last_row || mark [i] == j)	    {		/* row index is unsorted or repeated (or both), thus col */		/* is jumbled.  This is a notice, not an error condition. */		stats [COLAMD_STATUS] = COLAMD_OK_BUT_JUMBLED ;		stats [COLAMD_INFO1] = j ;		stats [COLAMD_INFO2] = i ;		(stats [COLAMD_INFO3]) ++ ;		DEBUG1 (("symamd: row %d col %d unsorted/duplicate\n", i, j)) ;	    }	    if (i > j && mark [i] != j)	    {		/* row k of M will contain column indices i and j */		count [i]++ ;		count [j]++ ;	    }	    /* mark the row as having been seen in this column */	    mark [i] = j ;	    last_row = i ;	}    }    if (stats [COLAMD_STATUS] == COLAMD_OK)    {	/* if there are no duplicate entries, then mark is no longer needed */	(*release) ((void *) mark) ;    }    /* === Compute column pointers of M ===================================== */    /* use output permutation, perm, for column pointers of M */    perm [0] = 0 ;    for (j = 1 ; j <= n ; j++)    {	perm [j] = perm [j-1] + count [j-1] ;    }    for (j = 0 ; j < n ; j++)    {	count [j] = perm [j] ;    }    /* === Construct M ====================================================== */    mnz = perm [n] ;    n_row = mnz / 2 ;    Mlen = colamd_recommended (mnz, n_row, n) ;    M = (int *) ((*allocate) (Mlen, sizeof (int))) ;    DEBUG0 (("symamd: M is %d-by-%d with %d entries, Mlen = %d\n",    	n_row, n, mnz, Mlen)) ;    if (!M)    {	stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ;	(*release) ((void *) count) ;	(*release) ((void *) mark) ;	DEBUG0 (("symamd: allocate M (size %d) failed\n", Mlen)) ;	return (FALSE) ;    }    k = 0 ;    if (stats [COLAMD_STATUS] == COLAMD_OK)    {	/* Matrix is OK */	for (j = 0 ; j < n ; j++)	{	    ASSERT (p [j+1] - p [j] >= 0) ;	    for (pp = p [j] ; pp < p [j+1] ; pp++)	    {		i = A [pp] ;		ASSERT (i >= 0 && i < n) ;		if (i > j)		{		    /* row k of M contains column indices i and j */		    M [count [i]++] = k ;		    M [count [j]++] = k ;		    k++ ;		}	    }	}    }    else    {	/* Matrix is jumbled.  Do not add duplicates to M.  Unsorted cols OK. */	DEBUG0 (("symamd: Duplicates in A.\n")) ;	for (i = 0 ; i < n ; i++)	{	    mark [i] = -1 ;	}	for (j = 0 ; j < n ; j++)	{	    ASSERT (p [j+1] - p [j] >= 0) ;	    for (pp = p [j] ; pp < p [j+1] ; pp++)	    {		i = A [pp] ;		ASSERT (i >= 0 && i < n) ;		if (i > j && mark [i] != j)		{		    /* row k of M contains column indices i and j */		    M [count [i]++] = k ;		    M [count [j]++] = k ;		    k++ ;		    mark [i] = j ;		}	    }	}	(*release) ((void *) mark) ;    }    /* count and mark no longer needed */    (*release) ((void *) count) ;    ASSERT (k == n_row) ;    /* === Adjust the knobs for M =========================================== */    for (i = 0 ; i < COLAMD_KNOBS ; i++)    {	cknobs [i] = knobs [i] ;    }    /* there are no dense rows in M */    cknobs [COLAMD_DENSE_ROW] = 1.0 ;    if (n_row != 0 && n < n_row)    {	/* On input, the knob is a fraction of 1..n, the number of rows of A. */	/* Convert it to a fraction of 1..n_row, of the number of rows of M. */    	cknobs [COLAMD_DENSE_COL] = (knobs [COLAMD_DENSE_ROW] * n) / n_row ;    }    else    {	/* no dense columns in M */    	cknobs [COLAMD_DENSE_COL] = 1.0 ;    }    DEBUG0 (("symamd: dense col knob for M: %g\n", cknobs [COLAMD_DENSE_COL])) ;    /* === Order the columns of M =========================================== */    if (!colamd (n_row, n, Mlen, M, perm, cknobs, cstats))    {	/* This "cannot" happen, unless there is a bug in the code. */	stats [COLAMD_STATUS] = COLAMD_ERROR_internal_error ;	(*release) ((void *) M) ;	DEBUG0 (("symamd: internal error!\n")) ;	return (FALSE) ;    }    /* Note that the output permutation is now in perm */    /* === get the statistics for symamd from colamd ======================== */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -