# HG changeset patch # User jwe # Date 1110833519 0 # Node ID 49de4e624020bb71ce361167ad2f6f5b6d012009 # Parent 63c15a67612d4c6dc5ce97df95126f9685faf630 [project @ 2005-03-14 20:51:59 by jwe] diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Demo/Makefile --- a/liboctave/UMFPACK/AMD/Demo/Makefile Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -#------------------------------------------------------------------------------ -# compile the AMD demo (for both GNU make or original make) -#----------------------------------------------------------------------------- - -all: amd_simple amd_demo amd_demo2 - -include ../Make/Make.include - -C = $(CC) $(CFLAGS) $(CONFIG) -I../Include - -INC = ../Include/amd.h - -../Lib/libamd.a: - ( cd ../Source ; make ) - -../Lib/libamdf77.a: - ( cd ../Source ; make fortran ) - -#------------------------------------------------------------------------------ -# Create the demo program, run it, and compare the output -#------------------------------------------------------------------------------ - -dist: - -amd_demo: amd_demo.c ../Lib/libamd.a $(INC) - $(C) -DDINT -o amd_demo amd_demo.c ../Lib/libamd.a $(LIB) - ./amd_demo > my_amd_demo.out - - diff amd_demo.out my_amd_demo.out - -amd_demo2: amd_demo2.c ../Lib/libamd.a $(INC) - $(C) -DDINT -o amd_demo2 amd_demo2.c ../Lib/libamd.a $(LIB) - ./amd_demo2 > my_amd_demo2.out - - diff amd_demo2.out my_amd_demo2.out - -amd_simple: amd_simple.c ../Lib/libamd.a $(INC) - $(C) -DDINT -o amd_simple amd_simple.c ../Lib/libamd.a $(LIB) - ./amd_simple > my_amd_simple.out - - diff amd_simple.out my_amd_simple.out - -#------------------------------------------------------------------------------ -# compile the Fortran demo -#------------------------------------------------------------------------------ - -fortran: amd_f77demo amd_f77simple - -cross: amd_f77cross - -amd_f77demo: amd_f77demo.f ../Lib/libamdf77.a - $(F77) $(F77FLAGS) -o amd_f77demo amd_f77demo.f ../Lib/libamdf77.a \ - $(F77LIB) - ./amd_f77demo > my_amd_f77demo.out - - diff amd_f77demo.out my_amd_f77demo.out - -amd_f77simple: amd_f77simple.f ../Lib/libamdf77.a - $(F77) $(F77FLAGS) -o amd_f77simple amd_f77simple.f \ - ../Lib/libamdf77.a $(F77LIB) - ./amd_f77simple > my_amd_f77simple.out - - diff amd_f77simple.out my_amd_f77simple.out - -amd_f77wrapper.o: amd_f77wrapper.c - $(C) -DDINT -c amd_f77wrapper.c - -amd_f77cross: amd_f77cross.f amd_f77wrapper.o ../Lib/libamd.a - $(F77) $(F77FLAGS) -o amd_f77cross amd_f77cross.f amd_f77wrapper.o \ - ../Lib/libamd.a $(F77LIB) - ./amd_f77cross > my_amd_f77cross.out - - diff amd_f77cross.out my_amd_f77cross.out - -#------------------------------------------------------------------------------ -# Remove all but the files in the original distribution -#------------------------------------------------------------------------------ - -purge: clean - - $(RM) amd_demo my_amd_demo.out - - $(RM) amd_demo2 my_amd_demo2.out - - $(RM) amd_simple my_amd_simple.out - - $(RM) amd_f77demo my_amd_f77demo.out - - $(RM) amd_f77simple my_amd_f77simple.out - - $(RM) amd_f77cross my_amd_f77cross.out diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Demo/amd_demo.c --- a/liboctave/UMFPACK/AMD/Demo/amd_demo.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,169 +0,0 @@ -/* ========================================================================= */ -/* === AMD demo main program =============================================== */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* A simple C main program that illustrates the use of the ANSI C interface - * to AMD. - */ - -#include "amd.h" -#include -#include - -int main (int argc, char **argv) -{ - /* The symmetric can_24 Harwell/Boeing matrix, including upper and lower - * triangular parts, and the diagonal entries. Note that this matrix is - * 0-based, with row and column indices in the range 0 to n-1. */ - int n = 24, nz, - Ap [ ] = { 0, 9, 15, 21, 27, 33, 39, 48, 57, 61, 70, 76, 82, 88, 94, 100, - 106, 110, 119, 128, 137, 143, 152, 156, 160 }, - Ai [ ] = { - /* column 0: */ 0, 5, 6, 12, 13, 17, 18, 19, 21, - /* column 1: */ 1, 8, 9, 13, 14, 17, - /* column 2: */ 2, 6, 11, 20, 21, 22, - /* column 3: */ 3, 7, 10, 15, 18, 19, - /* column 4: */ 4, 7, 9, 14, 15, 16, - /* column 5: */ 0, 5, 6, 12, 13, 17, - /* column 6: */ 0, 2, 5, 6, 11, 12, 19, 21, 23, - /* column 7: */ 3, 4, 7, 9, 14, 15, 16, 17, 18, - /* column 8: */ 1, 8, 9, 14, - /* column 9: */ 1, 4, 7, 8, 9, 13, 14, 17, 18, - /* column 10: */ 3, 10, 18, 19, 20, 21, - /* column 11: */ 2, 6, 11, 12, 21, 23, - /* column 12: */ 0, 5, 6, 11, 12, 23, - /* column 13: */ 0, 1, 5, 9, 13, 17, - /* column 14: */ 1, 4, 7, 8, 9, 14, - /* column 15: */ 3, 4, 7, 15, 16, 18, - /* column 16: */ 4, 7, 15, 16, - /* column 17: */ 0, 1, 5, 7, 9, 13, 17, 18, 19, - /* column 18: */ 0, 3, 7, 9, 10, 15, 17, 18, 19, - /* column 19: */ 0, 3, 6, 10, 17, 18, 19, 20, 21, - /* column 20: */ 2, 10, 19, 20, 21, 22, - /* column 21: */ 0, 2, 6, 10, 11, 19, 20, 21, 22, - /* column 22: */ 2, 20, 21, 22, - /* column 23: */ 6, 11, 12, 23 } ; - - int P [24], Pinv [24], i, j, k, jnew, p, inew, result ; - double Control [AMD_CONTROL], Info [AMD_INFO] ; - char A [24][24] ; - - printf ("AMD demo, with the 24-by-24 Harwell/Boeing matrix, can_24:\n") ; - - /* get the default parameters, and print them */ - amd_defaults (Control) ; - amd_control (Control) ; - - /* print the input matrix */ - nz = Ap [n] ; - printf ("\nInput matrix: %d-by-%d, with %d entries.\n" - " Note that for a symmetric matrix such as this one, only the\n" - " strictly lower or upper triangular parts would need to be\n" - " passed to AMD, since AMD computes the ordering of A+A'. The\n" - " diagonal entries are also not needed, since AMD ignores them.\n" - , n, n, nz) ; - for (j = 0 ; j < n ; j++) - { - printf ("\nColumn: %d, number of entries: %d, with row indices in" - " Ai [%d ... %d]:\n row indices:", - j, Ap [j+1] - Ap [j], Ap [j], Ap [j+1]-1) ; - for (p = Ap [j] ; p < Ap [j+1] ; p++) - { - i = Ai [p] ; - printf (" %d", i) ; - } - printf ("\n") ; - } - - /* print a character plot of the input matrix. This is only reasonable - * because the matrix is small. */ - printf ("\nPlot of input matrix pattern:\n") ; - for (j = 0 ; j < n ; j++) - { - for (i = 0 ; i < n ; i++) A [i][j] = '.' ; - for (p = Ap [j] ; p < Ap [j+1] ; p++) - { - i = Ai [p] ; - A [i][j] = 'X' ; - } - } - printf (" ") ; - for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ; - printf ("\n") ; - for (i = 0 ; i < n ; i++) - { - printf ("%2d: ", i) ; - for (j = 0 ; j < n ; j++) - { - printf (" %c", A [i][j]) ; - } - printf ("\n") ; - } - - /* order the matrix */ - result = amd_order (n, Ap, Ai, P, Control, Info) ; - printf ("return value from amd_order: %d (should be %d)\n", - result, AMD_OK) ; - - /* print the statistics */ - amd_info (Info) ; - - if (result != AMD_OK) - { - printf ("AMD failed\n") ; - exit (1) ; - } - - /* print the permutation vector, P, and compute the inverse permutation */ - printf ("Permutation vector:\n") ; - for (k = 0 ; k < n ; k++) - { - /* row/column j is the kth row/column in the permuted matrix */ - j = P [k] ; - Pinv [j] = k ; - printf (" %2d", j) ; - } - printf ("\n\n") ; - - printf ("Inverse permutation vector:\n") ; - for (j = 0 ; j < n ; j++) - { - k = Pinv [j] ; - printf (" %2d", k) ; - } - printf ("\n\n") ; - - /* print a character plot of the permuted matrix. */ - printf ("\nPlot of permuted matrix pattern:\n") ; - for (jnew = 0 ; jnew < n ; jnew++) - { - j = P [jnew] ; - for (inew = 0 ; inew < n ; inew++) A [inew][jnew] = '.' ; - for (p = Ap [j] ; p < Ap [j+1] ; p++) - { - inew = Pinv [Ai [p]] ; - A [inew][jnew] = 'X' ; - } - } - printf (" ") ; - for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ; - printf ("\n") ; - for (i = 0 ; i < n ; i++) - { - printf ("%2d: ", i) ; - for (j = 0 ; j < n ; j++) - { - printf (" %c", A [i][j]) ; - } - printf ("\n") ; - } - - return (0) ; -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Demo/amd_demo.out --- a/liboctave/UMFPACK/AMD/Demo/amd_demo.out Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -AMD demo, with the 24-by-24 Harwell/Boeing matrix, can_24: - -amd: approximate minimum degree ordering, parameters: - dense row parameter: 10 - (rows with more than max (10 * sqrt (n), 16) entries are - considered "dense", and placed last in output permutation) - aggressive absorption: yes - - -Input matrix: 24-by-24, with 160 entries. - Note that for a symmetric matrix such as this one, only the - strictly lower or upper triangular parts would need to be - passed to AMD, since AMD computes the ordering of A+A'. The - diagonal entries are also not needed, since AMD ignores them. - -Column: 0, number of entries: 9, with row indices in Ai [0 ... 8]: - row indices: 0 5 6 12 13 17 18 19 21 - -Column: 1, number of entries: 6, with row indices in Ai [9 ... 14]: - row indices: 1 8 9 13 14 17 - -Column: 2, number of entries: 6, with row indices in Ai [15 ... 20]: - row indices: 2 6 11 20 21 22 - -Column: 3, number of entries: 6, with row indices in Ai [21 ... 26]: - row indices: 3 7 10 15 18 19 - -Column: 4, number of entries: 6, with row indices in Ai [27 ... 32]: - row indices: 4 7 9 14 15 16 - -Column: 5, number of entries: 6, with row indices in Ai [33 ... 38]: - row indices: 0 5 6 12 13 17 - -Column: 6, number of entries: 9, with row indices in Ai [39 ... 47]: - row indices: 0 2 5 6 11 12 19 21 23 - -Column: 7, number of entries: 9, with row indices in Ai [48 ... 56]: - row indices: 3 4 7 9 14 15 16 17 18 - -Column: 8, number of entries: 4, with row indices in Ai [57 ... 60]: - row indices: 1 8 9 14 - -Column: 9, number of entries: 9, with row indices in Ai [61 ... 69]: - row indices: 1 4 7 8 9 13 14 17 18 - -Column: 10, number of entries: 6, with row indices in Ai [70 ... 75]: - row indices: 3 10 18 19 20 21 - -Column: 11, number of entries: 6, with row indices in Ai [76 ... 81]: - row indices: 2 6 11 12 21 23 - -Column: 12, number of entries: 6, with row indices in Ai [82 ... 87]: - row indices: 0 5 6 11 12 23 - -Column: 13, number of entries: 6, with row indices in Ai [88 ... 93]: - row indices: 0 1 5 9 13 17 - -Column: 14, number of entries: 6, with row indices in Ai [94 ... 99]: - row indices: 1 4 7 8 9 14 - -Column: 15, number of entries: 6, with row indices in Ai [100 ... 105]: - row indices: 3 4 7 15 16 18 - -Column: 16, number of entries: 4, with row indices in Ai [106 ... 109]: - row indices: 4 7 15 16 - -Column: 17, number of entries: 9, with row indices in Ai [110 ... 118]: - row indices: 0 1 5 7 9 13 17 18 19 - -Column: 18, number of entries: 9, with row indices in Ai [119 ... 127]: - row indices: 0 3 7 9 10 15 17 18 19 - -Column: 19, number of entries: 9, with row indices in Ai [128 ... 136]: - row indices: 0 3 6 10 17 18 19 20 21 - -Column: 20, number of entries: 6, with row indices in Ai [137 ... 142]: - row indices: 2 10 19 20 21 22 - -Column: 21, number of entries: 9, with row indices in Ai [143 ... 151]: - row indices: 0 2 6 10 11 19 20 21 22 - -Column: 22, number of entries: 4, with row indices in Ai [152 ... 155]: - row indices: 2 20 21 22 - -Column: 23, number of entries: 4, with row indices in Ai [156 ... 159]: - row indices: 6 11 12 23 - -Plot of input matrix pattern: - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 - 0: X . . . . X X . . . . . X X . . . X X X . X . . - 1: . X . . . . . . X X . . . X X . . X . . . . . . - 2: . . X . . . X . . . . X . . . . . . . . X X X . - 3: . . . X . . . X . . X . . . . X . . X X . . . . - 4: . . . . X . . X . X . . . . X X X . . . . . . . - 5: X . . . . X X . . . . . X X . . . X . . . . . . - 6: X . X . . X X . . . . X X . . . . . . X . X . X - 7: . . . X X . . X . X . . . . X X X X X . . . . . - 8: . X . . . . . . X X . . . . X . . . . . . . . . - 9: . X . . X . . X X X . . . X X . . X X . . . . . -10: . . . X . . . . . . X . . . . . . . X X X X . . -11: . . X . . . X . . . . X X . . . . . . . . X . X -12: X . . . . X X . . . . X X . . . . . . . . . . X -13: X X . . . X . . . X . . . X . . . X . . . . . . -14: . X . . X . . X X X . . . . X . . . . . . . . . -15: . . . X X . . X . . . . . . . X X . X . . . . . -16: . . . . X . . X . . . . . . . X X . . . . . . . -17: X X . . . X . X . X . . . X . . . X X X . . . . -18: X . . X . . . X . X X . . . . X . X X X . . . . -19: X . . X . . X . . . X . . . . . . X X X X X . . -20: . . X . . . . . . . X . . . . . . . . X X X X . -21: X . X . . . X . . . X X . . . . . . . X X X X . -22: . . X . . . . . . . . . . . . . . . . . X X X . -23: . . . . . . X . . . . X X . . . . . . . . . . X -return value from amd_order: 0 (should be 0) - -amd: approximate minimum degree ordering, results: - status: OK - n, dimension of A: 24 - nz, number of nonzeros in A: 160 - symmetry of A: 1.0000 - number of nonzeros on diagonal: 24 - nonzeros in pattern of A+A' (excl. diagonal): 136 - # dense rows/columns of A+A': 0 - memory used, in bytes: 1516 - # of memory compactions: 0 - - The following approximate statistics are for a subsequent - factorization of A(P,P) + A(P,P)'. They are slight upper - bounds if there are no dense rows/columns in A+A', and become - looser if dense rows/columns exist. - - nonzeros in L (excluding diagonal): 97 - nonzeros in L (including diagonal): 121 - # divide operations for LDL' or LU: 97 - # multiply-subtract operations for LDL': 275 - # multiply-subtract operations for LU: 453 - max nz. in any column of L (incl. diagonal): 8 - - chol flop count for real A, sqrt counted as 1 flop: 671 - LDL' flop count for real A: 647 - LDL' flop count for complex A: 3073 - LU flop count for real A (with no pivoting): 1003 - LU flop count for complex A (with no pivoting): 4497 - -Permutation vector: - 22 20 10 23 12 5 16 8 14 4 15 7 1 9 13 17 0 2 3 6 11 18 21 19 - -Inverse permutation vector: - 16 12 17 18 9 5 19 11 7 13 2 20 4 14 8 10 6 15 21 23 1 22 0 3 - - -Plot of permuted matrix pattern: - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 - 0: X X . . . . . . . . . . . . . . . X . . . . X . - 1: X X X . . . . . . . . . . . . . . X . . . . X X - 2: . X X . . . . . . . . . . . . . . . X . . X X X - 3: . . . X X . . . . . . . . . . . . . . X X . . . - 4: . . . X X X . . . . . . . . . . X . . X X . . . - 5: . . . . X X . . . . . . . . X X X . . X . . . . - 6: . . . . . . X . . X X X . . . . . . . . . . . . - 7: . . . . . . . X X . . . X X . . . . . . . . . . - 8: . . . . . . . X X X . X X X . . . . . . . . . . - 9: . . . . . . X . X X X X . X . . . . . . . . . . -10: . . . . . . X . . X X X . . . . . . X . . X . . -11: . . . . . . X . X X X X . X . X . . X . . X . . -12: . . . . . . . X X . . . X X X X . . . . . . . . -13: . . . . . . . X X X . X X X X X . . . . . X . . -14: . . . . . X . . . . . . X X X X X . . . . . . . -15: . . . . . X . . . . . X X X X X X . . . . X . X -16: . . . . X X . . . . . . . . X X X . . X . X X X -17: X X . . . . . . . . . . . . . . . X . X X . X . -18: . . X . . . . . . . X X . . . . . . X . . X . X -19: . . . X X X . . . . . . . . . . X X . X X . X X -20: . . . X X . . . . . . . . . . . . X . X X . X . -21: . . X . . . . . . . X X . X . X X . X . . X . X -22: X X X . . . . . . . . . . . . . X X . X X . X X -23: . X X . . . . . . . . . . . . X X . X X . X X X diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Demo/amd_demo2.c --- a/liboctave/UMFPACK/AMD/Demo/amd_demo2.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,261 +0,0 @@ -/* ========================================================================= */ -/* === AMD demo main program (jumbled matrix version) ====================== */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* A simple C main program that illustrates the use of the ANSI C interface - * to AMD. - * - * Identical to amd_demo.c, except that it operates on an input matrix that has - * unsorted columns and duplicate entries. - */ - -#include "amd.h" -#include -#include - -int main (int argc, char **argv) -{ - /* The symmetric can_24 Harwell/Boeing matrix (jumbled, and not symmetric). - * Since AMD operates on A+A', only A(i,j) or A(j,i) need to be specified, - * or both. The diagonal entries are optional (some are missing). - * There are many duplicate entries, which must be removed. */ - int n = 24, nz, - Ap [ ] = { 0, 9, 14, 20, 28, 33, 37, 44, 53, 58, 63, 63, 66, 69, 72, 75, - 78, 82, 86, 91, 97, 101, 112, 112, 116 }, - Ai [ ] = { - /* column 0: */ 0, 17, 18, 21, 5, 12, 5, 0, 13, - /* column 1: */ 14, 1, 8, 13, 17, - /* column 2: */ 2, 20, 11, 6, 11, 22, - /* column 3: */ 3, 3, 10, 7, 18, 18, 15, 19, - /* column 4: */ 7, 9, 15, 14, 16, - /* column 5: */ 5, 13, 6, 17, - /* column 6: */ 5, 0, 11, 6, 12, 6, 23, - /* column 7: */ 3, 4, 9, 7, 14, 16, 15, 17, 18, - /* column 8: */ 1, 9, 14, 14, 14, - /* column 9: */ 7, 13, 8, 1, 17, - /* column 10: */ - /* column 11: */ 2, 12, 23, - /* column 12: */ 5, 11, 12, - /* column 13: */ 0, 13, 17, - /* column 14: */ 1, 9, 14, - /* column 15: */ 3, 15, 16, - /* column 16: */ 16, 4, 4, 15, - /* column 17: */ 13, 17, 19, 17, - /* column 18: */ 15, 17, 19, 9, 10, - /* column 19: */ 17, 19, 20, 0, 6, 10, - /* column 20: */ 22, 10, 20, 21, - /* column 21: */ 6, 2, 10, 19, 20, 11, 21, 22, 22, 22, 22, - /* column 22: */ - /* column 23: */ 12, 11, 12, 23 } ; - - int Rp [25], Ri [116] ; - int P [24], Pinv [24], i, j, k, jnew, p, inew, result ; - double Control [AMD_CONTROL], Info [AMD_INFO] ; - char A [24][24] ; - - printf ("AMD demo, with a jumbled version of the 24-by-24\n") ; - printf ("Harwell/Boeing matrix, can_24:\n") ; - - /* get the default parameters, and print them */ - amd_defaults (Control) ; - amd_control (Control) ; - - /* print the input matrix */ - nz = Ap [n] ; - printf ("\nJumbled input matrix: %d-by-%d, with %d entries.\n" - " Note that for a symmetric matrix such as this one, only the\n" - " strictly lower or upper triangular parts would need to be\n" - " passed to AMD, since AMD computes the ordering of A+A'. The\n" - " diagonal entries are also not needed, since AMD ignores them.\n" - " This version of the matrix has jumbled columns and duplicate\n" - " row indices, and must be fixed by amd_preprocess prior to\n" - " ordering it with amd_order.\n" , n, n, nz) ; - for (j = 0 ; j < n ; j++) - { - printf ("\nColumn: %d, number of entries: %d, with row indices in" - " Ai [%d ... %d]:\n row indices:", - j, Ap [j+1] - Ap [j], Ap [j], Ap [j+1]-1) ; - for (p = Ap [j] ; p < Ap [j+1] ; p++) - { - i = Ai [p] ; - printf (" %d", i) ; - } - printf ("\n") ; - } - - /* print a character plot of the input matrix. This is only reasonable - * because the matrix is small. */ - printf ("\nPlot of (jumbled) input matrix pattern:\n") ; - for (j = 0 ; j < n ; j++) - { - for (i = 0 ; i < n ; i++) A [i][j] = '.' ; - for (p = Ap [j] ; p < Ap [j+1] ; p++) - { - i = Ai [p] ; - A [i][j] = 'X' ; - } - } - printf (" ") ; - for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ; - printf ("\n") ; - for (i = 0 ; i < n ; i++) - { - printf ("%2d: ", i) ; - for (j = 0 ; j < n ; j++) - { - printf (" %c", A [i][j]) ; - } - printf ("\n") ; - } - - /* sort, remove duplicates, and transpose A to get R */ - result = amd_preprocess (n, Ap, Ai, Rp, Ri) ; - printf ("return value from amd_preprocess: %d (should be %d)\n", - result, AMD_OK) ; - - if (result != AMD_OK) - { - printf ("AMD failed\n") ; - exit (1) ; - } - - /* print the sorted/transposed matrix R */ - printf ("\nThe column-oriented form of the sorted/transposed matrix R:\n"); - for (j = 0 ; j < n ; j++) - { - printf ("\nColumn: %d, number of entries: %d, with row indices in" - " Ri [%d ... %d]:\n row indices:", - j, Rp [j+1] - Rp [j], Rp [j], Rp [j+1]-1) ; - for (p = Rp [j] ; p < Rp [j+1] ; p++) - { - i = Ri [p] ; - printf (" %d", i) ; - } - printf ("\n") ; - } - - /* print a character plot of the matrix R. */ - printf ("\nPlot of the sorted/transposed matrix R:\n") ; - for (j = 0 ; j < n ; j++) - { - for (i = 0 ; i < n ; i++) A [i][j] = '.' ; - for (p = Rp [j] ; p < Rp [j+1] ; p++) - { - i = Ri [p] ; - A [i][j] = 'X' ; - } - } - printf (" ") ; - for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ; - printf (" \n") ; - for (i = 0 ; i < n ; i++) - { - printf ("%2d: ", i) ; - for (j = 0 ; j < n ; j++) - { - printf (" %c", A [i][j]) ; - } - printf (" \n") ; - } - - /* print a character plot of the matrix R+R'. */ - printf ("\nPlot of symmetric matrix to be ordered by amd_order:\n") ; - for (j = 0 ; j < n ; j++) - { - for (i = 0 ; i < n ; i++) A [i][j] = '.' ; - } - for (j = 0 ; j < n ; j++) - { - A [j][j] = 'X' ; - for (p = Rp [j] ; p < Rp [j+1] ; p++) - { - i = Ri [p] ; - A [i][j] = 'X' ; - A [j][i] = 'X' ; - } - } - printf (" ") ; - for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ; - printf ("\n") ; - for (i = 0 ; i < n ; i++) - { - printf ("%2d: ", i) ; - for (j = 0 ; j < n ; j++) - { - printf (" %c", A [i][j]) ; - } - printf ("\n") ; - } - - /* order the matrix */ - result = amd_order (n, Rp, Ri, P, Control, Info) ; - printf ("return value from amd_order: %d (should be %d)\n", - result, AMD_OK) ; - - /* print the statistics */ - amd_info (Info) ; - - if (result != AMD_OK) - { - printf ("AMD failed\n") ; - exit (1) ; - } - - /* print the permutation vector, P, and compute the inverse permutation */ - printf ("Permutation vector:\n") ; - for (k = 0 ; k < n ; k++) - { - /* row/column j is the kth row/column in the permuted matrix */ - j = P [k] ; - Pinv [j] = k ; - printf (" %2d", j) ; - } - printf ("\n\n") ; - - printf ("Inverse permutation vector:\n") ; - for (j = 0 ; j < n ; j++) - { - k = Pinv [j] ; - printf (" %2d", k) ; - } - printf ("\n\n") ; - - /* print a character plot of the permuted matrix. */ - printf ("\nPlot of (symmetrized) permuted matrix pattern:\n") ; - for (j = 0 ; j < n ; j++) - { - for (i = 0 ; i < n ; i++) A [i][j] = '.' ; - } - for (jnew = 0 ; jnew < n ; jnew++) - { - j = P [jnew] ; - A [jnew][jnew] = 'X' ; - for (p = Rp [j] ; p < Rp [j+1] ; p++) - { - inew = Pinv [Ri [p]] ; - A [inew][jnew] = 'X' ; - A [jnew][inew] = 'X' ; - } - } - printf (" ") ; - for (j = 0 ; j < n ; j++) printf (" %1d", j % 10) ; - printf ("\n") ; - for (i = 0 ; i < n ; i++) - { - printf ("%2d: ", i) ; - for (j = 0 ; j < n ; j++) - { - printf (" %c", A [i][j]) ; - } - printf ("\n") ; - } - - return (0) ; -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Demo/amd_demo2.out --- a/liboctave/UMFPACK/AMD/Demo/amd_demo2.out Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,310 +0,0 @@ -AMD demo, with a jumbled version of the 24-by-24 -Harwell/Boeing matrix, can_24: - -amd: approximate minimum degree ordering, parameters: - dense row parameter: 10 - (rows with more than max (10 * sqrt (n), 16) entries are - considered "dense", and placed last in output permutation) - aggressive absorption: yes - - -Jumbled input matrix: 24-by-24, with 116 entries. - Note that for a symmetric matrix such as this one, only the - strictly lower or upper triangular parts would need to be - passed to AMD, since AMD computes the ordering of A+A'. The - diagonal entries are also not needed, since AMD ignores them. - This version of the matrix has jumbled columns and duplicate - row indices, and must be fixed by amd_preprocess prior to - ordering it with amd_order. - -Column: 0, number of entries: 9, with row indices in Ai [0 ... 8]: - row indices: 0 17 18 21 5 12 5 0 13 - -Column: 1, number of entries: 5, with row indices in Ai [9 ... 13]: - row indices: 14 1 8 13 17 - -Column: 2, number of entries: 6, with row indices in Ai [14 ... 19]: - row indices: 2 20 11 6 11 22 - -Column: 3, number of entries: 8, with row indices in Ai [20 ... 27]: - row indices: 3 3 10 7 18 18 15 19 - -Column: 4, number of entries: 5, with row indices in Ai [28 ... 32]: - row indices: 7 9 15 14 16 - -Column: 5, number of entries: 4, with row indices in Ai [33 ... 36]: - row indices: 5 13 6 17 - -Column: 6, number of entries: 7, with row indices in Ai [37 ... 43]: - row indices: 5 0 11 6 12 6 23 - -Column: 7, number of entries: 9, with row indices in Ai [44 ... 52]: - row indices: 3 4 9 7 14 16 15 17 18 - -Column: 8, number of entries: 5, with row indices in Ai [53 ... 57]: - row indices: 1 9 14 14 14 - -Column: 9, number of entries: 5, with row indices in Ai [58 ... 62]: - row indices: 7 13 8 1 17 - -Column: 10, number of entries: 0, with row indices in Ai [63 ... 62]: - row indices: - -Column: 11, number of entries: 3, with row indices in Ai [63 ... 65]: - row indices: 2 12 23 - -Column: 12, number of entries: 3, with row indices in Ai [66 ... 68]: - row indices: 5 11 12 - -Column: 13, number of entries: 3, with row indices in Ai [69 ... 71]: - row indices: 0 13 17 - -Column: 14, number of entries: 3, with row indices in Ai [72 ... 74]: - row indices: 1 9 14 - -Column: 15, number of entries: 3, with row indices in Ai [75 ... 77]: - row indices: 3 15 16 - -Column: 16, number of entries: 4, with row indices in Ai [78 ... 81]: - row indices: 16 4 4 15 - -Column: 17, number of entries: 4, with row indices in Ai [82 ... 85]: - row indices: 13 17 19 17 - -Column: 18, number of entries: 5, with row indices in Ai [86 ... 90]: - row indices: 15 17 19 9 10 - -Column: 19, number of entries: 6, with row indices in Ai [91 ... 96]: - row indices: 17 19 20 0 6 10 - -Column: 20, number of entries: 4, with row indices in Ai [97 ... 100]: - row indices: 22 10 20 21 - -Column: 21, number of entries: 11, with row indices in Ai [101 ... 111]: - row indices: 6 2 10 19 20 11 21 22 22 22 22 - -Column: 22, number of entries: 0, with row indices in Ai [112 ... 111]: - row indices: - -Column: 23, number of entries: 4, with row indices in Ai [112 ... 115]: - row indices: 12 11 12 23 - -Plot of (jumbled) input matrix pattern: - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 - 0: X . . . . . X . . . . . . X . . . . . X . . . . - 1: . X . . . . . . X X . . . . X . . . . . . . . . - 2: . . X . . . . . . . . X . . . . . . . . . X . . - 3: . . . X . . . X . . . . . . . X . . . . . . . . - 4: . . . . . . . X . . . . . . . . X . . . . . . . - 5: X . . . . X X . . . . . X . . . . . . . . . . . - 6: . . X . . X X . . . . . . . . . . . . X . X . . - 7: . . . X X . . X . X . . . . . . . . . . . . . . - 8: . X . . . . . . . X . . . . . . . . . . . . . . - 9: . . . . X . . X X . . . . . X . . . X . . . . . -10: . . . X . . . . . . . . . . . . . . X X X X . . -11: . . X . . . X . . . . . X . . . . . . . . X . X -12: X . . . . . X . . . . X X . . . . . . . . . . X -13: X X . . . X . . . X . . . X . . . X . . . . . . -14: . X . . X . . X X . . . . . X . . . . . . . . . -15: . . . X X . . X . . . . . . . X X . X . . . . . -16: . . . . X . . X . . . . . . . X X . . . . . . . -17: X X . . . X . X . X . . . X . . . X X X . . . . -18: X . . X . . . X . . . . . . . . . . . . . . . . -19: . . . X . . . . . . . . . . . . . X X X . X . . -20: . . X . . . . . . . . . . . . . . . . X X X . . -21: X . . . . . . . . . . . . . . . . . . . X X . . -22: . . X . . . . . . . . . . . . . . . . . X X . . -23: . . . . . . X . . . . X . . . . . . . . . . . X -return value from amd_preprocess: 0 (should be 0) - -The column-oriented form of the sorted/transposed matrix R: - -Column: 0, number of entries: 4, with row indices in Ri [0 ... 3]: - row indices: 0 6 13 19 - -Column: 1, number of entries: 4, with row indices in Ri [4 ... 7]: - row indices: 1 8 9 14 - -Column: 2, number of entries: 3, with row indices in Ri [8 ... 10]: - row indices: 2 11 21 - -Column: 3, number of entries: 3, with row indices in Ri [11 ... 13]: - row indices: 3 7 15 - -Column: 4, number of entries: 2, with row indices in Ri [14 ... 15]: - row indices: 7 16 - -Column: 5, number of entries: 4, with row indices in Ri [16 ... 19]: - row indices: 0 5 6 12 - -Column: 6, number of entries: 5, with row indices in Ri [20 ... 24]: - row indices: 2 5 6 19 21 - -Column: 7, number of entries: 4, with row indices in Ri [25 ... 28]: - row indices: 3 4 7 9 - -Column: 8, number of entries: 2, with row indices in Ri [29 ... 30]: - row indices: 1 9 - -Column: 9, number of entries: 5, with row indices in Ri [31 ... 35]: - row indices: 4 7 8 14 18 - -Column: 10, number of entries: 5, with row indices in Ri [36 ... 40]: - row indices: 3 18 19 20 21 - -Column: 11, number of entries: 5, with row indices in Ri [41 ... 45]: - row indices: 2 6 12 21 23 - -Column: 12, number of entries: 5, with row indices in Ri [46 ... 50]: - row indices: 0 6 11 12 23 - -Column: 13, number of entries: 6, with row indices in Ri [51 ... 56]: - row indices: 0 1 5 9 13 17 - -Column: 14, number of entries: 5, with row indices in Ri [57 ... 61]: - row indices: 1 4 7 8 14 - -Column: 15, number of entries: 6, with row indices in Ri [62 ... 67]: - row indices: 3 4 7 15 16 18 - -Column: 16, number of entries: 4, with row indices in Ri [68 ... 71]: - row indices: 4 7 15 16 - -Column: 17, number of entries: 9, with row indices in Ri [72 ... 80]: - row indices: 0 1 5 7 9 13 17 18 19 - -Column: 18, number of entries: 3, with row indices in Ri [81 ... 83]: - row indices: 0 3 7 - -Column: 19, number of entries: 5, with row indices in Ri [84 ... 88]: - row indices: 3 17 18 19 21 - -Column: 20, number of entries: 4, with row indices in Ri [89 ... 92]: - row indices: 2 19 20 21 - -Column: 21, number of entries: 3, with row indices in Ri [93 ... 95]: - row indices: 0 20 21 - -Column: 22, number of entries: 3, with row indices in Ri [96 ... 98]: - row indices: 2 20 21 - -Column: 23, number of entries: 3, with row indices in Ri [99 ... 101]: - row indices: 6 11 23 - -Plot of the sorted/transposed matrix R: - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 - 0: X . . . . X . . . . . . X X . . . X X . . X . . - 1: . X . . . . . . X . . . . X X . . X . . . . . . - 2: . . X . . . X . . . . X . . . . . . . . X . X . - 3: . . . X . . . X . . X . . . . X . . X X . . . . - 4: . . . . . . . X . X . . . . X X X . . . . . . . - 5: . . . . . X X . . . . . . X . . . X . . . . . . - 6: X . . . . X X . . . . X X . . . . . . . . . . X - 7: . . . X X . . X . X . . . . X X X X X . . . . . - 8: . X . . . . . . . X . . . . X . . . . . . . . . - 9: . X . . . . . X X . . . . X . . . X . . . . . . -10: . . . . . . . . . . . . . . . . . . . . . . . . -11: . . X . . . . . . . . . X . . . . . . . . . . X -12: . . . . . X . . . . . X X . . . . . . . . . . . -13: X . . . . . . . . . . . . X . . . X . . . . . . -14: . X . . . . . . . X . . . . X . . . . . . . . . -15: . . . X . . . . . . . . . . . X X . . . . . . . -16: . . . . X . . . . . . . . . . X X . . . . . . . -17: . . . . . . . . . . . . . X . . . X . X . . . . -18: . . . . . . . . . X X . . . . X . X . X . . . . -19: X . . . . . X . . . X . . . . . . X . X X . . . -20: . . . . . . . . . . X . . . . . . . . . X X X . -21: . . X . . . X . . . X X . . . . . . . X X X X . -22: . . . . . . . . . . . . . . . . . . . . . . . . -23: . . . . . . . . . . . X X . . . . . . . . . . X - -Plot of symmetric matrix to be ordered by amd_order: - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 - 0: X . . . . X X . . . . . X X . . . X X X . X . . - 1: . X . . . . . . X X . . . X X . . X . . . . . . - 2: . . X . . . X . . . . X . . . . . . . . X X X . - 3: . . . X . . . X . . X . . . . X . . X X . . . . - 4: . . . . X . . X . X . . . . X X X . . . . . . . - 5: X . . . . X X . . . . . X X . . . X . . . . . . - 6: X . X . . X X . . . . X X . . . . . . X . X . X - 7: . . . X X . . X . X . . . . X X X X X . . . . . - 8: . X . . . . . . X X . . . . X . . . . . . . . . - 9: . X . . X . . X X X . . . X X . . X X . . . . . -10: . . . X . . . . . . X . . . . . . . X X X X . . -11: . . X . . . X . . . . X X . . . . . . . . X . X -12: X . . . . X X . . . . X X . . . . . . . . . . X -13: X X . . . X . . . X . . . X . . . X . . . . . . -14: . X . . X . . X X X . . . . X . . . . . . . . . -15: . . . X X . . X . . . . . . . X X . X . . . . . -16: . . . . X . . X . . . . . . . X X . . . . . . . -17: X X . . . X . X . X . . . X . . . X X X . . . . -18: X . . X . . . X . X X . . . . X . X X X . . . . -19: X . . X . . X . . . X . . . . . . X X X X X . . -20: . . X . . . . . . . X . . . . . . . . X X X X . -21: X . X . . . X . . . X X . . . . . . . X X X X . -22: . . X . . . . . . . . . . . . . . . . . X X X . -23: . . . . . . X . . . . X X . . . . . . . . . . X -return value from amd_order: 0 (should be 0) - -amd: approximate minimum degree ordering, results: - status: OK - n, dimension of A: 24 - nz, number of nonzeros in A: 102 - symmetry of A: 0.4000 - number of nonzeros on diagonal: 17 - nonzeros in pattern of A+A' (excl. diagonal): 136 - # dense rows/columns of A+A': 0 - memory used, in bytes: 1516 - # of memory compactions: 0 - - The following approximate statistics are for a subsequent - factorization of A(P,P) + A(P,P)'. They are slight upper - bounds if there are no dense rows/columns in A+A', and become - looser if dense rows/columns exist. - - nonzeros in L (excluding diagonal): 97 - nonzeros in L (including diagonal): 121 - # divide operations for LDL' or LU: 97 - # multiply-subtract operations for LDL': 275 - # multiply-subtract operations for LU: 453 - max nz. in any column of L (incl. diagonal): 8 - - chol flop count for real A, sqrt counted as 1 flop: 671 - LDL' flop count for real A: 647 - LDL' flop count for complex A: 3073 - LU flop count for real A (with no pivoting): 1003 - LU flop count for complex A (with no pivoting): 4497 - -Permutation vector: - 22 20 10 23 12 5 16 8 14 4 15 7 1 9 13 17 0 2 3 6 11 18 21 19 - -Inverse permutation vector: - 16 12 17 18 9 5 19 11 7 13 2 20 4 14 8 10 6 15 21 23 1 22 0 3 - - -Plot of (symmetrized) permuted matrix pattern: - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 - 0: X X . . . . . . . . . . . . . . . X . . . . X . - 1: X X X . . . . . . . . . . . . . . X . . . . X X - 2: . X X . . . . . . . . . . . . . . . X . . X X X - 3: . . . X X . . . . . . . . . . . . . . X X . . . - 4: . . . X X X . . . . . . . . . . X . . X X . . . - 5: . . . . X X . . . . . . . . X X X . . X . . . . - 6: . . . . . . X . . X X X . . . . . . . . . . . . - 7: . . . . . . . X X . . . X X . . . . . . . . . . - 8: . . . . . . . X X X . X X X . . . . . . . . . . - 9: . . . . . . X . X X X X . X . . . . . . . . . . -10: . . . . . . X . . X X X . . . . . . X . . X . . -11: . . . . . . X . X X X X . X . X . . X . . X . . -12: . . . . . . . X X . . . X X X X . . . . . . . . -13: . . . . . . . X X X . X X X X X . . . . . X . . -14: . . . . . X . . . . . . X X X X X . . . . . . . -15: . . . . . X . . . . . X X X X X X . . . . X . X -16: . . . . X X . . . . . . . . X X X . . X . X X X -17: X X . . . . . . . . . . . . . . . X . X X . X . -18: . . X . . . . . . . X X . . . . . . X . . X . X -19: . . . X X X . . . . . . . . . . X X . X X . X X -20: . . . X X . . . . . . . . . . . . X . X X . X . -21: . . X . . . . . . . X X . X . X X . X . . X . X -22: X X X . . . . . . . . . . . . . X X . X X . X X -23: . X X . . . . . . . . . . . . X X . X X . X X X diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Demo/amd_f77cross.f --- a/liboctave/UMFPACK/AMD/Demo/amd_f77cross.f Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -C ====================================================================== -C === AMD_cross ======================================================== -C ====================================================================== - -C ---------------------------------------------------------------------- -C AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. -C Davis, Patrick R. Amestoy, and Iain S. Duff. See ../README for -C License. email: davis@cise.ufl.edu CISE Department, Univ. of -C Florida. web: http://www.cise.ufl.edu/research/sparse/amd -C ---------------------------------------------------------------------- - -C This program provides an example of how to call the C version of AMD -C from a Fortran program. It is HIGHLY non-portable. - -C The amd_order routine returns PERM (1) < 0 if an error occurs. -C (-1: out of memory, -2: invalid matrix) - -C Note that the input matrix is 0-based. From Fortran, column j of the -C matrix is in AI (AP (I)+1 ... AP (I+1)). The row indices in this -C set are in the range 0 to N-1. To demonstrate this translation, -C the input matrix is printed in 1-based form. This program uses -C the same 5-by-5 test matrix as amd_simple.c. - - INTEGER N, NZ, K, P - PARAMETER (N = 5, NZ = 14) - INTEGER AP (N+1), AI (NZ), PERM (N) - DATA AP / 0, 2, 6, 10, 12, 14 / - DATA AI / 0,1, 0,1,2,4, 1,2,3,4, 2,3, 1,4 / - DOUBLE PRECISION CONTROL (5), INFO (20) - -C print the input matrix - PRINT 10, N, N, NZ -10 FORMAT ('Input matrix:', I2, '-by-', I2, ' with',I3,' entries') - DO 40 J = 1, N - PRINT 20, J, AP (J+1) - AP (J), AP (J)+1, AP (J+1) -20 FORMAT ( /, 'Column: ', I2, ' number of entries: ', I2, - $ ' with row indices in AI (', I3, ' ... ', I3, ')') - PRINT 30, ((AI (P) + 1), P = AP (J) + 1, AP (J+1)) -30 FORMAT (' row indices: ', 24I3) -40 CONTINUE - - CALL AMDDEFAULTS (CONTROL) - CALL AMDORDER (N, AP, AI, PERM, CONTROL, INFO) - CALL AMDINFO (INFO) - - DO 60 K = 1, N - PRINT 50, K, PERM (K) + 1 -50 FORMAT ('PERM (',I2,') = ', I2) -60 CONTINUE - END - diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Demo/amd_f77cross.out --- a/liboctave/UMFPACK/AMD/Demo/amd_f77cross.out Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -Input matrix: 5-by- 5 with 14 entries - -Column: 1 number of entries: 2 with row indices in AI ( 1 ... 2) - row indices: 1 2 - -Column: 2 number of entries: 4 with row indices in AI ( 3 ... 6) - row indices: 1 2 3 5 - -Column: 3 number of entries: 4 with row indices in AI ( 7 ... 10) - row indices: 2 3 4 5 - -Column: 4 number of entries: 2 with row indices in AI ( 11 ... 12) - row indices: 3 4 - -Column: 5 number of entries: 2 with row indices in AI ( 13 ... 14) - row indices: 2 5 - -amd: approximate minimum degree ordering, results: - status: OK - n, dimension of A: 5 - nz, number of nonzeros in A: 14 - symmetry of A: 0.8889 - number of nonzeros on diagonal: 5 - nonzeros in pattern of A+A' (excl. diagonal): 10 - # dense rows/columns of A+A': 0 - memory used, in bytes: 228 - # of memory compactions: 0 - - The following approximate statistics are for a subsequent - factorization of A(P,P) + A(P,P)'. They are slight upper - bounds if there are no dense rows/columns in A+A', and become - looser if dense rows/columns exist. - - nonzeros in L (excluding diagonal): 5 - nonzeros in L (including diagonal): 10 - # divide operations for LDL' or LU: 5 - # multiply-subtract operations for LDL': 6 - # multiply-subtract operations for LU: 7 - max nz. in any column of L (incl. diagonal): 3 - - chol flop count for real A, sqrt counted as 1 flop: 22 - LDL' flop count for real A: 17 - LDL' flop count for complex A: 93 - LU flop count for real A (with no pivoting): 19 - LU flop count for complex A (with no pivoting): 101 - -PERM ( 1) = 1 -PERM ( 2) = 4 -PERM ( 3) = 3 -PERM ( 4) = 5 -PERM ( 5) = 2 diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Demo/amd_f77demo.f --- a/liboctave/UMFPACK/AMD/Demo/amd_f77demo.f Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -C ====================================================================== -C === Fortran AMD demo main program ==================================== -C ====================================================================== - -C ---------------------------------------------------------------------- -C AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. -C Davis, Patrick R. Amestoy, and Iain S. Duff. See ../README for -C License. email: davis@cise.ufl.edu CISE Department, Univ. of -C Florida. web: http://www.cise.ufl.edu/research/sparse/amd -C ---------------------------------------------------------------------- - -C A simple Fortran 77 main program that illustrates the use of the -C Fortran version of AMD (both the AMD and AMDBAR routines). Note -C that aggressive absorption has no effect on this particular matrix. - -C AP and AI contain the symmetric can_24 Harwell/Boeing matrix, -C including upper and lower triangular parts, but excluding the -C diagonal entries. Note that this matrix is 1-based, with row -C and column indices in the range 1 to N. - - INTEGER N, NZ, IWLEN, PFREE, I, J, K, JNEW, P, INEW, - $ METHOD, NCMPA - PARAMETER (N = 24, NZ = 136, IWLEN = 200) - INTEGER PE (N), DEGREE (N), NV (N), NEXT (N), PERM (N), W (N), - $ HEAD (N), PINV (N), LEN (N), AP (N+1), AI (NZ), IW (IWLEN) - CHARACTER A (24,24) - - DATA AP - $ / 1, 9, 14, 19, 24, 29, 34, 42, 50, 53, 61, 66, 71, - $ 76, 81, 86, 91, 94, 102, 110, 118, 123, 131, 134, 137 / - DATA AI / - $ 6, 7, 13, 14, 18, 19, 20, 22, - $ 9, 10, 14, 15, 18, - $ 7, 12, 21, 22, 23, - $ 8, 11, 16, 19, 20, - $ 8, 10, 15, 16, 17, - $ 1, 7, 13, 14, 18, - $ 1, 3, 6, 12, 13, 20, 22, 24, - $ 4, 5, 10, 15, 16, 17, 18, 19, - $ 2, 10, 15, - $ 2, 5, 8, 9, 14, 15, 18, 19, - $ 4, 19, 20, 21, 22, - $ 3, 7, 13, 22, 24, - $ 1, 6, 7, 12, 24, - $ 1, 2, 6, 10, 18, - $ 2, 5, 8, 9, 10, - $ 4, 5, 8, 17, 19, - $ 5, 8, 16, - $ 1, 2, 6, 8, 10, 14, 19, 20, - $ 1, 4, 8, 10, 11, 16, 18, 20, - $ 1, 4, 7, 11, 18, 19, 21, 22, - $ 3, 11, 20, 22, 23, - $ 1, 3, 7, 11, 12, 20, 21, 23, - $ 3, 21, 22, - $ 7, 12, 13 / - -C print the input matrix - PRINT 11, N, N, NZ -11 FORMAT ('AMD Fortran 77 demo, with the 24-by-24', - $ ' Harwell/Boeing matrix, can_24:' - $ /, 'Input matrix: ', I2, '-by-', I2,' with ',I3,' entries', - $ /, 'Note that the Fortran version of AMD requires that' - $ /, 'no diagonal entries be present.') - DO 20 J = 1, N - PRINT 21, J, AP (J+1) - AP (J), AP (J), AP (J+1)-1 -21 FORMAT ( /, 'Column: ', I2, ' number of entries: ', I2, - $ ' with row indices in AI (', I3, ' ... ', I3, ')') - PRINT 10, ((AI (P)), P = AP (J), AP (J+1) - 1) -10 FORMAT (' row indices: ', 24I3) -20 CONTINUE - -C print a character plot of the input matrix. This is only -C reasonable because the matrix is small. - PRINT 31 -31 FORMAT ('Plot of input matrix pattern:') - DO 50 J = 1,N - DO 30 I = 1,N - A (I, J) = '.' -30 CONTINUE -C add the diagonal entry to the plot - A (J, J) = 'X' - DO 40 P = AP (J), AP (J+1) - 1 - I = AI (P) - A (I, J) = 'X' -40 CONTINUE -50 CONTINUE - PRINT 60, ((MOD (J, 10)), J = 1,N) -60 FORMAT (' ', 24I2) - DO 80 I = 1,N - PRINT 70, I, (A (I, J), J = 1,N) -70 FORMAT (' ', I2, ': ', 24A2) -80 CONTINUE - - DO 190 METHOD = 1,2 - -C load the matrix into AMD's workspace - DO 90 J = 1,N - PE (J) = AP (J) - LEN (J) = AP (J+1) - AP (J) -90 CONTINUE - DO 100 P = 1,NZ - IW (P) = AI (P) -100 CONTINUE - PFREE = NZ + 1 - -C order the matrix using AMD or AMDBAR - IF (METHOD .EQ. 1) THEN - PRINT 101 -101 FORMAT (/, '------------------------------------------', - $ /, 'ordering the matrix with AMD', - $ /, '------------------------------------------') - CALL AMD (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, - $ PERM, HEAD, PINV, DEGREE, NCMPA, W) - ELSE - PRINT 102 -102 FORMAT (/, '------------------------------------------', - $ /, 'ordering the matrix with AMDBAR', - $ /, '------------------------------------------') - CALL AMDBAR (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, - $ PERM, HEAD, PINV, DEGREE, NCMPA, W) - ENDIF - -C print the permutation vector, PERM, and its inverse, PINV. -C row/column J = PERM (K) is the Kth row/column in the -C permuted matrix. - PRINT 110, (PERM (K), K = 1,N) -110 FORMAT (/, 'Permutation vector: ', /, 24I3) - PRINT 120, (PINV (J), J = 1,N) -120 FORMAT (/, 'Inverse permutation vector: ', /, 24I3) - -C print a character plot of the permuted matrix. - PRINT 121 -121 FORMAT ('Plot of permuted matrix pattern:') - DO 150 JNEW = 1,N - J = PERM (JNEW) - DO 130 INEW = 1,N - A (INEW, JNEW) = '.' -130 CONTINUE -C add the diagonal entry to the plot - A (JNEW, JNEW) = 'X' - DO 140 P = AP (J), AP (J+1) - 1 - INEW = PINV (AI (P)) - A (INEW, JNEW) = 'X' -140 CONTINUE -150 CONTINUE - PRINT 60, ((MOD (J, 10)), J = 1,N) - DO 160 I = 1,N - PRINT 70, I, (A (I, J), J = 1,N) -160 CONTINUE - -C print the permuted matrix, PERM*A*PERM' - DO 180 JNEW = 1,N - J = PERM (JNEW) - PRINT 171, JNEW, J, AP (J+1) - AP (J) -171 FORMAT (/, 'New column: ', I2, ' old column: ', I2, - $ ' number of entries: ', I2) - PRINT 170, (PINV (AI (P)), P = AP (J), AP (J+1) - 1) -170 FORMAT (' new row indices: ', 24I3) -180 CONTINUE -190 CONTINUE - END diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Demo/amd_f77demo.out --- a/liboctave/UMFPACK/AMD/Demo/amd_f77demo.out Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,318 +0,0 @@ -AMD Fortran 77 demo, with the 24-by-24 Harwell/Boeing matrix, can_24: -Input matrix: 24-by-24 with 136 entries -Note that the Fortran version of AMD requires that -no diagonal entries be present. - -Column: 1 number of entries: 8 with row indices in AI ( 1 ... 8) - row indices: 6 7 13 14 18 19 20 22 - -Column: 2 number of entries: 5 with row indices in AI ( 9 ... 13) - row indices: 9 10 14 15 18 - -Column: 3 number of entries: 5 with row indices in AI ( 14 ... 18) - row indices: 7 12 21 22 23 - -Column: 4 number of entries: 5 with row indices in AI ( 19 ... 23) - row indices: 8 11 16 19 20 - -Column: 5 number of entries: 5 with row indices in AI ( 24 ... 28) - row indices: 8 10 15 16 17 - -Column: 6 number of entries: 5 with row indices in AI ( 29 ... 33) - row indices: 1 7 13 14 18 - -Column: 7 number of entries: 8 with row indices in AI ( 34 ... 41) - row indices: 1 3 6 12 13 20 22 24 - -Column: 8 number of entries: 8 with row indices in AI ( 42 ... 49) - row indices: 4 5 10 15 16 17 18 19 - -Column: 9 number of entries: 3 with row indices in AI ( 50 ... 52) - row indices: 2 10 15 - -Column: 10 number of entries: 8 with row indices in AI ( 53 ... 60) - row indices: 2 5 8 9 14 15 18 19 - -Column: 11 number of entries: 5 with row indices in AI ( 61 ... 65) - row indices: 4 19 20 21 22 - -Column: 12 number of entries: 5 with row indices in AI ( 66 ... 70) - row indices: 3 7 13 22 24 - -Column: 13 number of entries: 5 with row indices in AI ( 71 ... 75) - row indices: 1 6 7 12 24 - -Column: 14 number of entries: 5 with row indices in AI ( 76 ... 80) - row indices: 1 2 6 10 18 - -Column: 15 number of entries: 5 with row indices in AI ( 81 ... 85) - row indices: 2 5 8 9 10 - -Column: 16 number of entries: 5 with row indices in AI ( 86 ... 90) - row indices: 4 5 8 17 19 - -Column: 17 number of entries: 3 with row indices in AI ( 91 ... 93) - row indices: 5 8 16 - -Column: 18 number of entries: 8 with row indices in AI ( 94 ... 101) - row indices: 1 2 6 8 10 14 19 20 - -Column: 19 number of entries: 8 with row indices in AI (102 ... 109) - row indices: 1 4 8 10 11 16 18 20 - -Column: 20 number of entries: 8 with row indices in AI (110 ... 117) - row indices: 1 4 7 11 18 19 21 22 - -Column: 21 number of entries: 5 with row indices in AI (118 ... 122) - row indices: 3 11 20 22 23 - -Column: 22 number of entries: 8 with row indices in AI (123 ... 130) - row indices: 1 3 7 11 12 20 21 23 - -Column: 23 number of entries: 3 with row indices in AI (131 ... 133) - row indices: 3 21 22 - -Column: 24 number of entries: 3 with row indices in AI (134 ... 136) - row indices: 7 12 13 -Plot of input matrix pattern: - 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 - 1: X . . . . X X . . . . . X X . . . X X X . X . . - 2: . X . . . . . . X X . . . X X . . X . . . . . . - 3: . . X . . . X . . . . X . . . . . . . . X X X . - 4: . . . X . . . X . . X . . . . X . . X X . . . . - 5: . . . . X . . X . X . . . . X X X . . . . . . . - 6: X . . . . X X . . . . . X X . . . X . . . . . . - 7: X . X . . X X . . . . X X . . . . . . X . X . X - 8: . . . X X . . X . X . . . . X X X X X . . . . . - 9: . X . . . . . . X X . . . . X . . . . . . . . . - 10: . X . . X . . X X X . . . X X . . X X . . . . . - 11: . . . X . . . . . . X . . . . . . . X X X X . . - 12: . . X . . . X . . . . X X . . . . . . . . X . X - 13: X . . . . X X . . . . X X . . . . . . . . . . X - 14: X X . . . X . . . X . . . X . . . X . . . . . . - 15: . X . . X . . X X X . . . . X . . . . . . . . . - 16: . . . X X . . X . . . . . . . X X . X . . . . . - 17: . . . . X . . X . . . . . . . X X . . . . . . . - 18: X X . . . X . X . X . . . X . . . X X X . . . . - 19: X . . X . . . X . X X . . . . X . X X X . . . . - 20: X . . X . . X . . . X . . . . . . X X X X X . . - 21: . . X . . . . . . . X . . . . . . . . X X X X . - 22: X . X . . . X . . . X X . . . . . . . X X X X . - 23: . . X . . . . . . . . . . . . . . . . . X X X . - 24: . . . . . . X . . . . X X . . . . . . . . . . X - ------------------------------------------- -ordering the matrix with AMD ------------------------------------------- - -Permutation vector: - 24 23 17 9 15 5 21 13 6 11 16 8 2 10 14 18 1 3 4 19 7 12 22 20 - -Inverse permutation vector: - 17 13 18 19 6 9 21 12 4 14 10 22 8 15 5 11 3 16 20 24 7 23 2 1 -Plot of permuted matrix pattern: - 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 - 1: X . . . . . . X . . . . . . . . . . . . X X . . - 2: . X . . . . X . . . . . . . . . . X . . . . X . - 3: . . X . . X . . . . X X . . . . . . . . . . . . - 4: . . . X X . . . . . . . X X . . . . . . . . . . - 5: . . . X X X . . . . . X X X . . . . . . . . . . - 6: . . X . X X . . . . X X . X . . . . . . . . . . - 7: . X . . . . X . . X . . . . . . . X . . . . X X - 8: X . . . . . . X X . . . . . . . X . . . X X . . - 9: . . . . . . . X X . . . . . X X X . . . X . . . - 10: . . . . . . X . . X . . . . . . . . X X . . X X - 11: . . X . . X . . . . X X . . . . . . X X . . . . - 12: . . X . X X . . . . X X . X . X . . X X . . . . - 13: . . . X X . . . . . . . X X X X . . . . . . . . - 14: . . . X X X . . . . . X X X X X . . . X . . . . - 15: . . . . . . . . X . . . X X X X X . . . . . . . - 16: . . . . . . . . X . . X X X X X X . . X . . . X - 17: . . . . . . . X X . . . . . X X X . . X X . X X - 18: . X . . . . X . . . . . . . . . . X . . X X X . - 19: . . . . . . . . . X X X . . . . . . X X . . . X - 20: . . . . . . . . . X X X . X . X X . X X . . . X - 21: X . . . . . . X X . . . . . . . X X . . X X X X - 22: X . . . . . . X . . . . . . . . . X . . X X X . - 23: . X . . . . X . . X . . . . . . X X . . X X X X - 24: . . . . . . X . . X . . . . . X X . X X X . X X - -New column: 1 old column: 24 number of entries: 3 - new row indices: 21 22 8 - -New column: 2 old column: 23 number of entries: 3 - new row indices: 18 7 23 - -New column: 3 old column: 17 number of entries: 3 - new row indices: 6 12 11 - -New column: 4 old column: 9 number of entries: 3 - new row indices: 13 14 5 - -New column: 5 old column: 15 number of entries: 5 - new row indices: 13 6 12 4 14 - -New column: 6 old column: 5 number of entries: 5 - new row indices: 12 14 5 11 3 - -New column: 7 old column: 21 number of entries: 5 - new row indices: 18 10 24 23 2 - -New column: 8 old column: 13 number of entries: 5 - new row indices: 17 9 21 22 1 - -New column: 9 old column: 6 number of entries: 5 - new row indices: 17 21 8 15 16 - -New column: 10 old column: 11 number of entries: 5 - new row indices: 19 20 24 7 23 - -New column: 11 old column: 16 number of entries: 5 - new row indices: 19 6 12 3 20 - -New column: 12 old column: 8 number of entries: 8 - new row indices: 19 6 14 5 11 3 16 20 - -New column: 13 old column: 2 number of entries: 5 - new row indices: 4 14 15 5 16 - -New column: 14 old column: 10 number of entries: 8 - new row indices: 13 6 12 4 15 5 16 20 - -New column: 15 old column: 14 number of entries: 5 - new row indices: 17 13 9 14 16 - -New column: 16 old column: 18 number of entries: 8 - new row indices: 17 13 9 12 14 15 20 24 - -New column: 17 old column: 1 number of entries: 8 - new row indices: 9 21 8 15 16 20 24 23 - -New column: 18 old column: 3 number of entries: 5 - new row indices: 21 22 7 23 2 - -New column: 19 old column: 4 number of entries: 5 - new row indices: 12 10 11 20 24 - -New column: 20 old column: 19 number of entries: 8 - new row indices: 17 19 12 14 10 11 16 24 - -New column: 21 old column: 7 number of entries: 8 - new row indices: 17 18 9 22 8 24 23 1 - -New column: 22 old column: 12 number of entries: 5 - new row indices: 18 21 8 23 1 - -New column: 23 old column: 22 number of entries: 8 - new row indices: 17 18 21 10 22 24 7 2 - -New column: 24 old column: 20 number of entries: 8 - new row indices: 17 19 21 10 16 20 7 23 - ------------------------------------------- -ordering the matrix with AMDBAR ------------------------------------------- - -Permutation vector: - 24 23 17 9 15 5 21 13 6 11 16 8 2 10 14 18 1 3 4 19 7 12 22 20 - -Inverse permutation vector: - 17 13 18 19 6 9 21 12 4 14 10 22 8 15 5 11 3 16 20 24 7 23 2 1 -Plot of permuted matrix pattern: - 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 - 1: X . . . . . . X . . . . . . . . . . . . X X . . - 2: . X . . . . X . . . . . . . . . . X . . . . X . - 3: . . X . . X . . . . X X . . . . . . . . . . . . - 4: . . . X X . . . . . . . X X . . . . . . . . . . - 5: . . . X X X . . . . . X X X . . . . . . . . . . - 6: . . X . X X . . . . X X . X . . . . . . . . . . - 7: . X . . . . X . . X . . . . . . . X . . . . X X - 8: X . . . . . . X X . . . . . . . X . . . X X . . - 9: . . . . . . . X X . . . . . X X X . . . X . . . - 10: . . . . . . X . . X . . . . . . . . X X . . X X - 11: . . X . . X . . . . X X . . . . . . X X . . . . - 12: . . X . X X . . . . X X . X . X . . X X . . . . - 13: . . . X X . . . . . . . X X X X . . . . . . . . - 14: . . . X X X . . . . . X X X X X . . . X . . . . - 15: . . . . . . . . X . . . X X X X X . . . . . . . - 16: . . . . . . . . X . . X X X X X X . . X . . . X - 17: . . . . . . . X X . . . . . X X X . . X X . X X - 18: . X . . . . X . . . . . . . . . . X . . X X X . - 19: . . . . . . . . . X X X . . . . . . X X . . . X - 20: . . . . . . . . . X X X . X . X X . X X . . . X - 21: X . . . . . . X X . . . . . . . X X . . X X X X - 22: X . . . . . . X . . . . . . . . . X . . X X X . - 23: . X . . . . X . . X . . . . . . X X . . X X X X - 24: . . . . . . X . . X . . . . . X X . X X X . X X - -New column: 1 old column: 24 number of entries: 3 - new row indices: 21 22 8 - -New column: 2 old column: 23 number of entries: 3 - new row indices: 18 7 23 - -New column: 3 old column: 17 number of entries: 3 - new row indices: 6 12 11 - -New column: 4 old column: 9 number of entries: 3 - new row indices: 13 14 5 - -New column: 5 old column: 15 number of entries: 5 - new row indices: 13 6 12 4 14 - -New column: 6 old column: 5 number of entries: 5 - new row indices: 12 14 5 11 3 - -New column: 7 old column: 21 number of entries: 5 - new row indices: 18 10 24 23 2 - -New column: 8 old column: 13 number of entries: 5 - new row indices: 17 9 21 22 1 - -New column: 9 old column: 6 number of entries: 5 - new row indices: 17 21 8 15 16 - -New column: 10 old column: 11 number of entries: 5 - new row indices: 19 20 24 7 23 - -New column: 11 old column: 16 number of entries: 5 - new row indices: 19 6 12 3 20 - -New column: 12 old column: 8 number of entries: 8 - new row indices: 19 6 14 5 11 3 16 20 - -New column: 13 old column: 2 number of entries: 5 - new row indices: 4 14 15 5 16 - -New column: 14 old column: 10 number of entries: 8 - new row indices: 13 6 12 4 15 5 16 20 - -New column: 15 old column: 14 number of entries: 5 - new row indices: 17 13 9 14 16 - -New column: 16 old column: 18 number of entries: 8 - new row indices: 17 13 9 12 14 15 20 24 - -New column: 17 old column: 1 number of entries: 8 - new row indices: 9 21 8 15 16 20 24 23 - -New column: 18 old column: 3 number of entries: 5 - new row indices: 21 22 7 23 2 - -New column: 19 old column: 4 number of entries: 5 - new row indices: 12 10 11 20 24 - -New column: 20 old column: 19 number of entries: 8 - new row indices: 17 19 12 14 10 11 16 24 - -New column: 21 old column: 7 number of entries: 8 - new row indices: 17 18 9 22 8 24 23 1 - -New column: 22 old column: 12 number of entries: 5 - new row indices: 18 21 8 23 1 - -New column: 23 old column: 22 number of entries: 8 - new row indices: 17 18 21 10 22 24 7 2 - -New column: 24 old column: 20 number of entries: 8 - new row indices: 17 19 21 10 16 20 7 23 diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Demo/amd_f77simple.f --- a/liboctave/UMFPACK/AMD/Demo/amd_f77simple.f Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -C ---------------------------------------------------------------------- -C AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. -C Davis, Patrick R. Amestoy, and Iain S. Duff. See ../README for -C License. email: davis@cise.ufl.edu CISE Department, Univ. of -C Florida. web: http://www.cise.ufl.edu/research/sparse/amd -C ---------------------------------------------------------------------- - -C This program provides an example of how to call the Fortran version -C of AMD. It uses the same matrix as the amd_simple.c demo (in C). -C Note that the diagonal entries are not present, and the matrix is -C symmetric. - - INTEGER N, NZ, J, K, P, IWLEN, PFREE, NCMPA - PARAMETER (N = 5, NZ = 10, IWLEN = 17) - INTEGER AP (N+1), AI (NZ), LAST (N), PE (N), LEN (N), ELEN (N), - $ IW (IWLEN), DEGREE (N), NV (N), NEXT (N), HEAD (N), W (N) - DATA AP / 1, 2, 5, 8, 9, 11/ - DATA AI / 2, 1,3,5, 2,4,5, 3, 2,3 / - -C load the matrix into the AMD workspace - DO 10 J = 1,N - PE (J) = AP (J) - LEN (J) = AP (J+1) - AP (J) -10 CONTINUE - DO 20 P = 1,NZ - IW (P) = AI (P) -20 CONTINUE - PFREE = NZ + 1 - -C order the matrix (destroys the copy of A in IW, PE, and LEN) - CALL AMD (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, LAST, HEAD, - $ ELEN, DEGREE, NCMPA, W) - - DO 60 K = 1, N - PRINT 50, K, LAST (K) -50 FORMAT ('P (',I2,') = ', I2) -60 CONTINUE - END diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Demo/amd_f77simple.out --- a/liboctave/UMFPACK/AMD/Demo/amd_f77simple.out Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -P ( 1) = 4 -P ( 2) = 1 -P ( 3) = 3 -P ( 4) = 5 -P ( 5) = 2 diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Demo/amd_f77wrapper.c --- a/liboctave/UMFPACK/AMD/Demo/amd_f77wrapper.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -/* ========================================================================= */ -/* === amd_f77wrapper ====================================================== */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* Fortran interface for the C-callable AMD library (int version only). This - * is HIGHLY non-portable. You will need to modify this depending on how your - * Fortran and C compilers behave. Two examples are provided. - * - * To avoid using I/O, and to avoid the extra porting step of a Fortran - * function, the status code is returned as the first entry in P (P [0] in C - * and P (1) in Fortran) if an error occurs. The error codes are negative - * (-1: out of memory, -2: invalid matrix). - * - * For some C and Fortran compilers, the Fortran compiler appends a single "_" - * after each routine name. C doesn't do this, so the translation is made - * here. Some Fortran compilers don't append an underscore (xlf on IBM AIX, - * for * example). - * - * Tested with the following compilers: - * Solaris with cc and f77 from Sun WorkShop 6 update 1. - * SGI Irix with MIPSpro cc and f77 compilers version 7.4 - * Linux with GNU gcc or Intel's icc, and GNU g77 Intel's ifc Fortran compiler. - * (any combination). Note that with g77, a call to amd_order in Fortran - * gets translated to a call to amd_order__, with two underscores ("_"). - * Thus, the Fortran names do not include an underscore. - */ - -#include "amd.h" -#include - -/* ------------------------------------------------------------------------- */ -/* Linux, Solaris, SGI */ -/* ------------------------------------------------------------------------- */ - -void amdorder_ (int *n, const int *Ap, const int *Ai, int *P, - double *Control, double *Info) -{ - int result = amd_order (*n, Ap, Ai, P, Control, Info) ; - if (result != AMD_OK && P) P [0] = result ; -} - -void amddefaults_ (double *Control) -{ - amd_defaults (Control) ; -} - -void amdcontrol_ (double *Control) -{ - fflush (stdout) ; - amd_control (Control) ; - fflush (stdout) ; -} - -void amdinfo_ (double *Info) -{ - fflush (stdout) ; - amd_info (Info) ; - fflush (stdout) ; -} - -void amdpreproc_ (int *n, const int *Ap, const int *Ai, int *Rp, int *Ri) -{ - int result = amd_preprocess (*n, Ap, Ai, Rp, Ri) ; - if (result != AMD_OK && Rp) Rp [0] = result ; -} - -/* ------------------------------------------------------------------------- */ -/* IBM AIX. Probably Windows, Compaq Alpha, and HP Unix as well. */ -/* ------------------------------------------------------------------------- */ - -void amdorder (int *n, const int *Ap, const int *Ai, int *P, - double *Control, double *Info) -{ - int result = amd_order (*n, Ap, Ai, P, Control, Info) ; - if (result != AMD_OK && P) P [0] = result ; -} - -void amddefaults (double *Control) -{ - amd_defaults (Control) ; -} - -void amdcontrol (double *Control) -{ - fflush (stdout) ; - amd_control (Control) ; - fflush (stdout) ; -} - -void amdinfo (double *Info) -{ - fflush (stdout) ; - amd_info (Info) ; - fflush (stdout) ; -} - -void amdpreproc (int *n, const int *Ap, const int *Ai, int *Rp, int *Ri) -{ - int result = amd_preprocess (*n, Ap, Ai, Rp, Ri) ; - if (result != AMD_OK && Rp) Rp [0] = result ; -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Demo/amd_simple.c --- a/liboctave/UMFPACK/AMD/Demo/amd_simple.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -#include -#include "amd.h" - -int n = 5 ; -int Ap [ ] = { 0, 2, 6, 10, 12, 14} ; -int Ai [ ] = { 0,1, 0,1,2,4, 1,2,3,4, 2,3, 1,4 } ; -int P [5] ; - -int main (void) -{ - int k ; - (void) amd_order (n, Ap, Ai, P, (double *) NULL, (double *) NULL) ; - for (k = 0 ; k < n ; k++) printf ("P [%d] = %d\n", k, P [k]) ; - return (0) ; -} - diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Demo/amd_simple.out --- a/liboctave/UMFPACK/AMD/Demo/amd_simple.out Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -P [0] = 0 -P [1] = 3 -P [2] = 2 -P [3] = 4 -P [4] = 1 diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Doc/AMD_UserGuide.bib --- a/liboctave/UMFPACK/AMD/Doc/AMD_UserGuide.bib Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -@string{SIREV = "{SIAM} Review"} -@string{SIMAX = "{SIAM} J. Matrix Anal. Applic."} -@string{SIAMJSC = "{SIAM} J. Sci. Comput."} -@string{TOMS = "{ACM} Trans. Math. Softw."} - -@article{schu:01, - author = {J. Schulze}, - title = {Towards a tighter coupling of bottom-up and top-down sparse matrix ordering methods}, - journal = {BIT}, - volume = {41}, - number = {4}, - pages = "800--841", - year = {2001} - } - -@article{GeorgeLiu89, - author={George, A. and Liu, J. W. H.}, - year={1989}, - title={The Evolution of the Minimum Degree Ordering Algorithm}, - journal=SIREV, - volume={31}, - number={1}, - pages={1--19}} - -@article{AmestoyDavisDuff96, - author={Amestoy, P. R. and Davis, T. A. and Duff, I. S.}, - title={An approximate minimum degree ordering algorithm}, - journal=SIMAX, - year={1996} - ,volume={17} - ,number={4} - ,pages={886-905} - } - -@misc{hsl:2002, - author = {HSL}, - title = "{HSL} 2002: {A} collection of {F}ortran codes for large - scale scientific computation", - note = {{\tt www.cse.clrc.ac.uk/nag/hsl}}, - year = 2002} - - -@article{RothbergEisenstat98, - author={Rothberg, E. and Eisenstat, S. C.}, - title={Node selection strategies for bottom-up sparse matrix orderings}, - journal=SIMAX, - year={1998} - ,volume={19} - ,number={3} - ,pages={682-695} - } - -@article{KarypisKumar98e, - author={Karypis, G. and Kumar, V.}, - title={A fast and high quality multilevel scheme for partitioning irregular graphs}, - journal=SIAMJSC, - year={1998} - ,volume={20} - ,pages={359-392} - } - -@article{Chaco, - author={B. Hendrickson and E. Rothberg}, - title={Improving the runtime and quality of nested dissection ordering}, - journal=SIAMJSC, - year={1999} - ,volume={20} - ,pages={468--489} - } - -@article{PellegriniRomanAmestoy00, - author={Pellegrini, F. and Roman, J. and Amestoy, P.}, - title={Hybridizing nested dissection and halo approximate minimum degree for efficient sparse matrix ordering}, - journal={Concurrency: Practice and Experience}, - year={2000} - ,volume={12} - ,pages={68-84} - } - -@article{DavisGilbertLarimoreNg00pending, - author={Davis, T. A. and Gilbert, J. R. and Larimore, S. I. and Ng, E. G.}, - title={A column approximate minimum degree ordering algorithm}, - journal=TOMS, - year={(to appear)} - } - diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Doc/AMD_UserGuide.pdf Binary file liboctave/UMFPACK/AMD/Doc/AMD_UserGuide.pdf has changed diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Doc/AMD_UserGuide.tex --- a/liboctave/UMFPACK/AMD/Doc/AMD_UserGuide.tex Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1138 +0,0 @@ -\documentclass[11pt]{article} - -\newcommand{\m}[1]{{\bf{#1}}} % for matrices and vectors -\newcommand{\tr}{^{\sf T}} % transpose - -\topmargin 0in -\textheight 9in -\oddsidemargin 0pt -\evensidemargin 0pt -\textwidth 6.5in - -%------------------------------------------------------------------------------ -\begin{document} -%------------------------------------------------------------------------------ - -\title{AMD Version 1.1 User Guide} -\author{Patrick R. Amestoy\thanks{ENSEEIHT-IRIT, -2 rue Camichel 31017 Toulouse, France. -email: amestoy@enseeiht.fr. http://www.enseeiht.fr/$\sim$amestoy.} -\and Timothy A. Davis\thanks{ -Dept.~of Computer and Information Science and Engineering, -Univ.~of Florida, Gainesville, FL, USA. -email: davis@cise.ufl.edu. -http://www.cise.ufl.edu/$\sim$davis. -This work was supported by the National -Science Foundation, under grants ASC-9111263, DMS-9223088, and CCR-0203270. -Portions of the work were done while on sabbatical at Stanford University -and Lawrence Berkeley National Laboratory (with funding from Stanford -University and the SciDAC program). -} -\and Iain S. Duff\thanks{Rutherford Appleton Laboratory, Chilton, Didcot, -Oxon OX11 0QX, England. email: i.s.duff@rl.ac.uk. -http://www.numerical.rl.ac.uk/people/isd/isd.html. -This work was supported by the EPSRC under grant GR/R46441. -}} - -\date{January 29, 2004} -\maketitle - -%------------------------------------------------------------------------------ -\begin{abstract} -AMD is a set of routines that implements the approximate minimum degree ordering -algorithm to permute sparse matrices prior to -numerical factorization. -There are versions written in both C and Fortran 77. -A MATLAB interface is included. -\end{abstract} -%------------------------------------------------------------------------------ - -Technical report TR-04-002, CISE Department, University of Florida, -Gainesville, FL, 2004. - -AMD Version 1.1 (Jan. 21, 2004), Copyright\copyright 2004 by Timothy A. -Davis, Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. - -{\bf AMD License:} - Your use or distribution of AMD or any modified version of - AMD implies that you agree to this License. - - 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 or copy this program, 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 AMD or any modified version of AMD 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. This - software was developed with support from the National Science Foundation, - and is provided to you free of charge. - -{\bf Availability:} - http://www.cise.ufl.edu/research/sparse/amd - -{\bf Acknowledgments:} - - This work was supported by the National Science Foundation, under - grants ASC-9111263 and DMS-9223088 and CCR-0203270. - The conversion to C, the addition of the elimination tree - post-ordering, and the handling of dense rows and columns - were done while Davis was on sabbatical at - Stanford University and Lawrence Berkeley National Laboratory. - -%------------------------------------------------------------------------------ -\newpage -\section{Overview} -%------------------------------------------------------------------------------ - -AMD is a set of routines for preordering a sparse matrix prior to -numerical factorization. It uses an approximate minimum degree ordering -algorithm \cite{AmestoyDavisDuff96} to find a permutation matrix $\m{P}$ -so that the Cholesky factorization $\m{PAP}\tr=\m{LL}\tr$ has fewer -(often much fewer) nonzero entries than the Cholesky factorization of $\m{A}$. -The algorithm is typically much faster than other ordering methods -and minimum degree ordering -algorithms that compute an exact degree \cite{GeorgeLiu89}. -Some methods, such as approximate deficiency -\cite{RothbergEisenstat98} and graph-partitioning based methods -\cite{Chaco,KarypisKumar98e,PellegriniRomanAmestoy00,schu:01} -can produce better orderings, depending on the matrix. - -The algorithm starts with an undirected graph representation of a -symmetric sparse matrix $\m{A}$. Node $i$ in the graph corresponds to row -and column $i$ of the matrix, and there is an edge $(i,j)$ in the graph if -$a_{ij}$ is nonzero. -The degree of a node is initialized to the number of off-diagonal nonzeros -in row $i$, which is the size of the set of nodes -adjacent to $i$ in the graph. - -The selection of a pivot $a_{ii}$ from the diagonal of $\m{A}$ and the first -step of Gaussian elimination corresponds to one step of graph elimination. -Numerical fill-in causes new nonzero entries in the matrix -(fill-in refers to -nonzeros in $\m{L}$ that are not in $\m{A}$). -Node $i$ is eliminated and edges are added to its neighbors -so that they form a clique (or {\em element}). To reduce fill-in, -node $i$ is selected as the node of least degree in the graph. -This process repeats until the graph is eliminated. - -The clique is represented implicitly. Rather than listing all the -new edges in the graph, a single list of nodes is kept which represents -the clique. This list corresponds to the nonzero pattern of the first -column of $\m{L}$. As the elimination proceeds, some of these cliques -become subsets of subsequent cliques, and are removed. This graph -can be stored in place, that is -using the same amount of memory as the original graph. - -The most costly part of the minimum degree algorithm is the recomputation -of the degrees of nodes adjacent to the current pivot element. -Rather than keep track of the exact degree, the approximate minimum degree -algorithm finds an upper bound on the degree that is easier to compute. -For nodes of least degree, this bound tends to be tight. Using the -approximate degree instead of the exact degree leads to a substantial savings -in run time, particularly for very irregularly structured matrices. -It has no effect on the quality of the ordering. - -In the C version of AMD, the elimination phase is followed by an -elimination tree post-ordering. This has no effect on fill-in, but -reorganizes the ordering so that the subsequent numerical factorization is -more efficient. It also includes a pre-processing phase in which nodes of -very high degree are removed (without causing fill-in), and placed last in the -permutation $\m{P}$. This reduces the run time substantially if the matrix -has a few rows with many nonzero entries, and has little effect on the quality -of the ordering. -The C version operates on the -symmetric nonzero pattern of $\m{A}+\m{A}\tr$, so it can be given -an unsymmetric matrix, or either the lower or upper triangular part of -a symmetric matrix. - -The two Fortran versions of AMD are essentially identical to two versions of -the AMD algorithm discussed in an earlier paper \cite{AmestoyDavisDuff96} -(approximate minimum external degree, both with and without aggressive -absorption). -For a discussion of the long history of the minimum degree algorithm, -see \cite{GeorgeLiu89}. - -%------------------------------------------------------------------------------ -\section{Availability} -%------------------------------------------------------------------------------ - -In addition to appearing as a Collected Algorithm of the ACM, -AMD Version 1.1 is available at http://www.cise.ufl.edu/research/sparse. -The Fortran version is available as the routine {\tt MC47} in HSL -(formerly the Harwell Subroutine Library) \cite{hsl:2002}. - -%------------------------------------------------------------------------------ -\section{Using AMD in MATLAB} -%------------------------------------------------------------------------------ - -To use AMD in MATLAB, you must first compile the AMD mexFunction. -Just type {\tt make} in the Unix system shell, while in the {\tt AMD} -directory. You can also type {\tt amd\_make} in MATLAB, while in the -{\tt AMD/MATLAB} directory. Place the {\tt AMD/MATLAB} directory in your -MATLAB path. This can be done on any system with MATLAB, including Windows. -See Section~\ref{Install} for more details on how to install AMD. - -The MATLAB statement {\tt p=amd(A)} finds a permutation vector {\tt p} such -that the Cholesky factorization {\tt chol(A(p,p))} is typically sparser than -{\tt chol(A)}. -If {\tt A} is unsymmetric, {\tt amd(A)} is identical to {\tt amd(A+A')} -(ignoring numerical cancellation). -If {\tt A} is not symmetric positive definite, -but has substantial diagonal entries and a mostly symmetric nonzero pattern, -then this ordering is also suitable for LU factorization. A partial pivoting -threshold may be required to prevent pivots from being selected off the -diagonal, such as the statement {\tt [L,U,P] = lu (A (p,p), 0.1)}. -Type {\tt help lu} for more details. -The statement {\tt [L,U,P,Q] = lu (A (p,p))} in MATLAB 6.5 is -not suitable, however, because it uses UMFPACK Version 4.0 and thus -does not attempt to select pivots from the diagonal. UMFPACK Version 4.1 -uses several strategies, including a symmetric pivoting strategy, and -will give you better results if you want to factorize an unsymmetric matrix -of this type. Refer to the UMFPACK User Guide for more details, at -http://www.cise.ufl.edu/research/sparse/umfpack. - -The AMD mexFunction is much faster than the built-in MATLAB symmetric minimum -degree ordering methods, SYMAMD and SYMMMD. Its ordering quality is -comparable to SYMAMD, and better than SYMMMD -\cite{DavisGilbertLarimoreNg00pending}. - -An optional input argument can be used to modify the control parameters for -AMD (aggressive absorption, dense row/column handling, and printing of -statistics). An optional output -argument provides statistics on the ordering, including an analysis of the -fill-in and the floating-point operation count for a subsequent factorization. -For more details (once AMD is installed), -type {\tt help amd} in the MATLAB command window. - -%------------------------------------------------------------------------------ -\section{Using AMD in a C program} -\label{Cversion} -%------------------------------------------------------------------------------ - -The C-callable AMD library consists of five user-callable routines and one -include file. There are two versions of each of the routines, with -{\tt int} and {\tt long} integers. -The routines with prefix -{\tt amd\_l\_} use {\tt long} integer arguments; the others use -{\tt int} integer arguments. If you compile AMD in the standard -ILP32 mode (32-bit {\tt int}'s, {\tt long}'s, and pointers) then the versions -are essentially identical. You will be able to solve problems using up to 2GB -of memory. If you compile AMD in the standard LP64 mode, the size of an -{\tt int} remains 32-bits, but the size of a {\tt long} and a pointer both get -promoted to 64-bits. - -The following routines are fully described in Section~\ref{Primary}: - -\begin{itemize} -\item {\tt amd\_order} -({\tt long} version: {\tt amd\_l\_order}) - {\footnotesize - \begin{verbatim} - #include "amd.h" - int n, Ap [n+1], Ai [nz], P [n] ; - double Control [AMD_CONTROL], Info [AMD_INFO] ; - int result = amd_order (n, Ap, Ai, P, Control, Info) ; - \end{verbatim} - } - Computes the approximate minimum degree ordering of an $n$-by-$n$ matrix - $\m{A}$. Returns a permutation vector {\tt P} of size {\tt n}, where - {\tt P[k] = i} if row and column {\tt i} are the {\tt k}th row and - column in the permuted matrix. - This routine allocates its own memory of size $1.2e+9n$ integers, - where $e$ is the number of nonzeros in $\m{A}+\m{A}\tr$. - It computes statistics about the matrix $\m{A}$, such as the symmetry of - its nonzero pattern, the number of nonzeros in $\m{L}$, - and the number of floating-point operations required for Cholesky and LU - factorizations (which are returned in the {\tt Info} array). - The user's input matrix is not modified. - It returns {\tt AMD\_OK} if successful, {\tt AMD\_INVALID} if - the matrix is invalid, or {\tt AMD\_OUT\_OF\_MEMORY} if out of memory. - -\item {\tt amd\_defaults} -({\tt long} version: {\tt amd\_l\_defaults}) - {\footnotesize - \begin{verbatim} - #include "amd.h" - double Control [AMD_CONTROL] ; - amd_defaults (Control) ; - \end{verbatim} - } - Sets the default control parameters in the {\tt Control} array. These can - then be modified as desired before passing the array to the other AMD - routines. - -\item {\tt amd\_control} -({\tt long} version: {\tt amd\_l\_control}) - {\footnotesize - \begin{verbatim} - #include "amd.h" - double Control [AMD_CONTROL] ; - amd_control (Control) ; - \end{verbatim} - } - Prints a description of the control parameters, and their values. - -\item {\tt amd\_info} -({\tt long} version: {\tt amd\_l\_info}) - {\footnotesize - \begin{verbatim} - #include "amd.h" - double Info [AMD_INFO] ; - amd_info (Info) ; - \end{verbatim} - } - Prints a description of the statistics computed by AMD, and their values. - -\item {\tt amd\_preprocess} -({\tt long} version: {\tt amd\_l\_info}) - {\footnotesize - \begin{verbatim} - #include "amd.h" - int n, Ap [n+1], Ai [nz], Rp [n+1], Ri [nz] ; - int result = amd_preprocess (n, Ap, Ai, Rp, Ri) ; - \end{verbatim} - } - Removes duplicate entries and sorts each column of its input $\m{A}$, - and returns the nonzero pattern of the transpose, $\m{R}=\m{A}\tr$. - It returns the transpose because this is the simplest way to sort - a matrix and remove duplicate entries. Either $\m{A}$ or $\m{A}\tr$ - can be passed to {\tt amd\_order} with little effect on the - ordering (except for minor tie-breaking changes). - -\end{itemize} - -The nonzero pattern of the matrix $\m{A}$ is represented in compressed column -form. -For an $n$-by-$n$ matrix $\m{A}$ with {\tt nz} nonzero entries, the -representation consists of two arrays: {\tt Ap} of size {\tt n+1} and {\tt Ai} -of size {\tt nz}. The row indices of entries in column {\tt j} are stored in - {\tt Ai[Ap[j]} $\ldots$ {\tt Ap[j+1]-1]}. -For {\tt amd\_order}, -no duplicate row indices may be present, and the row indices in any given -column must be sorted in ascending order. -The matrix is 0-based, and thus -row indices must be in the range {\tt 0} to {\tt n-1}. -The first entry {\tt Ap[0]} must be zero. -The total number of entries in the matrix is thus {\tt nz = Ap[n]}. - -The matrix must be square, but it does not need to be symmetric. -The {\tt amd\_order} routine constructs the nonzero pattern of -$\m{B} = \m{A}+\m{A}\tr$ (without forming $\m{A}\tr$ explicitly), -and then orders the matrix $\m{B}$. Thus, either the -lower triangular part of $\m{A}$, the upper triangular part, -or any combination may be passed. The transpose $\m{A}\tr$ may also be -passed to {\tt amd\_order}. -The diagonal entries may be present, but are ignored. - -The input to {\tt amd\_order} must have sorted columns because it uses -an in-place algorithm to construct $\m{A}+\m{A}\tr$ without first constructing -$\m{A}\tr$. This saves memory, but places an additional restriction on -the input. If the input matrix has columns with unsorted and/or duplicate -row indices, it is not valid as input to {\tt amd\_order}. To handle this -case, the {\tt amd\_preprocess} routine is provided. It sorts, transposes, -and removes duplicate entries from its input matrix, returning its result -as another compressed-column matrix $\m{R}$ which can then be passed to -{\tt amd\_order}. - -%------------------------------------------------------------------------------ -\subsection{Control parameters} -\label{control_param} -%------------------------------------------------------------------------------ - -Control parameters are set an optional {\tt Control} array. -It is optional in the sense that if -a {\tt NULL} pointer is passed for the {\tt Control} input argument, -then default control parameters are used. -% -\begin{itemize} -\item {\tt Control[AMD\_DENSE]} (or {\tt Control(1)} in MATLAB): -controls the threshold for ``dense'' -rows/columns. A dense row/column in $\m{A}+\m{A}\tr$ -can cause AMD to spend significant time -in ordering the matrix. If {\tt Control[AMD\_DENSE]} $\ge 0$, -rows/columns with -more than {\tt Control[AMD\_DENSE]} $\sqrt{n}$ entries are ignored during -the ordering, and placed last in the output order. The default -value of {\tt Control[AMD\_DENSE]} is 10. If negative, no rows/columns -are treated as ``dense.'' Rows/columns with 16 or fewer off-diagonal -entries are never considered ``dense.'' -% -\item {\tt Control[AMD\_AGGRESSIVE]} (or {\tt Control(2)} in MATLAB): -controls whether or not to use -aggressive absorption, in which a prior element is absorbed into the current -element if it is a subset of the current element, even if it is not -adjacent to the current pivot element (refer to \cite{AmestoyDavisDuff96} -for more details). The default value is nonzero, -which means that aggressive absorption will be performed. This nearly always -leads to a better ordering (because the approximate degrees are more -accurate) and a lower execution time. There are cases where it can -lead to a slightly worse ordering, however. To turn it off, set -{\tt Control[AMD\_AGGRESSIVE]} to 0. -% -\end{itemize} - -Statistics are returned in the {\tt Info} array -(if {\tt Info} is {\tt NULL}, then no statistics are returned). -Refer to {\tt amd.h} file, for more details -(14 different statistics are returned, so the list is not included here). - -%------------------------------------------------------------------------------ -\subsection{Sample C program} -%------------------------------------------------------------------------------ - -The following program, {\tt amd\_demo.c}, illustrates the basic use of AMD. -See Section~\ref{Synopsis} for a short description -of each calling sequence. - -{\footnotesize -\begin{verbatim} -#include -#include "amd.h" - -int n = 5 ; -int Ap [ ] = { 0, 2, 6, 10, 12, 14} ; -int Ai [ ] = { 0,1, 0,1,2,4, 1,2,3,4, 2,3, 1,4 } ; -int P [5] ; - -int main (void) -{ - int k ; - (void) amd_order (n, Ap, Ai, P, (double *) NULL, (double *) NULL) ; - for (k = 0 ; k < n ; k++) printf ("P [%d] = %d\n", k, P [k]) ; - return (0) ; -} -\end{verbatim} -} - -The {\tt Ap} and {\tt Ai} arrays represent the binary matrix -\[ -\m{A} = \left[ -\begin{array}{rrrrr} - 1 & 1 & 0 & 0 & 0 \\ - 1 & 1 & 1 & 0 & 1 \\ - 0 & 1 & 1 & 1 & 0 \\ - 0 & 0 & 1 & 1 & 0 \\ - 0 & 1 & 1 & 0 & 1 \\ -\end{array} -\right]. -\] -The diagonal entries are ignored. -% -AMD constructs the pattern of $\m{A}+\m{A}\tr$, -and returns a permutation vector of $(0, 3, 1, 4, 2)$. -% -Since the matrix is unsymmetric but with a mostly symmetric nonzero -pattern, this would be a suitable permutation for an LU factorization of a -matrix with this nonzero pattern and whose diagonal entries are not too small. -The program uses default control settings and does not return any statistics -about the ordering, factorization, or solution ({\tt Control} and {\tt Info} -are both {\tt (double *) NULL}). It also ignores the status value returned by -{\tt amd\_order}. - -More example programs are included with the AMD package. -The {\tt amd\_demo.c} program provides a more detailed demo of AMD. -Another example is the AMD mexFunction, {\tt amd\_mex.c}. - -%------------------------------------------------------------------------------ -\subsection{A note about zero-sized arrays} -%------------------------------------------------------------------------------ - -AMD uses several user-provided arrays of size {\tt n} or {\tt nz}. -Either {\tt n} or {\tt nz} can be zero. -If you attempt to {\tt malloc} an array of size zero, -however, {\tt malloc} will return a null pointer which AMD will report -as invalid. If you {\tt malloc} an array of -size {\tt n} or {\tt nz} to pass to AMD, make sure that you handle the -{\tt n} = 0 and {\tt nz = 0} cases correctly. - -%------------------------------------------------------------------------------ -\section{Synopsis of C-callable routines} -\label{Synopsis} -%------------------------------------------------------------------------------ - -The matrix $\m{A}$ is {\tt n}-by-{\tt n} with {\tt nz} entries. - -{\footnotesize -\begin{verbatim} -#include "amd.h" -int n, status, Ap [n+1], Ai [nz], P [n], Rp [n+1], Ri [nz] ; -double Control [AMD_CONTROL], Info [AMD_INFO] ; -amd_defaults (Control) ; -status = amd_order (n, Ap, Ai, P, Control, Info) ; -amd_control (Control) ; -amd_info (Info) ; -amd_preprocess (n, Ap, Ai, Rp, Ri) ; -\end{verbatim} -} - -The {\tt amd\_l\_*} routines are identical, except that all {\tt int} -arguments become {\tt long}: - -{\footnotesize -\begin{verbatim} -#include "amd.h" -long n, status, Ap [n+1], Ai [nz], P [n], Rp [n+1], Ri [nz] ; -double Control [AMD_CONTROL], Info [AMD_INFO] ; -amd_l_defaults (Control) ; -status = amd_l_order (n, Ap, Ai, P, Control, Info) ; -amd_l_control (Control) ; -amd_l_info (Info) ; -amd_l_preprocess (n, Ap, Ai, Rp, Ri) ; -\end{verbatim} -} - -%------------------------------------------------------------------------------ -\section{Using AMD in a Fortran program} -%------------------------------------------------------------------------------ - -Two Fortran versions of AMD are provided. The {\tt AMD} routine computes the -approximate minimum degree ordering, using aggressive absorption. The -{\tt AMDBAR} routine is identical, except that it does not perform aggressive -absorption. The {\tt AMD} routine is essentially identical to the HSL -routine {\tt MC47B/BD}. -Note that earlier versions of the Fortran -{\tt AMD} and {\tt AMDBAR} routines included an {\tt IOVFLO} argument, -which is no longer present. - -In contrast to the C version, the Fortran routines require a symmetric -nonzero pattern, with no diagonal entries present although the {\tt MC47A/AD} -wrapper in HSL allows duplicates, ignores out-of-range entries, and only -uses entries from the upper triangular part of the matrix. Although we -have an experimental Fortran code for treating ``dense'' rows, the Fortran -codes in this release do not treat -``dense'' rows and columns of $\m{A}$ differently, and thus their run time -can be high if there are a few dense rows and columns in the matrix. -They do not perform a post-ordering of the elimination tree, -compute statistics on the ordering, or check the validity of their input -arguments. These facilities are provided by {\tt MC47A/AD} and other -subroutines from HSL. -Only one {\tt integer} -version of each Fortran routine is provided. -Both Fortran routines overwrite the user's input -matrix, in contrast to the C version. -% -The C version does not return the elimination or assembly tree. -The Fortran version returns an assembly tree; -refer to the User Guide for details. -The following is the syntax of the {\tt AMD} Fortran routine. -The {\tt AMDBAR} routine is identical except for the routine name. - -{\footnotesize -\begin{verbatim} - INTEGER N, IWLEN, PFREE, NCMPA, IW (IWLEN), PE (N), DEGREE (N), NV (N), - $ NEXT (N), LAST (N), HEAD (N), ELEN (N), W (N), LEN (N) - CALL AMD (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, - $ LAST, HEAD, ELEN, DEGREE, NCMPA, W) - CALL AMDBAR (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, - $ LAST, HEAD, ELEN, DEGREE, NCMPA, W) -\end{verbatim} -} - -The input matrix is provided to {\tt AMD} and {\tt AMDBAR} -in three arrays, {\tt PE}, of size {\tt N}, -{\tt LEN}, of size {\tt N}, and {\tt IW}, of size {\tt IWLEN}. The size of -{\tt IW} must be at least {\tt NZ+N}. The recommended size is -{\tt 1.2*NZ + N}. -On input, the indices of nonzero entries in row {\tt I} are stored in {\tt IW}. -{\tt PE(I)} is the index in {\tt IW} of the start of row {\tt I}. -{\tt LEN(I)} is the number of entries in row {\tt I}. -The matrix is 1-based, with row and column indices in the range 1 to {\tt N}. -Row {\tt I} is contained in -{\tt IW (PE(I)} $\ldots \:$ {\tt PE(I) + LEN(I) - 1)}. -The diagonal entries must not be present. The indices within each row must -not contain any duplicates, but they need not be sorted. The rows -themselves need not be in any particular order, and there may be empty space -between the rows. If {\tt LEN(I)} is zero, then there are no off-diagonal -entries in row {\tt I}, and {\tt PE(I)} is ignored. The integer -{\tt PFREE} defines what part of {\tt IW} contains the user's input matrix, -which is held in {\tt IW(1}~$\ldots~\:${\tt PFREE-1)}. -The contents of {\tt IW} and {\tt LEN} are undefined on output, -and {\tt PE} is modified to contain information about the ordering. - -As the algorithm proceeds, it modifies the {\tt IW} array, placing the -pattern of the partially eliminated matrix in -{\tt IW(PFREE} $\ldots \:${\tt IWLEN)}. -If this space is exhausted, the space is compressed. -The number of compressions performed on the {\tt IW} array is -returned in the scalar {\tt NCMPA}. The value of {\tt PFREE} on output is the -length of {\tt IW} required for no compressions to be needed. - -The output permutation is returned in the array {\tt LAST}, of size {\tt N}. -If {\tt I=LAST(K)}, then {\tt I} is the {\tt K}th row in the permuted -matrix. The inverse permutation is returned in the array {\tt ELEN}, where -{\tt K=ELEN(I)} if {\tt I} is the {\tt K}th row in the permuted matrix. -On output, the {\tt PE} and {\tt NV} arrays hold the assembly tree, -a supernodal elimination tree that represents the relationship between -columns of the Cholesky factor $\m{L}$. -If {\tt NV(I)} $> 0$, then {\tt I} is a node in the assembly -tree, and the parent of {\tt I} is {\tt -PE(I)}. If {\tt I} is a root of -the tree, then {\tt PE(I)} is zero. The value of {\tt NV(I)} is the -number of entries in the corresponding column of $\m{L}$, including the -diagonal. -If {\tt NV(I)} is zero, then {\tt I} is a non-principal node that is -not in the assembly tree. Node {\tt -PE(I)} is the parent of node {\tt I} -in a subtree, the root of which is a node in the assembly tree. All nodes -in one subtree belong to the same supernode in the assembly tree. -The other size {\tt N} arrays -({\tt DEGREE}, {\tt HEAD}, {\tt NEXT}, and {\tt W}) are used as workspace, -and are not defined on input or output. - -If you want to use a simpler user-interface and compute the elimination -tree post-ordering, you should be able to call the C routines {\tt amd\_order} -or {\tt amd\_l\_order} from a Fortran program. Just be sure to take into -account the 0-based indexing in the {\tt P}, {\tt Ap}, and {\tt Ai} arguments -to {\tt amd\_order} and {\tt amd\_l\_order}. A sample interface is provided -in the files {\tt AMD/Demo/amd\_f77cross.f} and -{\tt AMD/Demo/amd\_f77wrapper.c}. To compile the {\tt amd\_f77cross} program, -type {\tt make cross} in the {\tt AMD/Demo} directory. The -Fortran-to-C calling conventions are highly non-portable, so this example -is not guaranteed to work with your compiler C and Fortran compilers. -The output of {\tt amd\_f77cross} is in {\tt amd\_f77cross.out}. - -%------------------------------------------------------------------------------ -\section{Sample Fortran main program} -%------------------------------------------------------------------------------ - -The following program illustrates the basic usage of the Fortran version of AMD. -The {\tt AP} and {\tt AI} arrays represent the binary matrix -\[ -\m{A} = \left[ -\begin{array}{rrrrr} - 1 & 1 & 0 & 0 & 0 \\ - 1 & 1 & 1 & 0 & 1 \\ - 0 & 1 & 1 & 1 & 1 \\ - 0 & 0 & 1 & 1 & 0 \\ - 0 & 1 & 1 & 0 & 1 \\ -\end{array} -\right] -\] -in a conventional 1-based column-oriented form, -except that the diagonal entries are not present. -The matrix has the same as nonzero pattern of $\m{A}+\m{A}\tr$ in the C -program, in Section~\ref{Cversion}. -The output permutation is $(4, 1, 3, 5, 2)$. -It differs from the permutation returned by the C routine {\tt amd\_order} -because a post-order of the elimination tree has not yet been performed. - -{\footnotesize -\begin{verbatim} - INTEGER N, NZ, J, K, P, IWLEN, PFREE, NCMPA - PARAMETER (N = 5, NZ = 10, IWLEN = 17) - INTEGER AP (N+1), AI (NZ), LAST (N), PE (N), LEN (N), ELEN (N), - $ IW (IWLEN), DEGREE (N), NV (N), NEXT (N), HEAD (N), W (N) - DATA AP / 1, 2, 5, 8, 9, 11/ - DATA AI / 2, 1,3,5, 2,4,5, 3, 2,3 / -C load the matrix into the AMD workspace - DO 10 J = 1,N - PE (J) = AP (J) - LEN (J) = AP (J+1) - AP (J) -10 CONTINUE - DO 20 P = 1,NZ - IW (P) = AI (P) -20 CONTINUE - PFREE = NZ + 1 -C order the matrix (destroys the copy of A in IW, PE, and LEN) - CALL AMD (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, LAST, HEAD, - $ ELEN, DEGREE, NCMPA, W) - DO 60 K = 1, N - PRINT 50, K, LAST (K) -50 FORMAT ('P (',I2,') = ', I2) -60 CONTINUE - END -\end{verbatim} -} - -The {\tt Demo} directory contains an example of how the C version -may be called from a Fortran program, but this is highly non-portable. -For this reason, it is placed in the {\tt Demo} directory, not in the -primary {\tt Source} directory. - -%------------------------------------------------------------------------------ -\section{Installation} -\label{Install} -%------------------------------------------------------------------------------ - -The following discussion assumes you have the {\tt make} program, either in -Unix, or in Windows with Cygwin. - -System-dependent configurations are in the {\tt AMD/Make} -directory. You can edit the {\tt Make.include} -file in that directory to customize the compilation. The default -settings will work on most systems. -Sample configuration files are provided -for Linux, Sun Solaris, SGI IRIX, IBM AIX, and the DEC/Compaq Alpha. - -To compile and install the C-callable AMD library, -go to the {\tt AMD} directory and type {\tt make}. -The library will be placed in {\tt AMD/Lib/libamd.a}. -Two demo programs of the AMD ordering routine will be compiled and tested in -the {\tt AMD/Demo} directory. -The outputs of these demo programs will then be compared with output -files in the distribution. The AMD mexFunction for -use in MATLAB will also be compiled. If you do not have MATLAB -type {\tt make lib} instead. - -To compile and install the Fortran-callable AMD library, -go to the {\tt AMD} directory and type {\tt make fortran}. -The library will be placed in {\tt AMD/Lib/libamdf77.a}. -A demo program will be compiled and tested in the {\tt AMD/Demo} directory. -The output will be compared with an output file in the distribution. - -Typing {\tt make clean} will remove all but the final compiled libraries -and demo programs. Typing {\tt make purge} removes all files not in the -original distribution. -If you compile AMD and then later change the {\tt Make.include} -file or your system-specific configuration file such as {\tt Make.linux}, -then you should type {\tt make purge} and then {\tt make} to recompile. - -Here are the various parameters that you can control in your -{\tt Make.include} file: - -\begin{itemize} -\item {\tt CC = } your C compiler, such as {\tt cc}. -\item {\tt RANLIB = } your system's {\tt ranlib} program, if needed. -\item {\tt CFLAGS = } optimization flags, such as {\tt -O}. -\item {\tt LIB = } your libraries, such as {\tt -lm} or {\tt -lblas}. -\item {\tt RM =} the command to delete a file. -\item {\tt MV =} the command to rename a file. -\item {\tt MEX =} the command to compile a MATLAB mexFunction. -\item {\tt F77 =} the command to compile a Fortran program (optional). -\item {\tt F77FLAGS =} the Fortran compiler flags (optional). -\item {\tt F77LIB =} the Fortran libraries (optional). -\end{itemize} - -The {\tt Make.include} includes some definitions regarding the BLAS. -This is so that AMD and UMFPACK (which requires AMD) can share -the same configuration files. If you wish to use AMD only, then -you can ignore any references to the BLAS (the -DNBLAS compile flag). - -When you compile your program that uses the C-callable AMD library, -you need to add the {\tt AMD/Lib/libamd.a} library -and you need to tell your compiler to look in the -{\tt AMD/Include} directory for include -files. To compile a Fortran program that calls the Fortran AMD library, -you need to add the {\tt AMD/Lib/libamdf77.a} library. -See {\tt AMD/Demo/Makefile} for an example. - -If all you want to use is the AMD mexFunction in MATLAB, you can skip -the use of the {\tt make} command entirely. Simply type -{\tt amd\_make} in MATLAB while in the {\tt AMD/MATLAB} directory. -This works on any system with MATLAB, including Windows. - -If you are including AMD as a subset of a larger library and do not want -to link the C standard I/O library, or if you simply do not need to use -them, you can safely remove the {\tt amd\_control.c} and {\tt amd\_info.c} -files. Similarly, if you use default parameters (or define your -own {\tt Control} array), then you can exclude the {\tt amd\_defaults.c} -file. The {\tt amd\_preprocess.c} file is optional as well, if you -can ensure that the input matrix to {\tt amd\_order} is always sorted -and has no duplicate entries. -Each of these files contains the user-callable routines of the same -name. None of these auxiliary routines are directly called by -{\tt amd\_order}. -The {\tt amd\_dump.c} file contains debugging routines -that are neither used nor compiled unless debugging is enabled. -The {\tt amd\_internal.h} file must be edited to enable debugging; -refer to the instructions in that file. Thus, it too can be excluded -if compiled into a larger production program or library. -The bare minimum files required to use just {\tt amd\_order} are -{\tt amd.h} in the {\tt Include} directory, -and -{\tt amd\_1.c}, -{\tt amd\_2.c}, -{\tt amd\_aat.c}, -{\tt and\_order.c}, -{\tt amd\_postorder.c}, -{\tt amd\_post\_tree.c}, -{\tt amd\_valid.c}, -and -{\tt amd\_internal.h}, -in the {\tt Source} directory. - -%------------------------------------------------------------------------------ -\newpage -\section{The AMD routines} -\label{Primary} -%------------------------------------------------------------------------------ - -The file {\tt AMD/Include/amd.h} listed below -describes each user-callable routine in the C version of AMD, -and gives details on their use. - -{\footnotesize -\begin{verbatim} -/* ========================================================================= */ -/* === AMD: approximate minimum degree ordering =========================== */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* AMD finds a symmetric ordering P of a matrix A so that the Cholesky - * factorization of P*A*P' has fewer nonzeros and takes less work than the - * Cholesky factorization of A. If A is not symmetric, then it performs its - * ordering on the matrix A+A'. Two sets of user-callable routines are - * provided, one for "int" integers and the other for "long" integers. - * - * The method is based on the approximate minimum degree algorithm, discussed - * in Amestoy, Davis, and Duff, "An approximate degree ordering algorithm", - * SIAM Journal of Matrix Analysis and Applications, vol. 17, no. 4, pp. - * 886-905, 1996. This package can perform both the AMD ordering (with - * aggressive absorption), and the AMDBAR ordering (without aggressive - * absorption) discussed in the above paper. This package differs from the - * Fortran codes discussed in the paper: - * - * (1) it can ignore "dense" rows and columns, leading to faster run times - * (2) it computes the ordering of A+A' if A is not symmetric - * (3) it is followed by a depth-first post-ordering of the assembly tree - * (or supernodal elimination tree) - * - * For historical reasons, the Fortran versions, amd.f and amdbar.f, have - * been left (nearly) unchanged. They compute the identical ordering as - * described in the above paper. - */ - -#ifndef AMD_H -#define AMD_H - -int amd_order ( /* returns 0 if OK, negative value if error */ - int n, /* A is n-by-n. n must be >= 0. */ - const int Ap [ ], /* column pointers for A, of size n+1 */ - const int Ai [ ], /* row indices of A, of size nz = Ap [n] */ - int P [ ], /* output permutation, of size n */ - double Control [ ], /* input Control settings, of size AMD_CONTROL */ - double Info [ ] /* output Info statistics, of size AMD_INFO */ -) ; - -long amd_l_order ( /* see above for description of arguments */ - long n, - const long Ap [ ], - const long Ai [ ], - long P [ ], - double Control [ ], - double Info [ ] -) ; - -/* Input arguments (not modified): - * - * n: the matrix A is n-by-n. - * Ap: an int/long array of size n+1, containing the column pointers of A. - * Ai: an int/long array of size nz, containing the row indices of A, - * where nz = Ap [n]. - * Control: a double array of size AMD_CONTROL, containing control - * parameters. Defaults are used if Control is NULL. - * - * Output arguments (not defined on input): - * - * P: an int/long array of size n, containing the output permutation. If - * row i is the kth pivot row, then P [k] = i. In MATLAB notation, - * the reordered matrix is A (P,P). - * Info: a double array of size AMD_INFO, containing statistical - * information. Ignored if Info is NULL. - * - * On input, the matrix A is stored in column-oriented form. The row indices - * of nonzero entries in column j are stored in Ai [Ap [j] ... Ap [j+1]-1]. - * The row indices must appear in ascending order in each column, and there - * must not be any duplicate entries. Row indices must be in the range 0 to - * n-1. Ap [0] must be zero, and thus nz = Ap [n] is the number of nonzeros - * in A. The array Ap is of size n+1, and the array Ai is of size nz = Ap [n]. - * The matrix does not need to be symmetric, and the diagonal does not need to - * be present (if diagonal entries are present, they are ignored except for - * the output statistic Info [AMD_NZDIAG]). The arrays Ai and Ap are not - * modified. This form of the Ap and Ai arrays to represent the nonzero - * pattern of the matrix A is the same as that used internally by MATLAB. - * If you wish to use a more flexible input structure, please see the - * umfpack_*_triplet_to_col routines in the UMFPACK package, at - * http://www.cise.ufl.edu/research/sparse/umfpack, or use the amd_preprocess - * routine discussed below. - * - * Restrictions: n >= 0. Ap [0] = 0. Ap [j] <= Ap [j+1] for all j in the - * range 0 to n-1. nz = Ap [n] >= 0. For all j in the range 0 to n-1, - * and for all p in the range Ap [j] to Ap [j+1]-2, Ai [p] < Ai [p+1] must - * hold. Ai [0..nz-1] must be in the range 0 to n-1. To avoid integer - * overflow, (2.4*nz + 8*n) < INT_MAX / sizeof (int) for must hold for the - * "int" version. (2.4*nz + 8*n) < LONG_MAX / sizeof (long) must hold - * for the "long" version. Finally, Ai, Ap, and P must not be NULL. If - * any of these restrictions are not met, AMD returns AMD_INVALID. - * - * AMD returns: - * - * AMD_OK if the matrix is valid and sufficient memory can be allocated to - * perform the ordering. - * - * AMD_OUT_OF_MEMORY if not enough memory can be allocated. - * - * AMD_INVALID if the input arguments n, Ap, Ai are invalid, or if P is - * NULL. - * - * The AMD routine first forms the pattern of the matrix A+A', and then - * computes a fill-reducing ordering, P. If P [k] = i, then row/column i of - * the original is the kth pivotal row. In MATLAB notation, the permuted - * matrix is A (P,P), except that 0-based indexing is used instead of the - * 1-based indexing in MATLAB. - * - * The Control array is used to set various parameters for AMD. If a NULL - * pointer is passed, default values are used. The Control array is not - * modified. - * - * Control [AMD_DENSE]: controls the threshold for "dense" rows/columns. - * A dense row/column in A+A' can cause AMD to spend a lot of time in - * ordering the matrix. If Control [AMD_DENSE] >= 0, rows/columns - * with more than Control [AMD_DENSE] * sqrt (n) entries are ignored - * during the ordering, and placed last in the output order. The - * default value of Control [AMD_DENSE] is 10. If negative, no - * rows/columns are treated as "dense". Rows/columns with 16 or - * fewer off-diagonal entries are never considered "dense". - * - * Control [AMD_AGGRESSIVE]: controls whether or not to use aggressive - * absorption, in which a prior element is absorbed into the current - * element if is a subset of the current element, even if it is not - * adjacent to the current pivot element (refer to Amestoy, Davis, - * & Duff, 1996, for more details). The default value is nonzero, - * which means to perform aggressive absorption. This nearly always - * leads to a better ordering (because the approximate degrees are - * more accurate) and a lower execution time. There are cases where - * it can lead to a slightly worse ordering, however. To turn it off, - * set Control [AMD_AGGRESSIVE] to 0. - * - * Control [2..4] are not used in the current version, but may be used in - * future versions. - * - * The Info array provides statistics about the ordering on output. If it is - * not present, the statistics are not returned. This is not an error - * condition. - * - * Info [AMD_STATUS]: the return value of AMD, either AMD_OK, - * AMD_OUT_OF_MEMORY, or AMD_INVALID. - * - * Info [AMD_N]: n, the size of the input matrix - * - * Info [AMD_NZ]: the number of nonzeros in A, nz = Ap [n] - * - * Info [AMD_SYMMETRY]: the symmetry of the matrix A. It is the number - * of "matched" off-diagonal entries divided by the total number of - * off-diagonal entries. An entry A(i,j) is matched if A(j,i) is also - * an entry, for any pair (i,j) for which i != j. In MATLAB notation, - * S = spones (A) ; - * B = tril (S, -1) + triu (S, 1) ; - * symmetry = nnz (B & B') / nnz (B) ; - * - * Info [AMD_NZDIAG]: the number of entries on the diagonal of A. - * - * Info [AMD_NZ_A_PLUS_AT]: the number of nonzeros in A+A', excluding the - * diagonal. If A is perfectly symmetric (Info [AMD_SYMMETRY] = 1) - * with a fully nonzero diagonal, then Info [AMD_NZ_A_PLUS_AT] = nz-n - * (the smallest possible value). If A is perfectly unsymmetric - * (Info [AMD_SYMMETRY] = 0, for an upper triangular matrix, for - * example) with no diagonal, then Info [AMD_NZ_A_PLUS_AT] = 2*nz - * (the largest possible value). - * - * Info [AMD_NDENSE]: the number of "dense" rows/columns of A+A' that were - * removed from A prior to ordering. These are placed last in the - * output order P. - * - * Info [AMD_MEMORY]: the amount of memory used by AMD, in bytes. In the - * current version, this is 1.2 * Info [AMD_NZ_A_PLUS_AT] + 9*n - * times the size of an integer. This is at most 2.4nz + 9n. This - * excludes the size of the input arguments Ai, Ap, and P, which have - * a total size of nz + 2*n + 1 integers. - * - * Info [AMD_NCMPA]: the number of garbage collections performed. - * - * Info [AMD_LNZ]: the number of nonzeros in L (excluding the diagonal). - * This is a slight upper bound because mass elimination is combined - * with the approximate degree update. It is a rough upper bound if - * there are many "dense" rows/columns. The rest of the statistics, - * below, are also slight or rough upper bounds, for the same reasons. - * The post-ordering of the assembly tree might also not exactly - * correspond to a true elimination tree postordering. - * - * Info [AMD_NDIV]: the number of divide operations for a subsequent LDL' - * or LU factorization of the permuted matrix A (P,P). - * - * Info [AMD_NMULTSUBS_LDL]: the number of multiply-subtract pairs for a - * subsequent LDL' factorization of A (P,P). - * - * Info [AMD_NMULTSUBS_LU]: the number of multiply-subtract pairs for a - * subsequent LU factorization of A (P,P), assuming that no numerical - * pivoting is required. - * - * Info [AMD_DMAX]: the maximum number of nonzeros in any column of L, - * including the diagonal. - * - * Info [14..19] are not used in the current version, but may be used in - * future versions. - */ - -/* ------------------------------------------------------------------------- */ -/* AMD preprocess */ -/* ------------------------------------------------------------------------- */ - -/* amd_preprocess: sorts, removes duplicate entries, and transposes the - * nonzero pattern of a column-form matrix A, to obtain the matrix R. - * - * Alternatively, you can consider this routine as constructing a row-form - * matrix from a column-form matrix. Duplicate entries are allowed in A (and - * removed in R). The columns of R are sorted. Checks its input A for errors. - * - * On input, A can have unsorted columns, and can have duplicate entries. - * Ap [0] must still be zero, and Ap must be monotonically nondecreasing. - * Row indices must be in the range 0 to n-1. - * - * On output, if this routine returns AMD_OK, then the matrix R is a valid - * input matrix for AMD_order. It has sorted columns, with no duplicate - * entries in each column. Since AMD_order operates on the matrix A+A', it - * can just as easily use A or A', so the transpose has no significant effect - * (except for minor tie-breaking, which can lead to a minor effect in the - * quality of the ordering). As an example, compare the output of amd_demo.c - * and amd_demo2.c. - * - * This routine transposes A to get R because that's the simplest way to - * sort and remove duplicate entries from a matrix. - * - * Allocates 2*n integer work arrays, and free's them when done. - * - * If you wish to call amd_order, but do not know if your matrix has unsorted - * columns or duplicate entries, then you can use the following code, which is - * fairly efficient. amd_order will not allocate any internal matrix until - * it checks that the input matrix is valid, so the method below is memory- - * efficient as well. This code snippet assumes that Rp and Ri are already - * allocated, and are the same size as Ap and Ai respectively. - - result = amd_order (n, p, Ap, Ai, Control, Info) ; - if (result == AMD_INVALID) - { - if (amd_preprocess (n, Ap, Ai, Rp, Ri) == AMD_OK) - { - result = amd_order (n, p, Rp, Ri, Control, Info) ; - } - } - - * amd_preprocess will still return AMD_INVALID if any row index in Ai is out - * of range or if the Ap array is invalid. These errors are not corrected by - * amd_preprocess since they represent a more serious error that should be - * flagged with the AMD_INVALID error code. - */ - -int amd_preprocess -( - int n, - const int Ap [ ], - const int Ai [ ], - int Rp [ ], - int Ri [ ] -) ; - -long amd_l_preprocess -( - long n, - const long Ap [ ], - const long Ai [ ], - long Rp [ ], - long Ri [ ] -) ; - -/* Input arguments (not modified): - * - * n: the matrix A is n-by-n. - * Ap: an int/long array of size n+1, containing the column pointers of A. - * Ai: an int/long array of size nz, containing the row indices of A, - * where nz = Ap [n]. - * The nonzero pattern of column j of A is in Ai [Ap [j] ... Ap [j+1]-1]. - * Ap [0] must be zero, and Ap [j] <= Ap [j+1] must hold for all j in the - * range 0 to n-1. Row indices in Ai must be in the range 0 to n-1. - * The row indices in any one column need not be sorted, and duplicates - * may exist. - * - * Output arguments (not defined on input): - * - * Rp: an int/long array of size n+1, containing the column pointers of R. - * Ri: an int/long array of size rnz, containing the row indices of R, - * where rnz = Rp [n]. Note that Rp [n] will be less than Ap [n] if - * duplicates appear in A. In general, Rp [n] <= Ap [n]. - * The data structure for R is the same as A, except that each column of - * R contains sorted row indices, and no duplicates appear in any column. - * - * amd_preprocess returns: - * - * AMD_OK if the matrix A is valid and sufficient memory can be allocated - * to perform the preprocessing. - * - * AMD_OUT_OF_MEMORY if not enough memory can be allocated. - * - * AMD_INVALID if the input arguments n, Ap, Ai are invalid, or if Rp or - * Ri are NULL. - */ - -/* ------------------------------------------------------------------------- */ -/* AMD Control and Info arrays */ -/* ------------------------------------------------------------------------- */ - -/* amd_defaults: sets the default control settings */ -void amd_defaults (double Control [ ]) ; -void amd_l_defaults (double Control [ ]) ; - -/* amd_control: prints the control settings */ -void amd_control (double Control [ ]) ; -void amd_l_control (double Control [ ]) ; - -/* amd_info: prints the statistics */ -void amd_info (double Info [ ]) ; -void amd_l_info (double Info [ ]) ; - -#define AMD_CONTROL 5 /* size of Control array */ -#define AMD_INFO 20 /* size of Info array */ - -/* contents of Control */ -#define AMD_DENSE 0 /* "dense" if degree > Control [0] * sqrt (n) */ -#define AMD_AGGRESSIVE 1 /* do aggressive absorption if Control [1] != 0 */ - -/* default Control settings */ -#define AMD_DEFAULT_DENSE 10.0 /* default "dense" degree 10*sqrt(n) */ -#define AMD_DEFAULT_AGGRESSIVE 1 /* do aggressive absorption by default */ - -/* contents of Info */ -#define AMD_STATUS 0 /* return value of amd_order and amd_l_order */ -#define AMD_N 1 /* A is n-by-n */ -#define AMD_NZ 2 /* number of nonzeros in A */ -#define AMD_SYMMETRY 3 /* symmetry of pattern (1 is sym., 0 is unsym.) */ -#define AMD_NZDIAG 4 /* # of entries on diagonal */ -#define AMD_NZ_A_PLUS_AT 5 /* nz in A+A' */ -#define AMD_NDENSE 6 /* number of "dense" rows/columns in A */ -#define AMD_MEMORY 7 /* amount of memory used by AMD */ -#define AMD_NCMPA 8 /* number of garbage collections in AMD */ -#define AMD_LNZ 9 /* approx. nz in L, excluding the diagonal */ -#define AMD_NDIV 10 /* number of fl. point divides for LU and LDL' */ -#define AMD_NMULTSUBS_LDL 11 /* number of fl. point (*,-) pairs for LDL' */ -#define AMD_NMULTSUBS_LU 12 /* number of fl. point (*,-) pairs for LU */ -#define AMD_DMAX 13 /* max nz. in any column of L, incl. diagonal */ - -/* ------------------------------------------------------------------------- */ -/* return values of AMD */ -/* ------------------------------------------------------------------------- */ - -#define AMD_OK 0 /* success */ -#define AMD_OUT_OF_MEMORY -1 /* malloc failed */ -#define AMD_INVALID -2 /* input arguments are not valid */ - -#endif -\end{verbatim} -} - -%------------------------------------------------------------------------------ -\newpage -% References -%------------------------------------------------------------------------------ - -\bibliographystyle{plain} -\bibliography{AMD_UserGuide} - -\end{document} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Doc/ChangeLog --- a/liboctave/UMFPACK/AMD/Doc/ChangeLog Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -Jan. 21, 2004: AMD Version 1.1 - - * No bugs found or fixed - new features added, only - * amd_preprocess added, to allow for more general input of the matrix A. - * ME=0 added to amd*.f, unused DEXT variable removed from amdbar.f, - to avoid spurious compiler warnings (this was not a bug). - * amd_demo2.c and amd_demo2.out added, to test/demo amd_preprocess. - * option to allow compile-time redefinition of malloc, free, printf added - * amd_demo.c shortened slightly (removed printing of PAP') - * User Guide modified (more details added) - * linewidth reduced from 80 to 79 columns - -Oct. 7, 2003: AMD version 1.0.1. - - * MATLAB mexFunction modified, to remove call to mexCallMATLAB function. - This function can take a long time to call, particularly if you are - ordering many small matrices. - -May 6, 2003: AMD Version 1.0 released. - - * converted to C (compare amd.f and amdbar.f with amd_2.c) - * dense rows/column removed prior to ordering - * elimination tree post-ordering added - * demos, user guide written - * statistics added (nz in L, flop count, symmetry of A) - * computes the pattern of A+A' if A is unsymmetric - * user's input matrix no longer overwritten - * degree lists initialized differently - * IOVFLO argument removed from Fortran versions (amd.f and amdbar.f) - * parameters added (dense row/column detection, aggressive absorption) - * MATLAB mexFunction added - -Jan, 1996: - - * amdbar.f posted at http://www.netlib.org (with a restricted License) - * amd.f appears as MC47B/BD in the Harwell Subroutine Library - (without the IOVFLO argument) diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Doc/License --- a/liboctave/UMFPACK/AMD/Doc/License Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. -Davis, Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. - -AMD License: - - Your use or distribution of AMD or any modified version of - AMD implies that you agree to this License. - - 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 or copy this program, 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 AMD or any modified version of AMD 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. This - software was developed with support from the National Science Foundation, - and is provided to you free of charge. - -Availability: - - http://www.cise.ufl.edu/research/sparse/amd diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Doc/Makefile --- a/liboctave/UMFPACK/AMD/Doc/Makefile Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -#------------------------------------------------------------------------------ -# AMD Makefile for compiling on Unix systems (for GNU or original make) -#------------------------------------------------------------------------------ - -all: dist - -include ../Make/Make.include - -#------------------------------------------------------------------------------ -# Remove all but the files in the original distribution -#------------------------------------------------------------------------------ - -purge: clean - - $(RM) *.aux *.bbl *.blg *.log *.toc - -#------------------------------------------------------------------------------ -# Create the User Guide and Quick Start Guide -#------------------------------------------------------------------------------ - -AMD_UserGuide.pdf: AMD_UserGuide.tex AMD_UserGuide.bib - pdflatex AMD_UserGuide - bibtex AMD_UserGuide - pdflatex AMD_UserGuide - pdflatex AMD_UserGuide - -dist: AMD_UserGuide.pdf - - $(RM) *.aux *.bbl *.blg *.log *.toc - diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Include/amd.h --- a/liboctave/UMFPACK/AMD/Include/amd.h Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,359 +0,0 @@ -/* ========================================================================= */ -/* === AMD: approximate minimum degree ordering =========================== */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* AMD finds a symmetric ordering P of a matrix A so that the Cholesky - * factorization of P*A*P' has fewer nonzeros and takes less work than the - * Cholesky factorization of A. If A is not symmetric, then it performs its - * ordering on the matrix A+A'. Two sets of user-callable routines are - * provided, one for "int" integers and the other for "long" integers. - * - * The method is based on the approximate minimum degree algorithm, discussed - * in Amestoy, Davis, and Duff, "An approximate degree ordering algorithm", - * SIAM Journal of Matrix Analysis and Applications, vol. 17, no. 4, pp. - * 886-905, 1996. This package can perform both the AMD ordering (with - * aggressive absorption), and the AMDBAR ordering (without aggressive - * absorption) discussed in the above paper. This package differs from the - * Fortran codes discussed in the paper: - * - * (1) it can ignore "dense" rows and columns, leading to faster run times - * (2) it computes the ordering of A+A' if A is not symmetric - * (3) it is followed by a depth-first post-ordering of the assembly tree - * (or supernodal elimination tree) - * - * For historical reasons, the Fortran versions, amd.f and amdbar.f, have - * been left (nearly) unchanged. They compute the identical ordering as - * described in the above paper. - */ - -#ifndef AMD_H -#define AMD_H - -int amd_order ( /* returns 0 if OK, negative value if error */ - int n, /* A is n-by-n. n must be >= 0. */ - const int Ap [ ], /* column pointers for A, of size n+1 */ - const int Ai [ ], /* row indices of A, of size nz = Ap [n] */ - int P [ ], /* output permutation, of size n */ - double Control [ ], /* input Control settings, of size AMD_CONTROL */ - double Info [ ] /* output Info statistics, of size AMD_INFO */ -) ; - -long amd_l_order ( /* see above for description of arguments */ - long n, - const long Ap [ ], - const long Ai [ ], - long P [ ], - double Control [ ], - double Info [ ] -) ; - -/* Input arguments (not modified): - * - * n: the matrix A is n-by-n. - * Ap: an int/long array of size n+1, containing the column pointers of A. - * Ai: an int/long array of size nz, containing the row indices of A, - * where nz = Ap [n]. - * Control: a double array of size AMD_CONTROL, containing control - * parameters. Defaults are used if Control is NULL. - * - * Output arguments (not defined on input): - * - * P: an int/long array of size n, containing the output permutation. If - * row i is the kth pivot row, then P [k] = i. In MATLAB notation, - * the reordered matrix is A (P,P). - * Info: a double array of size AMD_INFO, containing statistical - * information. Ignored if Info is NULL. - * - * On input, the matrix A is stored in column-oriented form. The row indices - * of nonzero entries in column j are stored in Ai [Ap [j] ... Ap [j+1]-1]. - * The row indices must appear in ascending order in each column, and there - * must not be any duplicate entries. Row indices must be in the range 0 to - * n-1. Ap [0] must be zero, and thus nz = Ap [n] is the number of nonzeros - * in A. The array Ap is of size n+1, and the array Ai is of size nz = Ap [n]. - * The matrix does not need to be symmetric, and the diagonal does not need to - * be present (if diagonal entries are present, they are ignored except for - * the output statistic Info [AMD_NZDIAG]). The arrays Ai and Ap are not - * modified. This form of the Ap and Ai arrays to represent the nonzero - * pattern of the matrix A is the same as that used internally by MATLAB. - * If you wish to use a more flexible input structure, please see the - * umfpack_*_triplet_to_col routines in the UMFPACK package, at - * http://www.cise.ufl.edu/research/sparse/umfpack, or use the amd_preprocess - * routine discussed below. - * - * Restrictions: n >= 0. Ap [0] = 0. Ap [j] <= Ap [j+1] for all j in the - * range 0 to n-1. nz = Ap [n] >= 0. For all j in the range 0 to n-1, - * and for all p in the range Ap [j] to Ap [j+1]-2, Ai [p] < Ai [p+1] must - * hold. Ai [0..nz-1] must be in the range 0 to n-1. To avoid integer - * overflow, (2.4*nz + 8*n) < INT_MAX / sizeof (int) for must hold for the - * "int" version. (2.4*nz + 8*n) < LONG_MAX / sizeof (long) must hold - * for the "long" version. Finally, Ai, Ap, and P must not be NULL. If - * any of these restrictions are not met, AMD returns AMD_INVALID. - * - * AMD returns: - * - * AMD_OK if the matrix is valid and sufficient memory can be allocated to - * perform the ordering. - * - * AMD_OUT_OF_MEMORY if not enough memory can be allocated. - * - * AMD_INVALID if the input arguments n, Ap, Ai are invalid, or if P is - * NULL. - * - * The AMD routine first forms the pattern of the matrix A+A', and then - * computes a fill-reducing ordering, P. If P [k] = i, then row/column i of - * the original is the kth pivotal row. In MATLAB notation, the permuted - * matrix is A (P,P), except that 0-based indexing is used instead of the - * 1-based indexing in MATLAB. - * - * The Control array is used to set various parameters for AMD. If a NULL - * pointer is passed, default values are used. The Control array is not - * modified. - * - * Control [AMD_DENSE]: controls the threshold for "dense" rows/columns. - * A dense row/column in A+A' can cause AMD to spend a lot of time in - * ordering the matrix. If Control [AMD_DENSE] >= 0, rows/columns - * with more than Control [AMD_DENSE] * sqrt (n) entries are ignored - * during the ordering, and placed last in the output order. The - * default value of Control [AMD_DENSE] is 10. If negative, no - * rows/columns are treated as "dense". Rows/columns with 16 or - * fewer off-diagonal entries are never considered "dense". - * - * Control [AMD_AGGRESSIVE]: controls whether or not to use aggressive - * absorption, in which a prior element is absorbed into the current - * element if is a subset of the current element, even if it is not - * adjacent to the current pivot element (refer to Amestoy, Davis, - * & Duff, 1996, for more details). The default value is nonzero, - * which means to perform aggressive absorption. This nearly always - * leads to a better ordering (because the approximate degrees are - * more accurate) and a lower execution time. There are cases where - * it can lead to a slightly worse ordering, however. To turn it off, - * set Control [AMD_AGGRESSIVE] to 0. - * - * Control [2..4] are not used in the current version, but may be used in - * future versions. - * - * The Info array provides statistics about the ordering on output. If it is - * not present, the statistics are not returned. This is not an error - * condition. - * - * Info [AMD_STATUS]: the return value of AMD, either AMD_OK, - * AMD_OUT_OF_MEMORY, or AMD_INVALID. - * - * Info [AMD_N]: n, the size of the input matrix - * - * Info [AMD_NZ]: the number of nonzeros in A, nz = Ap [n] - * - * Info [AMD_SYMMETRY]: the symmetry of the matrix A. It is the number - * of "matched" off-diagonal entries divided by the total number of - * off-diagonal entries. An entry A(i,j) is matched if A(j,i) is also - * an entry, for any pair (i,j) for which i != j. In MATLAB notation, - * S = spones (A) ; - * B = tril (S, -1) + triu (S, 1) ; - * symmetry = nnz (B & B') / nnz (B) ; - * - * Info [AMD_NZDIAG]: the number of entries on the diagonal of A. - * - * Info [AMD_NZ_A_PLUS_AT]: the number of nonzeros in A+A', excluding the - * diagonal. If A is perfectly symmetric (Info [AMD_SYMMETRY] = 1) - * with a fully nonzero diagonal, then Info [AMD_NZ_A_PLUS_AT] = nz-n - * (the smallest possible value). If A is perfectly unsymmetric - * (Info [AMD_SYMMETRY] = 0, for an upper triangular matrix, for - * example) with no diagonal, then Info [AMD_NZ_A_PLUS_AT] = 2*nz - * (the largest possible value). - * - * Info [AMD_NDENSE]: the number of "dense" rows/columns of A+A' that were - * removed from A prior to ordering. These are placed last in the - * output order P. - * - * Info [AMD_MEMORY]: the amount of memory used by AMD, in bytes. In the - * current version, this is 1.2 * Info [AMD_NZ_A_PLUS_AT] + 9*n - * times the size of an integer. This is at most 2.4nz + 9n. This - * excludes the size of the input arguments Ai, Ap, and P, which have - * a total size of nz + 2*n + 1 integers. - * - * Info [AMD_NCMPA]: the number of garbage collections performed. - * - * Info [AMD_LNZ]: the number of nonzeros in L (excluding the diagonal). - * This is a slight upper bound because mass elimination is combined - * with the approximate degree update. It is a rough upper bound if - * there are many "dense" rows/columns. The rest of the statistics, - * below, are also slight or rough upper bounds, for the same reasons. - * The post-ordering of the assembly tree might also not exactly - * correspond to a true elimination tree postordering. - * - * Info [AMD_NDIV]: the number of divide operations for a subsequent LDL' - * or LU factorization of the permuted matrix A (P,P). - * - * Info [AMD_NMULTSUBS_LDL]: the number of multiply-subtract pairs for a - * subsequent LDL' factorization of A (P,P). - * - * Info [AMD_NMULTSUBS_LU]: the number of multiply-subtract pairs for a - * subsequent LU factorization of A (P,P), assuming that no numerical - * pivoting is required. - * - * Info [AMD_DMAX]: the maximum number of nonzeros in any column of L, - * including the diagonal. - * - * Info [14..19] are not used in the current version, but may be used in - * future versions. - */ - -/* ------------------------------------------------------------------------- */ -/* AMD preprocess */ -/* ------------------------------------------------------------------------- */ - -/* amd_preprocess: sorts, removes duplicate entries, and transposes the - * nonzero pattern of a column-form matrix A, to obtain the matrix R. - * - * Alternatively, you can consider this routine as constructing a row-form - * matrix from a column-form matrix. Duplicate entries are allowed in A (and - * removed in R). The columns of R are sorted. Checks its input A for errors. - * - * On input, A can have unsorted columns, and can have duplicate entries. - * Ap [0] must still be zero, and Ap must be monotonically nondecreasing. - * Row indices must be in the range 0 to n-1. - * - * On output, if this routine returns AMD_OK, then the matrix R is a valid - * input matrix for AMD_order. It has sorted columns, with no duplicate - * entries in each column. Since AMD_order operates on the matrix A+A', it - * can just as easily use A or A', so the transpose has no significant effect - * (except for minor tie-breaking, which can lead to a minor effect in the - * quality of the ordering). As an example, compare the output of amd_demo.c - * and amd_demo2.c. - * - * This routine transposes A to get R because that's the simplest way to - * sort and remove duplicate entries from a matrix. - * - * Allocates 2*n integer work arrays, and free's them when done. - * - * If you wish to call amd_order, but do not know if your matrix has unsorted - * columns or duplicate entries, then you can use the following code, which is - * fairly efficient. amd_order will not allocate any internal matrix until - * it checks that the input matrix is valid, so the method below is memory- - * efficient as well. This code snippet assumes that Rp and Ri are already - * allocated, and are the same size as Ap and Ai respectively. - - result = amd_order (n, p, Ap, Ai, Control, Info) ; - if (result == AMD_INVALID) - { - if (amd_preprocess (n, Ap, Ai, Rp, Ri) == AMD_OK) - { - result = amd_order (n, p, Rp, Ri, Control, Info) ; - } - } - - * amd_preprocess will still return AMD_INVALID if any row index in Ai is out - * of range or if the Ap array is invalid. These errors are not corrected by - * amd_preprocess since they represent a more serious error that should be - * flagged with the AMD_INVALID error code. - */ - -int amd_preprocess -( - int n, - const int Ap [ ], - const int Ai [ ], - int Rp [ ], - int Ri [ ] -) ; - -long amd_l_preprocess -( - long n, - const long Ap [ ], - const long Ai [ ], - long Rp [ ], - long Ri [ ] -) ; - -/* Input arguments (not modified): - * - * n: the matrix A is n-by-n. - * Ap: an int/long array of size n+1, containing the column pointers of A. - * Ai: an int/long array of size nz, containing the row indices of A, - * where nz = Ap [n]. - * The nonzero pattern of column j of A is in Ai [Ap [j] ... Ap [j+1]-1]. - * Ap [0] must be zero, and Ap [j] <= Ap [j+1] must hold for all j in the - * range 0 to n-1. Row indices in Ai must be in the range 0 to n-1. - * The row indices in any one column need not be sorted, and duplicates - * may exist. - * - * Output arguments (not defined on input): - * - * Rp: an int/long array of size n+1, containing the column pointers of R. - * Ri: an int/long array of size rnz, containing the row indices of R, - * where rnz = Rp [n]. Note that Rp [n] will be less than Ap [n] if - * duplicates appear in A. In general, Rp [n] <= Ap [n]. - * The data structure for R is the same as A, except that each column of - * R contains sorted row indices, and no duplicates appear in any column. - * - * amd_preprocess returns: - * - * AMD_OK if the matrix A is valid and sufficient memory can be allocated - * to perform the preprocessing. - * - * AMD_OUT_OF_MEMORY if not enough memory can be allocated. - * - * AMD_INVALID if the input arguments n, Ap, Ai are invalid, or if Rp or - * Ri are NULL. - */ - -/* ------------------------------------------------------------------------- */ -/* AMD Control and Info arrays */ -/* ------------------------------------------------------------------------- */ - -/* amd_defaults: sets the default control settings */ -void amd_defaults (double Control [ ]) ; -void amd_l_defaults (double Control [ ]) ; - -/* amd_control: prints the control settings */ -void amd_control (double Control [ ]) ; -void amd_l_control (double Control [ ]) ; - -/* amd_info: prints the statistics */ -void amd_info (double Info [ ]) ; -void amd_l_info (double Info [ ]) ; - -#define AMD_CONTROL 5 /* size of Control array */ -#define AMD_INFO 20 /* size of Info array */ - -/* contents of Control */ -#define AMD_DENSE 0 /* "dense" if degree > Control [0] * sqrt (n) */ -#define AMD_AGGRESSIVE 1 /* do aggressive absorption if Control [1] != 0 */ - -/* default Control settings */ -#define AMD_DEFAULT_DENSE 10.0 /* default "dense" degree 10*sqrt(n) */ -#define AMD_DEFAULT_AGGRESSIVE 1 /* do aggressive absorption by default */ - -/* contents of Info */ -#define AMD_STATUS 0 /* return value of amd_order and amd_l_order */ -#define AMD_N 1 /* A is n-by-n */ -#define AMD_NZ 2 /* number of nonzeros in A */ -#define AMD_SYMMETRY 3 /* symmetry of pattern (1 is sym., 0 is unsym.) */ -#define AMD_NZDIAG 4 /* # of entries on diagonal */ -#define AMD_NZ_A_PLUS_AT 5 /* nz in A+A' */ -#define AMD_NDENSE 6 /* number of "dense" rows/columns in A */ -#define AMD_MEMORY 7 /* amount of memory used by AMD */ -#define AMD_NCMPA 8 /* number of garbage collections in AMD */ -#define AMD_LNZ 9 /* approx. nz in L, excluding the diagonal */ -#define AMD_NDIV 10 /* number of fl. point divides for LU and LDL' */ -#define AMD_NMULTSUBS_LDL 11 /* number of fl. point (*,-) pairs for LDL' */ -#define AMD_NMULTSUBS_LU 12 /* number of fl. point (*,-) pairs for LU */ -#define AMD_DMAX 13 /* max nz. in any column of L, incl. diagonal */ - -/* ------------------------------------------------------------------------- */ -/* return values of AMD */ -/* ------------------------------------------------------------------------- */ - -#define AMD_OK 0 /* success */ -#define AMD_OUT_OF_MEMORY -1 /* malloc failed */ -#define AMD_INVALID -2 /* input arguments are not valid */ - -#endif diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Lib/libamd.def --- a/liboctave/UMFPACK/AMD/Lib/libamd.def Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -LIBRARY libamd.dll -EXPORTS -amd_order -amd_defaults -amd_control -amd_info -amd_preprocess -amd_l_order -amd_l_defaults -amd_l_control -amd_l_info -amd_l_preprocess diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/MATLAB/Contents.m --- a/liboctave/UMFPACK/AMD/MATLAB/Contents.m Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -%Contents of the AMD sparse matrix ordering package: -% -% amd p = amd (A), the approximate minimum degree ordering of A -% amd_demo a demo of amd, using the can_24 matrix -% amd_make to comple amd for use in MATLAB -% can_24.mat a sample sparse matrix from the Harwell/Boeing collection -% -% See also: amd, colamd, symamd, colmmd, symmmd, umfpack -% -% AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, -% Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. - -help Contents diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/MATLAB/GNUmakefile --- a/liboctave/UMFPACK/AMD/MATLAB/GNUmakefile Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -#------------------------------------------------------------------------------ -# GNUmakefile for the AMD MATLAB mexFunction -#------------------------------------------------------------------------------ - -all: amd - -include ../Make/Make.include - -MX = $(MEX) -I../Include - -AMD = amd_aat amd_1 amd_2 amd_dump amd_postorder amd_post_tree amd_defaults \ - amd_order amd_control amd_info amd_valid - -INC = ../Include/amd.h ../Source/amd_internal.h - -MEXAMD = $(addsuffix .o, $(subst amd_,amd_m_,$(AMD))) - -amd_m_%.o: ../Source/amd_%.c $(INC) - $(MX) -DDINT -c $< - - $(MV) amd_$*.o $@ - -amd: amd_mex.c $(MEXAMD) $(INC) - $(MX) -output amd amd_mex.c $(MEXAMD) - -#------------------------------------------------------------------------------ -# Remove all but the files in the original distribution -#------------------------------------------------------------------------------ - -purge: clean - - $(RM) amd.mex* amd.dll diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/MATLAB/Makefile --- a/liboctave/UMFPACK/AMD/MATLAB/Makefile Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -#------------------------------------------------------------------------------ -# compile the AMD mexFunction for MATLAB (original make only) -#------------------------------------------------------------------------------ - -# This is a very ugly Makefile, and is only provided for those who do not -# have GNU make. Note that it is not used if you have GNU make. It ignores -# dependency checking and just compiles everything. It was created -# automatically, via make -n using the GNUmakefile. That way, I don't have -# maintain two Makefiles. - -all: amd - -include ../Make/Make.include - -MX = $(MEX) -I../Include - -amd: - $(MX) -DDINT -c ../Source/amd_aat.c - $(MV) amd_aat.o amd_m_aat.o - $(MX) -DDINT -c ../Source/amd_1.c - $(MV) amd_1.o amd_m_1.o - $(MX) -DDINT -c ../Source/amd_2.c - $(MV) amd_2.o amd_m_2.o - $(MX) -DDINT -c ../Source/amd_dump.c - $(MV) amd_dump.o amd_m_dump.o - $(MX) -DDINT -c ../Source/amd_postorder.c - $(MV) amd_postorder.o amd_m_postorder.o - $(MX) -DDINT -c ../Source/amd_post_tree.c - $(MV) amd_post_tree.o amd_m_post_tree.o - $(MX) -DDINT -c ../Source/amd_defaults.c - $(MV) amd_defaults.o amd_m_defaults.o - $(MX) -DDINT -c ../Source/amd_order.c - $(MV) amd_order.o amd_m_order.o - $(MX) -DDINT -c ../Source/amd_control.c - $(MV) amd_control.o amd_m_control.o - $(MX) -DDINT -c ../Source/amd_info.c - $(MV) amd_info.o amd_m_info.o - $(MX) -DDINT -c ../Source/amd_valid.c - $(MV) amd_valid.o amd_m_valid.o - $(MX) -output amd amd_mex.c amd_m_aat.o \ - amd_m_1.o amd_m_2.o amd_m_dump.o amd_m_postorder.o \ - amd_m_post_tree.o amd_m_defaults.o amd_m_order.o amd_m_control.o \ - amd_m_info.o amd_m_valid.o - -#------------------------------------------------------------------------------ -# Remove all but the files in the original distribution -#------------------------------------------------------------------------------ - -purge: clean - - $(RM) amd.mex* amd.dll diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/MATLAB/amd.m --- a/liboctave/UMFPACK/AMD/MATLAB/amd.m Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -function [p, Info] = amd (A, Control) -%AMD Approximate minimum degree permutation. -% P = AMD (S) returns the approximate minimum degree permutation vector for -% the sparse matrix C = S+S'. The Cholesky factorization of C (P,P), or -% S (P,P), tends to be sparser than that of C or S. AMD tends to be faster -% than SYMMMD and SYMAMD, and tends to return better orderings than SYMMMD. -% S must be square. If S is full, amd (S) is equivalent to amd (sparse (S)). -% -% Usage: P = amd (S) ; % finds the ordering -% [P, Info] = amd (S, Control) ; % optional parameters & statistics -% Control = amd ; % returns default parameters -% amd ; % prints default parameters. -% -% Control (1); If S is n-by-n, then rows/columns with more than -% max (16, (Control (1))* sqrt(n)) entries in S+S' are considered -% "dense", and ignored during ordering. They are placed last in the -% output permutation. The default is 10.0 if Control is not present. -% Control (2): If nonzero, then aggressive absorption is performed. -% This is the default if Control is not present. -% Control (3): If nonzero, print statistics about the ordering. -% -% Info (1): status (0: ok, -1: out of memory, -2: matrix invalid) -% Info (2): n = size (A,1) -% Info (3): nnz (A) -% Info (4): the symmetry of the matrix S (0.0 means purely unsymmetric, -% 1.0 means purely symmetric). Computed as: -% B = tril (S, -1) + triu (S, 1) ; symmetry = nnz (B & B') / nnz (B); -% Info (5): nnz (diag (S)) -% Info (6): nnz in S+S', excluding the diagonal (= nnz (B+B')) -% Info (7): number "dense" rows/columns in S+S' -% Info (8): the amount of memory used by AMD, in bytes -% Info (9): the number of memory compactions performed by AMD -% -% The following statistics are slight upper bounds because of the -% approximate degree in AMD. The bounds are looser if "dense" rows/columns -% are ignored during ordering (Info (7) > 0). The statistics are for a -% subsequent factorization of the matrix C (P,P). The LU factorization -% statistics assume no pivoting. -% -% Info (10): the number of nonzeros in L, excluding the diagonal -% Info (11): the number of divide operations for LL', LDL', or LU -% Info (12): the number of multiply-subtract pairs for LL' or LDL' -% Info (13): the number of multiply-subtract pairs for LU -% Info (14): the max # of nonzeros in any column of L (incl. diagonal) -% Info (15:20): unused, reserved for future use -% -% An assembly tree post-ordering is performed, which is typically the same -% as an elimination tree post-ordering. It is not always identical because -% of the approximate degree update used, and because "dense" rows/columns -% do not take part in the post-order. It well-suited for a subsequent -% "chol", however. If you require a precise elimination tree post-ordering, -% then do: -% -% P = amd (S) ; -% C = spones (S) + spones (S') ; % skip this if S already symmetric -% [ignore, Q] = sparsfun ('symetree', C (P,P)) ; -% P = P (Q) ; -% -% -------------------------------------------------------------------------- -% AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, -% Patrick R. Amestoy, and Iain S. Duff. See ../README for License. -% email: davis@cise.ufl.edu CISE Department, Univ. of Florida. -% web: http://www.cise.ufl.edu/research/sparse/amd -% -------------------------------------------------------------------------- -% -% Acknowledgements: This work was supported by the National Science -% Foundation, under grants ASC-9111263, DMS-9223088, and CCR-0203270. -% -% See also COLMMD, COLAMD, COLPERM, SYMAMD, SYMMMD, SYMRCM. - -more on -help amd -more off -error ('amd mexFunction not found! Type "amd_make" in MATLAB to compile amd'); diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/MATLAB/amd_demo.m --- a/liboctave/UMFPACK/AMD/MATLAB/amd_demo.m Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -function amd_demo -% AMD DEMO -% -% A demo of AMD for MATLAB. -% -% -------------------------------------------------------------------------- -% AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, -% Patrick R. Amestoy, and Iain S. Duff. See ../README for License. -% email: davis@cise.ufl.edu CISE Department, Univ. of Florida. -% web: http://www.cise.ufl.edu/research/sparse/amd -% -------------------------------------------------------------------------- -% -% See also: amd, amd_make - -% This orders the same matrix as the ANSI C demo, amd_demo.c. It includes an -% additional analysis of the matrix via MATLAB's symbfact routine. - -% First, print the help information for AMD -help amd - -% Get the Harwell/Boeing can_24 matrix. This is an example matrix from the -% MATLAB-accessible UF sparse matrix collection, and can be loaded into -% MATLAB with the statment "Problem = UFget ('HB/can_24')", after obtaining -% the UFget function and its supporting routines at -% http://www.cise.ufl.edu/sparse/mat . - -load can_24 -A = Problem.A ; -n = size (A,1) ; - -figure (1) -clf -hold off -subplot (2,2,1) ; -spy (A) -% remove the "_" from the name before printing it in the plot title -title (sprintf ('%s', strrep (Problem.name, '_', '-'))) ; -fprintf ('Matrix name: %s\n', Problem.name) ; -fprintf ('Matrix title: %s\n', Problem.title) ; - -% print the details during AMD ordering and SYMBFACT -spparms ('spumoni', 1) ; - -% order the matrix. Note that the Info argument is optional. -fprintf ('\nIf the next step fails, then you have\n') ; -fprintf ('not yet compiled the AMD mexFunction.\n') ; -[p, Info] = amd (A) ; - -% order again, but this time print some statistics -[p, Info] = amd (A, [10 1 1]) ; - -fprintf ('Permutation vector:\n') ; -fprintf (' %2d', p) ; -fprintf ('\n\n') ; - -subplot (2,2,2) ; -spy (A (p,p)) -title ('Permuted matrix') ; - -% The amd_demo.c program stops here. - -fprintf ('Analyze A(p,p) with MATLAB''s symbfact routine:\n') ; -[cn, height, parent, post, R] = symbfact (A (p,p)) ; - -subplot (2,2,3) ; -spy (R') ; -title ('Cholesky factor, L') ; - -subplot (2,2,4) ; -treeplot (parent) ; -title ('elimination tree') ; - -% results from symbfact -lnz = sum (cn) ; % number of nonzeros in L, incl. diagonal -cn = cn - 1 ; % get the count of off-diagonal entries -fl = n + sum (cn.^2 + 2*cn) ; % flop count for chol (A (p,p) -fprintf ('number of nonzeros in L (including diagonal): %d\n', lnz) ; -fprintf ('floating point operation count for chol (A (p,p)): %d\n', fl) ; - -% approximations from amd: -lnz2 = n + Info (10) ; -fl2 = n + Info (11) + 2 * Info (12) ; -fprintf ('\nResults from AMD''s approximate analysis:\n') ; -fprintf ('number of nonzeros in L (including diagonal): %d\n', lnz2) ; -fprintf ('floating point operation count for chol (A (p,p)): %d\n\n', fl2) ; - -if (lnz2 ~= lnz | fl ~= fl2) - fprintf ('Note that the nonzero and flop counts from AMD are slight\n') ; - fprintf ('upper bounds. This is due to the approximate minimum degree\n'); - fprintf ('method used, in conjunction with "mass elimination".\n') ; - fprintf ('See the discussion about mass elimination in amd.h and\n') ; - fprintf ('amd_2.c for more details.\n') ; -end - -% turn off diagnostic output in MATLAB's sparse matrix routines -spparms ('spumoni', 0) ; diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/MATLAB/amd_demo.m.out --- a/liboctave/UMFPACK/AMD/MATLAB/amd_demo.m.out Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,136 +0,0 @@ ->> amd_demo - - AMD Approximate minimum degree permutation. - P = AMD (S) returns the approximate minimum degree permutation vector for - the sparse matrix C = S+S'. The Cholesky factorization of C (P,P), or - S (P,P), tends to be sparser than that of C or S. AMD tends to be faster - than SYMMMD and SYMAMD, and tends to return better orderings than SYMMMD. - S must be square. If S is full, amd (S) is equivalent to amd (sparse (S)). - - Usage: P = amd (S) ; % finds the ordering - [P, Info] = amd (S, Control) ; % optional parameters & statistics - Control = amd ; % returns default parameters - amd ; % prints default parameters. - - Control (1); If S is n-by-n, then rows/columns with more than - max (16, (Control (1))* sqrt(n)) entries in S+S' are considered - "dense", and ignored during ordering. They are placed last in the - output permutation. The default is 10.0 if Control is not present. - Control (2): If nonzero, then aggressive absorption is performed. - This is the default if Control is not present. - Control (3): If nonzero, print statistics about the ordering. - - Info (1): status (0: ok, -1: out of memory, -2: matrix invalid) - Info (2): n = size (A,1) - Info (3): nnz (A) - Info (4): the symmetry of the matrix S (0.0 means purely unsymmetric, - 1.0 means purely symmetric). Computed as: - B = tril (S, -1) + triu (S, 1) ; symmetry = nnz (B & B') / nnz (B); - Info (5): nnz (diag (S)) - Info (6): nnz in S+S', excluding the diagonal (= nnz (B+B')) - Info (7): number "dense" rows/columns in S+S' - Info (8): the amount of memory used by AMD, in bytes - Info (9): the number of memory compactions performed by AMD - - The following statistics are slight upper bounds because of the - approximate degree in AMD. The bounds are looser if "dense" rows/columns - are ignored during ordering (Info (7) > 0). The statistics are for a - subsequent factorization of the matrix C (P,P). The LU factorization - statistics assume no pivoting. - - Info (10): the number of nonzeros in L, excluding the diagonal - Info (11): the number of divide operations for LL', LDL', or LU - Info (12): the number of multiply-subtract pairs for LL' or LDL' - Info (13): the number of multiply-subtract pairs for LU - Info (14): the max # of nonzeros in any column of L (incl. diagonal) - Info (15:20): unused, reserved for future use - - An assembly tree post-ordering is performed, which is typically the same - as an elimination tree post-ordering. It is not always identical because - of the approximate degree update used, and because "dense" rows/columns - do not take part in the post-order. It well-suited for a subsequent - "chol", however. If you require a precise elimination tree post-ordering, - then do: - - P = amd (S) ; - C = spones (S) + spones (S') ; % skip this if S already symmetric - [ignore, Q] = sparsfun ('symetree', C (P,P)) ; - P = P (Q) ; - - -------------------------------------------------------------------------- - AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, - Patrick R. Amestoy, and Iain S. Duff. See ../README for License. - email: davis@cise.ufl.edu CISE Department, Univ. of Florida. - web: http://www.cise.ufl.edu/research/sparse/amd - -------------------------------------------------------------------------- - - Acknowledgements: This work was supported by the National Science - Foundation, under grants ASC-9111263, DMS-9223088, and CCR-0203270. - - See also COLMMD, COLAMD, COLPERM, SYMAMD, SYMMMD, SYMRCM. - -Matrix name: HB/can_24 -Matrix title: 1SYMMETRIC PATTERN FROM CANNES,LUCIEN MARRO,JUNE 1981. - -If the next step fails, then you have -not yet compiled the AMD mexFunction. - -amd: approximate minimum degree ordering, parameters: - dense row parameter: 10 - (rows with more than max (10 * sqrt (n), 16) entries are - considered "dense", and placed last in output permutation) - aggressive absorption: yes - - input matrix A is 24-by-24 - input matrix A has 160 nonzero entries - -amd: approximate minimum degree ordering, results: - status: OK - n, dimension of A: 24 - nz, number of nonzeros in A: 160 - symmetry of A: 1.0000 - number of nonzeros on diagonal: 24 - nonzeros in pattern of A+A' (excl. diagonal): 136 - # dense rows/columns of A+A': 0 - memory used, in bytes: 1516 - # of memory compactions: 0 - - The following approximate statistics are for a subsequent - factorization of A(P,P) + A(P,P)'. They are slight upper - bounds if there are no dense rows/columns in A+A', and become - looser if dense rows/columns exist. - - nonzeros in L (excluding diagonal): 97 - nonzeros in L (including diagonal): 121 - # divide operations for LDL' or LU: 97 - # multiply-subtract operations for LDL': 275 - # multiply-subtract operations for LU: 453 - max nz. in any column of L (incl. diagonal): 8 - - chol flop count for real A, sqrt counted as 1 flop: 671 - LDL' flop count for real A: 647 - LDL' flop count for complex A: 3073 - LU flop count for real A (with no pivoting): 1003 - LU flop count for complex A (with no pivoting): 4497 - -Permutation vector: - 23 21 11 24 13 6 17 9 15 5 16 8 2 10 14 18 1 3 4 7 12 19 22 20 - -Analyze A(p,p) with MATLAB's symbfact routine: -predicted nonzeros: 120 -predicted flops: 656 -predicted height: 16 -predicted front size: 7 -number of nonzeros in L (including diagonal): 120 -floating point operation count for chol (A (p,p)): 656 - -Results from AMD's approximate analysis: -number of nonzeros in L (including diagonal): 121 -floating point operation count for chol (A (p,p)): 671 - -Note that the nonzero and flop counts from AMD are slight -upper bounds. This is due to the approximate minimum degree -method used, in conjunction with "mass elimination". -See the discussion about mass elimination in amd.h and -amd_2.c for more details. ->> diary off diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/MATLAB/amd_make.m --- a/liboctave/UMFPACK/AMD/MATLAB/amd_make.m Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -function amd_make -% AMD_MAKE: compiles the AMD mexFunction for MATLAB -% -% -------------------------------------------------------------------------- -% AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, -% Patrick R. Amestoy, and Iain S. Duff. See ../README for License. -% email: davis@cise.ufl.edu CISE Department, Univ. of Florida. -% web: http://www.cise.ufl.edu/research/sparse/amd -% -------------------------------------------------------------------------- -% -% See also: amd, amd_demo - -help amd_make -fprintf ('Compiling the AMD mexFunction:\n') ; -cmd = sprintf ('mex -inline -O -output amd -I..%sInclude amd_mex.c', filesep) ; -files = {'amd_order', 'amd_dump', 'amd_postorder', 'amd_post_tree', ... - 'amd_aat', 'amd_2', 'amd_1', 'amd_defaults', 'amd_control', 'amd_info', ... - 'amd_valid' } ; -for i = 1 : length (files) - cmd = sprintf ('%s ..%sSource%s%s.c', cmd, filesep, filesep, files {i}) ; -end -fprintf ('%s\n', cmd) ; -try - eval (cmd) ; -catch - fprintf ('Compilation not successful.\n') ; -end - -input ('\nHit enter to run the AMD demo\n') ; -more on -amd_demo -more off diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/MATLAB/amd_mex.c --- a/liboctave/UMFPACK/AMD/MATLAB/amd_mex.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,189 +0,0 @@ -/* ========================================================================= */ -/* === AMD mexFunction ===================================================== */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* - * Usage: - * p = amd (A) - * p = amd (A, Control) - * [p, Info] = amd (A) - * [p, Info] = amd (A, Control) - * Control = amd ; % return the default Control settings for AMD - * amd ; % print the default Control settings for AMD - * - * Given a square matrix A, compute a permutation P suitable for a Cholesky - * factorization of the matrix B (P,P), where B = spones (A) + spones (A'). - * The method used is the approximate minimum degree ordering method. See - * amd.m and amd.h for more information. - */ - -#include "amd.h" -#include "mex.h" -#include "matrix.h" - -void mexFunction -( - int nlhs, - mxArray *plhs[], - int nrhs, - const mxArray *prhs[] -) -{ - int i, m, n, *Ap, *Ai, *P, nc, result, spumoni, full ; - double *Pout, *InfoOut, Control [AMD_CONTROL], Info [AMD_INFO], *ControlIn; - mxArray *A, *string, *parameter ; - - /* --------------------------------------------------------------------- */ - /* get control parameters */ - /* --------------------------------------------------------------------- */ - - spumoni = 0 ; - if (nrhs == 0) - { - /* get the default control parameters, and return */ - plhs [0] = mxCreateDoubleMatrix (AMD_CONTROL, 1, mxREAL) ; - amd_defaults (mxGetPr (plhs [0])) ; - if (nlhs == 0) - { - amd_control (mxGetPr (plhs [0])) ; - } - return ; - } - - amd_defaults (Control) ; - if (nrhs > 1) - { - ControlIn = mxGetPr (prhs [1]) ; - nc = mxGetM (prhs [1]) * mxGetN (prhs [1]) ; - Control [AMD_DENSE] - = (nc > 0) ? ControlIn [AMD_DENSE] : AMD_DEFAULT_DENSE ; - Control [AMD_AGGRESSIVE] - = (nc > 1) ? ControlIn [AMD_AGGRESSIVE] : AMD_DEFAULT_AGGRESSIVE ; - spumoni = (nc > 2) ? (ControlIn [2] != 0) : 0 ; - } - - if (spumoni > 0) - { - amd_control (Control) ; - } - - /* --------------------------------------------------------------------- */ - /* get inputs */ - /* --------------------------------------------------------------------- */ - - if (nlhs > 2 || nrhs > 2) - { - mexErrMsgTxt ("Usage: p = amd (A)\nor [p, Info] = amd (A, Control)") ; - } - - A = (mxArray *) prhs [0] ; - n = mxGetN (A) ; - m = mxGetM (A) ; - if (spumoni > 0) - { - mexPrintf (" input matrix A is %d-by-%d\n", m, n) ; - } - if (mxGetNumberOfDimensions (A) != 2) - { - mexErrMsgTxt ("amd: A must be 2-dimensional") ; - } - if (m != n) - { - mexErrMsgTxt ("amd: A must be square") ; - } - - /* --------------------------------------------------------------------- */ - /* allocate workspace for output permutation */ - /* --------------------------------------------------------------------- */ - - P = mxMalloc ((n+1) * sizeof (int)) ; - - /* --------------------------------------------------------------------- */ - /* if A is full, convert to a sparse matrix */ - /* --------------------------------------------------------------------- */ - - full = !mxIsSparse (A) ; - if (full) - { - if (spumoni > 0) - { - mexPrintf ( - " input matrix A is full (sparse copy of A will be created)\n"); - } - mexCallMATLAB (1, &A, 1, (mxArray **) prhs, "sparse") ; - } - Ap = mxGetJc (A) ; - Ai = mxGetIr (A) ; - if (spumoni > 0) - { - mexPrintf (" input matrix A has %d nonzero entries\n", Ap [n]) ; - } - - /* --------------------------------------------------------------------- */ - /* order the matrix */ - /* --------------------------------------------------------------------- */ - - result = amd_order (n, Ap, Ai, P, Control, Info) ; - - /* --------------------------------------------------------------------- */ - /* if A is full, free the sparse copy of A */ - /* --------------------------------------------------------------------- */ - - if (full) - { - mxDestroyArray (A) ; - } - - /* --------------------------------------------------------------------- */ - /* print results (including return value) */ - /* --------------------------------------------------------------------- */ - - if (spumoni > 0) - { - amd_info (Info) ; - } - - /* --------------------------------------------------------------------- */ - /* check error conditions */ - /* --------------------------------------------------------------------- */ - - if (result == AMD_OUT_OF_MEMORY) - { - mexErrMsgTxt ("amd: out of memory") ; - } - else if (result == AMD_INVALID) - { - mexErrMsgTxt ("amd: input matrix A is corrupted") ; - } - - /* --------------------------------------------------------------------- */ - /* copy the outputs to MATLAB */ - /* --------------------------------------------------------------------- */ - - /* output permutation, P */ - plhs [0] = mxCreateDoubleMatrix (1, n, mxREAL) ; - Pout = mxGetPr (plhs [0]) ; - for (i = 0 ; i < n ; i++) - { - Pout [i] = P [i] + 1 ; /* change to 1-based indexing for MATLAB */ - } - mxFree (P) ; - - /* Info */ - if (nlhs > 1) - { - plhs [1] = mxCreateDoubleMatrix (AMD_INFO, 1, mxREAL) ; - InfoOut = mxGetPr (plhs [1]) ; - for (i = 0 ; i < AMD_INFO ; i++) - { - InfoOut [i] = Info [i] ; - } - } -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/MATLAB/can_24.mat Binary file liboctave/UMFPACK/AMD/MATLAB/can_24.mat has changed diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Make/Make.alpha --- a/liboctave/UMFPACK/AMD/Make/Make.alpha Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -#------------------------------------------------------------------------------ -# Compaq Alpha configuration (for both AMD and UMFPACK) -#------------------------------------------------------------------------------ - -# 64-bit mode only -CFLAGS = -O2 -std1 -DLP64 - -#------------------------------------------------------------------------------ -# BLAS options (UMFPACK only): -#------------------------------------------------------------------------------ - -# 1: with the vendor-supplied BLAS -CONFIG = -LIB = -ldxml -lm - -# 2: with the vendor-supplied BLAS, including BLAS with 64-bit long integers -# CONFIG = -DLONGBLAS -# LIB = -ldxml -lm - -# 2: with no BLAS (this will be slow) -# CONFIG = -DNBLAS -# LIB = -lm - diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Make/Make.include --- a/liboctave/UMFPACK/AMD/Make/Make.include Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -#------------------------------------------------------------------------------ -# Include file for GNU make or original make (for both AMD and UMFPACK) -#------------------------------------------------------------------------------ - -# You can edit these definitions, or select and and edit a specfic -# Make.(architecture) file, below. This same file is used for configuring -# both AMD and UMFPACK. AMD is a stand-alone package. UMFPACK requires AMD, -# and for simplicity of configuring both packages, UMFPACK and AMD share this -# configuration file (and all files in the AMD/Make directory). To configure -# AMD, or both AMD and UMFPACK, you only need to edit this one file (and -# optionaly, one of the ../Make/Make. files below). - -# NOTE: -DNBLAS and other BLAS configurations are ignored by AMD, since AMD -# does not use the BLAS. This flag is here because this file, and the -# ../Make/Make.* files, are shared by UMFPACK (which requires AMD). If you -# use AMD but not UMFPACK, then you can ignore any BLAS-related configuration -# settings. - -CFLAGS = -O -RANLIB = ranlib -LIB = -lm -RM = rm -f -MV = mv -f -F77 = f77 -F77FLAGS = -O -F77LIB = -AR = ar - -#------------------------------------------------------------------------------ -# for the AMD and UMFPACK mexFunctions (-DNBLAS and -DNUTIL for UMFPACK only) -#------------------------------------------------------------------------------ - -# MATLAB 6.0 or later (default) -MEX = mex -inline -O - -# MATLAB 6.0 or later (no divide-by-zero) -# MEX = mex -inline -O -DNO_DIVIDE_BY_ZERO - -# MATLAB 5 (no BLAS, do not try to use utMalloc, utFree, and utRealloc) -# MEX = mex -inline -O -DNBLAS -DNUTIL - -#------------------------------------------------------------------------------ -# for UMFPACK only (BLAS configuration): -#------------------------------------------------------------------------------ - -# The default is to NOT use the BLAS. UMFPACK will be slow, but this is more -# portable. Try this option first, then use your architecture-specific -# configuration, below, to add the BLAS library. AMD ignores the -DNBLAS flag. - -CONFIG = -DNBLAS - -#------------------------------------------------------------------------------ -# Archicture-specific configuration (for both AMD and UMFPACK) -#------------------------------------------------------------------------------ - -# Select your architecture by un-commenting the appropriate line. The include -# file can redefine any of the above definitions, or other definitions. Use -# CC = ... to redefine the name of your C compiler, for example. Without -# any specific changes, this Makefile should work on nearly all systems. - -# include ../Make/Make.linux -# include ../Make/Make.sgi -# include ../Make/Make.solaris -# include ../Make/Make.alpha -# include ../Make/Make.rs6000 - -#------------------------------------------------------------------------------ -# remove object files and profile output -#------------------------------------------------------------------------------ - -clean: - - $(RM) *.o *.obj *.ln *.bb *.bbg *.da *.c.tcov *.c.gcov gmon.out *.bak diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Make/Make.linux --- a/liboctave/UMFPACK/AMD/Make/Make.linux Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -#------------------------------------------------------------------------------ -# Linux configuration (for both AMD and UMFPACK) -#------------------------------------------------------------------------------ - -# You may also need to add -lunwind -lcprts to the LIB= string, -# if you use the Intel compiler and the Fortran BLAS. - -# Using GNU gcc and f77 compilers: - CC = gcc - CFLAGS = -O3 -fPIC - -# Using Intel's icc and ifc compilers: -# F77 = ifc -# CC = icc -# CFLAGS = -ansi -O3 -ip -tpp7 -xW -vec_report0 -# CFLAGS = -pg -g - -# Using gcc compiler with picky tests -# CC = gcc -# CFLAGS = -ansi -pedantic -W -Wall -Wno-parentheses -Wshadow -Wcast-align -Winline -Wstrict-prototypes -Wno-unknown-pragmas -O3 -fPIC - -# for gcc and gcov: -# CC = gcc -# CFLAGS = -pg -ftest-coverage -fprofile-arcs - -# Running splint -# CC = - splint -# CFLAGS = -weak -fixedformalarray -badflag -fileextensions +relaxtypes +posixlib -unrecog - -#------------------------------------------------------------------------------ -# BLAS options (for UMFPACK only) -#------------------------------------------------------------------------------ - -# 1: with no BLAS (this will be slow) -# CONFIG = -DNBLAS -# LIB = -lm - -# 2: with the ATLAS C-BLAS (http://www.netlib.org/atlas). -# CONFIG = -DCBLAS -I../ATLAS/include -# LIB = -lcblas -latlas -lm - -# 3: with Fortran interface to the ATLAS BLAS -# CONFIG = -# LIB = -lf77blas -latlas -lfrtbegin -lg2c -lm - -# 4: with Fortran interface to the BLAS, and Goto's BLAS - CONFIG = - LIB = -lgoto -lxerbla -lfrtbegin -lg2c -lm - -# 5: with Fortran interface to the BLAS, and Goto's BLAS, and no divide-by-zero -# CONFIG = -DNO_DIVIDE_BY_ZERO -# LIB = -lgoto -lxerbla -lfrtbegin -lg2c -lm diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Make/Make.rs6000 --- a/liboctave/UMFPACK/AMD/Make/Make.rs6000 Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -#------------------------------------------------------------------------------ -# IBM RS 6000 configuration (for both AMD and UMFPACK) -#------------------------------------------------------------------------------ - -# 32-bit mode: -CFLAGS = -O4 -qipa -qmaxmem=16384 -qproto -F77FLAGS = -O4 -qipa -qmaxmem=16384 - -# 64-bit mode: -# CFLAGS = -O4 -qipa -qmaxmem=16384 -q64 -DLP64 -qproto -# F77FLAGS = -O4 -qipa -qmaxmem=16384 -q64 -DLP64 -# AR = ar -X64 - -#------------------------------------------------------------------------------ -# BLAS options (for UMFPACK only): -#------------------------------------------------------------------------------ - -# 1: with the vendor-supplied BLAS. This is the default. -CONFIG = -LIB = -lessl -lm - -# 2: with no BLAS (this will be slow) -# CONFIG = -DNBLAS -# LIB = -lm diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Make/Make.sgi --- a/liboctave/UMFPACK/AMD/Make/Make.sgi Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -#------------------------------------------------------------------------------ -# SGI IRIX configuration (for both AMD and UMFPACK) -#------------------------------------------------------------------------------ - -# Default: 32-bit mode -# CFLAGS = - -# 64-bit mode (32 bit int's and 64-bit long's): -# CFLAGS = -DLP64 -64 -# F77FLAGS = -64 - -# SGI doesn't have ranlib -RANLIB = echo - -#------------------------------------------------------------------------------ -# BLAS options (for UMFPACK only): -#------------------------------------------------------------------------------ - -# 1: Default: with 32-bit int's and long's, and the 32-bit SCSL BLAS -CONFIG = -LIB = -lscs -lm - -# 2,3: with no BLAS (32 bit or 64 bit mode) -# CONFIG = -DNBLAS -# LIB = -lm - -# 4: 64 bit mode, with 64-bit SCSL BLAS. -# CONFIG = -# LIB = -lscs_i8 -lm - -# 5: 32 bit mode, with the Fortran interface to the vendor-supplied BLAS -# CONFIG = -DNSCSL -# LIB = -lblas -lm - -# 6: 32 bit mode, with the C-BLAS interface to the vendor-supplied BLAS -# CONFIG = -DCBLAS -# LIB = -lblas -lm - diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Make/Make.solaris --- a/liboctave/UMFPACK/AMD/Make/Make.solaris Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -#------------------------------------------------------------------------------ -# Sun Solaris configuration (for both AMD and UMFPACK) -#------------------------------------------------------------------------------ - -# 32-bit mode: -CC = cc -CFLAGS = -Xc -xO5 -KPIC -dalign -native -F77FLAGS = -xO5 -KPIC -dalign -native - -# 64-bit mode: -# CC = cc -# CFLAGS = -Xc -xO5 -KPIC -dalign -native -DLP64 -xtarget=ultra -xarch=v9 -# F77FLAGS = -xO5 -KPIC -dalign -native -DLP64 -xtarget=ultra -xarch=v9 - -#------------------------------------------------------------------------------ -# BLAS options (for UMFPACK only): -#------------------------------------------------------------------------------ - -# 1: Default: with the Sun Performance BLAS in 32-bit mode -CONFIG = -LIB = -lsunperf -lfai -lfsu -lfui -lsunperf -lm -lF77 -lm -lM77 -lsunmath - -# 2,3: with no BLAS (32-bit or 64-bit mode) -# CONFIG = -DNBLAS -# LIB = -lm - -# 4: the Sun Performance BLAS in 64-bit mode -# CONFIG = -# LIB = -lsunperf -lfai -lfsu -lfui -lsunperf -lm - -# 5: with the C-BLAS (http://www.netlib.org/atlas) in the ../ATLAS directory. -# CONFIG = -DCBLAS -I../ATLAS/include -# LIB = -L../ATLAS/lib/SunOS_SunUS1/ -lcblas -latlas -lm - diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Makefile --- a/liboctave/UMFPACK/AMD/Makefile Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -#------------------------------------------------------------------------------ -# AMD Makefile (for GNU Make or original make) -#------------------------------------------------------------------------------ - -# Compile everything, including the C-callable routine and the mexFunctions. -# Do not compile the FORTRAN versions. -all: - ( cd Source ; make ) - ( cd Demo ; make ) - ( cd MATLAB ; make ) - - cat Doc/License - -# compile just the C-callable libraries and demo programs (not mexFunctions) -lib: - ( cd Source ; make ) - ( cd Demo ; make ) - - cat Doc/License - -# compile the FORTRAN libraries and demo programs (not compiled by "make all") -fortran: - ( cd Source ; make fortran ) - ( cd Demo ; make fortran ) - - cat Doc/License - -# compile a FORTRAN demo program that calls the C version of AMD -# (not compiled by "make all") -cross: - ( cd Demo ; make cross ) - - cat Doc/License - -# compile a Octave version -# (not compiled by "make all") -octave: - ( cd OCTAVE ; make ) - - cat Doc/License - -# remove object files, but keep the compiled programs and library archives -clean: - ( cd Source ; make clean ) - ( cd Demo ; make clean ) - ( cd MATLAB ; make clean ) - ( cd OCTAVE ; make clean ) - ( cd Doc ; make clean ) - -# clean, and then remove compiled programs and library archives -purge: - ( cd Source ; make purge ) - ( cd Demo ; make purge ) - ( cd MATLAB ; make purge ) - ( cd OCTAVE ; make purge ) - ( cd Doc ; make purge ) - -# create PDF documents for the original distribution -doc: - ( cd Doc ; make ) - -# get ready for distribution -dist: purge - ( cd Demo ; make dist ) - ( cd Doc ; make ) diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/OCTAVE/GNUmakefile --- a/liboctave/UMFPACK/AMD/OCTAVE/GNUmakefile Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -#------------------------------------------------------------------------------ -# GNUmakefile for the AMD MATLAB mexFunction -#------------------------------------------------------------------------------ - -all: amd - -include ../Make/Make.include - -MKOCT = mkoctfile -I../Include - -OCT_SPARSE_INC = -I../../../ - -AMD = amd_aat amd_1 amd_2 amd_dump amd_postorder amd_post_tree amd_defaults \ - amd_order amd_control amd_info amd_valid - -INC = ../Include/amd.h ../Source/amd_internal.h - -OCTAMD = $(addsuffix .o, $(subst amd_,amd_o_,$(AMD))) - -amd_o_%.o: ../Source/amd_%.c $(INC) - $(MKOCT) -DDINT -c $< -o $@ - - $(MV) ../Source/amd_$*.o - -# Note temporary addition of octave sparse path -amd: amd.cc $(OCTAMD) $(INC) - $(MKOCT) amd.cc $(OCTAMD) $(OCT_SPARSE_INC) -o amd.oct - -#------------------------------------------------------------------------------ -# Remove all but the files in the original distribution -#------------------------------------------------------------------------------ - -purge: clean - - $(RM) amd.oct diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/OCTAVE/Makefile --- a/liboctave/UMFPACK/AMD/OCTAVE/Makefile Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -#------------------------------------------------------------------------------ -# compile the AMD mexFunction for MATLAB (original make only) -#------------------------------------------------------------------------------ - -# This is a very ugly Makefile, and is only provided for those who do not -# have GNU make. Note that it is not used if you have GNU make. It ignores -# dependency checking and just compiles everything. It was created -# automatically, via make -n using the GNUmakefile. That way, I don't have -# maintain two Makefiles. - -all: amd - -include ../Make/Make.include - -MKOCT = mkoctfile -I../Include - -OCT_SPARSE_INC = ../../../ - -amd: - $(MKOCT) -DDINT -o amd_o_aat.o -c ../Source/amd_aat.c - $(MKOCT) -DDINT -o amd_o_1.o -c ../Source/amd_1.c - $(MKOCT) -DDINT -o amd_o_2.o -c ../Source/amd_2.c - $(MKOCT) -DDINT -o amd_o_dump.o -c ../Source/amd_dump.c - $(MKOCT) -DDINT -o amd_o_postorder.o -c ../Source/amd_postorder.c - $(MKOCT) -DDINT -o amd_o_post_tree.o -c ../Source/amd_post_tree.c - $(MKOCT) -DDINT -o amd_o_defaults.o -c ../Source/amd_defaults.c - $(MKOCT) -DDINT -o amd_o_order.o -c ../Source/amd_order.c - $(MKOCT) -DDINT -o amd_o_control.o -c ../Source/amd_control.c - $(MKOCT) -DDINT -o amd_o_info.o -c ../Source/amd_info.c - $(MKOCT) -DDINT -o amd_o_valid.o -c ../Source/amd_valid.c - $(MKOCT) -output amd.oct amd_mex.c amd_o_aat.o \ - amd_o_1.o amd_o_2.o amd_o_dump.o amd_o_postorder.o \ - amd_o_post_tree.o amd_o_defaults.o amd_o_order.o amd_o_control.o \ - amd_o_info.o amd_o_valid.o $(OCT_SPARSE_INC) -o amd.oct - -#------------------------------------------------------------------------------ -# Remove all but the files in the original distribution -#------------------------------------------------------------------------------ - -purge: clean - - $(RM) amd.oct diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/OCTAVE/amd.cc --- a/liboctave/UMFPACK/AMD/OCTAVE/amd.cc Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,299 +0,0 @@ -/* - -Copyright (C) 2004 David Bateman - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -This program 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 General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -In addition to the terms of the GPL, you are permitted to link -this program with any Open Source program, as defined by the -Open Source Initiative (www.opensource.org) - -*/ - -/* - -This is the Octave interface to the UMFPACK AMD code, which bore the following -copyright - - AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, - Patrick R. Amestoy, and Iain S. Duff. See ../README for License. - email: davis@cise.ufl.edu CISE Department, Univ. of Florida. - web: http://www.cise.ufl.edu/research/sparse/amd - -------------------------------------------------------------------------- - - Acknowledgements: This work was supported by the National Science - Foundation, under grants ASC-9111263, DMS-9223088, and CCR-0203270. - -*/ - -#include -#include - -#include -#include -#include -#include -#include - -#include "ov-re-sparse.h" -#include "ov-cx-sparse.h" - -// External AMD functions in C -extern "C" { -#include "amd.h" -} - -DEFUN_DLD (amd, args, nargout, - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {@var{p} =} amd (@var{s})\n\ -@deftypefnx {Loadable Function} {@var{Control} =} amd ()\n\ -@deftypefnx {Loadable Function} {[@var{p}, @var{info}] =} amd (@var{s})\n\ -\n\ -AMD Approximate minimum degree permutation. Returns the approximate\n\ -minimum degree permutation vector for the sparse matrix\n\ -@code{@var{c} = @var{S} + @var{S}'}. The Cholesky factorization of\n\ -@code{@var{c} (@var{p}, @var{p})}, or @code{@var{s} (@var{p}, @var{p})},\n\ -tends to be sparser than that of @var{c} or @var{s}.\n\ -@var{s} must be square. If @var{s} is full, @code{amd (@var{S})} is\n\ -equivalent to @code{amd (sparse (@var{s}))}.\n\ -\n\ -@table @asis\n\ -@item @var{Control} (1)\n\ -If S is n-by-n, then rows/columns with more than\n\ -@code{@dfn{max} (16, (@var{Control} (1)) * @dfn{sqrt} (@var{n}))} entries\n\ -in @code{@var{s} + @var{S}'} are considered @emph{dense}, and ignored during\n\ -ordering. They are placed last in the output permutation. The default is\n\ -10.0 if @var{Control} is not present.\n\ -@item @var{Control} (2)\n\ -If nonzero, then aggressive absorption is performed. This is the default if\n\ -@var{Control} is not present.\n\ -@item @var{Control} (3)\n\ -If nonzero, print statistics about the ordering.\n\ -@end table\n\ -\n\ -@table @asis\n\ -@item @var{Info} (1)\n\ -status (0: ok, -1: out of memory, -2: matrix invalid)\n\ -@item @var{Info} (2)\n\ -@code{@var{n} = size (@var{a}, 1)}\n\ -@item @var{Info} (3)\n\ -@code{nnz (A)}\n\ -@item @var{Info} (4)\n\ -The symmetry of the matrix @var{s} (0.0 means purely unsymmetric, 1.0 means\n\ -purely symmetric). Computed as: @code{@var{b} = tril (@var{s}, -1) +\n\ -triu (@var{s}, 1); @var{symmetry} = nnz (@var{b} & @var{b}')\n\ -/ nnz (@var{b});}\n\ -@item @var{Info} (5)\n\ -@code{nnz (diag (@var{s}))}\n\ -@item @var{Info} (6)\n\ -@dfn{nnz} in @code{@var{s} + @var{s}'}, excluding the diagonal\n\ -(= @code{nnz (@var{b} + @var{b}')})\n\ -@item @var{Info} (7)\n\ -Number of @emph{dense} rows/columns in @code{@var{s} + @var{s}'}\n\ -@item @var{Info} (8)\n\ -The amount of memory used by AMD, in bytes\n\ -@item @var{Info} (9)\n\ -The number of memory compactions performed by AMD\n\ -@end table\n\ -\n\ -The following statistics are slight upper bounds because of the\n\ -approximate degree in AMD. The bounds are looser if @emph{dense}\n\ -rows/columns are ignored during ordering @code{(@var{Info} (7) > 0)}.\n\ -The statistics are for a subsequent factorization of the matrix\n\ -@code{@var{c} (@var{p},@var{p})}. The LU factorization statistics assume\n \ -no pivoting.\n\ -\n\ -@table @asis\n\ -@item @var{Info} (10)\n\ -The number of nonzeros in L, excluding the diagonal\n\ -@item @var{Info} (11)\n\ -The number of divide operations for LL', LDL', or LU\n\ -@item @var{Info (12)}\n\ -The number of multiply-subtract pairs for LL' or LDL'\n\ -@item @var{Info} (13)\n\ -The number of multiply-subtract pairs for LU\n\ -@item @var{Info} (14)\n\ -The max number of nonzeros in any column of L (incl. diagonal)\n\ -@item @var{Info} (15:20)\n\ -unused, reserved for future use\n\ -@end table\n\ -\n\ -An assembly tree post-ordering is performed, which is typically the same\n\ -as an elimination tree post-ordering. It is not always identical because\n\ -of the approximate degree update used, and because @emph{dense} rows/columns\n\ -do not take part in the post-order. It well-suited for a subsequent\n\ -@dfn{chol}, however. If you require a precise elimination tree\n\ -post-ordering, then do:\n\ -\n\ -@group\n\ - @var{p} = @dfn{amd} (@var{s});\n\ - % skip this if S already symmetric\n\ - @var{c} = spones (@var{s}) + spones (@var{s}');\n\ - [@var{ignore}, @var{q}] = sparsfun ('symetree', @var{c} (@var{p}, @var{p}));\n\ - @var{p} = @var{p} (@var{q});\n\ -@end group\n\ -\n\ -AMD Version 1.1 (Jan. 21, 2004), Copyright @copyright{} 2004 by\n\ -Timothy A. Davis, Patrick R. Amestoy, and Iain S. Duff.\n\ -\n\ -email: davis@@cise.ufl.edu (CISE Department, Univ. of Florida).\n\ -\n\ -web: http://www.cise.ufl.edu/research/sparse/amd\n\ -\n\ -Acknowledgements: This work was supported by the National Science\n\ -Foundation, under grants ASC-9111263, DMS-9223088, and CCR-0203270.\n\ -@end deftypefn") -{ - int nargin = args.length (); - octave_value_list retval; - int spumoni = 0; - - if (nargin > 2 || nargout > 2) - usage ("p = amd (A) or [p, Info] = amd (A, Control)"); - else if (nargin == 0) - { - // Get the default control parameter, and return - NDArray control (dim_vector (AMD_CONTROL, 1)); - double *control_ptr = control.fortran_vec (); - amd_defaults (control_ptr); - if (nargout == 0) - amd_control (control_ptr); - else - retval(0) = control; - } - else - { - NDArray control (dim_vector (AMD_CONTROL, 1)); - double *control_ptr = control.fortran_vec (); - amd_defaults (control_ptr); - - if (nargin > 1) - { - NDArray control_in = args(1).array_value(); - - if (error_state) - { - error ("amd: could not read control vector"); - return retval; - } - - dim_vector dv = control_in.dims (); - if (dv.length() > 2 || (dv(0) != 1 && dv(1) != 1)) - { - error ("amd: control vector isn't a vector"); - return retval; - } - - int nc = dv.numel (); - control (AMD_DENSE) = (nc > 0 ? control_in (AMD_DENSE) : - AMD_DEFAULT_DENSE); - control (AMD_AGGRESSIVE) = (nc > 1 ? control_in (AMD_AGGRESSIVE) : - AMD_DEFAULT_AGGRESSIVE); - spumoni = (nc > 2 ? (control_in (2) != 0) : 0); - } - - if (spumoni > 0) - amd_control (control_ptr); - - int *Ap, *Ai; - int n, m, nz; - - // These are here only so that the C++ destructors don't prematurally - // remove the underlying data we are interested in - SparseMatrix sm; - SparseComplexMatrix scm; - Matrix mm; - ComplexMatrix cm; - - if (args(0).class_name () != "sparse" && spumoni > 0) - octave_stdout << " input matrix A is full (sparse copy" - << " of A will be created)" << std::endl; - - if (args(0).is_complex_type ()) - { - scm = args(0).sparse_complex_matrix_value (); - Ai = scm.ridx (); - Ap = scm.cidx (); - m = scm.rows (); - n = scm.cols (); - nz = scm.nnz (); - } - else - { - sm = args(0).sparse_matrix_value (); - Ai = sm.ridx (); - Ap = sm.cidx (); - m = sm.rows (); - n = sm.cols (); - nz = sm.nnz (); - } - - if (spumoni > 0) - octave_stdout << " input matrix A is " << m << "-by-" << n - << std::endl; - - if (m != n) - { - error ("amd: A must be square"); - return retval; - } - - if (spumoni > 0) - octave_stdout << " input matrix A has " << nz << - " nonzero entries" << std::endl; - - // allocate workspace for output permutation - Array P(n+1); - int *P_ptr = P.fortran_vec (); - NDArray info (dim_vector (AMD_INFO, 1)); - double *info_ptr = info.fortran_vec (); - int result; - - // order the matrix - result = amd_order (n, Ap, Ai, P_ptr, control_ptr, info_ptr); - - // print results (including return value) - if (spumoni > 0) - amd_info (info_ptr); - - // check error conditions - if (result == AMD_OUT_OF_MEMORY) - error ("amd: out of memory"); - else if (result == AMD_INVALID) - error ("amd: input matrix A is corrupted"); - else - { - // copy the outputs to Octave - - // output permutation, P - NDArray perm (dim_vector (1, n)); - for (int i = 0; i < n; i++) - perm (i) = double (P(i) + 1); // 1-based indexing for Octave - - retval (0) = perm; - - // Info - if (nargout > 1) - retval (1) = info; - } - } - return retval; -} - -/* -;;; Local Variables: *** -;;; mode: C++ *** -;;; End: *** -*/ diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/OCTAVE/amd_demo.m --- a/liboctave/UMFPACK/AMD/OCTAVE/amd_demo.m Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -function amd_demo -% AMD DEMO -% -% A demo of AMD for OCTAVE. -% -% -------------------------------------------------------------------------- -% AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, -% Patrick R. Amestoy, and Iain S. Duff. See ../README for License. -% email: davis@cise.ufl.edu CISE Department, Univ. of Florida. -% web: http://www.cise.ufl.edu/research/sparse/amd -% -------------------------------------------------------------------------- -% -% See also: amd - -% Get the Harwell/Boeing can_24 matrix. This is an example matrix from the -% MATLAB-accessible UF sparse matrix collection, and can be loaded into -% MATLAB with the statment "Problem = UFget ('HB/can_24')", after obtaining -% the UFget function and its supporting routines at -% http://www.cise.ufl.edu/sparse/mat . - -load can_24.mat -A = Problem.A ; -n = size (A,1) ; - -figure (1) -clf -hold off -subplot (2,1,1) ; -% remove the "_" from the name before printing it in the plot title -title (sprintf ('%s', strrep (Problem.name, '_', '-'))) ; -fprintf ('Matrix name: %s\n', Problem.name) ; -fprintf ('Matrix title: %s\n', Problem.title) ; -spy (A) - -% print the details during AMD ordering and SYMBFACT -control = amd (); -control (3) = 1; - -% order the matrix. Note that the Info argument is optional. -fprintf ('\nIf the next step fails, then you have\n') ; -fprintf ('not yet compiled the AMD mexFunction.\n') ; -[p, Info] = amd (A, control) ; - -% order again, but this time print some statistics -[p, Info] = amd (A, [10 1 1]) ; - -fprintf ('Permutation vector:\n') ; -fprintf (' %2d', p) ; -fprintf ('\n\n') ; - -subplot (2,1,2) ; -title ('Permuted matrix') ; -spy (A (p,p)) - -% approximations from amd: -lnz2 = n + Info (10) ; -fl2 = n + Info (11) + 2 * Info (12) ; -fprintf ('\nResults from AMD''s approximate analysis:\n') ; -fprintf ('number of nonzeros in L (including diagonal): %d\n', lnz2) ; -fprintf ('floating point operation count for chol (A (p,p)): %d\n\n', fl2) ; - diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/OCTAVE/amd_demo.m.out --- a/liboctave/UMFPACK/AMD/OCTAVE/amd_demo.m.out Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -octave:3> amd_demo -ans = 1 -Matrix name: HB/can_24 -Matrix title: 1SYMMETRIC PATTERN FROM CANNES,LUCIEN MARRO,JUNE 1981. - -If the next step fails, then you have -not yet compiled the AMD mexFunction. - input matrix A is 24-by-24 - input matrix A has 160 nonzero entries - input matrix A is 24-by-24 - input matrix A has 160 nonzero entries -Permutation vector: - 23 21 11 24 13 6 17 9 15 5 16 8 2 10 14 18 1 3 4 7 12 19 22 20 - - -Results from AMD's approximate analysis: -number of nonzeros in L (including diagonal): 121 -floating point operation count for chol (A (p,p)): 671 - -octave:4> quit diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/OCTAVE/can_24.mat Binary file liboctave/UMFPACK/AMD/OCTAVE/can_24.mat has changed diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/README.txt --- a/liboctave/UMFPACK/AMD/README.txt Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,202 +0,0 @@ -AMD version 1.1: a set of routines for permuting sparse matrices prior to - factorization. Includes a version in C, a version in Fortran, and a MATLAB - mexFunction. - -Quick start (Unix, or Windows with Cygwin): - - To compile, test, and install AMD, you may wish to first configure the - installation by editting the AMD/Make/Make.include file. Next, cd to this - directory (AMD) and type "make" (or "make lib" if you do not have MATLAB). - To compile and run a demo program for the Fortran version, type - "make fortran". When done, type "make clean" to remove unused *.o files - (keeps the compiled libraries and demo programs). See the User Guide - (Doc/AMD_UserGuide.pdf), or AMD/Make/Make.include, for more details. - -Quick start (for MATLAB users); - - To compile, test, and install the AMD mexFunction, cd to the - AMD/MATLAB directory and type amd_make at the MATLAB prompt. - This works on any system supported by MATLAB. - -------------------------------------------------------------------------------- - -AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. -Davis, Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. - -AMD License: - - Your use or distribution of AMD or any modified version of - AMD implies that you agree to this License. - - 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 or copy this program, 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 AMD or any modified version of AMD 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. This - software was developed with support from the National Science Foundation, - and is provided to you free of charge. - -Availability: - - http://www.cise.ufl.edu/research/sparse/amd - -------------------------------------------------------------------------------- - -This is the AMD Version 1.1 README file. It is a terse overview of AMD. -Refer to the User Guide (Doc/AMD_UserGuide.pdf) for how to install and use AMD. - -Description: - - AMD is a set of routines for pre-ordering sparse matrices prior to Cholesky - or LU factorization, using the approximate minimum degree ordering - algorithm. Written in ANSI/ISO C with a MATLAB interface, and in - Fortran 77. - -Authors: - - Timothy A. Davis (davis@cise.ufl.edu), University of Florida. - Patrick R. Amestory, ENSEEIHT, Toulouse, France. - Iain S. Duff, Rutherford Appleton Laboratory, UK. - -Acknowledgements: - - This work was supported by the National Science Foundation, under - grants DMS-9504974, DMS-9803599, and CCR-0203270. - - Portions of this work were done while on sabbatical at Stanford University - and Lawrence Berkeley National Laboratory (with funding from the SciDAC - program). I would like to thank Gene Golub, Esmond Ng, and Horst Simon - for making this sabbatical possible. - -------------------------------------------------------------------------------- -Files and directories in the AMD v1.0 distribution: -------------------------------------------------------------------------------- - - --------------------------------------------------------------------------- - Subdirectories of the AMD directory: - --------------------------------------------------------------------------- - - Doc documentation - Make for compiling AMD - Source primary source code - Include include file for use in your code that calls AMD - Demo demo programs. also serves as test of the AMD installation. - MATLAB AMD mexFunction for MATLAB, and supporting m-files - Lib where the compiled C-callable and Fortran-callable - AMD libraries placed. - - --------------------------------------------------------------------------- - Files in the AMD directory: - --------------------------------------------------------------------------- - - Makefile top-level Makefile for GNU make or original make. - Windows users would require Cygwin to use "make" - - README this file - - --------------------------------------------------------------------------- - Doc directory: documentation - --------------------------------------------------------------------------- - - ChangeLog change log - License the AMD License - Makefile for creating the documentation - AMD_UserGuide.bib AMD User Guide (references) - AMD_UserGuide.tex AMD User Guide (LaTeX) - AMD_UserGuide.pdf AmD User Guide (PDF) - - --------------------------------------------------------------------------- - Make directory: for compiling AMD (Lib/libamd.a and Lib/libamdf77.a) - --------------------------------------------------------------------------- - - Make.include overall configurations. Can use one of: - Make.alpha Makefile additions for Compaq Alpha - Make.linux Makefile additions for Linux - Make.rs6000 Makefile additions for RS 6000 - Make.sgi Makefile additions for SGI - Make.solaris Makefile additions for Solaris - - --------------------------------------------------------------------------- - Source directory: - --------------------------------------------------------------------------- - - GNUmakefile a nice Makefile, for GNU make - Makefile an ugly Unix Makefile (for older make's) - - amd_order.c user-callable, primary AMD ordering routine - amd_control.c user-callable, prints the control parameters - amd_defaults.c user-callable, sets default control parameters - amd_info.c user-callable, prints the statistics from AMD - - amd_1.c non-user-callable, construct A+A' - amd_2.c non-user-callable, primary ordering kernel - (a C version of amd.f and amdbar.f, with - post-ordering added) - amd_aat.c non-user-callable, computes nnz (A+A') - amd_dump.c non-user-callable, debugging routines - amd_internal.h non-user-callable, include file for AMD - amd_mex.c non-user-callable, MATLAB mexFunction - amd_postorder.c non-user-callable, postorder - amd_post_tree.c non-user-callable, postorder just one tree - amd_valid.c non-user-callable, verifies a matrix - - amd.f user-callable Fortran 77 version - amdbar.f user-callable Fortran 77 version - - --------------------------------------------------------------------------- - Include directory: - --------------------------------------------------------------------------- - - amd.h include file for C programs that use AMD - - --------------------------------------------------------------------------- - Demo directory: - --------------------------------------------------------------------------- - - Makefile for GNU make or original make - - amd_demo.c C demo program for AMD - amd_demo.out output of amd_demo.c - - amd_simple.c simple C demo program for AMD - amd_simple.out output of amd_simple.c - - amd_f77demo.f Fortran 77 demo program for AMD - amd_f77demo.out output of amd_f77demo.f - - amd_f77simple.c simple Fortran 77 demo program for AMD - amd_f77simple.out output of amd_f77simple.f - - amd_f77cross.f Fortran 77 demo, calls the C version of AMD - amd_f77cross.out output of amd_f77cross.f - amd_f77wrapper.c Fortran-callable wrapper for C version of AMD - - --------------------------------------------------------------------------- - MATLAB directory: - --------------------------------------------------------------------------- - - GNUmakefile a nice Makefile, for GNU make - Makefile an ugly Unix Makefile (for older make's) - - Contents.m for "help amd" listing of toolbox contents - - amd.m MATLAB help file for AMD - amd_make.m MATLAB m-file for compiling AMD mexFunction - - amd_mex.c AMD mexFunction for MATLAB - - amd_demo.m MATLAB demo for AMD - amd_demo.m.out diary output of amd_demo.m - can_24.mat input file for AMD demo - - --------------------------------------------------------------------------- - Lib directory: libamd.a and libamdf77.a libraries placed here - --------------------------------------------------------------------------- - - libamd.def AMD definitions for Windows diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/GNUmakefile --- a/liboctave/UMFPACK/AMD/Source/GNUmakefile Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -#------------------------------------------------------------------------------- -# AMD Makefile for compiling on Unix systems (for GNU make only) -#------------------------------------------------------------------------------- - -all: ../Lib/libamd.a - -include ../Make/Make.include - -C = $(CC) $(CFLAGS) $(CONFIG) -I../Include - -#------------------------------------------------------------------------------- -# source files -#------------------------------------------------------------------------------- - -AMD = amd_aat amd_1 amd_2 amd_dump amd_postorder amd_post_tree amd_defaults \ - amd_order amd_control amd_info amd_valid amd_preprocess - -INC = ../Include/amd.h amd_internal.h - -#------------------------------------------------------------------------------- -# object files for each version -#------------------------------------------------------------------------------- - -AMDI = $(addsuffix .o, $(subst amd_,amd_i_,$(AMD))) -AMDL = $(addsuffix .o, $(subst amd_,amd_l_,$(AMD))) - -#------------------------------------------------------------------------------- -# compile each int and long routine (with no real/complex version) -#------------------------------------------------------------------------------- - -amd_i_%.o: amd_%.c $(INC) - $(C) -DDINT -c $< -o $@ - -amd_l_%.o: amd_%.c $(INC) - $(C) -DDLONG -c $< -o $@ - -#------------------------------------------------------------------------------- -# Create the libamd.a library (C versions only) -#------------------------------------------------------------------------------- - -../Lib/libamd.a: $(AMDI) $(AMDL) - $(AR) cr ../Lib/libamd.a $^ - - $(RANLIB) ../Lib/libamd.a - -#------------------------------------------------------------------------------- -# compile the Fortran versions and the libamdf77.a library -#------------------------------------------------------------------------------- - -fortran: ../Lib/libamdf77.a - -AMDF77 = amd.o amdbar.o - -amd.o: amd.f - $(F77) $(F77FLAGS) -c amd.f -o amd.o - -amdbar.o: amdbar.f - $(F77) $(F77FLAGS) -c amdbar.f -o amdbar.o - -../Lib/libamdf77.a: $(AMDF77) - $(AR) cr ../Lib/libamdf77.a $^ - - $(RANLIB) ../Lib/libamdf77.a - -#------------------------------------------------------------------------------- -# Remove all but the files in the original distribution -#------------------------------------------------------------------------------- - -purge: clean - - $(RM) ../Lib/libamd.a ../Lib/libamdf77.a diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/Makefile --- a/liboctave/UMFPACK/AMD/Source/Makefile Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -#------------------------------------------------------------------------------- -# AMD Makefile for compiling on Unix systems (for original Make ONLY) -#------------------------------------------------------------------------------- - -# This is a very ugly Makefile, and is only provided for those who do not -# have GNU make. Note that it is not used if you have GNU make. It ignores -# dependency checking and just compiles everything. It was created -# automatically, via make -n using the GNUmakefile. That way, I don't have -# maintain two Makefiles. - -all: everything - -include ../Make/Make.include - -C = $(CC) $(CFLAGS) $(CONFIG) -I../Include - -everything: - $(C) -DDINT -c amd_aat.c -o amd_i_aat.o - $(C) -DDINT -c amd_1.c -o amd_i_1.o - $(C) -DDINT -c amd_2.c -o amd_i_2.o - $(C) -DDINT -c amd_dump.c -o amd_i_dump.o - $(C) -DDINT -c amd_postorder.c -o amd_i_postorder.o - $(C) -DDINT -c amd_post_tree.c -o amd_i_post_tree.o - $(C) -DDINT -c amd_defaults.c -o amd_i_defaults.o - $(C) -DDINT -c amd_order.c -o amd_i_order.o - $(C) -DDINT -c amd_control.c -o amd_i_control.o - $(C) -DDINT -c amd_info.c -o amd_i_info.o - $(C) -DDINT -c amd_valid.c -o amd_i_valid.o - $(C) -DDINT -c amd_preprocess.c -o amd_i_preprocess.o - $(C) -DDLONG -c amd_aat.c -o amd_l_aat.o - $(C) -DDLONG -c amd_1.c -o amd_l_1.o - $(C) -DDLONG -c amd_2.c -o amd_l_2.o - $(C) -DDLONG -c amd_dump.c -o amd_l_dump.o - $(C) -DDLONG -c amd_postorder.c -o amd_l_postorder.o - $(C) -DDLONG -c amd_post_tree.c -o amd_l_post_tree.o - $(C) -DDLONG -c amd_defaults.c -o amd_l_defaults.o - $(C) -DDLONG -c amd_order.c -o amd_l_order.o - $(C) -DDLONG -c amd_control.c -o amd_l_control.o - $(C) -DDLONG -c amd_info.c -o amd_l_info.o - $(C) -DDLONG -c amd_valid.c -o amd_l_valid.o - $(C) -DDLONG -c amd_preprocess.c -o amd_l_preprocess.o - $(AR) cr ../Lib/libamd.a amd_i_aat.o amd_i_1.o amd_i_2.o amd_i_dump.o \ - amd_i_postorder.o amd_i_post_tree.o amd_i_defaults.o amd_i_order.o \ - amd_i_control.o amd_i_info.o amd_i_valid.o amd_l_aat.o amd_l_1.o \ - amd_l_2.o amd_l_dump.o amd_l_postorder.o amd_l_post_tree.o \ - amd_l_defaults.o amd_l_order.o amd_l_control.o amd_l_info.o \ - amd_l_valid.o amd_i_preprocess.o amd_l_preprocess.o - - $(RANLIB) ../Lib/libamd.a - -#------------------------------------------------------------------------------- -# compile the Fortran versions and the libamdf77.a library -#------------------------------------------------------------------------------- - -fortran: - $(F77) $(F77FLAGS) -c amd.f -o amd.o - $(F77) $(F77FLAGS) -c amdbar.f -o amdbar.o - $(AR) cr ../Lib/libamdf77.a amd.o amdbar.o - - $(RANLIB) ../Lib/libamdf77.a - -#------------------------------------------------------------------------------- -# Remove all but the files in the original distribution -#------------------------------------------------------------------------------- - -purge: clean - - $(RM) ../Lib/libamd.a ../Lib/libamdf77.a diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amd.f --- a/liboctave/UMFPACK/AMD/Source/amd.f Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1214 +0,0 @@ -C----------------------------------------------------------------------- -C AMD: approximate minimum degree, with aggressive absorption -C----------------------------------------------------------------------- - - SUBROUTINE AMD - $ (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, - $ LAST, HEAD, ELEN, DEGREE, NCMPA, W) - - INTEGER N, IWLEN, PFREE, NCMPA, IW (IWLEN), PE (N), - $ DEGREE (N), NV (N), NEXT (N), LAST (N), HEAD (N), - $ ELEN (N), W (N), LEN (N) - -C Given a representation of the nonzero pattern of a symmetric matrix, -C A, (excluding the diagonal) perform an approximate minimum -C (UMFPACK/MA38-style) degree ordering to compute a pivot order -C such that the introduction of nonzeros (fill-in) in the Cholesky -C factors A = LL^T are kept low. At each step, the pivot -C selected is the one with the minimum UMFPACK/MA38-style -C upper-bound on the external degree. -C -C Aggresive absorption is used to tighten the bound on the degree. - -C ********************************************************************** -C ***** CAUTION: ARGUMENTS ARE NOT CHECKED FOR ERRORS ON INPUT. ****** -C ********************************************************************** - -C References: -C -C [1] Timothy A. Davis and Iain Duff, "An unsymmetric-pattern -C multifrontal method for sparse LU factorization", SIAM J. -C Matrix Analysis and Applications, vol. 18, no. 1, pp. -C 140-158. Discusses UMFPACK / MA38, which first introduced -C the approximate minimum degree used by this routine. -C -C [2] Patrick Amestoy, Timothy A. Davis, and Iain S. Duff, "An -C approximate degree ordering algorithm," SIAM J. Matrix -C Analysis and Applications, vol. 17, no. 4, pp. 886-905, -C 1996. Discusses AMD, AMDBAR, and MC47B. -C -C [3] Alan George and Joseph Liu, "The evolution of the minimum -C degree ordering algorithm," SIAM Review, vol. 31, no. 1, -C pp. 1-19, 1989. We list below the features mentioned in -C that paper that this code includes: -C -C mass elimination: -C Yes. MA27 relied on supervariable detection for mass -C elimination. -C indistinguishable nodes: -C Yes (we call these "supervariables"). This was also in -C the MA27 code - although we modified the method of -C detecting them (the previous hash was the true degree, -C which we no longer keep track of). A supervariable is -C a set of rows with identical nonzero pattern. All -C variables in a supervariable are eliminated together. -C Each supervariable has as its numerical name that of -C one of its variables (its principal variable). -C quotient graph representation: -C Yes. We use the term "element" for the cliques formed -C during elimination. This was also in the MA27 code. -C The algorithm can operate in place, but it will work -C more efficiently if given some "elbow room." -C element absorption: -C Yes. This was also in the MA27 code. -C external degree: -C Yes. The MA27 code was based on the true degree. -C incomplete degree update and multiple elimination: -C No. This was not in MA27, either. Our method of -C degree update within MC47B/BD is element-based, not -C variable-based. It is thus not well-suited for use -C with incomplete degree update or multiple elimination. - -C----------------------------------------------------------------------- -C Authors, and Copyright (C) 1995 by: -C Timothy A. Davis, Patrick Amestoy, Iain S. Duff, & John K. Reid. -C -C Acknowledgements: -C This work (and the UMFPACK package) was supported by the -C National Science Foundation (ASC-9111263 and DMS-9223088). -C The UMFPACK/MA38 approximate degree update algorithm, the -C unsymmetric analog which forms the basis of MC47B/BD, was -C developed while Tim Davis was supported by CERFACS (Toulouse, -C France) in a post-doctoral position. -C -C Date: September, 1995 -C----------------------------------------------------------------------- - -C----------------------------------------------------------------------- -C INPUT ARGUMENTS (unaltered): -C----------------------------------------------------------------------- - -C n: The matrix order. -C -C Restriction: 1 .le. n .lt. (iovflo/2)-2, where iovflo is -C the largest positive integer that your computer can represent. - -C iwlen: The length of iw (1..iwlen). On input, the matrix is -C stored in iw (1..pfree-1). However, iw (1..iwlen) should be -C slightly larger than what is required to hold the matrix, at -C least iwlen .ge. pfree + n is recommended. Otherwise, -C excessive compressions will take place. -C *** We do not recommend running this algorithm with *** -C *** iwlen .lt. pfree + n. *** -C *** Better performance will be obtained if *** -C *** iwlen .ge. pfree + n *** -C *** or better yet *** -C *** iwlen .gt. 1.2 * pfree *** -C *** (where pfree is its value on input). *** -C The algorithm will not run at all if iwlen .lt. pfree-1. -C -C Restriction: iwlen .ge. pfree-1 - -C----------------------------------------------------------------------- -C INPUT/OUPUT ARGUMENTS: -C----------------------------------------------------------------------- - -C pe: On input, pe (i) is the index in iw of the start of row i, or -C zero if row i has no off-diagonal non-zeros. -C -C During execution, it is used for both supervariables and -C elements: -C -C * Principal supervariable i: index into iw of the -C description of supervariable i. A supervariable -C represents one or more rows of the matrix -C with identical nonzero pattern. -C * Non-principal supervariable i: if i has been absorbed -C into another supervariable j, then pe (i) = -j. -C That is, j has the same pattern as i. -C Note that j might later be absorbed into another -C supervariable j2, in which case pe (i) is still -j, -C and pe (j) = -j2. -C * Unabsorbed element e: the index into iw of the description -C of element e, if e has not yet been absorbed by a -C subsequent element. Element e is created when -C the supervariable of the same name is selected as -C the pivot. -C * Absorbed element e: if element e is absorbed into element -C e2, then pe (e) = -e2. This occurs when the pattern of -C e (that is, Le) is found to be a subset of the pattern -C of e2 (that is, Le2). If element e is "null" (it has -C no nonzeros outside its pivot block), then pe (e) = 0. -C -C On output, pe holds the assembly tree/forest, which implicitly -C represents a pivot order with identical fill-in as the actual -C order (via a depth-first search of the tree). -C -C On output: -C If nv (i) .gt. 0, then i represents a node in the assembly tree, -C and the parent of i is -pe (i), or zero if i is a root. -C If nv (i) = 0, then (i,-pe (i)) represents an edge in a -C subtree, the root of which is a node in the assembly tree. - -C pfree: On input the tail end of the array, iw (pfree..iwlen), -C is empty, and the matrix is stored in iw (1..pfree-1). -C During execution, additional data is placed in iw, and pfree -C is modified so that iw (pfree..iwlen) is always the unused part -C of iw. On output, pfree is set equal to the size of iw that -C would have been needed for no compressions to occur. If -C ncmpa is zero, then pfree (on output) is less than or equal to -C iwlen, and the space iw (pfree+1 ... iwlen) was not used. -C Otherwise, pfree (on output) is greater than iwlen, and all the -C memory in iw was used. - -C----------------------------------------------------------------------- -C INPUT/MODIFIED (undefined on output): -C----------------------------------------------------------------------- - -C len: On input, len (i) holds the number of entries in row i of the -C matrix, excluding the diagonal. The contents of len (1..n) -C are undefined on output. - -C iw: On input, iw (1..pfree-1) holds the description of each row i -C in the matrix. The matrix must be symmetric, and both upper -C and lower triangular parts must be present. The diagonal must -C not be present. Row i is held as follows: -C -C len (i): the length of the row i data structure -C iw (pe (i) ... pe (i) + len (i) - 1): -C the list of column indices for nonzeros -C in row i (simple supervariables), excluding -C the diagonal. All supervariables start with -C one row/column each (supervariable i is just -C row i). -C if len (i) is zero on input, then pe (i) is ignored -C on input. -C -C Note that the rows need not be in any particular order, -C and there may be empty space between the rows. -C -C During execution, the supervariable i experiences fill-in. -C This is represented by placing in i a list of the elements -C that cause fill-in in supervariable i: -C -C len (i): the length of supervariable i -C iw (pe (i) ... pe (i) + elen (i) - 1): -C the list of elements that contain i. This list -C is kept short by removing absorbed elements. -C iw (pe (i) + elen (i) ... pe (i) + len (i) - 1): -C the list of supervariables in i. This list -C is kept short by removing nonprincipal -C variables, and any entry j that is also -C contained in at least one of the elements -C (j in Le) in the list for i (e in row i). -C -C When supervariable i is selected as pivot, we create an -C element e of the same name (e=i): -C -C len (e): the length of element e -C iw (pe (e) ... pe (e) + len (e) - 1): -C the list of supervariables in element e. -C -C An element represents the fill-in that occurs when supervariable -C i is selected as pivot (which represents the selection of row i -C and all non-principal variables whose principal variable is i). -C We use the term Le to denote the set of all supervariables -C in element e. Absorbed supervariables and elements are pruned -C from these lists when computationally convenient. -C -C CAUTION: THE INPUT MATRIX IS OVERWRITTEN DURING COMPUTATION. -C The contents of iw are undefined on output. - -C----------------------------------------------------------------------- -C OUTPUT (need not be set on input): -C----------------------------------------------------------------------- - -C nv: During execution, abs (nv (i)) is equal to the number of rows -C that are represented by the principal supervariable i. If i is -C a nonprincipal variable, then nv (i) = 0. Initially, -C nv (i) = 1 for all i. nv (i) .lt. 0 signifies that i is a -C principal variable in the pattern Lme of the current pivot -C element me. On output, nv (e) holds the true degree of element -C e at the time it was created (including the diagonal part). - -C ncmpa: The number of times iw was compressed. If this is -C excessive, then the execution took longer than what could have -C been. To reduce ncmpa, try increasing iwlen to be 10% or 20% -C larger than the value of pfree on input (or at least -C iwlen .ge. pfree + n). The fastest performance will be -C obtained when ncmpa is returned as zero. If iwlen is set to -C the value returned by pfree on *output*, then no compressions -C will occur. - -C elen: See the description of iw above. At the start of execution, -C elen (i) is set to zero. During execution, elen (i) is the -C number of elements in the list for supervariable i. When e -C becomes an element, elen (e) = -nel is set, where nel is the -C current step of factorization. elen (i) = 0 is done when i -C becomes nonprincipal. -C -C For variables, elen (i) .ge. 0 holds until just before the -C permutation vectors are computed. For elements, -C elen (e) .lt. 0 holds. -C -C On output elen (1..n) holds the inverse permutation (the same -C as the 'INVP' argument in Sparspak). That is, if k = elen (i), -C then row i is the kth pivot row. Row i of A appears as the -C (elen(i))-th row in the permuted matrix, PAP^T. - -C last: In a degree list, last (i) is the supervariable preceding i, -C or zero if i is the head of the list. In a hash bucket, -C last (i) is the hash key for i. last (head (hash)) is also -C used as the head of a hash bucket if head (hash) contains a -C degree list (see head, below). -C -C On output, last (1..n) holds the permutation (the same as the -C 'PERM' argument in Sparspak). That is, if i = last (k), then -C row i is the kth pivot row. Row last (k) of A is the k-th row -C in the permuted matrix, PAP^T. - -C----------------------------------------------------------------------- -C LOCAL (not input or output - used only during execution): -C----------------------------------------------------------------------- - -C degree: If i is a supervariable, then degree (i) holds the -C current approximation of the external degree of row i (an upper -C bound). The external degree is the number of nonzeros in row i, -C minus abs (nv (i)) (the diagonal part). The bound is equal to -C the external degree if elen (i) is less than or equal to two. -C -C We also use the term "external degree" for elements e to refer -C to |Le \ Lme|. If e is an element, then degree (e) holds |Le|, -C which is the degree of the off-diagonal part of the element e -C (not including the diagonal part). - -C head: head is used for degree lists. head (deg) is the first -C supervariable in a degree list (all supervariables i in a -C degree list deg have the same approximate degree, namely, -C deg = degree (i)). If the list deg is empty then -C head (deg) = 0. -C -C During supervariable detection head (hash) also serves as a -C pointer to a hash bucket. -C If head (hash) .gt. 0, there is a degree list of degree hash. -C The hash bucket head pointer is last (head (hash)). -C If head (hash) = 0, then the degree list and hash bucket are -C both empty. -C If head (hash) .lt. 0, then the degree list is empty, and -C -head (hash) is the head of the hash bucket. -C After supervariable detection is complete, all hash buckets -C are empty, and the (last (head (hash)) = 0) condition is -C restored for the non-empty degree lists. - -C next: next (i) is the supervariable following i in a link list, or -C zero if i is the last in the list. Used for two kinds of -C lists: degree lists and hash buckets (a supervariable can be -C in only one kind of list at a time). - -C w: The flag array w determines the status of elements and -C variables, and the external degree of elements. -C -C for elements: -C if w (e) = 0, then the element e is absorbed -C if w (e) .ge. wflg, then w (e) - wflg is the size of -C the set |Le \ Lme|, in terms of nonzeros (the -C sum of abs (nv (i)) for each principal variable i that -C is both in the pattern of element e and NOT in the -C pattern of the current pivot element, me). -C if wflg .gt. w (e) .gt. 0, then e is not absorbed and has -C not yet been seen in the scan of the element lists in -C the computation of |Le\Lme| in loop 150 below. -C -C for variables: -C during supervariable detection, if w (j) .ne. wflg then j is -C not in the pattern of variable i -C -C The w array is initialized by setting w (i) = 1 for all i, -C and by setting wflg = 2. It is reinitialized if wflg becomes -C too large (to ensure that wflg+n does not cause integer -C overflow). - -C----------------------------------------------------------------------- -C LOCAL INTEGERS: -C----------------------------------------------------------------------- - - INTEGER DEG, DEGME, DEXT, DMAX, E, ELENME, ELN, HASH, HMOD, I, - $ ILAST, INEXT, J, JLAST, JNEXT, K, KNT1, KNT2, KNT3, - $ LENJ, LN, MAXMEM, ME, MEM, MINDEG, NEL, NEWMEM, - $ NLEFT, NVI, NVJ, NVPIV, SLENME, WE, WFLG, WNVI, X - -C deg: the degree of a variable or element -C degme: size, |Lme|, of the current element, me (= degree (me)) -C dext: external degree, |Le \ Lme|, of some element e -C dmax: largest |Le| seen so far -C e: an element -C elenme: the length, elen (me), of element list of pivotal var. -C eln: the length, elen (...), of an element list -C hash: the computed value of the hash function -C hmod: the hash function is computed modulo hmod = max (1,n-1) -C i: a supervariable -C ilast: the entry in a link list preceding i -C inext: the entry in a link list following i -C j: a supervariable -C jlast: the entry in a link list preceding j -C jnext: the entry in a link list, or path, following j -C k: the pivot order of an element or variable -C knt1: loop counter used during element construction -C knt2: loop counter used during element construction -C knt3: loop counter used during compression -C lenj: len (j) -C ln: length of a supervariable list -C maxmem: amount of memory needed for no compressions -C me: current supervariable being eliminated, and the -C current element created by eliminating that -C supervariable -C mem: memory in use assuming no compressions have occurred -C mindeg: current minimum degree -C nel: number of pivots selected so far -C newmem: amount of new memory needed for current pivot element -C nleft: n - nel, the number of nonpivotal rows/columns remaining -C nvi: the number of variables in a supervariable i (= nv (i)) -C nvj: the number of variables in a supervariable j (= nv (j)) -C nvpiv: number of pivots in current element -C slenme: number of variables in variable list of pivotal variable -C we: w (e) -C wflg: used for flagging the w array. See description of iw. -C wnvi: wflg - nv (i) -C x: either a supervariable or an element - -C----------------------------------------------------------------------- -C LOCAL POINTERS: -C----------------------------------------------------------------------- - - INTEGER P, P1, P2, P3, PDST, PEND, PJ, PME, PME1, PME2, PN, PSRC - -C Any parameter (pe (...) or pfree) or local variable -C starting with "p" (for Pointer) is an index into iw, -C and all indices into iw use variables starting with -C "p." The only exception to this rule is the iwlen -C input argument. - -C p: pointer into lots of things -C p1: pe (i) for some variable i (start of element list) -C p2: pe (i) + elen (i) - 1 for some var. i (end of el. list) -C p3: index of first supervariable in clean list -C pdst: destination pointer, for compression -C pend: end of memory to compress -C pj: pointer into an element or variable -C pme: pointer into the current element (pme1...pme2) -C pme1: the current element, me, is stored in iw (pme1...pme2) -C pme2: the end of the current element -C pn: pointer into a "clean" variable, also used to compress -C psrc: source pointer, for compression - -C----------------------------------------------------------------------- -C FUNCTIONS CALLED: -C----------------------------------------------------------------------- - - INTRINSIC MAX, MIN, MOD - -C======================================================================= -C INITIALIZATIONS -C======================================================================= - - WFLG = 2 - MINDEG = 1 - NCMPA = 0 - NEL = 0 - HMOD = MAX (1, N-1) - DMAX = 0 - MEM = PFREE - 1 - MAXMEM = MEM - ME = 0 - - DO 10 I = 1, N - LAST (I) = 0 - HEAD (I) = 0 - NV (I) = 1 - W (I) = 1 - ELEN (I) = 0 - DEGREE (I) = LEN (I) -10 CONTINUE - -C ---------------------------------------------------------------- -C initialize degree lists and eliminate rows with no off-diag. nz. -C ---------------------------------------------------------------- - - DO 20 I = 1, N - - DEG = DEGREE (I) - - IF (DEG .GT. 0) THEN - -C ---------------------------------------------------------- -C place i in the degree list corresponding to its degree -C ---------------------------------------------------------- - - INEXT = HEAD (DEG) - IF (INEXT .NE. 0) LAST (INEXT) = I - NEXT (I) = INEXT - HEAD (DEG) = I - - ELSE - -C ---------------------------------------------------------- -C we have a variable that can be eliminated at once because -C there is no off-diagonal non-zero in its row. -C ---------------------------------------------------------- - - NEL = NEL + 1 - ELEN (I) = -NEL - PE (I) = 0 - W (I) = 0 - - ENDIF - -20 CONTINUE - -C======================================================================= -C WHILE (selecting pivots) DO -C======================================================================= - -30 CONTINUE - IF (NEL .LT. N) THEN - -C======================================================================= -C GET PIVOT OF MINIMUM DEGREE -C======================================================================= - -C ------------------------------------------------------------- -C find next supervariable for elimination -C ------------------------------------------------------------- - - DO 40 DEG = MINDEG, N - ME = HEAD (DEG) - IF (ME .GT. 0) GOTO 50 -40 CONTINUE -50 CONTINUE - MINDEG = DEG - -C ------------------------------------------------------------- -C remove chosen variable from link list -C ------------------------------------------------------------- - - INEXT = NEXT (ME) - IF (INEXT .NE. 0) LAST (INEXT) = 0 - HEAD (DEG) = INEXT - -C ------------------------------------------------------------- -C me represents the elimination of pivots nel+1 to nel+nv(me). -C place me itself as the first in this set. It will be moved -C to the nel+nv(me) position when the permutation vectors are -C computed. -C ------------------------------------------------------------- - - ELENME = ELEN (ME) - ELEN (ME) = - (NEL + 1) - NVPIV = NV (ME) - NEL = NEL + NVPIV - -C======================================================================= -C CONSTRUCT NEW ELEMENT -C======================================================================= - -C ------------------------------------------------------------- -C At this point, me is the pivotal supervariable. It will be -C converted into the current element. Scan list of the -C pivotal supervariable, me, setting tree pointers and -C constructing new list of supervariables for the new element, -C me. p is a pointer to the current position in the old list. -C ------------------------------------------------------------- - -C flag the variable "me" as being in Lme by negating nv (me) - NV (ME) = -NVPIV - DEGME = 0 - - IF (ELENME .EQ. 0) THEN - -C ---------------------------------------------------------- -C construct the new element in place -C ---------------------------------------------------------- - - PME1 = PE (ME) - PME2 = PME1 - 1 - - DO 60 P = PME1, PME1 + LEN (ME) - 1 - I = IW (P) - NVI = NV (I) - IF (NVI .GT. 0) THEN - -C ---------------------------------------------------- -C i is a principal variable not yet placed in Lme. -C store i in new list -C ---------------------------------------------------- - - DEGME = DEGME + NVI -C flag i as being in Lme by negating nv (i) - NV (I) = -NVI - PME2 = PME2 + 1 - IW (PME2) = I - -C ---------------------------------------------------- -C remove variable i from degree list. -C ---------------------------------------------------- - - ILAST = LAST (I) - INEXT = NEXT (I) - IF (INEXT .NE. 0) LAST (INEXT) = ILAST - IF (ILAST .NE. 0) THEN - NEXT (ILAST) = INEXT - ELSE -C i is at the head of the degree list - HEAD (DEGREE (I)) = INEXT - ENDIF - - ENDIF -60 CONTINUE -C this element takes no new memory in iw: - NEWMEM = 0 - - ELSE - -C ---------------------------------------------------------- -C construct the new element in empty space, iw (pfree ...) -C ---------------------------------------------------------- - - P = PE (ME) - PME1 = PFREE - SLENME = LEN (ME) - ELENME - - DO 120 KNT1 = 1, ELENME + 1 - - IF (KNT1 .GT. ELENME) THEN -C search the supervariables in me. - E = ME - PJ = P - LN = SLENME - ELSE -C search the elements in me. - E = IW (P) - P = P + 1 - PJ = PE (E) - LN = LEN (E) - ENDIF - -C ------------------------------------------------------- -C search for different supervariables and add them to the -C new list, compressing when necessary. this loop is -C executed once for each element in the list and once for -C all the supervariables in the list. -C ------------------------------------------------------- - - DO 110 KNT2 = 1, LN - I = IW (PJ) - PJ = PJ + 1 - NVI = NV (I) - IF (NVI .GT. 0) THEN - -C ------------------------------------------------- -C compress iw, if necessary -C ------------------------------------------------- - - IF (PFREE .GT. IWLEN) THEN -C prepare for compressing iw by adjusting -C pointers and lengths so that the lists being -C searched in the inner and outer loops contain -C only the remaining entries. - - PE (ME) = P - LEN (ME) = LEN (ME) - KNT1 - IF (LEN (ME) .EQ. 0) THEN -C nothing left of supervariable me - PE (ME) = 0 - ENDIF - PE (E) = PJ - LEN (E) = LN - KNT2 - IF (LEN (E) .EQ. 0) THEN -C nothing left of element e - PE (E) = 0 - ENDIF - - NCMPA = NCMPA + 1 -C store first item in pe -C set first entry to -item - DO 70 J = 1, N - PN = PE (J) - IF (PN .GT. 0) THEN - PE (J) = IW (PN) - IW (PN) = -J - ENDIF -70 CONTINUE - -C psrc/pdst point to source/destination - PDST = 1 - PSRC = 1 - PEND = PME1 - 1 - -C while loop: -80 CONTINUE - IF (PSRC .LE. PEND) THEN -C search for next negative entry - J = -IW (PSRC) - PSRC = PSRC + 1 - IF (J .GT. 0) THEN - IW (PDST) = PE (J) - PE (J) = PDST - PDST = PDST + 1 -C copy from source to destination - LENJ = LEN (J) - DO 90 KNT3 = 0, LENJ - 2 - IW (PDST + KNT3) = IW (PSRC + KNT3) -90 CONTINUE - PDST = PDST + LENJ - 1 - PSRC = PSRC + LENJ - 1 - ENDIF - GOTO 80 - ENDIF - -C move the new partially-constructed element - P1 = PDST - DO 100 PSRC = PME1, PFREE - 1 - IW (PDST) = IW (PSRC) - PDST = PDST + 1 -100 CONTINUE - PME1 = P1 - PFREE = PDST - PJ = PE (E) - P = PE (ME) - ENDIF - -C ------------------------------------------------- -C i is a principal variable not yet placed in Lme -C store i in new list -C ------------------------------------------------- - - DEGME = DEGME + NVI -C flag i as being in Lme by negating nv (i) - NV (I) = -NVI - IW (PFREE) = I - PFREE = PFREE + 1 - -C ------------------------------------------------- -C remove variable i from degree link list -C ------------------------------------------------- - - ILAST = LAST (I) - INEXT = NEXT (I) - IF (INEXT .NE. 0) LAST (INEXT) = ILAST - IF (ILAST .NE. 0) THEN - NEXT (ILAST) = INEXT - ELSE -C i is at the head of the degree list - HEAD (DEGREE (I)) = INEXT - ENDIF - - ENDIF -110 CONTINUE - - IF (E .NE. ME) THEN -C set tree pointer and flag to indicate element e is -C absorbed into new element me (the parent of e is me) - PE (E) = -ME - W (E) = 0 - ENDIF -120 CONTINUE - - PME2 = PFREE - 1 -C this element takes newmem new memory in iw (possibly zero) - NEWMEM = PFREE - PME1 - MEM = MEM + NEWMEM - MAXMEM = MAX (MAXMEM, MEM) - ENDIF - -C ------------------------------------------------------------- -C me has now been converted into an element in iw (pme1..pme2) -C ------------------------------------------------------------- - -C degme holds the external degree of new element - DEGREE (ME) = DEGME - PE (ME) = PME1 - LEN (ME) = PME2 - PME1 + 1 - -C ------------------------------------------------------------- -C make sure that wflg is not too large. With the current -C value of wflg, wflg+n must not cause integer overflow -C ------------------------------------------------------------- - - IF (WFLG + N .LE. WFLG) THEN - DO 130 X = 1, N - IF (W (X) .NE. 0) W (X) = 1 -130 CONTINUE - WFLG = 2 - ENDIF - -C======================================================================= -C COMPUTE (w (e) - wflg) = |Le\Lme| FOR ALL ELEMENTS -C======================================================================= - -C ------------------------------------------------------------- -C Scan 1: compute the external degrees of previous elements -C with respect to the current element. That is: -C (w (e) - wflg) = |Le \ Lme| -C for each element e that appears in any supervariable in Lme. -C The notation Le refers to the pattern (list of -C supervariables) of a previous element e, where e is not yet -C absorbed, stored in iw (pe (e) + 1 ... pe (e) + iw (pe (e))). -C The notation Lme refers to the pattern of the current element -C (stored in iw (pme1..pme2)). If (w (e) - wflg) becomes -C zero, then the element e will be absorbed in scan 2. -C ------------------------------------------------------------- - - DO 150 PME = PME1, PME2 - I = IW (PME) - ELN = ELEN (I) - IF (ELN .GT. 0) THEN -C note that nv (i) has been negated to denote i in Lme: - NVI = -NV (I) - WNVI = WFLG - NVI - DO 140 P = PE (I), PE (I) + ELN - 1 - E = IW (P) - WE = W (E) - IF (WE .GE. WFLG) THEN -C unabsorbed element e has been seen in this loop - WE = WE - NVI - ELSE IF (WE .NE. 0) THEN -C e is an unabsorbed element -C this is the first we have seen e in all of Scan 1 - WE = DEGREE (E) + WNVI - ENDIF - W (E) = WE -140 CONTINUE - ENDIF -150 CONTINUE - -C======================================================================= -C DEGREE UPDATE AND ELEMENT ABSORPTION -C======================================================================= - -C ------------------------------------------------------------- -C Scan 2: for each i in Lme, sum up the degree of Lme (which -C is degme), plus the sum of the external degrees of each Le -C for the elements e appearing within i, plus the -C supervariables in i. Place i in hash list. -C ------------------------------------------------------------- - - DO 180 PME = PME1, PME2 - I = IW (PME) - P1 = PE (I) - P2 = P1 + ELEN (I) - 1 - PN = P1 - HASH = 0 - DEG = 0 - -C ---------------------------------------------------------- -C scan the element list associated with supervariable i -C ---------------------------------------------------------- - - DO 160 P = P1, P2 - E = IW (P) -C dext = | Le \ Lme | - DEXT = W (E) - WFLG - IF (DEXT .GT. 0) THEN - DEG = DEG + DEXT - IW (PN) = E - PN = PN + 1 - HASH = HASH + E - ELSE IF (DEXT .EQ. 0) THEN -C aggressive absorption: e is not adjacent to me, but -C the |Le \ Lme| is 0, so absorb it into me - PE (E) = -ME - W (E) = 0 - ELSE -C element e has already been absorbed, due to -C regular absorption, in do loop 120 above. Ignore it. - CONTINUE - ENDIF -160 CONTINUE - -C count the number of elements in i (including me): - ELEN (I) = PN - P1 + 1 - -C ---------------------------------------------------------- -C scan the supervariables in the list associated with i -C ---------------------------------------------------------- - - P3 = PN - DO 170 P = P2 + 1, P1 + LEN (I) - 1 - J = IW (P) - NVJ = NV (J) - IF (NVJ .GT. 0) THEN -C j is unabsorbed, and not in Lme. -C add to degree and add to new list - DEG = DEG + NVJ - IW (PN) = J - PN = PN + 1 - HASH = HASH + J - ENDIF -170 CONTINUE - -C ---------------------------------------------------------- -C update the degree and check for mass elimination -C ---------------------------------------------------------- - - IF (DEG .EQ. 0) THEN - -C ------------------------------------------------------- -C mass elimination -C ------------------------------------------------------- - -C There is nothing left of this node except for an -C edge to the current pivot element. elen (i) is 1, -C and there are no variables adjacent to node i. -C Absorb i into the current pivot element, me. - - PE (I) = -ME - NVI = -NV (I) - DEGME = DEGME - NVI - NVPIV = NVPIV + NVI - NEL = NEL + NVI - NV (I) = 0 - ELEN (I) = 0 - - ELSE - -C ------------------------------------------------------- -C update the upper-bound degree of i -C ------------------------------------------------------- - -C the following degree does not yet include the size -C of the current element, which is added later: - DEGREE (I) = MIN (DEGREE (I), DEG) - -C ------------------------------------------------------- -C add me to the list for i -C ------------------------------------------------------- - -C move first supervariable to end of list - IW (PN) = IW (P3) -C move first element to end of element part of list - IW (P3) = IW (P1) -C add new element to front of list. - IW (P1) = ME -C store the new length of the list in len (i) - LEN (I) = PN - P1 + 1 - -C ------------------------------------------------------- -C place in hash bucket. Save hash key of i in last (i). -C ------------------------------------------------------- - - HASH = MOD (HASH, HMOD) + 1 - J = HEAD (HASH) - IF (J .LE. 0) THEN -C the degree list is empty, hash head is -j - NEXT (I) = -J - HEAD (HASH) = -I - ELSE -C degree list is not empty -C use last (head (hash)) as hash head - NEXT (I) = LAST (J) - LAST (J) = I - ENDIF - LAST (I) = HASH - ENDIF -180 CONTINUE - - DEGREE (ME) = DEGME - -C ------------------------------------------------------------- -C Clear the counter array, w (...), by incrementing wflg. -C ------------------------------------------------------------- - - DMAX = MAX (DMAX, DEGME) - WFLG = WFLG + DMAX - -C make sure that wflg+n does not cause integer overflow - IF (WFLG + N .LE. WFLG) THEN - DO 190 X = 1, N - IF (W (X) .NE. 0) W (X) = 1 -190 CONTINUE - WFLG = 2 - ENDIF -C at this point, w (1..n) .lt. wflg holds - -C======================================================================= -C SUPERVARIABLE DETECTION -C======================================================================= - - DO 250 PME = PME1, PME2 - I = IW (PME) - IF (NV (I) .LT. 0) THEN -C i is a principal variable in Lme - -C ------------------------------------------------------- -C examine all hash buckets with 2 or more variables. We -C do this by examing all unique hash keys for super- -C variables in the pattern Lme of the current element, me -C ------------------------------------------------------- - - HASH = LAST (I) -C let i = head of hash bucket, and empty the hash bucket - J = HEAD (HASH) - IF (J .EQ. 0) GOTO 250 - IF (J .LT. 0) THEN -C degree list is empty - I = -J - HEAD (HASH) = 0 - ELSE -C degree list is not empty, restore last () of head - I = LAST (J) - LAST (J) = 0 - ENDIF - IF (I .EQ. 0) GOTO 250 - -C while loop: -200 CONTINUE - IF (NEXT (I) .NE. 0) THEN - -C ---------------------------------------------------- -C this bucket has one or more variables following i. -C scan all of them to see if i can absorb any entries -C that follow i in hash bucket. Scatter i into w. -C ---------------------------------------------------- - - LN = LEN (I) - ELN = ELEN (I) -C do not flag the first element in the list (me) - DO 210 P = PE (I) + 1, PE (I) + LN - 1 - W (IW (P)) = WFLG -210 CONTINUE - -C ---------------------------------------------------- -C scan every other entry j following i in bucket -C ---------------------------------------------------- - - JLAST = I - J = NEXT (I) - -C while loop: -220 CONTINUE - IF (J .NE. 0) THEN - -C ------------------------------------------------- -C check if j and i have identical nonzero pattern -C ------------------------------------------------- - - IF (LEN (J) .NE. LN) THEN -C i and j do not have same size data structure - GOTO 240 - ENDIF - IF (ELEN (J) .NE. ELN) THEN -C i and j do not have same number of adjacent el - GOTO 240 - ENDIF -C do not flag the first element in the list (me) - DO 230 P = PE (J) + 1, PE (J) + LN - 1 - IF (W (IW (P)) .NE. WFLG) THEN -C an entry (iw(p)) is in j but not in i - GOTO 240 - ENDIF -230 CONTINUE - -C ------------------------------------------------- -C found it! j can be absorbed into i -C ------------------------------------------------- - - PE (J) = -I -C both nv (i) and nv (j) are negated since they -C are in Lme, and the absolute values of each -C are the number of variables in i and j: - NV (I) = NV (I) + NV (J) - NV (J) = 0 - ELEN (J) = 0 -C delete j from hash bucket - J = NEXT (J) - NEXT (JLAST) = J - GOTO 220 - -C ------------------------------------------------- -240 CONTINUE -C j cannot be absorbed into i -C ------------------------------------------------- - - JLAST = J - J = NEXT (J) - GOTO 220 - ENDIF - -C ---------------------------------------------------- -C no more variables can be absorbed into i -C go to next i in bucket and clear flag array -C ---------------------------------------------------- - - WFLG = WFLG + 1 - I = NEXT (I) - IF (I .NE. 0) GOTO 200 - ENDIF - ENDIF -250 CONTINUE - -C======================================================================= -C RESTORE DEGREE LISTS AND REMOVE NONPRINCIPAL SUPERVAR. FROM ELEMENT -C======================================================================= - - P = PME1 - NLEFT = N - NEL - DO 260 PME = PME1, PME2 - I = IW (PME) - NVI = -NV (I) - IF (NVI .GT. 0) THEN -C i is a principal variable in Lme -C restore nv (i) to signify that i is principal - NV (I) = NVI - -C ------------------------------------------------------- -C compute the external degree (add size of current elem) -C ------------------------------------------------------- - - DEG = MIN (DEGREE (I) + DEGME - NVI, NLEFT - NVI) - -C ------------------------------------------------------- -C place the supervariable at the head of the degree list -C ------------------------------------------------------- - - INEXT = HEAD (DEG) - IF (INEXT .NE. 0) LAST (INEXT) = I - NEXT (I) = INEXT - LAST (I) = 0 - HEAD (DEG) = I - -C ------------------------------------------------------- -C save the new degree, and find the minimum degree -C ------------------------------------------------------- - - MINDEG = MIN (MINDEG, DEG) - DEGREE (I) = DEG - -C ------------------------------------------------------- -C place the supervariable in the element pattern -C ------------------------------------------------------- - - IW (P) = I - P = P + 1 - ENDIF -260 CONTINUE - -C======================================================================= -C FINALIZE THE NEW ELEMENT -C======================================================================= - - NV (ME) = NVPIV + DEGME -C nv (me) is now the degree of pivot (including diagonal part) -C save the length of the list for the new element me - LEN (ME) = P - PME1 - IF (LEN (ME) .EQ. 0) THEN -C there is nothing left of the current pivot element - PE (ME) = 0 - W (ME) = 0 - ENDIF - IF (NEWMEM .NE. 0) THEN -C element was not constructed in place: deallocate part -C of it (final size is less than or equal to newmem, -C since newly nonprincipal variables have been removed). - PFREE = P - MEM = MEM - NEWMEM + LEN (ME) - ENDIF - -C======================================================================= -C END WHILE (selecting pivots) - GOTO 30 - ENDIF -C======================================================================= - -C======================================================================= -C COMPUTE THE PERMUTATION VECTORS -C======================================================================= - -C ---------------------------------------------------------------- -C The time taken by the following code is O(n). At this -C point, elen (e) = -k has been done for all elements e, -C and elen (i) = 0 has been done for all nonprincipal -C variables i. At this point, there are no principal -C supervariables left, and all elements are absorbed. -C ---------------------------------------------------------------- - -C ---------------------------------------------------------------- -C compute the ordering of unordered nonprincipal variables -C ---------------------------------------------------------------- - - DO 290 I = 1, N - IF (ELEN (I) .EQ. 0) THEN - -C ---------------------------------------------------------- -C i is an un-ordered row. Traverse the tree from i until -C reaching an element, e. The element, e, was the -C principal supervariable of i and all nodes in the path -C from i to when e was selected as pivot. -C ---------------------------------------------------------- - - J = -PE (I) -C while (j is a variable) do: -270 CONTINUE - IF (ELEN (J) .GE. 0) THEN - J = -PE (J) - GOTO 270 - ENDIF - E = J - -C ---------------------------------------------------------- -C get the current pivot ordering of e -C ---------------------------------------------------------- - - K = -ELEN (E) - -C ---------------------------------------------------------- -C traverse the path again from i to e, and compress the -C path (all nodes point to e). Path compression allows -C this code to compute in O(n) time. Order the unordered -C nodes in the path, and place the element e at the end. -C ---------------------------------------------------------- - - J = I -C while (j is a variable) do: -280 CONTINUE - IF (ELEN (J) .GE. 0) THEN - JNEXT = -PE (J) - PE (J) = -E - IF (ELEN (J) .EQ. 0) THEN -C j is an unordered row - ELEN (J) = K - K = K + 1 - ENDIF - J = JNEXT - GOTO 280 - ENDIF -C leave elen (e) negative, so we know it is an element - ELEN (E) = -K - ENDIF -290 CONTINUE - -C ---------------------------------------------------------------- -C reset the inverse permutation (elen (1..n)) to be positive, -C and compute the permutation (last (1..n)). -C ---------------------------------------------------------------- - - DO 300 I = 1, N - K = ABS (ELEN (I)) - LAST (K) = I - ELEN (I) = K -300 CONTINUE - -C======================================================================= -C RETURN THE MEMORY USAGE IN IW -C======================================================================= - -C If maxmem is less than or equal to iwlen, then no compressions -C occurred, and iw (maxmem+1 ... iwlen) was unused. Otherwise -C compressions did occur, and iwlen would have had to have been -C greater than or equal to maxmem for no compressions to occur. -C Return the value of maxmem in the pfree argument. - - PFREE = MAXMEM - - RETURN - END - diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amd_1.c --- a/liboctave/UMFPACK/AMD/Source/amd_1.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,181 +0,0 @@ -/* ========================================================================= */ -/* === AMD_1 =============================================================== */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* AMD_1: Construct A+A' for a sparse matrix A and perform the AMD ordering. - * - * The n-by-n sparse matrix A can be unsymmetric. It is stored in MATLAB-style - * compressed-column form, with sorted row indices in each column, and no - * duplicate entries. Diagonal entries may be present, but they are ignored. - * Row indices of column j of A are stored in Ai [Ap [j] ... Ap [j+1]-1]. - * Ap [0] must be zero, and nz = Ap [n] is the number of entries in A. The - * size of the matrix, n, must be greater than or equal to zero. - * - * This routine must be preceded by a call to AMD_aat, which computes the - * number of entries in each row/column in A+A', excluding the diagonal. - * Len [j], on input, is the number of entries in row/column j of A+A'. This - * routine constructs the matrix A+A' and then calls AMD_2. No error checking - * is performed (this was done in AMD_aat). - */ - -#include "amd_internal.h" - -GLOBAL void AMD_1 -( - Int n, /* n > 0 */ - const Int Ap [ ], /* input of size n+1, not modified */ - const Int Ai [ ], /* input of size nz = Ap [n], not modified */ - Int P [ ], /* size n output permutation */ - Int Pinv [ ], /* size n output inverse permutation */ - Int Len [ ], /* size n input, undefined on output */ - Int slen, /* slen >= sum (Len [0..n-1]) + 7n, - * ideally slen = 1.2 * sum (Len) + 8n */ - Int S [ ], /* size slen workspace */ - double Control [ ], /* input array of size AMD_CONTROL */ - double Info [ ] /* output array of size AMD_INFO */ -) -{ - Int i, j, k, p, pfree, iwlen, pj, p1, p2, pj2, *Iw, *Pe, *Nv, *Head, - *Elen, *Degree, *s, *W, *Sp, *Tp ; - - /* --------------------------------------------------------------------- */ - /* construct the matrix for AMD_2 */ - /* --------------------------------------------------------------------- */ - - ASSERT (n > 0) ; - - iwlen = slen - 6*n ; - s = S ; - Pe = s ; s += n ; - Nv = s ; s += n ; - Head = s ; s += n ; - Elen = s ; s += n ; - Degree = s ; s += n ; - W = s ; s += n ; - Iw = s ; s += iwlen ; - - ASSERT (AMD_valid (n, n, Ap, Ai)) ; - - /* construct the pointers for A+A' */ - Sp = Nv ; /* use Nv and W as workspace for Sp and Tp [ */ - Tp = W ; - pfree = 0 ; - for (j = 0 ; j < n ; j++) - { - Pe [j] = pfree ; - Sp [j] = pfree ; - pfree += Len [j] ; - } - - /* Note that this restriction on iwlen is slightly more restrictive than - * what is strictly required in AMD_2. AMD_2 can operate with no elbow - * room at all, but it will be very slow. For better performance, at - * least size-n elbow room is enforced. */ - ASSERT (iwlen >= pfree + n) ; - -#ifndef NDEBUG - for (p = 0 ; p < iwlen ; p++) Iw [p] = EMPTY ; -#endif - - for (k = 0 ; k < n ; k++) - { - AMD_DEBUG1 (("Construct row/column k= "ID" of A+A'\n", k)) ; - p1 = Ap [k] ; - p2 = Ap [k+1] ; - - /* construct A+A' */ - for (p = p1 ; p < p2 ; ) - { - /* scan the upper triangular part of A */ - j = Ai [p] ; - ASSERT (j >= 0 && j < n) ; - if (j < k) - { - /* entry A (j,k) in the strictly upper triangular part */ - ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; - ASSERT (Sp [k] < (k == n-1 ? pfree : Pe [k+1])) ; - Iw [Sp [j]++] = k ; - Iw [Sp [k]++] = j ; - p++ ; - } - else if (j == k) - { - /* skip the diagonal */ - p++ ; - break ; - } - else /* j > k */ - { - /* first entry below the diagonal */ - break ; - } - /* scan lower triangular part of A, in column j until reaching - * row k. Start where last scan left off. */ - ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ; - pj2 = Ap [j+1] ; - for (pj = Tp [j] ; pj < pj2 ; ) - { - i = Ai [pj] ; - ASSERT (i >= 0 && i < n) ; - if (i < k) - { - /* A (i,j) is only in the lower part, not in upper */ - ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ; - ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; - Iw [Sp [i]++] = j ; - Iw [Sp [j]++] = i ; - pj++ ; - } - else if (i == k) - { - /* entry A (k,j) in lower part and A (j,k) in upper */ - pj++ ; - break ; - } - else /* i > k */ - { - /* consider this entry later, when k advances to i */ - break ; - } - } - Tp [j] = pj ; - } - Tp [k] = p ; - } - - /* clean up, for remaining mismatched entries */ - for (j = 0 ; j < n ; j++) - { - for (pj = Tp [j] ; pj < Ap [j+1] ; pj++) - { - i = Ai [pj] ; - ASSERT (i >= 0 && i < n) ; - /* A (i,j) is only in the lower part, not in upper */ - ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ; - ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; - Iw [Sp [i]++] = j ; - Iw [Sp [j]++] = i ; - } - } - -#ifndef NDEBUG - for (j = 0 ; j < n-1 ; j++) ASSERT (Sp [j] == Pe [j+1]) ; - ASSERT (Sp [n-1] == pfree) ; -#endif - - /* Tp and Sp no longer needed ] */ - - /* --------------------------------------------------------------------- */ - /* order the matrix */ - /* --------------------------------------------------------------------- */ - - AMD_2 (n, Pe, Iw, Len, iwlen, pfree, - Nv, Pinv, P, Head, Elen, Degree, W, Control, Info) ; -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amd_2.c --- a/liboctave/UMFPACK/AMD/Source/amd_2.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1823 +0,0 @@ -/* ========================================================================= */ -/* === AMD_2 =============================================================== */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* AMD_2: performs the AMD ordering on a symmetric sparse matrix A, followed - * by a postordering (via depth-first search) of the assembly tree using the - * AMD_postorder routine. - */ - -#include "amd_internal.h" - -GLOBAL void AMD_2 -( - Int n, /* A is n-by-n, where n > 0 */ - Int Pe [ ], /* Pe [0..n-1]: index in Iw of row i on input */ - Int Iw [ ], /* workspace of size iwlen. Iw [0..pfree-1] - * holds the matrix on input */ - Int Len [ ], /* Len [0..n-1]: length for row/column i on input */ - Int iwlen, /* length of Iw. iwlen >= pfree + n */ - Int pfree, /* Iw [pfree ... iwlen-1] is empty on input */ - - /* 7 size-n workspaces, not defined on input: */ - Int Nv [ ], /* the size of each supernode on output */ - Int Next [ ], /* the output inverse permutation */ - Int Last [ ], /* the output permutation */ - Int Head [ ], - Int Elen [ ], /* the size columns of L for each supernode */ - Int Degree [ ], - Int W [ ], - - /* control parameters and output statistics */ - double Control [ ], /* array of size AMD_CONTROL */ - double Info [ ] /* array of size AMD_INFO */ -) -{ - -/* - * Given a representation of the nonzero pattern of a symmetric matrix, A, - * (excluding the diagonal) perform an approximate minimum (UMFPACK/MA38-style) - * degree ordering to compute a pivot order such that the introduction of - * nonzeros (fill-in) in the Cholesky factors A = LL' is kept low. At each - * step, the pivot selected is the one with the minimum UMFAPACK/MA38-style - * upper-bound on the external degree. This routine can optionally perform - * aggresive absorption (as done by MC47B in the Harwell Subroutine - * Library). - * - * The approximate degree algorithm implemented here is the symmetric analog of - * the degree update algorithm in MA38 and UMFPACK (the Unsymmetric-pattern - * MultiFrontal PACKage, both by Davis and Duff). The routine is based on the - * MA27 minimum degree ordering algorithm by Iain Duff and John Reid. - * - * This routine is a translation of the original AMDBAR and MC47B routines, - * in Fortran, with the following modifications: - * - * (1) dense rows/columns are removed prior to ordering the matrix, and placed - * last in the output order. The presence of a dense row/column can - * increase the ordering time by up to O(n^2), unless they are removed - * prior to ordering. - * - * (2) the minimum degree ordering is followed by a postordering (depth-first - * search) of the assembly tree. Note that mass elimination (discussed - * below) combined with the approximate degree update can lead to the mass - * elimination of nodes with lower exact degree than the current pivot - * element. No additional fill-in is caused in the representation of the - * Schur complement. The mass-eliminated nodes merge with the current - * pivot element. They are ordered prior to the current pivot element. - * Because they can have lower exact degree than the current element, the - * merger of two or more of these nodes in the current pivot element can - * lead to a single element that is not a "fundamental supernode". The - * diagonal block can have zeros in it. Thus, the assembly tree used here - * is not guaranteed to be the precise supernodal elemination tree (with - * "funadmental" supernodes), and the postordering performed by this - * routine is not guaranteed to be a precise postordering of the - * elimination tree. - * - * (3) input parameters are added, to control aggressive absorption and the - * detection of "dense" rows/columns of A. - * - * (4) additional statistical information is returned, such as the number of - * nonzeros in L, and the flop counts for subsequent LDL' and LU - * factorizations. These are slight upper bounds, because of the mass - * elimination issue discussed above. - * - * (5) additional routines are added to interface this routine to MATLAB - * to provide a simple C-callable user-interface, to check inputs for - * errors, compute the symmetry of the pattern of A and the number of - * nonzeros in each row/column of A+A', to compute the pattern of A+A', - * to perform the assembly tree postordering, and to provide debugging - * ouput. Many of these functions are also provided by the Fortran - * Harwell Subroutine Library routine MC47A. - * - * (6) both "int" and "long" versions are provided. In the descriptions below - * and integer is and "int" or "long", depending on which version is - * being used. - - ********************************************************************** - ***** CAUTION: ARGUMENTS ARE NOT CHECKED FOR ERRORS ON INPUT. ****** - ********************************************************************** - ** If you want error checking, a more versatile input format, and a ** - ** simpler user interface, use amd_order or amd_l_order instead. ** - ** This routine is not meant to be user-callable. ** - ********************************************************************** - - * ---------------------------------------------------------------------------- - * References: - * ---------------------------------------------------------------------------- - * - * [1] Timothy A. Davis and Iain Duff, "An unsymmetric-pattern multifrontal - * method for sparse LU factorization", SIAM J. Matrix Analysis and - * Applications, vol. 18, no. 1, pp. 140-158. Discusses UMFPACK / MA38, - * which first introduced the approximate minimum degree used by this - * routine. - * - * [2] Patrick Amestoy, Timothy A. Davis, and Iain S. Duff, "An approximate - * minimum degree ordering algorithm," SIAM J. Matrix Analysis and - * Applications, vol. 17, no. 4, pp. 886-905, 1996. Discusses AMDBAR and - * MC47B, which are the Fortran versions of this routine. - * - * [3] Alan George and Joseph Liu, "The evolution of the minimum degree - * ordering algorithm," SIAM Review, vol. 31, no. 1, pp. 1-19, 1989. - * We list below the features mentioned in that paper that this code - * includes: - * - * mass elimination: - * Yes. MA27 relied on supervariable detection for mass elimination. - * - * indistinguishable nodes: - * Yes (we call these "supervariables"). This was also in the MA27 - * code - although we modified the method of detecting them (the - * previous hash was the true degree, which we no longer keep track - * of). A supervariable is a set of rows with identical nonzero - * pattern. All variables in a supervariable are eliminated together. - * Each supervariable has as its numerical name that of one of its - * variables (its principal variable). - * - * quotient graph representation: - * Yes. We use the term "element" for the cliques formed during - * elimination. This was also in the MA27 code. The algorithm can - * operate in place, but it will work more efficiently if given some - * "elbow room." - * - * element absorption: - * Yes. This was also in the MA27 code. - * - * external degree: - * Yes. The MA27 code was based on the true degree. - * - * incomplete degree update and multiple elimination: - * No. This was not in MA27, either. Our method of degree update - * within MC47B is element-based, not variable-based. It is thus - * not well-suited for use with incomplete degree update or multiple - * elimination. - * - * Authors, and Copyright (C) 2004 by: - * Timothy A. Davis, Patrick Amestoy, Iain S. Duff, John K. Reid. - * - * Acknowledgements: This work (and the UMFPACK package) was supported by the - * National Science Foundation (ASC-9111263, DMS-9223088, and CCR-0203270). - * The UMFPACK/MA38 approximate degree update algorithm, the unsymmetric analog - * which forms the basis of AMD, was developed while Tim Davis was supported by - * CERFACS (Toulouse, France) in a post-doctoral position. This C version, and - * the etree postorder, were written while Tim Davis was on sabbatical at - * Stanford University and Lawrence Berkeley National Laboratory. - - * ---------------------------------------------------------------------------- - * INPUT ARGUMENTS (unaltered): - * ---------------------------------------------------------------------------- - - * n: The matrix order. Restriction: n >= 1. - * - * iwlen: The size of the Iw array. On input, the matrix is stored in - * Iw [0..pfree-1]. However, Iw [0..iwlen-1] should be slightly larger - * than what is required to hold the matrix, at least iwlen >= pfree + n. - * Otherwise, excessive compressions will take place. The recommended - * value of iwlen is 1.2 * pfree + n, which is the value used in the - * user-callable interface to this routine (amd_order.c). The algorithm - * will not run at all if iwlen < pfree. Restriction: iwlen >= pfree + n. - * Note that this is slightly more restrictive than the actual minimum - * (iwlen >= pfree), but AMD_2 will be very slow with no elbow room. - * Thus, this routine enforces a bare minimum elbow room of size n. - * - * pfree: On input the tail end of the array, Iw [pfree..iwlen-1], is empty, - * and the matrix is stored in Iw [0..pfree-1]. During execution, - * additional data is placed in Iw, and pfree is modified so that - * Iw [pfree..iwlen-1] is always the unused part of Iw. - * - * Control: A double array of size AMD_CONTROL containing input parameters - * that affect how the ordering is computed. If NULL, then default - * settings are used. - * - * Control [AMD_DENSE] is used to determine whether or not a given input - * row is "dense". A row is "dense" if the number of entries in the row - * exceeds Control [AMD_DENSE] times sqrt (n), except that rows with 16 or - * fewer entries are never considered "dense". To turn off the detection - * of dense rows, set Control [AMD_DENSE] to a negative number, or to a - * number larger than sqrt (n). The default value of Control [AMD_DENSE] - * is AMD_DEFAULT_DENSE, which is defined in amd.h as 10. - * - * Control [AMD_AGGRESSIVE] is used to determine whether or not aggressive - * absorption is to be performed. If nonzero, then aggressive absorption - * is performed (this is the default). - - * ---------------------------------------------------------------------------- - * INPUT/OUPUT ARGUMENTS: - * ---------------------------------------------------------------------------- - * - * Pe: An integer array of size n. On input, Pe [i] is the index in Iw of - * the start of row i. Pe [i] is ignored if row i has no off-diagonal - * entries. Thus Pe [i] must be in the range 0 to pfree-1 for non-empty - * rows. - * - * During execution, it is used for both supervariables and elements: - * - * Principal supervariable i: index into Iw of the description of - * supervariable i. A supervariable represents one or more rows of - * the matrix with identical nonzero pattern. In this case, - * Pe [i] >= 0. - * - * Non-principal supervariable i: if i has been absorbed into another - * supervariable j, then Pe [i] = FLIP (j), where FLIP (j) is defined - * as (-(j)-2). Row j has the same pattern as row i. Note that j - * might later be absorbed into another supervariable j2, in which - * case Pe [i] is still FLIP (j), and Pe [j] = FLIP (j2) which is - * < EMPTY, where EMPTY is defined as (-1) in amd_internal.h. - * - * Unabsorbed element e: the index into Iw of the description of element - * e, if e has not yet been absorbed by a subsequent element. Element - * e is created when the supervariable of the same name is selected as - * the pivot. In this case, Pe [i] >= 0. - * - * Absorbed element e: if element e is absorbed into element e2, then - * Pe [e] = FLIP (e2). This occurs when the pattern of e (which we - * refer to as Le) is found to be a subset of the pattern of e2 (that - * is, Le2). In this case, Pe [i] < EMPTY. If element e is "null" - * (it has no nonzeros outside its pivot block), then Pe [e] = EMPTY, - * and e is the root of an assembly subtree (or the whole tree if - * there is just one such root). - * - * Dense variable i: if i is "dense", then Pe [i] = EMPTY. - * - * On output, Pe holds the assembly tree/forest, which implicitly - * represents a pivot order with identical fill-in as the actual order - * (via a depth-first search of the tree), as follows. If Nv [i] > 0, - * then i represents a node in the assembly tree, and the parent of i is - * Pe [i], or EMPTY if i is a root. If Nv [i] = 0, then (i, Pe [i]) - * represents an edge in a subtree, the root of which is a node in the - * assembly tree. Note that i refers to a row/column in the original - * matrix, not the permuted matrix. - * - * Info: A double array of size AMD_INFO. If present, (that is, not NULL), - * then statistics about the ordering are returned in the Info array. - * See amd.h for a description. - - * ---------------------------------------------------------------------------- - * INPUT/MODIFIED (undefined on output): - * ---------------------------------------------------------------------------- - * - * Len: An integer array of size n. On input, Len [i] holds the number of - * entries in row i of the matrix, excluding the diagonal. The contents - * of Len are undefined on output. - * - * Iw: An integer array of size iwlen. On input, Iw [0..pfree-1] holds the - * description of each row i in the matrix. The matrix must be symmetric, - * and both upper and lower triangular parts must be present. The - * diagonal must not be present. Row i is held as follows: - * - * Len [i]: the length of the row i data structure in the Iw array. - * Iw [Pe [i] ... Pe [i] + Len [i] - 1]: - * the list of column indices for nonzeros in row i (simple - * supervariables), excluding the diagonal. All supervariables - * start with one row/column each (supervariable i is just row i). - * If Len [i] is zero on input, then Pe [i] is ignored on input. - * - * Note that the rows need not be in any particular order, and there - * may be empty space between the rows. - * - * During execution, the supervariable i experiences fill-in. This is - * represented by placing in i a list of the elements that cause fill-in - * in supervariable i: - * - * Len [i]: the length of supervariable i in the Iw array. - * Iw [Pe [i] ... Pe [i] + Elen [i] - 1]: - * the list of elements that contain i. This list is kept short - * by removing absorbed elements. - * Iw [Pe [i] + Elen [i] ... Pe [i] + Len [i] - 1]: - * the list of supervariables in i. This list is kept short by - * removing nonprincipal variables, and any entry j that is also - * contained in at least one of the elements (j in Le) in the list - * for i (e in row i). - * - * When supervariable i is selected as pivot, we create an element e of - * the same name (e=i): - * - * Len [e]: the length of element e in the Iw array. - * Iw [Pe [e] ... Pe [e] + Len [e] - 1]: - * the list of supervariables in element e. - * - * An element represents the fill-in that occurs when supervariable i is - * selected as pivot (which represents the selection of row i and all - * non-principal variables whose principal variable is i). We use the - * term Le to denote the set of all supervariables in element e. Absorbed - * supervariables and elements are pruned from these lists when - * computationally convenient. - * - * CAUTION: THE INPUT MATRIX IS OVERWRITTEN DURING COMPUTATION. - * The contents of Iw are undefined on output. - - * ---------------------------------------------------------------------------- - * OUTPUT (need not be set on input): - * ---------------------------------------------------------------------------- - * - * Nv: An integer array of size n. During execution, ABS (Nv [i]) is equal to - * the number of rows that are represented by the principal supervariable - * i. If i is a nonprincipal or dense variable, then Nv [i] = 0. - * Initially, Nv [i] = 1 for all i. Nv [i] < 0 signifies that i is a - * principal variable in the pattern Lme of the current pivot element me. - * After element me is constructed, Nv [i] is set back to a positive - * value. - * - * On output, Nv [i] holds the number of pivots represented by super - * row/column i of the original matrix, or Nv [i] = 0 for non-principal - * rows/columns. Note that i refers to a row/column in the original - * matrix, not the permuted matrix. - * - * Elen: An integer array of size n. See the description of Iw above. At the - * start of execution, Elen [i] is set to zero for all rows i. During - * execution, Elen [i] is the number of elements in the list for - * supervariable i. When e becomes an element, Elen [e] = FLIP (esize) is - * set, where esize is the size of the element (the number of pivots, plus - * the number of nonpivotal entries). Thus Elen [e] < EMPTY. - * Elen (i) = EMPTY set when variable i becomes nonprincipal. - * - * For variables, Elen (i) >= EMPTY holds until just before the - * postordering and permutation vectors are computed. For elements, - * Elen [e] < EMPTY holds. - * - * On output, Elen [i] is the degree of the row/column in the Cholesky - * factorization of the permuted matrix, corresponding to the original row - * i, if i is a super row/column. It is equal to EMPTY if i is - * non-principal. Note that i refers to a row/column in the original - * matrix, not the permuted matrix. - * - * Note that the contents of Elen on output differ from the Fortran - * version (Elen holds the inverse permutation in the Fortran version, - * which is instead returned in the Next array in this C version, - * described below). - * - * Last: In a degree list, Last [i] is the supervariable preceding i, or EMPTY - * if i is the head of the list. In a hash bucket, Last [i] is the hash - * key for i. - * - * Last [Head [hash]] is also used as the head of a hash bucket if - * Head [hash] contains a degree list (see the description of Head, - * below). - * - * On output, Last [0..n-1] holds the permutation. That is, if - * i = Last [k], then row i is the kth pivot row (where k ranges from 0 to - * n-1). Row Last [k] of A is the kth row in the permuted matrix, PAP'. - * - * Next: Next [i] is the supervariable following i in a link list, or EMPTY if - * i is the last in the list. Used for two kinds of lists: degree lists - * and hash buckets (a supervariable can be in only one kind of list at a - * time). - * - * On output Next [0..n-1] holds the inverse permutation. That is, if - * k = Next [i], then row i is the kth pivot row. Row i of A appears as - * the (Next[i])-th row in the permuted matrix, PAP'. - * - * Note that the contents of Next on output differ from the Fortran - * version (Next is undefined on output in the Fortran version). - - * ---------------------------------------------------------------------------- - * LOCAL WORKSPACE (not input or output - used only during execution): - * ---------------------------------------------------------------------------- - * - * Degree: An integer array of size n. If i is a supervariable, then - * Degree [i] holds the current approximation of the external degree of - * row i (an upper bound). The external degree is the number of nonzeros - * in row i, minus ABS (Nv [i]), the diagonal part. The bound is equal to - * the exact external degree if Elen [i] is less than or equal to two. - * - * We also use the term "external degree" for elements e to refer to - * |Le \ Lme|. If e is an element, then Degree [e] is |Le|, which is the - * degree of the off-diagonal part of the element e (not including the - * diagonal part). - * - * Head: An integer array of size n. Head is used for degree lists. - * Head [deg] is the first supervariable in a degree list. All - * supervariables i in a degree list Head [deg] have the same approximate - * degree, namely, deg = Degree [i]. If the list Head [deg] is empty then - * Head [deg] = EMPTY. - * - * During supervariable detection Head [hash] also serves as a pointer to - * a hash bucket. If Head [hash] >= 0, there is a degree list of degree - * hash. The hash bucket head pointer is Last [Head [hash]]. If - * Head [hash] = EMPTY, then the degree list and hash bucket are both - * empty. If Head [hash] < EMPTY, then the degree list is empty, and - * FLIP (Head [hash]) is the head of the hash bucket. After supervariable - * detection is complete, all hash buckets are empty, and the - * (Last [Head [hash]] = EMPTY) condition is restored for the non-empty - * degree lists. - * - * W: An integer array of size n. The flag array W determines the status of - * elements and variables, and the external degree of elements. - * - * for elements: - * if W [e] = 0, then the element e is absorbed. - * if W [e] >= wflg, then W [e] - wflg is the size of the set - * |Le \ Lme|, in terms of nonzeros (the sum of ABS (Nv [i]) for - * each principal variable i that is both in the pattern of - * element e and NOT in the pattern of the current pivot element, - * me). - * if wflg > W [e] > 0, then e is not absorbed and has not yet been - * seen in the scan of the element lists in the computation of - * |Le\Lme| in Scan 1 below. - * - * for variables: - * during supervariable detection, if W [j] != wflg then j is - * not in the pattern of variable i. - * - * The W array is initialized by setting W [i] = 1 for all i, and by - * setting wflg = 2. It is reinitialized if wflg becomes too large (to - * ensure that wflg+n does not cause integer overflow). - - * ---------------------------------------------------------------------------- - * LOCAL INTEGERS: - * ---------------------------------------------------------------------------- - */ - - Int deg, degme, dext, lemax, e, elenme, eln, i, ilast, inext, j, - jlast, jnext, k, knt1, knt2, knt3, lenj, ln, me, mindeg, nel, nleft, - nvi, nvj, nvpiv, slenme, wbig, we, wflg, wnvi, x, ok, ndense, ncmpa, - dense, aggressive ; - - unsigned Int hash ; /* unsigned, so that hash % n is well defined.*/ - -/* - * deg: the degree of a variable or element - * degme: size, |Lme|, of the current element, me (= Degree [me]) - * dext: external degree, |Le \ Lme|, of some element e - * lemax: largest |Le| seen so far (called dmax in Fortran version) - * e: an element - * elenme: the length, Elen [me], of element list of pivotal variable - * eln: the length, Elen [...], of an element list - * hash: the computed value of the hash function - * i: a supervariable - * ilast: the entry in a link list preceding i - * inext: the entry in a link list following i - * j: a supervariable - * jlast: the entry in a link list preceding j - * jnext: the entry in a link list, or path, following j - * k: the pivot order of an element or variable - * knt1: loop counter used during element construction - * knt2: loop counter used during element construction - * knt3: loop counter used during compression - * lenj: Len [j] - * ln: length of a supervariable list - * me: current supervariable being eliminated, and the current - * element created by eliminating that supervariable - * mindeg: current minimum degree - * nel: number of pivots selected so far - * nleft: n - nel, the number of nonpivotal rows/columns remaining - * nvi: the number of variables in a supervariable i (= Nv [i]) - * nvj: the number of variables in a supervariable j (= Nv [j]) - * nvpiv: number of pivots in current element - * slenme: number of variables in variable list of pivotal variable - * wbig: = INT_MAX - n for the "int" version, LONG_MAX - n for the - * "long" version. wflg is not allowed to be >= wbig. - * we: W [e] - * wflg: used for flagging the W array. See description of Iw. - * wnvi: wflg - Nv [i] - * x: either a supervariable or an element - * - * ok: true if supervariable j can be absorbed into i - * ndense: number of "dense" rows/columns - * dense: rows/columns with initial degree > dense are considered "dense" - * aggressive: true if aggressive absorption is being performed - * ncmpa: number of garbage collections - - * ---------------------------------------------------------------------------- - * LOCAL DOUBLES, used for statistical output only (except for alpha): - * ---------------------------------------------------------------------------- - */ - - double f, r, ndiv, s, nms_lu, nms_ldl, dmax, alpha, lnz, lnzme ; - -/* - * f: nvpiv - * r: degme + nvpiv - * ndiv: number of divisions for LU or LDL' factorizations - * s: number of multiply-subtract pairs for LU factorization, for the - * current element me - * nms_lu number of multiply-subtract pairs for LU factorization - * nms_ldl number of multiply-subtract pairs for LDL' factorization - * dmax: the largest number of entries in any column of L, including the - * diagonal - * alpha: "dense" degree ratio - * lnz: the number of nonzeros in L (excluding the diagonal) - * lnzme: the number of nonzeros in L (excl. the diagonal) for the - * current element me - - * ---------------------------------------------------------------------------- - * LOCAL "POINTERS" (indices into the Iw array) - * ---------------------------------------------------------------------------- -*/ - - Int p, p1, p2, p3, p4, pdst, pend, pj, pme, pme1, pme2, pn, psrc ; - -/* - * Any parameter (Pe [...] or pfree) or local variable starting with "p" (for - * Pointer) is an index into Iw, and all indices into Iw use variables starting - * with "p." The only exception to this rule is the iwlen input argument. - * - * p: pointer into lots of things - * p1: Pe [i] for some variable i (start of element list) - * p2: Pe [i] + Elen [i] - 1 for some variable i - * p3: index of first supervariable in clean list - * p4: - * pdst: destination pointer, for compression - * pend: end of memory to compress - * pj: pointer into an element or variable - * pme: pointer into the current element (pme1...pme2) - * pme1: the current element, me, is stored in Iw [pme1...pme2] - * pme2: the end of the current element - * pn: pointer into a "clean" variable, also used to compress - * psrc: source pointer, for compression -*/ - -/* ========================================================================= */ -/* INITIALIZATIONS */ -/* ========================================================================= */ - - /* Note that this restriction on iwlen is slightly more restrictive than - * what is actually required in AMD_2. AMD_2 can operate with no elbow - * room at all, but it will be slow. For better performance, at least - * size-n elbow room is enforced. */ - ASSERT (iwlen >= pfree + n) ; - ASSERT (n > 0) ; - - /* initialize output statistics */ - lnz = 0 ; - ndiv = 0 ; - nms_lu = 0 ; - nms_ldl = 0 ; - dmax = 1 ; - me = EMPTY ; - - wflg = 2 ; - mindeg = 0 ; - ncmpa = 0 ; - nel = 0 ; - lemax = 0 ; /* this is called dmax in the Fortran version */ - -#ifdef TEST_FOR_INTEGER_OVERFLOW - /* for testing only */ - wbig = 3*n ; -#else - /* normal operation */ - wbig = Int_MAX - n ; -#endif - - /* get control parameters */ - if (Control != (double *) NULL) - { - alpha = Control [AMD_DENSE] ; - aggressive = (Control [AMD_AGGRESSIVE] != 0) ; - } - else - { - alpha = AMD_DEFAULT_DENSE ; - aggressive = AMD_DEFAULT_AGGRESSIVE ; - } - if (alpha < 0) - { - /* no dense rows/columns */ - dense = n ; - } - else - { - dense = alpha * sqrt ((double) n) ; - } - dense = MAX (16, dense) ; - dense = MIN (n, dense) ; - AMD_DEBUG1 (("AMD (debug), alpha %g, aggr. "ID"\n", alpha, aggressive)) ; - - for (i = 0 ; i < n ; i++) - { - Last [i] = EMPTY ; - Head [i] = EMPTY ; - Next [i] = EMPTY ; - /* if seperate Hhead array is used for hash buckets: * - Hhead [i] = EMPTY ; - */ - Nv [i] = 1 ; - W [i] = 1 ; - Elen [i] = 0 ; - Degree [i] = Len [i] ; - } - -#ifndef NDEBUG - AMD_DEBUG1 (("\n======Nel "ID"\n", nel)) ; - AMD_dump (n, Pe, Iw, Len, iwlen, pfree, Nv, Next, Last, - Head, Elen, Degree, W, -1) ; -#endif - - /* --------------------------------------------------------------------- */ - /* initialize degree lists and eliminate dense and empty rows */ - /* --------------------------------------------------------------------- */ - - ndense = 0 ; - - /* for (i = n-1 ; i >= 0 ; i--) */ - for (i = 0 ; i < n ; i++) - { - deg = Degree [i] ; - ASSERT (deg >= 0 && deg < n) ; - if (deg == 0) - { - - /* ------------------------------------------------------------- - * we have a variable that can be eliminated at once because - * there is no off-diagonal non-zero in its row. Note that - * Nv [i] = 1 for an empty variable i. It is treated just - * the same as an eliminated element i. - * ------------------------------------------------------------- */ - - Elen [i] = FLIP (1) ; - nel++ ; - Pe [i] = EMPTY ; - W [i] = 0 ; - - } - else if (deg > dense) - { - - /* ------------------------------------------------------------- - * Dense variables are not treated as elements, but as unordered, - * non-principal variables that have no parent. They do not take - * part in the postorder, since Nv [i] = 0. Note that the Fortran - * version does not have this option. - * ------------------------------------------------------------- */ - - AMD_DEBUG1 (("Dense node "ID" degree "ID"\n", i, deg)) ; - ndense++ ; - Nv [i] = 0 ; /* do not postorder this node */ - Elen [i] = EMPTY ; - nel++ ; - Pe [i] = EMPTY ; - - } - else - { - - /* ------------------------------------------------------------- - * place i in the degree list corresponding to its degree - * ------------------------------------------------------------- */ - - inext = Head [deg] ; - ASSERT (inext >= EMPTY && inext < n) ; - if (inext != EMPTY) Last [inext] = i ; - Next [i] = inext ; - Head [deg] = i ; - - } - } - -/* ========================================================================= */ -/* WHILE (selecting pivots) DO */ -/* ========================================================================= */ - - while (nel < n) - { - -#ifndef NDEBUG - AMD_DEBUG1 (("\n======Nel "ID"\n", nel)) ; - if (AMD_debug >= 2) AMD_dump (n, Pe, Iw, Len, iwlen, pfree, Nv, Next, - Last, Head, Elen, Degree, W, nel) ; -#endif - -/* ========================================================================= */ -/* GET PIVOT OF MINIMUM DEGREE */ -/* ========================================================================= */ - - /* ----------------------------------------------------------------- */ - /* find next supervariable for elimination */ - /* ----------------------------------------------------------------- */ - - ASSERT (mindeg >= 0 && mindeg < n) ; - for (deg = mindeg ; deg < n ; deg++) - { - me = Head [deg] ; - if (me != EMPTY) break ; - } - mindeg = deg ; - ASSERT (me >= 0 && me < n) ; - AMD_DEBUG1 (("=================me: "ID"\n", me)) ; - - /* ----------------------------------------------------------------- */ - /* remove chosen variable from link list */ - /* ----------------------------------------------------------------- */ - - inext = Next [me] ; - ASSERT (inext >= EMPTY && inext < n) ; - if (inext != EMPTY) Last [inext] = EMPTY ; - Head [deg] = inext ; - - /* ----------------------------------------------------------------- */ - /* me represents the elimination of pivots nel to nel+Nv[me]-1. */ - /* place me itself as the first in this set. */ - /* ----------------------------------------------------------------- */ - - elenme = Elen [me] ; - nvpiv = Nv [me] ; - ASSERT (nvpiv > 0) ; - nel += nvpiv ; - -/* ========================================================================= */ -/* CONSTRUCT NEW ELEMENT */ -/* ========================================================================= */ - - /* ----------------------------------------------------------------- - * At this point, me is the pivotal supervariable. It will be - * converted into the current element. Scan list of the pivotal - * supervariable, me, setting tree pointers and constructing new list - * of supervariables for the new element, me. p is a pointer to the - * current position in the old list. - * ----------------------------------------------------------------- */ - - /* flag the variable "me" as being in Lme by negating Nv [me] */ - Nv [me] = -nvpiv ; - degme = 0 ; - ASSERT (Pe [me] >= 0 && Pe [me] < iwlen) ; - - if (elenme == 0) - { - - /* ------------------------------------------------------------- */ - /* construct the new element in place */ - /* ------------------------------------------------------------- */ - - pme1 = Pe [me] ; - pme2 = pme1 - 1 ; - - for (p = pme1 ; p <= pme1 + Len [me] - 1 ; p++) - { - i = Iw [p] ; - ASSERT (i >= 0 && i < n && Nv [i] >= 0) ; - nvi = Nv [i] ; - if (nvi > 0) - { - - /* ----------------------------------------------------- */ - /* i is a principal variable not yet placed in Lme. */ - /* store i in new list */ - /* ----------------------------------------------------- */ - - /* flag i as being in Lme by negating Nv [i] */ - degme += nvi ; - Nv [i] = -nvi ; - Iw [++pme2] = i ; - - /* ----------------------------------------------------- */ - /* remove variable i from degree list. */ - /* ----------------------------------------------------- */ - - ilast = Last [i] ; - inext = Next [i] ; - ASSERT (ilast >= EMPTY && ilast < n) ; - ASSERT (inext >= EMPTY && inext < n) ; - if (inext != EMPTY) Last [inext] = ilast ; - if (ilast != EMPTY) - { - Next [ilast] = inext ; - } - else - { - /* i is at the head of the degree list */ - ASSERT (Degree [i] >= 0 && Degree [i] < n) ; - Head [Degree [i]] = inext ; - } - } - } - } - else - { - - /* ------------------------------------------------------------- */ - /* construct the new element in empty space, Iw [pfree ...] */ - /* ------------------------------------------------------------- */ - - p = Pe [me] ; - pme1 = pfree ; - slenme = Len [me] - elenme ; - - for (knt1 = 1 ; knt1 <= elenme + 1 ; knt1++) - { - - if (knt1 > elenme) - { - /* search the supervariables in me. */ - e = me ; - pj = p ; - ln = slenme ; - AMD_DEBUG2 (("Search sv: "ID" "ID" "ID"\n", me,pj,ln)) ; - } - else - { - /* search the elements in me. */ - e = Iw [p++] ; - ASSERT (e >= 0 && e < n) ; - pj = Pe [e] ; - ln = Len [e] ; - AMD_DEBUG2 (("Search element e "ID" in me "ID"\n", e,me)) ; - ASSERT (Elen [e] < EMPTY && W [e] > 0 && pj >= 0) ; - } - ASSERT (ln >= 0 && (ln == 0 || (pj >= 0 && pj < iwlen))) ; - - /* --------------------------------------------------------- - * search for different supervariables and add them to the - * new list, compressing when necessary. this loop is - * executed once for each element in the list and once for - * all the supervariables in the list. - * --------------------------------------------------------- */ - - for (knt2 = 1 ; knt2 <= ln ; knt2++) - { - i = Iw [pj++] ; - ASSERT (i >= 0 && i < n && (i == me || Elen [i] >= EMPTY)); - nvi = Nv [i] ; - AMD_DEBUG2 ((": "ID" "ID" "ID" "ID"\n", - i, Elen [i], Nv [i], wflg)) ; - - if (nvi > 0) - { - - /* ------------------------------------------------- */ - /* compress Iw, if necessary */ - /* ------------------------------------------------- */ - - if (pfree >= iwlen) - { - - AMD_DEBUG1 (("GARBAGE COLLECTION\n")) ; - - /* prepare for compressing Iw by adjusting pointers - * and lengths so that the lists being searched in - * the inner and outer loops contain only the - * remaining entries. */ - - Pe [me] = p ; - Len [me] -= knt1 ; - /* check if nothing left of supervariable me */ - if (Len [me] == 0) Pe [me] = EMPTY ; - Pe [e] = pj ; - Len [e] = ln - knt2 ; - /* nothing left of element e */ - if (Len [e] == 0) Pe [e] = EMPTY ; - - ncmpa++ ; /* one more garbage collection */ - - /* store first entry of each object in Pe */ - /* FLIP the first entry in each object */ - for (j = 0 ; j < n ; j++) - { - pn = Pe [j] ; - if (pn >= 0) - { - ASSERT (pn >= 0 && pn < iwlen) ; - Pe [j] = Iw [pn] ; - Iw [pn] = FLIP (j) ; - } - } - - /* psrc/pdst point to source/destination */ - psrc = 0 ; - pdst = 0 ; - pend = pme1 - 1 ; - - while (psrc <= pend) - { - /* search for next FLIP'd entry */ - j = FLIP (Iw [psrc++]) ; - if (j >= 0) - { - AMD_DEBUG2 (("Got object j: "ID"\n", j)) ; - Iw [pdst] = Pe [j] ; - Pe [j] = pdst++ ; - lenj = Len [j] ; - /* copy from source to destination */ - for (knt3 = 0 ; knt3 <= lenj - 2 ; knt3++) - { - Iw [pdst++] = Iw [psrc++] ; - } - } - } - - /* move the new partially-constructed element */ - p1 = pdst ; - for (psrc = pme1 ; psrc <= pfree-1 ; psrc++) - { - Iw [pdst++] = Iw [psrc] ; - } - pme1 = p1 ; - pfree = pdst ; - pj = Pe [e] ; - p = Pe [me] ; - - } - - /* ------------------------------------------------- */ - /* i is a principal variable not yet placed in Lme */ - /* store i in new list */ - /* ------------------------------------------------- */ - - /* flag i as being in Lme by negating Nv [i] */ - degme += nvi ; - Nv [i] = -nvi ; - Iw [pfree++] = i ; - AMD_DEBUG2 ((" s: "ID" nv "ID"\n", i, Nv [i])); - - /* ------------------------------------------------- */ - /* remove variable i from degree link list */ - /* ------------------------------------------------- */ - - ilast = Last [i] ; - inext = Next [i] ; - ASSERT (ilast >= EMPTY && ilast < n) ; - ASSERT (inext >= EMPTY && inext < n) ; - if (inext != EMPTY) Last [inext] = ilast ; - if (ilast != EMPTY) - { - Next [ilast] = inext ; - } - else - { - /* i is at the head of the degree list */ - ASSERT (Degree [i] >= 0 && Degree [i] < n) ; - Head [Degree [i]] = inext ; - } - } - } - - if (e != me) - { - /* set tree pointer and flag to indicate element e is - * absorbed into new element me (the parent of e is me) */ - AMD_DEBUG1 ((" Element "ID" => "ID"\n", e, me)) ; - Pe [e] = FLIP (me) ; - W [e] = 0 ; - } - } - - pme2 = pfree - 1 ; - } - - /* ----------------------------------------------------------------- */ - /* me has now been converted into an element in Iw [pme1..pme2] */ - /* ----------------------------------------------------------------- */ - - /* degme holds the external degree of new element */ - Degree [me] = degme ; - Pe [me] = pme1 ; - Len [me] = pme2 - pme1 + 1 ; - ASSERT (Pe [me] >= 0 && Pe [me] < iwlen) ; - - Elen [me] = FLIP (nvpiv + degme) ; - /* FLIP (Elen (me)) is now the degree of pivot (including - * diagonal part). */ - -#ifndef NDEBUG - AMD_DEBUG2 (("New element structure: length= "ID"\n", pme2-pme1+1)) ; - for (pme = pme1 ; pme <= pme2 ; pme++) AMD_DEBUG3 ((" "ID"", Iw[pme])); - AMD_DEBUG3 (("\n")) ; -#endif - - /* ----------------------------------------------------------------- */ - /* make sure that wflg is not too large. */ - /* ----------------------------------------------------------------- */ - - /* With the current value of wflg, wflg+n must not cause integer - * overflow */ - - if (wflg >= wbig) - { - for (x = 0 ; x < n ; x++) - { - if (W [x] != 0) W [x] = 1 ; - } - wflg = 2 ; - } - -/* ========================================================================= */ -/* COMPUTE (W [e] - wflg) = |Le\Lme| FOR ALL ELEMENTS */ -/* ========================================================================= */ - - /* ----------------------------------------------------------------- - * Scan 1: compute the external degrees of previous elements with - * respect to the current element. That is: - * (W [e] - wflg) = |Le \ Lme| - * for each element e that appears in any supervariable in Lme. The - * notation Le refers to the pattern (list of supervariables) of a - * previous element e, where e is not yet absorbed, stored in - * Iw [Pe [e] + 1 ... Pe [e] + Iw [Pe [e]]]. The notation Lme - * refers to the pattern of the current element (stored in - * Iw [pme1..pme2]). If aggressive absorption is enabled, and - * (W [e] - wflg) becomes zero, then the element e will be absorbed - * in Scan 2. - * ----------------------------------------------------------------- */ - - AMD_DEBUG2 (("me: ")) ; - for (pme = pme1 ; pme <= pme2 ; pme++) - { - i = Iw [pme] ; - ASSERT (i >= 0 && i < n) ; - eln = Elen [i] ; - AMD_DEBUG3 ((""ID" Elen "ID": \n", i, eln)) ; - if (eln > 0) - { - /* note that Nv [i] has been negated to denote i in Lme: */ - nvi = -Nv [i] ; - ASSERT (nvi > 0 && Pe [i] >= 0 && Pe [i] < iwlen) ; - wnvi = wflg - nvi ; - for (p = Pe [i] ; p <= Pe [i] + eln - 1 ; p++) - { - e = Iw [p] ; - ASSERT (e >= 0 && e < n) ; - we = W [e] ; - AMD_DEBUG4 ((" e "ID" we "ID" ", e, we)) ; - if (we >= wflg) - { - /* unabsorbed element e has been seen in this loop */ - AMD_DEBUG4 ((" unabsorbed, first time seen")) ; - we -= nvi ; - } - else if (we != 0) - { - /* e is an unabsorbed element */ - /* this is the first we have seen e in all of Scan 1 */ - AMD_DEBUG4 ((" unabsorbed")) ; - we = Degree [e] + wnvi ; - } - AMD_DEBUG4 (("\n")) ; - W [e] = we ; - } - } - } - AMD_DEBUG2 (("\n")) ; - -/* ========================================================================= */ -/* DEGREE UPDATE AND ELEMENT ABSORPTION */ -/* ========================================================================= */ - - /* ----------------------------------------------------------------- - * Scan 2: for each i in Lme, sum up the degree of Lme (which is - * degme), plus the sum of the external degrees of each Le for the - * elements e appearing within i, plus the supervariables in i. - * Place i in hash list. - * ----------------------------------------------------------------- */ - - for (pme = pme1 ; pme <= pme2 ; pme++) - { - i = Iw [pme] ; - ASSERT (i >= 0 && i < n && Nv [i] < 0 && Elen [i] >= 0) ; - AMD_DEBUG2 (("Updating: i "ID" "ID" "ID"\n", i, Elen[i], Len [i])); - p1 = Pe [i] ; - p2 = p1 + Elen [i] - 1 ; - pn = p1 ; - hash = 0 ; - deg = 0 ; - ASSERT (p1 >= 0 && p1 < iwlen && p2 >= -1 && p2 < iwlen) ; - - /* ------------------------------------------------------------- */ - /* scan the element list associated with supervariable i */ - /* ------------------------------------------------------------- */ - - /* UMFPACK/MA38-style approximate degree: */ - if (aggressive) - { - for (p = p1 ; p <= p2 ; p++) - { - e = Iw [p] ; - ASSERT (e >= 0 && e < n) ; - we = W [e] ; - if (we != 0) - { - /* e is an unabsorbed element */ - /* dext = | Le \ Lme | */ - dext = we - wflg ; - if (dext > 0) - { - deg += dext ; - Iw [pn++] = e ; - hash += e ; - AMD_DEBUG4 ((" e: "ID" hash = "ID"\n",e,hash)) ; - } - else - { - /* external degree of e is zero, absorb e into me*/ - AMD_DEBUG1 ((" Element "ID" =>"ID" (aggressive)\n", - e, me)) ; - ASSERT (dext == 0) ; - Pe [e] = FLIP (me) ; - W [e] = 0 ; - } - } - } - } - else - { - for (p = p1 ; p <= p2 ; p++) - { - e = Iw [p] ; - ASSERT (e >= 0 && e < n) ; - we = W [e] ; - if (we != 0) - { - /* e is an unabsorbed element */ - dext = we - wflg ; - ASSERT (dext >= 0) ; - deg += dext ; - Iw [pn++] = e ; - hash += e ; - AMD_DEBUG4 ((" e: "ID" hash = "ID"\n",e,hash)) ; - } - } - } - - /* count the number of elements in i (including me): */ - Elen [i] = pn - p1 + 1 ; - - /* ------------------------------------------------------------- */ - /* scan the supervariables in the list associated with i */ - /* ------------------------------------------------------------- */ - - /* The bulk of the AMD run time is typically spent in this loop, - * particularly if the matrix has many dense rows that are not - * removed prior to ordering. */ - p3 = pn ; - p4 = p1 + Len [i] ; - for (p = p2 + 1 ; p < p4 ; p++) - { - j = Iw [p] ; - ASSERT (j >= 0 && j < n) ; - nvj = Nv [j] ; - if (nvj > 0) - { - /* j is unabsorbed, and not in Lme. */ - /* add to degree and add to new list */ - deg += nvj ; - Iw [pn++] = j ; - hash += j ; - AMD_DEBUG4 ((" s: "ID" hash "ID" Nv[j]= "ID"\n", - j, hash, nvj)) ; - } - } - - /* ------------------------------------------------------------- */ - /* update the degree and check for mass elimination */ - /* ------------------------------------------------------------- */ - - /* with aggressive absorption, deg==0 is identical to the - * Elen [i] == 1 && p3 == pn test, below. */ - ASSERT (IMPLIES (aggressive, (deg==0) == (Elen[i]==1 && p3==pn))) ; - - if (Elen [i] == 1 && p3 == pn) - { - - /* --------------------------------------------------------- */ - /* mass elimination */ - /* --------------------------------------------------------- */ - - /* There is nothing left of this node except for an edge to - * the current pivot element. Elen [i] is 1, and there are - * no variables adjacent to node i. Absorb i into the - * current pivot element, me. Note that if there are two or - * more mass eliminations, fillin due to mass elimination is - * possible within the nvpiv-by-nvpiv pivot block. It is this - * step that causes AMD's analysis to be an upper bound. - * - * The reason is that the selected pivot has a lower - * approximate degree than the true degree of the two mass - * eliminated nodes. There is no edge between the two mass - * eliminated nodes. They are merged with the current pivot - * anyway. - * - * No fillin occurs in the Schur complement, in any case, - * and this effect does not decrease the quality of the - * ordering itself, just the quality of the nonzero and - * flop count analysis. It also means that the post-ordering - * is not an exact elimination tree post-ordering. */ - - AMD_DEBUG1 ((" MASS i "ID" => parent e "ID"\n", i, me)) ; - Pe [i] = FLIP (me) ; - nvi = -Nv [i] ; - degme -= nvi ; - nvpiv += nvi ; - nel += nvi ; - Nv [i] = 0 ; - Elen [i] = EMPTY ; - - } - else - { - - /* --------------------------------------------------------- */ - /* update the upper-bound degree of i */ - /* --------------------------------------------------------- */ - - /* the following degree does not yet include the size - * of the current element, which is added later: */ - - Degree [i] = MIN (Degree [i], deg) ; - - /* --------------------------------------------------------- */ - /* add me to the list for i */ - /* --------------------------------------------------------- */ - - /* move first supervariable to end of list */ - Iw [pn] = Iw [p3] ; - /* move first element to end of element part of list */ - Iw [p3] = Iw [p1] ; - /* add new element, me, to front of list. */ - Iw [p1] = me ; - /* store the new length of the list in Len [i] */ - Len [i] = pn - p1 + 1 ; - - /* --------------------------------------------------------- */ - /* place in hash bucket. Save hash key of i in Last [i]. */ - /* --------------------------------------------------------- */ - - /* NOTE: this can fail if hash is negative, because the ANSI C - * standard does not define a % b when a and/or b are negative. - * That's why hash is defined as an unsigned Int, to avoid this - * problem. */ - hash = hash % n ; - ASSERT (((Int) hash) >= 0 && ((Int) hash) < n) ; - - /* if the Hhead array is not used: */ - j = Head [hash] ; - if (j <= EMPTY) - { - /* degree list is empty, hash head is FLIP (j) */ - Next [i] = FLIP (j) ; - Head [hash] = FLIP (i) ; - } - else - { - /* degree list is not empty, use Last [Head [hash]] as - * hash head. */ - Next [i] = Last [j] ; - Last [j] = i ; - } - - /* if a seperate Hhead array is used: * - Next [i] = Hhead [hash] ; - Hhead [hash] = i ; - */ - - Last [i] = hash ; - } - } - - Degree [me] = degme ; - - /* ----------------------------------------------------------------- */ - /* Clear the counter array, W [...], by incrementing wflg. */ - /* ----------------------------------------------------------------- */ - - /* make sure that wflg+n does not cause integer overflow */ - lemax = MAX (lemax, degme) ; - wflg += lemax ; - if (wflg >= wbig) - { - for (x = 0 ; x < n ; x++) - { - if (W [x] != 0) W [x] = 1 ; - } - wflg = 2 ; - } - /* at this point, W [0..n-1] < wflg holds */ - -/* ========================================================================= */ -/* SUPERVARIABLE DETECTION */ -/* ========================================================================= */ - - AMD_DEBUG1 (("Detecting supervariables:\n")) ; - for (pme = pme1 ; pme <= pme2 ; pme++) - { - i = Iw [pme] ; - ASSERT (i >= 0 && i < n) ; - AMD_DEBUG2 (("Consider i "ID" nv "ID"\n", i, Nv [i])) ; - if (Nv [i] < 0) - { - /* i is a principal variable in Lme */ - - /* --------------------------------------------------------- - * examine all hash buckets with 2 or more variables. We do - * this by examing all unique hash keys for supervariables in - * the pattern Lme of the current element, me - * --------------------------------------------------------- */ - - /* let i = head of hash bucket, and empty the hash bucket */ - ASSERT (Last [i] >= 0 && Last [i] < n) ; - hash = Last [i] ; - - /* if Hhead array is not used: */ - j = Head [hash] ; - if (j == EMPTY) - { - /* hash bucket and degree list are both empty */ - i = EMPTY ; - } - else if (j < EMPTY) - { - /* degree list is empty */ - i = FLIP (j) ; - Head [hash] = EMPTY ; - } - else - { - /* degree list is not empty, restore Last [j] of head j */ - i = Last [j] ; - Last [j] = EMPTY ; - } - - /* if seperate Hhead array is used: * - i = Hhead [hash] ; - Hhead [hash] = EMPTY ; - */ - - ASSERT (i >= EMPTY && i < n) ; - AMD_DEBUG2 (("----i "ID" hash "ID"\n", i, hash)) ; - - while (i != EMPTY && Next [i] != EMPTY) - { - - /* ----------------------------------------------------- - * this bucket has one or more variables following i. - * scan all of them to see if i can absorb any entries - * that follow i in hash bucket. Scatter i into w. - * ----------------------------------------------------- */ - - ln = Len [i] ; - eln = Elen [i] ; - ASSERT (ln >= 0 && eln >= 0) ; - ASSERT (Pe [i] >= 0 && Pe [i] < iwlen) ; - /* do not flag the first element in the list (me) */ - for (p = Pe [i] + 1 ; p <= Pe [i] + ln - 1 ; p++) - { - ASSERT (Iw [p] >= 0 && Iw [p] < n) ; - W [Iw [p]] = wflg ; - } - - /* ----------------------------------------------------- */ - /* scan every other entry j following i in bucket */ - /* ----------------------------------------------------- */ - - jlast = i ; - j = Next [i] ; - ASSERT (j >= EMPTY && j < n) ; - - while (j != EMPTY) - { - /* ------------------------------------------------- */ - /* check if j and i have identical nonzero pattern */ - /* ------------------------------------------------- */ - - AMD_DEBUG3 (("compare i "ID" and j "ID"\n", i,j)) ; - - /* check if i and j have the same Len and Elen */ - ASSERT (Len [j] >= 0 && Elen [j] >= 0) ; - ASSERT (Pe [j] >= 0 && Pe [j] < iwlen) ; - ok = (Len [j] == ln) && (Elen [j] == eln) ; - /* skop the first element in the list (me) */ - for (p = Pe [j] + 1 ; ok && p <= Pe [j] + ln - 1 ; p++) - { - ASSERT (Iw [p] >= 0 && Iw [p] < n) ; - if (W [Iw [p]] != wflg) ok = 0 ; - } - if (ok) - { - /* --------------------------------------------- */ - /* found it! j can be absorbed into i */ - /* --------------------------------------------- */ - - AMD_DEBUG1 (("found it! j "ID" => i "ID"\n", j,i)); - Pe [j] = FLIP (i) ; - /* both Nv [i] and Nv [j] are negated since they */ - /* are in Lme, and the absolute values of each */ - /* are the number of variables in i and j: */ - Nv [i] += Nv [j] ; - Nv [j] = 0 ; - Elen [j] = EMPTY ; - /* delete j from hash bucket */ - ASSERT (j != Next [j]) ; - j = Next [j] ; - Next [jlast] = j ; - - } - else - { - /* j cannot be absorbed into i */ - jlast = j ; - ASSERT (j != Next [j]) ; - j = Next [j] ; - } - ASSERT (j >= EMPTY && j < n) ; - } - - /* ----------------------------------------------------- - * no more variables can be absorbed into i - * go to next i in bucket and clear flag array - * ----------------------------------------------------- */ - - wflg++ ; - i = Next [i] ; - ASSERT (i >= EMPTY && i < n) ; - - } - } - } - AMD_DEBUG2 (("detect done\n")) ; - -/* ========================================================================= */ -/* RESTORE DEGREE LISTS AND REMOVE NONPRINCIPAL SUPERVARIABLES FROM ELEMENT */ -/* ========================================================================= */ - - p = pme1 ; - nleft = n - nel ; - for (pme = pme1 ; pme <= pme2 ; pme++) - { - i = Iw [pme] ; - ASSERT (i >= 0 && i < n) ; - nvi = -Nv [i] ; - AMD_DEBUG3 (("Restore i "ID" "ID"\n", i, nvi)) ; - if (nvi > 0) - { - /* i is a principal variable in Lme */ - /* restore Nv [i] to signify that i is principal */ - Nv [i] = nvi ; - - /* --------------------------------------------------------- */ - /* compute the external degree (add size of current element) */ - /* --------------------------------------------------------- */ - - deg = Degree [i] + degme - nvi ; - deg = MIN (deg, nleft - nvi) ; - ASSERT (IMPLIES (aggressive, deg > 0) && deg >= 0 && deg < n) ; - - /* --------------------------------------------------------- */ - /* place the supervariable at the head of the degree list */ - /* --------------------------------------------------------- */ - - inext = Head [deg] ; - ASSERT (inext >= EMPTY && inext < n) ; - if (inext != EMPTY) Last [inext] = i ; - Next [i] = inext ; - Last [i] = EMPTY ; - Head [deg] = i ; - - /* --------------------------------------------------------- */ - /* save the new degree, and find the minimum degree */ - /* --------------------------------------------------------- */ - - mindeg = MIN (mindeg, deg) ; - Degree [i] = deg ; - - /* --------------------------------------------------------- */ - /* place the supervariable in the element pattern */ - /* --------------------------------------------------------- */ - - Iw [p++] = i ; - - } - } - AMD_DEBUG2 (("restore done\n")) ; - -/* ========================================================================= */ -/* FINALIZE THE NEW ELEMENT */ -/* ========================================================================= */ - - AMD_DEBUG2 (("ME = "ID" DONE\n", me)) ; - Nv [me] = nvpiv ; - /* save the length of the list for the new element me */ - Len [me] = p - pme1 ; - if (Len [me] == 0) - { - /* there is nothing left of the current pivot element */ - /* it is a root of the assembly tree */ - Pe [me] = EMPTY ; - W [me] = 0 ; - } - if (elenme != 0) - { - /* element was not constructed in place: deallocate part of */ - /* it since newly nonprincipal variables may have been removed */ - pfree = p ; - } - - /* The new element has nvpiv pivots and the size of the contribution - * block for a multifrontal method is degme-by-degme, not including - * the "dense" rows/columns. If the "dense" rows/columns are included, - * the frontal matrix is no larger than - * (degme+ndense)-by-(degme+ndense). - */ - - if (Info != (double *) NULL) - { - f = nvpiv ; - r = degme + ndense ; - dmax = MAX (dmax, f + r) ; - - /* number of nonzeros in L (excluding the diagonal) */ - lnzme = f*r + (f-1)*f/2 ; - lnz += lnzme ; - - /* number of divide operations for LDL' and for LU */ - ndiv += lnzme ; - - /* number of multiply-subtract pairs for LU */ - s = f*r*r + r*(f-1)*f + (f-1)*f*(2*f-1)/6 ; - nms_lu += s ; - - /* number of multiply-subtract pairs for LDL' */ - nms_ldl += (s + lnzme)/2 ; - } - -#ifndef NDEBUG - AMD_DEBUG2 (("finalize done nel "ID" n "ID"\n ::::\n", nel, n)) ; - for (pme = Pe [me] ; pme <= Pe [me] + Len [me] - 1 ; pme++) - { - AMD_DEBUG3 ((" "ID"", Iw [pme])) ; - } - AMD_DEBUG3 (("\n")) ; -#endif - - } - -/* ========================================================================= */ -/* DONE SELECTING PIVOTS */ -/* ========================================================================= */ - - if (Info != (double *) NULL) - { - - /* count the work to factorize the ndense-by-ndense submatrix */ - f = ndense ; - dmax = MAX (dmax, (double) ndense) ; - - /* number of nonzeros in L (excluding the diagonal) */ - lnzme = (f-1)*f/2 ; - lnz += lnzme ; - - /* number of divide operations for LDL' and for LU */ - ndiv += lnzme ; - - /* number of multiply-subtract pairs for LU */ - s = (f-1)*f*(2*f-1)/6 ; - nms_lu += s ; - - /* number of multiply-subtract pairs for LDL' */ - nms_ldl += (s + lnzme)/2 ; - - /* number of nz's in L (excl. diagonal) */ - Info [AMD_LNZ] = lnz ; - - /* number of divide ops for LU and LDL' */ - Info [AMD_NDIV] = ndiv ; - - /* number of multiply-subtract pairs for LDL' */ - Info [AMD_NMULTSUBS_LDL] = nms_ldl ; - - /* number of multiply-subtract pairs for LU */ - Info [AMD_NMULTSUBS_LU] = nms_lu ; - - /* number of "dense" rows/columns */ - Info [AMD_NDENSE] = ndense ; - - /* largest front is dmax-by-dmax */ - Info [AMD_DMAX] = dmax ; - - /* number of garbage collections in AMD */ - Info [AMD_NCMPA] = ncmpa ; - - /* successful ordering */ - Info [AMD_STATUS] = AMD_OK ; - } - -/* ------------------------------------------------------------------------- - * Variables at this point: - * - * Pe: holds the elimination tree. The parent of j is FLIP (Pe [j]), - * or EMPTY if j is a root. The tree holds both elements and - * non-principal (unordered) variables absorbed into them. - * Dense variables are non-principal and unordered. - * - * Elen: holds the size of each element, including the diagonal part. - * FLIP (Elen [e]) > 0 if e is an element. For unordered - * variables i, Elen [i] is EMPTY. - * - * Nv: Nv [e] > 0 is the number of pivots represented by the element e. - * For unordered variables i, Nv [i] is zero. - * - * Contents no longer needed: - * W, Iw, Len, Degree, Head, Next, Last. - * - * The matrix itself has been destroyed. - * - * n: the size of the matrix. - * No other scalars needed (pfree, iwlen, etc.) - * ------------------------------------------------------------------------- */ - - for (i = 0 ; i < n ; i++) - { - Pe [i] = FLIP (Pe [i]) ; - Elen [i] = FLIP (Elen [i]) ; - } - -/* Now the parent of j is Pe [j], or EMPTY if j is a root. Elen [e] > 0 - * is the size of element e. Elen [i] is EMPTY for unordered variable i. */ - -#ifndef NDEBUG - AMD_DEBUG2 (("\nTree:\n")) ; - for (i = 0 ; i < n ; i++) - { - AMD_DEBUG2 ((" "ID" parent: "ID" ", i, Pe [i])) ; - ASSERT (Pe [i] >= EMPTY && Pe [i] < n) ; - if (Nv [i] > 0) - { - /* this is an element */ - e = i ; - AMD_DEBUG2 ((" element, size is "ID"\n", Elen [i])) ; - ASSERT (Elen [e] > 0) ; - } - AMD_DEBUG2 (("\n")) ; - } - AMD_DEBUG2 (("\nelements:\n")) ; - for (e = 0 ; e < n ; e++) - { - if (Nv [e] > 0) - { - AMD_DEBUG3 (("Element e= "ID" size "ID" nv "ID" \n", e, - Elen [e], Nv [e])) ; - } - } - AMD_DEBUG2 (("\nvariables:\n")) ; - for (i = 0 ; i < n ; i++) - { - Int cnt ; - if (Nv [i] == 0) - { - AMD_DEBUG3 (("i unordered: "ID"\n", i)) ; - j = Pe [i] ; - cnt = 0 ; - AMD_DEBUG3 ((" j: "ID"\n", j)) ; - if (j == EMPTY) - { - AMD_DEBUG3 ((" i is a dense variable\n")) ; - } - else - { - ASSERT (j >= 0 && j < n) ; - while (Nv [j] == 0) - { - AMD_DEBUG3 ((" j : "ID"\n", j)) ; - j = Pe [j] ; - AMD_DEBUG3 ((" j:: "ID"\n", j)) ; - cnt++ ; - if (cnt > n) break ; - } - e = j ; - AMD_DEBUG3 ((" got to e: "ID"\n", e)) ; - } - } - } -#endif - -/* ========================================================================= */ -/* compress the paths of the variables */ -/* ========================================================================= */ - - for (i = 0 ; i < n ; i++) - { - if (Nv [i] == 0) - { - - /* ------------------------------------------------------------- - * i is an un-ordered row. Traverse the tree from i until - * reaching an element, e. The element, e, was the principal - * supervariable of i and all nodes in the path from i to when e - * was selected as pivot. - * ------------------------------------------------------------- */ - - AMD_DEBUG1 (("Path compression, i unordered: "ID"\n", i)) ; - j = Pe [i] ; - ASSERT (j >= EMPTY && j < n) ; - AMD_DEBUG3 ((" j: "ID"\n", j)) ; - if (j == EMPTY) - { - /* Skip a dense variable. It has no parent. */ - AMD_DEBUG3 ((" i is a dense variable\n")) ; - continue ; - } - - /* while (j is a variable) */ - while (Nv [j] == 0) - { - AMD_DEBUG3 ((" j : "ID"\n", j)) ; - j = Pe [j] ; - AMD_DEBUG3 ((" j:: "ID"\n", j)) ; - ASSERT (j >= 0 && j < n) ; - } - /* got to an element e */ - e = j ; - AMD_DEBUG3 (("got to e: "ID"\n", e)) ; - - /* ------------------------------------------------------------- - * traverse the path again from i to e, and compress the path - * (all nodes point to e). Path compression allows this code to - * compute in O(n) time. - * ------------------------------------------------------------- */ - - j = i ; - /* while (j is a variable) */ - while (Nv [j] == 0) - { - jnext = Pe [j] ; - AMD_DEBUG3 (("j "ID" jnext "ID"\n", j, jnext)) ; - Pe [j] = e ; - j = jnext ; - ASSERT (j >= 0 && j < n) ; - } - } - } - -/* ========================================================================= */ -/* postorder the assembly tree */ -/* ========================================================================= */ - - AMD_postorder (n, Pe, Nv, Elen, - W, /* output order */ - Head, Next, Last) ; /* workspace */ - -/* ========================================================================= */ -/* compute output permutation and inverse permutation */ -/* ========================================================================= */ - - /* W [e] = k means that element e is the kth element in the new - * order. e is in the range 0 to n-1, and k is in the range 0 to - * the number of elements. Use Head for inverse order. */ - - for (k = 0 ; k < n ; k++) - { - Head [k] = EMPTY ; - Next [k] = EMPTY ; - } - for (e = 0 ; e < n ; e++) - { - k = W [e] ; - ASSERT ((k == EMPTY) == (Nv [e] == 0)) ; - if (k != EMPTY) - { - ASSERT (k >= 0 && k < n) ; - Head [k] = e ; - } - } - - /* construct output inverse permutation in Next, - * and permutation in Last */ - nel = 0 ; - for (k = 0 ; k < n ; k++) - { - e = Head [k] ; - if (e == EMPTY) break ; - ASSERT (e >= 0 && e < n && Nv [e] > 0) ; - Next [e] = nel ; - nel += Nv [e] ; - } - ASSERT (nel == n - ndense) ; - - /* order non-principal variables (dense, & those merged into supervar's) */ - for (i = 0 ; i < n ; i++) - { - if (Nv [i] == 0) - { - e = Pe [i] ; - ASSERT (e >= EMPTY && e < n) ; - if (e != EMPTY) - { - /* This is an unordered variable that was merged - * into element e via supernode detection or mass - * elimination of i when e became the pivot element. - * Place i in order just before e. */ - ASSERT (Next [i] == EMPTY && Nv [e] > 0) ; - Next [i] = Next [e] ; - Next [e]++ ; - } - else - { - /* This is a dense unordered variable, with no parent. - * Place it last in the output order. */ - Next [i] = nel++ ; - } - } - } - ASSERT (nel == n) ; - - AMD_DEBUG2 (("\n\nPerm:\n")) ; - for (i = 0 ; i < n ; i++) - { - k = Next [i] ; - ASSERT (k >= 0 && k < n) ; - Last [k] = i ; - AMD_DEBUG2 ((" perm ["ID"] = "ID"\n", k, i)) ; - } -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amd_aat.c --- a/liboctave/UMFPACK/AMD/Source/amd_aat.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ -/* ========================================================================= */ -/* === AMD_aat ============================================================= */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* AMD_aat: compute the symmetry of the pattern of A, and count the number of - * nonzeros each column of A+A' (excluding the diagonal). Assume the input - * matrix has no errors. - */ - -#include "amd_internal.h" - -GLOBAL Int AMD_aat /* returns nz in A+A' */ -( - Int n, - const Int Ap [ ], - const Int Ai [ ], - Int Len [ ], /* Len [j]: length of column j of A+A', excl diagonal*/ - Int Tp [ ], /* workspace of size n */ - double Info [ ] -) -{ - Int p1, p2, p, i, j, pj, pj2, k, nzdiag, nzboth, nz, nzaat ; - double sym ; - -#ifndef NDEBUG - AMD_debug_init ("AMD AAT") ; - for (k = 0 ; k < n ; k++) Tp [k] = EMPTY ; - ASSERT (AMD_valid (n, n, Ap, Ai)) ; -#endif - - if (Info != (double *) NULL) - { - /* clear the Info array, if it exists */ - for (i = 0 ; i < AMD_INFO ; i++) - { - Info [i] = EMPTY ; - } - Info [AMD_STATUS] = AMD_OK ; - } - - for (k = 0 ; k < n ; k++) - { - Len [k] = 0 ; - } - - nzdiag = 0 ; - nzboth = 0 ; - nz = Ap [n] ; - - for (k = 0 ; k < n ; k++) - { - p1 = Ap [k] ; - p2 = Ap [k+1] ; - AMD_DEBUG2 (("\nAAT Column: "ID" p1: "ID" p2: "ID"\n", k, p1, p2)) ; - - /* construct A+A' */ - for (p = p1 ; p < p2 ; ) - { - /* scan the upper triangular part of A */ - j = Ai [p] ; - if (j < k) - { - /* entry A (j,k) is in the strictly upper triangular part, - * add both A (j,k) and A (k,j) to the matrix A+A' */ - Len [j]++ ; - Len [k]++ ; - AMD_DEBUG3 ((" upper ("ID","ID") ("ID","ID")\n", j,k, k,j)); - p++ ; - } - else if (j == k) - { - /* skip the diagonal */ - p++ ; - nzdiag++ ; - break ; - } - else /* j > k */ - { - /* first entry below the diagonal */ - break ; - } - /* scan lower triangular part of A, in column j until reaching - * row k. Start where last scan left off. */ - ASSERT (Tp [j] != EMPTY) ; - ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ; - pj2 = Ap [j+1] ; - for (pj = Tp [j] ; pj < pj2 ; ) - { - i = Ai [pj] ; - if (i < k) - { - /* A (i,j) is only in the lower part, not in upper. - * add both A (i,j) and A (j,i) to the matrix A+A' */ - Len [i]++ ; - Len [j]++ ; - AMD_DEBUG3 ((" lower ("ID","ID") ("ID","ID")\n", - i,j, j,i)) ; - pj++ ; - } - else if (i == k) - { - /* entry A (k,j) in lower part and A (j,k) in upper */ - pj++ ; - nzboth++ ; - break ; - } - else /* i > k */ - { - /* consider this entry later, when k advances to i */ - break ; - } - } - Tp [j] = pj ; - } - /* Tp [k] points to the entry just below the diagonal in column k */ - Tp [k] = p ; - } - - /* clean up, for remaining mismatched entries */ - for (j = 0 ; j < n ; j++) - { - for (pj = Tp [j] ; pj < Ap [j+1] ; pj++) - { - i = Ai [pj] ; - /* A (i,j) is only in the lower part, not in upper. - * add both A (i,j) and A (j,i) to the matrix A+A' */ - Len [i]++ ; - Len [j]++ ; - AMD_DEBUG3 ((" lower cleanup ("ID","ID") ("ID","ID")\n", - i,j, j,i)) ; - } - } - - /* --------------------------------------------------------------------- */ - /* compute the symmetry of the nonzero pattern of A */ - /* --------------------------------------------------------------------- */ - - /* Given a matrix A, the symmetry of A is: - * B = tril (spones (A), -1) + triu (spones (A), 1) ; - * sym = nnz (B & B') / nnz (B) ; - * or 1 if nnz (B) is zero. - */ - - if (nz == nzdiag) - { - sym = 1 ; - } - else - { - sym = ((double) (2 * nzboth)) / ((double) (nz - nzdiag)) ; - } - - nzaat = 0 ; - for (k = 0 ; k < n ; k++) - { - nzaat += Len [k] ; - } - AMD_DEBUG1 (("AMD nz in A+A', excluding diagonal (nzaat) = "ID"\n",nzaat)); - AMD_DEBUG1 ((" nzboth: "ID" nz: "ID" nzdiag: "ID" symmetry: %g\n", - nzboth, nz, nzdiag, sym)) ; - - if (Info != (double *) NULL) - { - Info [AMD_STATUS] = AMD_OK ; - Info [AMD_N] = n ; - Info [AMD_NZ] = nz ; - Info [AMD_SYMMETRY] = sym ; /* symmetry of pattern of A */ - Info [AMD_NZDIAG] = nzdiag ; /* nonzeros on diagonal of A */ - Info [AMD_NZ_A_PLUS_AT] = nzaat ; /* nonzeros in A+A' */ - } - - return (nzaat) ; -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amd_control.c --- a/liboctave/UMFPACK/AMD/Source/amd_control.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* ========================================================================= */ -/* === AMD_control ========================================================= */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* User-callable. Prints the control parameters for AMD. See amd.h - * for details. If the Control array is not present, the defaults are - * printed instead. - */ - -#include "amd_internal.h" - -GLOBAL void AMD_control -( - double Control [ ] -) -{ - double alpha ; - Int aggressive ; - - if (Control != (double *) NULL) - { - alpha = Control [AMD_DENSE] ; - aggressive = Control [AMD_AGGRESSIVE] != 0 ; - } - else - { - alpha = AMD_DEFAULT_DENSE ; - aggressive = AMD_DEFAULT_AGGRESSIVE ; - } - - PRINTF (("\namd: approximate minimum degree ordering, parameters:\n" - " dense row parameter: %g\n", alpha)) ; - - if (alpha < 0) - { - PRINTF ((" no rows treated as dense\n")) ; - } - else - { - PRINTF (( - " (rows with more than max (%g * sqrt (n), 16) entries are\n" - " considered \"dense\", and placed last in output permutation)\n", - alpha)) ; - } - - if (aggressive) - { - PRINTF ((" aggressive absorption: yes\n\n")) ; - } - else - { - PRINTF ((" aggressive absorption: no\n\n")) ; - } -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amd_defaults.c --- a/liboctave/UMFPACK/AMD/Source/amd_defaults.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* ========================================================================= */ -/* === AMD_defaults ======================================================== */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* User-callable. Sets default control parameters for AMD. See amd.h - * for details. - */ - -#include "amd_internal.h" - -GLOBAL void AMD_defaults -( - double Control [ ] -) -{ - Int i ; - if (Control != (double *) NULL) - { - for (i = 0 ; i < AMD_CONTROL ; i++) - { - Control [i] = 0 ; - } - Control [AMD_DENSE] = AMD_DEFAULT_DENSE ; - Control [AMD_AGGRESSIVE] = AMD_DEFAULT_AGGRESSIVE ; - } -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amd_dump.c --- a/liboctave/UMFPACK/AMD/Source/amd_dump.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,176 +0,0 @@ -/* ========================================================================= */ -/* === AMD_dump ============================================================ */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* Debugging routines for AMD. Not used if NDEBUG is not defined at compile- - * time (the default). See comments in amd_internal.h on how to enable - * debugging. Not user-callable. - */ - -#include "amd_internal.h" - -#ifndef NDEBUG - -/* This global variable is present only when debugging */ -GLOBAL Int AMD_debug = -999 ; /* default is no debug printing */ - -/* ========================================================================= */ -/* === AMD_debug_init ====================================================== */ -/* ========================================================================= */ - -/* Sets the debug print level, by reading the file debug.amd (if it exists) */ - -GLOBAL void AMD_debug_init ( char *s ) -{ - FILE *f ; - f = fopen ("debug.amd", "r") ; - if (f == (FILE *) NULL) - { - AMD_debug = -999 ; - } - else - { - fscanf (f, ID, &AMD_debug) ; - fclose (f) ; - } - if (AMD_debug >= 0) printf ("%s: AMD_debug_init, D= "ID"\n", s, AMD_debug); -} - -/* ========================================================================= */ -/* === AMD_dump ============================================================ */ -/* ========================================================================= */ - -/* Dump AMD's data structure, except for the hash buckets. This routine - * cannot be called when the hash buckets are non-empty. - */ - -GLOBAL void AMD_dump ( - Int n, /* A is n-by-n */ - Int Pe [ ], /* pe [0..n-1]: index in iw of start of row i */ - Int Iw [ ], /* workspace of size iwlen, iwlen [0..pfree-1] - * holds the matrix on input */ - Int Len [ ], /* len [0..n-1]: length for row i */ - Int iwlen, /* length of iw */ - Int pfree, /* iw [pfree ... iwlen-1] is empty on input */ - Int Nv [ ], /* nv [0..n-1] */ - Int Next [ ], /* next [0..n-1] */ - Int Last [ ], /* last [0..n-1] */ - Int Head [ ], /* head [0..n-1] */ - Int Elen [ ], /* size n */ - Int Degree [ ], /* size n */ - Int W [ ], /* size n */ - Int nel -) -{ - Int i, pe, elen, nv, len, e, p, k, j, deg, w, cnt, ilast ; - - if (AMD_debug < 0) return ; - ASSERT (pfree <= iwlen) ; - for (i = 0 ; i < n ; i++) - { - pe = Pe [i] ; - elen = Elen [i] ; - nv = Nv [i] ; - len = Len [i] ; - w = W [i] ; - - if (elen >= EMPTY) - { - if (nv == 0) - { - AMD_DEBUG3 (("\nI "ID": nonprincipal: ", i)) ; - ASSERT (elen == EMPTY) ; - if (pe == EMPTY) - { - AMD_DEBUG3 ((" dense node\n")) ; - ASSERT (w == 1) ; - } - else - { - ASSERT (pe < EMPTY) ; - AMD_DEBUG3 ((" i "ID" -> parent "ID"\n", i, FLIP (Pe[i]))); - } - } - else - { - AMD_DEBUG3 (("\nI "ID": active principal supervariable:\n",i)); - AMD_DEBUG3 ((" nv(i): "ID" Flag: %d\n", nv, (nv < 0))) ; - ASSERT (elen >= 0) ; - ASSERT (nv > 0 && pe >= 0) ; - p = pe ; - AMD_DEBUG3 ((" e/s: ")) ; - if (elen == 0) AMD_DEBUG3 ((" : ")) ; - ASSERT (pe < pfree) ; - for (k = 0 ; k < len ; k++) - { - j = Iw [p] ; - AMD_DEBUG3 ((" "ID"", j)) ; - ASSERT (j >= 0 && j < n) ; - if (k == elen-1) AMD_DEBUG3 ((" : ")) ; - p++ ; - } - AMD_DEBUG3 (("\n")) ; - } - } - else - { - e = i ; - if (w == 0) - { - AMD_DEBUG3 (("\nE "ID": absorbed element: w "ID"\n", e, w)) ; - ASSERT (nv > 0 && pe < 0) ; - AMD_DEBUG3 ((" e "ID" -> parent "ID"\n", e, FLIP (Pe [e]))) ; - } - else - { - AMD_DEBUG3 (("\nE "ID": unabsorbed element: w "ID"\n", e, w)) ; - ASSERT (nv > 0 && pe >= 0) ; - p = pe ; - AMD_DEBUG3 ((" : ")) ; - ASSERT (pe < pfree) ; - for (k = 0 ; k < len ; k++) - { - j = Iw [p] ; - AMD_DEBUG3 ((" "ID"", j)) ; - ASSERT (j >= 0 && j < n) ; - p++ ; - } - AMD_DEBUG3 (("\n")) ; - } - } - } - - /* this routine cannot be called when the hash buckets are non-empty */ - AMD_DEBUG3 (("\nDegree lists:\n")) ; - if (nel >= 0) - { - cnt = 0 ; - for (deg = 0 ; deg < n ; deg++) - { - if (Head [deg] == EMPTY) continue ; - ilast = EMPTY ; - AMD_DEBUG3 ((ID": ", deg)) ; - for (i = Head [deg] ; i != EMPTY ; i = Next [i]) - { - AMD_DEBUG3 ((" "ID" : next "ID" last "ID" deg "ID"\n", - i, Next [i], Last [i], Degree [i])) ; - ASSERT (i >= 0 && i < n && ilast == Last [i] && - deg == Degree [i]) ; - cnt += Nv [i] ; - ilast = i ; - } - AMD_DEBUG3 (("\n")) ; - } - ASSERT (cnt == n - nel) ; - } - -} - -#endif diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amd_info.c --- a/liboctave/UMFPACK/AMD/Source/amd_info.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -/* ========================================================================= */ -/* === AMD_info ============================================================ */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* User-callable. Prints the output statistics for AMD. See amd.h - * for details. If the Info array is not present, nothing is printed. - */ - -#include "amd_internal.h" - -#define PRI(format,x) { if (x >= 0) { PRINTF ((format, x)) ; }} - -GLOBAL void AMD_info -( - double Info [ ] -) -{ - double n, ndiv, nmultsubs_ldl, nmultsubs_lu, lnz, lnzd ; - - if (!Info) - { - return ; - } - - n = Info [AMD_N] ; - ndiv = Info [AMD_NDIV] ; - nmultsubs_ldl = Info [AMD_NMULTSUBS_LDL] ; - nmultsubs_lu = Info [AMD_NMULTSUBS_LU] ; - lnz = Info [AMD_LNZ] ; - lnzd = (n >= 0 && lnz >= 0) ? (n + lnz) : (-1) ; - - /* AMD return status */ - PRINTF (( - "\namd: approximate minimum degree ordering, results:\n" - " status: ")) ; - if (Info [AMD_STATUS] == AMD_OK) - { - PRINTF (("OK\n")) ; - } - else if (Info [AMD_STATUS] == AMD_OUT_OF_MEMORY) - { - PRINTF (("out of memory\n")) ; - } - else if (Info [AMD_STATUS] == AMD_INVALID) - { - PRINTF (("invalid matrix\n")) ; - } - else - { - PRINTF (("unknown\n")) ; - } - - /* statistics about the input matrix */ - PRI (" n, dimension of A: %.20g\n", n); - PRI (" nz, number of nonzeros in A: %.20g\n", - Info [AMD_NZ]) ; - PRI (" symmetry of A: %.4f\n", - Info [AMD_SYMMETRY]) ; - PRI (" number of nonzeros on diagonal: %.20g\n", - Info [AMD_NZDIAG]) ; - PRI (" nonzeros in pattern of A+A' (excl. diagonal): %.20g\n", - Info [AMD_NZ_A_PLUS_AT]) ; - PRI (" # dense rows/columns of A+A': %.20g\n", - Info [AMD_NDENSE]) ; - - /* statistics about AMD's behavior */ - PRI (" memory used, in bytes: %.20g\n", - Info [AMD_MEMORY]) ; - PRI (" # of memory compactions: %.20g\n", - Info [AMD_NCMPA]) ; - - /* statistics about the ordering quality */ - PRINTF (("\n" - " The following approximate statistics are for a subsequent\n" - " factorization of A(P,P) + A(P,P)'. They are slight upper\n" - " bounds if there are no dense rows/columns in A+A', and become\n" - " looser if dense rows/columns exist.\n\n")) ; - - PRI (" nonzeros in L (excluding diagonal): %.20g\n", - lnz) ; - PRI (" nonzeros in L (including diagonal): %.20g\n", - lnzd) ; - PRI (" # divide operations for LDL' or LU: %.20g\n", - ndiv) ; - PRI (" # multiply-subtract operations for LDL': %.20g\n", - nmultsubs_ldl) ; - PRI (" # multiply-subtract operations for LU: %.20g\n", - nmultsubs_lu) ; - PRI (" max nz. in any column of L (incl. diagonal): %.20g\n", - Info [AMD_DMAX]) ; - - /* total flop counts for various factorizations */ - - if (n >= 0 && ndiv >= 0 && nmultsubs_ldl >= 0 && nmultsubs_lu >= 0) - { - PRINTF (("\n" - " chol flop count for real A, sqrt counted as 1 flop: %.20g\n" - " LDL' flop count for real A: %.20g\n" - " LDL' flop count for complex A: %.20g\n" - " LU flop count for real A (with no pivoting): %.20g\n" - " LU flop count for complex A (with no pivoting): %.20g\n\n", - n + ndiv + 2*nmultsubs_ldl, - ndiv + 2*nmultsubs_ldl, - 9*ndiv + 8*nmultsubs_ldl, - ndiv + 2*nmultsubs_lu, - 9*ndiv + 8*nmultsubs_lu)) ; - } -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amd_internal.h --- a/liboctave/UMFPACK/AMD/Source/amd_internal.h Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,426 +0,0 @@ -/* ========================================================================= */ -/* === amd_internal.h ====================================================== */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* This file is for internal use in AMD itself, and does not normally need to - * be included in user code. Use amd.h instead. - * - * The following compile-time definitions affect how AMD is compiled. - * - * -DMATLAB_MEX_FILE - * - * This flag is turned on when compiling the amd mexFunction for - * use in MATLAB. - * - * -DMATHWORKS - * - * This flag is turned on when compiling amd as a built-in routine - * in MATLAB. Internal routines utMalloc, utFree, utRealloc, and - * utPrintf are used, and the MathWorks "util.h" file is included. - * This option is intended for use by The MathWorks, Inc., only. - * - * -DNDEBUG - * - * Debugging mode (if NDEBUG is not defined). The default, of course, - * is no debugging. Turning on debugging takes some work (see below). - * If you do not edit this file, then debugging is turned off anyway, - * regardless of whether or not -DNDEBUG is specified in your compiler - * options. - * - * -DALLOCATE=allocation_routine - * -DFREE=free_routine - * - * If you do not wish to use malloc or free, you can define the - * routines to be used here. You must specify both of them, or - * neither. - * - * -DPRINTF=printf_routine - * - * If you wish to use a routine other than printf, you can define it - * with -DPRINTF= followed by the name of the printf replacement. - */ - -/* ========================================================================= */ -/* === NDEBUG ============================================================== */ -/* ========================================================================= */ - -/* - AMD will be exceedingly slow when running in debug mode. The next three - lines ensure that debugging is turned off. -*/ -#ifndef NDEBUG -#define NDEBUG -#endif - -/* - To enable debugging, uncomment the following line: -#undef NDEBUG -*/ - -/* ------------------------------------------------------------------------- */ -/* ANSI include files */ -/* ------------------------------------------------------------------------- */ - -/* from stdlib.h: malloc, free, realloc (when not compiling for MATLAB) */ -#include - -/* from stdio.h: printf. When in debug mode: fopen, fscanf */ -#include - -/* from limits.h: INT_MAX and LONG_MAX */ -#include - -/* from math.h: sqrt */ -#include - -/* ------------------------------------------------------------------------- */ -/* MATLAB include files (only if being used in or via MATLAB) */ -/* ------------------------------------------------------------------------- */ - -#ifdef MATHWORKS -#include "util.h" -#endif - -#ifdef MATLAB_MEX_FILE -#include "matrix.h" -#include "mex.h" -#endif - -/* ------------------------------------------------------------------------- */ -/* basic definitions */ -/* ------------------------------------------------------------------------- */ - -#ifdef FLIP -#undef FLIP -#endif - -#ifdef MAX -#undef MAX -#endif - -#ifdef MIN -#undef MIN -#endif - -#ifdef EMPTY -#undef EMPTY -#endif - -#ifdef GLOBAL -#undef GLOBAL -#endif - -#ifdef PRIVATE -#undef PRIVATE -#endif - -/* FLIP is a "negation about -1", and is used to mark an integer i that is - * normally non-negative. FLIP (EMPTY) is EMPTY. FLIP of a number > EMPTY - * is negative, and FLIP of a number < EMTPY is positive. FLIP (FLIP (i)) = i - * for all integers i. UNFLIP (i) is >= EMPTY. */ -#define EMPTY (-1) -#define FLIP(i) (-(i)-2) -#define UNFLIP(i) ((i < EMPTY) ? FLIP (i) : (i)) - -/* for integer MAX/MIN, or for doubles when we don't care how NaN's behave: */ -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) - -/* logical expression of p implies q: */ -#define IMPLIES(p,q) (!(p) || (q)) - -/* Note that the IBM RS 6000 xlc predefines TRUE and FALSE in . */ -/* The Compaq Alpha also predefines TRUE and FALSE. */ -#ifdef TRUE -#undef TRUE -#endif -#ifdef FALSE -#undef FALSE -#endif - -#define TRUE (1) -#define FALSE (0) -#define PRIVATE static -#define GLOBAL -#define EMPTY (-1) - -/* Note that Linux's gcc 2.96 defines NULL as ((void *) 0), but other */ -/* compilers (even gcc 2.95.2 on Solaris) define NULL as 0 or (0). We */ -/* need to use the ANSI standard value of 0. */ -#ifdef NULL -#undef NULL -#endif - -#define NULL 0 - -/* ------------------------------------------------------------------------- */ -/* integer type for AMD: int or long */ -/* ------------------------------------------------------------------------- */ - -#if defined (DLONG) || defined (ZLONG) - -#define Int long -#define ID "%ld" -#define Int_MAX LONG_MAX -#define Int_MIN LONG_MIN - -#define AMD_order amd_l_order -#define AMD_defaults amd_l_defaults -#define AMD_control amd_l_control -#define AMD_info amd_l_info -#define AMD_1 amd_l1 -#define AMD_2 amd_l2 -#define AMD_valid amd_l_valid -#define AMD_aat amd_l_aat -#define AMD_postorder amd_l_postorder -#define AMD_post_tree amd_l_post_tree -#define AMD_dump amd_l_dump -#define AMD_debug amd_l_debug -#define AMD_debug_init amd_l_debug_init -#define AMD_wpreprocess amd_l_wpreprocess -#define AMD_preprocess amd_l_preprocess -#define AMD_preprocess_valid amd_l_preprocess_valid - -#else - -#define Int int -#define ID "%d" -#define Int_MAX INT_MAX -#define Int_MIN INT_MIN - -#define AMD_order amd_order -#define AMD_defaults amd_defaults -#define AMD_control amd_control -#define AMD_info amd_info -#define AMD_1 amd_1 -#define AMD_2 amd_2 -#define AMD_valid amd_valid -#define AMD_aat amd_aat -#define AMD_postorder amd_postorder -#define AMD_post_tree amd_post_tree -#define AMD_dump amd_dump -#define AMD_debug amd_debug -#define AMD_debug_init amd_debug_init -#define AMD_wpreprocess amd_wpreprocess -#define AMD_preprocess amd_preprocess -#define AMD_preprocess_valid amd_preprocess_valid - -#endif - -/* ========================================================================= */ -/* === Memory allocator ==================================================== */ -/* ========================================================================= */ - -/* The MATLAB mexFunction uses MATLAB's memory manager, while the C-callable */ -/* AMD routine uses the ANSI C malloc, free, and realloc routines. */ - -#ifndef ALLOCATE -#ifdef MATLAB_MEX_FILE -#define ALLOCATE mxMalloc -#define FREE mxFree -#else -#ifdef MATHWORKS -/* Compiling as a built-in routine. Since out-of-memory conditions are checked - * after every allocation, we can use ut* routines here. */ -#define ALLOCATE utMalloc -#define FREE utFree -#else -/* use the ANSI C memory allocation routines */ -#define ALLOCATE malloc -#define FREE free -#endif -#endif -#endif - - -/* ========================================================================= */ -/* === PRINTF macro ======================================================== */ -/* ========================================================================= */ - -/* All output goes through the PRINTF macro. */ - -#ifndef PRINTF -#ifdef MATLAB_MEX_FILE -#define PRINTF(params) { (void) mexPrintf params ; } -#else -#ifdef MATHWORKS -#define PRINTF(params) { (void) utPrintf params ; } -#else -#define PRINTF(params) { (void) printf params ; } -#endif -#endif -#endif - -/* ------------------------------------------------------------------------- */ -/* AMD routine definitions (user-callable) */ -/* ------------------------------------------------------------------------- */ - -#include "amd.h" - -/* ------------------------------------------------------------------------- */ -/* AMD routine definitions (not user-callable) */ -/* ------------------------------------------------------------------------- */ - -GLOBAL Int AMD_valid -( - Int n_row, - Int n_col, - const Int Ap [ ], - const Int Ai [ ] -) ; - -GLOBAL Int AMD_aat -( - Int n, - const Int Ap [ ], - const Int Ai [ ], - Int Len [ ], - Int Tp [ ], - double Info [ ] -) ; - -GLOBAL void AMD_1 -( - Int n, - const Int Ap [ ], - const Int Ai [ ], - Int P [ ], - Int Pinv [ ], - Int Len [ ], - Int slen, - Int S [ ], - double Control [ ], - double Info [ ] -) ; - -GLOBAL void AMD_2 ( - Int n, - Int Pe [ ], - Int Iw [ ], - Int Len [ ], - Int iwlen, - Int pfree, - Int Nv [ ], - Int Next [ ], - Int Last [ ], - Int Head [ ], - Int Elen [ ], - Int Degree [ ], - Int W [ ], - double Control [ ], - double Info [ ] -) ; - -GLOBAL void AMD_postorder -( - Int nn, - Int Parent [ ], - Int Npiv [ ], - Int Fsize [ ], - Int Order [ ], - Int Child [ ], - Int Sibling [ ], - Int Stack [ ] -) ; - -GLOBAL Int AMD_post_tree -( - Int root, - Int k, - Int Child [ ], - const Int Sibling [ ], - Int Order [ ], - Int Stack [ ] -#ifndef NDEBUG - , Int nn -#endif -) ; - -GLOBAL void AMD_wpreprocess -( - Int n, - const Int Ap [ ], - const Int Ai [ ], - Int Rp [ ], - Int Ri [ ], - Int W [ ], - Int Flag [ ] -) ; - -GLOBAL Int AMD_preprocess_valid -( - Int n, - const Int Ap [ ], - const Int Ai [ ] -) ; - -/* ------------------------------------------------------------------------- */ -/* debugging definitions */ -/* ------------------------------------------------------------------------- */ - -/* from assert.h: assert macro */ -#if !defined (MATHWORKS) && !defined (MATLAB_MEX_FILE) -#include -#endif - -#ifndef NDEBUG - -GLOBAL Int AMD_debug ; - -GLOBAL void AMD_debug_init ( char *s ) ; - -GLOBAL void AMD_dump ( - Int n, - Int Pe [ ], - Int Iw [ ], - Int Len [ ], - Int iwlen, - Int pfree, - Int Nv [ ], - Int Next [ ], - Int Last [ ], - Int Head [ ], - Int Elen [ ], - Int Degree [ ], - Int W [ ], - Int nel -) ; - -#ifdef ASSERT -#undef ASSERT -#endif - -#ifdef MATLAB_MEX_FILE -#define ASSERT(expression) (mxAssert ((expression), "")) -#else -#ifdef MATHWORKS -#define ASSERT(expression) (utAssert (expression)) -#else -#define ASSERT(expression) (assert (expression)) -#endif -#endif /* MATLAB_MEX_FILE */ - -#define AMD_DEBUG0(params) { PRINTF (params) ; } -#define AMD_DEBUG1(params) { if (AMD_debug >= 1) PRINTF (params) ; } -#define AMD_DEBUG2(params) { if (AMD_debug >= 2) PRINTF (params) ; } -#define AMD_DEBUG3(params) { if (AMD_debug >= 3) PRINTF (params) ; } -#define AMD_DEBUG4(params) { if (AMD_debug >= 4) PRINTF (params) ; } - -#else - -#define AMD_DEBUG0(params) -#define AMD_DEBUG1(params) -#define AMD_DEBUG2(params) -#define AMD_DEBUG3(params) -#define AMD_DEBUG4(params) - -#define ASSERT(expression) - -#endif diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amd_order.c --- a/liboctave/UMFPACK/AMD/Source/amd_order.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -/* ========================================================================= */ -/* === AMD_order =========================================================== */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* User-callable AMD minimum degree ordering routine. See amd.h for - * documentation. - */ - -#include "amd_internal.h" - -GLOBAL Int AMD_order -( - Int n, - const Int Ap [ ], - const Int Ai [ ], - Int P [ ], - double Control [ ], - double Info [ ] -) -{ - Int slen, *Len, *S, nz, nzaat, i, *Pinv, info ; - -#ifndef NDEBUG - AMD_debug_init ("amd") ; -#endif - - /* clear the Info array, if it exists */ - info = Info != (double *) NULL ; - if (info) - { - for (i = 0 ; i < AMD_INFO ; i++) - { - Info [i] = EMPTY ; - } - Info [AMD_N] = n ; - Info [AMD_STATUS] = AMD_OK ; - } - - /* make sure inputs exist and n is >= 0 */ - if (Ai == (Int *) NULL || Ap == (Int *) NULL || P == (Int *) NULL || n < 0) - { - if (info) Info [AMD_STATUS] = AMD_INVALID ; - return (AMD_INVALID) ; /* arguments are invalid */ - } - - if (n == 0) - { - return (AMD_OK) ; /* n is 0 so there's nothing to do */ - } - - nz = Ap [n] ; - if (info) - { - Info [AMD_NZ] = nz ; - } - if (nz < 0) - { - if (info) Info [AMD_STATUS] = AMD_INVALID ; - return (AMD_INVALID) ; - } - - /* Avoid integer overflow in memory size calculations. The space required - * by AMD is at most 2.4nz + 8n for S, and n for Len. - * Note nz - n <= nzaat <= 2*nz, below. */ - if ((2.4 * (double) nz + 8 * (double) n) > (double) Int_MAX / sizeof (Int)) - { - /* :: int overflow :: */ - if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; - return (AMD_OUT_OF_MEMORY) ; - } - - if (!AMD_valid (n, n, Ap, Ai)) - { - if (info) Info [AMD_STATUS] = AMD_INVALID ; - return (AMD_INVALID) ; /* matrix is invalid */ - } - - /* --------------------------------------------------------------------- */ - /* determine the symmetry and count off-diagonal nonzeros in A+A' */ - /* --------------------------------------------------------------------- */ - - /* allocate size-n integer workspace */ - Len = (Int *) ALLOCATE (n * sizeof (Int)) ; - if (!Len) - { - /* :: out of memory :: */ - if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; - return (AMD_OUT_OF_MEMORY) ; - } - nzaat = AMD_aat (n, Ap, Ai, Len, P, Info) ; - AMD_DEBUG1 (("nzaat: "ID"\n", nzaat)) ; - ASSERT (nz-n <= nzaat && nzaat <= 2*nz) ; - - /* --------------------------------------------------------------------- */ - /* allocate workspace for matrix, elbow room, and 7 size-n vectors */ - /* --------------------------------------------------------------------- */ - - slen = (nzaat + nzaat/5 + n) + 7*n ; - if (info) - { - /* memory usage (Len and S), in bytes. */ - Info [AMD_MEMORY] = ((double) slen + n) * sizeof (Int) ; - } - S = (Int *) ALLOCATE (slen * sizeof (Int)) ; - AMD_DEBUG1 ((" S "ID" Len "ID" n "ID" nzaat "ID" slen "ID"\n", - (Int) S, (Int) Len, n, nzaat, slen)) ; - if (S == (Int *) NULL) - { - /* :: out of memory :: */ - FREE (Len) ; - if (Info != (double *) NULL) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; - return (AMD_OUT_OF_MEMORY) ; - } - - /* allocate space from S for Pinv */ - Pinv = S + slen - n ; - slen -= n ; - - /* --------------------------------------------------------------------- */ - /* order the matrix */ - /* --------------------------------------------------------------------- */ - - AMD_1 (n, Ap, Ai, P, Pinv, Len, slen, S, Control, Info) ; - - /* --------------------------------------------------------------------- */ - /* free the workspace */ - /* --------------------------------------------------------------------- */ - - FREE (Len) ; - FREE (S) ; - return (AMD_OK) ; /* successful ordering */ -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amd_post_tree.c --- a/liboctave/UMFPACK/AMD/Source/amd_post_tree.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,121 +0,0 @@ -/* ========================================================================= */ -/* === AMD_post_tree ======================================================= */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* Post-ordering of a supernodal elimination tree. */ - -#include "amd_internal.h" - -GLOBAL Int AMD_post_tree -( - Int root, /* root of the tree */ - Int k, /* start numbering at k */ - Int Child [ ], /* input argument of size nn, undefined on - * output. Child [i] is the head of a link - * list of all nodes that are children of node - * i in the tree. */ - const Int Sibling [ ], /* input argument of size nn, not modified. - * If f is a node in the link list of the - * children of node i, then Sibling [f] is the - * next child of node i. - */ - Int Order [ ], /* output order, of size nn. Order [i] = k - * if node i is the kth node of the reordered - * tree. */ - Int Stack [ ] /* workspace of size nn */ -#ifndef NDEBUG - , Int nn /* nodes are in the range 0..nn-1. */ -#endif -) -{ - Int f, head, h, i ; - -#if 0 - /* --------------------------------------------------------------------- */ - /* recursive version (Stack [ ] is not used): */ - /* --------------------------------------------------------------------- */ - - /* this is simple, but can caouse stack overflow if nn is large */ - i = root ; - for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) - { - k = AMD_post_tree (f, k, Child, Sibling, Order, Stack, nn) ; - } - Order [i] = k++ ; - return (k) ; -#endif - - /* --------------------------------------------------------------------- */ - /* non-recursive version, using an explicit stack */ - /* --------------------------------------------------------------------- */ - - /* push root on the stack */ - head = 0 ; - Stack [0] = root ; - - while (head >= 0) - { - /* get head of stack */ - ASSERT (head < nn) ; - i = Stack [head] ; - AMD_DEBUG1 (("head of stack "ID" \n", i)) ; - ASSERT (i >= 0 && i < nn) ; - - if (Child [i] != EMPTY) - { - /* the children of i are not yet ordered */ - /* push each child onto the stack in reverse order */ - /* so that small ones at the head of the list get popped first */ - /* and the biggest one at the end of the list gets popped last */ - for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) - { - head++ ; - ASSERT (head < nn) ; - ASSERT (f >= 0 && f < nn) ; - } - h = head ; - ASSERT (head < nn) ; - for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) - { - ASSERT (h > 0) ; - Stack [h--] = f ; - AMD_DEBUG1 (("push "ID" on stack\n", f)) ; - ASSERT (f >= 0 && f < nn) ; - } - ASSERT (Stack [h] == i) ; - - /* delete child list so that i gets ordered next time we see it */ - Child [i] = EMPTY ; - } - else - { - /* the children of i (if there were any) are already ordered */ - /* remove i from the stack and order it. Front i is kth front */ - head-- ; - AMD_DEBUG1 (("pop "ID" order "ID"\n", i, k)) ; - Order [i] = k++ ; - ASSERT (k <= nn) ; - } - -#ifndef NDEBUG - AMD_DEBUG1 (("\nStack:")) ; - for (h = head ; h >= 0 ; h--) - { - Int j = Stack [h] ; - AMD_DEBUG1 ((" "ID, j)) ; - ASSERT (j >= 0 && j < nn) ; - } - AMD_DEBUG1 (("\n\n")) ; - ASSERT (head < nn) ; -#endif - - } - return (k) ; -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amd_postorder.c --- a/liboctave/UMFPACK/AMD/Source/amd_postorder.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,207 +0,0 @@ -/* ========================================================================= */ -/* === AMD_postorder ======================================================= */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* Perform a postordering (via depth-first search) of an assembly tree. */ - -#include "amd_internal.h" - -GLOBAL void AMD_postorder -( - /* inputs, not modified on output: */ - Int nn, /* nodes are in the range 0..nn-1 */ - Int Parent [ ], /* Parent [j] is the parent of j, or EMPTY if root */ - Int Nv [ ], /* Nv [j] > 0 number of pivots represented by node j, - * or zero if j is not a node. */ - Int Fsize [ ], /* Fsize [j]: size of node j */ - - /* output, not defined on input: */ - Int Order [ ], /* output post-order */ - - /* workspaces of size nn: */ - Int Child [ ], - Int Sibling [ ], - Int Stack [ ] -) -{ - Int i, j, k, parent, frsize, f, fprev, maxfrsize, bigfprev, bigf, fnext ; - - for (j = 0 ; j < nn ; j++) - { - Child [j] = EMPTY ; - Sibling [j] = EMPTY ; - } - - /* --------------------------------------------------------------------- */ - /* place the children in link lists - bigger elements tend to be last */ - /* --------------------------------------------------------------------- */ - - for (j = nn-1 ; j >= 0 ; j--) - { - if (Nv [j] > 0) - { - /* this is an element */ - parent = Parent [j] ; - if (parent != EMPTY) - { - /* place the element in link list of the children its parent */ - /* bigger elements will tend to be at the end of the list */ - Sibling [j] = Child [parent] ; - Child [parent] = j ; - } - } - } - -#ifndef NDEBUG - { - Int nels, ff, nchild ; - AMD_DEBUG1 (("\n\n================================ AMD_postorder:\n")); - nels = 0 ; - for (j = 0 ; j < nn ; j++) - { - if (Nv [j] > 0) - { - AMD_DEBUG1 (( ""ID" : nels "ID" npiv "ID" size "ID - " parent "ID" maxfr "ID"\n", j, nels, - Nv [j], Fsize [j], Parent [j], Fsize [j])) ; - /* this is an element */ - /* dump the link list of children */ - nchild = 0 ; - AMD_DEBUG1 ((" Children: ")) ; - for (ff = Child [j] ; ff != EMPTY ; ff = Sibling [ff]) - { - AMD_DEBUG1 ((ID" ", ff)) ; - ASSERT (Parent [ff] == j) ; - nchild++ ; - ASSERT (nchild < nn) ; - } - AMD_DEBUG1 (("\n")) ; - parent = Parent [j] ; - if (parent != EMPTY) - { - ASSERT (Nv [parent] > 0) ; - } - nels++ ; - } - } - } - AMD_DEBUG1 (("\n\nGo through the children of each node, and put\n" - "the biggest child last in each list:\n")) ; -#endif - - /* --------------------------------------------------------------------- */ - /* place the largest child last in the list of children for each node */ - /* --------------------------------------------------------------------- */ - - for (i = 0 ; i < nn ; i++) - { - if (Nv [i] > 0 && Child [i] != EMPTY) - { - -#ifndef NDEBUG - Int nchild ; - AMD_DEBUG1 (("Before partial sort, element "ID"\n", i)) ; - nchild = 0 ; - for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) - { - ASSERT (f >= 0 && f < nn) ; - AMD_DEBUG1 ((" f: "ID" size: "ID"\n", f, Fsize [f])) ; - nchild++ ; - ASSERT (nchild <= nn) ; - } -#endif - - /* find the biggest element in the child list */ - fprev = EMPTY ; - maxfrsize = EMPTY ; - bigfprev = EMPTY ; - bigf = EMPTY ; - for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) - { - ASSERT (f >= 0 && f < nn) ; - frsize = Fsize [f] ; - if (frsize >= maxfrsize) - { - /* this is the biggest seen so far */ - maxfrsize = frsize ; - bigfprev = fprev ; - bigf = f ; - } - fprev = f ; - } - ASSERT (bigf != EMPTY) ; - - fnext = Sibling [bigf] ; - - AMD_DEBUG1 (("bigf "ID" maxfrsize "ID" bigfprev "ID" fnext "ID - " fprev " ID"\n", bigf, maxfrsize, bigfprev, fnext, fprev)) ; - - if (fnext != EMPTY) - { - /* if fnext is EMPTY then bigf is already at the end of list */ - - if (bigfprev == EMPTY) - { - /* delete bigf from the element of the list */ - Child [i] = fnext ; - } - else - { - /* delete bigf from the middle of the list */ - Sibling [bigfprev] = fnext ; - } - - /* put bigf at the end of the list */ - Sibling [bigf] = EMPTY ; - ASSERT (Child [i] != EMPTY) ; - ASSERT (fprev != bigf) ; - ASSERT (fprev != EMPTY) ; - Sibling [fprev] = bigf ; - } - -#ifndef NDEBUG - AMD_DEBUG1 (("After partial sort, element "ID"\n", i)) ; - for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) - { - ASSERT (f >= 0 && f < nn) ; - AMD_DEBUG1 ((" "ID" "ID"\n", f, Fsize [f])) ; - ASSERT (Nv [f] > 0) ; - nchild-- ; - } - ASSERT (nchild == 0) ; -#endif - - } - } - - /* --------------------------------------------------------------------- */ - /* postorder the assembly tree */ - /* --------------------------------------------------------------------- */ - - for (i = 0 ; i < nn ; i++) - { - Order [i] = EMPTY ; - } - - k = 0 ; - - for (i = 0 ; i < nn ; i++) - { - if (Parent [i] == EMPTY && Nv [i] > 0) - { - AMD_DEBUG1 (("Root of assembly tree "ID"\n", i)) ; - k = AMD_post_tree (i, k, Child, Sibling, Order, Stack -#ifndef NDEBUG - , nn -#endif - ) ; - } - } -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amd_preprocess.c --- a/liboctave/UMFPACK/AMD/Source/amd_preprocess.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,225 +0,0 @@ -/* ========================================================================= */ -/* === AMD_preprocess ====================================================== */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* Sorts, removes duplicate entries, and transposes from the nonzero pattern of - * a column-form matrix A, to obtain the matrix R. - * See amd.h for a complete description of AMD_preprocess - */ - -#include "amd_internal.h" - -GLOBAL Int AMD_preprocess /* returns AMD_OK if input is OK, AMD_INVALID - * if the matrix is invalid, or AMD_OUT_OF_MEMORY - * if out of memory for the 2n workspace. */ -( - Int n, /* input matrix: A is n-by-n */ - const Int Ap [ ], /* size n+1 */ - const Int Ai [ ], /* size nz = Ap [n] */ - - /* output matrix R: */ - Int Rp [ ], /* size n+1 */ - Int Ri [ ] /* size nz (or less, if duplicates present) */ -) -{ - /* --------------------------------------------------------------------- */ - /* local variables */ - /* --------------------------------------------------------------------- */ - - Int *Flag, *W ; - - /* --------------------------------------------------------------------- */ - /* check inputs (note: fewer restrictions than AMD_order) */ - /* --------------------------------------------------------------------- */ - - if (!AMD_preprocess_valid (n, Ap, Ai) || !Ri || !Rp) - { - return (AMD_INVALID) ; - } - - /* --------------------------------------------------------------------- */ - /* allocate workspace */ - /* --------------------------------------------------------------------- */ - - W = (Int *) ALLOCATE (MAX (n,1) * sizeof (Int)) ; - if (!W) - { - return (AMD_OUT_OF_MEMORY) ; - } - Flag = (Int *) ALLOCATE (MAX (n,1) * sizeof (Int)) ; - if (!Flag) - { - FREE (W) ; - return (AMD_OUT_OF_MEMORY) ; - } - - /* --------------------------------------------------------------------- */ - /* preprocess the matrix: sort, remove duplicates, and transpose */ - /* --------------------------------------------------------------------- */ - - AMD_wpreprocess (n, Ap, Ai, Rp, Ri, W, Flag) ; - - /* --------------------------------------------------------------------- */ - /* free the workspace */ - /* --------------------------------------------------------------------- */ - - FREE (W) ; - FREE (Flag) ; - return (AMD_OK) ; -} - - -/* ========================================================================= */ -/* === AMD_wpreprocess ===================================================== */ -/* ========================================================================= */ - -/* The AMD_wpreprocess routine is not user-callable. It does not check its - * input for errors or allocate workspace (that is done by the user-callable - * AMD_preprocess routine). It does handle the n=0 case. */ - -GLOBAL void AMD_wpreprocess -( - Int n, /* input matrix: A is n-by-n */ - const Int Ap [ ], /* size n+1 */ - const Int Ai [ ], /* size nz = Ap [n] */ - - /* output matrix R: */ - Int Rp [ ], /* size n+1 */ - Int Ri [ ], /* size nz (or less, if duplicates present) */ - - Int W [ ], /* workspace of size n */ - Int Flag [ ] /* workspace of size n */ -) -{ - - /* --------------------------------------------------------------------- */ - /* local variables */ - /* --------------------------------------------------------------------- */ - - Int i, j, p, p2 ; - - /* --------------------------------------------------------------------- */ - /* count the entries in each row of A (excluding duplicates) */ - /* --------------------------------------------------------------------- */ - - for (i = 0 ; i < n ; i++) - { - W [i] = 0 ; /* # of nonzeros in row i (excl duplicates) */ - Flag [i] = EMPTY ; /* Flag [i] = j if i appears in column j */ - } - for (j = 0 ; j < n ; j++) - { - p2 = Ap [j+1] ; - for (p = Ap [j] ; p < p2 ; p++) - { - i = Ai [p] ; - if (Flag [i] != j) - { - /* row index i has not yet appeared in column j */ - W [i]++ ; /* one more entry in row i */ - Flag [i] = j ; /* flag row index i as appearing in col j*/ - } - } - } - - /* --------------------------------------------------------------------- */ - /* compute the row pointers for R */ - /* --------------------------------------------------------------------- */ - - Rp [0] = 0 ; - for (i = 0 ; i < n ; i++) - { - Rp [i+1] = Rp [i] + W [i] ; - } - for (i = 0 ; i < n ; i++) - { - W [i] = Rp [i] ; - Flag [i] = EMPTY ; - } - - /* --------------------------------------------------------------------- */ - /* construct the row form matrix R */ - /* --------------------------------------------------------------------- */ - - /* R = row form of pattern of A */ - for (j = 0 ; j < n ; j++) - { - p2 = Ap [j+1] ; - for (p = Ap [j] ; p < p2 ; p++) - { - i = Ai [p] ; - if (Flag [i] != j) - { - /* row index i has not yet appeared in column j */ - Ri [W [i]++] = j ; /* put col j in row i */ - Flag [i] = j ; /* flag row index i as appearing in col j*/ - } - } - } - -#ifndef NDEBUG - for (j = 0 ; j < n ; j++) - { - ASSERT (W [j] == Rp [j+1]) ; - } - ASSERT (AMD_valid (n, n, Rp, Ri)) ; -#endif -} - - -/* ========================================================================= */ -/* === AMD_preprocess_valid ================================================ */ -/* ========================================================================= */ - -/* Not user-callable. Checks a matrix and returns TRUE if it is valid as input - * to AMD_wpreprocess, FALSE otherwise. */ - -GLOBAL Int AMD_preprocess_valid -( - Int n, - const Int Ap [ ], - const Int Ai [ ] -) -{ - Int i, j, p, nz ; - - if (n < 0 || !Ai || !Ap) - { - return (FALSE) ; - } - nz = Ap [n] ; - if (Ap [0] != 0 || nz < 0) - { - /* column pointers must start at Ap [0] = 0, and Ap [n] must be >= 0 */ - AMD_DEBUG0 (("column 0 pointer bad or nz < 0\n")) ; - return (FALSE) ; - } - for (j = 0 ; j < n ; j++) - { - if (Ap [j] > Ap [j+1]) - { - /* column pointers must be ascending */ - AMD_DEBUG0 (("column "ID" pointer bad\n", j)) ; - return (FALSE) ; - } - } - for (p = 0 ; p < nz ; p++) - { - i = Ai [p] ; - AMD_DEBUG3 (("row: "ID"\n", i)) ; - if (i < 0 || i >= n) - { - /* row index out of range */ - AMD_DEBUG0 (("index out of range, col "ID" row "ID"\n", j, i)) ; - return (FALSE) ; - } - } - return (TRUE) ; -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amd_valid.c --- a/liboctave/UMFPACK/AMD/Source/amd_valid.c Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/* ========================================================================= */ -/* === AMD_valid =========================================================== */ -/* ========================================================================= */ - -/* ------------------------------------------------------------------------- */ -/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */ -/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */ -/* email: davis@cise.ufl.edu CISE Department, Univ. of Florida. */ -/* web: http://www.cise.ufl.edu/research/sparse/amd */ -/* ------------------------------------------------------------------------- */ - -/* Check if a column-form matrix is valid or not. The matrix A is - * n_row-by-n_col. The row indices of entries in column j are in - * Ai [Ap [j] ... Ap [j+1]-1]. Required conditions are: - * - * n_row >= 0 - * n_col >= 0 - * nz = Ap [n_col] >= 0 number of entries in the matrix - * Ap [0] == 0 - * Ap [j] <= Ap [j+1] for all j in the range 0 to n_col. - * row indices in Ai [Ap [j] ... Ap [j+1]-1] must be sorted in ascending - * order, must be in the range 0 to n_row-1, and no duplicate entries - * can exist. - * - * Not user-callable. - */ - -#include "amd_internal.h" - -GLOBAL Int AMD_valid -( - /* inputs, not modified on output: */ - Int n_row, /* A is n_row-by-n_col */ - Int n_col, - const Int Ap [ ], /* column pointers of A, of size n_col+1 */ - const Int Ai [ ] /* row indices of A, of size nz = Ap [n_col] */ -) -{ - Int nz, j, p1, p2, ilast, i, p ; - if (n_row < 0 || n_col < 0) - { - AMD_DEBUG0 (("n must be >= 0: "ID" "ID"\n", n_row, n_col)) ; - return (FALSE) ; - } - nz = Ap [n_col] ; - if (Ap [0] != 0 || nz < 0) - { - /* column pointers must start at Ap [0] = 0, and Ap [n] must be >= 0 */ - AMD_DEBUG0 (("column 0 pointer bad or nz < 0\n")) ; - return (FALSE) ; - } - for (j = 0 ; j < n_col ; j++) - { - p1 = Ap [j] ; - p2 = Ap [j+1] ; - AMD_DEBUG2 (("\nColumn: "ID" p1: "ID" p2: "ID"\n", j, p1, p2)) ; - if (p1 > p2) - { - /* column pointers must be ascending */ - AMD_DEBUG0 (("column "ID" pointer bad\n", j)) ; - return (FALSE) ; - } - ilast = EMPTY ; - for (p = p1 ; p < p2 ; p++) - { - i = Ai [p] ; - AMD_DEBUG3 (("row: "ID"\n", i)) ; - if (i <= ilast || i >= n_row) - { - /* row index out of range, or unsorted */ - AMD_DEBUG0 (("index out of range, col "ID" row "ID"\n", j, i)); - return (FALSE) ; - } - ilast = i ; - } - } - return (TRUE) ; -} diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/AMD/Source/amdbar.f --- a/liboctave/UMFPACK/AMD/Source/amdbar.f Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1206 +0,0 @@ -C----------------------------------------------------------------------- -C AMDBAR: approximate minimum degree, without aggressive absorption -C----------------------------------------------------------------------- - - SUBROUTINE AMDBAR - $ (N, PE, IW, LEN, IWLEN, PFREE, NV, NEXT, - $ LAST, HEAD, ELEN, DEGREE, NCMPA, W) - - INTEGER N, IWLEN, PFREE, NCMPA, IW (IWLEN), PE (N), - $ DEGREE (N), NV (N), NEXT (N), LAST (N), HEAD (N), - $ ELEN (N), W (N), LEN (N) - -C Given a representation of the nonzero pattern of a symmetric matrix, -C A, (excluding the diagonal) perform an approximate minimum -C (UMFPACK/MA38-style) degree ordering to compute a pivot order -C such that the introduction of nonzeros (fill-in) in the Cholesky -C factors A = LL^T are kept low. At each step, the pivot -C selected is the one with the minimum UMFPACK/MA38-style -C upper-bound on the external degree. -C -C This routine does not do aggresive absorption (as done by AMD). - -C ********************************************************************** -C ***** CAUTION: ARGUMENTS ARE NOT CHECKED FOR ERRORS ON INPUT. ****** -C ********************************************************************** - -C References: -C -C [1] Timothy A. Davis and Iain Duff, "An unsymmetric-pattern -C multifrontal method for sparse LU factorization", SIAM J. -C Matrix Analysis and Applications, vol. 18, no. 1, pp. -C 140-158. Discusses UMFPACK / MA38, which first introduced -C the approximate minimum degree used by this routine. -C -C [2] Patrick Amestoy, Timothy A. Davis, and Iain S. Duff, "An -C approximate degree ordering algorithm," SIAM J. Matrix -C Analysis and Applications, vol. 17, no. 4, pp. 886-905, -C 1996. Discusses AMD, AMDBAR, and MC47B. -C -C [3] Alan George and Joseph Liu, "The evolution of the minimum -C degree ordering algorithm," SIAM Review, vol. 31, no. 1, -C pp. 1-19, 1989. We list below the features mentioned in -C that paper that this code includes: -C -C mass elimination: -C Yes. MA27 relied on supervariable detection for mass -C elimination. -C indistinguishable nodes: -C Yes (we call these "supervariables"). This was also in -C the MA27 code - although we modified the method of -C detecting them (the previous hash was the true degree, -C which we no longer keep track of). A supervariable is -C a set of rows with identical nonzero pattern. All -C variables in a supervariable are eliminated together. -C Each supervariable has as its numerical name that of -C one of its variables (its principal variable). -C quotient graph representation: -C Yes. We use the term "element" for the cliques formed -C during elimination. This was also in the MA27 code. -C The algorithm can operate in place, but it will work -C more efficiently if given some "elbow room." -C element absorption: -C Yes. This was also in the MA27 code. -C external degree: -C Yes. The MA27 code was based on the true degree. -C incomplete degree update and multiple elimination: -C No. This was not in MA27, either. Our method of -C degree update within MC47B/BD is element-based, not -C variable-based. It is thus not well-suited for use -C with incomplete degree update or multiple elimination. - -C----------------------------------------------------------------------- -C Authors, and Copyright (C) 1995 by: -C Timothy A. Davis, Patrick Amestoy, Iain S. Duff, & John K. Reid. -C -C Acknowledgements: -C This work (and the UMFPACK package) was supported by the -C National Science Foundation (ASC-9111263 and DMS-9223088). -C The UMFPACK/MA38 approximate degree update algorithm, the -C unsymmetric analog which forms the basis of MC47B/BD, was -C developed while Tim Davis was supported by CERFACS (Toulouse, -C France) in a post-doctoral position. -C -C Date: September, 1995 -C----------------------------------------------------------------------- - -C----------------------------------------------------------------------- -C INPUT ARGUMENTS (unaltered): -C----------------------------------------------------------------------- - -C n: The matrix order. -C -C Restriction: 1 .le. n .lt. (iovflo/2)-2, where iovflo is -C the largest positive integer that your computer can represent. - -C iwlen: The length of iw (1..iwlen). On input, the matrix is -C stored in iw (1..pfree-1). However, iw (1..iwlen) should be -C slightly larger than what is required to hold the matrix, at -C least iwlen .ge. pfree + n is recommended. Otherwise, -C excessive compressions will take place. -C *** We do not recommend running this algorithm with *** -C *** iwlen .lt. pfree + n. *** -C *** Better performance will be obtained if *** -C *** iwlen .ge. pfree + n *** -C *** or better yet *** -C *** iwlen .gt. 1.2 * pfree *** -C *** (where pfree is its value on input). *** -C The algorithm will not run at all if iwlen .lt. pfree-1. -C -C Restriction: iwlen .ge. pfree-1 - -C----------------------------------------------------------------------- -C INPUT/OUPUT ARGUMENTS: -C----------------------------------------------------------------------- - -C pe: On input, pe (i) is the index in iw of the start of row i, or -C zero if row i has no off-diagonal non-zeros. -C -C During execution, it is used for both supervariables and -C elements: -C -C * Principal supervariable i: index into iw of the -C description of supervariable i. A supervariable -C represents one or more rows of the matrix -C with identical nonzero pattern. -C * Non-principal supervariable i: if i has been absorbed -C into another supervariable j, then pe (i) = -j. -C That is, j has the same pattern as i. -C Note that j might later be absorbed into another -C supervariable j2, in which case pe (i) is still -j, -C and pe (j) = -j2. -C * Unabsorbed element e: the index into iw of the description -C of element e, if e has not yet been absorbed by a -C subsequent element. Element e is created when -C the supervariable of the same name is selected as -C the pivot. -C * Absorbed element e: if element e is absorbed into element -C e2, then pe (e) = -e2. This occurs when the pattern of -C e (that is, Le) is found to be a subset of the pattern -C of e2 (that is, Le2). If element e is "null" (it has -C no nonzeros outside its pivot block), then pe (e) = 0. -C -C On output, pe holds the assembly tree/forest, which implicitly -C represents a pivot order with identical fill-in as the actual -C order (via a depth-first search of the tree). -C -C On output: -C If nv (i) .gt. 0, then i represents a node in the assembly tree, -C and the parent of i is -pe (i), or zero if i is a root. -C If nv (i) = 0, then (i,-pe (i)) represents an edge in a -C subtree, the root of which is a node in the assembly tree. - -C pfree: On input the tail end of the array, iw (pfree..iwlen), -C is empty, and the matrix is stored in iw (1..pfree-1). -C During execution, additional data is placed in iw, and pfree -C is modified so that iw (pfree..iwlen) is always the unused part -C of iw. On output, pfree is set equal to the size of iw that -C would have been needed for no compressions to occur. If -C ncmpa is zero, then pfree (on output) is less than or equal to -C iwlen, and the space iw (pfree+1 ... iwlen) was not used. -C Otherwise, pfree (on output) is greater than iwlen, and all the -C memory in iw was used. - -C----------------------------------------------------------------------- -C INPUT/MODIFIED (undefined on output): -C----------------------------------------------------------------------- - -C len: On input, len (i) holds the number of entries in row i of the -C matrix, excluding the diagonal. The contents of len (1..n) -C are undefined on output. - -C iw: On input, iw (1..pfree-1) holds the description of each row i -C in the matrix. The matrix must be symmetric, and both upper -C and lower triangular parts must be present. The diagonal must -C not be present. Row i is held as follows: -C -C len (i): the length of the row i data structure -C iw (pe (i) ... pe (i) + len (i) - 1): -C the list of column indices for nonzeros -C in row i (simple supervariables), excluding -C the diagonal. All supervariables start with -C one row/column each (supervariable i is just -C row i). -C if len (i) is zero on input, then pe (i) is ignored -C on input. -C -C Note that the rows need not be in any particular order, -C and there may be empty space between the rows. -C -C During execution, the supervariable i experiences fill-in. -C This is represented by placing in i a list of the elements -C that cause fill-in in supervariable i: -C -C len (i): the length of supervariable i -C iw (pe (i) ... pe (i) + elen (i) - 1): -C the list of elements that contain i. This list -C is kept short by removing absorbed elements. -C iw (pe (i) + elen (i) ... pe (i) + len (i) - 1): -C the list of supervariables in i. This list -C is kept short by removing nonprincipal -C variables, and any entry j that is also -C contained in at least one of the elements -C (j in Le) in the list for i (e in row i). -C -C When supervariable i is selected as pivot, we create an -C element e of the same name (e=i): -C -C len (e): the length of element e -C iw (pe (e) ... pe (e) + len (e) - 1): -C the list of supervariables in element e. -C -C An element represents the fill-in that occurs when supervariable -C i is selected as pivot (which represents the selection of row i -C and all non-principal variables whose principal variable is i). -C We use the term Le to denote the set of all supervariables -C in element e. Absorbed supervariables and elements are pruned -C from these lists when computationally convenient. -C -C CAUTION: THE INPUT MATRIX IS OVERWRITTEN DURING COMPUTATION. -C The contents of iw are undefined on output. - -C----------------------------------------------------------------------- -C OUTPUT (need not be set on input): -C----------------------------------------------------------------------- - -C nv: During execution, abs (nv (i)) is equal to the number of rows -C that are represented by the principal supervariable i. If i is -C a nonprincipal variable, then nv (i) = 0. Initially, -C nv (i) = 1 for all i. nv (i) .lt. 0 signifies that i is a -C principal variable in the pattern Lme of the current pivot -C element me. On output, nv (e) holds the true degree of element -C e at the time it was created (including the diagonal part). - -C ncmpa: The number of times iw was compressed. If this is -C excessive, then the execution took longer than what could have -C been. To reduce ncmpa, try increasing iwlen to be 10% or 20% -C larger than the value of pfree on input (or at least -C iwlen .ge. pfree + n). The fastest performance will be -C obtained when ncmpa is returned as zero. If iwlen is set to -C the value returned by pfree on *output*, then no compressions -C will occur. - -C elen: See the description of iw above. At the start of execution, -C elen (i) is set to zero. During execution, elen (i) is the -C number of elements in the list for supervariable i. When e -C becomes an element, elen (e) = -nel is set, where nel is the -C current step of factorization. elen (i) = 0 is done when i -C becomes nonprincipal. -C -C For variables, elen (i) .ge. 0 holds until just before the -C permutation vectors are computed. For elements, -C elen (e) .lt. 0 holds. -C -C On output elen (1..n) holds the inverse permutation (the same -C as the 'INVP' argument in Sparspak). That is, if k = elen (i), -C then row i is the kth pivot row. Row i of A appears as the -C (elen(i))-th row in the permuted matrix, PAP^T. - -C last: In a degree list, last (i) is the supervariable preceding i, -C or zero if i is the head of the list. In a hash bucket, -C last (i) is the hash key for i. last (head (hash)) is also -C used as the head of a hash bucket if head (hash) contains a -C degree list (see head, below). -C -C On output, last (1..n) holds the permutation (the same as the -C 'PERM' argument in Sparspak). That is, if i = last (k), then -C row i is the kth pivot row. Row last (k) of A is the k-th row -C in the permuted matrix, PAP^T. - -C----------------------------------------------------------------------- -C LOCAL (not input or output - used only during execution): -C----------------------------------------------------------------------- - -C degree: If i is a supervariable, then degree (i) holds the -C current approximation of the external degree of row i (an upper -C bound). The external degree is the number of nonzeros in row i, -C minus abs (nv (i)) (the diagonal part). The bound is equal to -C the external degree if elen (i) is less than or equal to two. -C -C We also use the term "external degree" for elements e to refer -C to |Le \ Lme|. If e is an element, then degree (e) holds |Le|, -C which is the degree of the off-diagonal part of the element e -C (not including the diagonal part). - -C head: head is used for degree lists. head (deg) is the first -C supervariable in a degree list (all supervariables i in a -C degree list deg have the same approximate degree, namely, -C deg = degree (i)). If the list deg is empty then -C head (deg) = 0. -C -C During supervariable detection head (hash) also serves as a -C pointer to a hash bucket. -C If head (hash) .gt. 0, there is a degree list of degree hash. -C The hash bucket head pointer is last (head (hash)). -C If head (hash) = 0, then the degree list and hash bucket are -C both empty. -C If head (hash) .lt. 0, then the degree list is empty, and -C -head (hash) is the head of the hash bucket. -C After supervariable detection is complete, all hash buckets -C are empty, and the (last (head (hash)) = 0) condition is -C restored for the non-empty degree lists. - -C next: next (i) is the supervariable following i in a link list, or -C zero if i is the last in the list. Used for two kinds of -C lists: degree lists and hash buckets (a supervariable can be -C in only one kind of list at a time). - -C w: The flag array w determines the status of elements and -C variables, and the external degree of elements. -C -C for elements: -C if w (e) = 0, then the element e is absorbed -C if w (e) .ge. wflg, then w (e) - wflg is the size of -C the set |Le \ Lme|, in terms of nonzeros (the -C sum of abs (nv (i)) for each principal variable i that -C is both in the pattern of element e and NOT in the -C pattern of the current pivot element, me). -C if wflg .gt. w (e) .gt. 0, then e is not absorbed and has -C not yet been seen in the scan of the element lists in -C the computation of |Le\Lme| in loop 150 below. -C -C for variables: -C during supervariable detection, if w (j) .ne. wflg then j is -C not in the pattern of variable i -C -C The w array is initialized by setting w (i) = 1 for all i, -C and by setting wflg = 2. It is reinitialized if wflg becomes -C too large (to ensure that wflg+n does not cause integer -C overflow). - -C----------------------------------------------------------------------- -C LOCAL INTEGERS: -C----------------------------------------------------------------------- - - INTEGER DEG, DEGME, DMAX, E, ELENME, ELN, HASH, HMOD, I, - $ ILAST, INEXT, J, JLAST, JNEXT, K, KNT1, KNT2, KNT3, - $ LENJ, LN, MAXMEM, ME, MEM, MINDEG, NEL, NEWMEM, - $ NLEFT, NVI, NVJ, NVPIV, SLENME, WE, WFLG, WNVI, X - -C deg: the degree of a variable or element -C degme: size, |Lme|, of the current element, me (= degree (me)) -C dext: external degree, |Le \ Lme|, of some element e -C dmax: largest |Le| seen so far -C e: an element -C elenme: the length, elen (me), of element list of pivotal var. -C eln: the length, elen (...), of an element list -C hash: the computed value of the hash function -C hmod: the hash function is computed modulo hmod = max (1,n-1) -C i: a supervariable -C ilast: the entry in a link list preceding i -C inext: the entry in a link list following i -C j: a supervariable -C jlast: the entry in a link list preceding j -C jnext: the entry in a link list, or path, following j -C k: the pivot order of an element or variable -C knt1: loop counter used during element construction -C knt2: loop counter used during element construction -C knt3: loop counter used during compression -C lenj: len (j) -C ln: length of a supervariable list -C maxmem: amount of memory needed for no compressions -C me: current supervariable being eliminated, and the -C current element created by eliminating that -C supervariable -C mem: memory in use assuming no compressions have occurred -C mindeg: current minimum degree -C nel: number of pivots selected so far -C newmem: amount of new memory needed for current pivot element -C nleft: n - nel, the number of nonpivotal rows/columns remaining -C nvi: the number of variables in a supervariable i (= nv (i)) -C nvj: the number of variables in a supervariable j (= nv (j)) -C nvpiv: number of pivots in current element -C slenme: number of variables in variable list of pivotal variable -C we: w (e) -C wflg: used for flagging the w array. See description of iw. -C wnvi: wflg - nv (i) -C x: either a supervariable or an element - -C----------------------------------------------------------------------- -C LOCAL POINTERS: -C----------------------------------------------------------------------- - - INTEGER P, P1, P2, P3, PDST, PEND, PJ, PME, PME1, PME2, PN, PSRC - -C Any parameter (pe (...) or pfree) or local variable -C starting with "p" (for Pointer) is an index into iw, -C and all indices into iw use variables starting with -C "p." The only exception to this rule is the iwlen -C input argument. - -C p: pointer into lots of things -C p1: pe (i) for some variable i (start of element list) -C p2: pe (i) + elen (i) - 1 for some var. i (end of el. list) -C p3: index of first supervariable in clean list -C pdst: destination pointer, for compression -C pend: end of memory to compress -C pj: pointer into an element or variable -C pme: pointer into the current element (pme1...pme2) -C pme1: the current element, me, is stored in iw (pme1...pme2) -C pme2: the end of the current element -C pn: pointer into a "clean" variable, also used to compress -C psrc: source pointer, for compression - -C----------------------------------------------------------------------- -C FUNCTIONS CALLED: -C----------------------------------------------------------------------- - - INTRINSIC MAX, MIN, MOD - -C======================================================================= -C INITIALIZATIONS -C======================================================================= - - WFLG = 2 - MINDEG = 1 - NCMPA = 0 - NEL = 0 - HMOD = MAX (1, N-1) - DMAX = 0 - MEM = PFREE - 1 - MAXMEM = MEM - ME = 0 - - DO 10 I = 1, N - LAST (I) = 0 - HEAD (I) = 0 - NV (I) = 1 - W (I) = 1 - ELEN (I) = 0 - DEGREE (I) = LEN (I) -10 CONTINUE - -C ---------------------------------------------------------------- -C initialize degree lists and eliminate rows with no off-diag. nz. -C ---------------------------------------------------------------- - - DO 20 I = 1, N - - DEG = DEGREE (I) - - IF (DEG .GT. 0) THEN - -C ---------------------------------------------------------- -C place i in the degree list corresponding to its degree -C ---------------------------------------------------------- - - INEXT = HEAD (DEG) - IF (INEXT .NE. 0) LAST (INEXT) = I - NEXT (I) = INEXT - HEAD (DEG) = I - - ELSE - -C ---------------------------------------------------------- -C we have a variable that can be eliminated at once because -C there is no off-diagonal non-zero in its row. -C ---------------------------------------------------------- - - NEL = NEL + 1 - ELEN (I) = -NEL - PE (I) = 0 - W (I) = 0 - - ENDIF - -20 CONTINUE - -C======================================================================= -C WHILE (selecting pivots) DO -C======================================================================= - -30 CONTINUE - IF (NEL .LT. N) THEN - -C======================================================================= -C GET PIVOT OF MINIMUM DEGREE -C======================================================================= - -C ------------------------------------------------------------- -C find next supervariable for elimination -C ------------------------------------------------------------- - - DO 40 DEG = MINDEG, N - ME = HEAD (DEG) - IF (ME .GT. 0) GOTO 50 -40 CONTINUE -50 CONTINUE - MINDEG = DEG - -C ------------------------------------------------------------- -C remove chosen variable from link list -C ------------------------------------------------------------- - - INEXT = NEXT (ME) - IF (INEXT .NE. 0) LAST (INEXT) = 0 - HEAD (DEG) = INEXT - -C ------------------------------------------------------------- -C me represents the elimination of pivots nel+1 to nel+nv(me). -C place me itself as the first in this set. It will be moved -C to the nel+nv(me) position when the permutation vectors are -C computed. -C ------------------------------------------------------------- - - ELENME = ELEN (ME) - ELEN (ME) = - (NEL + 1) - NVPIV = NV (ME) - NEL = NEL + NVPIV - -C======================================================================= -C CONSTRUCT NEW ELEMENT -C======================================================================= - -C ------------------------------------------------------------- -C At this point, me is the pivotal supervariable. It will be -C converted into the current element. Scan list of the -C pivotal supervariable, me, setting tree pointers and -C constructing new list of supervariables for the new element, -C me. p is a pointer to the current position in the old list. -C ------------------------------------------------------------- - -C flag the variable "me" as being in Lme by negating nv (me) - NV (ME) = -NVPIV - DEGME = 0 - - IF (ELENME .EQ. 0) THEN - -C ---------------------------------------------------------- -C construct the new element in place -C ---------------------------------------------------------- - - PME1 = PE (ME) - PME2 = PME1 - 1 - - DO 60 P = PME1, PME1 + LEN (ME) - 1 - I = IW (P) - NVI = NV (I) - IF (NVI .GT. 0) THEN - -C ---------------------------------------------------- -C i is a principal variable not yet placed in Lme. -C store i in new list -C ---------------------------------------------------- - - DEGME = DEGME + NVI -C flag i as being in Lme by negating nv (i) - NV (I) = -NVI - PME2 = PME2 + 1 - IW (PME2) = I - -C ---------------------------------------------------- -C remove variable i from degree list. -C ---------------------------------------------------- - - ILAST = LAST (I) - INEXT = NEXT (I) - IF (INEXT .NE. 0) LAST (INEXT) = ILAST - IF (ILAST .NE. 0) THEN - NEXT (ILAST) = INEXT - ELSE -C i is at the head of the degree list - HEAD (DEGREE (I)) = INEXT - ENDIF - - ENDIF -60 CONTINUE -C this element takes no new memory in iw: - NEWMEM = 0 - - ELSE - -C ---------------------------------------------------------- -C construct the new element in empty space, iw (pfree ...) -C ---------------------------------------------------------- - - P = PE (ME) - PME1 = PFREE - SLENME = LEN (ME) - ELENME - - DO 120 KNT1 = 1, ELENME + 1 - - IF (KNT1 .GT. ELENME) THEN -C search the supervariables in me. - E = ME - PJ = P - LN = SLENME - ELSE -C search the elements in me. - E = IW (P) - P = P + 1 - PJ = PE (E) - LN = LEN (E) - ENDIF - -C ------------------------------------------------------- -C search for different supervariables and add them to the -C new list, compressing when necessary. this loop is -C executed once for each element in the list and once for -C all the supervariables in the list. -C ------------------------------------------------------- - - DO 110 KNT2 = 1, LN - I = IW (PJ) - PJ = PJ + 1 - NVI = NV (I) - IF (NVI .GT. 0) THEN - -C ------------------------------------------------- -C compress iw, if necessary -C ------------------------------------------------- - - IF (PFREE .GT. IWLEN) THEN -C prepare for compressing iw by adjusting -C pointers and lengths so that the lists being -C searched in the inner and outer loops contain -C only the remaining entries. - - PE (ME) = P - LEN (ME) = LEN (ME) - KNT1 - IF (LEN (ME) .EQ. 0) THEN -C nothing left of supervariable me - PE (ME) = 0 - ENDIF - PE (E) = PJ - LEN (E) = LN - KNT2 - IF (LEN (E) .EQ. 0) THEN -C nothing left of element e - PE (E) = 0 - ENDIF - - NCMPA = NCMPA + 1 -C store first item in pe -C set first entry to -item - DO 70 J = 1, N - PN = PE (J) - IF (PN .GT. 0) THEN - PE (J) = IW (PN) - IW (PN) = -J - ENDIF -70 CONTINUE - -C psrc/pdst point to source/destination - PDST = 1 - PSRC = 1 - PEND = PME1 - 1 - -C while loop: -80 CONTINUE - IF (PSRC .LE. PEND) THEN -C search for next negative entry - J = -IW (PSRC) - PSRC = PSRC + 1 - IF (J .GT. 0) THEN - IW (PDST) = PE (J) - PE (J) = PDST - PDST = PDST + 1 -C copy from source to destination - LENJ = LEN (J) - DO 90 KNT3 = 0, LENJ - 2 - IW (PDST + KNT3) = IW (PSRC + KNT3) -90 CONTINUE - PDST = PDST + LENJ - 1 - PSRC = PSRC + LENJ - 1 - ENDIF - GOTO 80 - ENDIF - -C move the new partially-constructed element - P1 = PDST - DO 100 PSRC = PME1, PFREE - 1 - IW (PDST) = IW (PSRC) - PDST = PDST + 1 -100 CONTINUE - PME1 = P1 - PFREE = PDST - PJ = PE (E) - P = PE (ME) - ENDIF - -C ------------------------------------------------- -C i is a principal variable not yet placed in Lme -C store i in new list -C ------------------------------------------------- - - DEGME = DEGME + NVI -C flag i as being in Lme by negating nv (i) - NV (I) = -NVI - IW (PFREE) = I - PFREE = PFREE + 1 - -C ------------------------------------------------- -C remove variable i from degree link list -C ------------------------------------------------- - - ILAST = LAST (I) - INEXT = NEXT (I) - IF (INEXT .NE. 0) LAST (INEXT) = ILAST - IF (ILAST .NE. 0) THEN - NEXT (ILAST) = INEXT - ELSE -C i is at the head of the degree list - HEAD (DEGREE (I)) = INEXT - ENDIF - - ENDIF -110 CONTINUE - - IF (E .NE. ME) THEN -C set tree pointer and flag to indicate element e is -C absorbed into new element me (the parent of e is me) - PE (E) = -ME - W (E) = 0 - ENDIF -120 CONTINUE - - PME2 = PFREE - 1 -C this element takes newmem new memory in iw (possibly zero) - NEWMEM = PFREE - PME1 - MEM = MEM + NEWMEM - MAXMEM = MAX (MAXMEM, MEM) - ENDIF - -C ------------------------------------------------------------- -C me has now been converted into an element in iw (pme1..pme2) -C ------------------------------------------------------------- - -C degme holds the external degree of new element - DEGREE (ME) = DEGME - PE (ME) = PME1 - LEN (ME) = PME2 - PME1 + 1 - -C ------------------------------------------------------------- -C make sure that wflg is not too large. With the current -C value of wflg, wflg+n must not cause integer overflow -C ------------------------------------------------------------- - - IF (WFLG + N .LE. WFLG) THEN - DO 130 X = 1, N - IF (W (X) .NE. 0) W (X) = 1 -130 CONTINUE - WFLG = 2 - ENDIF - -C======================================================================= -C COMPUTE (w (e) - wflg) = |Le\Lme| FOR ALL ELEMENTS -C======================================================================= - -C ------------------------------------------------------------- -C Scan 1: compute the external degrees of previous elements -C with respect to the current element. That is: -C (w (e) - wflg) = |Le \ Lme| -C for each element e that appears in any supervariable in Lme. -C The notation Le refers to the pattern (list of -C supervariables) of a previous element e, where e is not yet -C absorbed, stored in iw (pe (e) + 1 ... pe (e) + iw (pe (e))). -C The notation Lme refers to the pattern of the current element -C (stored in iw (pme1..pme2)). If (w (e) - wflg) becomes -C zero, then the element e will be absorbed in scan 2. -C ------------------------------------------------------------- - - DO 150 PME = PME1, PME2 - I = IW (PME) - ELN = ELEN (I) - IF (ELN .GT. 0) THEN -C note that nv (i) has been negated to denote i in Lme: - NVI = -NV (I) - WNVI = WFLG - NVI - DO 140 P = PE (I), PE (I) + ELN - 1 - E = IW (P) - WE = W (E) - IF (WE .GE. WFLG) THEN -C unabsorbed element e has been seen in this loop - WE = WE - NVI - ELSE IF (WE .NE. 0) THEN -C e is an unabsorbed element -C this is the first we have seen e in all of Scan 1 - WE = DEGREE (E) + WNVI - ENDIF - W (E) = WE -140 CONTINUE - ENDIF -150 CONTINUE - -C======================================================================= -C DEGREE UPDATE AND ELEMENT ABSORPTION -C======================================================================= - -C ------------------------------------------------------------- -C Scan 2: for each i in Lme, sum up the degree of Lme (which -C is degme), plus the sum of the external degrees of each Le -C for the elements e appearing within i, plus the -C supervariables in i. Place i in hash list. -C ------------------------------------------------------------- - - DO 180 PME = PME1, PME2 - I = IW (PME) - P1 = PE (I) - P2 = P1 + ELEN (I) - 1 - PN = P1 - HASH = 0 - DEG = 0 - -C ---------------------------------------------------------- -C scan the element list associated with supervariable i -C ---------------------------------------------------------- - -C UMFPACK/MA38-style approximate degree: - DO 160 P = P1, P2 - E = IW (P) - WE = W (E) - IF (WE .NE. 0) THEN -C e is an unabsorbed element - DEG = DEG + WE - WFLG - IW (PN) = E - PN = PN + 1 - HASH = HASH + E - ENDIF -160 CONTINUE - -C count the number of elements in i (including me): - ELEN (I) = PN - P1 + 1 - -C ---------------------------------------------------------- -C scan the supervariables in the list associated with i -C ---------------------------------------------------------- - - P3 = PN - DO 170 P = P2 + 1, P1 + LEN (I) - 1 - J = IW (P) - NVJ = NV (J) - IF (NVJ .GT. 0) THEN -C j is unabsorbed, and not in Lme. -C add to degree and add to new list - DEG = DEG + NVJ - IW (PN) = J - PN = PN + 1 - HASH = HASH + J - ENDIF -170 CONTINUE - -C ---------------------------------------------------------- -C update the degree and check for mass elimination -C ---------------------------------------------------------- - - IF (ELEN (I) .EQ. 1 .AND. P3 .EQ. PN) THEN - -C ------------------------------------------------------- -C mass elimination -C ------------------------------------------------------- - -C There is nothing left of this node except for an -C edge to the current pivot element. elen (i) is 1, -C and there are no variables adjacent to node i. -C Absorb i into the current pivot element, me. - - PE (I) = -ME - NVI = -NV (I) - DEGME = DEGME - NVI - NVPIV = NVPIV + NVI - NEL = NEL + NVI - NV (I) = 0 - ELEN (I) = 0 - - ELSE - -C ------------------------------------------------------- -C update the upper-bound degree of i -C ------------------------------------------------------- - -C the following degree does not yet include the size -C of the current element, which is added later: - DEGREE (I) = MIN (DEGREE (I), DEG) - -C ------------------------------------------------------- -C add me to the list for i -C ------------------------------------------------------- - -C move first supervariable to end of list - IW (PN) = IW (P3) -C move first element to end of element part of list - IW (P3) = IW (P1) -C add new element to front of list. - IW (P1) = ME -C store the new length of the list in len (i) - LEN (I) = PN - P1 + 1 - -C ------------------------------------------------------- -C place in hash bucket. Save hash key of i in last (i). -C ------------------------------------------------------- - - HASH = MOD (HASH, HMOD) + 1 - J = HEAD (HASH) - IF (J .LE. 0) THEN -C the degree list is empty, hash head is -j - NEXT (I) = -J - HEAD (HASH) = -I - ELSE -C degree list is not empty -C use last (head (hash)) as hash head - NEXT (I) = LAST (J) - LAST (J) = I - ENDIF - LAST (I) = HASH - ENDIF -180 CONTINUE - - DEGREE (ME) = DEGME - -C ------------------------------------------------------------- -C Clear the counter array, w (...), by incrementing wflg. -C ------------------------------------------------------------- - - DMAX = MAX (DMAX, DEGME) - WFLG = WFLG + DMAX - -C make sure that wflg+n does not cause integer overflow - IF (WFLG + N .LE. WFLG) THEN - DO 190 X = 1, N - IF (W (X) .NE. 0) W (X) = 1 -190 CONTINUE - WFLG = 2 - ENDIF -C at this point, w (1..n) .lt. wflg holds - -C======================================================================= -C SUPERVARIABLE DETECTION -C======================================================================= - - DO 250 PME = PME1, PME2 - I = IW (PME) - IF (NV (I) .LT. 0) THEN -C i is a principal variable in Lme - -C ------------------------------------------------------- -C examine all hash buckets with 2 or more variables. We -C do this by examing all unique hash keys for super- -C variables in the pattern Lme of the current element, me -C ------------------------------------------------------- - - HASH = LAST (I) -C let i = head of hash bucket, and empty the hash bucket - J = HEAD (HASH) - IF (J .EQ. 0) GOTO 250 - IF (J .LT. 0) THEN -C degree list is empty - I = -J - HEAD (HASH) = 0 - ELSE -C degree list is not empty, restore last () of head - I = LAST (J) - LAST (J) = 0 - ENDIF - IF (I .EQ. 0) GOTO 250 - -C while loop: -200 CONTINUE - IF (NEXT (I) .NE. 0) THEN - -C ---------------------------------------------------- -C this bucket has one or more variables following i. -C scan all of them to see if i can absorb any entries -C that follow i in hash bucket. Scatter i into w. -C ---------------------------------------------------- - - LN = LEN (I) - ELN = ELEN (I) -C do not flag the first element in the list (me) - DO 210 P = PE (I) + 1, PE (I) + LN - 1 - W (IW (P)) = WFLG -210 CONTINUE - -C ---------------------------------------------------- -C scan every other entry j following i in bucket -C ---------------------------------------------------- - - JLAST = I - J = NEXT (I) - -C while loop: -220 CONTINUE - IF (J .NE. 0) THEN - -C ------------------------------------------------- -C check if j and i have identical nonzero pattern -C ------------------------------------------------- - - IF (LEN (J) .NE. LN) THEN -C i and j do not have same size data structure - GOTO 240 - ENDIF - IF (ELEN (J) .NE. ELN) THEN -C i and j do not have same number of adjacent el - GOTO 240 - ENDIF -C do not flag the first element in the list (me) - DO 230 P = PE (J) + 1, PE (J) + LN - 1 - IF (W (IW (P)) .NE. WFLG) THEN -C an entry (iw(p)) is in j but not in i - GOTO 240 - ENDIF -230 CONTINUE - -C ------------------------------------------------- -C found it! j can be absorbed into i -C ------------------------------------------------- - - PE (J) = -I -C both nv (i) and nv (j) are negated since they -C are in Lme, and the absolute values of each -C are the number of variables in i and j: - NV (I) = NV (I) + NV (J) - NV (J) = 0 - ELEN (J) = 0 -C delete j from hash bucket - J = NEXT (J) - NEXT (JLAST) = J - GOTO 220 - -C ------------------------------------------------- -240 CONTINUE -C j cannot be absorbed into i -C ------------------------------------------------- - - JLAST = J - J = NEXT (J) - GOTO 220 - ENDIF - -C ---------------------------------------------------- -C no more variables can be absorbed into i -C go to next i in bucket and clear flag array -C ---------------------------------------------------- - - WFLG = WFLG + 1 - I = NEXT (I) - IF (I .NE. 0) GOTO 200 - ENDIF - ENDIF -250 CONTINUE - -C======================================================================= -C RESTORE DEGREE LISTS AND REMOVE NONPRINCIPAL SUPERVAR. FROM ELEMENT -C======================================================================= - - P = PME1 - NLEFT = N - NEL - DO 260 PME = PME1, PME2 - I = IW (PME) - NVI = -NV (I) - IF (NVI .GT. 0) THEN -C i is a principal variable in Lme -C restore nv (i) to signify that i is principal - NV (I) = NVI - -C ------------------------------------------------------- -C compute the external degree (add size of current elem) -C ------------------------------------------------------- - - DEG = MAX (1, MIN (DEGREE (I) + DEGME-NVI, NLEFT-NVI)) - -C ------------------------------------------------------- -C place the supervariable at the head of the degree list -C ------------------------------------------------------- - - INEXT = HEAD (DEG) - IF (INEXT .NE. 0) LAST (INEXT) = I - NEXT (I) = INEXT - LAST (I) = 0 - HEAD (DEG) = I - -C ------------------------------------------------------- -C save the new degree, and find the minimum degree -C ------------------------------------------------------- - - MINDEG = MIN (MINDEG, DEG) - DEGREE (I) = DEG - -C ------------------------------------------------------- -C place the supervariable in the element pattern -C ------------------------------------------------------- - - IW (P) = I - P = P + 1 - ENDIF -260 CONTINUE - -C======================================================================= -C FINALIZE THE NEW ELEMENT -C======================================================================= - - NV (ME) = NVPIV + DEGME -C nv (me) is now the degree of pivot (including diagonal part) -C save the length of the list for the new element me - LEN (ME) = P - PME1 - IF (LEN (ME) .EQ. 0) THEN -C there is nothing left of the current pivot element - PE (ME) = 0 - W (ME) = 0 - ENDIF - IF (NEWMEM .NE. 0) THEN -C element was not constructed in place: deallocate part -C of it (final size is less than or equal to newmem, -C since newly nonprincipal variables have been removed). - PFREE = P - MEM = MEM - NEWMEM + LEN (ME) - ENDIF - -C======================================================================= -C END WHILE (selecting pivots) - GOTO 30 - ENDIF -C======================================================================= - -C======================================================================= -C COMPUTE THE PERMUTATION VECTORS -C======================================================================= - -C ---------------------------------------------------------------- -C The time taken by the following code is O(n). At this -C point, elen (e) = -k has been done for all elements e, -C and elen (i) = 0 has been done for all nonprincipal -C variables i. At this point, there are no principal -C supervariables left, and all elements are absorbed. -C ---------------------------------------------------------------- - -C ---------------------------------------------------------------- -C compute the ordering of unordered nonprincipal variables -C ---------------------------------------------------------------- - - DO 290 I = 1, N - IF (ELEN (I) .EQ. 0) THEN - -C ---------------------------------------------------------- -C i is an un-ordered row. Traverse the tree from i until -C reaching an element, e. The element, e, was the -C principal supervariable of i and all nodes in the path -C from i to when e was selected as pivot. -C ---------------------------------------------------------- - - J = -PE (I) -C while (j is a variable) do: -270 CONTINUE - IF (ELEN (J) .GE. 0) THEN - J = -PE (J) - GOTO 270 - ENDIF - E = J - -C ---------------------------------------------------------- -C get the current pivot ordering of e -C ---------------------------------------------------------- - - K = -ELEN (E) - -C ---------------------------------------------------------- -C traverse the path again from i to e, and compress the -C path (all nodes point to e). Path compression allows -C this code to compute in O(n) time. Order the unordered -C nodes in the path, and place the element e at the end. -C ---------------------------------------------------------- - - J = I -C while (j is a variable) do: -280 CONTINUE - IF (ELEN (J) .GE. 0) THEN - JNEXT = -PE (J) - PE (J) = -E - IF (ELEN (J) .EQ. 0) THEN -C j is an unordered row - ELEN (J) = K - K = K + 1 - ENDIF - J = JNEXT - GOTO 280 - ENDIF -C leave elen (e) negative, so we know it is an element - ELEN (E) = -K - ENDIF -290 CONTINUE - -C ---------------------------------------------------------------- -C reset the inverse permutation (elen (1..n)) to be positive, -C and compute the permutation (last (1..n)). -C ---------------------------------------------------------------- - - DO 300 I = 1, N - K = ABS (ELEN (I)) - LAST (K) = I - ELEN (I) = K -300 CONTINUE - -C======================================================================= -C RETURN THE MEMORY USAGE IN IW -C======================================================================= - -C If maxmem is less than or equal to iwlen, then no compressions -C occurred, and iw (maxmem+1 ... iwlen) was unused. Otherwise -C compressions did occur, and iwlen would have had to have been -C greater than or equal to maxmem for no compressions to occur. -C Return the value of maxmem in the pfree argument. - - PFREE = MAXMEM - - RETURN - END - diff -r 63c15a67612d -r 49de4e624020 liboctave/UMFPACK/README.txt --- a/liboctave/UMFPACK/README.txt Mon Mar 14 20:47:58 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -UMFPACK v4.4 and AMD v1.1. - -See UMFPACK/README.txt and AMD/README.txt for details. Documention is in -UMFPACK/Doc and AMD/Doc. -