Mercurial > hg > octave-nkf
changeset 5438:49ff3dd744ee
[project @ 2005-09-04 12:25:21 by dbateman]
author | dbateman |
---|---|
date | Sun, 04 Sep 2005 12:25:21 +0000 |
parents | 009606303874 |
children | ca7ebff13a16 |
files | liboctave/COLAMD.README liboctave/COLAMD.files liboctave/COLAMD/ChangeLog liboctave/COLAMD/Makefile liboctave/COLAMD/colamd.c liboctave/COLAMD/colamd.h liboctave/COLAMD/colamd.m liboctave/COLAMD/colamd_demo.m liboctave/COLAMD/colamd_example.c liboctave/COLAMD/colamd_example.out liboctave/COLAMD/colamd_test.m liboctave/COLAMD/colamdmex.c liboctave/COLAMD/colamdtestmex.c liboctave/COLAMD/symamd.m liboctave/COLAMD/symamdmex.c liboctave/COLAMD/symamdtestmex.c liboctave/ChangeLog |
diffstat | 17 files changed, 1169 insertions(+), 1080 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/COLAMD.README +++ b/liboctave/COLAMD.README @@ -1,4 +1,4 @@ -This directory contains an unmodified copy of COLAMD version 2.3 in +This directory contains an unmodified copy of COLAMD version 2.4 in the subdirectory COLAMD. COLAMD was written by Stefan I. Larimore and Timothy A. Davis (davis@cise.ufl.edu), University of Florida. The algorithm was developed in collaboration with John Gilbert, Xerox
--- a/liboctave/COLAMD.files +++ b/liboctave/COLAMD.files @@ -1,7 +1,9 @@ -COLAMD_SRC := colamd.c +COLAMD_SRC := colamd_global.c colamd.c -COLAMD_OBJ := $(COLAMD_SRC:.c=.o) +COLAMD_VIRTUAL_SRC := colamd_l.c + +COLAMD_OBJ := $(COLAMD_SRC:.c=.o) $(COLAMD_VIRTUAL_SRC:.c=.o) COLAMD_DEP := $(COLAMD_SRC:.c=.d) @@ -9,3 +11,9 @@ COLAMD_EXTRAS := COLAMD.files COLAMD.README +# Special rules for long version of colamd +colamd_l.o : colamd.c + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -DDLONG $< -o $@ + +pic/colamd_l.o : colamd.c + $(CC) -c $(CPPFLAGS) $(CPICFLAGS) $(ALL_CFLAGS) -DDLONG $< -o $@
--- a/liboctave/COLAMD/ChangeLog +++ b/liboctave/COLAMD/ChangeLog @@ -1,3 +1,31 @@ +Changes from Version 2.3 to 2.4 (Aug 30, 2005) + + * Makefile now relies on ../UFconfig/UFconfig.mk + + * changed the dense row/col detection. The meaning of the knobs + has thus changed. + + * added an option to turn off aggressive absorption. It was + always on in versions 2.3 and earlier. + + * added a #define'd version number + + * added a function pointer (colamd_printf) for COLAMD's printing. + + * added a -DNPRINT option, to turn off printing at compile-time. + + * added a check for integer overflow in colamd_recommended + + * minor changes to allow for more simpler 100% test coverage + + * bug fix. If symamd v2.3 fails to allocate its copy of the input + matrix, then it erroneously frees a calloc'd workspace twice. + This bug has no effect on the MATLAB symamd mexFunction, since + mxCalloc terminates the mexFunction if it fails to allocate + memory. Similarly, UMFPACK is not affected because it does not + use symamd. The bug has no affect on the colamd ordering + routine in v2.3. + Changes from Version 2.2 to 2.3 (Sept. 8, 2003) * removed the call to the MATLAB spparms ('spumoni') function. @@ -38,7 +66,7 @@ No bugs were found in version 1.1. These changes merely add new functionality. - * added the COLAMD_RECOMMENDED (nnz, n_row, n_col) macro. + * added the COLAMD_RECOMMENDED (nnz, n_row, n_col) macro. * moved the output statistics, from A, to a separate output argument. The arguments changed for the C-callable routines.
--- a/liboctave/COLAMD/Makefile +++ b/liboctave/COLAMD/Makefile @@ -1,19 +1,46 @@ -colamd_example: colamd_example.c colamd.c colamd.h - cc -O -o colamd_example colamd_example.c colamd.c - - ./colamd_example + +default: libcolamd.a colamd_example colamd_l_example + +include ../UFconfig/UFconfig.mk + +colamd_example: colamd_example.c libcolamd.a + $(CC) $(CFLAGS) -o colamd_example colamd_example.c libcolamd.a -lm + - ./colamd_example > my_colamd_example.out + - diff colamd_example.out my_colamd_example.out -clean: - - rm *.o colamd_example - - rm colamdmex.mex* symamdmex.mex* - - rm colamdtestmex.mex* symamdtestmex.mex* +colamd_l_example: colamd_l_example.c libcolamd.a + $(CC) $(CFLAGS) -o colamd_l_example colamd_l_example.c libcolamd.a -lm + - ./colamd_l_example > my_colamd_l_example.out + - diff colamd_example.out my_colamd_example.out + +purge: distclean + +distclean: clean2 + - $(RM) libcolamd.a + +clean2: clean + - $(RM) *.o *.dll colamd_example colamd_l_example + - $(RM) colamdmex.mex* symamdmex.mex* + - $(RM) colamdtestmex.mex* symamdtestmex.mex* + - $(RM) my_colamd_example.out my_colamd_l_example.out # Compiles the MATLAB-callable routines -matlab: colamdmex.c colamd.c colamd.h - mex -O colamdmex.c colamd.c - mex -O symamdmex.c colamd.c +matlab: colamdmex.c symamdmex.c libcolamd.a + $(MEX) colamdmex.c libcolamd.a + $(MEX) symamdmex.c libcolamd.a # Compiles the extensive test code -test: matlab colamdmex.c colamd.c colamd.h - mex -O colamdtestmex.c colamd.c - mex -O symamdtestmex.c colamd.c +test: matlab colamdtestmex.c symamdtestmex.c libcolamd.a + $(MEX) colamdtestmex.c libcolamd.a + $(MEX) symamdtestmex.c libcolamd.a +# creates libcolamd.a, a C-callable COLAMD library +libcolamd.a: colamd.c colamd_global.c colamd.h + $(CC) $(CFLAGS) -c colamd_global.c + $(CC) $(CFLAGS) -c colamd.c + $(CC) $(CFLAGS) -c colamd.c -DDLONG -o colamd_l.o + $(AR) libcolamd.a colamd.o colamd_l.o colamd_global.o + +ccode: libcolamd.a + +library: libcolamd.a
--- a/liboctave/COLAMD/colamd.c +++ b/liboctave/COLAMD/colamd.c @@ -2,7 +2,8 @@ /* === colamd/symamd - a sparse matrix column ordering algorithm ============ */ /* ========================================================================== */ -/* +/* COLAMD Version 2.4. + colamd: an approximate minimum degree column ordering algorithm, for LU factorization of symmetric or unsymmetric matrices, QR factorization, least squares, interior point methods for @@ -34,14 +35,10 @@ Authors: The authors of the code itself are Stefan I. Larimore and Timothy A. - Davis (davis@cise.ufl.edu), University of Florida. The algorithm was + Davis (davis at cise.ufl.edu), University of Florida. The algorithm was developed in collaboration with John Gilbert, Xerox PARC, and Esmond Ng, Oak Ridge National Laboratory. - Date: - - September 8, 2003. Version 2.3. - Acknowledgements: This work was supported by the National Science Foundation, under @@ -49,17 +46,34 @@ Copyright and License: - Copyright (c) 1998-2003 by the University of Florida. - All Rights Reserved. - - THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY - EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. - - Permission is hereby granted to use, copy, modify, and/or distribute - this program, provided that the Copyright, this License, and the - Availability of the original version is retained on all copies and made - accessible to the end-user of any code or package that includes COLAMD - or any modified version of COLAMD. + Copyright (c) 1998-2005, Timothy A. Davis, All Rights Reserved. + COLAMD is also available under alternate licenses, contact T. Davis + for details. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA + + Permission is hereby granted to use or copy this program under the + terms of the GNU LGPL, provided that the Copyright, this License, + and the Availability of the original version is retained on all copies. + User documentation of any code that uses this code or any modified + version of this code must cite the Copyright, this License, the + Availability note, and "Used by permission." Permission to modify + the code and to distribute modified code is granted, provided the + Copyright, this License, and the Availability note are retained, + and a notice that the code was modified is included. Availability: @@ -70,16 +84,31 @@ This is the http://www.cise.ufl.edu/research/sparse/colamd/colamd.c file. It requires the colamd.h file. It is required by the colamdmex.c and symamdmex.c files, for the MATLAB interface to colamd and symamd. + Appears as ACM Algorithm 836. See the ChangeLog file for changes since Version 1.0. + References: + + T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, An approximate column + minimum degree ordering algorithm, ACM Transactions on Mathematical + Software, vol. 30, no. 3., pp. 353-376, 2004. + + T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836: COLAMD, + an approximate column minimum degree ordering algorithm, ACM + Transactions on Mathematical Software, vol. 30, no. 3., pp. 377-380, + 2004. + */ /* ========================================================================== */ /* === Description of user-callable routines ================================ */ /* ========================================================================== */ -/* +/* COLAMD includes both int and long versions of all its routines. The + * description below os fir the int version. For long, all int arguments + * become long. + ---------------------------------------------------------------------------- colamd_recommended: ---------------------------------------------------------------------------- @@ -88,11 +117,7 @@ #include "colamd.h" int colamd_recommended (int nnz, int n_row, int n_col) ; - - or as a C macro - - #include "colamd.h" - Alen = COLAMD_RECOMMENDED (int nnz, int n_row, int n_col) ; + long colamd_l_recommended (long nnz, long n_row, long n_col) ; Purpose: @@ -122,6 +147,7 @@ #include "colamd.h" colamd_set_defaults (double knobs [COLAMD_KNOBS]) ; + colamd_l_set_defaults (double knobs [COLAMD_KNOBS]) ; Purpose: @@ -131,19 +157,26 @@ double knobs [COLAMD_KNOBS] ; Output only. - Colamd: rows with more than (knobs [COLAMD_DENSE_ROW] * n_col) + NOTE: the meaning of the dense row/col knobs has changed in v2.4 + + knobs [0] and knobs [1] control dense row and col detection: + + Colamd: rows with more than + max (16, knobs [COLAMD_DENSE_ROW] * sqrt (n_col)) entries are removed prior to ordering. Columns with more than - (knobs [COLAMD_DENSE_COL] * n_row) entries are removed prior to + max (16, knobs [COLAMD_DENSE_COL] * sqrt (MIN (n_row,n_col))) + entries are removed prior to ordering, and placed last in the output column ordering. Symamd: uses only knobs [COLAMD_DENSE_ROW], which is knobs [0]. - Rows and columns with more than (knobs [COLAMD_DENSE_ROW] * n) + Rows and columns with more than + max (16, knobs [COLAMD_DENSE_ROW] * sqrt (n)) entries are removed prior to ordering, and placed last in the output ordering. COLAMD_DENSE_ROW and COLAMD_DENSE_COL are defined as 0 and 1, respectively, in colamd.h. Default values of these two knobs - are both 0.5. Currently, only knobs [0] and knobs [1] are + are both 10. Currently, only knobs [0] and knobs [1] are used, but future versions may use more knobs. If so, they will be properly set to their defaults by the future version of colamd_set_defaults, so that the code that calls colamd will @@ -151,6 +184,12 @@ colamd_set_defaults, or pass a (double *) NULL pointer as the knobs array to colamd or symamd. + knobs [2]: aggressive absorption + + knobs [COLAMD_AGGRESSIVE] controls whether or not to do + aggressive absorption during the ordering. Default is TRUE. + + ---------------------------------------------------------------------------- colamd: ---------------------------------------------------------------------------- @@ -160,6 +199,8 @@ #include "colamd.h" int colamd (int n_row, int n_col, int Alen, int *A, int *p, double knobs [COLAMD_KNOBS], int stats [COLAMD_STATS]) ; + long colamd_l (long n_row, long n_col, long Alen, long *A, long *p, + double knobs [COLAMD_KNOBS], long stats [COLAMD_STATS]) ; Purpose: @@ -202,7 +243,9 @@ Alen >= COLAMD_RECOMMENDED (nnz, n_row, n_col) - will be sufficient. + will be sufficient. Note: the macro version does not check + for integer overflow, and thus is not recommended. Use + the colamd_recommended routine instead. int A [Alen] ; Input argument, undefined on output. @@ -352,8 +395,8 @@ with default knobs and no output statistics, do the following: #include "colamd.h" - #define ALEN COLAMD_RECOMMENDED (11, 5, 4) - int A [ALEN] = {1, 2, 5, 3, 5, 1, 2, 3, 4, 2, 4} ; + #define ALEN 100 + int A [ALEN] = {0, 1, 4, 2, 4, 0, 1, 2, 3, 1, 3} ; int p [ ] = {0, 3, 5, 9, 11} ; int stats [COLAMD_STATS] ; colamd (5, 4, ALEN, A, p, (double *) NULL, stats) ; @@ -370,6 +413,9 @@ int symamd (int n, int *A, int *p, int *perm, double knobs [COLAMD_KNOBS], int stats [COLAMD_STATS], void (*allocate) (size_t, size_t), void (*release) (void *)) ; + long symamd_l (long n, long *A, long *p, long *perm, + double knobs [COLAMD_KNOBS], long stats [COLAMD_STATS], + void (*allocate) (size_t, size_t), void (*release) (void *)) ; Purpose: @@ -510,13 +556,6 @@ workspace for M or count arrays using the "allocate" routine passed into symamd). - -999 internal error. colamd failed to order the - matrix M, when it should have succeeded. This - indicates a bug. If this (and *only* this) - error code occurs, please contact the authors. - Don't contact the authors if you get any other - error code. - Future versions may return more statistics in the stats array. void * (*allocate) (size_t, size_t) @@ -543,6 +582,7 @@ #include "colamd.h" colamd_report (int stats [COLAMD_STATS]) ; + colamd_l_report (long stats [COLAMD_STATS]) ; Purpose: @@ -563,6 +603,7 @@ #include "colamd.h" symamd_report (int stats [COLAMD_STATS]) ; + symamd_l_report (long stats [COLAMD_STATS]) ; Purpose: @@ -584,7 +625,11 @@ /* Ensure that debugging is turned off: */ #ifndef NDEBUG #define NDEBUG -#endif /* NDEBUG */ +#endif + +/* turn on debugging by uncommenting the following line + #undef NDEBUG +*/ /* Our "scaffolding code" philosophy: In our opinion, well-written library @@ -603,9 +648,7 @@ (3) (gasp!) for actually finding bugs. This code has been heavily tested and "should" be fully functional and bug-free ... but you never know... - To enable debugging, comment out the "#define NDEBUG" above. For a MATLAB - mexFunction, you will also need to modify mexopts.sh to remove the -DNDEBUG - definition. The code will become outrageously slow when debugging is + The code will become outrageously slow when debugging is enabled. To control the level of debugging output, set an environment variable D to 0 (little), 1 (some), 2, 3, or 4 (lots). When debugging, you should see the following message on the standard output: @@ -623,14 +666,115 @@ #include "colamd.h" #include <limits.h> +#include <math.h> #ifdef MATLAB_MEX_FILE #include "mex.h" #include "matrix.h" -#else +#endif /* MATLAB_MEX_FILE */ + +#if !defined (NPRINT) || !defined (NDEBUG) #include <stdio.h> -#include <assert.h> -#endif /* MATLAB_MEX_FILE */ +#endif + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +/* ========================================================================== */ +/* === int or long ========================================================== */ +/* ========================================================================== */ + +#ifdef DLONG + +#define Int long +#define ID "%ld" +#define Int_MAX LONG_MAX +#define COLAMD_recommended colamd_l_recommended +#define COLAMD_set_defaults colamd_l_set_defaults +#define COLAMD_MAIN colamd_l +#define SYMAMD_MAIN symamd_l +#define COLAMD_report colamd_l_report +#define SYMAMD_report symamd_l_report + +#else + +#define Int int +#define ID "%d" +#define Int_MAX INT_MAX +#define COLAMD_recommended colamd_recommended +#define COLAMD_set_defaults colamd_set_defaults +#define COLAMD_MAIN colamd +#define SYMAMD_MAIN symamd +#define COLAMD_report colamd_report +#define SYMAMD_report symamd_report + +#endif + +/* ========================================================================== */ +/* === Row and Column structures ============================================ */ +/* ========================================================================== */ + +/* User code that makes use of the colamd/symamd routines need not directly */ +/* reference these structures. They are used only for the COLAMD_RECOMMENDED */ +/* macro. */ + +typedef struct Colamd_Col_struct +{ + Int start ; /* index for A of first row in this column, or DEAD */ + /* if column is dead */ + Int length ; /* number of rows in this column */ + union + { + Int thickness ; /* number of original columns represented by this */ + /* col, if the column is alive */ + Int parent ; /* parent in parent tree super-column structure, if */ + /* the column is dead */ + } shared1 ; + union + { + Int score ; /* the score used to maintain heap, if col is alive */ + Int order ; /* pivot ordering of this column, if col is dead */ + } shared2 ; + union + { + Int headhash ; /* head of a hash bucket, if col is at the head of */ + /* a degree list */ + Int hash ; /* hash value, if col is not in a degree list */ + Int prev ; /* previous column in degree list, if col is in a */ + /* degree list (but not at the head of a degree list) */ + } shared3 ; + union + { + Int degree_next ; /* next column, if col is in a degree list */ + Int hash_next ; /* next column, if col is in a hash list */ + } shared4 ; + +} Colamd_Col ; + +typedef struct Colamd_Row_struct +{ + Int start ; /* index for A of first col in this row */ + Int length ; /* number of principal columns in this row */ + union + { + Int degree ; /* number of principal & non-principal columns in row */ + Int p ; /* used as a row pointer in init_rows_cols () */ + } shared1 ; + union + { + Int mark ; /* for computing set differences and marking dead rows*/ + Int first_column ;/* first column in row (used in garbage collection) */ + } shared2 ; + +} Colamd_Row ; + +/* size of the Col and Row structures */ +#define COLAMD_C(n_col) \ + ((Int) (((n_col) + 1) * sizeof (Colamd_Col) / sizeof (Int))) + +#define COLAMD_R(n_row) \ + ((Int) (((n_row) + 1) * sizeof (Colamd_Row) / sizeof (Int))) /* ========================================================================== */ /* === Definitions ========================================================== */ @@ -640,6 +784,9 @@ #define PUBLIC #define PRIVATE static +#define DENSE_DEGREE(alpha,n) \ + ((Int) MAX (16.0, (alpha) * sqrt ((double) (n)))) + #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) @@ -684,111 +831,105 @@ /* === Colamd reporting mechanism =========================================== */ /* ========================================================================== */ -#ifdef MATLAB_MEX_FILE - -/* use mexPrintf in a MATLAB mexFunction, for debugging and statistics output */ -#define PRINTF mexPrintf - +#if defined (MATLAB_MEX_FILE) || defined (MATHWORKS) /* In MATLAB, matrices are 1-based to the user, but 0-based internally */ #define INDEX(i) ((i)+1) - #else - -/* Use printf in standard C environment, for debugging and statistics output. */ -/* Output is generated only if debugging is enabled at compile time, or if */ -/* the caller explicitly calls colamd_report or symamd_report. */ -#define PRINTF printf - /* In C, matrices are 0-based and indices are reported as such in *_report */ #define INDEX(i) (i) - -#endif /* MATLAB_MEX_FILE */ +#endif + +/* All output goes through the PRINTF macro. */ +#define PRINTF(params) { if (colamd_printf != NULL) (void) colamd_printf params ; } /* ========================================================================== */ /* === Prototypes of PRIVATE routines ======================================= */ /* ========================================================================== */ -PRIVATE int init_rows_cols +PRIVATE Int init_rows_cols ( - int n_row, - int n_col, + Int n_row, + Int n_col, Colamd_Row Row [], Colamd_Col Col [], - int A [], - int p [], - int stats [COLAMD_STATS] + Int A [], + Int p [], + Int stats [COLAMD_STATS] ) ; PRIVATE void init_scoring ( - int n_row, - int n_col, + Int n_row, + Int n_col, Colamd_Row Row [], Colamd_Col Col [], - int A [], - int head [], + Int A [], + Int head [], double knobs [COLAMD_KNOBS], - int *p_n_row2, - int *p_n_col2, - int *p_max_deg + Int *p_n_row2, + Int *p_n_col2, + Int *p_max_deg ) ; -PRIVATE int find_ordering +PRIVATE Int find_ordering ( - int n_row, - int n_col, - int Alen, + Int n_row, + Int n_col, + Int Alen, Colamd_Row Row [], Colamd_Col Col [], - int A [], - int head [], - int n_col2, - int max_deg, - int pfree + Int A [], + Int head [], + Int n_col2, + Int max_deg, + Int pfree, + Int aggressive ) ; PRIVATE void order_children ( - int n_col, + Int n_col, Colamd_Col Col [], - int p [] + Int p [] ) ; PRIVATE void detect_super_cols ( #ifndef NDEBUG - int n_col, + Int n_col, Colamd_Row Row [], #endif /* NDEBUG */ Colamd_Col Col [], - int A [], - int head [], - int row_start, - int row_length + Int A [], + Int head [], + Int row_start, + Int row_length ) ; -PRIVATE int garbage_collection +PRIVATE Int garbage_collection ( - int n_row, - int n_col, + Int n_row, + Int n_col, Colamd_Row Row [], Colamd_Col Col [], - int A [], - int *pfree + Int A [], + Int *pfree ) ; -PRIVATE int clear_mark +PRIVATE Int clear_mark ( - int n_row, + Int tag_mark, + Int max_mark, + Int n_row, Colamd_Row Row [] ) ; PRIVATE void print_report ( char *method, - int stats [COLAMD_STATS] + Int stats [COLAMD_STATS] ) ; /* ========================================================================== */ @@ -797,16 +938,18 @@ #ifndef NDEBUG +#include <assert.h> + /* colamd_debug is the *ONLY* global variable, and is only */ /* present when debugging */ -PRIVATE int colamd_debug ; /* debug print level */ - -#define DEBUG0(params) { (void) PRINTF params ; } -#define DEBUG1(params) { if (colamd_debug >= 1) (void) PRINTF params ; } -#define DEBUG2(params) { if (colamd_debug >= 2) (void) PRINTF params ; } -#define DEBUG3(params) { if (colamd_debug >= 3) (void) PRINTF params ; } -#define DEBUG4(params) { if (colamd_debug >= 4) (void) PRINTF params ; } +PRIVATE Int colamd_debug = 0 ; /* debug print level */ + +#define DEBUG0(params) { PRINTF (params) ; } +#define DEBUG1(params) { if (colamd_debug >= 1) PRINTF (params) ; } +#define DEBUG2(params) { if (colamd_debug >= 2) PRINTF (params) ; } +#define DEBUG3(params) { if (colamd_debug >= 3) PRINTF (params) ; } +#define DEBUG4(params) { if (colamd_debug >= 4) PRINTF (params) ; } #ifdef MATLAB_MEX_FILE #define ASSERT(expression) (mxAssert ((expression), "")) @@ -821,41 +964,41 @@ PRIVATE void debug_deg_lists ( - int n_row, - int n_col, + Int n_row, + Int n_col, Colamd_Row Row [], Colamd_Col Col [], - int head [], - int min_score, - int should, - int max_deg + Int head [], + Int min_score, + Int should, + Int max_deg ) ; PRIVATE void debug_mark ( - int n_row, + Int n_row, Colamd_Row Row [], - int tag_mark, - int max_mark + Int tag_mark, + Int max_mark ) ; PRIVATE void debug_matrix ( - int n_row, - int n_col, + Int n_row, + Int n_col, Colamd_Row Row [], Colamd_Col Col [], - int A [] + Int A [] ) ; PRIVATE void debug_structures ( - int n_row, - int n_col, + Int n_row, + Int n_col, Colamd_Row Row [], Colamd_Col Col [], - int A [], - int n_col2 + Int A [], + Int n_col2 ) ; #else /* NDEBUG */ @@ -868,19 +1011,14 @@ #define DEBUG3(params) ; #define DEBUG4(params) ; -#define ASSERT(expression) ((void) 0) +#define ASSERT(expression) #endif /* NDEBUG */ /* ========================================================================== */ - - - -/* ========================================================================== */ /* === USER-CALLABLE ROUTINES: ============================================== */ /* ========================================================================== */ - /* ========================================================================== */ /* === colamd_recommended =================================================== */ /* ========================================================================== */ @@ -892,17 +1030,54 @@ 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. + + The recommended length Alen of the array A passed to colamd is given by + the COLAMD_RECOMMENDED (nnz, n_row, n_col) macro. It returns -1 if any + argument is negative. 2*nnz space is required for the row and column + indices of the matrix. COLAMD_C (n_col) + COLAMD_R (n_row) space is + required for the Col and Row arrays, respectively, which are internal to + colamd. An additional n_col space is the minimal amount of "elbow room", + and nnz/5 more space is recommended for run time efficiency. + + This macro is not needed when using symamd. + + Explicit typecast to Int added Sept. 23, 2002, COLAMD version 2.2, to avoid + gcc -pedantic warning messages. + + Change in version 2.4: + The COLAMD_RECOMMEND macro does not check for integer overflow, but the + routine colamd_recommended does. The macro is thus no longer available + to the user. */ -PUBLIC int colamd_recommended /* returns recommended value of Alen. */ +#define COLAMD_RECOMMENDED(nnz, n_row, n_col) \ +( \ +((nnz) < 0 || (n_row) < 0 || (n_col) < 0) \ +? \ + (-1) \ +: \ + (2 * (nnz) + COLAMD_C (n_col) + COLAMD_R (n_row) + (n_col) + ((nnz) / 5)) \ +) + +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 */ + Int nnz, /* number of nonzeros in A */ + Int n_row, /* number of rows in A */ + Int n_col /* number of columns in A */ ) { + double xnz = nnz ; + double xncol = n_col ; + double xnrow = n_row ; + + /* change for version 2.4: check Alen for integer overflow */ + if (COLAMD_RECOMMENDED (xnz, xnrow, xncol) >= INT_MAX) + { + return (-1) ; + } + return (COLAMD_RECOMMENDED (nnz, n_row, n_col)) ; } @@ -928,7 +1103,7 @@ knobs [2..19] unused, but future versions might use this */ -PUBLIC void colamd_set_defaults +PUBLIC void COLAMD_set_defaults ( /* === Parameters ======================================================= */ @@ -937,7 +1112,7 @@ { /* === Local variables ================================================== */ - int i ; + Int i ; if (!knobs) { @@ -947,8 +1122,9 @@ { 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 */ + knobs [COLAMD_DENSE_ROW] = 10 ; + knobs [COLAMD_DENSE_COL] = 10 ; + knobs [COLAMD_AGGRESSIVE] = TRUE ; /* default: do aggressive absorption*/ } @@ -956,16 +1132,16 @@ /* === symamd =============================================================== */ /* ========================================================================== */ -PUBLIC int symamd /* return TRUE if OK, FALSE otherwise */ +PUBLIC Int SYMAMD_MAIN /* 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 */ + 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 */ + 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) */ @@ -976,23 +1152,22 @@ { /* === 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 */ + 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") ; @@ -1056,13 +1231,13 @@ if (!knobs) { - colamd_set_defaults (default_knobs) ; + COLAMD_set_defaults (default_knobs) ; knobs = default_knobs ; } /* === Allocate count and mark ========================================== */ - count = (int *) ((*allocate) (n+1, sizeof (int))) ; + count = (Int *) ((*allocate) (n+1, sizeof (Int))) ; if (!count) { stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; @@ -1070,7 +1245,7 @@ return (FALSE) ; } - mark = (int *) ((*allocate) (n+1, sizeof (int))) ; + mark = (Int *) ((*allocate) (n+1, sizeof (Int))) ; if (!mark) { stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; @@ -1146,11 +1321,7 @@ } } - if (stats [COLAMD_STATUS] == COLAMD_OK) - { - /* if there are no duplicate entries, then mark is no longer needed */ - (*release) ((void *) mark) ; - } + /* v2.4: removed free(mark) */ /* === Compute column pointers of M ===================================== */ @@ -1169,8 +1340,8 @@ mnz = perm [n] ; n_row = mnz / 2 ; - Mlen = colamd_recommended (mnz, n_row, n) ; - M = (int *) ((*allocate) (Mlen, sizeof (int))) ; + 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)) ; @@ -1230,11 +1401,12 @@ } } } - (*release) ((void *) mark) ; + /* v2.4: free(mark) moved below */ } /* count and mark no longer needed */ (*release) ((void *) count) ; + (*release) ((void *) mark) ; /* v2.4: free (mark) moved here */ ASSERT (k == n_row) ; /* === Adjust the knobs for M =========================================== */ @@ -1245,41 +1417,20 @@ } /* 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])) ; + cknobs [COLAMD_DENSE_ROW] = -1 ; + cknobs [COLAMD_DENSE_COL] = knobs [COLAMD_DENSE_ROW] ; /* === 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) ; - } + /* v2.4: colamd cannot fail here, so the error check is removed */ + (void) COLAMD_MAIN (n_row, n, Mlen, M, perm, cknobs, stats) ; /* Note that the output permutation is now in perm */ /* === get the statistics for symamd from colamd ======================== */ - /* note that a dense column in colamd means a dense row and col in symamd */ - stats [COLAMD_DENSE_ROW] = cstats [COLAMD_DENSE_COL] ; - stats [COLAMD_DENSE_COL] = cstats [COLAMD_DENSE_COL] ; - stats [COLAMD_DEFRAG_COUNT] = cstats [COLAMD_DEFRAG_COUNT] ; + /* a dense column in colamd means a dense row and col in symamd */ + stats [COLAMD_DENSE_ROW] = stats [COLAMD_DENSE_COL] ; /* === Free M =========================================================== */ @@ -1301,33 +1452,34 @@ (AQ)'(AQ) = LL' remains sparse. */ -PUBLIC int colamd /* returns TRUE if successful, FALSE otherwise*/ +PUBLIC Int COLAMD_MAIN /* returns TRUE if successful, FALSE otherwise*/ ( /* === Parameters ======================================================= */ - int n_row, /* number of rows in A */ - int n_col, /* number of columns in A */ - int Alen, /* length of A */ - int A [], /* row indices of A */ - int p [], /* pointers to columns in A */ + Int n_row, /* number of rows in A */ + Int n_col, /* number of columns in A */ + Int Alen, /* length of A */ + Int A [], /* row indices of A */ + Int p [], /* pointers to columns in A */ double knobs [COLAMD_KNOBS],/* parameters (uses defaults if NULL) */ - int stats [COLAMD_STATS] /* output statistics and error codes */ + Int stats [COLAMD_STATS] /* output statistics and error codes */ ) { /* === Local variables ================================================== */ - int i ; /* loop index */ - int nnz ; /* nonzeros in A */ - int Row_size ; /* size of Row [], in integers */ - int Col_size ; /* size of Col [], in integers */ - int need ; /* minimum required length of A */ + Int i ; /* loop index */ + Int nnz ; /* nonzeros in A */ + Int Row_size ; /* size of Row [], in integers */ + Int Col_size ; /* size of Col [], in integers */ + Int need ; /* minimum required length of A */ Colamd_Row *Row ; /* pointer into A of Row [0..n_row] array */ Colamd_Col *Col ; /* pointer into A of Col [0..n_col] array */ - int n_col2 ; /* number of non-dense, non-empty columns */ - int n_row2 ; /* number of non-dense, non-empty rows */ - int ngarbage ; /* number of garbage collections performed */ - int max_deg ; /* maximum row degree */ + Int n_col2 ; /* number of non-dense, non-empty columns */ + Int n_row2 ; /* number of non-dense, non-empty rows */ + Int ngarbage ; /* number of garbage collections performed */ + Int max_deg ; /* maximum row degree */ double default_knobs [COLAMD_KNOBS] ; /* default knobs array */ + Int aggressive ; /* do aggressive absorption */ #ifndef NDEBUG colamd_get_debug ("colamd") ; @@ -1399,10 +1551,12 @@ if (!knobs) { - colamd_set_defaults (default_knobs) ; + COLAMD_set_defaults (default_knobs) ; knobs = default_knobs ; } + aggressive = (knobs [COLAMD_AGGRESSIVE] != FALSE) ; + /* === Allocate the Row and Col arrays from array A ===================== */ Col_size = COLAMD_C (n_col) ; @@ -1440,7 +1594,7 @@ /* === Order the supercolumns =========================================== */ ngarbage = find_ordering (n_row, n_col, Alen, Row, Col, A, p, - n_col2, max_deg, 2*nnz) ; + n_col2, max_deg, 2*nnz, aggressive) ; /* === Order the non-principal columns ================================== */ @@ -1460,9 +1614,9 @@ /* === colamd_report ======================================================== */ /* ========================================================================== */ -PUBLIC void colamd_report +PUBLIC void COLAMD_report ( - int stats [COLAMD_STATS] + Int stats [COLAMD_STATS] ) { print_report ("colamd", stats) ; @@ -1473,9 +1627,9 @@ /* === symamd_report ======================================================== */ /* ========================================================================== */ -PUBLIC void symamd_report +PUBLIC void SYMAMD_report ( - int stats [COLAMD_STATS] + Int stats [COLAMD_STATS] ) { print_report ("symamd", stats) ; @@ -1503,28 +1657,28 @@ TRUE otherwise. Not user-callable. */ -PRIVATE int init_rows_cols /* returns TRUE if OK, or FALSE otherwise */ +PRIVATE Int init_rows_cols /* returns TRUE if OK, or FALSE otherwise */ ( /* === Parameters ======================================================= */ - int n_row, /* number of rows of A */ - int n_col, /* number of columns of A */ + Int n_row, /* number of rows of A */ + Int n_col, /* number of columns of A */ Colamd_Row Row [], /* of size n_row+1 */ Colamd_Col Col [], /* of size n_col+1 */ - int A [], /* row indices of A, of size Alen */ - int p [], /* pointers to columns in A, of size n_col+1 */ - int stats [COLAMD_STATS] /* colamd statistics */ + Int A [], /* row indices of A, of size Alen */ + Int p [], /* pointers to columns in A, of size n_col+1 */ + Int stats [COLAMD_STATS] /* colamd statistics */ ) { /* === Local variables ================================================== */ - int col ; /* a column index */ - int row ; /* a row index */ - int *cp ; /* a column pointer */ - int *cp_end ; /* a pointer to the end of a column */ - int *rp ; /* a row pointer */ - int *rp_end ; /* a pointer to the end of a row */ - int last_row ; /* previous row */ + Int col ; /* a column index */ + Int row ; /* a row index */ + Int *cp ; /* a column pointer */ + Int *cp_end ; /* a pointer to the end of a column */ + Int *rp ; /* a row pointer */ + Int *rp_end ; /* a pointer to the end of a row */ + Int last_row ; /* previous row */ /* === Initialize columns, and check column pointers ==================== */ @@ -1744,44 +1898,63 @@ ( /* === Parameters ======================================================= */ - int n_row, /* number of rows of A */ - int n_col, /* number of columns of A */ + Int n_row, /* number of rows of A */ + Int n_col, /* number of columns of A */ Colamd_Row Row [], /* of size n_row+1 */ Colamd_Col Col [], /* of size n_col+1 */ - int A [], /* column form and row form of A */ - int head [], /* of size n_col+1 */ + Int A [], /* column form and row form of A */ + Int head [], /* of size n_col+1 */ double knobs [COLAMD_KNOBS],/* parameters */ - int *p_n_row2, /* number of non-dense, non-empty rows */ - int *p_n_col2, /* number of non-dense, non-empty columns */ - int *p_max_deg /* maximum row degree */ + Int *p_n_row2, /* number of non-dense, non-empty rows */ + Int *p_n_col2, /* number of non-dense, non-empty columns */ + Int *p_max_deg /* maximum row degree */ ) { /* === Local variables ================================================== */ - int c ; /* a column index */ - int r, row ; /* a row index */ - int *cp ; /* a column pointer */ - int deg ; /* degree of a row or column */ - int *cp_end ; /* a pointer to the end of a column */ - int *new_cp ; /* new column pointer */ - int col_length ; /* length of pruned column */ - int score ; /* current column score */ - int n_col2 ; /* number of non-dense, non-empty columns */ - int n_row2 ; /* number of non-dense, non-empty rows */ - int dense_row_count ; /* remove rows with more entries than this */ - int dense_col_count ; /* remove cols with more entries than this */ - int min_score ; /* smallest column score */ - int max_deg ; /* maximum row degree */ - int next_col ; /* Used to add to degree list.*/ + Int c ; /* a column index */ + Int r, row ; /* a row index */ + Int *cp ; /* a column pointer */ + Int deg ; /* degree of a row or column */ + Int *cp_end ; /* a pointer to the end of a column */ + Int *new_cp ; /* new column pointer */ + Int col_length ; /* length of pruned column */ + Int score ; /* current column score */ + Int n_col2 ; /* number of non-dense, non-empty columns */ + Int n_row2 ; /* number of non-dense, non-empty rows */ + Int dense_row_count ; /* remove rows with more entries than this */ + Int dense_col_count ; /* remove cols with more entries than this */ + Int min_score ; /* smallest column score */ + Int max_deg ; /* maximum row degree */ + Int next_col ; /* Used to add to degree list.*/ #ifndef NDEBUG - int debug_count ; /* debug only. */ + Int debug_count ; /* debug only. */ #endif /* NDEBUG */ /* === Extract knobs ==================================================== */ - dense_row_count = MAX (0, MIN (knobs [COLAMD_DENSE_ROW] * n_col, n_col)) ; - dense_col_count = MAX (0, MIN (knobs [COLAMD_DENSE_COL] * n_row, n_row)) ; + /* Note: if knobs contains a NaN, this is undefined: */ + if (knobs [COLAMD_DENSE_ROW] < 0) + { + /* only remove completely dense rows */ + dense_row_count = n_col-1 ; + } + else + { + dense_row_count = DENSE_DEGREE (knobs [COLAMD_DENSE_ROW], n_col) ; + } + if (knobs [COLAMD_DENSE_COL] < 0) + { + /* only remove completely dense columns */ + dense_col_count = n_row-1 ; + } + else + { + dense_col_count = + DENSE_DEGREE (knobs [COLAMD_DENSE_COL], MIN (n_row, n_col)) ; + } + DEBUG1 (("colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ; max_deg = 0 ; n_col2 = n_col ; @@ -1886,7 +2059,7 @@ score = MIN (score, n_col) ; } /* determine pruned column length */ - col_length = (int) (new_cp - &A [Col [c].start]) ; + col_length = (Int) (new_cp - &A [Col [c].start]) ; if (col_length == 0) { /* a newly-made null column (all rows in this col are "dense" */ @@ -1996,65 +2169,66 @@ degree ordering method. Not user-callable. */ -PRIVATE int find_ordering /* return the number of garbage collections */ +PRIVATE Int find_ordering /* return the number of garbage collections */ ( /* === Parameters ======================================================= */ - int n_row, /* number of rows of A */ - int n_col, /* number of columns of A */ - int Alen, /* size of A, 2*nnz + n_col or larger */ + Int n_row, /* number of rows of A */ + Int n_col, /* number of columns of A */ + Int Alen, /* size of A, 2*nnz + n_col or larger */ Colamd_Row Row [], /* of size n_row+1 */ Colamd_Col Col [], /* of size n_col+1 */ - int A [], /* column form and row form of A */ - int head [], /* of size n_col+1 */ - int n_col2, /* Remaining columns to order */ - int max_deg, /* Maximum row degree */ - int pfree /* index of first free slot (2*nnz on entry) */ + Int A [], /* column form and row form of A */ + Int head [], /* of size n_col+1 */ + Int n_col2, /* Remaining columns to order */ + Int max_deg, /* Maximum row degree */ + Int pfree, /* index of first free slot (2*nnz on entry) */ + Int aggressive ) { /* === Local variables ================================================== */ - int k ; /* current pivot ordering step */ - int pivot_col ; /* current pivot column */ - int *cp ; /* a column pointer */ - int *rp ; /* a row pointer */ - int pivot_row ; /* current pivot row */ - int *new_cp ; /* modified column pointer */ - int *new_rp ; /* modified row pointer */ - int pivot_row_start ; /* pointer to start of pivot row */ - int pivot_row_degree ; /* number of columns in pivot row */ - int pivot_row_length ; /* number of supercolumns in pivot row */ - int pivot_col_score ; /* score of pivot column */ - int needed_memory ; /* free space needed for pivot row */ - int *cp_end ; /* pointer to the end of a column */ - int *rp_end ; /* pointer to the end of a row */ - int row ; /* a row index */ - int col ; /* a column index */ - int max_score ; /* maximum possible score */ - int cur_score ; /* score of current column */ - unsigned int hash ; /* hash value for supernode detection */ - int head_column ; /* head of hash bucket */ - int first_col ; /* first column in hash bucket */ - int tag_mark ; /* marker value for mark array */ - int row_mark ; /* Row [row].shared2.mark */ - int set_difference ; /* set difference size of row with pivot row */ - int min_score ; /* smallest column score */ - int col_thickness ; /* "thickness" (no. of columns in a supercol) */ - int max_mark ; /* maximum value of tag_mark */ - int pivot_col_thickness ; /* number of columns represented by pivot col */ - int prev_col ; /* Used by Dlist operations. */ - int next_col ; /* Used by Dlist operations. */ - int ngarbage ; /* number of garbage collections performed */ + Int k ; /* current pivot ordering step */ + Int pivot_col ; /* current pivot column */ + Int *cp ; /* a column pointer */ + Int *rp ; /* a row pointer */ + Int pivot_row ; /* current pivot row */ + Int *new_cp ; /* modified column pointer */ + Int *new_rp ; /* modified row pointer */ + Int pivot_row_start ; /* pointer to start of pivot row */ + Int pivot_row_degree ; /* number of columns in pivot row */ + Int pivot_row_length ; /* number of supercolumns in pivot row */ + Int pivot_col_score ; /* score of pivot column */ + Int needed_memory ; /* free space needed for pivot row */ + Int *cp_end ; /* pointer to the end of a column */ + Int *rp_end ; /* pointer to the end of a row */ + Int row ; /* a row index */ + Int col ; /* a column index */ + Int max_score ; /* maximum possible score */ + Int cur_score ; /* score of current column */ + unsigned Int hash ; /* hash value for supernode detection */ + Int head_column ; /* head of hash bucket */ + Int first_col ; /* first column in hash bucket */ + Int tag_mark ; /* marker value for mark array */ + Int row_mark ; /* Row [row].shared2.mark */ + Int set_difference ; /* set difference size of row with pivot row */ + Int min_score ; /* smallest column score */ + Int col_thickness ; /* "thickness" (no. of columns in a supercol) */ + Int max_mark ; /* maximum value of tag_mark */ + Int pivot_col_thickness ; /* number of columns represented by pivot col */ + Int prev_col ; /* Used by Dlist operations. */ + Int next_col ; /* Used by Dlist operations. */ + Int ngarbage ; /* number of garbage collections performed */ #ifndef NDEBUG - int debug_d ; /* debug loop counter */ - int debug_step = 0 ; /* debug loop counter */ + Int debug_d ; /* debug loop counter */ + Int debug_step = 0 ; /* debug loop counter */ #endif /* NDEBUG */ /* === Initialization and clear mark ==================================== */ max_mark = INT_MAX - n_col ; /* INT_MAX defined in <limits.h> */ - tag_mark = clear_mark (n_row, Row) ; + tag_mark = clear_mark (0, max_mark, n_row, Row) ; min_score = 0 ; ngarbage = 0 ; DEBUG1 (("colamd: Ordering, n_col2=%d\n", n_col2)) ; @@ -2108,7 +2282,6 @@ } ASSERT (COL_IS_ALIVE (pivot_col)) ; - DEBUG3 (("Pivot col: %d\n", pivot_col)) ; /* remember score for defrag check */ pivot_col_score = Col [pivot_col].shared2.score ; @@ -2120,6 +2293,7 @@ pivot_col_thickness = Col [pivot_col].shared1.thickness ; k += pivot_col_thickness ; ASSERT (pivot_col_thickness > 0) ; + DEBUG3 (("Pivot col: %d thick %d\n", pivot_col, pivot_col_thickness)) ; /* === Garbage_collection, if necessary ============================= */ @@ -2131,7 +2305,7 @@ /* after garbage collection we will have enough */ ASSERT (pfree + needed_memory < Alen) ; /* garbage collection has wiped out the Row[].shared2.mark array */ - tag_mark = clear_mark (n_row, Row) ; + tag_mark = clear_mark (0, max_mark, n_row, Row) ; #ifndef NDEBUG debug_matrix (n_row, n_col, Row, Col, A) ; @@ -2159,26 +2333,25 @@ row = *cp++ ; DEBUG4 (("Pivot col pattern %d %d\n", ROW_IS_ALIVE (row), row)) ; /* skip if row is dead */ - if (ROW_IS_DEAD (row)) - { - continue ; - } - rp = &A [Row [row].start] ; - rp_end = rp + Row [row].length ; - while (rp < rp_end) + if (ROW_IS_ALIVE (row)) { - /* get a column */ - col = *rp++ ; - /* add the column, if alive and untagged */ - col_thickness = Col [col].shared1.thickness ; - if (col_thickness > 0 && COL_IS_ALIVE (col)) + rp = &A [Row [row].start] ; + rp_end = rp + Row [row].length ; + while (rp < rp_end) { - /* tag column in pivot row */ - Col [col].shared1.thickness = -col_thickness ; - ASSERT (pfree < Alen) ; - /* place column in pivot row */ - A [pfree++] = col ; - pivot_row_degree += col_thickness ; + /* get a column */ + col = *rp++ ; + /* add the column, if alive and untagged */ + col_thickness = Col [col].shared1.thickness ; + if (col_thickness > 0 && COL_IS_ALIVE (col)) + { + /* tag column in pivot row */ + Col [col].shared1.thickness = -col_thickness ; + ASSERT (pfree < Alen) ; + /* place column in pivot row */ + A [pfree++] = col ; + pivot_row_degree += col_thickness ; + } } } } @@ -2309,7 +2482,7 @@ set_difference -= col_thickness ; ASSERT (set_difference >= 0) ; /* absorb this row if the set difference becomes zero */ - if (set_difference == 0) + if (set_difference == 0 && aggressive) { DEBUG3 (("aggressive absorption. Row: %d\n", row)) ; KILL_ROW (row) ; @@ -2357,9 +2530,11 @@ /* skip if dead */ if (ROW_IS_MARKED_DEAD (row_mark)) { + DEBUG4 ((" Row %d, dead\n", row)) ; continue ; } - ASSERT (row_mark > tag_mark) ; + DEBUG4 ((" Row %d, set diff %d\n", row, row_mark-tag_mark)); + ASSERT (row_mark >= tag_mark) ; /* compact the column */ *new_cp++ = row ; /* compute hash function */ @@ -2371,7 +2546,7 @@ } /* recompute the column's length */ - Col [col].length = (int) (new_cp - &A [Col [col].start]) ; + Col [col].length = (Int) (new_cp - &A [Col [col].start]) ; /* === Further mass elimination ================================= */ @@ -2400,7 +2575,7 @@ hash %= n_col + 1 ; DEBUG4 ((" Hash = %d, n_col = %d.\n", hash, n_col)) ; - ASSERT (hash <= n_col) ; + ASSERT (((Int) hash) <= n_col) ; head_column = head [hash] ; if (head_column > EMPTY) @@ -2419,7 +2594,7 @@ Col [col].shared4.hash_next = first_col ; /* save hash function in Col [col].shared3.hash */ - Col [col].shared3.hash = (int) hash ; + Col [col].shared3.hash = (Int) hash ; ASSERT (COL_IS_ALIVE (col)) ; } } @@ -2444,12 +2619,7 @@ /* === Clear mark =================================================== */ - tag_mark += (max_deg + 1) ; - if (tag_mark >= max_mark) - { - DEBUG2 (("clearing tag_mark\n")) ; - tag_mark = clear_mark (n_row, Row) ; - } + tag_mark = clear_mark (tag_mark+max_deg+1, max_mark, n_row, Row) ; #ifndef NDEBUG DEBUG3 (("check3\n")) ; @@ -2530,10 +2700,14 @@ /* update pivot row length to reflect any cols that were killed */ /* during super-col detection and mass elimination */ Row [pivot_row].start = pivot_row_start ; - Row [pivot_row].length = (int) (new_rp - &A[pivot_row_start]) ; + Row [pivot_row].length = (Int) (new_rp - &A[pivot_row_start]) ; + ASSERT (Row [pivot_row].length > 0) ; Row [pivot_row].shared1.degree = pivot_row_degree ; Row [pivot_row].shared2.mark = 0 ; /* pivot row is no longer dead */ + + DEBUG1 (("Resurrect Pivot_row %d deg: %d\n", + pivot_row, pivot_row_degree)) ; } } @@ -2564,17 +2738,17 @@ ( /* === Parameters ======================================================= */ - int n_col, /* number of columns of A */ + Int n_col, /* number of columns of A */ Colamd_Col Col [], /* of size n_col+1 */ - int p [] /* p [0 ... n_col-1] is the column permutation*/ + Int p [] /* p [0 ... n_col-1] is the column permutation*/ ) { /* === Local variables ================================================== */ - int i ; /* loop counter for all columns */ - int c ; /* column index */ - int parent ; /* index of column's parent */ - int order ; /* column's order */ + Int i ; /* loop counter for all columns */ + Int c ; /* column index */ + Int parent ; /* index of column's parent */ + Int order ; /* column's order */ /* === Order each non-principal column ================================== */ @@ -2667,32 +2841,32 @@ #ifndef NDEBUG /* these two parameters are only needed when debugging is enabled: */ - int n_col, /* number of columns of A */ + Int n_col, /* number of columns of A */ Colamd_Row Row [], /* of size n_row+1 */ #endif /* NDEBUG */ Colamd_Col Col [], /* of size n_col+1 */ - int A [], /* row indices of A */ - int head [], /* head of degree lists and hash buckets */ - int row_start, /* pointer to set of columns to check */ - int row_length /* number of columns to check */ + Int A [], /* row indices of A */ + Int head [], /* head of degree lists and hash buckets */ + Int row_start, /* pointer to set of columns to check */ + Int row_length /* number of columns to check */ ) { /* === Local variables ================================================== */ - int hash ; /* hash value for a column */ - int *rp ; /* pointer to a row */ - int c ; /* a column index */ - int super_c ; /* column index of the column to absorb into */ - int *cp1 ; /* column pointer for column super_c */ - int *cp2 ; /* column pointer for column c */ - int length ; /* length of column super_c */ - int prev_c ; /* column preceding c in hash bucket */ - int i ; /* loop counter */ - int *rp_end ; /* pointer to the end of the row */ - int col ; /* a column index in the row to check */ - int head_column ; /* first column in hash bucket or degree list */ - int first_col ; /* first column in hash bucket */ + Int hash ; /* hash value for a column */ + Int *rp ; /* pointer to a row */ + Int c ; /* a column index */ + Int super_c ; /* column index of the column to absorb into */ + Int *cp1 ; /* column pointer for column super_c */ + Int *cp2 ; /* column pointer for column c */ + Int length ; /* length of column super_c */ + Int prev_c ; /* column preceding c in hash bucket */ + Int i ; /* loop counter */ + Int *rp_end ; /* pointer to the end of the row */ + Int col ; /* a column index in the row to check */ + Int head_column ; /* first column in hash bucket or degree list */ + Int first_col ; /* first column in hash bucket */ /* === Consider each column in the row ================================== */ @@ -2818,29 +2992,29 @@ Not user-callable. */ -PRIVATE int garbage_collection /* returns the new value of pfree */ +PRIVATE Int garbage_collection /* returns the new value of pfree */ ( /* === Parameters ======================================================= */ - int n_row, /* number of rows */ - int n_col, /* number of columns */ + Int n_row, /* number of rows */ + Int n_col, /* number of columns */ Colamd_Row Row [], /* row info */ Colamd_Col Col [], /* column info */ - int A [], /* A [0 ... Alen-1] holds the matrix */ - int *pfree /* &A [0] ... pfree is in use */ + Int A [], /* A [0 ... Alen-1] holds the matrix */ + Int *pfree /* &A [0] ... pfree is in use */ ) { /* === Local variables ================================================== */ - int *psrc ; /* source pointer */ - int *pdest ; /* destination pointer */ - int j ; /* counter */ - int r ; /* a row index */ - int c ; /* a column index */ - int length ; /* length of a row or column */ + Int *psrc ; /* source pointer */ + Int *pdest ; /* destination pointer */ + Int j ; /* counter */ + Int r ; /* a row index */ + Int c ; /* a column index */ + Int length ; /* length of a row or column */ #ifndef NDEBUG - int debug_rows ; + Int debug_rows ; DEBUG2 (("Defrag..\n")) ; for (psrc = &A[0] ; psrc < pfree ; psrc++) ASSERT (*psrc >= 0) ; debug_rows = 0 ; @@ -2857,7 +3031,7 @@ /* move and compact the column */ ASSERT (pdest <= psrc) ; - Col [c].start = (int) (pdest - &A [0]) ; + Col [c].start = (Int) (pdest - &A [0]) ; length = Col [c].length ; for (j = 0 ; j < length ; j++) { @@ -2867,7 +3041,7 @@ *pdest++ = r ; } } - Col [c].length = (int) (pdest - &A [Col [c].start]) ; + Col [c].length = (Int) (pdest - &A [Col [c].start]) ; } } @@ -2875,28 +3049,25 @@ for (r = 0 ; r < n_row ; r++) { - if (ROW_IS_ALIVE (r)) + if (ROW_IS_DEAD (r) || (Row [r].length == 0)) + { + /* This row is already dead, or is of zero length. Cannot compact + * a row of zero length, so kill it. NOTE: in the current version, + * there are no zero-length live rows. Kill the row (for the first + * time, or again) just to be safe. */ + KILL_ROW (r) ; + } + else { - if (Row [r].length == 0) - { - /* this row is of zero length. cannot compact it, so kill it */ - DEBUG3 (("Defrag row kill\n")) ; - KILL_ROW (r) ; - } - else - { - /* save first column index in Row [r].shared2.first_column */ - psrc = &A [Row [r].start] ; - Row [r].shared2.first_column = *psrc ; - ASSERT (ROW_IS_ALIVE (r)) ; - /* flag the start of the row with the one's complement of row */ - *psrc = ONES_COMPLEMENT (r) ; - + /* save first column index in Row [r].shared2.first_column */ + psrc = &A [Row [r].start] ; + Row [r].shared2.first_column = *psrc ; + ASSERT (ROW_IS_ALIVE (r)) ; + /* flag the start of the row with the one's complement of row */ + *psrc = ONES_COMPLEMENT (r) ; #ifndef NDEBUG - debug_rows++ ; + debug_rows++ ; #endif /* NDEBUG */ - - } } } @@ -2915,10 +3086,10 @@ /* restore first column index */ *psrc = Row [r].shared2.first_column ; ASSERT (ROW_IS_ALIVE (r)) ; - + ASSERT (Row [r].length > 0) ; /* move and compact the row */ ASSERT (pdest <= psrc) ; - Row [r].start = (int) (pdest - &A [0]) ; + Row [r].start = (Int) (pdest - &A [0]) ; length = Row [r].length ; for (j = 0 ; j < length ; j++) { @@ -2928,12 +3099,11 @@ *pdest++ = c ; } } - Row [r].length = (int) (pdest - &A [Row [r].start]) ; - + Row [r].length = (Int) (pdest - &A [Row [r].start]) ; + ASSERT (Row [r].length > 0) ; #ifndef NDEBUG debug_rows-- ; #endif /* NDEBUG */ - } } /* ensure we found all the rows */ @@ -2941,7 +3111,7 @@ /* === Return the new value of pfree ==================================== */ - return ((int) (pdest - &A [0])) ; + return ((Int) (pdest - &A [0])) ; } @@ -2954,26 +3124,34 @@ Return value is the new tag_mark. Not user-callable. */ -PRIVATE int clear_mark /* return the new value for tag_mark */ +PRIVATE Int clear_mark /* return the new value for tag_mark */ ( /* === Parameters ======================================================= */ - int n_row, /* number of rows in A */ + Int tag_mark, /* new value of tag_mark */ + Int max_mark, /* max allowed value of tag_mark */ + + Int n_row, /* number of rows in A */ Colamd_Row Row [] /* Row [0 ... n_row-1].shared2.mark is set to zero */ ) { /* === Local variables ================================================== */ - int r ; - - for (r = 0 ; r < n_row ; r++) + Int r ; + + if (tag_mark <= 0 || tag_mark >= max_mark) { - if (ROW_IS_ALIVE (r)) + for (r = 0 ; r < n_row ; r++) { - Row [r].shared2.mark = 0 ; + if (ROW_IS_ALIVE (r)) + { + Row [r].shared2.mark = 0 ; + } } + tag_mark = 1 ; } - return (1) ; + + return (tag_mark) ; } @@ -2984,15 +3162,18 @@ PRIVATE void print_report ( char *method, - int stats [COLAMD_STATS] + Int stats [COLAMD_STATS] ) { - int i1, i2, i3 ; + Int i1, i2, i3 ; + + PRINTF (("\n%s version %d.%d, %s: ", method, + COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION, COLAMD_DATE)) ; if (!stats) { - PRINTF ("%s: No statistics available.\n", method) ; + PRINTF (("No statistics available.\n")) ; return ; } @@ -3002,11 +3183,11 @@ if (stats [COLAMD_STATUS] >= 0) { - PRINTF ("%s: OK. ", method) ; + PRINTF (("OK. ")) ; } else { - PRINTF ("%s: ERROR. ", method) ; + PRINTF (("ERROR. ")) ; } switch (stats [COLAMD_STATUS]) @@ -3014,95 +3195,90 @@ case COLAMD_OK_BUT_JUMBLED: - PRINTF ("Matrix has unsorted or duplicate row indices.\n") ; - - PRINTF ("%s: number of duplicate or out-of-order row indices: %d\n", - method, i3) ; - - PRINTF ("%s: last seen duplicate or out-of-order row index: %d\n", - method, INDEX (i2)) ; - - PRINTF ("%s: last seen in column: %d", - method, INDEX (i1)) ; + PRINTF(("Matrix has unsorted or duplicate row indices.\n")) ; + + PRINTF(("%s: number of duplicate or out-of-order row indices: %d\n", + method, i3)) ; + + PRINTF(("%s: last seen duplicate or out-of-order row index: %d\n", + method, INDEX (i2))) ; + + PRINTF(("%s: last seen in column: %d", + method, INDEX (i1))) ; /* no break - fall through to next case instead */ case COLAMD_OK: - PRINTF ("\n") ; - - PRINTF ("%s: number of dense or empty rows ignored: %d\n", - method, stats [COLAMD_DENSE_ROW]) ; - - PRINTF ("%s: number of dense or empty columns ignored: %d\n", - method, stats [COLAMD_DENSE_COL]) ; - - PRINTF ("%s: number of garbage collections performed: %d\n", - method, stats [COLAMD_DEFRAG_COUNT]) ; + PRINTF(("\n")) ; + + PRINTF(("%s: number of dense or empty rows ignored: %d\n", + method, stats [COLAMD_DENSE_ROW])) ; + + PRINTF(("%s: number of dense or empty columns ignored: %d\n", + method, stats [COLAMD_DENSE_COL])) ; + + PRINTF(("%s: number of garbage collections performed: %d\n", + method, stats [COLAMD_DEFRAG_COUNT])) ; break ; case COLAMD_ERROR_A_not_present: - PRINTF ("Array A (row indices of matrix) not present.\n") ; + PRINTF(("Array A (row indices of matrix) not present.\n")) ; break ; case COLAMD_ERROR_p_not_present: - PRINTF ("Array p (column pointers for matrix) not present.\n") ; + PRINTF(("Array p (column pointers for matrix) not present.\n")) ; break ; case COLAMD_ERROR_nrow_negative: - PRINTF ("Invalid number of rows (%d).\n", i1) ; + PRINTF(("Invalid number of rows (%d).\n", i1)) ; break ; case COLAMD_ERROR_ncol_negative: - PRINTF ("Invalid number of columns (%d).\n", i1) ; + PRINTF(("Invalid number of columns (%d).\n", i1)) ; break ; case COLAMD_ERROR_nnz_negative: - PRINTF ("Invalid number of nonzero entries (%d).\n", i1) ; + PRINTF(("Invalid number of nonzero entries (%d).\n", i1)) ; break ; case COLAMD_ERROR_p0_nonzero: - PRINTF ("Invalid column pointer, p [0] = %d, must be zero.\n", i1) ; + PRINTF(("Invalid column pointer, p [0] = %d, must be zero.\n", i1)); break ; case COLAMD_ERROR_A_too_small: - PRINTF ("Array A too small.\n") ; - PRINTF (" Need Alen >= %d, but given only Alen = %d.\n", - i1, i2) ; + PRINTF(("Array A too small.\n")) ; + PRINTF((" Need Alen >= %d, but given only Alen = %d.\n", + i1, i2)) ; break ; case COLAMD_ERROR_col_length_negative: PRINTF - ("Column %d has a negative number of nonzero entries (%d).\n", - INDEX (i1), i2) ; + (("Column %d has a negative number of nonzero entries (%d).\n", + INDEX (i1), i2)) ; break ; case COLAMD_ERROR_row_index_out_of_bounds: PRINTF - ("Row index (row %d) out of bounds (%d to %d) in column %d.\n", - INDEX (i2), INDEX (0), INDEX (i3-1), INDEX (i1)) ; + (("Row index (row %d) out of bounds (%d to %d) in column %d.\n", + INDEX (i2), INDEX (0), INDEX (i3-1), INDEX (i1))) ; break ; case COLAMD_ERROR_out_of_memory: - PRINTF ("Out of memory.\n") ; + PRINTF(("Out of memory.\n")) ; break ; - case COLAMD_ERROR_internal_error: - - /* if this happens, there is a bug in the code */ - PRINTF - ("Internal error! Please contact authors (davis@cise.ufl.edu).\n") ; - break ; + /* v2.4: internal-error case deleted */ } } @@ -3133,26 +3309,26 @@ ( /* === Parameters ======================================================= */ - int n_row, - int n_col, + Int n_row, + Int n_col, Colamd_Row Row [], Colamd_Col Col [], - int A [], - int n_col2 + Int A [], + Int n_col2 ) { /* === Local variables ================================================== */ - int i ; - int c ; - int *cp ; - int *cp_end ; - int len ; - int score ; - int r ; - int *rp ; - int *rp_end ; - int deg ; + Int i ; + Int c ; + Int *cp ; + Int *cp_end ; + Int len ; + Int score ; + Int r ; + Int *rp ; + Int *rp_end ; + Int deg ; /* === Check A, Row, and Col ============================================ */ @@ -3220,22 +3396,22 @@ ( /* === Parameters ======================================================= */ - int n_row, - int n_col, + Int n_row, + Int n_col, Colamd_Row Row [], Colamd_Col Col [], - int head [], - int min_score, - int should, - int max_deg + Int head [], + Int min_score, + Int should, + Int max_deg ) { /* === Local variables ================================================== */ - int deg ; - int col ; - int have ; - int row ; + Int deg ; + Int col ; + Int have ; + Int row ; /* === Check the degree lists =========================================== */ @@ -3294,15 +3470,15 @@ ( /* === Parameters ======================================================= */ - int n_row, + Int n_row, Colamd_Row Row [], - int tag_mark, - int max_mark + Int tag_mark, + Int max_mark ) { /* === Local variables ================================================== */ - int r ; + Int r ; /* === Check the Row marks ============================================== */ @@ -3330,21 +3506,21 @@ ( /* === Parameters ======================================================= */ - int n_row, - int n_col, + Int n_row, + Int n_col, Colamd_Row Row [], Colamd_Col Col [], - int A [] + Int A [] ) { /* === Local variables ================================================== */ - int r ; - int c ; - int *rp ; - int *rp_end ; - int *cp ; - int *cp_end ; + Int r ; + Int c ; + Int *rp ; + Int *rp_end ; + Int *cp ; + Int *cp_end ; /* === Dump the rows and columns of the matrix ========================== */ @@ -3396,17 +3572,20 @@ char *method ) { + FILE *f ; colamd_debug = 0 ; /* no debug printing */ - - /* get "D" environment variable, which gives the debug printing level */ - if (getenv ("D")) + f = fopen ("debug", "r") ; + if (f == (FILE *) NULL) { - colamd_debug = atoi (getenv ("D")) ; + colamd_debug = 0 ; } - + else + { + fscanf (f, "%d", &colamd_debug) ; + fclose (f) ; + } DEBUG0 (("%s: debug version, D = %d (THIS WILL BE SLOW!)\n", method, colamd_debug)) ; } #endif /* NDEBUG */ -
--- a/liboctave/COLAMD/colamd.h +++ b/liboctave/COLAMD/colamd.h @@ -2,21 +2,18 @@ /* === colamd/symamd prototypes and definitions ============================= */ /* ========================================================================== */ -/* +/* COLAMD Version 2.4 + You must include this file (colamd.h) in any routine that uses colamd, symamd, or the related macros and definitions. Authors: The authors of the code itself are Stefan I. Larimore and Timothy A. - Davis (davis@cise.ufl.edu), University of Florida. The algorithm was + Davis (davis at cise.ufl.edu), University of Florida. The algorithm was developed in collaboration with John Gilbert, Xerox PARC, and Esmond Ng, Oak Ridge National Laboratory. - Date: - - September 8, 2003. Version 2.3. - Acknowledgements: This work was supported by the National Science Foundation, under @@ -24,8 +21,7 @@ Notice: - Copyright (c) 1998-2003 by the University of Florida. - All Rights Reserved. + Copyright (c) 1998-2005, Timothy A. Davis, All Rights Reserved. THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -52,6 +48,11 @@ #ifndef COLAMD_H #define COLAMD_H +/* make it easy for C++ programs to include COLAMD */ +#ifdef __cplusplus +extern "C" { +#endif + /* ========================================================================== */ /* === Include files ======================================================== */ /* ========================================================================== */ @@ -59,6 +60,35 @@ #include <stdlib.h> /* ========================================================================== */ +/* === COLAMD version ======================================================= */ +/* ========================================================================== */ + +/* COLAMD Version 2.4 and later will include the following definitions. + * As an example, to test if the version you are using is 2.4 or later: + * + * #ifdef COLAMD_VERSION + * if (COLAMD_VERSION >= COLAMD_VERSION_CODE (2,4)) ... + * #endif + * + * This also works during compile-time: + * + * #if defined(COLAMD_VERSION) && (COLAMD_VERSION >= COLAMD_VERSION_CODE (2,4)) + * printf ("This is version 2.4 or later\n") ; + * #else + * printf ("This is an early version\n") ; + * #endif + * + * Versions 2.3 and earlier of COLAMD do not include a #define'd version number. + */ + +#define COLAMD_DATE "Aug. 30, 2005" +#define COLAMD_VERSION_CODE(main,sub) ((main) * 1000 + (sub)) +#define COLAMD_MAIN_VERSION 2 +#define COLAMD_SUB_VERSION 4 +#define COLAMD_VERSION \ + COLAMD_VERSION_CODE(COLAMD_MAIN_VERSION,COLAMD_SUB_VERSION) + +/* ========================================================================== */ /* === Knob and statistics definitions ====================================== */ /* ========================================================================== */ @@ -74,6 +104,9 @@ /* knobs [1] and stats [1]: dense column knob and output statistic. */ #define COLAMD_DENSE_COL 1 +/* knobs [2]: aggressive absorption */ +#define COLAMD_AGGRESSIVE 2 + /* stats [2]: memory defragmentation count output statistic */ #define COLAMD_DEFRAG_COUNT 2 @@ -100,94 +133,6 @@ #define COLAMD_ERROR_out_of_memory (-10) #define COLAMD_ERROR_internal_error (-999) -/* ========================================================================== */ -/* === Row and Column structures ============================================ */ -/* ========================================================================== */ - -/* User code that makes use of the colamd/symamd routines need not directly */ -/* reference these structures. They are used only for the COLAMD_RECOMMENDED */ -/* macro. */ - -typedef struct Colamd_Col_struct -{ - int start ; /* index for A of first row in this column, or DEAD */ - /* if column is dead */ - int length ; /* number of rows in this column */ - union - { - int thickness ; /* number of original columns represented by this */ - /* col, if the column is alive */ - int parent ; /* parent in parent tree super-column structure, if */ - /* the column is dead */ - } shared1 ; - union - { - int score ; /* the score used to maintain heap, if col is alive */ - int order ; /* pivot ordering of this column, if col is dead */ - } shared2 ; - union - { - int headhash ; /* head of a hash bucket, if col is at the head of */ - /* a degree list */ - int hash ; /* hash value, if col is not in a degree list */ - int prev ; /* previous column in degree list, if col is in a */ - /* degree list (but not at the head of a degree list) */ - } shared3 ; - union - { - int degree_next ; /* next column, if col is in a degree list */ - int hash_next ; /* next column, if col is in a hash list */ - } shared4 ; - -} Colamd_Col ; - -typedef struct Colamd_Row_struct -{ - int start ; /* index for A of first col in this row */ - int length ; /* number of principal columns in this row */ - union - { - int degree ; /* number of principal & non-principal columns in row */ - int p ; /* used as a row pointer in init_rows_cols () */ - } shared1 ; - union - { - int mark ; /* for computing set differences and marking dead rows*/ - int first_column ;/* first column in row (used in garbage collection) */ - } shared2 ; - -} Colamd_Row ; - -/* ========================================================================== */ -/* === Colamd recommended memory size ======================================= */ -/* ========================================================================== */ - -/* - The recommended length Alen of the array A passed to colamd is given by - the COLAMD_RECOMMENDED (nnz, n_row, n_col) macro. It returns -1 if any - argument is negative. 2*nnz space is required for the row and column - indices of the matrix. COLAMD_C (n_col) + COLAMD_R (n_row) space is - required for the Col and Row arrays, respectively, which are internal to - colamd. An additional n_col space is the minimal amount of "elbow room", - and nnz/5 more space is recommended for run time efficiency. - - This macro is not needed when using symamd. - - Explicit typecast to int added Sept. 23, 2002, COLAMD version 2.2, to avoid - gcc -pedantic warning messages. -*/ - -#define COLAMD_C(n_col) ((int) (((n_col) + 1) * sizeof (Colamd_Col) / sizeof (int))) -#define COLAMD_R(n_row) ((int) (((n_row) + 1) * sizeof (Colamd_Row) / sizeof (int))) - -#define COLAMD_RECOMMENDED(nnz, n_row, n_col) \ -( \ -((nnz) < 0 || (n_row) < 0 || (n_col) < 0) \ -? \ - (-1) \ -: \ - (2 * (nnz) + COLAMD_C (n_col) + COLAMD_R (n_row) + (n_col) + ((nnz) / 5)) \ -) /* ========================================================================== */ /* === Prototypes of user-callable routines ================================= */ @@ -201,11 +146,24 @@ int n_col /* number of columns in A */ ) ; +long colamd_l_recommended /* returns recommended value of Alen, */ + /* or (-1) if input arguments are erroneous */ +( + long nnz, /* nonzeros in A */ + long n_row, /* number of rows in A */ + long n_col /* number of columns in A */ +) ; + void colamd_set_defaults /* sets default parameters */ ( /* knobs argument is modified on output */ double knobs [COLAMD_KNOBS] /* parameter settings for colamd */ ) ; +void colamd_l_set_defaults /* sets default parameters */ +( /* knobs argument is modified on output */ + double knobs [COLAMD_KNOBS] /* parameter settings for colamd */ +) ; + int colamd /* returns (1) if successful, (0) otherwise*/ ( /* A and p arguments are modified on output */ int n_row, /* number of rows in A */ @@ -217,6 +175,17 @@ int stats [COLAMD_STATS] /* colamd output statistics and error codes */ ) ; +long colamd_l /* returns (1) if successful, (0) otherwise*/ +( /* A and p arguments are modified on output */ + long n_row, /* number of rows in A */ + long n_col, /* number of columns in A */ + long Alen, /* size of the array A */ + long A [], /* row indices of A, of size Alen */ + long p [], /* column pointers of A, of size n_col+1 */ + double knobs [COLAMD_KNOBS],/* parameter settings for colamd */ + long stats [COLAMD_STATS] /* colamd output statistics and error codes */ +) ; + int symamd /* return (1) if OK, (0) otherwise */ ( int n, /* number of rows and columns of A */ @@ -233,14 +202,46 @@ /* mxFree (for MATLAB mexFunction) */ ) ; +long symamd_l /* return (1) if OK, (0) otherwise */ +( + long n, /* number of rows and columns of A */ + long A [], /* row indices of A */ + long p [], /* column pointers of A */ + long perm [], /* output permutation, size n_col+1 */ + double knobs [COLAMD_KNOBS], /* parameters (uses defaults if NULL) */ + long 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) */ +) ; + void colamd_report ( int stats [COLAMD_STATS] ) ; +void colamd_l_report +( + long stats [COLAMD_STATS] +) ; + void symamd_report ( int stats [COLAMD_STATS] ) ; +void symamd_l_report +( + long stats [COLAMD_STATS] +) ; + +extern int (*colamd_printf) (const char *, ...) ; + +#ifdef __cplusplus +} +#endif + #endif /* COLAMD_H */
--- a/liboctave/COLAMD/colamd.m +++ b/liboctave/COLAMD/colamd.m @@ -1,25 +1,70 @@ function [p,stats] = colamd (S, knobs) %COLAMD Column approximate minimum degree permutation. -% P = COLAMD (S) returns the column approximate minimum degree permutation -% vector for the sparse matrix S. For a non-symmetric matrix S, S (:,P) +% P = COLAMD(S) returns the column approximate minimum degree permutation +% vector for the sparse matrix S. For a non-symmetric matrix S, S(:,P) % tends to have sparser LU factors than S. The Cholesky factorization of -% S (:,P)' * S (:,P) also tends to be sparser than that of S'*S. COLAMD -% tends to be faster than COLMMD and tends to return a better ordering. +% S(:,P)'*S(:,P) also tends to be sparser than that of S'*S. The ordering +% is followed by a column elimination tree post-ordering. % -% See also COLMMD, COLPERM, SPPARMS, SYMAMD, SYMMMD, SYMRCM. +% See also AMD, CCOLAMD, CSYMAMD, SYMAMD, COLPERM, SYMRCM. % % Usage: P = colamd (S) -% P = colamd (S, knobs) -% [P, stats] = colamd (S) % [P, stats] = colamd (S, knobs) % -% knobs is an optional two-element input vector. If S is m-by-n, then -% rows with more than (knobs (1))*n entries are ignored. Columns with -% more than (knobs (2))*m entries are removed prior to ordering, and -% ordered last in the output permutation P. If the knobs parameter is not -% present, then 0.5 is used instead, for both knobs (1) and knobs (2). -% knobs (3) controls the printing of statistics and error messages. +% knobs is an optional one- to three-element input vector. If S is m-by-n, +% then rows with more than max(16,knobs(1)*sqrt(n)) entries are ignored. +% Columns with more than max(16,knobs(2)*sqrt(min(m,n))) entries are +% removed prior to ordering, and ordered last in the output permutation P. +% Only completely dense rows or columns are removed if knobs(1) and knobs(2) +% are < 0, respectively. If knobs(3) is nonzero, stats and knobs are +% printed. The default is knobs = [10 10 0]. Note that knobs differs from +% earlier versions of colamd. +% +% Type the command "type colamd" for a description of the optional stats +% output and for the copyright information. +% +% Authors: S. Larimore and T. Davis, University of Florida. Developed in +% collaboration with J. Gilbert and E. Ng. Version 2.4. +% +% Acknowledgements: This work was supported by the National Science +% Foundation, under grants DMS-9504974 and DMS-9803599. + +% Notice: +% +% Copyright (c) 1998-2005, Timothy A. Davis, All Rights Reserved. +% +% See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c +% file) for the License. +% +% Availability: % +% The colamd, symamd, amd, ccolamd, and csymamd are available at +% http://www.cise.ufl.edu/research/sparse + +%------------------------------------------------------------------------------- +% Perform the colamd ordering: +%------------------------------------------------------------------------------- + +if (nargout <= 1 && nargin == 1) + p = colamdmex (S) ; +elseif (nargout <= 1 && nargin == 2) + p = colamdmex (S, knobs) ; +elseif (nargout == 2 && nargin == 1) + [p, stats] = colamdmex (S) ; +elseif (nargout == 2 && nargin == 2) + [p, stats] = colamdmex (S, knobs) ; +else + error ('MATLAB:colamd:WrongInputOrOutputNumber',... + 'colamd: incorrect number of input and/or output arguments') ; +end + +%------------------------------------------------------------------------------- +% column elimination tree post-ordering: +%------------------------------------------------------------------------------- + +[ignore, q] = sparsfun ('coletree', S (:,p)) ; +p = p (q) ; + % stats is an optional 20-element output vector that provides data about the % ordering and the validity of the input matrix S. Ordering statistics are % in stats (1:3). stats (1) and stats (2) are the number of dense or empty @@ -50,60 +95,4 @@ % % stats (8:20) is always zero in the current version of COLAMD (reserved % for future use). -% -% The ordering is followed by a column elimination tree post-ordering. -% -% Authors: -% -% The authors of the code itself are Stefan I. Larimore and Timothy A. -% Davis (davis@cise.ufl.edu), University of Florida. The algorithm was -% developed in collaboration with John Gilbert, Xerox PARC, and Esmond -% Ng, Oak Ridge National Laboratory. -% -% Date: -% -% September 8, 2003. Version 2.3. -% -% Acknowledgements: -% -% This work was supported by the National Science Foundation, under -% grants DMS-9504974 and DMS-9803599. -% Notice: -% -% Copyright (c) 1998-2003 by the University of Florida. -% All Rights Reserved. -% -% See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c -% file) for the License. -% -% Availability: -% -% The colamd/symamd library is available at -% -% http://www.cise.ufl.edu/research/sparse/colamd/ -% - -%------------------------------------------------------------------------------- -% Perform the colamd ordering: -%------------------------------------------------------------------------------- - -if (nargout <= 1 & nargin == 1) - p = colamdmex (S) ; -elseif (nargout <= 1 & nargin == 2) - p = colamdmex (S, knobs) ; -elseif (nargout == 2 & nargin == 1) - [p, stats] = colamdmex (S) ; -elseif (nargout == 2 & nargin == 2) - [p, stats] = colamdmex (S, knobs) ; -else - error ('colamd: incorrect number of input and/or output arguments') ; -end - -%------------------------------------------------------------------------------- -% column elimination tree post-ordering: -%------------------------------------------------------------------------------- - -[ignore, q] = sparsfun ('coletree', S (:,p)) ; -p = p (q) ; -
--- a/liboctave/COLAMD/colamd_demo.m +++ b/liboctave/COLAMD/colamd_demo.m @@ -14,16 +14,17 @@ % % For a description of the methods used, see the colamd.c file. % -% September 8, 2003. Version 2.3. +% COLAMD Version 2.4. % http://www.cise.ufl.edu/research/sparse/colamd/ % +% Minor changes: in MATLAB 7, symmmd and colmmd are flagged as "obsolete". +% This demo checks if they exist, so it should still work when they are removed. + %------------------------------------------------------------------------------- % Print the introduction, the help info, and compile the mexFunctions %------------------------------------------------------------------------------- -more on - fprintf (1, '\n-----------------------------------------------------------\n') ; fprintf (1, 'Colamd/symamd demo.') ; fprintf (1, '\n-----------------------------------------------------------\n') ; @@ -39,15 +40,6 @@ fprintf (1, '\n-----------------------------------------------------------\n') ; help symamd ; -fprintf (1, '\n-----------------------------------------------------------\n') ; -fprintf (1, 'colamd and symamd mexFunctions will now be compiled.') ; -fprintf (1, '\n-----------------------------------------------------------\n') ; -s = input ('\n\nHit any key (or type ''n'' to skip compilation): ', 's') ; -if (~strcmp (s, 'n')) - disp ('mex -O colamdmex.c colamd.c') ; mex -O colamdmex.c colamd.c - disp ('mex -O symamdmex.c colamd.c') ; mex -O symamdmex.c colamd.c -end - %------------------------------------------------------------------------------- % Solving Ax=b %------------------------------------------------------------------------------- @@ -77,6 +69,7 @@ fprintf (1, '\nFlop count for [L,U,P] = lu (A*Q): %d\n', fl) ; fprintf (1, 'residual: %e\n', norm (A*x-b)); +try fprintf (1, '\n\nSolving via lu (PAQ = LU), where Q is from colmmd:\n') ; q = colmmd (A) ; I = speye (n) ; @@ -86,6 +79,9 @@ x = Q * (U \ (L \ (P * b))) ; fprintf (1, '\nFlop count for [L,U,P] = lu (A*Q): %d\n', fl) ; fprintf (1, 'residual: %e\n', norm (A*x-b)); +catch +fprintf (1, 'colmmd is obsolete\n') ; +end fprintf (1, '\n\nSolving via lu (PA = LU), without regard for sparsity:\n') ; [L,U,P] = lu (A) ; @@ -123,6 +119,7 @@ fprintf (1, 'nz in Cholesky factors of A(:,p)''A(:,p): %d\n', sum (lnz)) ; fprintf (1, 'flop count for Cholesky of A(:,p)''A(:,p): %d\n', sum (lnz.^2)) ; +try tic ; p = colmmd (A) ; t = toc ; @@ -131,6 +128,9 @@ fprintf (1, 'colmmd ordering quality: \n') ; fprintf (1, 'nz in Cholesky factors of A(:,p)''A(:,p): %d\n', sum (lnz)) ; fprintf (1, 'flop count for Cholesky of A(:,p)''A(:,p): %d\n', sum (lnz.^2)) ; +catch +fprintf (1, 'colmmd is obsolete\n') ; +end %------------------------------------------------------------------------------- % Large demo for symamd @@ -157,6 +157,7 @@ fprintf (1, 'nz in Cholesky factors of A(p,p): %d\n', sum (lnz)) ; fprintf (1, 'flop count for Cholesky of A(p,p): %d\n', sum (lnz.^2)) ; +try tic ; p = symmmd (A) ; t = toc ; @@ -165,6 +166,6 @@ fprintf (1, 'symmmd ordering quality: \n') ; fprintf (1, 'nz in Cholesky factors of A(p,p): %d\n', sum (lnz)) ; fprintf (1, 'flop count for Cholesky of A(p,p): %d\n', sum (lnz.^2)) ; - -more off - +catch +fprintf (1, 'symmmd is obsolete\n') ; +end
--- a/liboctave/COLAMD/colamd_example.c +++ b/liboctave/COLAMD/colamd_example.c @@ -2,7 +2,8 @@ /* === colamd and symamd example ============================================ */ /* ========================================================================== */ -/* +/* COLAMD Version 2.4. + colamd example of use, to order the columns of a 5-by-4 matrix with 11 nonzero entries in the following nonzero pattern, with default knobs. @@ -24,8 +25,6 @@ (where x denotes a nonzero value). - September 8, 2003. Version 2.3. - See http://www.cise.ufl.edu/research/sparse/colamd/ (the colamd.c file) for the routines this program calls, and for the License. */ @@ -38,12 +37,12 @@ #define A_NNZ 11 #define A_NROW 5 #define A_NCOL 4 -#define ALEN (COLAMD_RECOMMENDED (A_NNZ, A_NCOL, A_NROW)) +#define ALEN 150 #define B_NNZ 4 #define B_N 5 -int main (int argc, char **argv) +int main (void) { /* ====================================================================== */
--- a/liboctave/COLAMD/colamd_example.out +++ b/liboctave/COLAMD/colamd_example.out @@ -14,15 +14,16 @@ Column 3, with 2 entries: row 1 row 3 -colamd: OK. -colamd: number of dense or empty rows ignored: 1 -colamd: number of dense or empty columns ignored: 2 + +colamd version 2.4, Aug. 30, 2005: OK. +colamd: number of dense or empty rows ignored: 0 +colamd: number of dense or empty columns ignored: 0 colamd: number of garbage collections performed: 0 colamd column ordering: 1st column: 1 -2nd column: 3 -3rd column: 0 -4th column: 2 +2nd column: 0 +3rd column: 2 +4th column: 3 symamd 5-by-5 input matrix: @@ -36,7 +37,8 @@ Column 3, with 1 entries: row 4 Column 4, with 0 entries: -symamd: OK. + +symamd version 2.4, Aug. 30, 2005: OK. symamd: number of dense or empty rows ignored: 0 symamd: number of dense or empty columns ignored: 0 symamd: number of garbage collections performed: 0
--- a/liboctave/COLAMD/colamd_test.m +++ b/liboctave/COLAMD/colamd_test.m @@ -1,23 +1,17 @@ -function colamd_test (spumoni) +function colamd_test % -% colamd_test (spumoni) +% colamd_test % % COLAMD and SYMAMD testing function. Here we try to give colamd and symamd % every possible type of matrix and erroneous input that they may encounter. % We want either a valid permutation returned or we want them to fail -% gracefully. If the optional spumoni argument is present, additional -% diagnostic messages are printed during the test: -% -% spumoni: -% 0: very little, just a progress meter (default) -% 1: lots -% 2: far too much +% gracefully. % % You are prompted as to whether or not the colamd and symand routines and % the test mexFunctions are to be compiled. % % Tim Davis -% September 8, 2003. Version 2.3. +% COLAMD Version 2.4. % http://www.cise.ufl.edu/research/sparse/colamd/ help colamd_test @@ -55,31 +49,34 @@ rand ('state', 0) ; randn ('state', 0) ; -if (nargin < 1) - spumoni = 0 ; -end -old = spparms ('spumoni') ; -spparms ('spumoni', spumoni) ; + +A = sprandn (500,500,0.4) ; + +p = colamd (A, [10 10 1]) ; check_perm (p, A) ; +p = colamd (A, [2 7 1]) ; check_perm (p, A) ; +p = symamd (A, [10 1]) ; check_perm (p, A) ; +p = symamd (A, [7 1]) ; check_perm (p, A) ; +p = symamd (A, [4 1]) ; check_perm (p, A) ; fprintf ('Null matrices') ; A = zeros (0,0) ; A = sparse (A) ; -[p, stats] = colamd (A, [.5 .5 spumoni]) ; +[p, stats] = colamd (A, [10 10 0]) ; check_perm (p, A) ; -[p, stats] = symamd (A, [.5 spumoni]) ; +[p, stats] = symamd (A, [10 0]) ; check_perm (p, A) ; A = zeros (0, 100) ; A = sparse (A) ; -[p, stats] = colamd (A, [.5 .5 spumoni]) ; +[p, stats] = colamd (A, [10 10 0]) ; check_perm (p, A) ; A = zeros (100, 0) ; A = sparse (A) ; -[p, stats] = colamd (A, [.5 .5 spumoni]) ; +[p, stats] = colamd (A, [10 10 0]) ; check_perm (p, A) ; fprintf (' OK\n') ; @@ -92,20 +89,19 @@ A = rand_matrix (1000, 1000, 1, 10, 20) ; [m n] = size (A) ; + for tol = [0:.1:2 3:20 1e6] - for tol = [0 0.001 0.005 0.01:0.01:0.10 0.5:.1:1] - - [p, stats] = colamd (A, [tol tol spumoni]) ; + [p, stats] = colamd (A, [tol tol 0]) ; check_perm (p, A) ; B = A + A' ; - [p, stats] = symamd (B, [tol spumoni]) ; + [p, stats] = symamd (B, [tol 0]) ; check_perm (p, A) ; - [p, stats] = colamd (A, [tol 1 spumoni]) ; + [p, stats] = colamd (A, [tol 1 0]) ; check_perm (p, A) ; - [p, stats] = colamd (A, [1 tol spumoni]) ; + [p, stats] = colamd (A, [1 tol 0]) ; check_perm (p, A) ; fprintf ('.') ; @@ -142,31 +138,31 @@ for err = 1:13 - p = Tcolamd (A, [1 1 spumoni 0 err]) ; + p = Tcolamd (A, [n n 0 0 err]) ; if p ~= -1 check_perm (p, A) ; end if (err == 1) % check different (valid) input args to colamd - p = Acolamd (A, spumoni) ; + p = Acolamd (A) ; - p2 = Acolamd (A, spumoni, [.5 .5 spumoni 0 0]) ; + p2 = Acolamd (A, [10 10 0 0 0]) ; if (any (p ~= p2)) error ('colamd: mismatch 1!') ; end - [p2 stats] = Acolamd (A, spumoni) ; + [p2 stats] = Acolamd (A) ; if (any (p ~= p2)) error ('colamd: mismatch 2!') ; end - [p2 stats] = Acolamd (A, spumoni, [.5 .5 spumoni 0 0]) ; + [p2 stats] = Acolamd (A, [10 10 0 0 0]) ; if (any (p ~= p2)) error ('colamd: mismatch 3!') ; end end B = A'*A ; - p = Tsymamd (B, [1 spumoni err]) ; + p = Tsymamd (B, [n 0 err]) ; if p ~= -1 check_perm (p, A) ; end @@ -174,17 +170,17 @@ if (err == 1) % check different (valid) input args to symamd - p = Asymamd (B, spumoni) ; + p = Asymamd (B) ; check_perm (p, A) ; - p2 = Asymamd (B, spumoni, [.5 spumoni 0]) ; + p2 = Asymamd (B, [10 0 0]) ; if (any (p ~= p2)) error ('symamd: mismatch 1!') ; end - [p2 stats] = Asymamd (B, spumoni) ; + [p2 stats] = Asymamd (B) ; if (any (p ~= p2)) error ('symamd: mismatch 2!') ; end - [p2 stats] = Asymamd (B, spumoni, [.5 spumoni 0]) ; + [p2 stats] = Asymamd (B, [10 0 0]) ; if (any (p ~= p2)) error ('symamd: mismatch 3!') ; end @@ -213,12 +209,17 @@ A (:, null_col) = 0 ; % Order the matrix and make sure that the null columns are ordered last. - [p, stats] = colamd (A, [1 1 spumoni]) ; + [p, stats] = colamd (A, [1e6 1e6 0]) ; check_perm (p, A) ; - if (stats (2) ~= 5) - error ('colamd: wrong number of null columns') ; - end +% if (stats (2) ~= 5) +% stats (2) +% error ('colamd: wrong number of null columns') ; +% end + + % find all null columns in A + null_col = find (sum (spones (A), 1) == 0) ; + nnull = length (null_col) ; if (any (null_col ~= p ((n-4):n))) error ('colamd: Null cols are not ordered last in natural order') ; end @@ -246,7 +247,7 @@ A (null_col, :) = 0 ; % Order the matrix and make sure that the null rows/cols are ordered last. - [p,stats] = symamd (A, [1 spumoni]) ; + [p,stats] = symamd (A, [10 0]) ; check_perm (p, A) ; % find actual number of null rows and columns @@ -282,7 +283,7 @@ null_row = sort (null_row (1:5)) ; A (null_row, :) = 0 ; - p = colamd (A, [.5 .5 spumoni]) ; + p = colamd (A, [10 10 0]) ; check_perm (p, A) ; if (stats (1) ~= 5) error ('colamd: wrong number of null rows') ; @@ -293,25 +294,20 @@ fprintf ('\ncolamd and symamd: all tests passed\n\n') ; -spparms ('spumoni', old) ; %------------------------------------------------------------------------------- % Acolamd: compare colamd and Tcolamd results %------------------------------------------------------------------------------- -function [p,stats] = Acolamd (S, spumoni, knobs) - -if (nargin < 2) - spumoni = 0 ; -end +function [p,stats] = Acolamd (S, knobs) if (nargin < 3) if (nargout == 1) [p] = colamd (S) ; - [p1] = Tcolamd (S, [.5 .5 spumoni 0 0]) ; + [p1] = Tcolamd (S, [10 10 0 0 0]) ; else [p, stats] = colamd (S) ; - [p1, stats1] = Tcolamd (S, [.5 .5 spumoni 0 0]) ; + [p1, stats1] = Tcolamd (S, [10 10 0 0 0]) ; end else if (nargout == 1) @@ -335,19 +331,15 @@ % Asymamd: compare symamd and Tsymamd results %------------------------------------------------------------------------------- -function [p,stats] = Asymamd (S, spumoni, knobs) - -if (nargin < 2) - spumoni = 0 ; -end +function [p,stats] = Asymamd (S, knobs) if (nargin < 3) if (nargout == 1) [p] = symamd (S) ; - [p1] = Tsymamd (S, [.5 spumoni 0]) ; + [p1] = Tsymamd (S, [10 0 0]) ; else [p, stats] = symamd (S) ; - [p1, stats1] = Tsymamd (S, [.5 spumoni 0]) ; + [p1, stats1] = Tsymamd (S, [10 0 0]) ; end else if (nargout == 1) @@ -518,4 +510,3 @@ p = p (q) ; check_perm (p, S) ; end -
--- a/liboctave/COLAMD/colamdmex.c +++ b/liboctave/COLAMD/colamdmex.c @@ -2,76 +2,22 @@ /* === colamd mexFunction =================================================== */ /* ========================================================================== */ -/* +/* COLAMD Version 2.4 + Usage: P = colamd (A) ; - - P = colamd (A, knobs) ; - - [ P, stats ] = colamd (A) ; - [ P, stats ] = colamd (A, knobs) ; - Returns a permutation vector P such that the LU factorization of A (:,P) - tends to be sparser than that of A. The Cholesky factorization of - (A (:,P))'*(A (:,P)) will also tend to be sparser than that of A'*A. - This routine provides the same functionality as COLMMD, but is much faster - and returns a better permutation vector. Note that the COLMMD m-file in - MATLAB 5.2 also performs a column elimination tree post-ordering. This - mexFunction does not do this post-ordering. This mexFunction is a - replacement for the p = sparsfun ('colmmd', A) operation. - - The knobs and stats vectors are optional: - - knobs (1) rows with more than (knobs (1))*n_col entries - are removed prior to ordering. If knobs is not present, - then the default is used (0.5). - - knobs (2) columns with more than (knobs (2))*n_row entries - are removed prior to ordering, and placed last in the - column permutation. If knobs is not present, - then the default is used (0.5). - - knobs (3) print level, similar to spparms ('spumoni') - - stats (1) the number of dense (or empty) rows ignored - - stats (2) the number of dense (or empty) columms. These - are ordered last, in their natural order. - - stats (3) the number of garbage collections performed. - - stats (4) return status: - - 0: matrix is a valid MATLAB matrix. - - 1: matrix has duplicate entries or unsorted columns. - This should not occur in a valid MATLAB matrix, - but the ordering proceeded anyway by sorting the - row indices in each column and by ignoring the - duplicate row indices in each column. See - stats (5:7) for more information. - - stats (5) highest numbered column that is unsorted or has - duplicate entries (zero if none) - - stats (6) last seen duplicate or unsorted row index - (zero if none) - - stats (7) number of duplicate or unsorted row indices + see colamd.m for a description. Authors: The authors of the code itself are Stefan I. Larimore and Timothy A. - Davis (davis@cise.ufl.edu), University of Florida. The algorithm was + Davis (davis at cise.ufl.edu), University of Florida. The algorithm was developed in collaboration with John Gilbert, Xerox PARC, and Esmond Ng, Oak Ridge National Laboratory. - Date: - - September 8, 2003. Version 2.3. - Acknowledgements: This work was supported by the National Science Foundation, under @@ -79,8 +25,7 @@ Notice: - Copyright (c) 1998-2003 by the University of Florida. - All Rights Reserved. + Copyright (c) 1998-2005, Timothy A. Davis, All Rights Reserved. See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c file) for the License. @@ -138,6 +83,8 @@ int spumoni ; /* verbosity variable */ int stats [COLAMD_STATS] ; /* stats for colamd */ + colamd_printf = mexPrintf ; /* COLAMD printf routine */ + /* === Check inputs ===================================================== */ if (nrhs < 1 || nrhs > 2 || nlhs < 0 || nlhs > 2) @@ -156,18 +103,38 @@ { in_knobs = mxGetPr (prhs [1]) ; i = mxGetNumberOfElements (prhs [1]) ; - if (i > 0) knobs [COLAMD_DENSE_ROW] = in_knobs [COLAMD_DENSE_ROW] ; - if (i > 1) knobs [COLAMD_DENSE_COL] = in_knobs [COLAMD_DENSE_COL] ; - if (i > 2) spumoni = (int) in_knobs [2] ; + if (i > 0) knobs [COLAMD_DENSE_ROW] = in_knobs [0] ; + if (i > 1) knobs [COLAMD_DENSE_COL] = in_knobs [1] ; + if (i > 2) spumoni = (int) (in_knobs [2] != 0) ; } /* print knob settings if spumoni is set */ - if (spumoni > 0) + if (spumoni) { - mexPrintf ("colamd: dense row fraction: %f\n", - knobs [COLAMD_DENSE_ROW]) ; - mexPrintf ("colamd: dense col fraction: %f\n", - knobs [COLAMD_DENSE_COL]) ; + mexPrintf ("\ncolamd version %d.%d, %s:\n", + COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION, COLAMD_DATE) ; + if (knobs [COLAMD_DENSE_ROW] >= 0) + { + mexPrintf ("knobs(1): %g, rows with > max(16,%g*sqrt(size(A,2)))" + " entries removed\n", in_knobs [0], knobs [COLAMD_DENSE_ROW]) ; + } + else + { + mexPrintf ("knobs(1): %g, only completely dense rows removed\n", + in_knobs [0]) ; + } + if (knobs [COLAMD_DENSE_COL] >= 0) + { + mexPrintf ("knobs(2): %g, cols with > max(16,%g*sqrt(min(size(A)))" + " entries removed\n", in_knobs [1], knobs [COLAMD_DENSE_COL]) ; + } + else + { + mexPrintf ("knobs(2): %g, only completely dense columns removed\n", + in_knobs [1]) ; + } + mexPrintf ("knobs(3): %g, statistics and knobs printed\n", + in_knobs [2]) ; } /* === If A is full, convert to a sparse matrix ========================= */ @@ -227,8 +194,8 @@ /* === Return the stats vector ========================================== */ - /* print stats if spumoni > 0 */ - if (spumoni > 0) + /* print stats if spumoni is set */ + if (spumoni) { colamd_report (stats) ; }
--- a/liboctave/COLAMD/colamdtestmex.c +++ b/liboctave/COLAMD/colamdtestmex.c @@ -2,7 +2,8 @@ /* === colamdtest mexFunction =============================================== */ /* ========================================================================== */ -/* +/* COLAMD Version 2.4. + This MATLAB mexFunction is for testing only. It is not meant for production use. See colamdmex.c instead. @@ -10,28 +11,11 @@ [ P, stats ] = colamdtest (A, knobs) ; - Returns a permutation vector P such that the LU factorization of A (:,P) - tends to be sparser than that of A. The Cholesky factorization of - (A (:,P))'*(A (:,P)) will also tend to be sparser than that of A'*A. - This routine provides the same functionality as COLMMD, but is much faster - and returns a better permutation vector. Note that the COLMMD m-file in - MATLAB 5.2 also performs a column elimination tree post-ordering. This - mexFunction does not do this post-ordering. This mexFunction is a - replacement for the p = sparsfun ('colmmd', A) operation. - - The knobs and stats vectors are optional: + See colamd.m for a description. knobs is required. - knobs (1) rows with more than (knobs (1))*n_col entries - are removed prior to ordering. If knobs is not present, - then the default is used (0.5). - - knobs (2) columns with more than (knobs (2))*n_row entries - are removed prior to ordering, and placed last in the - column permutation. If knobs is not present, - then the default is used (0.5). - - knobs (3) print level, similar to spparms ('spumoni') - + knobs (1) dense row control + knobs (2) dense column control + knobs (3) spumoni knobs (4) for testing only. Controls the workspace used by colamd. @@ -39,43 +23,13 @@ jumbled prior to calling colamd, to test its error handling capability. - stats (1) the number of dense (or empty) rows ignored - - stats (2) the number of dense (or empty) columms. These - are ordered last, in their natural order. - - stats (3) the number of garbage collections performed. - - stats (4) return status: - - 0: matrix is a valid MATLAB matrix. - - 1: matrix has duplicate entries or unsorted columns. - This should not occur in a valid MATLAB matrix, - but the ordering proceeded anyway by sorting the - row indices in each column and by ignoring the - duplicate row indices in each column. See - stats (5:7) for more information. - - stats (5) highest numbered column that is unsorted or has - duplicate entries (zero if none) - - stats (6) last seen duplicate or unsorted row index - (zero if none) - - stats (7) number of duplicate or unsorted row indices - Authors: The authors of the code itself are Stefan I. Larimore and Timothy A. - Davis (davis@cise.ufl.edu), University of Florida. The algorithm was + Davis (davis at cise.ufl.edu), University of Florida. The algorithm was developed in collaboration with John Gilbert, Xerox PARC, and Esmond Ng, Oak Ridge National Laboratory. - Date: - - September 8, 2003. Version 2.3. - Acknowledgements: This work was supported by the National Science Foundation, under @@ -83,8 +37,7 @@ Notice: - Copyright (c) 1998-2003 by the University of Florida. - All Rights Reserved. + Copyright (c) 1998-2005, Timothy A. Davis, All Rights Reserved. See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c file) for the License. @@ -157,6 +110,8 @@ int *stats ; stats = stats2 ; + colamd_printf = mexPrintf ; /* COLAMD printf routine */ + /* === Check inputs ===================================================== */ if (nrhs < 1 || nrhs > 2 || nlhs < 0 || nlhs > 2) @@ -170,7 +125,7 @@ mexErrMsgTxt ("colamdtest: knobs are required") ; } /* for testing we require all 5 knobs */ - if (mxGetNumberOfElements (prhs [1]) < 5) + if (mxGetNumberOfElements (prhs [1]) != 5) { mexErrMsgTxt ("colamd: must have all 5 knobs for testing") ; } @@ -185,18 +140,38 @@ { in_knobs = mxGetPr (prhs [1]) ; i = mxGetNumberOfElements (prhs [1]) ; - if (i > 0) knobs [COLAMD_DENSE_ROW] = in_knobs [COLAMD_DENSE_ROW] ; - if (i > 1) knobs [COLAMD_DENSE_COL] = in_knobs [COLAMD_DENSE_COL] ; + if (i > 0) knobs [COLAMD_DENSE_ROW] = in_knobs [0] ; + if (i > 1) knobs [COLAMD_DENSE_COL] = in_knobs [1] ; if (i > 2) spumoni = (int) in_knobs [2] ; } /* print knob settings if spumoni is set */ - if (spumoni > 0) + if (spumoni) { - mexPrintf ("colamd: dense row fraction: %f\n", - knobs [COLAMD_DENSE_ROW]) ; - mexPrintf ("colamd: dense col fraction: %f\n", - knobs [COLAMD_DENSE_COL]) ; + mexPrintf ("\ncolamd version %d.%d, %s:\n", + COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION, COLAMD_DATE) ; + if (knobs [COLAMD_DENSE_ROW] >= 0) + { + mexPrintf ("knobs(1): %g, rows with > max(16,%g*sqrt(size(A,2)))" + " entries removed\n", in_knobs [0], knobs [COLAMD_DENSE_ROW]) ; + } + else + { + mexPrintf ("knobs(1): %g, only completely dense rows removed\n", + in_knobs [0]) ; + } + if (knobs [COLAMD_DENSE_COL] >= 0) + { + mexPrintf ("knobs(2): %g, cols with > max(16,%g*sqrt(min(size(A)))" + " entries removed\n", in_knobs [1], knobs [COLAMD_DENSE_COL]) ; + } + else + { + mexPrintf ("knobs(2): %g, only completely dense columns removed\n", + in_knobs [1]) ; + } + mexPrintf ("knobs(3): %g, statistics and knobs printed\n", + in_knobs [2]) ; } /* === If A is full, convert to a sparse matrix ========================= */
--- a/liboctave/COLAMD/symamd.m +++ b/liboctave/COLAMD/symamd.m @@ -1,25 +1,71 @@ function [p, stats] = symamd (S, knobs) %SYMAMD Symmetric approximate minimum degree permutation. -% P = SYMAMD (S) for a symmetric positive definite matrix S, returns the +% P = SYMAMD(S) for a symmetric positive definite matrix S, returns the % permutation vector p such that S(p,p) tends to have a sparser Cholesky % factor than S. Sometimes SYMAMD works well for symmetric indefinite -% matrices too. SYMAMD tends to be faster than SYMMMD and tends to return -% a better ordering. The matrix S is assumed to be symmetric; only the +% matrices too. The matrix S is assumed to be symmetric; only the % strictly lower triangular part is referenced. S must be square. +% Note that p = amd(S) is much faster and generates comparable orderings. +% The ordering is followed by an elimination tree post-ordering. % -% See also COLMMD, COLPERM, SPPARMS, COLAMD, SYMMMD, SYMRCM. +% See also AMD, CCOLAMD, CSYMAMD, COLAMD, COLPERM, SYMRCM. % % Usage: P = symamd (S) -% P = symamd (S, knobs) -% [P, stats] = symamd (S) % [P, stats] = symamd (S, knobs) % -% knobs is an optional input argument. If S is n-by-n, then rows and -% columns with more than knobs(1)*n entries are removed prior to ordering, -% and ordered last in the output permutation P. If the knobs parameter is not -% present, then the default of 0.5 is used instead. knobs (2) controls the -% printing of statistics and error messages. +% knobs is an optional one- to two-element input vector. If S is n-by-n, +% then rows and columns with more than max(16,knobs(1)*sqrt(n)) entries are +% removed prior to ordering, and ordered last in the output permutation P. +% No rows/columns are removed if knobs(1)<0. If knobs(2) is nonzero, stats +% and knobs are printed. The default is knobs = [10 0]. Note that knobs +% differs from earlier versions of symamd. +% +% Type the command "type symamd" for a description of the optional stats +% output and for the copyright information. +% +% Authors: S. Larimore and T. Davis, University of Florida. Developed in +% collaboration with J. Gilbert and E. Ng. Version 2.4. +% +% Acknowledgements: This work was supported by the National Science +% Foundation, under grants DMS-9504974 and DMS-9803599. + +% Notice: +% +% Copyright (c) 1998-2005, Timothy A. Davis, All Rights Reserved. +% +% See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c +% file) for the License. +% +% Availability: % +% The colamd, symamd, amd, ccolamd, and csymamd are available at +% http://www.cise.ufl.edu/research/sparse + +%------------------------------------------------------------------------------- +% perform the symamd ordering: +%------------------------------------------------------------------------------- + +if (nargout <= 1 && nargin == 1) + p = symamdmex (S) ; +elseif (nargout <= 1 && nargin == 2) + p = symamdmex (S, knobs) ; +elseif (nargout == 2 && nargin == 1) + [p, stats] = symamdmex (S) ; +elseif (nargout == 2 && nargin == 2) + [p, stats] = symamdmex (S, knobs) ; +else + error('MATLAB:symamd:WrongInputOrOutputNumber',... + 'symamd: incorrect number of input and/or output arguments.') ; +end + +%------------------------------------------------------------------------------- +% symmetric elimination tree post-ordering: +%------------------------------------------------------------------------------- + +[ignore, q] = sparsfun ('symetree', S (p,p)) ; +p = p (q) ; + + % stats is an optional 20-element output vector that provides data about the % ordering and the validity of the input matrix S. Ordering statistics are % in stats (1:3). stats (1) = stats (2) is the number of dense or empty @@ -50,59 +96,3 @@ % % stats (8:20) is always zero in the current version of SYMAMD (reserved % for future use). -% -% The ordering is followed by a column elimination tree post-ordering. -% -% Authors: -% -% The authors of the code itself are Stefan I. Larimore and Timothy A. -% Davis (davis@cise.ufl.edu), University of Florida. The algorithm was -% developed in collaboration with John Gilbert, Xerox PARC, and Esmond -% Ng, Oak Ridge National Laboratory. -% -% Date: -% -% September 8, 2003. Version 2.3. -% -% Acknowledgements: -% -% This work was supported by the National Science Foundation, under -% grants DMS-9504974 and DMS-9803599. - -% Notice: -% Copyright (c) 1998-2003 by the University of Florida. -% All Rights Reserved. -% -% See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c -% file) for the License. -% -% Availability: -% -% The colamd/symamd library is available at -% -% http://www.cise.ufl.edu/research/sparse/colamd/ -% - -%------------------------------------------------------------------------------- -% perform the symamd ordering: -%------------------------------------------------------------------------------- - -if (nargout <= 1 & nargin == 1) - p = symamdmex (S) ; -elseif (nargout <= 1 & nargin == 2) - p = symamdmex (S, knobs) ; -elseif (nargout == 2 & nargin == 1) - [p, stats] = symamdmex (S) ; -elseif (nargout == 2 & nargin == 2) - [p, stats] = symamdmex (S, knobs) ; -else - error ('symamd: incorrect number of input and/or output arguments') ; -end - -%------------------------------------------------------------------------------- -% symmetric elimination tree post-ordering: -%------------------------------------------------------------------------------- - -[ignore, q] = sparsfun ('symetree', S (p,p)) ; -p = p (q) ; -
--- a/liboctave/COLAMD/symamdmex.c +++ b/liboctave/COLAMD/symamdmex.c @@ -2,76 +2,22 @@ /* === symamd mexFunction =================================================== */ /* ========================================================================== */ -/* +/* COLAMD Version 2.4. + Usage: P = symamd (A) ; - - P = symamd (A, knobs) ; - - [ P, stats ] = symamd (A) ; - [ P, stats ] = symamd (A, knobs) ; - Returns a permutation vector P such that the Cholesky factorization of - A (P,P) tends to be sparser than that of A. This routine provides the same - functionality as SYMMMD, but tends to be much faster and tends to return a - better permutation vector. Note that the SYMMMD m-file in - MATLAB 5.2 also performs a symmetric elimination tree post-ordering. This - mexFunction does not do this post-ordering. This mexFunction is a - replacement for the p = sparsfun ('symmmd', A) operation. - - A must be square, and is assummed to have a symmetric nonzero pattern. - Only the nonzero pattern of the lower triangular portion of A is accessed. - This routine constructs a matrix M such that the nonzero pattern of M'M is - equal to A (assuming A has symmetric pattern), and then performs a column - ordering of M using colamd. - - The knobs and stats vectors are optional: - - knobs (1) rows and columns with more than (knobs(1))*n entries - are removed prior to ordering, and placed last in - the output ordering. If knobs is not present, then the - default of 0.5 is used. - - knobs (2) print level, similar to spparms ('spumoni') - - stats (1) the number of dense (or empty) rows and columms. These - are ordered last, in their natural order. - - stats (2) (same as stats (1)) - - stats (3) the number of garbage collections performed. - - stats (4) return status: - - 0: matrix is a valid MATLAB matrix. - - 1: matrix has duplicate entries or unsorted columns. - This should not occur in a valid MATLAB matrix, - but the ordering proceeded anyway by ignoring the - duplicate row indices in each column. See - stats (5:7) for more information. - - stats (5) highest numbered column that is unsorted or has - duplicate entries (zero if none) - - stats (6) last seen duplicate or unsorted row index - (zero if none) - - stats (7) number of duplicate or unsorted row indices + See symamd.m for a description. Authors: The authors of the code itself are Stefan I. Larimore and Timothy A. - Davis (davis@cise.ufl.edu), University of Florida. The algorithm was + Davis (davis at cise.ufl.edu), University of Florida. The algorithm was developed in collaboration with John Gilbert, Xerox PARC, and Esmond Ng, Oak Ridge National Laboratory. - Date: - - September 8, 2003. Version 2.3. - Acknowledgements: This work was supported by the National Science Foundation, under @@ -79,8 +25,7 @@ Notice: - Copyright (c) 1998-2003 by the University of Florida. - All Rights Reserved. + Copyright (c) 1998-2005, Timothy A. Davis. All Rights Reserved. See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c file) for the License. @@ -136,6 +81,8 @@ int spumoni ; /* verbosity variable */ int stats [COLAMD_STATS] ; /* stats for symamd */ + colamd_printf = mexPrintf ; /* COLAMD printf routine */ + /* === Check inputs ===================================================== */ if (nrhs < 1 || nrhs > 2 || nlhs < 0 || nlhs > 2) @@ -154,15 +101,27 @@ { in_knobs = mxGetPr (prhs [1]) ; i = mxGetNumberOfElements (prhs [1]) ; - if (i > 0) knobs [COLAMD_DENSE_ROW] = in_knobs [COLAMD_DENSE_ROW] ; - if (i > 1) spumoni = (int) in_knobs [1] ; + if (i > 0) knobs [COLAMD_DENSE_ROW] = in_knobs [0] ; + if (i > 1) spumoni = (int) (in_knobs [1] != 0) ; } - /* print knob settings if spumoni > 0 */ - if (spumoni > 0) + /* print knob settings if spumoni is set */ + if (spumoni) { - mexPrintf ("symamd: dense row/col fraction: %f\n", - knobs [COLAMD_DENSE_ROW]) ; + mexPrintf ("\nsymamd version %d.%d, %s:\n", + COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION, COLAMD_DATE) ; + if (knobs [COLAMD_DENSE_ROW] >= 0) + { + mexPrintf ("knobs(1): %g, rows/cols with > " + "max(16,%g*sqrt(size(A,2))) entries removed\n", + in_knobs [0], knobs [COLAMD_DENSE_ROW]) ; + } + else + { + mexPrintf ("knobs(1): %g, no dense rows removed\n", in_knobs [0]) ; + } + mexPrintf ("knobs(2): %g, statistics and knobs printed\n", + in_knobs [1]) ; } /* === If A is full, convert to a sparse matrix ========================= */ @@ -218,8 +177,8 @@ /* === Return the stats vector ========================================== */ - /* print stats if spumoni > 0 */ - if (spumoni > 0) + /* print stats if spumoni is set */ + if (spumoni) { symamd_report (stats) ; }
--- a/liboctave/COLAMD/symamdtestmex.c +++ b/liboctave/COLAMD/symamdtestmex.c @@ -2,7 +2,8 @@ /* === symamdtest mexFunction =============================================== */ /* ========================================================================== */ -/* +/* COLAMD Version 2.4. + This MATLAB mexFunction is for testing only. It is not meant for production use. See symamdmex.c instead. @@ -10,69 +11,21 @@ [ P, stats ] = symamdtest (A, knobs) ; - Returns a permutation vector P such that the Cholesky factorization of - A (P,P) tends to be sparser than that of A. This routine provides the same - functionality as SYMMMD, but tends to be much faster and tends to return a - better permutation vector. Note that the SYMMMD m-file in - MATLAB 5.2 also performs a symmetric elimination tree post-ordering. This - mexFunction does not do this post-ordering. This mexFunction is a - replacement for the p = sparsfun ('symmmd', A) operation. + See symamd.m for a description. knobs is required. - A must be square, and is assummed to have a symmetric nonzero pattern. - Only the nonzero pattern of the lower triangular portion of A is accessed. - This routine constructs a matrix M such that the nonzero pattern of M'M is - equal to A (assuming A has symmetric pattern), and then performs a column - ordering of M using colamd. - - The knobs and stats vectors are optional: - - knobs (1) rows and columns with more than (knobs(1))*n entries - are removed prior to ordering, and placed last in - the output ordering. If knobs is not present, then the - default of 0.5 is used. - - knobs (2) print level, similar to spparms ('spumoni') - + knobs (1) dense row control + knobs (2) spumoni knobs (3) for testing only. Controls how the input matrix is jumbled prior to calling symamd, to test its error handling capability. - stats (1) the number of dense (or empty) rows and columms. These - are ordered last, in their natural order. - - stats (2) (same as stats (1)) - - stats (3) the number of garbage collections performed. - - stats (4) return status: - - 0: matrix is a valid MATLAB matrix. - - 1: matrix has duplicate entries or unsorted columns. - This should not occur in a valid MATLAB matrix, - but the ordering proceeded anyway by ignoring the - duplicate row indices in each column. See - stats (5:7) for more information. - - stats (5) highest numbered column that is unsorted or has - duplicate entries (zero if none) - - stats (6) last seen duplicate or unsorted row index - (zero if none) - - stats (7) number of duplicate or unsorted row indices - Authors: The authors of the code itself are Stefan I. Larimore and Timothy A. - Davis (davis@cise.ufl.edu), University of Florida. The algorithm was + Davis (davis at cise.ufl.edu), University of Florida. The algorithm was developed in collaboration with John Gilbert, Xerox PARC, and Esmond Ng, Oak Ridge National Laboratory. - Date: - - September 8, 2003. Version 2.3. - Acknowledgements: This work was supported by the National Science Foundation, under @@ -80,8 +33,7 @@ Notice: - Copyright (c) 1998-2003 by the University of Florida. - All Rights Reserved. + Copyright (c) 1998-2005, Timothy A. Davis. All Rights Reserved. See http://www.cise.ufl.edu/research/sparse/colamd (the colamd.c file) for the License. @@ -153,6 +105,8 @@ int *stats ; stats = stats2 ; + colamd_printf = mexPrintf ; /* COLAMD printf routine */ + /* === Check inputs ===================================================== */ if (nrhs < 1 || nrhs > 2 || nlhs < 0 || nlhs > 2) @@ -166,7 +120,7 @@ mexErrMsgTxt ("symamdtest: knobs are required") ; } /* for testing we require all 3 knobs */ - if (mxGetNumberOfElements (prhs [1]) < 3) + if (mxGetNumberOfElements (prhs [1]) != 3) { mexErrMsgTxt ("symamdtest: must have all 3 knobs for testing") ; } @@ -181,15 +135,28 @@ { in_knobs = mxGetPr (prhs [1]) ; i = mxGetNumberOfElements (prhs [1]) ; - if (i > 0) knobs [COLAMD_DENSE_ROW] = in_knobs [COLAMD_DENSE_ROW] ; + if (i > 0) knobs [COLAMD_DENSE_ROW] = in_knobs [0] ; if (i > 1) spumoni = (int) in_knobs [1] ; } - /* print knob settings if spumoni > 0 */ - if (spumoni > 0) + /* print knob settings if spumoni is set */ + if (spumoni) { - mexPrintf ("symamd: dense row/col fraction: %f\n", - knobs [COLAMD_DENSE_ROW]) ; + mexPrintf ("\nsymamd version %d.%d, %s:\n", + COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION, COLAMD_DATE) ; + if (knobs [COLAMD_DENSE_ROW] >= 0) + { + mexPrintf ("knobs(1): %g, rows/cols with > " + "max(16,%g*sqrt(size(A,2))) entries removed\n", + in_knobs [0], knobs [COLAMD_DENSE_ROW]) ; + } + else + { + mexPrintf ("knobs(1): %g, no dense rows removed\n", in_knobs [0]) ; + } + mexPrintf ("knobs(2): %g, statistics and knobs printed\n", + in_knobs [1]) ; + mexPrintf ("Testing %d\n", in_knobs [2]) ; } /* === If A is full, convert to a sparse matrix ========================= */
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,9 @@ +2005-09-04 David Bateman <dbateman@free.fr> + + * COLAMD: Update version of colamd to v2.4. + * COLAMD.files: Add colamd_global.c to COLAMD_SRC and second build of + colamd.c for long version. + 2005-08-25 David Bateman <dbateman@free.fr> * Sparse-op-defs.h (FULL_SPARSE_MUL, SPARSE_FULL_MUL): Macro for