Added UMFPACK as new experimental linear solver, (#1 new files)

This commit is contained in:
Francesco Lannutti 2012-03-12 19:20:20 +01:00 committed by Francesco Lannutti
parent 7f546a2877
commit 3560c8ee16
180 changed files with 44917 additions and 0 deletions

View File

@ -0,0 +1,436 @@
/* ========================================================================== */
/* === umfpack.h ============================================================ */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/*
This is the umfpack.h include file, and should be included in all user code
that uses UMFPACK. Do not include any of the umf_* header files in user
code. All routines in UMFPACK starting with "umfpack_" are user-callable.
All other routines are prefixed "umf_XY_", (where X is d or z, and Y is
i or l) and are not user-callable.
*/
#ifndef UMFPACK_H
#define UMFPACK_H
/* -------------------------------------------------------------------------- */
/* Make it easy for C++ programs to include UMFPACK */
/* -------------------------------------------------------------------------- */
#ifdef __cplusplus
extern "C" {
#endif
/* define UF_long */
#include "ngspice/UFconfig.h"
/* -------------------------------------------------------------------------- */
/* size of Info and Control arrays */
/* -------------------------------------------------------------------------- */
/* These might be larger in future versions, since there are only 3 unused
* entries in Info, and no unused entries in Control. */
#define UMFPACK_INFO 90
#define UMFPACK_CONTROL 20
/* -------------------------------------------------------------------------- */
/* User-callable routines */
/* -------------------------------------------------------------------------- */
/* Primary routines: */
#include "umfpack_symbolic.h"
#include "umfpack_numeric.h"
#include "umfpack_solve.h"
#include "umfpack_free_symbolic.h"
#include "umfpack_free_numeric.h"
/* Alternative routines: */
#include "umfpack_defaults.h"
#include "umfpack_qsymbolic.h"
#include "umfpack_wsolve.h"
/* Matrix manipulation routines: */
#include "umfpack_triplet_to_col.h"
#include "umfpack_col_to_triplet.h"
#include "umfpack_transpose.h"
#include "umfpack_scale.h"
/* Getting the contents of the Symbolic and Numeric opaque objects: */
#include "umfpack_get_lunz.h"
#include "umfpack_get_numeric.h"
#include "umfpack_get_symbolic.h"
#include "umfpack_save_numeric.h"
#include "umfpack_load_numeric.h"
#include "umfpack_save_symbolic.h"
#include "umfpack_load_symbolic.h"
#include "umfpack_get_determinant.h"
/* Reporting routines (the above 14 routines print nothing): */
#include "umfpack_report_status.h"
#include "umfpack_report_info.h"
#include "umfpack_report_control.h"
#include "umfpack_report_matrix.h"
#include "umfpack_report_triplet.h"
#include "umfpack_report_vector.h"
#include "umfpack_report_symbolic.h"
#include "umfpack_report_numeric.h"
#include "umfpack_report_perm.h"
/* Utility routines: */
#include "umfpack_timer.h"
#include "umfpack_tictoc.h"
/* AMD */
#include "ngspice/amd.h"
/* global function pointers */
#include "umfpack_global.h"
/* -------------------------------------------------------------------------- */
/* Version, copyright, and license */
/* -------------------------------------------------------------------------- */
#define UMFPACK_VERSION "UMFPACK V5.5.2 (Dec 7, 2011)"
#define UMFPACK_COPYRIGHT \
"UMFPACK: Copyright (c) 2005-2011 by Timothy A. Davis. All Rights Reserved.\n"
#define UMFPACK_LICENSE_PART1 \
"\nUMFPACK License:\n" \
"\n" \
" UMFPACK is available under alternate licenses,\n" \
" contact T. Davis for details.\n" \
"\n" \
" Your use or distribution of UMFPACK or any modified version of\n" \
" UMFPACK implies that you agree to this License.\n" \
"\n" \
" This library is free software; you can redistribute it and/or\n" \
" modify it under the terms of the GNU General Public\n" \
" License as published by the Free Software Foundation; either\n" \
" version 2 of the License, or (at your option) any later version.\n" \
"\n" \
" This library is distributed in the hope that it will be useful,\n" \
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n" \
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" \
" General Public License for more details.\n" \
"\n" \
" You should have received a copy of the GNU General Public\n" \
" License along with this library; if not, write to the Free Software\n" \
" Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301\n" \
" USA\n" \
#define UMFPACK_LICENSE_PART2 \
"\n" \
" Permission is hereby granted to use or copy this program under the\n" \
" terms of the GNU GPL, provided that the Copyright, this License,\n" \
" and the Availability of the original version is retained on all copies.\n" \
" User documentation of any code that uses this code or any modified\n" \
" version of this code must cite the Copyright, this License, the\n" \
" Availability note, and \"Used by permission.\" Permission to modify\n" \
" the code and to distribute modified code is granted, provided the\n" \
" Copyright, this License, and the Availability note are retained,\n" \
" and a notice that the code was modified is included.\n"
#define UMFPACK_LICENSE_PART3 \
"\n" \
"Availability: http://www.cise.ufl.edu/research/sparse/umfpack\n" \
"\n"
/* UMFPACK Version 4.5 and later will include the following definitions.
* As an example, to test if the version you are using is 4.5 or later:
*
* #ifdef UMFPACK_VER
* if (UMFPACK_VER >= UMFPACK_VER_CODE (4,5)) ...
* #endif
*
* This also works during compile-time:
*
* #if defined(UMFPACK_VER) && (UMFPACK >= UMFPACK_VER_CODE (4,5))
* printf ("This is version 4.5 or later\n") ;
* #else
* printf ("This is an early version\n") ;
* #endif
*
* Versions 4.4 and earlier of UMFPACK do not include a #define'd version
* number, although they do include the UMFPACK_VERSION string, defined
* above.
*/
#define UMFPACK_DATE "Dec 7, 2011"
#define UMFPACK_VER_CODE(main,sub) ((main) * 1000 + (sub))
#define UMFPACK_MAIN_VERSION 5
#define UMFPACK_SUB_VERSION 5
#define UMFPACK_SUBSUB_VERSION 2
#define UMFPACK_VER UMFPACK_VER_CODE(UMFPACK_MAIN_VERSION,UMFPACK_SUB_VERSION)
/* -------------------------------------------------------------------------- */
/* contents of Info */
/* -------------------------------------------------------------------------- */
/* Note that umfpack_report.m must coincide with these definitions. S is
* the submatrix of A after removing row/col singletons and empty rows/cols. */
/* returned by all routines that use Info: */
#define UMFPACK_STATUS 0 /* UMFPACK_OK, or other result */
#define UMFPACK_NROW 1 /* n_row input value */
#define UMFPACK_NCOL 16 /* n_col input value */
#define UMFPACK_NZ 2 /* # of entries in A */
/* computed in UMFPACK_*symbolic and UMFPACK_numeric: */
#define UMFPACK_SIZE_OF_UNIT 3 /* sizeof (Unit) */
/* computed in UMFPACK_*symbolic: */
#define UMFPACK_SIZE_OF_INT 4 /* sizeof (int) */
#define UMFPACK_SIZE_OF_LONG 5 /* sizeof (UF_long) */
#define UMFPACK_SIZE_OF_POINTER 6 /* sizeof (void *) */
#define UMFPACK_SIZE_OF_ENTRY 7 /* sizeof (Entry), real or complex */
#define UMFPACK_NDENSE_ROW 8 /* number of dense rows */
#define UMFPACK_NEMPTY_ROW 9 /* number of empty rows */
#define UMFPACK_NDENSE_COL 10 /* number of dense rows */
#define UMFPACK_NEMPTY_COL 11 /* number of empty rows */
#define UMFPACK_SYMBOLIC_DEFRAG 12 /* # of memory compactions */
#define UMFPACK_SYMBOLIC_PEAK_MEMORY 13 /* memory used by symbolic analysis */
#define UMFPACK_SYMBOLIC_SIZE 14 /* size of Symbolic object, in Units */
#define UMFPACK_SYMBOLIC_TIME 15 /* time (sec.) for symbolic analysis */
#define UMFPACK_SYMBOLIC_WALLTIME 17 /* wall clock time for sym. analysis */
#define UMFPACK_STRATEGY_USED 18 /* strategy used: sym, unsym */
#define UMFPACK_ORDERING_USED 19 /* ordering used: colamd, amd, given */
#define UMFPACK_QFIXED 31 /* whether Q is fixed or refined */
#define UMFPACK_DIAG_PREFERRED 32 /* whether diagonal pivoting attempted*/
#define UMFPACK_PATTERN_SYMMETRY 33 /* symmetry of pattern of S */
#define UMFPACK_NZ_A_PLUS_AT 34 /* nnz (S+S'), excl. diagonal */
#define UMFPACK_NZDIAG 35 /* nnz (diag (S)) */
/* AMD statistics, computed in UMFPACK_*symbolic: */
#define UMFPACK_SYMMETRIC_LUNZ 36 /* nz in L+U, if AMD ordering used */
#define UMFPACK_SYMMETRIC_FLOPS 37 /* flops for LU, if AMD ordering used */
#define UMFPACK_SYMMETRIC_NDENSE 38 /* # of "dense" rows/cols in S+S' */
#define UMFPACK_SYMMETRIC_DMAX 39 /* max nz in cols of L, for AMD */
/* 51:55 unused */
/* statistcs for singleton pruning */
#define UMFPACK_COL_SINGLETONS 56 /* # of column singletons */
#define UMFPACK_ROW_SINGLETONS 57 /* # of row singletons */
#define UMFPACK_N2 58 /* size of S */
#define UMFPACK_S_SYMMETRIC 59 /* 1 if S square and symmetricly perm.*/
/* estimates computed in UMFPACK_*symbolic: */
#define UMFPACK_NUMERIC_SIZE_ESTIMATE 20 /* final size of Numeric->Memory */
#define UMFPACK_PEAK_MEMORY_ESTIMATE 21 /* for symbolic & numeric */
#define UMFPACK_FLOPS_ESTIMATE 22 /* flop count */
#define UMFPACK_LNZ_ESTIMATE 23 /* nz in L, incl. diagonal */
#define UMFPACK_UNZ_ESTIMATE 24 /* nz in U, incl. diagonal */
#define UMFPACK_VARIABLE_INIT_ESTIMATE 25 /* initial size of Numeric->Memory*/
#define UMFPACK_VARIABLE_PEAK_ESTIMATE 26 /* peak size of Numeric->Memory */
#define UMFPACK_VARIABLE_FINAL_ESTIMATE 27 /* final size of Numeric->Memory */
#define UMFPACK_MAX_FRONT_SIZE_ESTIMATE 28 /* max frontal matrix size */
#define UMFPACK_MAX_FRONT_NROWS_ESTIMATE 29 /* max # rows in any front */
#define UMFPACK_MAX_FRONT_NCOLS_ESTIMATE 30 /* max # columns in any front */
/* exact values, (estimates shown above) computed in UMFPACK_numeric: */
#define UMFPACK_NUMERIC_SIZE 40 /* final size of Numeric->Memory */
#define UMFPACK_PEAK_MEMORY 41 /* for symbolic & numeric */
#define UMFPACK_FLOPS 42 /* flop count */
#define UMFPACK_LNZ 43 /* nz in L, incl. diagonal */
#define UMFPACK_UNZ 44 /* nz in U, incl. diagonal */
#define UMFPACK_VARIABLE_INIT 45 /* initial size of Numeric->Memory*/
#define UMFPACK_VARIABLE_PEAK 46 /* peak size of Numeric->Memory */
#define UMFPACK_VARIABLE_FINAL 47 /* final size of Numeric->Memory */
#define UMFPACK_MAX_FRONT_SIZE 48 /* max frontal matrix size */
#define UMFPACK_MAX_FRONT_NROWS 49 /* max # rows in any front */
#define UMFPACK_MAX_FRONT_NCOLS 50 /* max # columns in any front */
/* computed in UMFPACK_numeric: */
#define UMFPACK_NUMERIC_DEFRAG 60 /* # of garbage collections */
#define UMFPACK_NUMERIC_REALLOC 61 /* # of memory reallocations */
#define UMFPACK_NUMERIC_COSTLY_REALLOC 62 /* # of costlly memory realloc's */
#define UMFPACK_COMPRESSED_PATTERN 63 /* # of integers in LU pattern */
#define UMFPACK_LU_ENTRIES 64 /* # of reals in LU factors */
#define UMFPACK_NUMERIC_TIME 65 /* numeric factorization time */
#define UMFPACK_UDIAG_NZ 66 /* nz on diagonal of U */
#define UMFPACK_RCOND 67 /* est. reciprocal condition # */
#define UMFPACK_WAS_SCALED 68 /* none, max row, or sum row */
#define UMFPACK_RSMIN 69 /* min (max row) or min (sum row) */
#define UMFPACK_RSMAX 70 /* max (max row) or max (sum row) */
#define UMFPACK_UMIN 71 /* min abs diagonal entry of U */
#define UMFPACK_UMAX 72 /* max abs diagonal entry of U */
#define UMFPACK_ALLOC_INIT_USED 73 /* alloc_init parameter used */
#define UMFPACK_FORCED_UPDATES 74 /* # of forced updates */
#define UMFPACK_NUMERIC_WALLTIME 75 /* numeric wall clock time */
#define UMFPACK_NOFF_DIAG 76 /* number of off-diagonal pivots */
#define UMFPACK_ALL_LNZ 77 /* nz in L, if no dropped entries */
#define UMFPACK_ALL_UNZ 78 /* nz in U, if no dropped entries */
#define UMFPACK_NZDROPPED 79 /* # of dropped small entries */
/* computed in UMFPACK_solve: */
#define UMFPACK_IR_TAKEN 80 /* # of iterative refinement steps taken */
#define UMFPACK_IR_ATTEMPTED 81 /* # of iter. refinement steps attempted */
#define UMFPACK_OMEGA1 82 /* omega1, sparse backward error estimate */
#define UMFPACK_OMEGA2 83 /* omega2, sparse backward error estimate */
#define UMFPACK_SOLVE_FLOPS 84 /* flop count for solve */
#define UMFPACK_SOLVE_TIME 85 /* solve time (seconds) */
#define UMFPACK_SOLVE_WALLTIME 86 /* solve time (wall clock, seconds) */
/* Info [87, 88, 89] unused */
/* Unused parts of Info may be used in future versions of UMFPACK. */
/* -------------------------------------------------------------------------- */
/* contents of Control */
/* -------------------------------------------------------------------------- */
/* used in all UMFPACK_report_* routines: */
#define UMFPACK_PRL 0 /* print level */
/* used in UMFPACK_*symbolic only: */
#define UMFPACK_DENSE_ROW 1 /* dense row parameter */
#define UMFPACK_DENSE_COL 2 /* dense col parameter */
#define UMFPACK_BLOCK_SIZE 4 /* BLAS-3 block size */
#define UMFPACK_STRATEGY 5 /* auto, symmetric, or unsym. */
#define UMFPACK_ORDERING 10 /* ordering method to use */
#define UMFPACK_FIXQ 13 /* -1: no fixQ, 0: default, 1: fixQ */
#define UMFPACK_AMD_DENSE 14 /* for AMD ordering */
#define UMFPACK_AGGRESSIVE 19 /* whether or not to use aggressive */
#define UMFPACK_SINGLETONS 11 /* singleton filter on if true */
/* used in UMFPACK_numeric only: */
#define UMFPACK_PIVOT_TOLERANCE 3 /* threshold partial pivoting setting */
#define UMFPACK_ALLOC_INIT 6 /* initial allocation ratio */
#define UMFPACK_SYM_PIVOT_TOLERANCE 15 /* threshold, only for diag. entries */
#define UMFPACK_SCALE 16 /* what row scaling to do */
#define UMFPACK_FRONT_ALLOC_INIT 17 /* frontal matrix allocation ratio */
#define UMFPACK_DROPTOL 18 /* drop tolerance for entries in L,U */
/* used in UMFPACK_*solve only: */
#define UMFPACK_IRSTEP 7 /* max # of iterative refinements */
/* compile-time settings - Control [8..11] cannot be changed at run time: */
#define UMFPACK_COMPILED_WITH_BLAS 8 /* uses the BLAS */
/* 9,12: unused */
/* -------------------------------------------------------------------------- */
/* Control [UMFPACK_STRATEGY] is one of the following: */
#define UMFPACK_STRATEGY_AUTO 0 /* use sym. or unsym. strategy */
#define UMFPACK_STRATEGY_UNSYMMETRIC 1 /* COLAMD(A), coletree postorder,
not prefer diag*/
#define UMFPACK_STRATEGY_OBSOLETE 2 /* 2-by-2 is no longer available */
#define UMFPACK_STRATEGY_SYMMETRIC 3 /* AMD(A+A'), no coletree postorder,
prefer diagonal */
/* Control [UMFPACK_SCALE] is one of the following: */
#define UMFPACK_SCALE_NONE 0 /* no scaling */
#define UMFPACK_SCALE_SUM 1 /* default: divide each row by sum (abs (row))*/
#define UMFPACK_SCALE_MAX 2 /* divide each row by max (abs (row)) */
/* Control [UMFPACK_ORDERING] and Info [UMFPACK_ORDERING_USED] are one of: */
#define UMFPACK_ORDERING_CHOLMOD 0 /* use CHOLMOD (AMD/COLAMD then METIS)*/
#define UMFPACK_ORDERING_AMD 1 /* use AMD/COLAMD */
#define UMFPACK_ORDERING_GIVEN 2 /* user-provided Qinit */
#define UMFPACK_ORDERING_METIS 3 /* use METIS */
#define UMFPACK_ORDERING_BEST 4 /* try many orderings, pick best */
#define UMFPACK_ORDERING_NONE 5 /* natural ordering */
#define UMFPACK_ORDERING_USER 6 /* user-provided function */
/* AMD/COLAMD means: use AMD for symmetric strategy, COLAMD for unsymmetric */
/* -------------------------------------------------------------------------- */
/* default values of Control: */
/* -------------------------------------------------------------------------- */
#define UMFPACK_DEFAULT_PRL 1
#define UMFPACK_DEFAULT_DENSE_ROW 0.2
#define UMFPACK_DEFAULT_DENSE_COL 0.2
#define UMFPACK_DEFAULT_PIVOT_TOLERANCE 0.1
#define UMFPACK_DEFAULT_SYM_PIVOT_TOLERANCE 0.001
#define UMFPACK_DEFAULT_BLOCK_SIZE 32
#define UMFPACK_DEFAULT_ALLOC_INIT 0.7
#define UMFPACK_DEFAULT_FRONT_ALLOC_INIT 0.5
#define UMFPACK_DEFAULT_IRSTEP 2
#define UMFPACK_DEFAULT_SCALE UMFPACK_SCALE_SUM
#define UMFPACK_DEFAULT_STRATEGY UMFPACK_STRATEGY_AUTO
#define UMFPACK_DEFAULT_AMD_DENSE AMD_DEFAULT_DENSE
#define UMFPACK_DEFAULT_FIXQ 0
#define UMFPACK_DEFAULT_AGGRESSIVE 1
#define UMFPACK_DEFAULT_DROPTOL 0
#define UMFPACK_DEFAULT_ORDERING UMFPACK_ORDERING_AMD
#define UMFPACK_DEFAULT_SINGLETONS TRUE
/* default values of Control may change in future versions of UMFPACK. */
/* -------------------------------------------------------------------------- */
/* status codes */
/* -------------------------------------------------------------------------- */
#define UMFPACK_OK (0)
/* status > 0 means a warning, but the method was successful anyway. */
/* A Symbolic or Numeric object was still created. */
#define UMFPACK_WARNING_singular_matrix (1)
/* The following warnings were added in umfpack_*_get_determinant */
#define UMFPACK_WARNING_determinant_underflow (2)
#define UMFPACK_WARNING_determinant_overflow (3)
/* status < 0 means an error, and the method was not successful. */
/* No Symbolic of Numeric object was created. */
#define UMFPACK_ERROR_out_of_memory (-1)
#define UMFPACK_ERROR_invalid_Numeric_object (-3)
#define UMFPACK_ERROR_invalid_Symbolic_object (-4)
#define UMFPACK_ERROR_argument_missing (-5)
#define UMFPACK_ERROR_n_nonpositive (-6)
#define UMFPACK_ERROR_invalid_matrix (-8)
#define UMFPACK_ERROR_different_pattern (-11)
#define UMFPACK_ERROR_invalid_system (-13)
#define UMFPACK_ERROR_invalid_permutation (-15)
#define UMFPACK_ERROR_internal_error (-911) /* yes, call me if you get this! */
#define UMFPACK_ERROR_file_IO (-17)
#define UMFPACK_ERROR_ordering_failed (-18)
/* -------------------------------------------------------------------------- */
/* solve codes */
/* -------------------------------------------------------------------------- */
/* Solve the system ( )x=b, where ( ) is defined below. "t" refers to the */
/* linear algebraic transpose (complex conjugate if A is complex), or the (') */
/* operator in MATLAB. "at" refers to the array transpose, or the (.') */
/* operator in MATLAB. */
#define UMFPACK_A (0) /* Ax=b */
#define UMFPACK_At (1) /* A'x=b */
#define UMFPACK_Aat (2) /* A.'x=b */
#define UMFPACK_Pt_L (3) /* P'Lx=b */
#define UMFPACK_L (4) /* Lx=b */
#define UMFPACK_Lt_P (5) /* L'Px=b */
#define UMFPACK_Lat_P (6) /* L.'Px=b */
#define UMFPACK_Lt (7) /* L'x=b */
#define UMFPACK_Lat (8) /* L.'x=b */
#define UMFPACK_U_Qt (9) /* UQ'x=b */
#define UMFPACK_U (10) /* Ux=b */
#define UMFPACK_Q_Ut (11) /* QU'x=b */
#define UMFPACK_Q_Uat (12) /* QU.'x=b */
#define UMFPACK_Ut (13) /* U'x=b */
#define UMFPACK_Uat (14) /* U.'x=b */
/* -------------------------------------------------------------------------- */
/* Integer constants are used for status and solve codes instead of enum */
/* to make it easier for a Fortran code to call UMFPACK. */
#ifdef __cplusplus
}
#endif
#endif /* UMFPACK_H */

View File

@ -0,0 +1,110 @@
/* ========================================================================== */
/* === umfpack_col_to_triplet =============================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_col_to_triplet
(
int n_col,
const int Ap [ ],
int Tj [ ]
) ;
UF_long umfpack_dl_col_to_triplet
(
UF_long n_col,
const UF_long Ap [ ],
UF_long Tj [ ]
) ;
int umfpack_zi_col_to_triplet
(
int n_col,
const int Ap [ ],
int Tj [ ]
) ;
UF_long umfpack_zl_col_to_triplet
(
UF_long n_col,
const UF_long Ap [ ],
UF_long Tj [ ]
) ;
/*
double int Syntax:
#include "umfpack.h"
int n_col, *Tj, *Ap, status ;
status = umfpack_di_col_to_triplet (n_col, Ap, Tj) ;
double UF_long Syntax:
#include "umfpack.h"
UF_long n_col, *Tj, *Ap, status ;
status = umfpack_dl_col_to_triplet (n_col, Ap, Tj) ;
complex int Syntax:
#include "umfpack.h"
int n_col, *Tj, *Ap, status ;
status = umfpack_zi_col_to_triplet (n_col, Ap, Tj) ;
complex UF_long Syntax:
#include "umfpack.h"
UF_long n_col, *Tj, *Ap, status ;
status = umfpack_zl_col_to_triplet (n_col, Ap, Tj) ;
Purpose:
Converts a column-oriented matrix to a triplet form. Only the column
pointers, Ap, are required, and only the column indices of the triplet form
are constructed. This routine is the opposite of umfpack_*_triplet_to_col.
The matrix may be singular and/or rectangular. Analogous to [i, Tj, x] =
find (A) in MATLAB, except that zero entries present in the column-form of
A are present in the output, and i and x are not created (those are just Ai
and Ax+Az*1i, respectively, for a column-form matrix A).
Returns:
UMFPACK_OK if successful
UMFPACK_ERROR_argument_missing if Ap or Tj is missing
UMFPACK_ERROR_n_nonpositive if n_col <= 0
UMFPACK_ERROR_invalid_matrix if Ap [n_col] < 0, Ap [0] != 0, or
Ap [j] > Ap [j+1] for any j in the range 0 to n-1.
Unsorted columns and duplicate entries do not cause an error (these would
only be evident by examining Ai). Empty rows and columns are OK.
Arguments:
Int n_col ; Input argument, not modified.
A is an n_row-by-n_col matrix. Restriction: n_col > 0.
(n_row is not required)
Int Ap [n_col+1] ; Input argument, not modified.
The column pointers of the column-oriented form of the matrix. See
umfpack_*_*symbolic for a description. The number of entries in
the matrix is nz = Ap [n_col]. Restrictions on Ap are the same as those
for umfpack_*_transpose. Ap [0] must be zero, nz must be >= 0, and
Ap [j] <= Ap [j+1] and Ap [j] <= Ap [n_col] must be true for all j in
the range 0 to n_col-1. Empty columns are OK (that is, Ap [j] may equal
Ap [j+1] for any j in the range 0 to n_col-1).
Int Tj [nz] ; Output argument.
Tj is an integer array of size nz on input, where nz = Ap [n_col].
Suppose the column-form of the matrix is held in Ap, Ai, Ax, and Az
(see umfpack_*_*symbolic for a description). Then on output, the
triplet form of the same matrix is held in Ai (row indices), Tj (column
indices), and Ax (numerical values). Note, however, that this routine
does not require Ai and Ax (or Az for the complex version) in order to
do the conversion.
*/

View File

@ -0,0 +1,69 @@
/* ========================================================================== */
/* === umfpack_defaults ===================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
void umfpack_di_defaults
(
double Control [UMFPACK_CONTROL]
) ;
void umfpack_dl_defaults
(
double Control [UMFPACK_CONTROL]
) ;
void umfpack_zi_defaults
(
double Control [UMFPACK_CONTROL]
) ;
void umfpack_zl_defaults
(
double Control [UMFPACK_CONTROL]
) ;
/*
double int Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL] ;
umfpack_di_defaults (Control) ;
double UF_long Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL] ;
umfpack_dl_defaults (Control) ;
complex int Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL] ;
umfpack_zi_defaults (Control) ;
complex UF_long Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL] ;
umfpack_zl_defaults (Control) ;
Purpose:
Sets the default control parameter settings.
Arguments:
double Control [UMFPACK_CONTROL] ; Output argument.
Control is set to the default control parameter settings. You can
then modify individual settings by changing specific entries in the
Control array. If Control is a (double *) NULL pointer, then
umfpack_*_defaults returns silently (no error is generated, since
passing a NULL pointer for Control to any UMFPACK routine is valid).
*/

View File

@ -0,0 +1,67 @@
/* ========================================================================== */
/* === umfpack_free_numeric ================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
void umfpack_di_free_numeric
(
void **Numeric
) ;
void umfpack_dl_free_numeric
(
void **Numeric
) ;
void umfpack_zi_free_numeric
(
void **Numeric
) ;
void umfpack_zl_free_numeric
(
void **Numeric
) ;
/*
double int Syntax:
#include "umfpack.h"
void *Numeric ;
umfpack_di_free_numeric (&Numeric) ;
double UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
umfpack_dl_free_numeric (&Numeric) ;
complex int Syntax:
#include "umfpack.h"
void *Numeric ;
umfpack_zi_free_numeric (&Numeric) ;
complex UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
umfpack_zl_free_numeric (&Numeric) ;
Purpose:
Deallocates the Numeric object and sets the Numeric handle to NULL. This
routine is the only valid way of destroying the Numeric object.
Arguments:
void **Numeric ; Input argument, set to (void *) NULL on output.
Numeric points to a valid Numeric object, computed by umfpack_*_numeric.
No action is taken if Numeric is a (void *) NULL pointer.
*/

View File

@ -0,0 +1,67 @@
/* ========================================================================== */
/* === umfpack_free_symbolic ================================================ */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
void umfpack_di_free_symbolic
(
void **Symbolic
) ;
void umfpack_dl_free_symbolic
(
void **Symbolic
) ;
void umfpack_zi_free_symbolic
(
void **Symbolic
) ;
void umfpack_zl_free_symbolic
(
void **Symbolic
) ;
/*
double int Syntax:
#include "umfpack.h"
void *Symbolic ;
umfpack_di_free_symbolic (&Symbolic) ;
double UF_long Syntax:
#include "umfpack.h"
void *Symbolic ;
umfpack_dl_free_symbolic (&Symbolic) ;
complex int Syntax:
#include "umfpack.h"
void *Symbolic ;
umfpack_zi_free_symbolic (&Symbolic) ;
complex UF_long Syntax:
#include "umfpack.h"
void *Symbolic ;
umfpack_zl_free_symbolic (&Symbolic) ;
Purpose:
Deallocates the Symbolic object and sets the Symbolic handle to NULL. This
routine is the only valid way of destroying the Symbolic object.
Arguments:
void **Symbolic ; Input argument, set to (void *) NULL on output.
Points to a valid Symbolic object computed by umfpack_*_symbolic.
No action is taken if Symbolic is a (void *) NULL pointer.
*/

View File

@ -0,0 +1,196 @@
/* ========================================================================== */
/* === UMFPACK_get_determinant ============================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* UMFPACK_get_determinant contributed by David Bateman, Motorola, Paris. */
/* -------------------------------------------------------------------------- */
int umfpack_di_get_determinant
(
double *Mx,
double *Ex,
void *NumericHandle,
double User_Info [UMFPACK_INFO]
) ;
UF_long umfpack_dl_get_determinant
(
double *Mx,
double *Ex,
void *NumericHandle,
double User_Info [UMFPACK_INFO]
) ;
int umfpack_zi_get_determinant
(
double *Mx,
double *Mz,
double *Ex,
void *NumericHandle,
double User_Info [UMFPACK_INFO]
) ;
UF_long umfpack_zl_get_determinant
(
double *Mx,
double *Mz,
double *Ex,
void *NumericHandle,
double User_Info [UMFPACK_INFO]
) ;
/*
double int Syntax:
#include "umfpack.h"
void *Numeric ;
int status ;
double Mx, Ex, Info [UMFPACK_INFO] ;
status = umfpack_di_get_determinant (&Mx, &Ex, Numeric, Info) ;
double UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
UF_long status ;
double Mx, Ex, Info [UMFPACK_INFO] ;
status = umfpack_dl_get_determinant (&Mx, &Ex, Numeric, Info) ;
complex int Syntax:
#include "umfpack.h"
void *Numeric ;
int status ;
double Mx, Mz, Ex, Info [UMFPACK_INFO] ;
status = umfpack_zi_get_determinant (&Mx, &Mz, &Ex, Numeric, Info) ;
complex int Syntax:
#include "umfpack.h"
void *Numeric ;
UF_long status ;
double *Mx, *Mz, *Ex, Info [UMFPACK_INFO] ;
status = umfpack_zl_get_determinant (&Mx, &Mz, &Ex, Numeric, Info) ;
packed complex int Syntax:
Same as above, except Mz is NULL.
Author: Contributed by David Bateman, Motorola, Paris
Purpose:
Using the LU factors and the permutation vectors contained in the Numeric
object, calculate the determinant of the matrix A.
The value of the determinant can be returned in two forms, depending on
whether Ex is NULL or not. If Ex is NULL then the value of the determinant
is returned on Mx and Mz for the real and imaginary parts. However, to
avoid over- or underflows, the determinant can be split into a mantissa
and exponent, and the parts returned separately, in which case Ex is not
NULL. The actual determinant is then given by
double det ;
det = Mx * pow (10.0, Ex) ;
for the double case, or
double det [2] ;
det [0] = Mx * pow (10.0, Ex) ; // real part
det [1] = Mz * pow (10.0, Ex) ; // imaginary part
for the complex case. Information on if the determinant will or has
over or under-flowed is given by Info [UMFPACK_STATUS].
In the "packed complex" syntax, Mx [0] holds the real part and Mx [1]
holds the imaginary part. Mz is not used (it is NULL).
Returns:
Returns UMFPACK_OK if sucessful. Returns UMFPACK_ERROR_out_of_memory if
insufficient memory is available for the n_row integer workspace that
umfpack_*_get_determinant allocates to construct pivots from the
permutation vectors. Returns UMFPACK_ERROR_invalid_Numeric_object if the
Numeric object provided as input is invalid. Returns
UMFPACK_WARNING_singular_matrix if the determinant is zero. Returns
UMFPACK_WARNING_determinant_underflow or
UMFPACK_WARNING_determinant_overflow if the determinant has underflowed
overflowed (for the case when Ex is NULL), or will overflow if Ex is not
NULL and det is computed (see above) in the user program.
Arguments:
double *Mx ; Output argument (array of size 1, or size 2 if Mz is NULL)
double *Mz ; Output argument (optional)
double *Ex ; Output argument (optional)
The determinant returned in mantissa/exponent form, as discussed above.
If Mz is NULL, then both the original and imaginary parts will be
returned in Mx. If Ex is NULL then the determinant is returned directly
in Mx and Mz (or Mx [0] and Mx [1] if Mz is NULL), rather than in
mantissa/exponent form.
void *Numeric ; Input argument, not modified.
Numeric must point to a valid Numeric object, computed by
umfpack_*_numeric.
double Info [UMFPACK_INFO] ; Output argument.
Contains information about the calculation of the determinant. If a
(double *) NULL pointer is passed, then no statistics are returned in
Info (this is not an error condition). The following statistics are
computed in umfpack_*_determinant:
Info [UMFPACK_STATUS]: status code. This is also the return value,
whether or not Info is present.
UMFPACK_OK
The determinant was successfully found.
UMFPACK_ERROR_out_of_memory
Insufficient memory to solve the linear system.
UMFPACK_ERROR_argument_missing
Mx is missing (NULL).
UMFPACK_ERROR_invalid_Numeric_object
The Numeric object is not valid.
UMFPACK_ERROR_invalid_system
The matrix is rectangular. Only square systems can be
handled.
UMFPACK_WARNING_singluar_matrix
The determinant is zero or NaN. The matrix is singular.
UMFPACK_WARNING_determinant_underflow
When passing from mantissa/exponent form to the determinant
an underflow has or will occur. If the mantissa/exponent from
of obtaining the determinant is used, the underflow will occur
in the user program. If the single argument method of
obtaining the determinant is used, the underflow has already
occurred.
UMFPACK_WARNING_determinant_overflow
When passing from mantissa/exponent form to the determinant
an overflow has or will occur. If the mantissa/exponent from
of obtaining the determinant is used, the overflow will occur
in the user program. If the single argument method of
obtaining the determinant is used, the overflow has already
occurred.
*/

View File

@ -0,0 +1,137 @@
/* ========================================================================== */
/* === umfpack_get_lunz ===================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_get_lunz
(
int *lnz,
int *unz,
int *n_row,
int *n_col,
int *nz_udiag,
void *Numeric
) ;
UF_long umfpack_dl_get_lunz
(
UF_long *lnz,
UF_long *unz,
UF_long *n_row,
UF_long *n_col,
UF_long *nz_udiag,
void *Numeric
) ;
int umfpack_zi_get_lunz
(
int *lnz,
int *unz,
int *n_row,
int *n_col,
int *nz_udiag,
void *Numeric
) ;
UF_long umfpack_zl_get_lunz
(
UF_long *lnz,
UF_long *unz,
UF_long *n_row,
UF_long *n_col,
UF_long *nz_udiag,
void *Numeric
) ;
/*
double int Syntax:
#include "umfpack.h"
void *Numeric ;
int status, lnz, unz, n_row, n_col, nz_udiag ;
status = umfpack_di_get_lunz (&lnz, &unz, &n_row, &n_col, &nz_udiag,
Numeric) ;
double UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
UF_long status, lnz, unz, n_row, n_col, nz_udiag ;
status = umfpack_dl_get_lunz (&lnz, &unz, &n_row, &n_col, &nz_udiag,
Numeric) ;
complex int Syntax:
#include "umfpack.h"
void *Numeric ;
int status, lnz, unz, n_row, n_col, nz_udiag ;
status = umfpack_zi_get_lunz (&lnz, &unz, &n_row, &n_col, &nz_udiag,
Numeric) ;
complex UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
UF_long status, lnz, unz, n_row, n_col, nz_udiag ;
status = umfpack_zl_get_lunz (&lnz, &unz, &n_row, &n_col, &nz_udiag,
Numeric) ;
Purpose:
Determines the size and number of nonzeros in the LU factors held by the
Numeric object. These are also the sizes of the output arrays required
by umfpack_*_get_numeric.
The matrix L is n_row -by- min(n_row,n_col), with lnz nonzeros, including
the entries on the unit diagonal of L.
The matrix U is min(n_row,n_col) -by- n_col, with unz nonzeros, including
nonzeros on the diagonal of U.
Returns:
UMFPACK_OK if successful.
UMFPACK_ERROR_invalid_Numeric_object if Numeric is not a valid object.
UMFPACK_ERROR_argument_missing if any other argument is (Int *) NULL.
Arguments:
Int *lnz ; Output argument.
The number of nonzeros in L, including the diagonal (which is all
one's). This value is the required size of the Lj and Lx arrays as
computed by umfpack_*_get_numeric. The value of lnz is identical to
Info [UMFPACK_LNZ], if that value was returned by umfpack_*_numeric.
Int *unz ; Output argument.
The number of nonzeros in U, including the diagonal. This value is the
required size of the Ui and Ux arrays as computed by
umfpack_*_get_numeric. The value of unz is identical to
Info [UMFPACK_UNZ], if that value was returned by umfpack_*_numeric.
Int *n_row ; Output argument.
Int *n_col ; Output argument.
The order of the L and U matrices. L is n_row -by- min(n_row,n_col)
and U is min(n_row,n_col) -by- n_col.
Int *nz_udiag ; Output argument.
The number of numerically nonzero values on the diagonal of U. The
matrix is singular if nz_diag < min(n_row,n_col). A divide-by-zero
will occur if nz_diag < n_row == n_col when solving a sparse system
involving the matrix U in umfpack_*_*solve. The value of nz_udiag is
identical to Info [UMFPACK_UDIAG_NZ] if that value was returned by
umfpack_*_numeric.
void *Numeric ; Input argument, not modified.
Numeric must point to a valid Numeric object, computed by
umfpack_*_numeric.
*/

View File

@ -0,0 +1,254 @@
/* ========================================================================== */
/* === umfpack_get_numeric ================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_get_numeric
(
int Lp [ ],
int Lj [ ],
double Lx [ ],
int Up [ ],
int Ui [ ],
double Ux [ ],
int P [ ],
int Q [ ],
double Dx [ ],
int *do_recip,
double Rs [ ],
void *Numeric
) ;
UF_long umfpack_dl_get_numeric
(
UF_long Lp [ ],
UF_long Lj [ ],
double Lx [ ],
UF_long Up [ ],
UF_long Ui [ ],
double Ux [ ],
UF_long P [ ],
UF_long Q [ ],
double Dx [ ],
UF_long *do_recip,
double Rs [ ],
void *Numeric
) ;
int umfpack_zi_get_numeric
(
int Lp [ ],
int Lj [ ],
double Lx [ ], double Lz [ ],
int Up [ ],
int Ui [ ],
double Ux [ ], double Uz [ ],
int P [ ],
int Q [ ],
double Dx [ ], double Dz [ ],
int *do_recip,
double Rs [ ],
void *Numeric
) ;
UF_long umfpack_zl_get_numeric
(
UF_long Lp [ ],
UF_long Lj [ ],
double Lx [ ], double Lz [ ],
UF_long Up [ ],
UF_long Ui [ ],
double Ux [ ], double Uz [ ],
UF_long P [ ],
UF_long Q [ ],
double Dx [ ], double Dz [ ],
UF_long *do_recip,
double Rs [ ],
void *Numeric
) ;
/*
double int Syntax:
#include "umfpack.h"
void *Numeric ;
int *Lp, *Lj, *Up, *Ui, *P, *Q, status, do_recip ;
double *Lx, *Ux, *Dx, *Rs ;
status = umfpack_di_get_numeric (Lp, Lj, Lx, Up, Ui, Ux, P, Q, Dx,
&do_recip, Rs, Numeric) ;
double UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
UF_long *Lp, *Lj, *Up, *Ui, *P, *Q, status, do_recip ;
double *Lx, *Ux, *Dx, *Rs ;
status = umfpack_dl_get_numeric (Lp, Lj, Lx, Up, Ui, Ux, P, Q, Dx,
&do_recip, Rs, Numeric) ;
complex int Syntax:
#include "umfpack.h"
void *Numeric ;
int *Lp, *Lj, *Up, *Ui, *P, *Q, status, do_recip ;
double *Lx, *Lz, *Ux, *Uz, *Dx, *Dz, *Rs ;
status = umfpack_zi_get_numeric (Lp, Lj, Lx, Lz, Up, Ui, Ux, Uz, P, Q,
Dx, Dz, &do_recip, Rs, Numeric) ;
complex UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
UF_long *Lp, *Lj, *Up, *Ui, *P, *Q, status, do_recip ;
double *Lx, *Lz, *Ux, *Uz, *Dx, *Dz, *Rs ;
status = umfpack_zl_get_numeric (Lp, Lj, Lx, Lz, Up, Ui, Ux, Uz, P, Q,
Dx, Dz, &do_recip, Rs, Numeric) ;
packed complex int/UF_long Syntax:
Same as above, except Lz, Uz, and Dz are all NULL.
Purpose:
This routine copies the LU factors and permutation vectors from the Numeric
object into user-accessible arrays. This routine is not needed to solve a
linear system. Note that the output arrays Lp, Lj, Lx, Up, Ui, Ux, P, Q,
Dx, and Rs are not allocated by umfpack_*_get_numeric; they must exist on
input.
All output arguments are optional. If any of them are NULL
on input, then that part of the LU factorization is not copied. You can
use this routine to extract just the parts of the LU factorization that
you want. For example, to retrieve just the column permutation Q, use:
#define noD (double *) NULL
#define noI (int *) NULL
status = umfpack_di_get_numeric (noI, noI, noD, noI, noI, noD, noI,
Q, noD, noI, noD, Numeric) ;
Returns:
Returns UMFPACK_OK if successful. Returns UMFPACK_ERROR_out_of_memory
if insufficient memory is available for the 2*max(n_row,n_col) integer
workspace that umfpack_*_get_numeric allocates to construct L and/or U.
Returns UMFPACK_ERROR_invalid_Numeric_object if the Numeric object provided
as input is invalid.
Arguments:
Int Lp [n_row+1] ; Output argument.
Int Lj [lnz] ; Output argument.
double Lx [lnz] ; Output argument. Size 2*lnz for packed complex case.
double Lz [lnz] ; Output argument for complex versions.
The n_row-by-min(n_row,n_col) matrix L is returned in compressed-row
form. The column indices of row i and corresponding numerical values
are in:
Lj [Lp [i] ... Lp [i+1]-1]
Lx [Lp [i] ... Lp [i+1]-1] real part
Lz [Lp [i] ... Lp [i+1]-1] imaginary part (complex versions)
respectively. Each row is stored in sorted order, from low column
indices to higher. The last entry in each row is the diagonal, which
is numerically equal to one. The sizes of Lp, Lj, Lx, and Lz are
returned by umfpack_*_get_lunz. If Lp, Lj, or Lx are not present,
then the matrix L is not returned. This is not an error condition.
The L matrix can be printed if n_row, Lp, Lj, Lx (and Lz for the split
complex case) are passed to umfpack_*_report_matrix (using the
"row" form).
If Lx is present and Lz is NULL, then both real
and imaginary parts are returned in Lx[0..2*lnz-1], with Lx[2*k]
and Lx[2*k+1] being the real and imaginary part of the kth entry.
Int Up [n_col+1] ; Output argument.
Int Ui [unz] ; Output argument.
double Ux [unz] ; Output argument. Size 2*unz for packed complex case.
double Uz [unz] ; Output argument for complex versions.
The min(n_row,n_col)-by-n_col matrix U is returned in compressed-column
form. The row indices of column j and corresponding numerical values
are in
Ui [Up [j] ... Up [j+1]-1]
Ux [Up [j] ... Up [j+1]-1] real part
Uz [Up [j] ... Up [j+1]-1] imaginary part (complex versions)
respectively. Each column is stored in sorted order, from low row
indices to higher. The last entry in each column is the diagonal
(assuming that it is nonzero). The sizes of Up, Ui, Ux, and Uz are
returned by umfpack_*_get_lunz. If Up, Ui, or Ux are not present,
then the matrix U is not returned. This is not an error condition.
The U matrix can be printed if n_col, Up, Ui, Ux (and Uz for the
split complex case) are passed to umfpack_*_report_matrix (using the
"column" form).
If Ux is present and Uz is NULL, then both real
and imaginary parts are returned in Ux[0..2*unz-1], with Ux[2*k]
and Ux[2*k+1] being the real and imaginary part of the kth entry.
Int P [n_row] ; Output argument.
The permutation vector P is defined as P [k] = i, where the original
row i of A is the kth pivot row in PAQ. If you do not want the P vector
to be returned, simply pass (Int *) NULL for P. This is not an error
condition. You can print P and Q with umfpack_*_report_perm.
Int Q [n_col] ; Output argument.
The permutation vector Q is defined as Q [k] = j, where the original
column j of A is the kth pivot column in PAQ. If you not want the Q
vector to be returned, simply pass (Int *) NULL for Q. This is not
an error condition. Note that Q is not necessarily identical to
Qtree, the column pre-ordering held in the Symbolic object. Refer to
the description of Qtree and Front_npivcol in umfpack_*_get_symbolic for
details.
double Dx [min(n_row,n_col)] ; Output argument. Size 2*n for
the packed complex case.
double Dz [min(n_row,n_col)] ; Output argument for complex versions.
The diagonal of U is also returned in Dx and Dz. You can extract the
diagonal of U without getting all of U by passing a non-NULL Dx (and
Dz for the complex version) and passing Up, Ui, and Ux as NULL. Dx is
the real part of the diagonal, and Dz is the imaginary part.
If Dx is present and Dz is NULL, then both real
and imaginary parts are returned in Dx[0..2*min(n_row,n_col)-1],
with Dx[2*k] and Dx[2*k+1] being the real and imaginary part of the kth
entry.
Int *do_recip ; Output argument.
This argument defines how the scale factors Rs are to be interpretted.
If do_recip is TRUE (one), then the scale factors Rs [i] are to be used
by multiplying row i by Rs [i]. Otherwise, the entries in row i are to
be divided by Rs [i].
If UMFPACK has been compiled with gcc, or for MATLAB as either a
built-in routine or as a mexFunction, then the NRECIPROCAL flag is
set, and do_recip will always be FALSE (zero).
double Rs [n_row] ; Output argument.
The row scale factors are returned in Rs [0..n_row-1]. Row i of A is
scaled by dividing or multiplying its values by Rs [i]. If default
scaling is in use, Rs [i] is the sum of the absolute values of row i
(or its reciprocal). If max row scaling is in use, then Rs [i] is the
maximum absolute value in row i (or its reciprocal).
Otherwise, Rs [i] = 1. If row i is all zero, Rs [i] = 1 as well. For
the complex version, an approximate absolute value is used
(|x_real|+|x_imag|).
void *Numeric ; Input argument, not modified.
Numeric must point to a valid Numeric object, computed by
umfpack_*_numeric.
*/

View File

@ -0,0 +1,337 @@
/* ========================================================================== */
/* === umfpack_get_symbolic ================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_get_symbolic
(
int *n_row,
int *n_col,
int *n1,
int *nz,
int *nfr,
int *nchains,
int P [ ],
int Q [ ],
int Front_npivcol [ ],
int Front_parent [ ],
int Front_1strow [ ],
int Front_leftmostdesc [ ],
int Chain_start [ ],
int Chain_maxrows [ ],
int Chain_maxcols [ ],
void *Symbolic
) ;
UF_long umfpack_dl_get_symbolic
(
UF_long *n_row,
UF_long *n_col,
UF_long *n1,
UF_long *nz,
UF_long *nfr,
UF_long *nchains,
UF_long P [ ],
UF_long Q [ ],
UF_long Front_npivcol [ ],
UF_long Front_parent [ ],
UF_long Front_1strow [ ],
UF_long Front_leftmostdesc [ ],
UF_long Chain_start [ ],
UF_long Chain_maxrows [ ],
UF_long Chain_maxcols [ ],
void *Symbolic
) ;
int umfpack_zi_get_symbolic
(
int *n_row,
int *n_col,
int *n1,
int *nz,
int *nfr,
int *nchains,
int P [ ],
int Q [ ],
int Front_npivcol [ ],
int Front_parent [ ],
int Front_1strow [ ],
int Front_leftmostdesc [ ],
int Chain_start [ ],
int Chain_maxrows [ ],
int Chain_maxcols [ ],
void *Symbolic
) ;
UF_long umfpack_zl_get_symbolic
(
UF_long *n_row,
UF_long *n_col,
UF_long *n1,
UF_long *nz,
UF_long *nfr,
UF_long *nchains,
UF_long P [ ],
UF_long Q [ ],
UF_long Front_npivcol [ ],
UF_long Front_parent [ ],
UF_long Front_1strow [ ],
UF_long Front_leftmostdesc [ ],
UF_long Chain_start [ ],
UF_long Chain_maxrows [ ],
UF_long Chain_maxcols [ ],
void *Symbolic
) ;
/*
double int Syntax:
#include "umfpack.h"
int status, n_row, n_col, nz, nfr, nchains, *P, *Q,
*Front_npivcol, *Front_parent, *Front_1strow, *Front_leftmostdesc,
*Chain_start, *Chain_maxrows, *Chain_maxcols ;
void *Symbolic ;
status = umfpack_di_get_symbolic (&n_row, &n_col, &nz, &nfr, &nchains,
P, Q, Front_npivcol, Front_parent, Front_1strow,
Front_leftmostdesc, Chain_start, Chain_maxrows, Chain_maxcols,
Symbolic) ;
double UF_long Syntax:
#include "umfpack.h"
UF_long status, n_row, n_col, nz, nfr, nchains, *P, *Q,
*Front_npivcol, *Front_parent, *Front_1strow, *Front_leftmostdesc,
*Chain_start, *Chain_maxrows, *Chain_maxcols ;
void *Symbolic ;
status = umfpack_dl_get_symbolic (&n_row, &n_col, &nz, &nfr, &nchains,
P, Q, Front_npivcol, Front_parent, Front_1strow,
Front_leftmostdesc, Chain_start, Chain_maxrows, Chain_maxcols,
Symbolic) ;
complex int Syntax:
#include "umfpack.h"
int status, n_row, n_col, nz, nfr, nchains, *P, *Q,
*Front_npivcol, *Front_parent, *Front_1strow, *Front_leftmostdesc,
*Chain_start, *Chain_maxrows, *Chain_maxcols ;
void *Symbolic ;
status = umfpack_zi_get_symbolic (&n_row, &n_col, &nz, &nfr, &nchains,
P, Q, Front_npivcol, Front_parent, Front_1strow,
Front_leftmostdesc, Chain_start, Chain_maxrows, Chain_maxcols,
Symbolic) ;
complex UF_long Syntax:
#include "umfpack.h"
UF_long status, n_row, n_col, nz, nfr, nchains, *P, *Q,
*Front_npivcol, *Front_parent, *Front_1strow, *Front_leftmostdesc,
*Chain_start, *Chain_maxrows, *Chain_maxcols ;
void *Symbolic ;
status = umfpack_zl_get_symbolic (&n_row, &n_col, &nz, &nfr, &nchains,
P, Q, Front_npivcol, Front_parent, Front_1strow,
Front_leftmostdesc, Chain_start, Chain_maxrows, Chain_maxcols,
Symbolic) ;
Purpose:
Copies the contents of the Symbolic object into simple integer arrays
accessible to the user. This routine is not needed to factorize and/or
solve a sparse linear system using UMFPACK. Note that the output arrays
P, Q, Front_npivcol, Front_parent, Front_1strow, Front_leftmostdesc,
Chain_start, Chain_maxrows, and Chain_maxcols are not allocated by
umfpack_*_get_symbolic; they must exist on input.
All output arguments are optional. If any of them are NULL
on input, then that part of the symbolic analysis is not copied. You can
use this routine to extract just the parts of the symbolic analysis that
you want. For example, to retrieve just the column permutation Q, use:
#define noI (int *) NULL
status = umfpack_di_get_symbolic (noI, noI, noI, noI, noI, noI, noI,
Q, noI, noI, noI, noI, noI, noI, noI, Symbolic) ;
The only required argument the last one, the pointer to the Symbolic object.
The Symbolic object is small. Its size for an n-by-n square matrix varies
from 4*n to 13*n, depending on the matrix. The object holds the initial
column permutation, the supernodal column elimination tree, and information
about each frontal matrix. You can print it with umfpack_*_report_symbolic.
Returns:
Returns UMFPACK_OK if successful, UMFPACK_ERROR_invalid_Symbolic_object
if Symbolic is an invalid object.
Arguments:
Int *n_row ; Output argument.
Int *n_col ; Output argument.
The dimensions of the matrix A analyzed by the call to
umfpack_*_symbolic that generated the Symbolic object.
Int *n1 ; Output argument.
The number of pivots with zero Markowitz cost (they have just one entry
in the pivot row, or the pivot column, or both). These appear first in
the output permutations P and Q.
Int *nz ; Output argument.
The number of nonzeros in A.
Int *nfr ; Output argument.
The number of frontal matrices that will be used by umfpack_*_numeric
to factorize the matrix A. It is in the range 0 to n_col.
Int *nchains ; Output argument.
The frontal matrices are related to one another by the supernodal
column elimination tree. Each node in this tree is one frontal matrix.
The tree is partitioned into a set of disjoint paths, and a frontal
matrix chain is one path in this tree. Each chain is factorized using
a unifrontal technique, with a single working array that holds each
frontal matrix in the chain, one at a time. nchains is in the range
0 to nfr.
Int P [n_row] ; Output argument.
The initial row permutation. If P [k] = i, then this means that
row i is the kth row in the pre-ordered matrix. In general, this P is
not the same as the final row permutation computed by umfpack_*_numeric.
For the unsymmetric strategy, P defines the row-merge order. Let j be
the column index of the leftmost nonzero entry in row i of A*Q. Then
P defines a sort of the rows according to this value. A row can appear
earlier in this ordering if it is aggressively absorbed before it can
become a pivot row. If P [k] = i, row i typically will not be the kth
pivot row.
For the symmetric strategy, P = Q. If no pivoting occurs during
numerical factorization, P [k] = i also defines the final permutation
of umfpack_*_numeric, for the symmetric strategy.
Int Q [n_col] ; Output argument.
The initial column permutation. If Q [k] = j, then this means that
column j is the kth pivot column in the pre-ordered matrix. Q is
not necessarily the same as the final column permutation Q, computed by
umfpack_*_numeric. The numeric factorization may reorder the pivot
columns within each frontal matrix to reduce fill-in. If the matrix is
structurally singular, and if the symmetric strategy is
used (or if Control [UMFPACK_FIXQ] > 0), then this Q will be the same
as the final column permutation computed in umfpack_*_numeric.
Int Front_npivcol [n_col+1] ; Output argument.
This array should be of size at least n_col+1, in order to guarantee
that it will be large enough to hold the output. Only the first nfr+1
entries are used, however.
The kth frontal matrix holds Front_npivcol [k] pivot columns. Thus, the
first frontal matrix, front 0, is used to factorize the first
Front_npivcol [0] columns; these correspond to the original columns
Q [0] through Q [Front_npivcol [0]-1]. The next frontal matrix
is used to factorize the next Front_npivcol [1] columns, which are thus
the original columns Q [Front_npivcol [0]] through
Q [Front_npivcol [0] + Front_npivcol [1] - 1], and so on. Columns
with no entries at all are put in a placeholder "front",
Front_npivcol [nfr]. The sum of Front_npivcol [0..nfr] is equal to
n_col.
Any modifications that umfpack_*_numeric makes to the initial column
permutation are constrained to within each frontal matrix. Thus, for
the first frontal matrix, Q [0] through Q [Front_npivcol [0]-1] is some
permutation of the columns Q [0] through
Q [Front_npivcol [0]-1]. For second frontal matrix,
Q [Front_npivcol [0]] through Q [Front_npivcol [0] + Front_npivcol[1]-1]
is some permutation of the same portion of Q, and so on. All pivot
columns are numerically factorized within the frontal matrix originally
determined by the symbolic factorization; there is no delayed pivoting
across frontal matrices.
Int Front_parent [n_col+1] ; Output argument.
This array should be of size at least n_col+1, in order to guarantee
that it will be large enough to hold the output. Only the first nfr+1
entries are used, however.
Front_parent [0..nfr] holds the supernodal column elimination tree
(including the placeholder front nfr, which may be empty). Each node in
the tree corresponds to a single frontal matrix. The parent of node f
is Front_parent [f].
Int Front_1strow [n_col+1] ; Output argument.
This array should be of size at least n_col+1, in order to guarantee
that it will be large enough to hold the output. Only the first nfr+1
entries are used, however.
Front_1strow [k] is the row index of the first row in A (P,Q)
whose leftmost entry is in a pivot column for the kth front. This is
necessary only to properly factorize singular matrices. Rows in the
range Front_1strow [k] to Front_1strow [k+1]-1 first become pivot row
candidates at the kth front. Any rows not eliminated in the kth front
may be selected as pivot rows in the parent of k (Front_parent [k])
and so on up the tree.
Int Front_leftmostdesc [n_col+1] ; Output argument.
This array should be of size at least n_col+1, in order to guarantee
that it will be large enough to hold the output. Only the first nfr+1
entries are used, however.
Front_leftmostdesc [k] is the leftmost descendant of front k, or k
if the front has no children in the tree. Since the rows and columns
(P and Q) have been post-ordered via a depth-first-search of
the tree, rows in the range Front_1strow [Front_leftmostdesc [k]] to
Front_1strow [k+1]-1 form the entire set of candidate pivot rows for
the kth front (some of these will typically have already been selected
by fronts in the range Front_leftmostdesc [k] to front k-1, before
the factorization reaches front k).
Chain_start [n_col+1] ; Output argument.
This array should be of size at least n_col+1, in order to guarantee
that it will be large enough to hold the output. Only the first
nchains+1 entries are used, however.
The kth frontal matrix chain consists of frontal matrices Chain_start[k]
through Chain_start [k+1]-1. Thus, Chain_start [0] is always 0, and
Chain_start [nchains] is the total number of frontal matrices, nfr. For
two adjacent fronts f and f+1 within a single chain, f+1 is always the
parent of f (that is, Front_parent [f] = f+1).
Int Chain_maxrows [n_col+1] ; Output argument.
Int Chain_maxcols [n_col+1] ; Output argument.
These arrays should be of size at least n_col+1, in order to guarantee
that they will be large enough to hold the output. Only the first
nchains entries are used, however.
The kth frontal matrix chain requires a single working array of
dimension Chain_maxrows [k] by Chain_maxcols [k], for the unifrontal
technique that factorizes the frontal matrix chain. Since the symbolic
factorization only provides an upper bound on the size of each frontal
matrix, not all of the working array is necessarily used during the
numerical factorization.
Note that the upper bound on the number of rows and columns of each
frontal matrix is computed by umfpack_*_symbolic, but all that is
required by umfpack_*_numeric is the maximum of these two sets of
values for each frontal matrix chain. Thus, the size of each
individual frontal matrix is not preserved in the Symbolic object.
void *Symbolic ; Input argument, not modified.
The Symbolic object, which holds the symbolic factorization computed by
umfpack_*_symbolic. The Symbolic object is not modified by
umfpack_*_get_symbolic.
*/

View File

@ -0,0 +1,22 @@
/* ========================================================================== */
/* === umfpack_global ======================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/* prototypes for global variables, and basic operators for complex values */
#ifndef EXTERN
#define EXTERN extern
#endif
EXTERN double (*umfpack_hypot) (double, double) ;
EXTERN int (*umfpack_divcomplex) (double, double, double, double, double *, double *) ;
double umf_hypot (double x, double y) ;
int umf_divcomplex (double, double, double, double, double *, double *) ;

View File

@ -0,0 +1,95 @@
/* ========================================================================== */
/* === umfpack_load_numeric ================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_load_numeric
(
void **Numeric,
char *filename
) ;
UF_long umfpack_dl_load_numeric
(
void **Numeric,
char *filename
) ;
int umfpack_zi_load_numeric
(
void **Numeric,
char *filename
) ;
UF_long umfpack_zl_load_numeric
(
void **Numeric,
char *filename
) ;
/*
double int Syntax:
#include "umfpack.h"
int status ;
char *filename ;
void *Numeric ;
status = umfpack_di_load_numeric (&Numeric, filename) ;
double UF_long Syntax:
#include "umfpack.h"
UF_long status ;
char *filename ;
void *Numeric ;
status = umfpack_dl_load_numeric (&Numeric, filename) ;
complex int Syntax:
#include "umfpack.h"
int status ;
char *filename ;
void *Numeric ;
status = umfpack_zi_load_numeric (&Numeric, filename) ;
complex UF_long Syntax:
#include "umfpack.h"
UF_long status ;
char *filename ;
void *Numeric ;
status = umfpack_zl_load_numeric (&Numeric, filename) ;
Purpose:
Loads a Numeric object from a file created by umfpack_*_save_numeric. The
Numeric handle passed to this routine is overwritten with the new object.
If that object exists prior to calling this routine, a memory leak will
occur. The contents of Numeric are ignored on input.
Returns:
UMFPACK_OK if successful.
UMFPACK_ERROR_out_of_memory if not enough memory is available.
UMFPACK_ERROR_file_IO if an I/O error occurred.
Arguments:
void **Numeric ; Output argument.
**Numeric is the address of a (void *) pointer variable in the user's
calling routine (see Syntax, above). On input, the contents of this
variable are not defined. On output, this variable holds a (void *)
pointer to the Numeric object (if successful), or (void *) NULL if
a failure occurred.
char *filename ; Input argument, not modified.
A string that contains the filename from which to read the Numeric
object.
*/

View File

@ -0,0 +1,95 @@
/* ========================================================================== */
/* === umfpack_load_symbolic ================================================ */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_load_symbolic
(
void **Symbolic,
char *filename
) ;
UF_long umfpack_dl_load_symbolic
(
void **Symbolic,
char *filename
) ;
int umfpack_zi_load_symbolic
(
void **Symbolic,
char *filename
) ;
UF_long umfpack_zl_load_symbolic
(
void **Symbolic,
char *filename
) ;
/*
double int Syntax:
#include "umfpack.h"
int status ;
char *filename ;
void *Symbolic ;
status = umfpack_di_load_symbolic (&Symbolic, filename) ;
double UF_long Syntax:
#include "umfpack.h"
UF_long status ;
char *filename ;
void *Symbolic ;
status = umfpack_dl_load_symbolic (&Symbolic, filename) ;
complex int Syntax:
#include "umfpack.h"
int status ;
char *filename ;
void *Symbolic ;
status = umfpack_zi_load_symbolic (&Symbolic, filename) ;
complex UF_long Syntax:
#include "umfpack.h"
UF_long status ;
char *filename ;
void *Symbolic ;
status = umfpack_zl_load_symbolic (&Symbolic, filename) ;
Purpose:
Loads a Symbolic object from a file created by umfpack_*_save_symbolic. The
Symbolic handle passed to this routine is overwritten with the new object.
If that object exists prior to calling this routine, a memory leak will
occur. The contents of Symbolic are ignored on input.
Returns:
UMFPACK_OK if successful.
UMFPACK_ERROR_out_of_memory if not enough memory is available.
UMFPACK_ERROR_file_IO if an I/O error occurred.
Arguments:
void **Symbolic ; Output argument.
**Symbolic is the address of a (void *) pointer variable in the user's
calling routine (see Syntax, above). On input, the contents of this
variable are not defined. On output, this variable holds a (void *)
pointer to the Symbolic object (if successful), or (void *) NULL if
a failure occurred.
char *filename ; Input argument, not modified.
A string that contains the filename from which to read the Symbolic
object.
*/

View File

@ -0,0 +1,543 @@
/* ========================================================================== */
/* === umfpack_numeric ====================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_numeric
(
const int Ap [ ],
const int Ai [ ],
const double Ax [ ],
void *Symbolic,
void **Numeric,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
UF_long umfpack_dl_numeric
(
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ],
void *Symbolic,
void **Numeric,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
int umfpack_zi_numeric
(
const int Ap [ ],
const int Ai [ ],
const double Ax [ ], const double Az [ ],
void *Symbolic,
void **Numeric,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
UF_long umfpack_zl_numeric
(
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ], const double Az [ ],
void *Symbolic,
void **Numeric,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
/*
double int Syntax:
#include "umfpack.h"
void *Symbolic, *Numeric ;
int *Ap, *Ai, status ;
double *Ax, Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ;
status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, Control, Info);
double UF_long Syntax:
#include "umfpack.h"
void *Symbolic, *Numeric ;
UF_long *Ap, *Ai, status ;
double *Ax, Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ;
status = umfpack_dl_numeric (Ap, Ai, Ax, Symbolic, &Numeric, Control, Info);
complex int Syntax:
#include "umfpack.h"
void *Symbolic, *Numeric ;
int *Ap, *Ai, status ;
double *Ax, *Az, Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ;
status = umfpack_zi_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric,
Control, Info) ;
complex UF_long Syntax:
#include "umfpack.h"
void *Symbolic, *Numeric ;
UF_long *Ap, *Ai, status ;
double *Ax, *Az, Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ;
status = umfpack_zl_numeric (Ap, Ai, Ax, Az, Symbolic, &Numeric,
Control, Info) ;
packed complex Syntax:
Same as above, except that Az is NULL.
Purpose:
Given a sparse matrix A in column-oriented form, and a symbolic analysis
computed by umfpack_*_*symbolic, the umfpack_*_numeric routine performs the
numerical factorization, PAQ=LU, PRAQ=LU, or P(R\A)Q=LU, where P and Q are
permutation matrices (represented as permutation vectors), R is the row
scaling, L is unit-lower triangular, and U is upper triangular. This is
required before the system Ax=b (or other related linear systems) can be
solved. umfpack_*_numeric can be called multiple times for each call to
umfpack_*_*symbolic, to factorize a sequence of matrices with identical
nonzero pattern. Simply compute the Symbolic object once, with
umfpack_*_*symbolic, and reuse it for subsequent matrices. This routine
safely detects if the pattern changes, and sets an appropriate error code.
Returns:
The status code is returned. See Info [UMFPACK_STATUS], below.
Arguments:
Int Ap [n_col+1] ; Input argument, not modified.
This must be identical to the Ap array passed to umfpack_*_*symbolic.
The value of n_col is what was passed to umfpack_*_*symbolic (this is
held in the Symbolic object).
Int Ai [nz] ; Input argument, not modified, of size nz = Ap [n_col].
This must be identical to the Ai array passed to umfpack_*_*symbolic.
double Ax [nz] ; Input argument, not modified, of size nz = Ap [n_col].
Size 2*nz for packed complex case.
The numerical values of the sparse matrix A. The nonzero pattern (row
indices) for column j is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)], and
the corresponding numerical values are stored in
Ax [(Ap [j]) ... (Ap [j+1]-1)].
double Az [nz] ; Input argument, not modified, for complex versions.
For the complex versions, this holds the imaginary part of A. The
imaginary part of column j is held in Az [(Ap [j]) ... (Ap [j+1]-1)].
If Az is NULL, then both real
and imaginary parts are contained in Ax[0..2*nz-1], with Ax[2*k]
and Ax[2*k+1] being the real and imaginary part of the kth entry.
void *Symbolic ; Input argument, not modified.
The Symbolic object, which holds the symbolic factorization computed by
umfpack_*_*symbolic. The Symbolic object is not modified by
umfpack_*_numeric.
void **Numeric ; Output argument.
**Numeric is the address of a (void *) pointer variable in the user's
calling routine (see Syntax, above). On input, the contents of this
variable are not defined. On output, this variable holds a (void *)
pointer to the Numeric object (if successful), or (void *) NULL if
a failure occurred.
double Control [UMFPACK_CONTROL] ; Input argument, not modified.
If a (double *) NULL pointer is passed, then the default control
settings are used. Otherwise, the settings are determined from the
Control array. See umfpack_*_defaults on how to fill the Control
array with the default settings. If Control contains NaN's, the
defaults are used. The following Control parameters are used:
Control [UMFPACK_PIVOT_TOLERANCE]: relative pivot tolerance for
threshold partial pivoting with row interchanges. In any given
column, an entry is numerically acceptable if its absolute value is
greater than or equal to Control [UMFPACK_PIVOT_TOLERANCE] times
the largest absolute value in the column. A value of 1.0 gives true
partial pivoting. If less than or equal to zero, then any nonzero
entry is numerically acceptable as a pivot. Default: 0.1.
Smaller values tend to lead to sparser LU factors, but the solution
to the linear system can become inaccurate. Larger values can lead
to a more accurate solution (but not always), and usually an
increase in the total work.
For complex matrices, a cheap approximate of the absolute value
is used for the threshold partial pivoting test (|a_real| + |a_imag|
instead of the more expensive-to-compute exact absolute value
sqrt (a_real^2 + a_imag^2)).
Control [UMFPACK_SYM_PIVOT_TOLERANCE]:
If diagonal pivoting is attempted (the symmetric
strategy is used) then this parameter is used to control when the
diagonal entry is selected in a given pivot column. The absolute
value of the entry must be >= Control [UMFPACK_SYM_PIVOT_TOLERANCE]
times the largest absolute value in the column. A value of zero
will ensure that no off-diagonal pivoting is performed, except that
zero diagonal entries are not selected if there are any off-diagonal
nonzero entries.
If an off-diagonal pivot is selected, an attempt is made to restore
symmetry later on. Suppose A (i,j) is selected, where i != j.
If column i has not yet been selected as a pivot column, then
the entry A (j,i) is redefined as a "diagonal" entry, except that
the tighter tolerance (Control [UMFPACK_PIVOT_TOLERANCE]) is
applied. This strategy has an effect similar to 2-by-2 pivoting
for symmetric indefinite matrices. If a 2-by-2 block pivot with
nonzero structure
i j
i: 0 x
j: x 0
is selected in a symmetric indefinite factorization method, the
2-by-2 block is inverted and a rank-2 update is applied. In
UMFPACK, this 2-by-2 block would be reordered as
j i
i: x 0
j: 0 x
In both cases, the symmetry of the Schur complement is preserved.
Control [UMFPACK_SCALE]: Note that the user's input matrix is
never modified, only an internal copy is scaled.
There are three valid settings for this parameter. If any other
value is provided, the default is used.
UMFPACK_SCALE_NONE: no scaling is performed.
UMFPACK_SCALE_SUM: each row of the input matrix A is divided by
the sum of the absolute values of the entries in that row.
The scaled matrix has an infinity norm of 1.
UMFPACK_SCALE_MAX: each row of the input matrix A is divided by
the maximum the absolute values of the entries in that row.
In the scaled matrix the largest entry in each row has
a magnitude exactly equal to 1.
Note that for complex matrices, a cheap approximate absolute value
is used, |a_real| + |a_imag|, instead of the exact absolute value
sqrt ((a_real)^2 + (a_imag)^2).
Scaling is very important for the "symmetric" strategy when
diagonal pivoting is attempted. It also improves the performance
of the "unsymmetric" strategy.
Default: UMFPACK_SCALE_SUM.
Control [UMFPACK_ALLOC_INIT]:
When umfpack_*_numeric starts, it allocates memory for the Numeric
object. Part of this is of fixed size (approximately n double's +
12*n integers). The remainder is of variable size, which grows to
hold the LU factors and the frontal matrices created during
factorization. A estimate of the upper bound is computed by
umfpack_*_*symbolic, and returned by umfpack_*_*symbolic in
Info [UMFPACK_VARIABLE_PEAK_ESTIMATE] (in Units).
If Control [UMFPACK_ALLOC_INIT] is >= 0, umfpack_*_numeric initially
allocates space for the variable-sized part equal to this estimate
times Control [UMFPACK_ALLOC_INIT]. Typically, for matrices for
which the "unsymmetric" strategy applies, umfpack_*_numeric needs
only about half the estimated memory space, so a setting of 0.5 or
0.6 often provides enough memory for umfpack_*_numeric to factorize
the matrix with no subsequent increases in the size of this block.
If the matrix is ordered via AMD, then this non-negative parameter
is ignored. The initial allocation ratio computed automatically,
as 1.2 * (nz + Info [UMFPACK_SYMMETRIC_LUNZ]) /
(Info [UMFPACK_LNZ_ESTIMATE] + Info [UMFPACK_UNZ_ESTIMATE] -
min (n_row, n_col)).
If Control [UMFPACK_ALLOC_INIT] is negative, then umfpack_*_numeric
allocates a space with initial size (in Units) equal to
(-Control [UMFPACK_ALLOC_INIT]).
Regardless of the value of this parameter, a space equal to or
greater than the the bare minimum amount of memory needed to start
the factorization is always initially allocated. The bare initial
memory required is returned by umfpack_*_*symbolic in
Info [UMFPACK_VARIABLE_INIT_ESTIMATE] (an exact value, not an
estimate).
If the variable-size part of the Numeric object is found to be too
small sometime after numerical factorization has started, the memory
is increased in size by a factor of 1.2. If this fails, the
request is reduced by a factor of 0.95 until it succeeds, or until
it determines that no increase in size is possible. Garbage
collection then occurs.
The strategy of attempting to "malloc" a working space, and
re-trying with a smaller space, may not work when UMFPACK is used
as a mexFunction MATLAB, since mxMalloc aborts the mexFunction if it
fails. This issue does not affect the use of UMFPACK as a part of
the built-in x=A\b in MATLAB 6.5 and later.
If you are using the umfpack mexFunction, decrease the magnitude of
Control [UMFPACK_ALLOC_INIT] if you run out of memory in MATLAB.
Default initial allocation size: 0.7. Thus, with the default
control settings and the "unsymmetric" strategy, the upper-bound is
reached after two reallocations (0.7 * 1.2 * 1.2 = 1.008).
Changing this parameter has little effect on fill-in or operation
count. It has a small impact on run-time (the extra time required
to do the garbage collection and memory reallocation).
Control [UMFPACK_FRONT_ALLOC_INIT]:
When UMFPACK starts the factorization of each "chain" of frontal
matrices, it allocates a working array to hold the frontal matrices
as they are factorized. The symbolic factorization computes the
size of the largest possible frontal matrix that could occur during
the factorization of each chain.
If Control [UMFPACK_FRONT_ALLOC_INIT] is >= 0, the following
strategy is used. If the AMD ordering was used, this non-negative
parameter is ignored. A front of size (d+2)*(d+2) is allocated,
where d = Info [UMFPACK_SYMMETRIC_DMAX]. Otherwise, a front of
size Control [UMFPACK_FRONT_ALLOC_INIT] times the largest front
possible for this chain is allocated.
If Control [UMFPACK_FRONT_ALLOC_INIT] is negative, then a front of
size (-Control [UMFPACK_FRONT_ALLOC_INIT]) is allocated (where the
size is in terms of the number of numerical entries). This is done
regardless of the ordering method or ordering strategy used.
Default: 0.5.
Control [UMFPACK_DROPTOL]:
Entries in L and U with absolute value less than or equal to the
drop tolerance are removed from the data structures (unless leaving
them there reduces memory usage by reducing the space required
for the nonzero pattern of L and U).
Default: 0.0.
double Info [UMFPACK_INFO] ; Output argument.
Contains statistics about the numeric factorization. If a
(double *) NULL pointer is passed, then no statistics are returned in
Info (this is not an error condition). The following statistics are
computed in umfpack_*_numeric:
Info [UMFPACK_STATUS]: status code. This is also the return value,
whether or not Info is present.
UMFPACK_OK
Numeric factorization was successful. umfpack_*_numeric
computed a valid numeric factorization.
UMFPACK_WARNING_singular_matrix
Numeric factorization was successful, but the matrix is
singular. umfpack_*_numeric computed a valid numeric
factorization, but you will get a divide by zero in
umfpack_*_*solve. For the other cases below, no Numeric object
is created (*Numeric is (void *) NULL).
UMFPACK_ERROR_out_of_memory
Insufficient memory to complete the numeric factorization.
UMFPACK_ERROR_argument_missing
One or more required arguments are missing.
UMFPACK_ERROR_invalid_Symbolic_object
Symbolic object provided as input is invalid.
UMFPACK_ERROR_different_pattern
The pattern (Ap and/or Ai) has changed since the call to
umfpack_*_*symbolic which produced the Symbolic object.
Info [UMFPACK_NROW]: the value of n_row stored in the Symbolic object.
Info [UMFPACK_NCOL]: the value of n_col stored in the Symbolic object.
Info [UMFPACK_NZ]: the number of entries in the input matrix.
This value is obtained from the Symbolic object.
Info [UMFPACK_SIZE_OF_UNIT]: the number of bytes in a Unit, for memory
usage statistics below.
Info [UMFPACK_VARIABLE_INIT]: the initial size (in Units) of the
variable-sized part of the Numeric object. If this differs from
Info [UMFPACK_VARIABLE_INIT_ESTIMATE], then the pattern (Ap and/or
Ai) has changed since the last call to umfpack_*_*symbolic, which is
an error condition.
Info [UMFPACK_VARIABLE_PEAK]: the peak size (in Units) of the
variable-sized part of the Numeric object. This size is the amount
of space actually used inside the block of memory, not the space
allocated via UMF_malloc. You can reduce UMFPACK's memory
requirements by setting Control [UMFPACK_ALLOC_INIT] to the ratio
Info [UMFPACK_VARIABLE_PEAK] / Info[UMFPACK_VARIABLE_PEAK_ESTIMATE].
This will ensure that no memory reallocations occur (you may want to
add 0.001 to make sure that integer roundoff does not lead to a
memory size that is 1 Unit too small; otherwise, garbage collection
and reallocation will occur).
Info [UMFPACK_VARIABLE_FINAL]: the final size (in Units) of the
variable-sized part of the Numeric object. It holds just the
sparse LU factors.
Info [UMFPACK_NUMERIC_SIZE]: the actual final size (in Units) of the
entire Numeric object, including the final size of the variable
part of the object. Info [UMFPACK_NUMERIC_SIZE_ESTIMATE],
an estimate, was computed by umfpack_*_*symbolic. The estimate is
normally an upper bound on the actual final size, but this is not
guaranteed.
Info [UMFPACK_PEAK_MEMORY]: the actual peak memory usage (in Units) of
both umfpack_*_*symbolic and umfpack_*_numeric. An estimate,
Info [UMFPACK_PEAK_MEMORY_ESTIMATE], was computed by
umfpack_*_*symbolic. The estimate is normally an upper bound on the
actual peak usage, but this is not guaranteed. With testing on
hundreds of matrix arising in real applications, I have never
observed a matrix where this estimate or the Numeric size estimate
was less than the actual result, but this is theoretically possible.
Please send me one if you find such a matrix.
Info [UMFPACK_FLOPS]: the actual count of the (useful) floating-point
operations performed. An estimate, Info [UMFPACK_FLOPS_ESTIMATE],
was computed by umfpack_*_*symbolic. The estimate is guaranteed to
be an upper bound on this flop count. The flop count excludes
"useless" flops on zero values, flops performed during the pivot
search (for tentative updates and assembly of candidate columns),
and flops performed to add frontal matrices together.
For the real version, only (+ - * /) are counted. For the complex
version, the following counts are used:
operation flops
c = 1/b 6
c = a*b 6
c -= a*b 8
Info [UMFPACK_LNZ]: the actual nonzero entries in final factor L,
including the diagonal. This excludes any zero entries in L,
although some of these are stored in the Numeric object. The
Info [UMFPACK_LU_ENTRIES] statistic does account for all
explicitly stored zeros, however. Info [UMFPACK_LNZ_ESTIMATE],
an estimate, was computed by umfpack_*_*symbolic. The estimate is
guaranteed to be an upper bound on Info [UMFPACK_LNZ].
Info [UMFPACK_UNZ]: the actual nonzero entries in final factor U,
including the diagonal. This excludes any zero entries in U,
although some of these are stored in the Numeric object. The
Info [UMFPACK_LU_ENTRIES] statistic does account for all
explicitly stored zeros, however. Info [UMFPACK_UNZ_ESTIMATE],
an estimate, was computed by umfpack_*_*symbolic. The estimate is
guaranteed to be an upper bound on Info [UMFPACK_UNZ].
Info [UMFPACK_NUMERIC_DEFRAG]: The number of garbage collections
performed during umfpack_*_numeric, to compact the contents of the
variable-sized workspace used by umfpack_*_numeric. No estimate was
computed by umfpack_*_*symbolic. In the current version of UMFPACK,
garbage collection is performed and then the memory is reallocated,
so this statistic is the same as Info [UMFPACK_NUMERIC_REALLOC],
below. It may differ in future releases.
Info [UMFPACK_NUMERIC_REALLOC]: The number of times that the Numeric
object was increased in size from its initial size. A rough upper
bound on the peak size of the Numeric object was computed by
umfpack_*_*symbolic, so reallocations should be rare. However, if
umfpack_*_numeric is unable to allocate that much storage, it
reduces its request until either the allocation succeeds, or until
it gets too small to do anything with. If the memory that it
finally got was small, but usable, then the reallocation count
could be high. No estimate of this count was computed by
umfpack_*_*symbolic.
Info [UMFPACK_NUMERIC_COSTLY_REALLOC]: The number of times that the
system realloc library routine (or mxRealloc for the mexFunction)
had to move the workspace. Realloc can sometimes increase the size
of a block of memory without moving it, which is much faster. This
statistic will always be <= Info [UMFPACK_NUMERIC_REALLOC]. If your
memory space is fragmented, then the number of "costly" realloc's
will be equal to Info [UMFPACK_NUMERIC_REALLOC].
Info [UMFPACK_COMPRESSED_PATTERN]: The number of integers used to
represent the pattern of L and U.
Info [UMFPACK_LU_ENTRIES]: The total number of numerical values that
are stored for the LU factors. Some of the values may be explicitly
zero in order to save space (allowing for a smaller compressed
pattern).
Info [UMFPACK_NUMERIC_TIME]: The CPU time taken, in seconds.
Info [UMFPACK_RCOND]: A rough estimate of the condition number, equal
to min (abs (diag (U))) / max (abs (diag (U))), or zero if the
diagonal of U is all zero.
Info [UMFPACK_UDIAG_NZ]: The number of numerically nonzero values on
the diagonal of U.
Info [UMFPACK_UMIN]: the smallest absolute value on the diagonal of U.
Info [UMFPACK_UMAX]: the smallest absolute value on the diagonal of U.
Info [UMFPACK_MAX_FRONT_SIZE]: the size of the
largest frontal matrix (number of entries).
Info [UMFPACK_NUMERIC_WALLTIME]: The wallclock time taken, in seconds.
Info [UMFPACK_MAX_FRONT_NROWS]: the max number of
rows in any frontal matrix.
Info [UMFPACK_MAX_FRONT_NCOLS]: the max number of
columns in any frontal matrix.
Info [UMFPACK_WAS_SCALED]: the scaling used, either UMFPACK_SCALE_NONE,
UMFPACK_SCALE_SUM, or UMFPACK_SCALE_MAX.
Info [UMFPACK_RSMIN]: if scaling is performed, the smallest scale factor
for any row (either the smallest sum of absolute entries, or the
smallest maximum of absolute entries).
Info [UMFPACK_RSMAX]: if scaling is performed, the largest scale factor
for any row (either the largest sum of absolute entries, or the
largest maximum of absolute entries).
Info [UMFPACK_ALLOC_INIT_USED]: the initial allocation parameter used.
Info [UMFPACK_FORCED_UPDATES]: the number of BLAS-3 updates to the
frontal matrices that were required because the frontal matrix
grew larger than its current working array.
Info [UMFPACK_NOFF_DIAG]: number of off-diagonal pivots selected, if the
symmetric strategy is used.
Info [UMFPACK_NZDROPPED]: the number of entries smaller in absolute
value than Control [UMFPACK_DROPTOL] that were dropped from L and U.
Note that entries on the diagonal of U are never dropped.
Info [UMFPACK_ALL_LNZ]: the number of entries in L, including the
diagonal, if no small entries are dropped.
Info [UMFPACK_ALL_UNZ]: the number of entries in U, including the
diagonal, if no small entries are dropped.
Only the above listed Info [...] entries are accessed. The remaining
entries of Info are not accessed or modified by umfpack_*_numeric.
Future versions might modify different parts of Info.
*/

View File

@ -0,0 +1,234 @@
/* ========================================================================== */
/* === umfpack_qsymbolic ==================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_qsymbolic
(
int n_row,
int n_col,
const int Ap [ ],
const int Ai [ ],
const double Ax [ ],
const int Qinit [ ],
void **Symbolic,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
UF_long umfpack_dl_qsymbolic
(
UF_long n_row,
UF_long n_col,
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ],
const UF_long Qinit [ ],
void **Symbolic,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
int umfpack_zi_qsymbolic
(
int n_row,
int n_col,
const int Ap [ ],
const int Ai [ ],
const double Ax [ ], const double Az [ ],
const int Qinit [ ],
void **Symbolic,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
UF_long umfpack_zl_qsymbolic
(
UF_long n_row,
UF_long n_col,
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ], const double Az [ ],
const UF_long Qinit [ ],
void **Symbolic,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
int umfpack_di_fsymbolic
(
int n_row,
int n_col,
const int Ap [ ],
const int Ai [ ],
const double Ax [ ],
/* user-provided ordering function */
int (*user_ordering) /* TRUE if OK, FALSE otherwise */
(
/* inputs, not modified on output */
int, /* nrow */
int, /* ncol */
int, /* sym: if TRUE and nrow==ncol do A+A', else do A'A */
int *, /* Ap, size ncol+1 */
int *, /* Ai, size nz */
/* output */
int *, /* size ncol, fill-reducing permutation */
/* input/output */
void *, /* user_params (ignored by UMFPACK) */
double * /* user_info[0..2], optional output for symmetric case.
user_info[0]: max column count for L=chol(A+A')
user_info[1]: nnz (L)
user_info[2]: flop count for chol(A+A'), if A real */
),
void *user_params, /* passed to user_ordering function */
void **Symbolic,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
UF_long umfpack_dl_fsymbolic
(
UF_long n_row,
UF_long n_col,
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ],
int (*user_ordering) (UF_long, UF_long, UF_long,
UF_long *, UF_long *, UF_long *, void *, double *),
void *user_params,
void **Symbolic,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
int umfpack_zi_fsymbolic
(
int n_row,
int n_col,
const int Ap [ ],
const int Ai [ ],
const double Ax [ ], const double Az [ ],
int (*user_ordering) (int, int, int, int *, int *, int *, void *, double *),
void *user_params,
void **Symbolic,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
UF_long umfpack_zl_fsymbolic
(
UF_long n_row,
UF_long n_col,
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ], const double Az [ ],
int (*user_ordering) (UF_long, UF_long, UF_long,
UF_long *, UF_long *, UF_long *, void *, double *),
void *user_params,
void **Symbolic,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
/*
double int Syntax:
#include "umfpack.h"
void *Symbolic ;
int n_row, n_col, *Ap, *Ai, *Qinit, status ;
double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax ;
status = umfpack_di_qsymbolic (n_row, n_col, Ap, Ai, Ax, Qinit,
&Symbolic, Control, Info) ;
double UF_long Syntax:
#include "umfpack.h"
void *Symbolic ;
UF_long n_row, n_col, *Ap, *Ai, *Qinit, status ;
double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax ;
status = umfpack_dl_qsymbolic (n_row, n_col, Ap, Ai, Ax, Qinit,
&Symbolic, Control, Info) ;
complex int Syntax:
#include "umfpack.h"
void *Symbolic ;
int n_row, n_col, *Ap, *Ai, *Qinit, status ;
double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax, *Az ;
status = umfpack_zi_qsymbolic (n_row, n_col, Ap, Ai, Ax, Az, Qinit,
&Symbolic, Control, Info) ;
complex UF_long Syntax:
#include "umfpack.h"
void *Symbolic ;
UF_long n_row, n_col, *Ap, *Ai, *Qinit, status ;
double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax, *Az ;
status = umfpack_zl_qsymbolic (n_row, n_col, Ap, Ai, Ax, Az, Qinit,
&Symbolic, Control, Info) ;
packed complex Syntax:
Same as above, except Az is NULL.
Purpose:
Given the nonzero pattern of a sparse matrix A in column-oriented form, and
a sparsity preserving column pre-ordering Qinit, umfpack_*_qsymbolic
performs the symbolic factorization of A*Qinit (or A (:,Qinit) in MATLAB
notation). This is identical to umfpack_*_symbolic, except that neither
COLAMD nor AMD are called and the user input column order Qinit is used
instead. Note that in general, the Qinit passed to umfpack_*_qsymbolic
can differ from the final Q found in umfpack_*_numeric. The unsymmetric
strategy will perform a column etree postordering done in
umfpack_*_qsymbolic and sparsity-preserving modifications are made within
each frontal matrix during umfpack_*_numeric. The symmetric
strategy will preserve Qinit, unless the matrix is structurally singular.
See umfpack_*_symbolic for more information. Note that Ax and Ax are
optional. The may be NULL.
*** WARNING *** A poor choice of Qinit can easily cause umfpack_*_numeric
to use a huge amount of memory and do a lot of work. The "default" symbolic
analysis method is umfpack_*_symbolic, not this routine. If you use this
routine, the performance of UMFPACK is your responsibility; UMFPACK will
not try to second-guess a poor choice of Qinit.
Returns:
The value of Info [UMFPACK_STATUS]; see umfpack_*_symbolic.
Also returns UMFPACK_ERROR_invalid_permuation if Qinit is not a valid
permutation vector.
Arguments:
All arguments are the same as umfpack_*_symbolic, except for the following:
Int Qinit [n_col] ; Input argument, not modified.
The user's fill-reducing initial column pre-ordering. This must be a
permutation of 0..n_col-1. If Qinit [k] = j, then column j is the kth
column of the matrix A (:,Qinit) to be factorized. If Qinit is an
(Int *) NULL pointer, then COLAMD or AMD are called instead.
double Control [UMFPACK_CONTROL] ; Input argument, not modified.
If Qinit is not NULL, then only two strategies are recognized:
the unsymmetric strategy and the symmetric strategy.
If Control [UMFPACK_STRATEGY] is UMFPACK_STRATEGY_SYMMETRIC,
then the symmetric strategy is used. Otherwise the unsymmetric
strategy is used.
*/

View File

@ -0,0 +1,76 @@
/* ========================================================================== */
/* === umfpack_report_control =============================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
void umfpack_di_report_control
(
const double Control [UMFPACK_CONTROL]
) ;
void umfpack_dl_report_control
(
const double Control [UMFPACK_CONTROL]
) ;
void umfpack_zi_report_control
(
const double Control [UMFPACK_CONTROL]
) ;
void umfpack_zl_report_control
(
const double Control [UMFPACK_CONTROL]
) ;
/*
double int Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL] ;
umfpack_di_report_control (Control) ;
double UF_long Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL] ;
umfpack_dl_report_control (Control) ;
complex int Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL] ;
umfpack_zi_report_control (Control) ;
double UF_long Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL] ;
umfpack_zl_report_control (Control) ;
Purpose:
Prints the current control settings. Note that with the default print
level, nothing is printed. Does nothing if Control is (double *) NULL.
Arguments:
double Control [UMFPACK_CONTROL] ; Input argument, not modified.
If a (double *) NULL pointer is passed, then the default control
settings are used. Otherwise, the settings are determined from the
Control array. See umfpack_*_defaults on how to fill the Control
array with the default settings. If Control contains NaN's, the
defaults are used. The following Control parameters are used:
Control [UMFPACK_PRL]: printing level.
1 or less: no output
2 or more: print all of Control
Default: 1
*/

View File

@ -0,0 +1,86 @@
/* ========================================================================== */
/* === umfpack_report_info ================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
void umfpack_di_report_info
(
const double Control [UMFPACK_CONTROL],
const double Info [UMFPACK_INFO]
) ;
void umfpack_dl_report_info
(
const double Control [UMFPACK_CONTROL],
const double Info [UMFPACK_INFO]
) ;
void umfpack_zi_report_info
(
const double Control [UMFPACK_CONTROL],
const double Info [UMFPACK_INFO]
) ;
void umfpack_zl_report_info
(
const double Control [UMFPACK_CONTROL],
const double Info [UMFPACK_INFO]
) ;
/*
double int Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ;
umfpack_di_report_info (Control, Info) ;
double UF_long Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ;
umfpack_dl_report_info (Control, Info) ;
complex int Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ;
umfpack_zi_report_info (Control, Info) ;
complex UF_long Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO] ;
umfpack_zl_report_info (Control, Info) ;
Purpose:
Reports statistics from the umfpack_*_*symbolic, umfpack_*_numeric, and
umfpack_*_*solve routines.
Arguments:
double Control [UMFPACK_CONTROL] ; Input argument, not modified.
If a (double *) NULL pointer is passed, then the default control
settings are used. Otherwise, the settings are determined from the
Control array. See umfpack_*_defaults on how to fill the Control
array with the default settings. If Control contains NaN's, the
defaults are used. The following Control parameters are used:
Control [UMFPACK_PRL]: printing level.
0 or less: no output, even when an error occurs
1: error messages only
2 or more: error messages, and print all of Info
Default: 1
double Info [UMFPACK_INFO] ; Input argument, not modified.
Info is an output argument of several UMFPACK routines.
The contents of Info are printed on standard output.
*/

View File

@ -0,0 +1,203 @@
/* ========================================================================== */
/* === umfpack_report_matrix ================================================ */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_report_matrix
(
int n_row,
int n_col,
const int Ap [ ],
const int Ai [ ],
const double Ax [ ],
int col_form,
const double Control [UMFPACK_CONTROL]
) ;
UF_long umfpack_dl_report_matrix
(
UF_long n_row,
UF_long n_col,
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ],
UF_long col_form,
const double Control [UMFPACK_CONTROL]
) ;
int umfpack_zi_report_matrix
(
int n_row,
int n_col,
const int Ap [ ],
const int Ai [ ],
const double Ax [ ], const double Az [ ],
int col_form,
const double Control [UMFPACK_CONTROL]
) ;
UF_long umfpack_zl_report_matrix
(
UF_long n_row,
UF_long n_col,
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ], const double Az [ ],
UF_long col_form,
const double Control [UMFPACK_CONTROL]
) ;
/*
double int Syntax:
#include "umfpack.h"
int n_row, n_col, *Ap, *Ai, status ;
double *Ax, Control [UMFPACK_CONTROL] ;
status = umfpack_di_report_matrix (n_row, n_col, Ap, Ai, Ax, 1, Control) ;
or:
status = umfpack_di_report_matrix (n_row, n_col, Ap, Ai, Ax, 0, Control) ;
double UF_long Syntax:
#include "umfpack.h"
UF_long n_row, n_col, *Ap, *Ai, status ;
double *Ax, Control [UMFPACK_CONTROL] ;
status = umfpack_dl_report_matrix (n_row, n_col, Ap, Ai, Ax, 1, Control) ;
or:
status = umfpack_dl_report_matrix (n_row, n_col, Ap, Ai, Ax, 0, Control) ;
complex int Syntax:
#include "umfpack.h"
int n_row, n_col, *Ap, *Ai, status ;
double *Ax, *Az, Control [UMFPACK_CONTROL] ;
status = umfpack_zi_report_matrix (n_row, n_col, Ap, Ai, Ax, Az, 1,
Control) ;
or:
status = umfpack_zi_report_matrix (n_row, n_col, Ap, Ai, Ax, Az, 0,
Control) ;
complex UF_long Syntax:
#include "umfpack.h"
UF_long n_row, n_col, *Ap, *Ai, status ;
double *Ax, Control [UMFPACK_CONTROL] ;
status = umfpack_zl_report_matrix (n_row, n_col, Ap, Ai, Ax, Az, 1,
Control) ;
or:
status = umfpack_zl_report_matrix (n_row, n_col, Ap, Ai, Ax, Az, 0,
Control) ;
packed complex Syntax:
Same as above, except Az is NULL.
Purpose:
Verifies and prints a row or column-oriented sparse matrix.
Returns:
UMFPACK_OK if Control [UMFPACK_PRL] <= 2 (the input is not checked).
Otherwise (where n is n_col for the column form and n_row for row
and let ni be n_row for the column form and n_col for row):
UMFPACK_OK if the matrix is valid.
UMFPACK_ERROR_n_nonpositive if n_row <= 0 or n_col <= 0.
UMFPACK_ERROR_argument_missing if Ap and/or Ai are missing.
UMFPACK_ERROR_invalid_matrix if Ap [n] < 0, if Ap [0] is not zero,
if Ap [j+1] < Ap [j] for any j in the range 0 to n-1,
if any row index in Ai is not in the range 0 to ni-1, or
if the row indices in any column are not in
ascending order, or contain duplicates.
UMFPACK_ERROR_out_of_memory if out of memory.
Arguments:
Int n_row ; Input argument, not modified.
Int n_col ; Input argument, not modified.
A is an n_row-by-n_row matrix. Restriction: n_row > 0 and n_col > 0.
Int Ap [n+1] ; Input argument, not modified.
n is n_row for a row-form matrix, and n_col for a column-form matrix.
Ap is an integer array of size n+1. If col_form is true (nonzero),
then on input, it holds the "pointers" for the column form of the
sparse matrix A. The row indices of column j of the matrix A are held
in Ai [(Ap [j]) ... (Ap [j+1]-1)]. Otherwise, Ap holds the
row pointers, and the column indices of row j of the matrix are held
in Ai [(Ap [j]) ... (Ap [j+1]-1)].
The first entry, Ap [0], must be zero, and Ap [j] <= Ap [j+1] must hold
for all j in the range 0 to n-1. The value nz = Ap [n] is thus the
total number of entries in the pattern of the matrix A.
Int Ai [nz] ; Input argument, not modified, of size nz = Ap [n].
If col_form is true (nonzero), then the nonzero pattern (row indices)
for column j is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)]. Row indices
must be in the range 0 to n_row-1 (the matrix is 0-based).
Otherwise, the nonzero pattern (column indices) for row j is stored in
Ai [(Ap [j]) ... (Ap [j+1]-1)]. Column indices must be in the range 0
to n_col-1 (the matrix is 0-based).
double Ax [nz] ; Input argument, not modified, of size nz = Ap [n].
Size 2*nz for packed complex case.
The numerical values of the sparse matrix A.
If col_form is true (nonzero), then the nonzero pattern (row indices)
for column j is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)], and the
corresponding (real) numerical values are stored in
Ax [(Ap [j]) ... (Ap [j+1]-1)]. The imaginary parts are stored in
Az [(Ap [j]) ... (Ap [j+1]-1)], for the complex versions
(see below if Az is NULL).
Otherwise, the nonzero pattern (column indices) for row j
is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)], and the corresponding
(real) numerical values are stored in Ax [(Ap [j]) ... (Ap [j+1]-1)].
The imaginary parts are stored in Az [(Ap [j]) ... (Ap [j+1]-1)],
for the complex versions (see below if Az is NULL).
No numerical values are printed if Ax is NULL.
double Az [nz] ; Input argument, not modified, for complex versions.
The imaginary values of the sparse matrix A. See the description
of Ax, above.
If Az is NULL, then both real
and imaginary parts are contained in Ax[0..2*nz-1], with Ax[2*k]
and Ax[2*k+1] being the real and imaginary part of the kth entry.
Int col_form ; Input argument, not modified.
The matrix is in row-oriented form if form is col_form is false (0).
Otherwise, the matrix is in column-oriented form.
double Control [UMFPACK_CONTROL] ; Input argument, not modified.
If a (double *) NULL pointer is passed, then the default control
settings are used. Otherwise, the settings are determined from the
Control array. See umfpack_*_defaults on how to fill the Control
array with the default settings. If Control contains NaN's, the
defaults are used. The following Control parameters are used:
Control [UMFPACK_PRL]: printing level.
2 or less: no output. returns silently without checking anything.
3: fully check input, and print a short summary of its status
4: as 3, but print first few entries of the input
5: as 3, but print all of the input
Default: 1
*/

View File

@ -0,0 +1,112 @@
/* ========================================================================== */
/* === umfpack_report_numeric =============================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_report_numeric
(
void *Numeric,
const double Control [UMFPACK_CONTROL]
) ;
UF_long umfpack_dl_report_numeric
(
void *Numeric,
const double Control [UMFPACK_CONTROL]
) ;
int umfpack_zi_report_numeric
(
void *Numeric,
const double Control [UMFPACK_CONTROL]
) ;
UF_long umfpack_zl_report_numeric
(
void *Numeric,
const double Control [UMFPACK_CONTROL]
) ;
/*
double int Syntax:
#include "umfpack.h"
void *Numeric ;
double Control [UMFPACK_CONTROL] ;
int status ;
status = umfpack_di_report_numeric (Numeric, Control) ;
double UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
double Control [UMFPACK_CONTROL] ;
UF_long status ;
status = umfpack_dl_report_numeric (Numeric, Control) ;
complex int Syntax:
#include "umfpack.h"
void *Numeric ;
double Control [UMFPACK_CONTROL] ;
int status ;
status = umfpack_zi_report_numeric (Numeric, Control) ;
complex UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
double Control [UMFPACK_CONTROL] ;
UF_long status ;
status = umfpack_zl_report_numeric (Numeric, Control) ;
Purpose:
Verifies and prints a Numeric object (the LU factorization, both its pattern
numerical values, and permutation vectors P and Q). This routine checks the
object more carefully than the computational routines. Normally, this check
is not required, since umfpack_*_numeric either returns (void *) NULL, or a
valid Numeric object. However, if you suspect that your own code has
corrupted the Numeric object (by overruning memory bounds, for example),
then this routine might be able to detect a corrupted Numeric object. Since
this is a complex object, not all such user-generated errors are guaranteed
to be caught by this routine.
Returns:
UMFPACK_OK if Control [UMFPACK_PRL] <= 2 (the input is not checked).
Otherwise:
UMFPACK_OK if the Numeric object is valid.
UMFPACK_ERROR_invalid_Numeric_object if the Numeric object is invalid.
UMFPACK_ERROR_out_of_memory if out of memory.
Arguments:
void *Numeric ; Input argument, not modified.
The Numeric object, which holds the numeric factorization computed by
umfpack_*_numeric.
double Control [UMFPACK_CONTROL] ; Input argument, not modified.
If a (double *) NULL pointer is passed, then the default control
settings are used. Otherwise, the settings are determined from the
Control array. See umfpack_*_defaults on how to fill the Control
array with the default settings. If Control contains NaN's, the
defaults are used. The following Control parameters are used:
Control [UMFPACK_PRL]: printing level.
2 or less: no output. returns silently without checking anything.
3: fully check input, and print a short summary of its status
4: as 3, but print first few entries of the input
5: as 3, but print all of the input
Default: 1
*/

View File

@ -0,0 +1,112 @@
/* ========================================================================== */
/* === umfpack_report_perm ================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_report_perm
(
int np,
const int Perm [ ],
const double Control [UMFPACK_CONTROL]
) ;
UF_long umfpack_dl_report_perm
(
UF_long np,
const UF_long Perm [ ],
const double Control [UMFPACK_CONTROL]
) ;
int umfpack_zi_report_perm
(
int np,
const int Perm [ ],
const double Control [UMFPACK_CONTROL]
) ;
UF_long umfpack_zl_report_perm
(
UF_long np,
const UF_long Perm [ ],
const double Control [UMFPACK_CONTROL]
) ;
/*
double int Syntax:
#include "umfpack.h"
int np, *Perm, status ;
double Control [UMFPACK_CONTROL] ;
status = umfpack_di_report_perm (np, Perm, Control) ;
double UF_long Syntax:
#include "umfpack.h"
UF_long np, *Perm, status ;
double Control [UMFPACK_CONTROL] ;
status = umfpack_dl_report_perm (np, Perm, Control) ;
complex int Syntax:
#include "umfpack.h"
int np, *Perm, status ;
double Control [UMFPACK_CONTROL] ;
status = umfpack_zi_report_perm (np, Perm, Control) ;
complex UF_long Syntax:
#include "umfpack.h"
UF_long np, *Perm, status ;
double Control [UMFPACK_CONTROL] ;
status = umfpack_zl_report_perm (np, Perm, Control) ;
Purpose:
Verifies and prints a permutation vector.
Returns:
UMFPACK_OK if Control [UMFPACK_PRL] <= 2 (the input is not checked).
Otherwise:
UMFPACK_OK if the permutation vector is valid (this includes that case
when Perm is (Int *) NULL, which is not an error condition).
UMFPACK_ERROR_n_nonpositive if np <= 0.
UMFPACK_ERROR_out_of_memory if out of memory.
UMFPACK_ERROR_invalid_permutation if Perm is not a valid permutation vector.
Arguments:
Int np ; Input argument, not modified.
Perm is an integer vector of size np. Restriction: np > 0.
Int Perm [np] ; Input argument, not modified.
A permutation vector of size np. If Perm is not present (an (Int *)
NULL pointer), then it is assumed to be the identity permutation. This
is consistent with its use as an input argument to umfpack_*_qsymbolic,
and is not an error condition. If Perm is present, the entries in Perm
must range between 0 and np-1, and no duplicates may exist.
double Control [UMFPACK_CONTROL] ; Input argument, not modified.
If a (double *) NULL pointer is passed, then the default control
settings are used. Otherwise, the settings are determined from the
Control array. See umfpack_*_defaults on how to fill the Control
array with the default settings. If Control contains NaN's, the
defaults are used. The following Control parameters are used:
Control [UMFPACK_PRL]: printing level.
2 or less: no output. returns silently without checking anything.
3: fully check input, and print a short summary of its status
4: as 3, but print first few entries of the input
5: as 3, but print all of the input
Default: 1
*/

View File

@ -0,0 +1,90 @@
/* ========================================================================== */
/* === umfpack_report_status ================================================ */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
void umfpack_di_report_status
(
const double Control [UMFPACK_CONTROL],
int status
) ;
void umfpack_dl_report_status
(
const double Control [UMFPACK_CONTROL],
UF_long status
) ;
void umfpack_zi_report_status
(
const double Control [UMFPACK_CONTROL],
int status
) ;
void umfpack_zl_report_status
(
const double Control [UMFPACK_CONTROL],
UF_long status
) ;
/*
double int Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL] ;
int status ;
umfpack_di_report_status (Control, status) ;
double UF_long Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL] ;
UF_long status ;
umfpack_dl_report_status (Control, status) ;
complex int Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL] ;
int status ;
umfpack_zi_report_status (Control, status) ;
complex UF_long Syntax:
#include "umfpack.h"
double Control [UMFPACK_CONTROL] ;
UF_long status ;
umfpack_zl_report_status (Control, status) ;
Purpose:
Prints the status (return value) of other umfpack_* routines.
Arguments:
double Control [UMFPACK_CONTROL] ; Input argument, not modified.
If a (double *) NULL pointer is passed, then the default control
settings are used. Otherwise, the settings are determined from the
Control array. See umfpack_*_defaults on how to fill the Control
array with the default settings. If Control contains NaN's, the
defaults are used. The following Control parameters are used:
Control [UMFPACK_PRL]: printing level.
0 or less: no output, even when an error occurs
1: error messages only
2 or more: print status, whether or not an error occurred
4 or more: also print the UMFPACK Copyright
6 or more: also print the UMFPACK License
Default: 1
Int status ; Input argument, not modified.
The return value from another umfpack_* routine.
*/

View File

@ -0,0 +1,111 @@
/* ========================================================================== */
/* === umfpack_report_symbolic ============================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_report_symbolic
(
void *Symbolic,
const double Control [UMFPACK_CONTROL]
) ;
UF_long umfpack_dl_report_symbolic
(
void *Symbolic,
const double Control [UMFPACK_CONTROL]
) ;
int umfpack_zi_report_symbolic
(
void *Symbolic,
const double Control [UMFPACK_CONTROL]
) ;
UF_long umfpack_zl_report_symbolic
(
void *Symbolic,
const double Control [UMFPACK_CONTROL]
) ;
/*
double int Syntax:
#include "umfpack.h"
void *Symbolic ;
double Control [UMFPACK_CONTROL] ;
int status ;
status = umfpack_di_report_symbolic (Symbolic, Control) ;
double UF_long Syntax:
#include "umfpack.h"
void *Symbolic ;
double Control [UMFPACK_CONTROL] ;
UF_long status ;
status = umfpack_dl_report_symbolic (Symbolic, Control) ;
complex int Syntax:
#include "umfpack.h"
void *Symbolic ;
double Control [UMFPACK_CONTROL] ;
int status ;
status = umfpack_zi_report_symbolic (Symbolic, Control) ;
complex UF_long Syntax:
#include "umfpack.h"
void *Symbolic ;
double Control [UMFPACK_CONTROL] ;
UF_long status ;
status = umfpack_zl_report_symbolic (Symbolic, Control) ;
Purpose:
Verifies and prints a Symbolic object. This routine checks the object more
carefully than the computational routines. Normally, this check is not
required, since umfpack_*_*symbolic either returns (void *) NULL, or a valid
Symbolic object. However, if you suspect that your own code has corrupted
the Symbolic object (by overruning memory bounds, for example), then this
routine might be able to detect a corrupted Symbolic object. Since this is
a complex object, not all such user-generated errors are guaranteed to be
caught by this routine.
Returns:
UMFPACK_OK if Control [UMFPACK_PRL] is <= 2 (no inputs are checked).
Otherwise:
UMFPACK_OK if the Symbolic object is valid.
UMFPACK_ERROR_invalid_Symbolic_object if the Symbolic object is invalid.
UMFPACK_ERROR_out_of_memory if out of memory.
Arguments:
void *Symbolic ; Input argument, not modified.
The Symbolic object, which holds the symbolic factorization computed by
umfpack_*_*symbolic.
double Control [UMFPACK_CONTROL] ; Input argument, not modified.
If a (double *) NULL pointer is passed, then the default control
settings are used. Otherwise, the settings are determined from the
Control array. See umfpack_*_defaults on how to fill the Control
array with the default settings. If Control contains NaN's, the
defaults are used. The following Control parameters are used:
Control [UMFPACK_PRL]: printing level.
2 or less: no output. returns silently without checking anything.
3: fully check input, and print a short summary of its status
4: as 3, but print first few entries of the input
5: as 3, but print all of the input
Default: 1
*/

View File

@ -0,0 +1,153 @@
/* ========================================================================== */
/* === umfpack_report_triplet =============================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_report_triplet
(
int n_row,
int n_col,
int nz,
const int Ti [ ],
const int Tj [ ],
const double Tx [ ],
const double Control [UMFPACK_CONTROL]
) ;
UF_long umfpack_dl_report_triplet
(
UF_long n_row,
UF_long n_col,
UF_long nz,
const UF_long Ti [ ],
const UF_long Tj [ ],
const double Tx [ ],
const double Control [UMFPACK_CONTROL]
) ;
int umfpack_zi_report_triplet
(
int n_row,
int n_col,
int nz,
const int Ti [ ],
const int Tj [ ],
const double Tx [ ], const double Tz [ ],
const double Control [UMFPACK_CONTROL]
) ;
UF_long umfpack_zl_report_triplet
(
UF_long n_row,
UF_long n_col,
UF_long nz,
const UF_long Ti [ ],
const UF_long Tj [ ],
const double Tx [ ], const double Tz [ ],
const double Control [UMFPACK_CONTROL]
) ;
/*
double int Syntax:
#include "umfpack.h"
int n_row, n_col, nz, *Ti, *Tj, status ;
double *Tx, Control [UMFPACK_CONTROL] ;
status = umfpack_di_report_triplet (n_row, n_col, nz, Ti, Tj, Tx, Control) ;
double UF_long Syntax:
#include "umfpack.h"
UF_long n_row, n_col, nz, *Ti, *Tj, status ;
double *Tx, Control [UMFPACK_CONTROL] ;
status = umfpack_dl_report_triplet (n_row, n_col, nz, Ti, Tj, Tx, Control) ;
complex int Syntax:
#include "umfpack.h"
int n_row, n_col, nz, *Ti, *Tj, status ;
double *Tx, *Tz, Control [UMFPACK_CONTROL] ;
status = umfpack_zi_report_triplet (n_row, n_col, nz, Ti, Tj, Tx, Tz,
Control) ;
complex UF_long Syntax:
#include "umfpack.h"
UF_long n_row, n_col, nz, *Ti, *Tj, status ;
double *Tx, *Tz, Control [UMFPACK_CONTROL] ;
status = umfpack_zl_report_triplet (n_row, n_col, nz, Ti, Tj, Tx, Tz,
Control) ;
packed complex Syntax:
Same as above, except Tz is NULL.
Purpose:
Verifies and prints a matrix in triplet form.
Returns:
UMFPACK_OK if Control [UMFPACK_PRL] <= 2 (the input is not checked).
Otherwise:
UMFPACK_OK if the Triplet matrix is OK.
UMFPACK_ERROR_argument_missing if Ti and/or Tj are missing.
UMFPACK_ERROR_n_nonpositive if n_row <= 0 or n_col <= 0.
UMFPACK_ERROR_invalid_matrix if nz < 0, or
if any row or column index in Ti and/or Tj
is not in the range 0 to n_row-1 or 0 to n_col-1, respectively.
Arguments:
Int n_row ; Input argument, not modified.
Int n_col ; Input argument, not modified.
A is an n_row-by-n_col matrix.
Int nz ; Input argument, not modified.
The number of entries in the triplet form of the matrix.
Int Ti [nz] ; Input argument, not modified.
Int Tj [nz] ; Input argument, not modified.
double Tx [nz] ; Input argument, not modified.
Size 2*nz for packed complex case.
double Tz [nz] ; Input argument, not modified, for complex versions.
Ti, Tj, Tx (and Tz for complex versions) hold the "triplet" form of a
sparse matrix. The kth nonzero entry is in row i = Ti [k], column
j = Tj [k], the real numerical value of a_ij is Tx [k], and the
imaginary part of a_ij is Tz [k] (for complex versions). The row and
column indices i and j must be in the range 0 to n_row-1 or 0 to
n_col-1, respectively. Duplicate entries may be present. The
"triplets" may be in any order. Tx and Tz are optional; if Tx is
not present ((double *) NULL), then the numerical values are
not printed.
If Tx is present and Tz is NULL, then both real
and imaginary parts are contained in Tx[0..2*nz-1], with Tx[2*k]
and Tx[2*k+1] being the real and imaginary part of the kth entry.
double Control [UMFPACK_CONTROL] ; Input argument, not modified.
If a (double *) NULL pointer is passed, then the default control
settings are used. Otherwise, the settings are determined from the
Control array. See umfpack_*_defaults on how to fill the Control
array with the default settings. If Control contains NaN's, the
defaults are used. The following Control parameters are used:
Control [UMFPACK_PRL]: printing level.
2 or less: no output. returns silently without checking anything.
3: fully check input, and print a short summary of its status
4: as 3, but print first few entries of the input
5: as 3, but print all of the input
Default: 1
*/

View File

@ -0,0 +1,133 @@
/* ========================================================================== */
/* === umfpack_report_vector ================================================ */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_report_vector
(
int n,
const double X [ ],
const double Control [UMFPACK_CONTROL]
) ;
UF_long umfpack_dl_report_vector
(
UF_long n,
const double X [ ],
const double Control [UMFPACK_CONTROL]
) ;
int umfpack_zi_report_vector
(
int n,
const double Xx [ ], const double Xz [ ],
const double Control [UMFPACK_CONTROL]
) ;
UF_long umfpack_zl_report_vector
(
UF_long n,
const double Xx [ ], const double Xz [ ],
const double Control [UMFPACK_CONTROL]
) ;
/*
double int Syntax:
#include "umfpack.h"
int n, status ;
double *X, Control [UMFPACK_CONTROL] ;
status = umfpack_di_report_vector (n, X, Control) ;
double UF_long Syntax:
#include "umfpack.h"
UF_long n, status ;
double *X, Control [UMFPACK_CONTROL] ;
status = umfpack_dl_report_vector (n, X, Control) ;
complex int Syntax:
#include "umfpack.h"
int n, status ;
double *Xx, *Xz, Control [UMFPACK_CONTROL] ;
status = umfpack_zi_report_vector (n, Xx, Xz, Control) ;
complex UF_long Syntax:
#include "umfpack.h"
UF_long n, status ;
double *Xx, *Xz, Control [UMFPACK_CONTROL] ;
status = umfpack_zl_report_vector (n, Xx, Xz, Control) ;
Purpose:
Verifies and prints a dense vector.
Returns:
UMFPACK_OK if Control [UMFPACK_PRL] <= 2 (the input is not checked).
Otherwise:
UMFPACK_OK if the vector is valid.
UMFPACK_ERROR_argument_missing if X or Xx is missing.
UMFPACK_ERROR_n_nonpositive if n <= 0.
Arguments:
Int n ; Input argument, not modified.
X is a real or complex vector of size n. Restriction: n > 0.
double X [n] ; Input argument, not modified. For real versions.
A real vector of size n. X must not be (double *) NULL.
double Xx [n or 2*n] ; Input argument, not modified. For complex versions.
double Xz [n or 0] ; Input argument, not modified. For complex versions.
A complex vector of size n, in one of two storage formats.
Xx must not be (double *) NULL.
If Xz is not (double *) NULL, then Xx [i] is the real part of X (i) and
Xz [i] is the imaginary part of X (i). Both vectors are of length n.
This is the "split" form of the complex vector X.
If Xz is (double *) NULL, then Xx holds both real and imaginary parts,
where Xx [2*i] is the real part of X (i) and Xx [2*i+1] is the imaginary
part of X (i). Xx is of length 2*n doubles. If you have an ANSI C99
compiler with the intrinsic double _Complex type, then Xx can be of
type double _Complex in the calling routine and typecast to (double *)
when passed to umfpack_*_report_vector (this is untested, however).
This is the "merged" form of the complex vector X.
Note that all complex routines in UMFPACK V4.4 and later use this same
strategy for their complex arguments. The split format is useful for
MATLAB, which holds its real and imaginary parts in seperate arrays.
The packed format is compatible with the intrinsic double _Complex
type in ANSI C99, and is also compatible with SuperLU's method of
storing complex matrices. In Version 4.3, this routine was the only
one that allowed for packed complex arguments.
double Control [UMFPACK_CONTROL] ; Input argument, not modified.
If a (double *) NULL pointer is passed, then the default control
settings are used. Otherwise, the settings are determined from the
Control array. See umfpack_*_defaults on how to fill the Control
array with the default settings. If Control contains NaN's, the
defaults are used. The following Control parameters are used:
Control [UMFPACK_PRL]: printing level.
2 or less: no output. returns silently without checking anything.
3: fully check input, and print a short summary of its status
4: as 3, but print first few entries of the input
5: as 3, but print all of the input
Default: 1
*/

View File

@ -0,0 +1,90 @@
/* ========================================================================== */
/* === umfpack_save_numeric ================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_save_numeric
(
void *Numeric,
char *filename
) ;
UF_long umfpack_dl_save_numeric
(
void *Numeric,
char *filename
) ;
int umfpack_zi_save_numeric
(
void *Numeric,
char *filename
) ;
UF_long umfpack_zl_save_numeric
(
void *Numeric,
char *filename
) ;
/*
double int Syntax:
#include "umfpack.h"
int status ;
char *filename ;
void *Numeric ;
status = umfpack_di_save_numeric (Numeric, filename) ;
double UF_long Syntax:
#include "umfpack.h"
UF_long status ;
char *filename ;
void *Numeric ;
status = umfpack_dl_save_numeric (Numeric, filename) ;
complex int Syntax:
#include "umfpack.h"
int status ;
char *filename ;
void *Numeric ;
status = umfpack_zi_save_numeric (Numeric, filename) ;
complex UF_long Syntax:
#include "umfpack.h"
UF_long status ;
char *filename ;
void *Numeric ;
status = umfpack_zl_save_numeric (Numeric, filename) ;
Purpose:
Saves a Numeric object to a file, which can later be read by
umfpack_*_load_numeric. The Numeric object is not modified.
Returns:
UMFPACK_OK if successful.
UMFPACK_ERROR_invalid_Numeric_object if Numeric is not valid.
UMFPACK_ERROR_file_IO if an I/O error occurred.
Arguments:
void *Numeric ; Input argument, not modified.
Numeric must point to a valid Numeric object, computed by
umfpack_*_numeric or loaded by umfpack_*_load_numeric.
char *filename ; Input argument, not modified.
A string that contains the filename to which the Numeric
object is written.
*/

View File

@ -0,0 +1,90 @@
/* ========================================================================== */
/* === umfpack_save_symbolic================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_save_symbolic
(
void *Symbolic,
char *filename
) ;
UF_long umfpack_dl_save_symbolic
(
void *Symbolic,
char *filename
) ;
int umfpack_zi_save_symbolic
(
void *Symbolic,
char *filename
) ;
UF_long umfpack_zl_save_symbolic
(
void *Symbolic,
char *filename
) ;
/*
double int Syntax:
#include "umfpack.h"
int status ;
char *filename ;
void *Symbolic ;
status = umfpack_di_save_symbolic (Symbolic, filename) ;
double UF_long Syntax:
#include "umfpack.h"
UF_long status ;
char *filename ;
void *Symbolic ;
status = umfpack_dl_save_symbolic (Symbolic, filename) ;
complex int Syntax:
#include "umfpack.h"
int status ;
char *filename ;
void *Symbolic ;
status = umfpack_zi_save_symbolic (Symbolic, filename) ;
complex UF_long Syntax:
#include "umfpack.h"
UF_long status ;
char *filename ;
void *Symbolic ;
status = umfpack_zl_save_symbolic (Symbolic, filename) ;
Purpose:
Saves a Symbolic object to a file, which can later be read by
umfpack_*_load_symbolic. The Symbolic object is not modified.
Returns:
UMFPACK_OK if successful.
UMFPACK_ERROR_invalid_Symbolic_object if Symbolic is not valid.
UMFPACK_ERROR_file_IO if an I/O error occurred.
Arguments:
void *Symbolic ; Input argument, not modified.
Symbolic must point to a valid Symbolic object, computed by
umfpack_*_symbolic or loaded by umfpack_*_load_symbolic.
char *filename ; Input argument, not modified.
A string that contains the filename to which the Symbolic
object is written.
*/

View File

@ -0,0 +1,112 @@
/* ========================================================================== */
/* === umfpack_scale ======================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_scale
(
double X [ ],
const double B [ ],
void *Numeric
) ;
UF_long umfpack_dl_scale
(
double X [ ],
const double B [ ],
void *Numeric
) ;
int umfpack_zi_scale
(
double Xx [ ], double Xz [ ],
const double Bx [ ], const double Bz [ ],
void *Numeric
) ;
UF_long umfpack_zl_scale
(
double Xx [ ], double Xz [ ],
const double Bx [ ], const double Bz [ ],
void *Numeric
) ;
/*
double int Syntax:
#include "umfpack.h"
void *Numeric ;
double *B, *X ;
status = umfpack_di_scale (X, B, Numeric) ;
double UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
double *B, *X ;
status = umfpack_dl_scale (X, B, Numeric) ;
complex int Syntax:
#include "umfpack.h"
void *Numeric ;
double *Bx, *Bz, *Xx, *Xz ;
status = umfpack_zi_scale (Xx, Xz, Bx, Bz, Numeric) ;
complex UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
double *Bx, *Bz, *Xx, *Xz ;
status = umfpack_zl_scale (Xx, Xz, Bx, Bz, Numeric) ;
packed complex Syntax:
Same as above, except both Xz and Bz are NULL.
Purpose:
Given LU factors computed by umfpack_*_numeric (PAQ=LU, PRAQ=LU, or
P(R\A)Q=LU), and a vector B, this routine computes X = B, X = R*B, or
X = R\B, as appropriate. X and B must be vectors equal in length to the
number of rows of A.
Returns:
The status code is returned. UMFPACK_OK is returned if successful.
UMFPACK_ERROR_invalid_Numeric_object is returned in the Numeric
object is invalid. UMFPACK_ERROR_argument_missing is returned if
any of the input vectors are missing (X and B for the real version,
and Xx and Bx for the complex version).
Arguments:
double X [n_row] ; Output argument.
or:
double Xx [n_row] ; Output argument, real part.
Size 2*n_row for packed complex case.
double Xz [n_row] ; Output argument, imaginary part.
The output vector X. If either Xz or Bz are NULL, the vector
X is in packed complex form, with the kth entry in Xx [2*k] and
Xx [2*k+1], and likewise for B.
double B [n_row] ; Input argument, not modified.
or:
double Bx [n_row] ; Input argument, not modified, real part.
Size 2*n_row for packed complex case.
double Bz [n_row] ; Input argument, not modified, imaginary part.
The input vector B. See above if either Xz or Bz are NULL.
void *Numeric ; Input argument, not modified.
Numeric must point to a valid Numeric object, computed by
umfpack_*_numeric.
*/

View File

@ -0,0 +1,301 @@
/* ========================================================================== */
/* === umfpack_solve ======================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_solve
(
int sys,
const int Ap [ ],
const int Ai [ ],
const double Ax [ ],
double X [ ],
const double B [ ],
void *Numeric,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
UF_long umfpack_dl_solve
(
UF_long sys,
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ],
double X [ ],
const double B [ ],
void *Numeric,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
int umfpack_zi_solve
(
int sys,
const int Ap [ ],
const int Ai [ ],
const double Ax [ ], const double Az [ ],
double Xx [ ], double Xz [ ],
const double Bx [ ], const double Bz [ ],
void *Numeric,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
UF_long umfpack_zl_solve
(
UF_long sys,
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ], const double Az [ ],
double Xx [ ], double Xz [ ],
const double Bx [ ], const double Bz [ ],
void *Numeric,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
/*
double int Syntax:
#include "umfpack.h"
void *Numeric ;
int status, *Ap, *Ai, sys ;
double *B, *X, *Ax, Info [UMFPACK_INFO], Control [UMFPACK_CONTROL] ;
status = umfpack_di_solve (sys, Ap, Ai, Ax, X, B, Numeric, Control, Info) ;
double UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
UF_long status, *Ap, *Ai, sys ;
double *B, *X, *Ax, Info [UMFPACK_INFO], Control [UMFPACK_CONTROL] ;
status = umfpack_dl_solve (sys, Ap, Ai, Ax, X, B, Numeric, Control, Info) ;
complex int Syntax:
#include "umfpack.h"
void *Numeric ;
int status, *Ap, *Ai, sys ;
double *Bx, *Bz, *Xx, *Xz, *Ax, *Az, Info [UMFPACK_INFO],
Control [UMFPACK_CONTROL] ;
status = umfpack_zi_solve (sys, Ap, Ai, Ax, Az, Xx, Xz, Bx, Bz, Numeric,
Control, Info) ;
complex UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
UF_long status, *Ap, *Ai, sys ;
double *Bx, *Bz, *Xx, *Xz, *Ax, *Az, Info [UMFPACK_INFO],
Control [UMFPACK_CONTROL] ;
status = umfpack_zl_solve (sys, Ap, Ai, Ax, Az, Xx, Xz, Bx, Bz, Numeric,
Control, Info) ;
packed complex Syntax:
Same as above, Xz, Bz, and Az are NULL.
Purpose:
Given LU factors computed by umfpack_*_numeric (PAQ=LU, PRAQ=LU, or
P(R\A)Q=LU) and the right-hand-side, B, solve a linear system for the
solution X. Iterative refinement is optionally performed. Only square
systems are handled. Singular matrices result in a divide-by-zero for all
systems except those involving just the matrix L. Iterative refinement is
not performed for singular matrices. In the discussion below, n is equal
to n_row and n_col, because only square systems are handled.
Returns:
The status code is returned. See Info [UMFPACK_STATUS], below.
Arguments:
Int sys ; Input argument, not modified.
Defines which system to solve. (') is the linear algebraic transpose
(complex conjugate if A is complex), and (.') is the array transpose.
sys value system solved
UMFPACK_A Ax=b
UMFPACK_At A'x=b
UMFPACK_Aat A.'x=b
UMFPACK_Pt_L P'Lx=b
UMFPACK_L Lx=b
UMFPACK_Lt_P L'Px=b
UMFPACK_Lat_P L.'Px=b
UMFPACK_Lt L'x=b
UMFPACK_U_Qt UQ'x=b
UMFPACK_U Ux=b
UMFPACK_Q_Ut QU'x=b
UMFPACK_Q_Uat QU.'x=b
UMFPACK_Ut U'x=b
UMFPACK_Uat U.'x=b
Iterative refinement can be optionally performed when sys is any of
the following:
UMFPACK_A Ax=b
UMFPACK_At A'x=b
UMFPACK_Aat A.'x=b
For the other values of the sys argument, iterative refinement is not
performed (Control [UMFPACK_IRSTEP], Ap, Ai, Ax, and Az are ignored).
Int Ap [n+1] ; Input argument, not modified.
Int Ai [nz] ; Input argument, not modified.
double Ax [nz] ; Input argument, not modified.
Size 2*nz for packed complex case.
double Az [nz] ; Input argument, not modified, for complex versions.
If iterative refinement is requested (Control [UMFPACK_IRSTEP] >= 1,
Ax=b, A'x=b, or A.'x=b is being solved, and A is nonsingular), then
these arrays must be identical to the same ones passed to
umfpack_*_numeric. The umfpack_*_solve routine does not check the
contents of these arguments, so the results are undefined if Ap, Ai, Ax,
and/or Az are modified between the calls the umfpack_*_numeric and
umfpack_*_solve. These three arrays do not need to be present (NULL
pointers can be passed) if Control [UMFPACK_IRSTEP] is zero, or if a
system other than Ax=b, A'x=b, or A.'x=b is being solved, or if A is
singular, since in each of these cases A is not accessed.
If Az, Xz, or Bz are NULL, then both real
and imaginary parts are contained in Ax[0..2*nz-1], with Ax[2*k]
and Ax[2*k+1] being the real and imaginary part of the kth entry.
double X [n] ; Output argument.
or:
double Xx [n] ; Output argument, real part
Size 2*n for packed complex case.
double Xz [n] ; Output argument, imaginary part.
The solution to the linear system, where n = n_row = n_col is the
dimension of the matrices A, L, and U.
If Az, Xz, or Bz are NULL, then both real
and imaginary parts are returned in Xx[0..2*n-1], with Xx[2*k] and
Xx[2*k+1] being the real and imaginary part of the kth entry.
double B [n] ; Input argument, not modified.
or:
double Bx [n] ; Input argument, not modified, real part.
Size 2*n for packed complex case.
double Bz [n] ; Input argument, not modified, imaginary part.
The right-hand side vector, b, stored as a conventional array of size n
(or two arrays of size n for complex versions). This routine does not
solve for multiple right-hand-sides, nor does it allow b to be stored in
a sparse-column form.
If Az, Xz, or Bz are NULL, then both real
and imaginary parts are contained in Bx[0..2*n-1], with Bx[2*k]
and Bx[2*k+1] being the real and imaginary part of the kth entry.
void *Numeric ; Input argument, not modified.
Numeric must point to a valid Numeric object, computed by
umfpack_*_numeric.
double Control [UMFPACK_CONTROL] ; Input argument, not modified.
If a (double *) NULL pointer is passed, then the default control
settings are used. Otherwise, the settings are determined from the
Control array. See umfpack_*_defaults on how to fill the Control
array with the default settings. If Control contains NaN's, the
defaults are used. The following Control parameters are used:
Control [UMFPACK_IRSTEP]: The maximum number of iterative refinement
steps to attempt. A value less than zero is treated as zero. If
less than 1, or if Ax=b, A'x=b, or A.'x=b is not being solved, or
if A is singular, then the Ap, Ai, Ax, and Az arguments are not
accessed. Default: 2.
double Info [UMFPACK_INFO] ; Output argument.
Contains statistics about the solution factorization. If a
(double *) NULL pointer is passed, then no statistics are returned in
Info (this is not an error condition). The following statistics are
computed in umfpack_*_solve:
Info [UMFPACK_STATUS]: status code. This is also the return value,
whether or not Info is present.
UMFPACK_OK
The linear system was successfully solved.
UMFPACK_WARNING_singular_matrix
A divide-by-zero occurred. Your solution will contain Inf's
and/or NaN's. Some parts of the solution may be valid. For
example, solving Ax=b with
A = [2 0] b = [ 1 ] returns x = [ 0.5 ]
[0 0] [ 0 ] [ Inf ]
UMFPACK_ERROR_out_of_memory
Insufficient memory to solve the linear system.
UMFPACK_ERROR_argument_missing
One or more required arguments are missing. The B, X, (or
Bx and Xx for the complex versions) arguments
are always required. Info and Control are not required. Ap,
Ai, Ax are required if Ax=b,
A'x=b, A.'x=b is to be solved, the (default) iterative
refinement is requested, and the matrix A is nonsingular.
UMFPACK_ERROR_invalid_system
The sys argument is not valid, or the matrix A is not square.
UMFPACK_ERROR_invalid_Numeric_object
The Numeric object is not valid.
Info [UMFPACK_NROW], Info [UMFPACK_NCOL]:
The dimensions of the matrix A (L is n_row-by-n_inner and
U is n_inner-by-n_col, with n_inner = min(n_row,n_col)).
Info [UMFPACK_NZ]: the number of entries in the input matrix, Ap [n],
if iterative refinement is requested (Ax=b, A'x=b, or A.'x=b is
being solved, Control [UMFPACK_IRSTEP] >= 1, and A is nonsingular).
Info [UMFPACK_IR_TAKEN]: The number of iterative refinement steps
effectively taken. The number of steps attempted may be one more
than this; the refinement algorithm backtracks if the last
refinement step worsens the solution.
Info [UMFPACK_IR_ATTEMPTED]: The number of iterative refinement steps
attempted. The number of times a linear system was solved is one
more than this (once for the initial Ax=b, and once for each Ay=r
solved for each iterative refinement step attempted).
Info [UMFPACK_OMEGA1]: sparse backward error estimate, omega1, if
iterative refinement was performed, or -1 if iterative refinement
not performed.
Info [UMFPACK_OMEGA2]: sparse backward error estimate, omega2, if
iterative refinement was performed, or -1 if iterative refinement
not performed.
Info [UMFPACK_SOLVE_FLOPS]: the number of floating point operations
performed to solve the linear system. This includes the work
taken for all iterative refinement steps, including the backtrack
(if any).
Info [UMFPACK_SOLVE_TIME]: The time taken, in seconds.
Info [UMFPACK_SOLVE_WALLTIME]: The wallclock time taken, in seconds.
Only the above listed Info [...] entries are accessed. The remaining
entries of Info are not accessed or modified by umfpack_*_solve.
Future versions might modify different parts of Info.
*/

View File

@ -0,0 +1,517 @@
/* ========================================================================== */
/* === umfpack_symbolic ===================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_symbolic
(
int n_row,
int n_col,
const int Ap [ ],
const int Ai [ ],
const double Ax [ ],
void **Symbolic,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
UF_long umfpack_dl_symbolic
(
UF_long n_row,
UF_long n_col,
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ],
void **Symbolic,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
int umfpack_zi_symbolic
(
int n_row,
int n_col,
const int Ap [ ],
const int Ai [ ],
const double Ax [ ], const double Az [ ],
void **Symbolic,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
UF_long umfpack_zl_symbolic
(
UF_long n_row,
UF_long n_col,
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ], const double Az [ ],
void **Symbolic,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO]
) ;
/*
double int Syntax:
#include "umfpack.h"
void *Symbolic ;
int n_row, n_col, *Ap, *Ai, status ;
double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax ;
status = umfpack_di_symbolic (n_row, n_col, Ap, Ai, Ax,
&Symbolic, Control, Info) ;
double UF_long Syntax:
#include "umfpack.h"
void *Symbolic ;
UF_long n_row, n_col, *Ap, *Ai, status ;
double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax ;
status = umfpack_dl_symbolic (n_row, n_col, Ap, Ai, Ax,
&Symbolic, Control, Info) ;
complex int Syntax:
#include "umfpack.h"
void *Symbolic ;
int n_row, n_col, *Ap, *Ai, status ;
double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax, *Az ;
status = umfpack_zi_symbolic (n_row, n_col, Ap, Ai, Ax, Az,
&Symbolic, Control, Info) ;
complex UF_long Syntax:
#include "umfpack.h"
void *Symbolic ;
UF_long n_row, n_col, *Ap, *Ai, status ;
double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], *Ax, *Az ;
status = umfpack_zl_symbolic (n_row, n_col, Ap, Ai, Ax, Az,
&Symbolic, Control, Info) ;
packed complex Syntax:
Same as above, except Az is NULL.
Purpose:
Given nonzero pattern of a sparse matrix A in column-oriented form,
umfpack_*_symbolic performs a column pre-ordering to reduce fill-in
(using COLAMD, AMD or METIS) and a symbolic factorization. This is required
before the matrix can be numerically factorized with umfpack_*_numeric.
If you wish to bypass the COLAMD/AMD/METIS pre-ordering and provide your own
ordering, use umfpack_*_qsymbolic instead. If you wish to pass in a
pointer to a user-provided ordering function, use umfpack_*_fsymbolic.
Since umfpack_*_symbolic and umfpack_*_qsymbolic are very similar, options
for both routines are discussed below.
For the following discussion, let S be the submatrix of A obtained after
eliminating all pivots of zero Markowitz cost. S has dimension
(n_row-n1-nempty_row) -by- (n_col-n1-nempty_col), where
n1 = Info [UMFPACK_COL_SINGLETONS] + Info [UMFPACK_ROW_SINGLETONS],
nempty_row = Info [UMFPACK_NEMPTY_ROW] and
nempty_col = Info [UMFPACK_NEMPTY_COL].
Returns:
The status code is returned. See Info [UMFPACK_STATUS], below.
Arguments:
Int n_row ; Input argument, not modified.
Int n_col ; Input argument, not modified.
A is an n_row-by-n_col matrix. Restriction: n_row > 0 and n_col > 0.
Int Ap [n_col+1] ; Input argument, not modified.
Ap is an integer array of size n_col+1. On input, it holds the
"pointers" for the column form of the sparse matrix A. Column j of
the matrix A is held in Ai [(Ap [j]) ... (Ap [j+1]-1)]. The first
entry, Ap [0], must be zero, and Ap [j] <= Ap [j+1] must hold for all
j in the range 0 to n_col-1. The value nz = Ap [n_col] is thus the
total number of entries in the pattern of the matrix A. nz must be
greater than or equal to zero.
Int Ai [nz] ; Input argument, not modified, of size nz = Ap [n_col].
The nonzero pattern (row indices) for column j is stored in
Ai [(Ap [j]) ... (Ap [j+1]-1)]. The row indices in a given column j
must be in ascending order, and no duplicate row indices may be present.
Row indices must be in the range 0 to n_row-1 (the matrix is 0-based).
See umfpack_*_triplet_to_col for how to sort the columns of a matrix
and sum up the duplicate entries. See umfpack_*_report_matrix for how
to print the matrix A.
double Ax [nz] ; Optional input argument, not modified. May be NULL.
Size 2*nz for packed complex case.
The numerical values of the sparse matrix A. The nonzero pattern (row
indices) for column j is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)], and
the corresponding numerical values are stored in
Ax [(Ap [j]) ... (Ap [j+1]-1)]. Used only for gathering statistics
about how many nonzeros are placed on the diagonal by the fill-reducing
ordering.
double Az [nz] ; Optional input argument, not modified, for complex
versions. May be NULL.
For the complex versions, this holds the imaginary part of A. The
imaginary part of column j is held in Az [(Ap [j]) ... (Ap [j+1]-1)].
If Az is NULL, then both real
and imaginary parts are contained in Ax[0..2*nz-1], with Ax[2*k]
and Ax[2*k+1] being the real and imaginary part of the kth entry.
Used for statistics only. See the description of Ax, above.
void **Symbolic ; Output argument.
**Symbolic is the address of a (void *) pointer variable in the user's
calling routine (see Syntax, above). On input, the contents of this
variable are not defined. On output, this variable holds a (void *)
pointer to the Symbolic object (if successful), or (void *) NULL if
a failure occurred.
double Control [UMFPACK_CONTROL] ; Input argument, not modified.
If a (double *) NULL pointer is passed, then the default control
settings are used (the defaults are suitable for all matrices,
ranging from those with highly unsymmetric nonzero pattern, to
symmetric matrices). Otherwise, the settings are determined from the
Control array. See umfpack_*_defaults on how to fill the Control
array with the default settings. If Control contains NaN's, the
defaults are used. The following Control parameters are used:
Control [UMFPACK_STRATEGY]: This is the most important control
parameter. It determines what kind of ordering and pivoting
strategy that UMFPACK should use. There are 4 options:
UMFPACK_STRATEGY_AUTO: This is the default. The input matrix is
analyzed to determine how symmetric the nonzero pattern is, and
how many entries there are on the diagonal. It then selects one
of the following strategies. Refer to the User Guide for a
description of how the strategy is automatically selected.
UMFPACK_STRATEGY_UNSYMMETRIC: Use the unsymmetric strategy. COLAMD
is used to order the columns of A, followed by a postorder of
the column elimination tree. No attempt is made to perform
diagonal pivoting. The column ordering is refined during
factorization.
In the numerical factorization, the
Control [UMFPACK_SYM_PIVOT_TOLERANCE] parameter is ignored. A
pivot is selected if its magnitude is >=
Control [UMFPACK_PIVOT_TOLERANCE] (default 0.1) times the
largest entry in its column.
UMFPACK_STRATEGY_SYMMETRIC: Use the symmetric strategy
In this method, the approximate minimum degree
ordering (AMD) is applied to A+A', followed by a postorder of
the elimination tree of A+A'. UMFPACK attempts to perform
diagonal pivoting during numerical factorization. No refinement
of the column pre-ordering is performed during factorization.
In the numerical factorization, a nonzero entry on the diagonal
is selected as the pivot if its magnitude is >= Control
[UMFPACK_SYM_PIVOT_TOLERANCE] (default 0.001) times the largest
entry in its column. If this is not acceptable, then an
off-diagonal pivot is selected with magnitude >= Control
[UMFPACK_PIVOT_TOLERANCE] (default 0.1) times the largest entry
in its column.
Control [UMFPACK_ORDERING]: The ordering method to use:
UMFPACK_ORDERING_CHOLMOD try AMD/COLAMD, then METIS if needed
UMFPACK_ORDERING_AMD just AMD or COLAMD
UMFPACK_ORDERING_GIVEN just Qinit (umfpack_*_qsymbolic only)
UMFPACK_ORDERING_NONE no fill-reducing ordering
UMFPACK_ORDERING_METIS just METIS(A+A') or METIS(A'A)
UMFPACK_ORDERING_BEST try AMD/COLAMD, METIS, and NESDIS
UMFPACK_ORDERING_USER just user function (*_fsymbolic only)
Control [UMFPACK_SINGLETONS]: If false (0), then singletons are
not removed prior to factorization. Default: true (1).
Control [UMFPACK_DENSE_COL]:
If COLAMD is used, columns with more than
max (16, Control [UMFPACK_DENSE_COL] * 16 * sqrt (n_row)) entries
are placed placed last in the column pre-ordering. Default: 0.2.
Control [UMFPACK_DENSE_ROW]:
Rows with more than max (16, Control [UMFPACK_DENSE_ROW] * 16 *
sqrt (n_col)) entries are treated differently in the COLAMD
pre-ordering, and in the internal data structures during the
subsequent numeric factorization. Default: 0.2.
Control [UMFPACK_AMD_DENSE]: rows/columns in A+A' with more than
max (16, Control [UMFPACK_AMD_DENSE] * sqrt (n)) entries
(where n = n_row = n_col) are ignored in the AMD pre-ordering.
Default: 10.
Control [UMFPACK_BLOCK_SIZE]: the block size to use for Level-3 BLAS
in the subsequent numerical factorization (umfpack_*_numeric).
A value less than 1 is treated as 1. Default: 32. Modifying this
parameter affects when updates are applied to the working frontal
matrix, and can indirectly affect fill-in and operation count.
Assuming the block size is large enough (8 or so), this parameter
has a modest effect on performance.
Control [UMFPACK_FIXQ]: If > 0, then the pre-ordering Q is not modified
during numeric factorization. If < 0, then Q may be modified. If
zero, then this is controlled automatically (the unsymmetric
strategy modifies Q, the others do not). Default: 0.
Control [UMFPACK_AGGRESSIVE]: If nonzero, aggressive absorption is used
in COLAMD and AMD. Default: 1.
double Info [UMFPACK_INFO] ; Output argument, not defined on input.
Contains statistics about the symbolic analysis. If a (double *) NULL
pointer is passed, then no statistics are returned in Info (this is not
an error condition). The entire Info array is cleared (all entries set
to -1) and then the following statistics are computed:
Info [UMFPACK_STATUS]: status code. This is also the return value,
whether or not Info is present.
UMFPACK_OK
Each column of the input matrix contained row indices
in increasing order, with no duplicates. Only in this case
does umfpack_*_symbolic compute a valid symbolic factorization.
For the other cases below, no Symbolic object is created
(*Symbolic is (void *) NULL).
UMFPACK_ERROR_n_nonpositive
n is less than or equal to zero.
UMFPACK_ERROR_invalid_matrix
Number of entries in the matrix is negative, Ap [0] is nonzero,
a column has a negative number of entries, a row index is out of
bounds, or the columns of input matrix were jumbled (unsorted
columns or duplicate entries).
UMFPACK_ERROR_out_of_memory
Insufficient memory to perform the symbolic analysis. If the
analysis requires more than 2GB of memory and you are using
the 32-bit ("int") version of UMFPACK, then you are guaranteed
to run out of memory. Try using the 64-bit version of UMFPACK.
UMFPACK_ERROR_argument_missing
One or more required arguments is missing.
UMFPACK_ERROR_internal_error
Something very serious went wrong. This is a bug.
Please contact the author (davis@cise.ufl.edu).
Info [UMFPACK_NROW]: the value of the input argument n_row.
Info [UMFPACK_NCOL]: the value of the input argument n_col.
Info [UMFPACK_NZ]: the number of entries in the input matrix
(Ap [n_col]).
Info [UMFPACK_SIZE_OF_UNIT]: the number of bytes in a Unit,
for memory usage statistics below.
Info [UMFPACK_SIZE_OF_INT]: the number of bytes in an int.
Info [UMFPACK_SIZE_OF_LONG]: the number of bytes in a UF_long.
Info [UMFPACK_SIZE_OF_POINTER]: the number of bytes in a void *
pointer.
Info [UMFPACK_SIZE_OF_ENTRY]: the number of bytes in a numerical entry.
Info [UMFPACK_NDENSE_ROW]: number of "dense" rows in A. These rows are
ignored when the column pre-ordering is computed in COLAMD. They
are also treated differently during numeric factorization. If > 0,
then the matrix had to be re-analyzed by UMF_analyze, which does
not ignore these rows.
Info [UMFPACK_NEMPTY_ROW]: number of "empty" rows in A, as determined
These are rows that either have no entries, or whose entries are
all in pivot columns of zero-Markowitz-cost pivots.
Info [UMFPACK_NDENSE_COL]: number of "dense" columns in A. COLAMD
orders these columns are ordered last in the factorization, but
before "empty" columns.
Info [UMFPACK_NEMPTY_COL]: number of "empty" columns in A. These are
columns that either have no entries, or whose entries are all in
pivot rows of zero-Markowitz-cost pivots. These columns are
ordered last in the factorization, to the right of "dense" columns.
Info [UMFPACK_SYMBOLIC_DEFRAG]: number of garbage collections
performed during ordering and symbolic pre-analysis.
Info [UMFPACK_SYMBOLIC_PEAK_MEMORY]: the amount of memory (in Units)
required for umfpack_*_symbolic to complete. This count includes
the size of the Symbolic object itself, which is also reported in
Info [UMFPACK_SYMBOLIC_SIZE].
Info [UMFPACK_SYMBOLIC_SIZE]: the final size of the Symbolic object (in
Units). This is fairly small, roughly 2*n to 13*n integers,
depending on the matrix.
Info [UMFPACK_VARIABLE_INIT_ESTIMATE]: the Numeric object contains two
parts. The first is fixed in size (O (n_row+n_col)). The
second part holds the sparse LU factors and the contribution blocks
from factorized frontal matrices. This part changes in size during
factorization. Info [UMFPACK_VARIABLE_INIT_ESTIMATE] is the exact
size (in Units) required for this second variable-sized part in
order for the numerical factorization to start.
Info [UMFPACK_VARIABLE_PEAK_ESTIMATE]: the estimated peak size (in
Units) of the variable-sized part of the Numeric object. This is
usually an upper bound, but that is not guaranteed.
Info [UMFPACK_VARIABLE_FINAL_ESTIMATE]: the estimated final size (in
Units) of the variable-sized part of the Numeric object. This is
usually an upper bound, but that is not guaranteed. It holds just
the sparse LU factors.
Info [UMFPACK_NUMERIC_SIZE_ESTIMATE]: an estimate of the final size (in
Units) of the entire Numeric object (both fixed-size and variable-
sized parts), which holds the LU factorization (including the L, U,
P and Q matrices).
Info [UMFPACK_PEAK_MEMORY_ESTIMATE]: an estimate of the total amount of
memory (in Units) required by umfpack_*_symbolic and
umfpack_*_numeric to perform both the symbolic and numeric
factorization. This is the larger of the amount of memory needed
in umfpack_*_numeric itself, and the amount of memory needed in
umfpack_*_symbolic (Info [UMFPACK_SYMBOLIC_PEAK_MEMORY]). The
count includes the size of both the Symbolic and Numeric objects
themselves. It can be a very loose upper bound, particularly when
the symmetric strategy is used.
Info [UMFPACK_FLOPS_ESTIMATE]: an estimate of the total floating-point
operations required to factorize the matrix. This is a "true"
theoretical estimate of the number of flops that would be performed
by a flop-parsimonious sparse LU algorithm. It assumes that no
extra flops are performed except for what is strictly required to
compute the LU factorization. It ignores, for example, the flops
performed by umfpack_di_numeric to add contribution blocks of
frontal matrices together. If L and U are the upper bound on the
pattern of the factors, then this flop count estimate can be
represented in MATLAB (for real matrices, not complex) as:
Lnz = full (sum (spones (L))) - 1 ; % nz in each col of L
Unz = full (sum (spones (U')))' - 1 ; % nz in each row of U
flops = 2*Lnz*Unz + sum (Lnz) ;
The actual "true flop" count found by umfpack_*_numeric will be
less than this estimate.
For the real version, only (+ - * /) are counted. For the complex
version, the following counts are used:
operation flops
c = 1/b 6
c = a*b 6
c -= a*b 8
Info [UMFPACK_LNZ_ESTIMATE]: an estimate of the number of nonzeros in
L, including the diagonal. Since L is unit-diagonal, the diagonal
of L is not stored. This estimate is a strict upper bound on the
actual nonzeros in L to be computed by umfpack_*_numeric.
Info [UMFPACK_UNZ_ESTIMATE]: an estimate of the number of nonzeros in
U, including the diagonal. This estimate is a strict upper bound on
the actual nonzeros in U to be computed by umfpack_*_numeric.
Info [UMFPACK_MAX_FRONT_SIZE_ESTIMATE]: estimate of the size of the
largest frontal matrix (# of entries), for arbitrary partial
pivoting during numerical factorization.
Info [UMFPACK_SYMBOLIC_TIME]: The CPU time taken, in seconds.
Info [UMFPACK_SYMBOLIC_WALLTIME]: The wallclock time taken, in seconds.
Info [UMFPACK_STRATEGY_USED]: The ordering strategy used:
UMFPACK_STRATEGY_SYMMETRIC or UMFPACK_STRATEGY_UNSYMMETRIC
Info [UMFPACK_ORDERING_USED]: The ordering method used:
UMFPACK_ORDERING_AMD
UMFPACK_ORDERING_GIVEN
UMFPACK_ORDERING_NONE
UMFPACK_ORDERING_METIS
UMFPACK_ORDERING_USER
Info [UMFPACK_QFIXED]: 1 if the column pre-ordering will be refined
during numerical factorization, 0 if not.
Info [UMFPACK_DIAG_PREFERED]: 1 if diagonal pivoting will be attempted,
0 if not.
Info [UMFPACK_COL_SINGLETONS]: the matrix A is analyzed by first
eliminating all pivots with zero Markowitz cost. This count is the
number of these pivots with exactly one nonzero in their pivot
column.
Info [UMFPACK_ROW_SINGLETONS]: the number of zero-Markowitz-cost
pivots with exactly one nonzero in their pivot row.
Info [UMFPACK_PATTERN_SYMMETRY]: the symmetry of the pattern of S.
Info [UMFPACK_NZ_A_PLUS_AT]: the number of off-diagonal entries in S+S'.
Info [UMFPACK_NZDIAG]: the number of entries on the diagonal of S.
Info [UMFPACK_N2]: if S is square, and nempty_row = nempty_col, this
is equal to n_row - n1 - nempty_row.
Info [UMFPACK_S_SYMMETRIC]: 1 if S is square and its diagonal has been
preserved, 0 otherwise.
Info [UMFPACK_MAX_FRONT_NROWS_ESTIMATE]: estimate of the max number of
rows in any frontal matrix, for arbitrary partial pivoting.
Info [UMFPACK_MAX_FRONT_NCOLS_ESTIMATE]: estimate of the max number of
columns in any frontal matrix, for arbitrary partial pivoting.
------------------------------------------------------------------------
The next four statistics are computed only if AMD is used:
------------------------------------------------------------------------
Info [UMFPACK_SYMMETRIC_LUNZ]: The number of nonzeros in L and U,
assuming no pivoting during numerical factorization, and assuming a
zero-free diagonal of U. Excludes the entries on the diagonal of
L. If the matrix has a purely symmetric nonzero pattern, this is
often a lower bound on the nonzeros in the actual L and U computed
in the numerical factorization, for matrices that fit the criteria
for the "symmetric" strategy.
Info [UMFPACK_SYMMETRIC_FLOPS]: The floating-point operation count in
the numerical factorization phase, assuming no pivoting. If the
pattern of the matrix is symmetric, this is normally a lower bound
on the floating-point operation count in the actual numerical
factorization, for matrices that fit the criteria for the symmetric
strategy.
Info [UMFPACK_SYMMETRIC_NDENSE]: The number of "dense" rows/columns of
S+S' that were ignored during the AMD ordering. These are placed
last in the output order. If > 0, then the
Info [UMFPACK_SYMMETRIC_*] statistics, above are rough upper bounds.
Info [UMFPACK_SYMMETRIC_DMAX]: The maximum number of nonzeros in any
column of L, if no pivoting is performed during numerical
factorization. Excludes the part of the LU factorization for
pivots with zero Markowitz cost.
At the start of umfpack_*_symbolic, all of Info is set of -1, and then
after that only the above listed Info [...] entries are accessed.
Future versions might modify different parts of Info.
*/

View File

@ -0,0 +1,60 @@
/* ========================================================================== */
/* === umfpack_tictoc ======================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
void umfpack_tic (double stats [2]) ;
void umfpack_toc (double stats [2]) ;
/*
Syntax (for all versions: di, dl, zi, and zl):
#include "umfpack.h"
double stats [2] ;
umfpack_tic (stats) ;
...
umfpack_toc (stats) ;
Purpose:
umfpack_tic returns the CPU time and wall clock time used by the process.
The CPU time includes both "user" and "system" time (the latter is time
spent by the system on behalf of the process, and is thus charged to the
process). umfpack_toc returns the CPU time and wall clock time since the
last call to umfpack_tic with the same stats array.
Typical usage:
umfpack_tic (stats) ;
... do some work ...
umfpack_toc (stats) ;
then stats [1] contains the time in seconds used by the code between
umfpack_tic and umfpack_toc, and stats [0] contains the wall clock time
elapsed between the umfpack_tic and umfpack_toc. These two routines act
just like tic and toc in MATLAB, except that the both process time and
wall clock time are returned.
This routine normally uses the sysconf and times routines in the POSIX
standard. If -DNPOSIX is defined at compile time, then the ANSI C clock
routine is used instead, and only the CPU time is returned (stats [0]
is set to zero).
umfpack_tic and umfpack_toc are the routines used internally in UMFPACK
to time the symbolic analysis, numerical factorization, and the forward/
backward solve.
Arguments:
double stats [2]:
stats [0]: wall clock time, in seconds
stats [1]: CPU time, in seconds
*/

View File

@ -0,0 +1,39 @@
/* ========================================================================== */
/* === umfpack_timer ======================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
double umfpack_timer ( void ) ;
/*
Syntax (for all versions: di, dl, zi, and zl):
#include "umfpack.h"
double t ;
t = umfpack_timer ( ) ;
Purpose:
Returns the CPU time used by the process. Includes both "user" and "system"
time (the latter is time spent by the system on behalf of the process, and
is thus charged to the process). It does not return the wall clock time.
See umfpack_tic and umfpack_toc (the file umfpack_tictoc.h) for the timer
used internally by UMFPACK.
This routine uses the Unix getrusage routine, if available. It is less
subject to overflow than the ANSI C clock routine. If getrusage is not
available, the portable ANSI C clock routine is used instead.
Unfortunately, clock ( ) overflows if the CPU time exceeds 2147 seconds
(about 36 minutes) when sizeof (clock_t) is 4 bytes. If you have getrusage,
be sure to compile UMFPACK with the -DGETRUSAGE flag set; see umf_config.h
and the User Guide for details. Even the getrusage routine can overlow.
Arguments:
None.
*/

View File

@ -0,0 +1,216 @@
/* ========================================================================== */
/* === umfpack_transpose ==================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_transpose
(
int n_row,
int n_col,
const int Ap [ ],
const int Ai [ ],
const double Ax [ ],
const int P [ ],
const int Q [ ],
int Rp [ ],
int Ri [ ],
double Rx [ ]
) ;
UF_long umfpack_dl_transpose
(
UF_long n_row,
UF_long n_col,
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ],
const UF_long P [ ],
const UF_long Q [ ],
UF_long Rp [ ],
UF_long Ri [ ],
double Rx [ ]
) ;
int umfpack_zi_transpose
(
int n_row,
int n_col,
const int Ap [ ],
const int Ai [ ],
const double Ax [ ], const double Az [ ],
const int P [ ],
const int Q [ ],
int Rp [ ],
int Ri [ ],
double Rx [ ], double Rz [ ],
int do_conjugate
) ;
UF_long umfpack_zl_transpose
(
UF_long n_row,
UF_long n_col,
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ], const double Az [ ],
const UF_long P [ ],
const UF_long Q [ ],
UF_long Rp [ ],
UF_long Ri [ ],
double Rx [ ], double Rz [ ],
UF_long do_conjugate
) ;
/*
double int Syntax:
#include "umfpack.h"
int n_row, n_col, status, *Ap, *Ai, *P, *Q, *Rp, *Ri ;
double *Ax, *Rx ;
status = umfpack_di_transpose (n_row, n_col, Ap, Ai, Ax, P, Q, Rp, Ri, Rx) ;
double UF_long Syntax:
#include "umfpack.h"
UF_long n_row, n_col, status, *Ap, *Ai, *P, *Q, *Rp, *Ri ;
double *Ax, *Rx ;
status = umfpack_dl_transpose (n_row, n_col, Ap, Ai, Ax, P, Q, Rp, Ri, Rx) ;
complex int Syntax:
#include "umfpack.h"
int n_row, n_col, status, *Ap, *Ai, *P, *Q, *Rp, *Ri, do_conjugate ;
double *Ax, *Az, *Rx, *Rz ;
status = umfpack_zi_transpose (n_row, n_col, Ap, Ai, Ax, Az, P, Q,
Rp, Ri, Rx, Rz, do_conjugate) ;
complex UF_long Syntax:
#include "umfpack.h"
UF_long n_row, n_col, status, *Ap, *Ai, *P, *Q, *Rp, *Ri, do_conjugate ;
double *Ax, *Az, *Rx, *Rz ;
status = umfpack_zl_transpose (n_row, n_col, Ap, Ai, Ax, Az, P, Q,
Rp, Ri, Rx, Rz, do_conjugate) ;
packed complex Syntax:
Same as above, except Az are Rz are NULL.
Purpose:
Transposes and optionally permutes a sparse matrix in row or column-form,
R = (PAQ)'. In MATLAB notation, R = (A (P,Q))' or R = (A (P,Q)).' doing
either the linear algebraic transpose or the array transpose. Alternatively,
this routine can be viewed as converting A (P,Q) from column-form to
row-form, or visa versa (for the array transpose). Empty rows and columns
may exist. The matrix A may be singular and/or rectangular.
umfpack_*_transpose is useful if you want to factorize A' or A.' instead of
A. Factorizing A' or A.' instead of A can be much better, particularly if
AA' is much sparser than A'A. You can still solve Ax=b if you factorize
A' or A.', by solving with the sys argument UMFPACK_At or UMFPACK_Aat,
respectively, in umfpack_*_*solve.
Returns:
UMFPACK_OK if successful.
UMFPACK_ERROR_out_of_memory if umfpack_*_transpose fails to allocate a
size-max (n_row,n_col) workspace.
UMFPACK_ERROR_argument_missing if Ai, Ap, Ri, and/or Rp are missing.
UMFPACK_ERROR_n_nonpositive if n_row <= 0 or n_col <= 0
UMFPACK_ERROR_invalid_permutation if P and/or Q are invalid.
UMFPACK_ERROR_invalid_matrix if Ap [n_col] < 0, if Ap [0] != 0,
if Ap [j] > Ap [j+1] for any j in the range 0 to n_col-1,
if any row index i is < 0 or >= n_row, or if the row indices
in any column are not in ascending order.
Arguments:
Int n_row ; Input argument, not modified.
Int n_col ; Input argument, not modified.
A is an n_row-by-n_col matrix. Restriction: n_row > 0 and n_col > 0.
Int Ap [n_col+1] ; Input argument, not modified.
The column pointers of the column-oriented form of the matrix A. See
umfpack_*_symbolic for a description. The number of entries in
the matrix is nz = Ap [n_col]. Ap [0] must be zero, Ap [n_col] must be
=> 0, and Ap [j] <= Ap [j+1] and Ap [j] <= Ap [n_col] must be true for
all j in the range 0 to n_col-1. Empty columns are OK (that is, Ap [j]
may equal Ap [j+1] for any j in the range 0 to n_col-1).
Int Ai [nz] ; Input argument, not modified, of size nz = Ap [n_col].
The nonzero pattern (row indices) for column j is stored in
Ai [(Ap [j]) ... (Ap [j+1]-1)]. The row indices in a given column j
must be in ascending order, and no duplicate row indices may be present.
Row indices must be in the range 0 to n_row-1 (the matrix is 0-based).
double Ax [nz] ; Input argument, not modified, of size nz = Ap [n_col].
Size 2*nz if Az or Rz are NULL.
double Az [nz] ; Input argument, not modified, for complex versions.
If present, these are the numerical values of the sparse matrix A.
The nonzero pattern (row indices) for column j is stored in
Ai [(Ap [j]) ... (Ap [j+1]-1)], and the corresponding real numerical
values are stored in Ax [(Ap [j]) ... (Ap [j+1]-1)]. The imaginary
values are stored in Az [(Ap [j]) ... (Ap [j+1]-1)]. The values are
transposed only if Ax and Rx are present.
This is not an error conditions; you are able to transpose
and permute just the pattern of a matrix.
If Az or Rz are NULL, then both real
and imaginary parts are contained in Ax[0..2*nz-1], with Ax[2*k]
and Ax[2*k+1] being the real and imaginary part of the kth entry.
Int P [n_row] ; Input argument, not modified.
The permutation vector P is defined as P [k] = i, where the original
row i of A is the kth row of PAQ. If you want to use the identity
permutation for P, simply pass (Int *) NULL for P. This is not an error
condition. P is a complete permutation of all the rows of A; this
routine does not support the creation of a transposed submatrix of A
(R = A (1:3,:)' where A has more than 3 rows, for example, cannot be
done; a future version might support this operation).
Int Q [n_col] ; Input argument, not modified.
The permutation vector Q is defined as Q [k] = j, where the original
column j of A is the kth column of PAQ. If you want to use the identity
permutation for Q, simply pass (Int *) NULL for Q. This is not an error
condition. Q is a complete permutation of all the columns of A; this
routine does not support the creation of a transposed submatrix of A.
Int Rp [n_row+1] ; Output argument.
The column pointers of the matrix R = (A (P,Q))' or (A (P,Q)).', in the
same form as the column pointers Ap for the matrix A.
Int Ri [nz] ; Output argument.
The row indices of the matrix R = (A (P,Q))' or (A (P,Q)).' , in the
same form as the row indices Ai for the matrix A.
double Rx [nz] ; Output argument.
Size 2*nz if Az or Rz are NULL.
double Rz [nz] ; Output argument, imaginary part for complex versions.
If present, these are the numerical values of the sparse matrix R,
in the same form as the values Ax and Az of the matrix A.
If Az or Rz are NULL, then both real
and imaginary parts are contained in Rx[0..2*nz-1], with Rx[2*k]
and Rx[2*k+1] being the real and imaginary part of the kth entry.
Int do_conjugate ; Input argument for complex versions only.
If true, and if Ax and Rx are present, then the linear
algebraic transpose is computed (complex conjugate). If false, the
array transpose is computed instead.
*/

View File

@ -0,0 +1,263 @@
/* ========================================================================== */
/* === umfpack_triplet_to_col =============================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_triplet_to_col
(
int n_row,
int n_col,
int nz,
const int Ti [ ],
const int Tj [ ],
const double Tx [ ],
int Ap [ ],
int Ai [ ],
double Ax [ ],
int Map [ ]
) ;
UF_long umfpack_dl_triplet_to_col
(
UF_long n_row,
UF_long n_col,
UF_long nz,
const UF_long Ti [ ],
const UF_long Tj [ ],
const double Tx [ ],
UF_long Ap [ ],
UF_long Ai [ ],
double Ax [ ],
UF_long Map [ ]
) ;
int umfpack_zi_triplet_to_col
(
int n_row,
int n_col,
int nz,
const int Ti [ ],
const int Tj [ ],
const double Tx [ ], const double Tz [ ],
int Ap [ ],
int Ai [ ],
double Ax [ ], double Az [ ],
int Map [ ]
) ;
UF_long umfpack_zl_triplet_to_col
(
UF_long n_row,
UF_long n_col,
UF_long nz,
const UF_long Ti [ ],
const UF_long Tj [ ],
const double Tx [ ], const double Tz [ ],
UF_long Ap [ ],
UF_long Ai [ ],
double Ax [ ], double Az [ ],
UF_long Map [ ]
) ;
/*
double int Syntax:
#include "umfpack.h"
int n_row, n_col, nz, *Ti, *Tj, *Ap, *Ai, status, *Map ;
double *Tx, *Ax ;
status = umfpack_di_triplet_to_col (n_row, n_col, nz, Ti, Tj, Tx,
Ap, Ai, Ax, Map) ;
double UF_long Syntax:
#include "umfpack.h"
UF_long n_row, n_col, nz, *Ti, *Tj, *Ap, *Ai, status, *Map ;
double *Tx, *Ax ;
status = umfpack_dl_triplet_to_col (n_row, n_col, nz, Ti, Tj, Tx,
Ap, Ai, Ax, Map) ;
complex int Syntax:
#include "umfpack.h"
int n_row, n_col, nz, *Ti, *Tj, *Ap, *Ai, status, *Map ;
double *Tx, *Tz, *Ax, *Az ;
status = umfpack_zi_triplet_to_col (n_row, n_col, nz, Ti, Tj, Tx, Tz,
Ap, Ai, Ax, Az, Map) ;
UF_long Syntax:
#include "umfpack.h"
UF_long n_row, n_col, nz, *Ti, *Tj, *Ap, *Ai, status, *Map ;
double *Tx, *Tz, *Ax, *Az ;
status = umfpack_zl_triplet_to_col (n_row, n_col, nz, Ti, Tj, Tx, Tz,
Ap, Ai, Ax, Az, Map) ;
packed complex Syntax:
Same as above, except Tz and Az are NULL.
Purpose:
Converts a sparse matrix from "triplet" form to compressed-column form.
Analogous to A = spconvert (Ti, Tj, Tx + Tz*1i) in MATLAB, except that
zero entries present in the triplet form are present in A.
The triplet form of a matrix is a very simple data structure for basic
sparse matrix operations. For example, suppose you wish to factorize a
matrix A coming from a finite element method, in which A is a sum of
dense submatrices, A = E1 + E2 + E3 + ... . The entries in each element
matrix Ei can be concatenated together in the three triplet arrays, and
any overlap between the elements will be correctly summed by
umfpack_*_triplet_to_col.
Transposing a matrix in triplet form is simple; just interchange the
use of Ti and Tj. You can construct the complex conjugate transpose by
negating Tz, for the complex versions.
Permuting a matrix in triplet form is also simple. If you want the matrix
PAQ, or A (P,Q) in MATLAB notation, where P [k] = i means that row i of
A is the kth row of PAQ and Q [k] = j means that column j of A is the kth
column of PAQ, then do the following. First, create inverse permutations
Pinv and Qinv such that Pinv [i] = k if P [k] = i and Qinv [j] = k if
Q [k] = j. Next, for the mth triplet (Ti [m], Tj [m], Tx [m], Tz [m]),
replace Ti [m] with Pinv [Ti [m]] and replace Tj [m] with Qinv [Tj [m]].
If you have a column-form matrix with duplicate entries or unsorted
columns, you can sort it and sum up the duplicates by first converting it
to triplet form with umfpack_*_col_to_triplet, and then converting it back
with umfpack_*_triplet_to_col.
Constructing a submatrix is also easy. Just scan the triplets and remove
those entries outside the desired subset of 0...n_row-1 and 0...n_col-1,
and renumber the indices according to their position in the subset.
You can do all these operations on a column-form matrix by first
converting it to triplet form with umfpack_*_col_to_triplet, doing the
operation on the triplet form, and then converting it back with
umfpack_*_triplet_to_col.
The only operation not supported easily in the triplet form is the
multiplication of two sparse matrices (UMFPACK does not provide this
operation).
You can print the input triplet form with umfpack_*_report_triplet, and
the output matrix with umfpack_*_report_matrix.
The matrix may be singular (nz can be zero, and empty rows and/or columns
may exist). It may also be rectangular and/or complex.
Returns:
UMFPACK_OK if successful.
UMFPACK_ERROR_argument_missing if Ap, Ai, Ti, and/or Tj are missing.
UMFPACK_ERROR_n_nonpositive if n_row <= 0 or n_col <= 0.
UMFPACK_ERROR_invalid_matrix if nz < 0, or if for any k, Ti [k] and/or
Tj [k] are not in the range 0 to n_row-1 or 0 to n_col-1, respectively.
UMFPACK_ERROR_out_of_memory if unable to allocate sufficient workspace.
Arguments:
Int n_row ; Input argument, not modified.
Int n_col ; Input argument, not modified.
A is an n_row-by-n_col matrix. Restriction: n_row > 0 and n_col > 0.
All row and column indices in the triplet form must be in the range
0 to n_row-1 and 0 to n_col-1, respectively.
Int nz ; Input argument, not modified.
The number of entries in the triplet form of the matrix. Restriction:
nz >= 0.
Int Ti [nz] ; Input argument, not modified.
Int Tj [nz] ; Input argument, not modified.
double Tx [nz] ; Input argument, not modified.
Size 2*nz if Tz or Az are NULL.
double Tz [nz] ; Input argument, not modified, for complex versions.
Ti, Tj, Tx, and Tz hold the "triplet" form of a sparse matrix. The kth
nonzero entry is in row i = Ti [k], column j = Tj [k], and the real part
of a_ij is Tx [k]. The imaginary part of a_ij is Tz [k], for complex
versions. The row and column indices i and j must be in the range 0 to
n_row-1 and 0 to n_col-1, respectively. Duplicate entries may be
present; they are summed in the output matrix. This is not an error
condition. The "triplets" may be in any order. Tx, Tz, Ax, and Az
are optional. Ax is computed only if both Ax and Tx are present
(not (double *) NULL). This is not error condition; the routine can
create just the pattern of the output matrix from the pattern of the
triplets.
If Az or Tz are NULL, then both real
and imaginary parts are contained in Tx[0..2*nz-1], with Tx[2*k]
and Tx[2*k+1] being the real and imaginary part of the kth entry.
Int Ap [n_col+1] ; Output argument.
Ap is an integer array of size n_col+1 on input. On output, Ap holds
the "pointers" for the column form of the sparse matrix A. Column j of
the matrix A is held in Ai [(Ap [j]) ... (Ap [j+1]-1)]. The first
entry, Ap [0], is zero, and Ap [j] <= Ap [j+1] holds for all j in the
range 0 to n_col-1. The value nz2 = Ap [n_col] is thus the total
number of entries in the pattern of the matrix A. Equivalently, the
number of duplicate triplets is nz - Ap [n_col].
Int Ai [nz] ; Output argument.
Ai is an integer array of size nz on input. Note that only the first
Ap [n_col] entries are used.
The nonzero pattern (row indices) for column j is stored in
Ai [(Ap [j]) ... (Ap [j+1]-1)]. The row indices in a given column j
are in ascending order, and no duplicate row indices are present.
Row indices are in the range 0 to n_col-1 (the matrix is 0-based).
double Ax [nz] ; Output argument. Size 2*nz if Tz or Az are NULL.
double Az [nz] ; Output argument for complex versions.
Ax and Az (for the complex versions) are double arrays of size nz on
input. Note that only the first Ap [n_col] entries are used
in both arrays.
Ax is optional; if Tx and/or Ax are not present (a (double *) NULL
pointer), then Ax is not computed. If present, Ax holds the
numerical values of the the real part of the sparse matrix A and Az
holds the imaginary parts. The nonzero pattern (row indices) for
column j is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)], and the
corresponding numerical values are stored in
Ax [(Ap [j]) ... (Ap [j+1]-1)]. The imaginary parts are stored in
Az [(Ap [j]) ... (Ap [j+1]-1)], for the complex versions.
If Az or Tz are NULL, then both real
and imaginary parts are returned in Ax[0..2*nz2-1], with Ax[2*k]
and Ax[2*k+1] being the real and imaginary part of the kth entry.
int Map [nz] ; Optional output argument.
If Map is present (a non-NULL pointer to an Int array of size nz), then
on output it holds the position of the triplets in the column-form
matrix. That is, suppose p = Map [k], and the k-th triplet is i=Ti[k],
j=Tj[k], and aij=Tx[k]. Then i=Ai[p], and aij will have been summed
into Ax[p] (or simply aij=Ax[p] if there were no duplicate entries also
in row i and column j). Also, Ap[j] <= p < Ap[j+1]. The Map array is
not computed if it is (Int *) NULL. The Map array is useful for
converting a subsequent triplet form matrix with the same pattern as the
first one, without calling this routine. If Ti and Tj do not change,
then Ap, and Ai can be reused from the prior call to
umfpack_*_triplet_to_col. You only need to recompute Ax (and Az for the
split complex version). This code excerpt properly sums up all
duplicate values (for the real version):
for (p = 0 ; p < Ap [n_col] ; p++) Ax [p] = 0 ;
for (k = 0 ; k < nz ; k++) Ax [Map [k]] += Tx [k] ;
This feature is useful (along with the reuse of the Symbolic object) if
you need to factorize a sequence of triplet matrices with identical
nonzero pattern (the order of the triplets in the Ti,Tj,Tx arrays must
also remain unchanged). It is faster than calling this routine for
each matrix, and requires no workspace.
*/

View File

@ -0,0 +1,172 @@
/* ========================================================================== */
/* === umfpack_wsolve ======================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
int umfpack_di_wsolve
(
int sys,
const int Ap [ ],
const int Ai [ ],
const double Ax [ ],
double X [ ],
const double B [ ],
void *Numeric,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO],
int Wi [ ],
double W [ ]
) ;
UF_long umfpack_dl_wsolve
(
UF_long sys,
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ],
double X [ ],
const double B [ ],
void *Numeric,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO],
UF_long Wi [ ],
double W [ ]
) ;
int umfpack_zi_wsolve
(
int sys,
const int Ap [ ],
const int Ai [ ],
const double Ax [ ], const double Az [ ],
double Xx [ ], double Xz [ ],
const double Bx [ ], const double Bz [ ],
void *Numeric,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO],
int Wi [ ],
double W [ ]
) ;
UF_long umfpack_zl_wsolve
(
UF_long sys,
const UF_long Ap [ ],
const UF_long Ai [ ],
const double Ax [ ], const double Az [ ],
double Xx [ ], double Xz [ ],
const double Bx [ ], const double Bz [ ],
void *Numeric,
const double Control [UMFPACK_CONTROL],
double Info [UMFPACK_INFO],
UF_long Wi [ ],
double W [ ]
) ;
/*
double int Syntax:
#include "umfpack.h"
void *Numeric ;
int status, *Ap, *Ai, *Wi, sys ;
double *B, *X, *Ax, *W, Info [UMFPACK_INFO], Control [UMFPACK_CONTROL] ;
status = umfpack_di_wsolve (sys, Ap, Ai, Ax, X, B, Numeric,
Control, Info, Wi, W) ;
double UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
UF_long status, *Ap, *Ai, *Wi, sys ;
double *B, *X, *Ax, *W, Info [UMFPACK_INFO], Control [UMFPACK_CONTROL] ;
status = umfpack_dl_wsolve (sys, Ap, Ai, Ax, X, B, Numeric,
Control, Info, Wi, W) ;
complex int Syntax:
#include "umfpack.h"
void *Numeric ;
int status, *Ap, *Ai, *Wi, sys ;
double *Bx, *Bz, *Xx, *Xz, *Ax, *Az, *W,
Info [UMFPACK_INFO], Control [UMFPACK_CONTROL] ;
status = umfpack_zi_wsolve (sys, Ap, Ai, Ax, Az, Xx, Xz, Bx, Bz, Numeric,
Control, Info, Wi, W) ;
complex UF_long Syntax:
#include "umfpack.h"
void *Numeric ;
UF_long status, *Ap, *Ai, *Wi, sys ;
double *Bx, *Bz, *Xx, *Xz, *Ax, *Az, *W,
Info [UMFPACK_INFO], Control [UMFPACK_CONTROL] ;
status = umfpack_zl_wsolve (sys, Ap, Ai, Ax, Az, Xx, Xz, Bx, Bz, Numeric,
Control, Info, Wi, W) ;
packed complex Syntax:
Same as above, except Az, Xz, and Bz are NULL.
Purpose:
Given LU factors computed by umfpack_*_numeric (PAQ=LU) and the
right-hand-side, B, solve a linear system for the solution X. Iterative
refinement is optionally performed. This routine is identical to
umfpack_*_solve, except that it does not dynamically allocate any workspace.
When you have many linear systems to solve, this routine is faster than
umfpack_*_solve, since the workspace (Wi, W) needs to be allocated only
once, prior to calling umfpack_*_wsolve.
Returns:
The status code is returned. See Info [UMFPACK_STATUS], below.
Arguments:
Int sys ; Input argument, not modified.
Int Ap [n+1] ; Input argument, not modified.
Int Ai [nz] ; Input argument, not modified.
double Ax [nz] ; Input argument, not modified.
Size 2*nz in packed complex case.
double X [n] ; Output argument.
double B [n] ; Input argument, not modified.
void *Numeric ; Input argument, not modified.
double Control [UMFPACK_CONTROL] ; Input argument, not modified.
double Info [UMFPACK_INFO] ; Output argument.
for complex versions:
double Az [nz] ; Input argument, not modified, imaginary part
double Xx [n] ; Output argument, real part.
Size 2*n in packed complex case.
double Xz [n] ; Output argument, imaginary part
double Bx [n] ; Input argument, not modified, real part.
Size 2*n in packed complex case.
double Bz [n] ; Input argument, not modified, imaginary part
The above arguments are identical to umfpack_*_solve, except that the
error code UMFPACK_ERROR_out_of_memory will not be returned in
Info [UMFPACK_STATUS], since umfpack_*_wsolve does not allocate any
memory.
Int Wi [n] ; Workspace.
double W [c*n] ; Workspace, where c is defined below.
The Wi and W arguments are workspace used by umfpack_*_wsolve. They
need not be initialized on input, and their contents are undefined on
output. The size of W depends on whether or not iterative refinement is
used, and which version (real or complex) is called. Iterative
refinement is performed if Ax=b, A'x=b, or A.'x=b is being solved,
Control [UMFPACK_IRSTEP] > 0, and A is nonsingular. The size of W is
given below:
no iter. with iter.
refinement refinement
umfpack_di_wsolve n 5*n
umfpack_dl_wsolve n 5*n
umfpack_zi_wsolve 4*n 10*n
umfpack_zl_wsolve 4*n 10*n
*/

View File

@ -0,0 +1,352 @@
## Process this file with automake to produce Makefile.in
#THIS LIBRARY IS VERY COMPLICATED TO BUILD
noinst_LTLIBRARIES = \
libUMFPACK_AMD.la \
libUMFPACK_global.la \
libUMFPACK_CONJ_DINT.la \
libUMFPACK_DOMAP_DINT.la \
libUMFPACK_DOVALUES_DINT.la \
libUMFPACK_DOMAP_DOVALUES_DINT.la \
libUMFPACK_DFIXQ_DINT.la \
libUMFPACK_DDROP_DINT.la \
libUMFPACK_DWSOLVE_DINT.la \
libUMFPACK_DINT.la \
libUMFPACK_ZINT.la \
libUMFPACK_CONJ_ZINT.la \
libUMFPACK_DOMAP_ZINT.la \
libUMFPACK_DOVALUES_ZINT.la \
libUMFPACK_DOMAP_DOVALUES_ZINT.la \
libUMFPACK_DFIXQ_ZINT.la \
libUMFPACK_DDROP_ZINT.la \
libUMFPACK_DWSOLVE_ZINT.la \
libUMFPACK.la
libUMFPACK_AMD_la_SOURCES = \
amd_1.c \
amd_2.c \
amd_aat.c \
amd_control.c \
amd_defaults.c \
amd_dump.c \
amd_global.c \
amd_info.c \
amd_order.c \
amd_postorder.c \
amd_post_tree.c \
amd_preprocess.c \
amd_valid.c
libUMFPACK_AMD_la_CPPFLAGS = -I$(top_srcdir)/src/include
libUMFPACK_global_la_SOURCES = \
umfpack_global.c \
umfpack_tictoc.c \
umfpack_timer.c \
umf_triplet.c
libUMFPACK_global_la_CPPFLAGS = -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_global_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_CONJ_DINT_la_SOURCES = \
umf_ltsolve.c \
umf_utsolve.c
libUMFPACK_CONJ_DINT_la_CPPFLAGS = -DDINT -DCONJUGATE_SOLVE -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_CONJ_DINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_DOMAP_DINT_la_SOURCES = \
umf_triplet.c
libUMFPACK_DOMAP_DINT_la_CPPFLAGS = -DDINT -DDO_MAP -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_DOMAP_DINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_DOVALUES_DINT_la_SOURCES = \
umf_triplet.c
libUMFPACK_DOVALUES_DINT_la_CPPFLAGS = -DDINT -DDO_VALUES -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_DOVALUES_DINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_DOMAP_DOVALUES_DINT_la_SOURCES = \
umf_triplet.c
libUMFPACK_DOMAP_DOVALUES_DINT_la_CPPFLAGS = -DDINT -DDO_MAP -DDO_VALUES -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_DOMAP_DOVALUES_DINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_DFIXQ_DINT_la_SOURCES = \
umf_assemble.c
libUMFPACK_DFIXQ_DINT_la_CPPFLAGS = -DDINT -DFIXQ -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_DFIXQ_DINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_DDROP_DINT_la_SOURCES = \
umf_store_lu.c
libUMFPACK_DDROP_DINT_la_CPPFLAGS = -DDINT -DDROP -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_DDROP_DINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_DWSOLVE_DINT_la_SOURCES = \
umfpack_solve.c
libUMFPACK_DWSOLVE_DINT_la_CPPFLAGS = -DDINT -DWSOLVE -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_DWSOLVE_DINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_DINT_la_SOURCES = \
umf_analyze.c \
umf_apply_order.c \
umf_assemble.c \
umf_blas3_update.c \
umf_build_tuples.c \
umf_cholmod.c \
umf_colamd.c \
umf_create_element.c \
umf_dump.c \
umf_extend_front.c \
umf_free.c \
umf_fsize.c \
umf_garbage_collection.c \
umf_get_memory.c \
umf_grow_front.c \
umf_init_front.c \
umf_is_permutation.c \
umf_kernel.c \
umf_kernel_init.c \
umf_kernel_wrapup.c \
umf_local_search.c \
umf_lsolve.c \
umf_ltsolve.c \
umf_malloc.c \
umf_mem_alloc_element.c \
umf_mem_alloc_head_block.c \
umf_mem_alloc_tail_block.c \
umf_mem_free_tail_block.c \
umf_mem_init_memoryspace.c \
umfpack_col_to_triplet.c \
umfpack_defaults.c \
umfpack_free_numeric.c \
umfpack_free_symbolic.c \
umfpack_get_determinant.c \
umfpack_get_lunz.c \
umfpack_get_numeric.c \
umfpack_get_symbolic.c \
umfpack_load_numeric.c \
umfpack_load_symbolic.c \
umfpack_numeric.c \
umfpack_qsymbolic.c \
umfpack_report_control.c \
umfpack_report_info.c \
umfpack_report_matrix.c \
umfpack_report_numeric.c \
umfpack_report_perm.c \
umfpack_report_status.c \
umfpack_report_symbolic.c \
umfpack_report_triplet.c \
umfpack_report_vector.c \
umfpack_save_numeric.c \
umfpack_save_symbolic.c \
umfpack_scale.c \
umfpack_solve.c \
umfpack_symbolic.c \
umfpack_transpose.c \
umfpack_triplet_to_col.c \
umf_realloc.c \
umf_report_perm.c \
umf_report_vector.c \
umf_row_search.c \
umf_scale.c \
umf_scale_column.c \
umf_set_stats.c \
umf_singletons.c \
umf_solve.c \
umf_start_front.c \
umf_store_lu.c \
umf_symbolic_usage.c \
umf_transpose.c \
umf_tuple_lengths.c \
umf_usolve.c \
umf_utsolve.c \
umf_valid_numeric.c \
umf_valid_symbolic.c
libUMFPACK_DINT_la_CPPFLAGS = -DDINT -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_DINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_ZINT_la_SOURCES = \
umf_assemble.c \
umf_blas3_update.c \
umf_build_tuples.c \
umf_create_element.c \
umf_dump.c \
umf_extend_front.c \
umf_garbage_collection.c \
umf_get_memory.c \
umf_init_front.c \
umf_is_permutation.c \
umf_kernel.c \
umf_kernel_init.c \
umf_kernel_wrapup.c \
umf_local_search.c \
umf_lsolve.c \
umf_ltsolve.c \
umf_mem_alloc_element.c \
umf_mem_alloc_head_block.c \
umf_mem_alloc_tail_block.c \
umf_mem_free_tail_block.c \
umf_mem_init_memoryspace.c \
umfpack_col_to_triplet.c \
umfpack_defaults.c \
umfpack_free_numeric.c \
umfpack_free_symbolic.c \
umfpack_get_determinant.c \
umfpack_get_lunz.c \
umfpack_get_numeric.c \
umfpack_get_symbolic.c \
umfpack_load_numeric.c \
umfpack_load_symbolic.c \
umfpack_numeric.c \
umfpack_qsymbolic.c \
umfpack_report_control.c \
umfpack_report_info.c \
umfpack_report_matrix.c \
umfpack_report_numeric.c \
umfpack_report_perm.c \
umfpack_report_status.c \
umfpack_report_symbolic.c \
umfpack_report_triplet.c \
umfpack_report_vector.c \
umfpack_save_numeric.c \
umfpack_save_symbolic.c \
umfpack_scale.c \
umfpack_solve.c \
umfpack_symbolic.c \
umfpack_transpose.c \
umfpack_triplet_to_col.c \
umf_report_vector.c \
umf_row_search.c \
umf_scale.c \
umf_scale_column.c \
umf_set_stats.c \
umf_solve.c \
umf_start_front.c \
umf_store_lu.c \
umf_symbolic_usage.c \
umf_transpose.c \
umf_tuple_lengths.c \
umf_usolve.c \
umf_utsolve.c \
umf_valid_numeric.c \
umf_valid_symbolic.c
libUMFPACK_ZINT_la_CPPFLAGS = -DZINT -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_ZINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_CONJ_ZINT_la_SOURCES = \
umf_ltsolve.c \
umf_utsolve.c
libUMFPACK_CONJ_ZINT_la_CPPFLAGS = -DZINT -DCONJUGATE_SOLVE -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_CONJ_ZINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_DOMAP_ZINT_la_SOURCES = \
umf_triplet.c
libUMFPACK_DOMAP_ZINT_la_CPPFLAGS = -DZINT -DDO_MAP -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_DOMAP_ZINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_DOVALUES_ZINT_la_SOURCES = \
umf_triplet.c
libUMFPACK_DOVALUES_ZINT_la_CPPFLAGS = -DZINT -DDO_VALUES -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_DOVALUES_ZINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_DOMAP_DOVALUES_ZINT_la_SOURCES = \
umf_triplet.c
libUMFPACK_DOMAP_DOVALUES_ZINT_la_CPPFLAGS = -DZINT -DDO_MAP -DDO_VALUES -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_DOMAP_DOVALUES_ZINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_DFIXQ_ZINT_la_SOURCES = \
umf_assemble.c
libUMFPACK_DFIXQ_ZINT_la_CPPFLAGS = -DZINT -DFIXQ -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_DFIXQ_ZINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_DDROP_ZINT_la_SOURCES = \
umf_store_lu.c
libUMFPACK_DDROP_ZINT_la_CPPFLAGS = -DZINT -DDROP -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_DDROP_ZINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_DWSOLVE_ZINT_la_SOURCES = \
umfpack_solve.c
libUMFPACK_DWSOLVE_ZINT_la_CPPFLAGS = -DZINT -DWSOLVE -DNCHOLMOD -I$(top_srcdir)/src/include
libUMFPACK_DWSOLVE_ZINT_la_LDFLAGS = -L/usr/lib/atlas-corei7sse3 -lf77blas -latlas
libUMFPACK_la_SOURCES = \
umfpacksmp.c
libUMFPACK_la_LIBADD = \
libUMFPACK_AMD.la \
libUMFPACK_global.la \
libUMFPACK_CONJ_DINT.la \
libUMFPACK_DOMAP_DINT.la \
libUMFPACK_DOVALUES_DINT.la \
libUMFPACK_DOMAP_DOVALUES_DINT.la \
libUMFPACK_DFIXQ_DINT.la \
libUMFPACK_DDROP_DINT.la \
libUMFPACK_DWSOLVE_DINT.la \
libUMFPACK_DINT.la \
libUMFPACK_ZINT.la \
libUMFPACK_CONJ_ZINT.la \
libUMFPACK_DOMAP_ZINT.la \
libUMFPACK_DOVALUES_ZINT.la \
libUMFPACK_DOMAP_DOVALUES_ZINT.la \
libUMFPACK_DFIXQ_ZINT.la \
libUMFPACK_DDROP_ZINT.la \
libUMFPACK_DWSOLVE_ZINT.la
MAINTAINERCLEANFILES = Makefile.in

181
src/maths/UMFPACK/amd_1.c Normal file
View File

@ -0,0 +1,181 @@
/* ========================================================================= */
/* === AMD_1 =============================================================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at 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_valid).
*/
#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) == AMD_OK) ;
/* 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) ;
}

1842
src/maths/UMFPACK/amd_2.c Normal file

File diff suppressed because it is too large Load Diff

185
src/maths/UMFPACK/amd_aat.c Normal file
View File

@ -0,0 +1,185 @@
/* ========================================================================= */
/* === AMD_aat ============================================================= */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at 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). Assumes the input
* matrix has no errors, with sorted columns and no duplicates
* (AMD_valid (n, n, Ap, Ai) must be AMD_OK, but this condition is not
* checked).
*/
#include "amd_internal.h"
GLOBAL size_t 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 ;
double sym ;
size_t nzaat ;
#ifndef NDEBUG
AMD_debug_init ("AMD AAT") ;
for (k = 0 ; k < n ; k++) Tp [k] = EMPTY ;
ASSERT (AMD_valid (n, n, Ap, Ai) == AMD_OK) ;
#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 = (2 * (double) 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) = %g\n",
(double) 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) ;
}

View File

@ -0,0 +1,64 @@
/* ========================================================================= */
/* === AMD_control ========================================================= */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at 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 version %d.%d.%d, %s: approximate minimum degree ordering\n"
" dense row parameter: %g\n", AMD_MAIN_VERSION, AMD_SUB_VERSION,
AMD_SUBSUB_VERSION, AMD_DATE, 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")) ;
}
else
{
PRINTF ((" aggressive absorption: no\n")) ;
}
PRINTF ((" size of AMD integer: %d\n\n", sizeof (Int))) ;
}

View File

@ -0,0 +1,38 @@
/* ========================================================================= */
/* === AMD_defaults ======================================================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at 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"
/* ========================================================================= */
/* === AMD defaults ======================================================== */
/* ========================================================================= */
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 ;
}
}

View File

@ -0,0 +1,180 @@
/* ========================================================================= */
/* === AMD_dump ============================================================ */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at 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) ;
AMD_DEBUG3 (("\nAMD dump, pfree: "ID"\n", pfree)) ;
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 + len <= 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 + len <= 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": \n", 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

View File

@ -0,0 +1,84 @@
/* ========================================================================= */
/* === amd_global ========================================================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
/* web: http://www.cise.ufl.edu/research/sparse/amd */
/* ------------------------------------------------------------------------- */
#include <stdlib.h>
#ifdef MATLAB_MEX_FILE
#include "mex.h"
#include "matrix.h"
#endif
#ifndef NULL
#define NULL 0
#endif
/* ========================================================================= */
/* === Default AMD memory manager ========================================== */
/* ========================================================================= */
/* The user can redefine these global pointers at run-time to change the memory
* manager used by AMD. AMD only uses malloc and free; realloc and calloc are
* include for completeness, in case another package wants to use the same
* memory manager as AMD.
*
* If compiling as a MATLAB mexFunction, the default memory manager is mxMalloc.
* You can also compile AMD as a standard ANSI-C library and link a mexFunction
* against it, and then redefine these pointers at run-time, in your
* mexFunction.
*
* If -DNMALLOC is defined at compile-time, no memory manager is specified at
* compile-time. You must then define these functions at run-time, before
* calling AMD, for AMD to work properly.
*/
#ifndef NMALLOC
#ifdef MATLAB_MEX_FILE
/* MATLAB mexFunction: */
void *(*amd_malloc) (size_t) = mxMalloc ;
void (*amd_free) (void *) = mxFree ;
void *(*amd_realloc) (void *, size_t) = mxRealloc ;
void *(*amd_calloc) (size_t, size_t) = mxCalloc ;
#else
/* standard ANSI-C: */
void *(*amd_malloc) (size_t) = malloc ;
void (*amd_free) (void *) = free ;
void *(*amd_realloc) (void *, size_t) = realloc ;
void *(*amd_calloc) (size_t, size_t) = calloc ;
#endif
#else
/* no memory manager defined at compile-time; you MUST define one at run-time */
void *(*amd_malloc) (size_t) = NULL ;
void (*amd_free) (void *) = NULL ;
void *(*amd_realloc) (void *, size_t) = NULL ;
void *(*amd_calloc) (size_t, size_t) = NULL ;
#endif
/* ========================================================================= */
/* === Default AMD printf routine ========================================== */
/* ========================================================================= */
/* The user can redefine this global pointer at run-time to change the printf
* routine used by AMD. If NULL, no printing occurs.
*
* If -DNPRINT is defined at compile-time, stdio.h is not included. Printing
* can then be enabled at run-time by setting amd_printf to a non-NULL function.
*/
#ifndef NPRINT
#ifdef MATLAB_MEX_FILE
int (*amd_printf) (const char *, ...) = mexPrintf ;
#else
#include <stdio.h>
int (*amd_printf) (const char *, ...) = printf ;
#endif
#else
int (*amd_printf) (const char *, ...) = NULL ;
#endif

View File

@ -0,0 +1,120 @@
/* ========================================================================= */
/* === AMD_info ============================================================ */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at 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 ;
PRINTF (("\nAMD version %d.%d.%d, %s, results:\n",
AMD_MAIN_VERSION, AMD_SUB_VERSION, AMD_SUBSUB_VERSION, AMD_DATE)) ;
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 ((" 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 if (Info [AMD_STATUS] == AMD_OK_BUT_JUMBLED)
{
PRINTF (("OK, but jumbled\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)) ;
}
}

View File

@ -0,0 +1,350 @@
/* ========================================================================= */
/* === amd_internal.h ====================================================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at 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 (it is included in UMFPACK, however). All others
* should use amd.h instead.
*
* The following compile-time definitions affect how AMD is compiled.
*
* -DNPRINT
*
* Disable all printing. stdio.h will not be included. Printing can
* be re-enabled at run-time by setting the global pointer amd_printf
* to printf (or mexPrintf for a MATLAB mexFunction).
*
* -DNMALLOC
*
* No memory manager is defined at compile-time. You MUST define the
* function pointers amd_malloc, amd_free, amd_realloc, and
* amd_calloc at run-time for AMD to work properly.
*/
/* ========================================================================= */
/* === NDEBUG ============================================================== */
/* ========================================================================= */
/*
* Turning on debugging takes some work (see below). If you do not edit this
* file, then debugging is always turned off, regardless of whether or not
* -DNDEBUG is specified in your compiler options.
*
* If AMD is being compiled as a mexFunction, then MATLAB_MEX_FILE is defined,
* and mxAssert is used instead of assert. If debugging is not enabled, no
* MATLAB include files or functions are used. Thus, the AMD library libamd.a
* can be safely used in either a stand-alone C program or in another
* mexFunction, without any change.
*/
/*
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: size_t, malloc, free, realloc, and calloc */
#include <stdlib.h>
#if !defined(NPRINT) || !defined(NDEBUG)
/* from stdio.h: printf. Not included if NPRINT is defined at compile time.
* fopen and fscanf are used when debugging. */
#include <stdio.h>
#endif
/* from limits.h: INT_MAX and LONG_MAX */
#include <limits.h>
/* from math.h: sqrt */
#include <math.h>
/* ------------------------------------------------------------------------- */
/* MATLAB include files (only if being used in or via MATLAB) */
/* ------------------------------------------------------------------------- */
#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 <types.h>. */
/* 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
/* largest value of size_t */
#ifndef SIZE_T_MAX
#define SIZE_T_MAX ((size_t) (-1))
#endif
/* ------------------------------------------------------------------------- */
/* integer type for AMD: int or UF_long */
/* ------------------------------------------------------------------------- */
/* define UF_long */
#include <ngspice/UFconfig.h>
#if defined (DLONG) || defined (ZLONG)
#define Int UF_long
#define ID UF_long_id
#define Int_MAX UF_long_max
#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_preprocess amd_l_preprocess
#else
#define Int int
#define ID "%d"
#define Int_MAX INT_MAX
#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_preprocess amd_preprocess
#endif
/* ========================================================================= */
/* === PRINTF macro ======================================================== */
/* ========================================================================= */
/* All output goes through the PRINTF macro. */
#define PRINTF(params) { if (amd_printf != NULL) (void) amd_printf params ; }
/* ------------------------------------------------------------------------- */
/* AMD routine definitions (user-callable) */
/* ------------------------------------------------------------------------- */
#include <ngspice/amd.h>
/* ------------------------------------------------------------------------- */
/* AMD routine definitions (not user-callable) */
/* ------------------------------------------------------------------------- */
GLOBAL size_t 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_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_preprocess
(
Int n,
const Int Ap [ ],
const Int Ai [ ],
Int Rp [ ],
Int Ri [ ],
Int W [ ],
Int Flag [ ]
) ;
/* ------------------------------------------------------------------------- */
/* debugging definitions */
/* ------------------------------------------------------------------------- */
#ifndef NDEBUG
/* from assert.h: assert macro */
#include <assert.h>
#ifndef EXTERN
#define EXTERN extern
#endif
EXTERN 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
/* Use mxAssert if AMD is compiled into a mexFunction */
#ifdef MATLAB_MEX_FILE
#define ASSERT(expression) (mxAssert ((expression), ""))
#else
#define ASSERT(expression) (assert (expression))
#endif
#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
/* no debugging */
#define ASSERT(expression)
#define AMD_DEBUG0(params)
#define AMD_DEBUG1(params)
#define AMD_DEBUG2(params)
#define AMD_DEBUG3(params)
#define AMD_DEBUG4(params)
#endif

View File

@ -0,0 +1,200 @@
/* ========================================================================= */
/* === AMD_order =========================================================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at 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"
/* ========================================================================= */
/* === AMD_order =========================================================== */
/* ========================================================================= */
GLOBAL Int AMD_order
(
Int n,
const Int Ap [ ],
const Int Ai [ ],
Int P [ ],
double Control [ ],
double Info [ ]
)
{
Int *Len, *S, nz, i, *Pinv, info, status, *Rp, *Ri, *Cp, *Ci, ok ;
size_t nzaat, slen ;
double mem = 0 ;
#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) ;
}
/* check if n or nz will cause size_t overflow */
if (((size_t) n) >= SIZE_T_MAX / sizeof (Int)
|| ((size_t) nz) >= SIZE_T_MAX / sizeof (Int))
{
if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
return (AMD_OUT_OF_MEMORY) ; /* problem too large */
}
/* check the input matrix: AMD_OK, AMD_INVALID, or AMD_OK_BUT_JUMBLED */
status = AMD_valid (n, n, Ap, Ai) ;
if (status == AMD_INVALID)
{
if (info) Info [AMD_STATUS] = AMD_INVALID ;
return (AMD_INVALID) ; /* matrix is invalid */
}
/* allocate two size-n integer workspaces */
Len = amd_malloc (n * sizeof (Int)) ;
Pinv = amd_malloc (n * sizeof (Int)) ;
mem += n ;
mem += n ;
if (!Len || !Pinv)
{
/* :: out of memory :: */
amd_free (Len) ;
amd_free (Pinv) ;
if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
return (AMD_OUT_OF_MEMORY) ;
}
if (status == AMD_OK_BUT_JUMBLED)
{
/* sort the input matrix and remove duplicate entries */
AMD_DEBUG1 (("Matrix is jumbled\n")) ;
Rp = amd_malloc ((n+1) * sizeof (Int)) ;
Ri = amd_malloc (MAX (nz,1) * sizeof (Int)) ;
mem += (n+1) ;
mem += MAX (nz,1) ;
if (!Rp || !Ri)
{
/* :: out of memory :: */
amd_free (Rp) ;
amd_free (Ri) ;
amd_free (Len) ;
amd_free (Pinv) ;
if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
return (AMD_OUT_OF_MEMORY) ;
}
/* use Len and Pinv as workspace to create R = A' */
AMD_preprocess (n, Ap, Ai, Rp, Ri, Len, Pinv) ;
Cp = Rp ;
Ci = Ri ;
}
else
{
/* order the input matrix as-is. No need to compute R = A' first */
Rp = NULL ;
Ri = NULL ;
Cp = (Int *) Ap ;
Ci = (Int *) Ai ;
}
/* --------------------------------------------------------------------- */
/* determine the symmetry and count off-diagonal nonzeros in A+A' */
/* --------------------------------------------------------------------- */
nzaat = AMD_aat (n, Cp, Ci, Len, P, Info) ;
AMD_DEBUG1 (("nzaat: %g\n", (double) nzaat)) ;
ASSERT ((MAX (nz-n, 0) <= nzaat) && (nzaat <= 2 * (size_t) nz)) ;
/* --------------------------------------------------------------------- */
/* allocate workspace for matrix, elbow room, and 6 size-n vectors */
/* --------------------------------------------------------------------- */
S = NULL ;
slen = nzaat ; /* space for matrix */
ok = ((slen + nzaat/5) >= slen) ; /* check for size_t overflow */
slen += nzaat/5 ; /* add elbow room */
for (i = 0 ; ok && i < 7 ; i++)
{
ok = ((slen + n) > slen) ; /* check for size_t overflow */
slen += n ; /* size-n elbow room, 6 size-n work */
}
mem += slen ;
ok = ok && (slen < SIZE_T_MAX / sizeof (Int)) ; /* check for overflow */
ok = ok && (slen < Int_MAX) ; /* S[i] for Int i must be OK */
if (ok)
{
S = amd_malloc (slen * sizeof (Int)) ;
}
AMD_DEBUG1 (("slen %g\n", (double) slen)) ;
if (!S)
{
/* :: out of memory :: (or problem too large) */
amd_free (Rp) ;
amd_free (Ri) ;
amd_free (Len) ;
amd_free (Pinv) ;
if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
return (AMD_OUT_OF_MEMORY) ;
}
if (info)
{
/* memory usage, in bytes. */
Info [AMD_MEMORY] = mem * sizeof (Int) ;
}
/* --------------------------------------------------------------------- */
/* order the matrix */
/* --------------------------------------------------------------------- */
AMD_1 (n, Cp, Ci, P, Pinv, Len, slen, S, Control, Info) ;
/* --------------------------------------------------------------------- */
/* free the workspace */
/* --------------------------------------------------------------------- */
amd_free (Rp) ;
amd_free (Ri) ;
amd_free (Len) ;
amd_free (Pinv) ;
amd_free (S) ;
if (info) Info [AMD_STATUS] = status ;
return (status) ; /* successful ordering */
}

View File

@ -0,0 +1,121 @@
/* ========================================================================= */
/* === AMD_post_tree ======================================================= */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at 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) ;
}

View File

@ -0,0 +1,207 @@
/* ========================================================================= */
/* === AMD_postorder ======================================================= */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at 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
) ;
}
}
}

View File

@ -0,0 +1,119 @@
/* ========================================================================= */
/* === AMD_preprocess ====================================================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at 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. The input matrix can have
* duplicate entries and/or unsorted columns (AMD_valid (n,Ap,Ai) must not be
* AMD_INVALID).
*
* This input condition is NOT checked. This routine is not user-callable.
*/
#include "amd_internal.h"
/* ========================================================================= */
/* === AMD_preprocess ====================================================== */
/* ========================================================================= */
/* AMD_preprocess does not check its input for errors or allocate workspace.
* On input, the condition (AMD_valid (n,n,Ap,Ai) != AMD_INVALID) must hold.
*/
GLOBAL void AMD_preprocess
(
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 ;
ASSERT (AMD_valid (n, n, Ap, Ai) != AMD_INVALID) ;
/* --------------------------------------------------------------------- */
/* 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
ASSERT (AMD_valid (n, n, Rp, Ri) == AMD_OK) ;
for (j = 0 ; j < n ; j++)
{
ASSERT (W [j] == Rp [j+1]) ;
}
#endif
}

View File

@ -0,0 +1,93 @@
/* ========================================================================= */
/* === AMD_valid =========================================================== */
/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/* AMD, Copyright (c) Timothy A. Davis, */
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
/* email: davis at 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.
* Ai [0 ... nz-1] must be in the range 0 to n_row-1.
*
* If any of the above conditions hold, AMD_INVALID is returned. If the
* following condition holds, AMD_OK_BUT_JUMBLED is returned (a warning,
* not an error):
*
* row indices in Ai [Ap [j] ... Ap [j+1]-1] are not sorted in ascending
* order, and/or duplicate entries exist.
*
* Otherwise, AMD_OK is returned.
*
* In v1.2 and earlier, this function returned TRUE if the matrix was valid
* (now returns AMD_OK), or FALSE otherwise (now returns AMD_INVALID or
* AMD_OK_BUT_JUMBLED).
*/
#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, result = AMD_OK ;
if (n_row < 0 || n_col < 0 || Ap == NULL || Ai == NULL)
{
return (AMD_INVALID) ;
}
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 (AMD_INVALID) ;
}
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 (AMD_INVALID) ;
}
ilast = EMPTY ;
for (p = p1 ; p < p2 ; p++)
{
i = Ai [p] ;
AMD_DEBUG3 (("row: "ID"\n", i)) ;
if (i < 0 || i >= n_row)
{
/* row index out of range */
AMD_DEBUG0 (("index out of range, col "ID" row "ID"\n", j, i));
return (AMD_INVALID) ;
}
if (i <= ilast)
{
/* row index unsorted, or duplicate entry present */
AMD_DEBUG1 (("index unsorted/dupl col "ID" row "ID"\n", j, i));
result = AMD_OK_BUT_JUMBLED ;
}
ilast = i ;
}
}
return (result) ;
}

View File

@ -0,0 +1,456 @@
/* ========================================================================== */
/* === Include/cholmod_blas.h =============================================== */
/* ========================================================================== */
/* -----------------------------------------------------------------------------
* CHOLMOD/Include/cholmod_blas.h.
* Copyright (C) 2005-2006, Univ. of Florida. Author: Timothy A. Davis
* CHOLMOD/Include/cholmod_blas.h is licensed under Version 2.1 of the GNU
* Lesser General Public License. See lesser.txt for a text of the license.
* CHOLMOD is also available under other licenses; contact authors for details.
* http://www.cise.ufl.edu/research/sparse
* -------------------------------------------------------------------------- */
/* This does not need to be included in the user's program. */
#ifndef CHOLMOD_BLAS_H
#define CHOLMOD_BLAS_H
/* ========================================================================== */
/* === Architecture ========================================================= */
/* ========================================================================== */
#if defined (__sun) || defined (MSOL2) || defined (ARCH_SOL2)
#define CHOLMOD_SOL2
#define CHOLMOD_ARCHITECTURE "Sun Solaris"
#elif defined (__sgi) || defined (MSGI) || defined (ARCH_SGI)
#define CHOLMOD_SGI
#define CHOLMOD_ARCHITECTURE "SGI Irix"
#elif defined (__linux) || defined (MGLNX86) || defined (ARCH_GLNX86)
#define CHOLMOD_LINUX
#define CHOLMOD_ARCHITECTURE "Linux"
#elif defined (__APPLE__)
#define CHOLMOD_MAC
#define CHOLMOD_ARCHITECTURE "Mac"
#elif defined (_AIX) || defined (MIBM_RS) || defined (ARCH_IBM_RS)
#define CHOLMOD_AIX
#define CHOLMOD_ARCHITECTURE "IBM AIX"
/* recent reports from IBM AIX seem to indicate that this is not needed: */
/* #define BLAS_NO_UNDERSCORE */
#elif defined (__alpha) || defined (MALPHA) || defined (ARCH_ALPHA)
#define CHOLMOD_ALPHA
#define CHOLMOD_ARCHITECTURE "Compaq Alpha"
#elif defined (_WIN32) || defined (WIN32) || defined (_WIN64) || defined (WIN64)
#if defined (__MINGW32__) || defined (__MINGW32__)
#define CHOLMOD_MINGW
#elif defined (__CYGWIN32__) || defined (__CYGWIN32__)
#define CHOLMOD_CYGWIN
#else
#define CHOLMOD_WINDOWS
#define BLAS_NO_UNDERSCORE
#endif
#define CHOLMOD_ARCHITECTURE "Microsoft Windows"
#elif defined (__hppa) || defined (__hpux) || defined (MHPUX) || defined (ARCH_HPUX)
#define CHOLMOD_HP
#define CHOLMOD_ARCHITECTURE "HP Unix"
#define BLAS_NO_UNDERSCORE
#elif defined (__hp700) || defined (MHP700) || defined (ARCH_HP700)
#define CHOLMOD_HP
#define CHOLMOD_ARCHITECTURE "HP 700 Unix"
#define BLAS_NO_UNDERSCORE
#else
/* If the architecture is unknown, and you call the BLAS, you may need to */
/* define BLAS_BY_VALUE, BLAS_NO_UNDERSCORE, and/or BLAS_CHAR_ARG yourself. */
#define CHOLMOD_ARCHITECTURE "unknown"
#endif
/* ========================================================================== */
/* === BLAS and LAPACK names ================================================ */
/* ========================================================================== */
/* Prototypes for the various versions of the BLAS. */
/* Determine if the 64-bit Sun Performance BLAS is to be used */
#if defined(CHOLMOD_SOL2) && !defined(NSUNPERF) && defined(BLAS64)
#define SUN64
#endif
#ifdef SUN64
#define BLAS_DTRSV dtrsv_64_
#define BLAS_DGEMV dgemv_64_
#define BLAS_DTRSM dtrsm_64_
#define BLAS_DGEMM dgemm_64_
#define BLAS_DSYRK dsyrk_64_
#define BLAS_DGER dger_64_
#define BLAS_DSCAL dscal_64_
#define LAPACK_DPOTRF dpotrf_64_
#define BLAS_ZTRSV ztrsv_64_
#define BLAS_ZGEMV zgemv_64_
#define BLAS_ZTRSM ztrsm_64_
#define BLAS_ZGEMM zgemm_64_
#define BLAS_ZHERK zherk_64_
#define BLAS_ZGER zgeru_64_
#define BLAS_ZSCAL zscal_64_
#define LAPACK_ZPOTRF zpotrf_64_
#elif defined (BLAS_NO_UNDERSCORE)
#define BLAS_DTRSV dtrsv
#define BLAS_DGEMV dgemv
#define BLAS_DTRSM dtrsm
#define BLAS_DGEMM dgemm
#define BLAS_DSYRK dsyrk
#define BLAS_DGER dger
#define BLAS_DSCAL dscal
#define LAPACK_DPOTRF dpotrf
#define BLAS_ZTRSV ztrsv
#define BLAS_ZGEMV zgemv
#define BLAS_ZTRSM ztrsm
#define BLAS_ZGEMM zgemm
#define BLAS_ZHERK zherk
#define BLAS_ZGER zgeru
#define BLAS_ZSCAL zscal
#define LAPACK_ZPOTRF zpotrf
#else
#define BLAS_DTRSV dtrsv_
#define BLAS_DGEMV dgemv_
#define BLAS_DTRSM dtrsm_
#define BLAS_DGEMM dgemm_
#define BLAS_DSYRK dsyrk_
#define BLAS_DGER dger_
#define BLAS_DSCAL dscal_
#define LAPACK_DPOTRF dpotrf_
#define BLAS_ZTRSV ztrsv_
#define BLAS_ZGEMV zgemv_
#define BLAS_ZTRSM ztrsm_
#define BLAS_ZGEMM zgemm_
#define BLAS_ZHERK zherk_
#define BLAS_ZGER zgeru_
#define BLAS_ZSCAL zscal_
#define LAPACK_ZPOTRF zpotrf_
#endif
/* ========================================================================== */
/* === BLAS and LAPACK integer arguments ==================================== */
/* ========================================================================== */
/* Compile CHOLMOD, UMFPACK, and SPQR with -DBLAS64 if you have a BLAS that
* uses 64-bit integers */
#if defined (LONGBLAS) || defined (BLAS64)
#define BLAS_INT UF_long
#else
#define BLAS_INT int
#endif
/* If the BLAS integer is smaller than the basic CHOLMOD integer, then we need
* to check for integer overflow when converting from Int to BLAS_INT. If
* any integer overflows, the externally-defined BLAS_OK variable is
* set to FALSE. BLAS_OK should be set to TRUE before calling any
* BLAS_* macro.
*/
#define CHECK_BLAS_INT (sizeof (BLAS_INT) < sizeof (Int))
#define EQ(K,k) (((BLAS_INT) K) == ((Int) k))
/* ========================================================================== */
/* === BLAS and LAPACK prototypes and macros ================================ */
/* ========================================================================== */
void BLAS_DGEMV (char *trans, BLAS_INT *m, BLAS_INT *n, double *alpha,
double *A, BLAS_INT *lda, double *X, BLAS_INT *incx, double *beta,
double *Y, BLAS_INT *incy) ;
#define BLAS_dgemv(trans,m,n,alpha,A,lda,X,incx,beta,Y,incy) \
{ \
BLAS_INT M = m, N = n, LDA = lda, INCX = incx, INCY = incy ; \
if (CHECK_BLAS_INT && !(EQ (M,m) && EQ (N,n) && EQ (LDA,lda) && \
EQ (INCX,incx) && EQ (INCY,incy))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
BLAS_DGEMV (trans, &M, &N, alpha, A, &LDA, X, &INCX, beta, Y, &INCY) ; \
} \
}
void BLAS_ZGEMV (char *trans, BLAS_INT *m, BLAS_INT *n, double *alpha,
double *A, BLAS_INT *lda, double *X, BLAS_INT *incx, double *beta,
double *Y, BLAS_INT *incy) ;
#define BLAS_zgemv(trans,m,n,alpha,A,lda,X,incx,beta,Y,incy) \
{ \
BLAS_INT M = m, N = n, LDA = lda, INCX = incx, INCY = incy ; \
if (CHECK_BLAS_INT && !(EQ (M,m) && EQ (N,n) && EQ (LDA,lda) && \
EQ (INCX,incx) && EQ (INCY,incy))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
BLAS_ZGEMV (trans, &M, &N, alpha, A, &LDA, X, &INCX, beta, Y, &INCY) ; \
} \
}
void BLAS_DTRSV (char *uplo, char *trans, char *diag, BLAS_INT *n, double *A,
BLAS_INT *lda, double *X, BLAS_INT *incx) ;
#define BLAS_dtrsv(uplo,trans,diag,n,A,lda,X,incx) \
{ \
BLAS_INT N = n, LDA = lda, INCX = incx ; \
if (CHECK_BLAS_INT && !(EQ (N,n) && EQ (LDA,lda) && EQ (INCX,incx))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
BLAS_DTRSV (uplo, trans, diag, &N, A, &LDA, X, &INCX) ; \
} \
}
void BLAS_ZTRSV (char *uplo, char *trans, char *diag, BLAS_INT *n, double *A,
BLAS_INT *lda, double *X, BLAS_INT *incx) ;
#define BLAS_ztrsv(uplo,trans,diag,n,A,lda,X,incx) \
{ \
BLAS_INT N = n, LDA = lda, INCX = incx ; \
if (CHECK_BLAS_INT && !(EQ (N,n) && EQ (LDA,lda) && EQ (INCX,incx))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
BLAS_ZTRSV (uplo, trans, diag, &N, A, &LDA, X, &INCX) ; \
} \
}
void BLAS_DTRSM (char *side, char *uplo, char *transa, char *diag, BLAS_INT *m,
BLAS_INT *n, double *alpha, double *A, BLAS_INT *lda, double *B,
BLAS_INT *ldb) ;
#define BLAS_dtrsm(side,uplo,transa,diag,m,n,alpha,A,lda,B,ldb) \
{ \
BLAS_INT M = m, N = n, LDA = lda, LDB = ldb ; \
if (CHECK_BLAS_INT && !(EQ (M,m) && EQ (N,n) && EQ (LDA,lda) && \
EQ (LDB,ldb))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
BLAS_DTRSM (side, uplo, transa, diag, &M, &N, alpha, A, &LDA, B, &LDB);\
} \
}
void BLAS_ZTRSM (char *side, char *uplo, char *transa, char *diag, BLAS_INT *m,
BLAS_INT *n, double *alpha, double *A, BLAS_INT *lda, double *B,
BLAS_INT *ldb) ;
#define BLAS_ztrsm(side,uplo,transa,diag,m,n,alpha,A,lda,B,ldb) \
{ \
BLAS_INT M = m, N = n, LDA = lda, LDB = ldb ; \
if (CHECK_BLAS_INT && !(EQ (M,m) && EQ (N,n) && EQ (LDA,lda) && \
EQ (LDB,ldb))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
BLAS_ZTRSM (side, uplo, transa, diag, &M, &N, alpha, A, &LDA, B, &LDB);\
} \
}
void BLAS_DGEMM (char *transa, char *transb, BLAS_INT *m, BLAS_INT *n,
BLAS_INT *k, double *alpha, double *A, BLAS_INT *lda, double *B,
BLAS_INT *ldb, double *beta, double *C, BLAS_INT *ldc) ;
#define BLAS_dgemm(transa,transb,m,n,k,alpha,A,lda,B,ldb,beta,C,ldc) \
{ \
BLAS_INT M = m, N = n, K = k, LDA = lda, LDB = ldb, LDC = ldc ; \
if (CHECK_BLAS_INT && !(EQ (M,m) && EQ (N,n) && EQ (K,k) && \
EQ (LDA,lda) && EQ (LDB,ldb) && EQ (LDC,ldc))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
BLAS_DGEMM (transa, transb, &M, &N, &K, alpha, A, &LDA, B, &LDB, beta, \
C, &LDC) ; \
} \
}
void BLAS_ZGEMM (char *transa, char *transb, BLAS_INT *m, BLAS_INT *n,
BLAS_INT *k, double *alpha, double *A, BLAS_INT *lda, double *B,
BLAS_INT *ldb, double *beta, double *C, BLAS_INT *ldc) ;
#define BLAS_zgemm(transa,transb,m,n,k,alpha,A,lda,B,ldb,beta,C,ldc) \
{ \
BLAS_INT M = m, N = n, K = k, LDA = lda, LDB = ldb, LDC = ldc ; \
if (CHECK_BLAS_INT && !(EQ (M,m) && EQ (N,n) && EQ (K,k) && \
EQ (LDA,lda) && EQ (LDB,ldb) && EQ (LDC,ldc))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
BLAS_ZGEMM (transa, transb, &M, &N, &K, alpha, A, &LDA, B, &LDB, beta, \
C, &LDC) ; \
} \
}
void BLAS_DSYRK (char *uplo, char *trans, BLAS_INT *n, BLAS_INT *k,
double *alpha, double *A, BLAS_INT *lda, double *beta, double *C,
BLAS_INT *ldc) ;
#define BLAS_dsyrk(uplo,trans,n,k,alpha,A,lda,beta,C,ldc) \
{ \
BLAS_INT N = n, K = k, LDA = lda, LDC = ldc ; \
if (CHECK_BLAS_INT && !(EQ (N,n) && EQ (K,k) && EQ (LDA,lda) && \
EQ (LDC,ldc))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
BLAS_DSYRK (uplo, trans, &N, &K, alpha, A, &LDA, beta, C, &LDC) ; \
} \
} \
void BLAS_ZHERK (char *uplo, char *trans, BLAS_INT *n, BLAS_INT *k,
double *alpha, double *A, BLAS_INT *lda, double *beta, double *C,
BLAS_INT *ldc) ;
#define BLAS_zherk(uplo,trans,n,k,alpha,A,lda,beta,C,ldc) \
{ \
BLAS_INT N = n, K = k, LDA = lda, LDC = ldc ; \
if (CHECK_BLAS_INT && !(EQ (N,n) && EQ (K,k) && EQ (LDA,lda) && \
EQ (LDC,ldc))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
BLAS_ZHERK (uplo, trans, &N, &K, alpha, A, &LDA, beta, C, &LDC) ; \
} \
} \
void LAPACK_DPOTRF (char *uplo, BLAS_INT *n, double *A, BLAS_INT *lda,
BLAS_INT *info) ;
#define LAPACK_dpotrf(uplo,n,A,lda,info) \
{ \
BLAS_INT N = n, LDA = lda, INFO = 1 ; \
if (CHECK_BLAS_INT && !(EQ (N,n) && EQ (LDA,lda))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
LAPACK_DPOTRF (uplo, &N, A, &LDA, &INFO) ; \
} \
info = INFO ; \
}
void LAPACK_ZPOTRF (char *uplo, BLAS_INT *n, double *A, BLAS_INT *lda,
BLAS_INT *info) ;
#define LAPACK_zpotrf(uplo,n,A,lda,info) \
{ \
BLAS_INT N = n, LDA = lda, INFO = 1 ; \
if (CHECK_BLAS_INT && !(EQ (N,n) && EQ (LDA,lda))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
LAPACK_ZPOTRF (uplo, &N, A, &LDA, &INFO) ; \
} \
info = INFO ; \
}
/* ========================================================================== */
void BLAS_DSCAL (BLAS_INT *n, double *alpha, double *Y, BLAS_INT *incy) ;
#define BLAS_dscal(n,alpha,Y,incy) \
{ \
BLAS_INT N = n, INCY = incy ; \
if (CHECK_BLAS_INT && !(EQ (N,n) && EQ (INCY,incy))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
BLAS_DSCAL (&N, alpha, Y, &INCY) ; \
} \
}
void BLAS_ZSCAL (BLAS_INT *n, double *alpha, double *Y, BLAS_INT *incy) ;
#define BLAS_zscal(n,alpha,Y,incy) \
{ \
BLAS_INT N = n, INCY = incy ; \
if (CHECK_BLAS_INT && !(EQ (N,n) && EQ (INCY,incy))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
BLAS_ZSCAL (&N, alpha, Y, &INCY) ; \
} \
}
void BLAS_DGER (BLAS_INT *m, BLAS_INT *n, double *alpha,
double *X, BLAS_INT *incx, double *Y, BLAS_INT *incy,
double *A, BLAS_INT *lda) ;
#define BLAS_dger(m,n,alpha,X,incx,Y,incy,A,lda) \
{ \
BLAS_INT M = m, N = n, LDA = lda, INCX = incx, INCY = incy ; \
if (CHECK_BLAS_INT && !(EQ (M,m) && EQ (N,n) && EQ (LDA,lda) && \
EQ (INCX,incx) && EQ (INCY,incy))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
BLAS_DGER (&M, &N, alpha, X, &INCX, Y, &INCY, A, &LDA) ; \
} \
}
void BLAS_ZGER (BLAS_INT *m, BLAS_INT *n, double *alpha,
double *X, BLAS_INT *incx, double *Y, BLAS_INT *incy,
double *A, BLAS_INT *lda) ;
#define BLAS_zgeru(m,n,alpha,X,incx,Y,incy,A,lda) \
{ \
BLAS_INT M = m, N = n, LDA = lda, INCX = incx, INCY = incy ; \
if (CHECK_BLAS_INT && !(EQ (M,m) && EQ (N,n) && EQ (LDA,lda) && \
EQ (INCX,incx) && EQ (INCY,incy))) \
{ \
BLAS_OK = FALSE ; \
} \
if (!CHECK_BLAS_INT || BLAS_OK) \
{ \
BLAS_ZGER (&M, &N, alpha, X, &INCX, Y, &INCY, A, &LDA) ; \
} \
}
#endif

View File

@ -0,0 +1,705 @@
/* ========================================================================== */
/* === UMF_analyze ========================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/*
Symbolic LL' factorization of A'*A, to get upper bounds on the size of
L and U for LU = PAQ, and to determine the frontal matrices and
(supernodal) column elimination tree. No fill-reducing column pre-ordering
is used.
Returns TRUE if successful, FALSE if out of memory. UMF_analyze can only
run out of memory if anzmax (which is Ap [n_row]) is too small.
Uses workspace of size O(nonzeros in A). On input, the matrix A is
stored in row-form at the tail end of Ai. It is destroyed on output.
The rows of A must be sorted by increasing first nonzero column.
The matrix is assumed to be valid.
Empty rows and columns have already been removed.
*/
#include "umf_internal.h"
#include "umf_analyze.h"
#include "umf_apply_order.h"
#include "umf_fsize.h"
/* ========================================================================== */
GLOBAL Int UMF_analyze
(
Int n_row, /* A is n_row-by-n_col */
Int n_col,
Int Ai [ ], /* Ai [Ap [0]..Ap[n_row]-1]: column indices */
/* destroyed on output. Note that this is NOT the */
/* user's Ai that was passed to UMFPACK_*symbolic */
/* size of Ai, Ap [n_row] = anzmax >= anz + n_col */
/* Ap [0] must be => n_col. The space to the */
/* front of Ai is used as workspace. */
Int Ap [ ], /* of size MAX (n_row, n_col) + 1 */
/* Ap [0..n_row]: row pointers */
/* Row i is in Ai [Ap [i] ... Ap [i+1]-1] */
/* rows must have smallest col first, or be */
/* in sorted form. Used as workspace of size n_col */
/* and destroyed. */
/* Note that this is NOT the */
/* user's Ap that was passed to UMFPACK_*symbolic */
Int Up [ ], /* workspace of size n_col, and output column perm.
* for column etree postorder. */
Int fixQ,
/* temporary workspaces: */
Int W [ ], /* W [0..n_col-1] */
Int Link [ ], /* Link [0..n_col-1] */
/* output: information about each frontal matrix: */
Int Front_ncols [ ], /* size n_col */
Int Front_nrows [ ], /* of size n_col */
Int Front_npivcol [ ], /* of size n_col */
Int Front_parent [ ], /* of size n_col */
Int *nfr_out,
Int *p_ncompactions /* number of compactions in UMF_analyze */
)
{
/* ====================================================================== */
/* ==== local variables ================================================= */
/* ====================================================================== */
Int j, j3, col, k, row, parent, j2, pdest, p, p2, thickness, npivots, nfr,
i, *Winv, kk, npiv, jnext, krow, knext, pfirst, jlast, ncompactions,
*Front_stack, *Front_order, *Front_child, *Front_sibling,
Wflag, npivcol, fallrows, fallcols, fpiv, frows, fcols, *Front_size ;
nfr = 0 ;
DEBUG0 (("UMF_analyze: anzmax "ID" anrow "ID" ancol "ID"\n",
Ap [n_row], n_row, n_col)) ;
/* ====================================================================== */
/* ==== initializations ================================================= */
/* ====================================================================== */
#pragma ivdep
for (j = 0 ; j < n_col ; j++)
{
Link [j] = EMPTY ;
W [j] = EMPTY ;
Up [j] = EMPTY ;
/* Frontal matrix data structure: */
Front_npivcol [j] = 0 ; /* number of pivot columns */
Front_nrows [j] = 0 ; /* number of rows, incl. pivot rows */
Front_ncols [j] = 0 ; /* number of cols, incl. pivot cols */
Front_parent [j] = EMPTY ; /* parent front */
/* Note that only non-pivotal columns are stored in a front (a "row" */
/* of U) during elimination. */
}
/* the rows must be sorted by increasing min col */
krow = 0 ;
pfirst = Ap [0] ;
jlast = EMPTY ;
jnext = EMPTY ;
Wflag = 0 ;
/* this test requires the size of Ai to be >= n_col + nz */
ASSERT (pfirst >= n_col) ; /* Ai must be large enough */
/* pdest points to the first free space in Ai */
pdest = 0 ;
ncompactions = 0 ;
/* ====================================================================== */
/* === compute symbolic LL' factorization (unsorted) ==================== */
/* ====================================================================== */
for (j = 0 ; j < n_col ; j = jnext)
{
DEBUG1 (("\n\n============Front "ID" starting. nfr = "ID"\n", j, nfr)) ;
/* ================================================================== */
/* === garbage collection =========================================== */
/* ================================================================== */
if (pdest + (n_col-j) > pfirst)
{
/* we might run out ... compact the rows of U */
#ifndef NDEBUG
DEBUG0 (("UMF_analyze COMPACTION, j="ID" pfirst="ID"\n",
j, pfirst)) ;
for (row = 0 ; row < j ; row++)
{
if (Up [row] != EMPTY)
{
/* this is a live row of U */
DEBUG1 (("Live row: "ID" cols: ", row)) ;
p = Up [row] ;
ASSERT (Front_ncols [row] > Front_npivcol [row]) ;
p2 = p + (Front_ncols [row] - Front_npivcol [row]) ;
for ( ; p < p2 ; p++)
{
DEBUG1 ((ID, Ai [p])) ;
ASSERT (p < pfirst) ;
ASSERT (Ai [p] > row && Ai [p] < n_col) ;
}
DEBUG1 (("\n")) ;
}
}
DEBUG1 (("\nStarting to compact:\n")) ;
#endif
pdest = 0 ;
ncompactions++ ;
for (row = 0 ; row < j ; row++)
{
if (Up [row] != EMPTY)
{
/* this is a live row of U */
DEBUG1 (("Live row: "ID" cols: ", row)) ;
ASSERT (row < n_col) ;
p = Up [row] ;
ASSERT (Front_ncols [row] > Front_npivcol [row]) ;
p2 = p + (Front_ncols [row] - Front_npivcol [row]) ;
Up [row] = pdest ;
for ( ; p < p2 ; p++)
{
DEBUG1 ((ID, Ai [p])) ;
ASSERT (p < pfirst) ;
ASSERT (Ai [p] > row && Ai [p] < n_col) ;
Ai [pdest++] = Ai [p] ;
ASSERT (pdest <= pfirst) ;
}
DEBUG1 (("\n")) ;
}
}
#ifndef NDEBUG
DEBUG1 (("\nAFTER COMPACTION, j="ID" pfirst="ID"\n", j, pfirst)) ;
for (row = 0 ; row < j ; row++)
{
if (Up [row] != EMPTY)
{
/* this is a live row of U */
DEBUG1 (("Live row: "ID" cols: ", row)) ;
p = Up [row] ;
ASSERT (Front_ncols [row] > Front_npivcol [row]) ;
p2 = p + (Front_ncols [row] - Front_npivcol [row]) ;
for ( ; p < p2 ; p++)
{
DEBUG1 ((ID, Ai [p])) ;
ASSERT (p < pfirst) ;
ASSERT (Ai [p] > row && Ai [p] < n_col) ;
}
DEBUG1 (("\n")) ;
}
}
#endif
}
if (pdest + (n_col-j) > pfirst)
{
/* :: out of memory in umf_analyze :: */
/* it can't happen, if pfirst >= n_col */
return (FALSE) ; /* internal error! */
}
/* ------------------------------------------------------------------ */
/* is the last front a child of this one? */
/* ------------------------------------------------------------------ */
if (jlast != EMPTY && Link [j] == jlast)
{
/* yes - create row j by appending to jlast */
DEBUG1 (("GOT:last front is child of this one: j "ID" jlast "ID"\n",
j, jlast)) ;
ASSERT (jlast >= 0 && jlast < j) ;
Up [j] = Up [jlast] ;
Up [jlast] = EMPTY ;
/* find the parent, delete column j, and update W */
parent = n_col ;
for (p = Up [j] ; p < pdest ; )
{
j3 = Ai [p] ;
DEBUG1 (("Initial row of U: col "ID" ", j3)) ;
ASSERT (j3 >= 0 && j3 < n_col) ;
DEBUG1 (("W: "ID" \n", W [j3])) ;
ASSERT (W [j3] == Wflag) ;
if (j == j3)
{
DEBUG1 (("Found column j at p = "ID"\n", p)) ;
Ai [p] = Ai [--pdest] ;
}
else
{
if (j3 < parent)
{
parent = j3 ;
}
p++ ;
}
}
/* delete jlast from the link list of j */
Link [j] = Link [jlast] ;
ASSERT (Front_nrows [jlast] > Front_npivcol [jlast]) ;
thickness = (Front_nrows [jlast] - Front_npivcol [jlast]) ;
DEBUG1 (("initial thickness: "ID"\n", thickness)) ;
}
else
{
Up [j] = pdest ;
parent = n_col ;
/* thickness: number of (nonpivotal) rows in frontal matrix j */
thickness = 0 ;
Wflag = j ;
}
/* ================================================================== */
/* === compute row j of A*A' ======================================== */
/* ================================================================== */
/* ------------------------------------------------------------------ */
/* flag the diagonal entry in row U, but do not add to pattern */
/* ------------------------------------------------------------------ */
ASSERT (pdest <= pfirst) ;
W [j] = Wflag ;
DEBUG1 (("\nComputing row "ID" of A'*A\n", j)) ;
DEBUG2 ((" col: "ID" (diagonal)\n", j)) ;
/* ------------------------------------------------------------------ */
/* find the rows the contribute to this column j */
/* ------------------------------------------------------------------ */
jnext = n_col ;
for (knext = krow ; knext < n_row ; knext++)
{
ASSERT (Ap [knext] < Ap [knext+1]) ;
ASSERT (Ap [knext] >= pfirst && Ap [knext] <= Ap [n_row]) ;
jnext = Ai [Ap [knext]] ;
ASSERT (jnext >= j) ;
if (jnext != j)
{
break ;
}
}
/* rows krow ... knext-1 all have first column of j */
/* (or are empty) */
/* row knext has first column of jnext */
/* if knext = n_row, then jnext is n_col */
if (knext == n_row)
{
jnext = n_col ;
}
ASSERT (jnext > j) ;
ASSERT (jnext <= n_col) ;
/* ------------------------------------------------------------------ */
/* for each nonzero A (k,j) in column j of A do: */
/* ------------------------------------------------------------------ */
for (k = krow ; k < knext ; k++)
{
p = Ap [k] ;
p2 = Ap [k+1] ;
ASSERT (p < p2) ;
/* merge row k of A into W */
DEBUG2 ((" ---- A row "ID" ", k)) ;
ASSERT (k >= 0 && k < n_row) ;
ASSERT (Ai [p] == j) ;
DEBUG2 ((" p "ID" p2 "ID"\n cols:", p, p2)) ;
ASSERT (p >= pfirst && p < Ap [n_row]) ;
ASSERT (p2 > pfirst && p2 <= Ap [n_row]) ;
for ( ; p < p2 ; p++)
{
/* add to pattern if seen for the first time */
col = Ai [p] ;
ASSERT (col >= j && col < n_col) ;
DEBUG3 ((" "ID, col)) ;
if (W [col] != Wflag)
{
Ai [pdest++] = col ;
ASSERT (pdest <= pfirst) ;
/* flag this column has having been seen for row j */
W [col] = Wflag ;
if (col < parent)
{
parent = col ;
}
}
}
DEBUG2 (("\n")) ;
thickness++ ;
}
#ifndef NDEBUG
DEBUG3 (("\nRow "ID" of A'A:\n", j)) ;
for (p = Up [j] ; p < pdest ; p++)
{
DEBUG3 ((" "ID, Ai [p])) ;
}
DEBUG3 (("\n")) ;
#endif
/* ------------------------------------------------------------------ */
/* delete rows up to but not including knext */
/* ------------------------------------------------------------------ */
krow = knext ;
pfirst = Ap [knext] ;
/* we can now use Ai [0..pfirst-1] as workspace for rows of U */
/* ================================================================== */
/* === compute jth row of U ========================================= */
/* ================================================================== */
/* for each nonzero U (k,j) in column j of U (1:j-1,:) do */
for (k = Link [j] ; k != EMPTY ; k = Link [k])
{
/* merge row k of U into W */
DEBUG2 ((" ---- U row "ID, k)) ;
ASSERT (k >= 0 && k < n_col) ;
ASSERT (Up [k] != EMPTY) ;
p = Up [k] ;
ASSERT (Front_ncols [k] > Front_npivcol [k]) ;
p2 = p + (Front_ncols [k] - Front_npivcol [k]) ;
DEBUG2 ((" p "ID" p2 "ID"\n cols:", p, p2)) ;
ASSERT (p <= pfirst) ;
ASSERT (p2 <= pfirst) ;
for ( ; p < p2 ; p++)
{
/* add to pattern if seen for the first time */
col = Ai [p] ;
ASSERT (col >= j && col < n_col) ;
DEBUG3 ((" "ID, col)) ;
if (W [col] != Wflag)
{
Ai [pdest++] = col ;
ASSERT (pdest <= pfirst) ;
/* flag this col has having been seen for row j */
W [col] = Wflag ;
if (col < parent)
{
parent = col ;
}
}
}
DEBUG2 (("\n")) ;
/* mark the row k as deleted */
Up [k] = EMPTY ;
ASSERT (Front_nrows [k] > Front_npivcol [k]) ;
thickness += (Front_nrows [k] - Front_npivcol [k]) ;
ASSERT (Front_parent [k] == j) ;
}
#ifndef NDEBUG
DEBUG3 (("\nRow "ID" of U prior to supercolumn detection:\n", j));
for (p = Up [j] ; p < pdest ; p++)
{
DEBUG3 ((" "ID, Ai [p])) ;
}
DEBUG3 (("\n")) ;
DEBUG1 (("thickness, prior to supercol detect: "ID"\n", thickness)) ;
#endif
/* ================================================================== */
/* === quicky mass elimination ====================================== */
/* ================================================================== */
/* this code detects some supernodes, but it might miss */
/* some because the elimination tree (created on the fly) */
/* is not yet post-ordered, and because the pattern of A'*A */
/* is also computed on the fly. */
/* j2 is incremented because the pivot columns are not stored */
for (j2 = j+1 ; j2 < jnext ; j2++)
{
ASSERT (j2 >= 0 && j2 < n_col) ;
if (W [j2] != Wflag || Link [j2] != EMPTY)
{
break ;
}
}
/* the loop above terminated with j2 at the first non-supernode */
DEBUG1 (("jnext = "ID"\n", jnext)) ;
ASSERT (j2 <= jnext) ;
jnext = j2 ;
j2-- ;
DEBUG1 (("j2 = "ID"\n", j2)) ;
ASSERT (j2 < n_col) ;
npivots = j2-j+1 ;
DEBUG1 (("Number of pivot columns: "ID"\n", npivots)) ;
/* rows j:j2 have the same nonzero pattern, except for columns j:j2-1 */
if (j2 > j)
{
/* supernode detected, prune the pattern of new row j */
ASSERT (parent == j+1) ;
ASSERT (j2 < n_col) ;
DEBUG1 (("Supernode detected, j "ID" to j2 "ID"\n", j, j2)) ;
parent = n_col ;
p2 = pdest ;
pdest = Up [j] ;
for (p = Up [j] ; p < p2 ; p++)
{
col = Ai [p] ;
ASSERT (col >= 0 && col < n_col) ;
ASSERT (W [col] == Wflag) ;
if (col > j2)
{
/* keep this col in the pattern of the new row j */
Ai [pdest++] = col ;
if (col < parent)
{
parent = col ;
}
}
}
}
DEBUG1 (("Parent ["ID"] = "ID"\n", j, parent)) ;
ASSERT (parent > j2) ;
if (parent == n_col)
{
/* this front has no parent - it is the root of a subtree */
parent = EMPTY ;
}
#ifndef NDEBUG
DEBUG3 (("\nFinal row "ID" of U after supercolumn detection:\n", j)) ;
for (p = Up [j] ; p < pdest ; p++)
{
ASSERT (Ai [p] >= 0 && Ai [p] < n_col) ;
DEBUG3 ((" "ID" ("ID")", Ai [p], W [Ai [p]])) ;
ASSERT (W [Ai [p]] == Wflag) ;
}
DEBUG3 (("\n")) ;
#endif
/* ================================================================== */
/* === frontal matrix =============================================== */
/* ================================================================== */
/* front has Front_npivcol [j] pivot columns */
/* entire front is Front_nrows [j] -by- Front_ncols [j] */
/* j is first column in the front */
npivcol = npivots ;
fallrows = thickness ;
fallcols = npivots + pdest - Up [j] ;
/* number of pivots in the front (rows and columns) */
fpiv = MIN (npivcol, fallrows) ;
/* size of contribution block */
frows = fallrows - fpiv ;
fcols = fallcols - fpiv ;
if (frows == 0 || fcols == 0)
{
/* front has no contribution block and thus needs no parent */
DEBUG1 (("Frontal matrix evaporation\n")) ;
Up [j] = EMPTY ;
parent = EMPTY ;
}
Front_npivcol [j] = npivots ;
Front_nrows [j] = fallrows ;
Front_ncols [j] = fallcols ;
Front_parent [j] = parent ;
ASSERT (npivots > 0) ;
/* Front_parent [j] is the first column of the parent frontal matrix */
DEBUG1 (("\n\n==== Front "ID", nfr "ID" pivot columns "ID":"ID
" all front: "ID"-by-"ID" Parent: "ID"\n", j, nfr, j,j+npivots-1,
Front_nrows [j], Front_ncols [j], Front_parent [j])) ;
nfr++ ;
/* ================================================================== */
/* === prepare this row for its parent ============================== */
/* ================================================================== */
if (parent != EMPTY)
{
Link [j] = Link [parent] ;
Link [parent] = j ;
}
ASSERT (jnext > j) ;
jlast = j ;
}
/* ====================================================================== */
/* === postorder the fronts ============================================= */
/* ====================================================================== */
*nfr_out = nfr ;
Front_order = W ; /* use W for Front_order [ */
if (fixQ)
{
/* do not postorder the fronts if Q is fixed */
DEBUG1 (("\nNo postorder (Q is fixed)\n")) ;
k = 0 ;
/* Pragma added May 14, 2003. The Intel compiler icl 6.0 (an old
* version) incorrectly vectorizes this loop. */
#pragma novector
for (j = 0 ; j < n_col ; j++)
{
if (Front_npivcol [j] > 0)
{
Front_order [j] = k++ ;
DEBUG1 (("Front order of j: "ID" is:"ID"\n", j,
Front_order [j])) ;
}
else
{
Front_order [j] = EMPTY ;
}
}
}
else
{
/* use Ap for Front_child and use Link for Front_sibling [ */
Front_child = Ap ;
Front_sibling = Link ;
/* use Ai for Front_stack, size of Ai is >= 2*n_col */
Front_stack = Ai ;
Front_size = Front_stack + n_col ;
UMF_fsize (n_col, Front_size, Front_nrows, Front_ncols,
Front_parent, Front_npivcol) ;
AMD_postorder (n_col, Front_parent, Front_npivcol, Front_size,
Front_order, Front_child, Front_sibling, Front_stack) ;
/* done with Front_child, Front_sibling, Front_size, and Front_stack ]*/
/* ------------------------------------------------------------------ */
/* construct the column permutation (return in Up) */
/* ------------------------------------------------------------------ */
/* Front_order [i] = k means that front i is kth front in the new order.
* i is in the range 0 to n_col-1, and k is in the range 0 to nfr-1 */
/* Use Ai as workspace for Winv [ */
Winv = Ai ;
for (k = 0 ; k < nfr ; k++)
{
Winv [k] = EMPTY ;
}
/* compute the inverse of Front_order, so that Winv [k] = i */
/* if Front_order [i] = k */
DEBUG1 (("\n\nComputing output column permutation:\n")) ;
for (i = 0 ; i < n_col ; i++)
{
k = Front_order [i] ;
if (k != EMPTY)
{
DEBUG1 (("Front "ID" new order: "ID"\n", i, k)) ;
ASSERT (k >= 0 && k < nfr) ;
ASSERT (Winv [k] == EMPTY) ;
Winv [k] = i ;
}
}
/* Use Up as output permutation */
kk = 0 ;
for (k = 0 ; k < nfr ; k++)
{
i = Winv [k] ;
DEBUG1 (("Old Front "ID" New Front "ID" npivots "ID" nrows "ID
" ncols "ID"\n",
i, k, Front_npivcol [i], Front_nrows [i], Front_ncols [i])) ;
ASSERT (i >= 0 && i < n_col) ;
ASSERT (Front_npivcol [i] > 0) ;
for (npiv = 0 ; npiv < Front_npivcol [i] ; npiv++)
{
Up [kk] = i + npiv ;
DEBUG1 ((" Cperm ["ID"] = "ID"\n", kk, Up [kk])) ;
kk++ ;
}
}
ASSERT (kk == n_col) ;
/* Winv no longer needed ] */
}
/* ---------------------------------------------------------------------- */
/* apply the postorder traversal to renumber the frontal matrices */
/* (or pack them in same order, if fixQ) */
/* ---------------------------------------------------------------------- */
/* use Ai as workspace */
UMF_apply_order (Front_npivcol, Front_order, Ai, n_col, nfr) ;
UMF_apply_order (Front_nrows, Front_order, Ai, n_col, nfr) ;
UMF_apply_order (Front_ncols, Front_order, Ai, n_col, nfr) ;
UMF_apply_order (Front_parent, Front_order, Ai, n_col, nfr) ;
/* fix the parent to refer to the new numbering */
for (i = 0 ; i < nfr ; i++)
{
parent = Front_parent [i] ;
if (parent != EMPTY)
{
ASSERT (parent >= 0 && parent < n_col) ;
ASSERT (Front_order [parent] >= 0 && Front_order [parent] < nfr) ;
Front_parent [i] = Front_order [parent] ;
}
}
/* Front_order longer needed ] */
#ifndef NDEBUG
DEBUG1 (("\nFinal frontal matrices:\n")) ;
for (i = 0 ; i < nfr ; i++)
{
DEBUG1 (("Final front "ID": npiv "ID" nrows "ID" ncols "ID" parent "
ID"\n", i, Front_npivcol [i], Front_nrows [i],
Front_ncols [i], Front_parent [i])) ;
}
#endif
*p_ncompactions = ncompactions ;
return (TRUE) ;
}

View File

@ -0,0 +1,23 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL Int UMF_analyze
(
Int n_row,
Int n_col,
Int Ai [ ],
Int Ap [ ],
Int Up [ ],
Int fixQ,
Int Front_ncols [ ],
Int W [ ],
Int Link [ ],
Int Front_nrows [ ],
Int Front_npivcol [ ],
Int Front_parent [ ],
Int *nfr_out,
Int *p_ncompactions
) ;

View File

@ -0,0 +1,44 @@
/* ========================================================================== */
/* === UMF_apply_order ====================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/*
Apply post-ordering of supernodal elimination tree.
*/
#include "umf_internal.h"
#include "umf_apply_order.h"
GLOBAL void UMF_apply_order
(
Int Front [ ], /* of size nn on input, size nfr on output */
const Int Order [ ], /* Order [i] = k, i in the range 0..nn-1,
* and k in the range 0..nfr-1, means that node
* i is the kth node in the postordered tree. */
Int Temp [ ], /* workspace of size nfr */
Int nn, /* nodes are numbered in the range 0..nn-1 */
Int nfr /* the number of nodes actually in use */
)
{
Int i, k ;
for (i = 0 ; i < nn ; i++)
{
k = Order [i] ;
ASSERT (k >= EMPTY && k < nfr) ;
if (k != EMPTY)
{
Temp [k] = Front [i] ;
}
}
for (k = 0 ; k < nfr ; k++)
{
Front [k] = Temp [k] ;
}
}

View File

@ -0,0 +1,14 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL void UMF_apply_order
(
Int Front [ ],
const Int Order [ ],
Int Temp [ ],
Int n_col,
Int nfr
) ;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL void UMF_assemble
(
NumericType *Numeric,
WorkType *Work
) ;
GLOBAL void UMF_assemble_fixq
(
NumericType *Numeric,
WorkType *Work
) ;

View File

@ -0,0 +1,176 @@
/* ========================================================================== */
/* === UMF_blas3_update ===================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
#include "umf_internal.h"
#include "umf_blas3_update.h"
GLOBAL void UMF_blas3_update
(
WorkType *Work
)
{
/* ---------------------------------------------------------------------- */
/* local variables */
/* ---------------------------------------------------------------------- */
Entry *L, *U, *C, *LU ;
Int i, j, s, k, m, n, d, nb, dc ;
#ifndef NBLAS
Int blas_ok = TRUE ;
#else
#define blas_ok FALSE
#endif
DEBUG5 (("In UMF_blas3_update "ID" "ID" "ID"\n",
Work->fnpiv, Work->fnrows, Work->fncols)) ;
k = Work->fnpiv ;
if (k == 0)
{
/* no work to do */
return ;
}
m = Work->fnrows ;
n = Work->fncols ;
d = Work->fnr_curr ;
dc = Work->fnc_curr ;
nb = Work->nb ;
ASSERT (d >= 0 && (d % 2) == 1) ;
C = Work->Fcblock ; /* ldc is fnr_curr */
L = Work->Flblock ; /* ldl is fnr_curr */
U = Work->Fublock ; /* ldu is fnc_curr, stored by rows */
LU = Work->Flublock ; /* nb-by-nb */
#ifndef NDEBUG
DEBUG5 (("DO RANK-NB UPDATE of frontal:\n")) ;
DEBUG5 (("DGEMM : "ID" "ID" "ID"\n", k, m, n)) ;
DEBUG7 (("C block: ")) ; UMF_dump_dense (C, d, m, n) ;
DEBUG7 (("A block: ")) ; UMF_dump_dense (L, d, m, k) ;
DEBUG7 (("B' block: ")) ; UMF_dump_dense (U, dc, n, k) ;
DEBUG7 (("LU block: ")) ; UMF_dump_dense (LU, nb, k, k) ;
#endif
if (k == 1)
{
#ifndef NBLAS
BLAS_GER (m, n, L, U, C, d) ;
#endif
if (!blas_ok)
{
/* rank-1 outer product to update the C block */
for (j = 0 ; j < n ; j++)
{
Entry u_j = U [j] ;
if (IS_NONZERO (u_j))
{
Entry *c_ij, *l_is ;
c_ij = & C [j*d] ;
l_is = & L [0] ;
#pragma ivdep
for (i = 0 ; i < m ; i++)
{
/* C [i+j*d]-= L [i] * U [j] */
MULT_SUB (*c_ij, *l_is, u_j) ;
c_ij++ ;
l_is++ ;
}
}
}
}
}
else
{
/* triangular solve to update the U block */
#ifndef NBLAS
BLAS_TRSM_RIGHT (n, k, LU, nb, U, dc) ;
#endif
if (!blas_ok)
{
/* use plain C code if no BLAS at compile time, or if integer
* overflow has occurred */
for (s = 0 ; s < k ; s++)
{
for (i = s+1 ; i < k ; i++)
{
Entry l_is = LU [i+s*nb] ;
if (IS_NONZERO (l_is))
{
Entry *u_ij, *u_sj ;
u_ij = & U [i*dc] ;
u_sj = & U [s*dc] ;
#pragma ivdep
for (j = 0 ; j < n ; j++)
{
/* U [i*dc+j] -= LU [i+s*nb] * U [s*dc+j] ; */
MULT_SUB (*u_ij, l_is, *u_sj) ;
u_ij++ ;
u_sj++ ;
}
}
}
}
}
/* rank-k outer product to update the C block */
/* C = C - L*U' (U is stored by rows, not columns) */
#ifndef NBLAS
BLAS_GEMM (m, n, k, L, U, dc, C, d) ;
#endif
if (!blas_ok)
{
/* use plain C code if no BLAS at compile time, or if integer
* overflow has occurred */
for (s = 0 ; s < k ; s++)
{
for (j = 0 ; j < n ; j++)
{
Entry u_sj = U [j+s*dc] ;
if (IS_NONZERO (u_sj))
{
Entry *c_ij, *l_is ;
c_ij = & C [j*d] ;
l_is = & L [s*d] ;
#pragma ivdep
for (i = 0 ; i < m ; i++)
{
/* C [i+j*d]-= L [i+s*d] * U [s*dc+j] */
MULT_SUB (*c_ij, *l_is, u_sj) ;
c_ij++ ;
l_is++ ;
}
}
}
}
}
}
#ifndef NDEBUG
DEBUG5 (("RANK-NB UPDATE of frontal done:\n")) ;
DEBUG5 (("DGEMM : "ID" "ID" "ID"\n", k, m, n)) ;
DEBUG7 (("C block: ")) ; UMF_dump_dense (C, d, m, n) ;
DEBUG7 (("A block: ")) ; UMF_dump_dense (L, d, m, k) ;
DEBUG7 (("B' block: ")) ; UMF_dump_dense (U, dc, n, k) ;
DEBUG7 (("LU block: ")) ; UMF_dump_dense (LU, nb, k, k) ;
#endif
DEBUG2 (("blas3 "ID" "ID" "ID"\n", k, Work->fnrows, Work->fncols)) ;
}

View File

@ -0,0 +1,10 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL void UMF_blas3_update
(
WorkType *Work
) ;

View File

@ -0,0 +1,160 @@
/* ========================================================================== */
/* === UMF_build_tuples ===================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/*
Construct the tuple lists from a set of packed elements (no holes in
elements, no internal or external fragmentation, and a packed (0..Work->nel)
element name space). Assume no tuple lists are currently allocated, but
that the tuple lengths have been initialized by UMF_tuple_lengths.
Returns TRUE if successful, FALSE if not enough memory.
*/
#include "umf_internal.h"
#include "umf_build_tuples.h"
#include "umf_mem_alloc_tail_block.h"
GLOBAL Int UMF_build_tuples
(
NumericType *Numeric,
WorkType *Work
)
{
/* ---------------------------------------------------------------------- */
/* local variables */
/* ---------------------------------------------------------------------- */
Int e, nrows, ncols, nel, *Rows, *Cols, row, col, n_row, n_col, *E,
*Row_tuples, *Row_degree, *Row_tlen,
*Col_tuples, *Col_degree, *Col_tlen, n1 ;
Element *ep ;
Unit *p ;
Tuple tuple, *tp ;
/* ---------------------------------------------------------------------- */
/* get parameters */
/* ---------------------------------------------------------------------- */
E = Work->E ;
Col_degree = Numeric->Cperm ; /* for NON_PIVOTAL_COL macro */
Row_degree = Numeric->Rperm ; /* for NON_PIVOTAL_ROW macro */
Row_tuples = Numeric->Uip ;
Row_tlen = Numeric->Uilen ;
Col_tuples = Numeric->Lip ;
Col_tlen = Numeric->Lilen ;
n_row = Work->n_row ;
n_col = Work->n_col ;
nel = Work->nel ;
n1 = Work->n1 ;
DEBUG3 (("BUILD_TUPLES: n_row "ID" n_col "ID" nel "ID"\n",
n_row, n_col, nel)) ;
/* ---------------------------------------------------------------------- */
/* allocate space for the tuple lists */
/* ---------------------------------------------------------------------- */
/* Garbage collection and memory reallocation have already attempted to */
/* ensure that there is enough memory for all the tuple lists. If */
/* memory allocation fails here, then there is nothing more to be done. */
for (row = n1 ; row < n_row ; row++)
{
if (NON_PIVOTAL_ROW (row))
{
Row_tuples [row] = UMF_mem_alloc_tail_block (Numeric,
UNITS (Tuple, TUPLES (Row_tlen [row]))) ;
if (!Row_tuples [row])
{
/* :: out of memory for row tuples :: */
DEBUGm4 (("out of memory: build row tuples\n")) ;
return (FALSE) ; /* out of memory for row tuples */
}
Row_tlen [row] = 0 ;
}
}
/* push on stack in reverse order, so column tuples are in the order */
/* that they will be deleted. */
for (col = n_col-1 ; col >= n1 ; col--)
{
if (NON_PIVOTAL_COL (col))
{
Col_tuples [col] = UMF_mem_alloc_tail_block (Numeric,
UNITS (Tuple, TUPLES (Col_tlen [col]))) ;
if (!Col_tuples [col])
{
/* :: out of memory for col tuples :: */
DEBUGm4 (("out of memory: build col tuples\n")) ;
return (FALSE) ; /* out of memory for col tuples */
}
Col_tlen [col] = 0 ;
}
}
#ifndef NDEBUG
UMF_dump_memory (Numeric) ;
#endif
/* ---------------------------------------------------------------------- */
/* create the tuple lists (exclude element 0) */
/* ---------------------------------------------------------------------- */
/* for all elements, in order of creation */
for (e = 1 ; e <= nel ; e++)
{
DEBUG9 (("Adding tuples for element: "ID" at "ID"\n", e, E [e])) ;
ASSERT (E [e]) ; /* no external fragmentation */
p = Numeric->Memory + E [e] ;
GET_ELEMENT_PATTERN (ep, p, Cols, Rows, ncols) ;
nrows = ep->nrows ;
ASSERT (e != 0) ;
ASSERT (e == 0 || nrows == ep->nrowsleft) ;
ASSERT (e == 0 || ncols == ep->ncolsleft) ;
tuple.e = e ;
for (tuple.f = 0 ; tuple.f < ncols ; tuple.f++)
{
col = Cols [tuple.f] ;
ASSERT (col >= n1 && col < n_col) ;
ASSERT (NON_PIVOTAL_COL (col)) ;
ASSERT (Col_tuples [col]) ;
tp = ((Tuple *) (Numeric->Memory + Col_tuples [col]))
+ Col_tlen [col]++ ;
*tp = tuple ;
#ifndef NDEBUG
UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ;
#endif
}
for (tuple.f = 0 ; tuple.f < nrows ; tuple.f++)
{
row = Rows [tuple.f] ;
ASSERT (row >= n1 && row < n_row) ;
ASSERT (NON_PIVOTAL_COL (col)) ;
ASSERT (Row_tuples [row]) ;
tp = ((Tuple *) (Numeric->Memory + Row_tuples [row]))
+ Row_tlen [row]++ ;
*tp = tuple ;
#ifndef NDEBUG
UMF_dump_rowcol (0, Numeric, Work, row, FALSE) ;
#endif
}
}
/* ---------------------------------------------------------------------- */
/* the tuple lists are now valid, and can be scanned */
/* ---------------------------------------------------------------------- */
#ifndef NDEBUG
UMF_dump_memory (Numeric) ;
UMF_dump_matrix (Numeric, Work, FALSE) ;
#endif
DEBUG3 (("BUILD_TUPLES: done\n")) ;
return (TRUE) ;
}

View File

@ -0,0 +1,11 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL Int UMF_build_tuples
(
NumericType *Numeric,
WorkType *Work
) ;

View File

@ -0,0 +1,239 @@
/* ========================================================================== */
/* === umf_cholmod ========================================================== */
/* ========================================================================== */
/* umfpack_cholmod: user-defined ordering function to interface UMFPACK
* to CHOLMOD.
*
* This routine is an example of a user-provided ordering function for UMFPACK.
*
* This function can be passed to umfpack_*_fsymbolic as the
* user_ordering function pointer.
*/
#include "umf_internal.h"
#include "umf_cholmod.h"
#ifndef NCHOLMOD
#include "cholmod.h"
#endif
#if defined (DINT) || defined (ZINT)
#define CHOLMOD_start cholmod_start
#define CHOLMOD_transpose cholmod_transpose
#define CHOLMOD_analyze cholmod_analyze
#define CHOLMOD_free_sparse cholmod_free_sparse
#define CHOLMOD_free_factor cholmod_free_factor
#define CHOLMOD_finish cholmod_finish
#define CHOLMOD_print_common cholmod_print_common
#else
#define CHOLMOD_start cholmod_l_start
#define CHOLMOD_transpose cholmod_l_transpose
#define CHOLMOD_analyze cholmod_l_analyze
#define CHOLMOD_free_sparse cholmod_l_free_sparse
#define CHOLMOD_free_factor cholmod_l_free_factor
#define CHOLMOD_finish cholmod_l_finish
#define CHOLMOD_print_common cholmod_l_print_common
#endif
int UMF_cholmod
(
/* inputs */
Int nrow, /* A is nrow-by-ncol */
Int ncol, /* A is nrow-by-ncol */
Int symmetric, /* if true and nrow=ncol do A+A', else do A'A */
Int Ap [ ], /* column pointers, size ncol+1 */
Int Ai [ ], /* row indices, size nz = Ap [ncol] */
/* output */
Int Perm [ ], /* fill-reducing permutation, size ncol */
/* user-defined */
void *user_params, /* Int array of size 3 */
double user_info [3] /* [0]: max col count for L=chol(P(A+A')P')
[1]: nnz (L)
[2]: flop count for chol, if A real */
)
{
#ifndef NCHOLMOD
double dmax, flops, c, lnz ;
cholmod_sparse Amatrix, *A, *AT, *S ;
cholmod_factor *L ;
cholmod_common cm ;
Int *P, *ColCount ;
Int k, ordering_option, print_level, *params ;
params = (Int *) user_params ;
ordering_option = params [0] ;
print_level = params [1] - 1 ;
params [2] = -1 ;
if (Ap == NULL || Ai == NULL || Perm == NULL || nrow < 0 || ncol < 0)
{
/* invalid inputs */
return (FALSE) ;
}
if (nrow != ncol)
{
/* force symmetric to be false */
symmetric = FALSE ;
}
/* start CHOLMOD */
CHOLMOD_start (&cm) ;
cm.supernodal = CHOLMOD_SIMPLICIAL ;
cm.print = print_level ;
/* adjust cm based on ordering_option */
switch (ordering_option)
{
default:
case UMFPACK_ORDERING_AMD:
/* AMD on A+A' if symmetric, COLAMD on A otherwise */
cm.nmethods = 1 ;
cm.method [0].ordering = symmetric ? CHOLMOD_AMD : CHOLMOD_COLAMD ;
cm.postorder = TRUE ;
break ;
case UMFPACK_ORDERING_METIS:
/* metis on A+A' if symmetric, A'A otherwise */
cm.nmethods = 1 ;
cm.method [0].ordering = CHOLMOD_METIS ;
cm.postorder = TRUE ;
break ;
case UMFPACK_ORDERING_NONE:
case UMFPACK_ORDERING_GIVEN:
case UMFPACK_ORDERING_USER:
/* no ordering. No input permutation here, and no user
function, so all these are the same as "none". */
cm.nmethods = 1 ;
cm.method [0].ordering = CHOLMOD_NATURAL ;
cm.postorder = FALSE ;
break ;
case UMFPACK_ORDERING_BEST:
/* try AMD, METIS and NESDIS on A+A', or COLAMD(A), METIS(A'A),
and NESDIS (A'A) */
cm.nmethods = 3 ;
cm.method [0].ordering = symmetric ? CHOLMOD_AMD : CHOLMOD_COLAMD ;
cm.method [1].ordering = CHOLMOD_METIS ;
cm.method [2].ordering = CHOLMOD_NESDIS ;
cm.postorder = TRUE ;
break ;
case UMFPACK_ORDERING_CHOLMOD:
/* no change to CHOLMOD defaults:
Do not use given permutation, since it's not provided.
Try AMD. If fill-in and flop count are low, use AMD.
Otherwise, try METIS and take the best of AMD and METIS.
cm.method [0].ordering = CHOLMOD_GIVEN
cm.method [1].ordering = CHOLMOD_AMD
cm.method [2].ordering = CHOLMOD_METIS
cm.nmethods = 2 if METIS installed, 3 otherwise ('given' is skipped)
*/
break ;
}
/* use AMD memory management routines for CHOLMOD */
cm.malloc_memory = amd_malloc ;
cm.realloc_memory = amd_realloc ;
cm.calloc_memory = amd_calloc ;
cm.free_memory = amd_free ;
/* construct a CHOLMOD version of the input matrix A */
A = &Amatrix ;
A->nrow = nrow ; /* A is nrow-by-ncol */
A->ncol = ncol ;
A->nzmax = Ap [ncol] ; /* with nzmax entries */
A->packed = TRUE ; /* there is no A->nz array */
if (symmetric)
{
A->stype = 1 ; /* A is symmetric */
}
else
{
A->stype = 0 ; /* A is unsymmetric */
}
A->itype = CHOLMOD_INT ;
A->xtype = CHOLMOD_PATTERN ;
A->dtype = CHOLMOD_DOUBLE ;
A->nz = NULL ;
A->p = Ap ; /* column pointers */
A->i = Ai ; /* row indices */
A->x = NULL ; /* no numerical values */
A->z = NULL ;
A->sorted = FALSE ; /* columns of A might not be sorted */
if (symmetric)
{
/* CHOLMOD with order the symmetric matrix A */
AT = NULL ;
S = A ;
}
else
{
/* S = A'. CHOLMOD will order S*S', which is A'*A */
AT = CHOLMOD_transpose (A, 0, &cm) ;
S = AT ;
}
/* order and analyze S or S*S' */
L = CHOLMOD_analyze (S, &cm) ;
CHOLMOD_free_sparse (&AT, &cm) ;
if (L == NULL)
{
return (FALSE) ;
}
/* determine the ordering used */
switch (L->ordering)
{
case CHOLMOD_AMD:
case CHOLMOD_COLAMD:
params [2] = UMFPACK_ORDERING_AMD ;
break ;
case CHOLMOD_METIS:
case CHOLMOD_NESDIS:
params [2] = UMFPACK_ORDERING_METIS ;
break ;
case CHOLMOD_GIVEN:
case CHOLMOD_NATURAL:
default:
params [2] = UMFPACK_ORDERING_NONE ;
break ;
}
/* copy the permutation from L to the output and compute statistics */
P = L->Perm ;
ColCount = L->ColCount ;
dmax = 1 ;
lnz = 0 ;
flops = 0 ;
for (k = 0 ; k < ncol ; k++)
{
Perm [k] = P [k] ;
c = ColCount [k] ;
if (c > dmax) dmax = c ;
lnz += c ;
flops += c*c ;
}
user_info [0] = dmax ;
user_info [1] = lnz ;
user_info [2] = flops ;
CHOLMOD_free_factor (&L, &cm) ;
if (print_level > 0)
{
CHOLMOD_print_common ("for UMFPACK", &cm) ;
}
CHOLMOD_finish (&cm) ;
return (TRUE) ;
#else
/* CHOLMOD and its supporting packages (CAMD, CCOLAMD, COLAMD, metis-4.0)
not installed */
return (FALSE) ;
#endif
}

View File

@ -0,0 +1,38 @@
#include "ngspice/umfpack.h"
#include "ngspice/UFconfig.h"
int umf_i_cholmod
(
/* inputs */
int nrow, /* A is nrow-by-ncol */
int ncol, /* A is nrow-by-ncol */
int symmetric, /* if true and nrow=ncol do A+A', else do A'A */
int Ap [ ], /* column pointers, size ncol+1 */
int Ai [ ], /* row indices, size nz = Ap [ncol] */
/* output */
int Perm [ ], /* fill-reducing permutation, size ncol */
/* user-defined */
void *ignore, /* not needed */
double user_info [3] /* [0]: max col count for L=chol(P(A+A')P')
[1]: nnz (L)
[2]: flop count for chol, if A real */
) ;
int umf_l_cholmod
(
/* inputs */
UF_long nrow, /* A is nrow-by-ncol */
UF_long ncol, /* A is nrow-by-ncol */
UF_long symmetric, /* if true and nrow=ncol do A+A', else do A'A */
UF_long Ap [ ], /* column pointers, size ncol+1 */
UF_long Ai [ ], /* row indices, size nz = Ap [ncol] */
/* output */
UF_long Perm [ ], /* fill-reducing permutation, size ncol */
/* user-defined */
void *ignore, /* not needed */
double user_info [3] /* [0]: max col count for L=chol(P(A+A')P')
[1]: nnz (L)
[2]: flop count for chol, if A real */
) ;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,255 @@
/* ========================================================================== */
/* === umf_colamd.h ========================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/*
Authors:
The authors of the COLAMD code itself are Stefan I. Larimore and Timothy A.
Davis, University of Florida. The algorithm was developed in collaboration
with John Gilbert, Xerox PARC, and Esmond Ng, Oak Ridge National Laboratory.
Date:
UMFPACK Version: see above.
COLAMD Version 2.0 was released on January 31, 2000.
Acknowledgements:
This work was supported by the National Science Foundation, under
grants DMS-9504974, DMS-9803599, and CCR-0203270.
UMFPACK: Copyright (c) 2003 by Timothy A. Davis. All Rights Reserved.
See the UMFPACK README file for the License for your use of this code.
Availability:
Both UMFPACK and the original unmodified colamd/symamd library are
available at http://www.cise.ufl.edu/research/sparse.
*/
#ifndef COLAMD_H
#define COLAMD_H
/* ========================================================================== */
/* === Include files ======================================================== */
/* ========================================================================== */
#include <stdlib.h>
/* ========================================================================== */
/* === Knob and statistics definitions ====================================== */
/* ========================================================================== */
/* size of the knobs [ ] array. Only knobs [0..2] are currently used. */
#define COLAMD_KNOBS 20
/* number of output statistics. Only stats [0..8] are currently used. */
#define COLAMD_STATS 20
/* knobs [0] and stats [0]: dense row knob and output statistic. */
#define COLAMD_DENSE_ROW 0
/* knobs [1] and stats [1]: dense column knob and output statistic. */
#define COLAMD_DENSE_COL 1
/* knobs [2]: aggressive absorption option */
#define COLAMD_AGGRESSIVE 2
/* stats [2]: memory defragmentation count output statistic */
#define COLAMD_DEFRAG_COUNT 2
/* stats [3]: colamd status: zero OK, > 0 warning or notice, < 0 error */
#define COLAMD_STATUS 3
/* stats [4..6]: error info, or info on jumbled columns */
#define COLAMD_INFO1 4
#define COLAMD_INFO2 5
#define COLAMD_INFO3 6
/* ------------------ */
/* added for UMFPACK: */
/* stats [7]: number of originally empty rows */
#define COLAMD_EMPTY_ROW 7
/* stats [8]: number of originally empty cols */
#define COLAMD_EMPTY_COL 8
/* stats [9]: number of rows with entries only in dense cols */
#define COLAMD_NEWLY_EMPTY_ROW 9
/* stats [10]: number of cols with entries only in dense rows */
#define COLAMD_NEWLY_EMPTY_COL 10
/* ------------------ */
/* error codes returned in stats [3]: */
#define COLAMD_OK (0)
#define COLAMD_ERROR_jumbled_matrix (-11)
#define COLAMD_ERROR_A_not_present (-1)
#define COLAMD_ERROR_p_not_present (-2)
#define COLAMD_ERROR_nrow_negative (-3)
#define COLAMD_ERROR_ncol_negative (-4)
#define COLAMD_ERROR_nnz_negative (-5)
#define COLAMD_ERROR_p0_nonzero (-6)
#define COLAMD_ERROR_A_too_small (-7)
#define COLAMD_ERROR_col_length_negative (-8)
#define COLAMD_ERROR_row_index_out_of_bounds (-9)
#define COLAMD_ERROR_out_of_memory (-10)
#define COLAMD_ERROR_internal_error (-999)
/* ========================================================================== */
/* === Row and Column structures ============================================ */
/* ========================================================================== */
/* User code that makes use of the colamd/symamd routines need not directly */
/* reference these structures. They are used only for the COLAMD_RECOMMENDED */
/* macro. */
typedef struct Colamd_Col_struct
{
Int start ; /* index for A of first row in this column, or DEAD */
/* if column is dead */
Int length ; /* number of rows in this column */
union
{
Int thickness ; /* number of original columns represented by this */
/* col, if the column is alive */
Int parent ; /* parent in parent tree super-column structure, if */
/* the column is dead */
} shared1 ;
union
{
Int score ; /* the score used to maintain heap, if col is alive */
Int order ; /* pivot ordering of this column, if col is dead */
} shared2 ;
union
{
Int headhash ; /* head of a hash bucket, if col is at the head of */
/* a degree list */
Int hash ; /* hash value, if col is not in a degree list */
Int prev ; /* previous column in degree list, if col is in a */
/* degree list (but not at the head of a degree list) */
} shared3 ;
union
{
Int degree_next ; /* next column, if col is in a degree list */
Int hash_next ; /* next column, if col is in a hash list */
} shared4 ;
/* ------------------ */
/* added for UMFPACK: */
Int nextcol ; /* next column in this supercolumn */
Int lastcol ; /* last column in this supercolumn */
/* ------------------ */
} Colamd_Col ;
typedef struct Colamd_Row_struct
{
Int start ; /* index for A of first col in this row */
Int length ; /* number of principal columns in this row */
union
{
Int degree ; /* number of principal & non-principal columns in row */
Int p ; /* used as a row pointer in init_rows_cols () */
} shared1 ;
union
{
Int mark ; /* for computing set differences and marking dead rows*/
Int first_column ;/* first column in row (used in garbage collection) */
} shared2 ;
/* ------------------ */
/* added for UMFPACK: */
Int thickness ; /* number of original rows represented by this row */
/* that are not yet pivotal */
Int front ; /* -1 if an original row */
/* k if this row represents the kth frontal matrix */
/* where k goes from 0 to at most n_col-1 */
/* ------------------ */
} Colamd_Row ;
/* ========================================================================== */
/* === Colamd recommended memory size ======================================= */
/* ========================================================================== */
/*
The recommended length Alen of the array A passed to colamd is given by
the COLAMD_RECOMMENDED (nnz, n_row, n_col) macro. It returns -1 if any
argument is negative. 2*nnz space is required for the row and column
indices of the matrix. COLAMD_C (n_col) + COLAMD_R (n_row) space is
required for the Col and Row arrays, respectively, which are internal to
colamd. An additional n_col space is the minimal amount of "elbow room",
and nnz/5 more space is recommended for run time efficiency.
This macro is not needed when using symamd.
*/
/* about 8*(n_col+1) integers: */
#define UMF_COLAMD_C(n_col) ((n_col + 1) * sizeof (Colamd_Col) / sizeof (Int))
/* about 6*(n_row+1) integers: */
#define UMF_COLAMD_R(n_row) ((n_row + 1) * sizeof (Colamd_Row) / sizeof (Int))
/* UMFPACK: make sure Alen is >= 5*n_col + size of Col and Row structures.
* Alen is typically about 2.2*nz + 9*n_col + 6*n_row, or 2.2nz+15n for
* square matrices. */
#define UMF_COLAMD_RECOMMENDED(nnz, n_row, n_col) \
( \
((nnz) < 0 || (n_row) < 0 || (n_col) < 0) \
? \
(-1) \
: \
(MAX (2 * (nnz), 4 * (n_col)) + \
(Int) UMF_COLAMD_C (n_col) + \
(Int) UMF_COLAMD_R (n_row) + (n_col) + ((nnz) / 5)) \
)
/* ========================================================================== */
/* === Prototypes of user-callable routines ================================= */
/* ========================================================================== */
/* colamd_recommended removed for UMFPACK */
void UMF_colamd_set_defaults /* sets default parameters */
( /* knobs argument is modified on output */
double knobs [COLAMD_KNOBS] /* parameter settings for colamd */
) ;
Int UMF_colamd /* returns (1) if successful, (0) otherwise*/
( /* A and p arguments are modified on output */
Int n_row, /* number of rows in A */
Int n_col, /* number of columns in A */
Int Alen, /* size of the array A */
Int A [], /* row indices of A, of size Alen */
Int p [], /* column pointers of A, of size n_col+1 */
double knobs [COLAMD_KNOBS],/* parameter settings for colamd */
Int stats [COLAMD_STATS] /* colamd output statistics and error codes */
/* ------------------ */
/* added for UMFPACK: */
, Int Front_npivcol [ ]
, Int Front_nrows [ ]
, Int Front_ncols [ ]
, Int Front_parent [ ]
, Int Front_cols [ ]
, Int *p_nfr
, Int InFront [ ]
/* ------------------ */
) ;
/* symamd deleted for UMFPACK */
/* colamd_report deleted for UMFPACK */
/* symamd_report deleted for UMFPACK */
#endif /* COLAMD_H */

View File

@ -0,0 +1,326 @@
/* ========================================================================== */
/* === umf_config.h ========================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/*
This file controls the compile-time configuration of UMFPACK. Modify the
UFconfig/UFconfig.mk file and this file if necessary, to control these
options. The following flags may be given as options to your C compiler
(as in "cc -DNSUNPERF", for example). These flags are normally placed in
your UMFPACK_CONFIG string, defined in the UFconfig/UFconfig.mk file.
All of these options, except for the timer, are for accessing the BLAS.
-DNSUNPERF
Applies only to Sun Solaris. If -DNSUNPERF is set, then the Sun
Performance Library BLAS will not be used.
The Sun Performance Library BLAS is used by default when compiling
the C-callable libumfpack.a library on Sun Solaris.
-DLONGBLAS
-DNPOSIX
If -DNPOSIX is set, then your Unix operating system is not POSIX-
compliant, and the POSIX routines sysconf ( ) and times ( )
routines are not used. These routines provide CPU time and
wallclock time information. If -DNPOSIX is set, then the ANSI
C clock ( ) routine is used. If -DNPOSIX is not set, then
sysconf ( ) and times ( ) are used in umfpack_tic and umfpack_toc.
See umfpack_tictoc.c for more information.
The default is to use the POSIX routines, except for Windows,
which is not POSIX-compliant.
-DGETRUSAGE
If -DGETRUSAGE is set, then your system's getrusage ( ) routine
will be used for getting the process CPU time. Otherwise the ANSI
C clock ( ) routine will be used. The default is to use getrusage
( ) on Unix systems, and to use clock on all other architectures.
-DNO_TIMER
If -DNO_TIMER is set, then no timing routines are used at all.
-DNRECIPROCAL
This option controls a tradeoff between speed and accuracy. Using
-DNRECIPROCAL can lead to more accurate results, but with perhaps
some cost in performance, particularly if floating-point division
is much more costly than floating-point multiplication.
This option determines the method used to scale the pivot column.
If set, or if the absolute value of the pivot is < 1e-12 (or is a
NaN), then the pivot column is divided by the pivot value.
Otherwise, the reciprocal of the pivot value is computed, and the
pivot column is multiplied by (1/pivot). Multiplying by the
reciprocal can be slightly less accurate than dividing by the
pivot, but it is often faster. See umf_scale.c.
This has a small effect on the performance of UMFPACK, at least on
a Pentium 4M. It may have a larger effect on other architectures
where floating-point division is much more costly than floating-
point multiplication. The RS 6000 is one such example.
By default, the method chosen is to multiply by the reciprocal
(sacrificing accuracy for speed), except when compiling UMFPACK
as a built-in routine in MATLAB, or when gcc is being used.
When MATHWORKS is defined, -DNRECIPROCAL is forced on, and the pivot
column is divided by the pivot value. The only way of using the
other method in this case is to edit this file.
If -DNRECIPROCAL is enabled, then the row scaling factors are always
applied by dividing each row by the scale factor, rather than
multiplying by the reciprocal. If -DNRECIPROCAL is not enabled
(the default case), then the scale factors are normally applied by
multiplying by the reciprocal. If, however, the smallest scale
factor is tiny, then the scale factors are applied via division.
-DNO_DIVIDE_BY_ZERO
If the pivot is zero, and this flag is set, then no divide-by-zero
occurs.
The following options are controlled by amd_internal.h:
-DMATLAB_MEX_FILE
This flag is turned on when compiling the umfpack mexFunction for
use in MATLAB. The -DNRECIPROCAL flag is forced on (more accurate,
slightly slower). The umfpack mexFunction always returns
L*U = P*(R\A)*Q.
-DMATHWORKS
This flag is turned on when compiling umfpack as a built-in routine
in MATLAB. The -DNRECIPROCAL flag is forced on.
-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.
*/
/* ========================================================================== */
/* === AMD configuration ==================================================== */
/* ========================================================================== */
/* NDEBUG, PRINTF defined in amd_internal.h */
/* ========================================================================== */
/* === reciprocal option ==================================================== */
/* ========================================================================== */
/* Force the definition NRECIPROCAL when MATHWORKS or MATLAB_MEX_FILE
* are defined. Do not multiply by the reciprocal in those cases. */
#ifndef NRECIPROCAL
#if defined (MATHWORKS) || defined (MATLAB_MEX_FILE)
#define NRECIPROCAL
#endif
#endif
/* ========================================================================== */
/* === Microsoft Windows configuration ====================================== */
/* ========================================================================== */
#if defined (UMF_WINDOWS) || defined (UMF_MINGW)
/* Windows isn't Unix. Profound. */
#define NPOSIX
#endif
/* ========================================================================== */
/* === 0-based or 1-based printing ========================================== */
/* ========================================================================== */
#if defined (MATLAB_MEX_FILE) && defined (NDEBUG)
/* In MATLAB, matrices are 1-based to the user, but 0-based internally. */
/* One is added to all row and column indices when printing matrices */
/* for the MATLAB user. The +1 shift is turned off when debugging. */
#define INDEX(i) ((i)+1)
#else
/* In ANSI C, matrices are 0-based and indices are reported as such. */
/* This mode is also used for debug mode, and if MATHWORKS is defined rather */
/* than MATLAB_MEX_FILE. */
#define INDEX(i) (i)
#endif
/* ========================================================================== */
/* === Timer ================================================================ */
/* ========================================================================== */
/*
If you have the getrusage routine (all Unix systems I've test do), then use
that. Otherwise, use the ANSI C clock function. Note that on many
systems, the ANSI clock function wraps around after only 2147 seconds, or
about 36 minutes. BE CAREFUL: if you compare the run time of UMFPACK with
other sparse matrix packages, be sure to use the same timer. See
umfpack_tictoc.c for the timer used internally by UMFPACK. See also
umfpack_timer.c for the timer used in an earlier version of UMFPACK.
That timer is still available as a user-callable routine, but it is no
longer used internally by UMFPACK.
*/
/* Sun Solaris, SGI Irix, Linux, Compaq Alpha, and IBM RS 6000 all have */
/* getrusage. It's in BSD unix, so perhaps all unix systems have it. */
#if defined (UMF_SOL2) || defined (UMF_SGI) || defined (UMF_LINUX) \
|| defined (UMF_ALPHA) || defined (UMF_AIX) || defined (UMF_CYGWIN) \
|| defined (UMF_MAC)
#define GETRUSAGE
#endif
/* ========================================================================== */
/* === BLAS ================================================================= */
/* ========================================================================== */
#define BLAS_OK blas_ok
#include "cholmod_blas.h"
/* -------------------------------------------------------------------------- */
/* DGEMM */
/* -------------------------------------------------------------------------- */
/* C = C - A*B', where:
* A is m-by-k with leading dimension ldac
* B is k-by-n with leading dimension ldb
* C is m-by-n with leading dimension ldac */
#ifdef COMPLEX
#define BLAS_GEMM(m,n,k,A,B,ldb,C,ldac) \
{ \
double alpha [2] = {-1,0}, beta [2] = {1,0} ; \
BLAS_zgemm ("N", "T", m, n, k, alpha, (double *) A, ldac, \
(double *) B, ldb, beta, (double *) C, ldac) ; \
}
#else
#define BLAS_GEMM(m,n,k,A,B,ldb,C,ldac) \
{ \
double alpha = -1, beta = 1 ; \
BLAS_dgemm ("N", "T", m, n, k, &alpha, A, ldac, B, ldb, &beta, C, ldac) ; \
}
#endif
/* -------------------------------------------------------------------------- */
/* GER */
/* -------------------------------------------------------------------------- */
/* A = A - x*y', where:
* A is m-by-n with leading dimension d
x is a column vector with stride 1
y is a column vector with stride 1 */
#ifdef COMPLEX
#define BLAS_GER(m,n,x,y,A,d) \
{ \
double alpha [2] = {-1,0} ; \
BLAS_zgeru (m, n, alpha, (double *) x, 1, (double *) y, 1, \
(double *) A, d) ; \
}
#else
#define BLAS_GER(m,n,x,y,A,d) \
{ \
double alpha = -1 ; \
BLAS_dger (m, n, &alpha, x, 1, y, 1, A, d) ; \
}
#endif
/* -------------------------------------------------------------------------- */
/* GEMV */
/* -------------------------------------------------------------------------- */
/* y = y - A*x, where A is m-by-n with leading dimension d,
x is a column vector with stride 1
y is a column vector with stride 1 */
#ifdef COMPLEX
#define BLAS_GEMV(m,n,A,x,y,d) \
{ \
double alpha [2] = {-1,0}, beta [2] = {1,0} ; \
BLAS_zgemv ("N", m, n, alpha, (double *) A, d, (double *) x, 1, beta, \
(double *) y, 1) ; \
}
#else
#define BLAS_GEMV(m,n,A,x,y,d) \
{ \
double alpha = -1, beta = 1 ; \
BLAS_dgemv ("N", m, n, &alpha, A, d, x, 1, &beta, y, 1) ; \
}
#endif
/* -------------------------------------------------------------------------- */
/* TRSV */
/* -------------------------------------------------------------------------- */
/* solve Lx=b, where:
* B is a column vector (m-by-1) with leading dimension d
* A is m-by-m with leading dimension d */
#ifdef COMPLEX
#define BLAS_TRSV(m,A,b,d) \
{ \
BLAS_ztrsv ("L", "N", "U", m, (double *) A, d, (double *) b, 1) ; \
}
#else
#define BLAS_TRSV(m,A,b,d) \
{ \
BLAS_dtrsv ("L", "N", "U", m, A, d, b, 1) ; \
}
#endif
/* -------------------------------------------------------------------------- */
/* TRSM */
/* -------------------------------------------------------------------------- */
/* solve XL'=B where:
* B is m-by-n with leading dimension ldb
* A is n-by-n with leading dimension lda */
#ifdef COMPLEX
#define BLAS_TRSM_RIGHT(m,n,A,lda,B,ldb) \
{ \
double alpha [2] = {1,0} ; \
BLAS_ztrsm ("R", "L", "T", "U", m, n, alpha, (double *) A, lda, \
(double *) B, ldb) ; \
}
#else
#define BLAS_TRSM_RIGHT(m,n,A,lda,B,ldb) \
{ \
double alpha = 1 ; \
BLAS_dtrsm ("R", "L", "T", "U", m, n, &alpha, A, lda, B, ldb) ; \
}
#endif
/* -------------------------------------------------------------------------- */
/* SCAL */
/* -------------------------------------------------------------------------- */
/* x = s*x, where x is a stride-1 vector of length n */
#ifdef COMPLEX
#define BLAS_SCAL(n,s,x) \
{ \
double alpha [2] ; \
alpha [0] = REAL_COMPONENT (s) ; \
alpha [1] = IMAG_COMPONENT (s) ; \
BLAS_zscal (n, alpha, (double *) x, 1) ; \
}
#else
#define BLAS_SCAL(n,s,x) \
{ \
double alpha = REAL_COMPONENT (s) ; \
BLAS_dscal (n, &alpha, (double *) x, 1) ; \
}
#endif

View File

@ -0,0 +1,593 @@
/* ========================================================================== */
/* === UMF_create_element =================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/*
Factorization of a frontal matrix is complete. Create a new element for
later assembly into a subsequent frontal matrix. Returns TRUE if
successful, FALSE if out of memory.
*/
#include "umf_internal.h"
#include "umf_create_element.h"
#include "umf_mem_alloc_element.h"
#include "umf_mem_alloc_tail_block.h"
#include "umf_mem_free_tail_block.h"
#include "umf_get_memory.h"
/* ========================================================================== */
/* === copy_column ========================================================== */
/* ========================================================================== */
PRIVATE void copy_column (Int len, Entry *X, Entry *Y)
{
Int i ;
#pragma ivdep
for (i = 0 ; i < len ; i++)
{
Y [i] = X [i] ;
}
}
/* ========================================================================== */
/* === UMF_create_element =================================================== */
/* ========================================================================== */
GLOBAL Int UMF_create_element
(
NumericType *Numeric,
WorkType *Work,
SymbolicType *Symbolic
)
{
/* ---------------------------------------------------------------------- */
/* local variables */
/* ---------------------------------------------------------------------- */
Int j, col, row, *Fcols, *Frows, fnrows, fncols, *Cols, len, needunits, t1,
t2, size, e, i, *E, *Fcpos, *Frpos, *Rows, eloc, fnr_curr, f,
got_memory, *Row_tuples, *Row_degree, *Row_tlen, *Col_tuples, max_mark,
*Col_degree, *Col_tlen, nn, n_row, n_col, r2, c2, do_Fcpos ;
Entry *C, *Fcol ;
Element *ep ;
Unit *p, *Memory ;
Tuple *tp, *tp1, *tp2, tuple, *tpend ;
#ifndef NDEBUG
DEBUG2 (("FRONTAL WRAPUP\n")) ;
UMF_dump_current_front (Numeric, Work, TRUE) ;
#endif
/* ---------------------------------------------------------------------- */
/* get parameters */
/* ---------------------------------------------------------------------- */
ASSERT (Work->fnpiv == 0) ;
ASSERT (Work->fnzeros == 0) ;
Row_degree = Numeric->Rperm ;
Row_tuples = Numeric->Uip ;
Row_tlen = Numeric->Uilen ;
Col_degree = Numeric->Cperm ;
Col_tuples = Numeric->Lip ;
Col_tlen = Numeric->Lilen ;
n_row = Work->n_row ;
n_col = Work->n_col ;
nn = MAX (n_row, n_col) ;
Fcols = Work->Fcols ;
Frows = Work->Frows ;
Fcpos = Work->Fcpos ;
Frpos = Work->Frpos ;
Memory = Numeric->Memory ;
fncols = Work->fncols ;
fnrows = Work->fnrows ;
tp = (Tuple *) NULL ;
tp1 = (Tuple *) NULL ;
tp2 = (Tuple *) NULL ;
/* ---------------------------------------------------------------------- */
/* add the current frontal matrix to the degrees of each column */
/* ---------------------------------------------------------------------- */
if (!Symbolic->fixQ)
{
/* but only if the column ordering is not fixed */
#pragma ivdep
for (j = 0 ; j < fncols ; j++)
{
/* add the current frontal matrix to the degree */
ASSERT (Fcols [j] >= 0 && Fcols [j] < n_col) ;
Col_degree [Fcols [j]] += fnrows ;
}
}
/* ---------------------------------------------------------------------- */
/* add the current frontal matrix to the degrees of each row */
/* ---------------------------------------------------------------------- */
#pragma ivdep
for (i = 0 ; i < fnrows ; i++)
{
/* add the current frontal matrix to the degree */
ASSERT (Frows [i] >= 0 && Frows [i] < n_row) ;
Row_degree [Frows [i]] += fncols ;
}
/* ---------------------------------------------------------------------- */
/* Reset the external degree counters */
/* ---------------------------------------------------------------------- */
E = Work->E ;
max_mark = MAX_MARK (nn) ;
if (!Work->pivcol_in_front)
{
/* clear the external column degrees. no more Usons of current front */
Work->cdeg0 += (nn + 1) ;
if (Work->cdeg0 >= max_mark)
{
/* guard against integer overflow. This is very rare */
DEBUG1 (("Integer overflow, cdeg\n")) ;
Work->cdeg0 = 1 ;
#pragma ivdep
for (e = 1 ; e <= Work->nel ; e++)
{
if (E [e])
{
ep = (Element *) (Memory + E [e]) ;
ep->cdeg = 0 ;
}
}
}
}
if (!Work->pivrow_in_front)
{
/* clear the external row degrees. no more Lsons of current front */
Work->rdeg0 += (nn + 1) ;
if (Work->rdeg0 >= max_mark)
{
/* guard against integer overflow. This is very rare */
DEBUG1 (("Integer overflow, rdeg\n")) ;
Work->rdeg0 = 1 ;
#pragma ivdep
for (e = 1 ; e <= Work->nel ; e++)
{
if (E [e])
{
ep = (Element *) (Memory + E [e]) ;
ep->rdeg = 0 ;
}
}
}
}
/* ---------------------------------------------------------------------- */
/* clear row/col offsets */
/* ---------------------------------------------------------------------- */
if (!Work->pivrow_in_front)
{
#pragma ivdep
for (j = 0 ; j < fncols ; j++)
{
Fcpos [Fcols [j]] = EMPTY ;
}
}
if (!Work->pivcol_in_front)
{
#pragma ivdep
for (i = 0 ; i < fnrows ; i++)
{
Frpos [Frows [i]] = EMPTY ;
}
}
if (fncols <= 0 || fnrows <= 0)
{
/* no element to create */
DEBUG2 (("Element evaporation\n")) ;
Work->prior_element = EMPTY ;
return (TRUE) ;
}
/* ---------------------------------------------------------------------- */
/* create element for later assembly */
/* ---------------------------------------------------------------------- */
#ifndef NDEBUG
UMF_allocfail = FALSE ;
if (UMF_gprob > 0)
{
double rrr = ((double) (rand ( ))) / (((double) RAND_MAX) + 1) ;
DEBUG4 (("Check random %e %e\n", rrr, UMF_gprob)) ;
UMF_allocfail = rrr < UMF_gprob ;
if (UMF_allocfail) DEBUGm2 (("Random garbage collection (create)\n"));
}
#endif
needunits = 0 ;
got_memory = FALSE ;
eloc = UMF_mem_alloc_element (Numeric, fnrows, fncols, &Rows, &Cols, &C,
&needunits, &ep) ;
/* if UMF_get_memory needs to be called */
if (Work->do_grow)
{
/* full compaction of current frontal matrix, since UMF_grow_front will
* be called next anyway. */
r2 = fnrows ;
c2 = fncols ;
do_Fcpos = FALSE ;
}
else
{
/* partial compaction. */
r2 = MAX (fnrows, Work->fnrows_new + 1) ;
c2 = MAX (fncols, Work->fncols_new + 1) ;
/* recompute Fcpos if pivot row is in the front */
do_Fcpos = Work->pivrow_in_front ;
}
if (!eloc)
{
/* Do garbage collection, realloc, and try again. */
/* Compact the current front if it needs to grow anyway. */
/* Note that there are no pivot rows or columns in the current front */
DEBUGm3 (("get_memory from umf_create_element, 1\n")) ;
if (!UMF_get_memory (Numeric, Work, needunits, r2, c2, do_Fcpos))
{
/* :: out of memory in umf_create_element (1) :: */
DEBUGm4 (("out of memory: create element (1)\n")) ;
return (FALSE) ; /* out of memory */
}
got_memory = TRUE ;
Memory = Numeric->Memory ;
eloc = UMF_mem_alloc_element (Numeric, fnrows, fncols, &Rows, &Cols, &C,
&needunits, &ep) ;
ASSERT (eloc >= 0) ;
if (!eloc)
{
/* :: out of memory in umf_create_element (2) :: */
DEBUGm4 (("out of memory: create element (2)\n")) ;
return (FALSE) ; /* out of memory */
}
}
e = ++(Work->nel) ; /* get the name of this new frontal matrix */
Work->prior_element = e ;
DEBUG8 (("wrapup e "ID" nel "ID"\n", e, Work->nel)) ;
ASSERT (e > 0 && e < Work->elen) ;
ASSERT (E [e] == 0) ;
E [e] = eloc ;
if (Work->pivcol_in_front)
{
/* the new element is a Uson of the next frontal matrix */
ep->cdeg = Work->cdeg0 ;
}
if (Work->pivrow_in_front)
{
/* the new element is an Lson of the next frontal matrix */
ep->rdeg = Work->rdeg0 ;
}
/* ---------------------------------------------------------------------- */
/* copy frontal matrix into the new element */
/* ---------------------------------------------------------------------- */
#pragma ivdep
for (i = 0 ; i < fnrows ; i++)
{
Rows [i] = Frows [i] ;
}
#pragma ivdep
for (i = 0 ; i < fncols ; i++)
{
Cols [i] = Fcols [i] ;
}
Fcol = Work->Fcblock ;
DEBUG0 (("copy front "ID" by "ID"\n", fnrows, fncols)) ;
fnr_curr = Work->fnr_curr ;
ASSERT (fnr_curr >= 0 && fnr_curr % 2 == 1) ;
for (j = 0 ; j < fncols ; j++)
{
copy_column (fnrows, Fcol, C) ;
Fcol += fnr_curr ;
C += fnrows ;
}
DEBUG8 (("element copied\n")) ;
/* ---------------------------------------------------------------------- */
/* add tuples for the new element */
/* ---------------------------------------------------------------------- */
tuple.e = e ;
if (got_memory)
{
/* ------------------------------------------------------------------ */
/* UMF_get_memory ensures enough space exists for each new tuple */
/* ------------------------------------------------------------------ */
/* place (e,f) in the element list of each column */
for (tuple.f = 0 ; tuple.f < fncols ; tuple.f++)
{
col = Fcols [tuple.f] ;
ASSERT (col >= 0 && col < n_col) ;
ASSERT (NON_PIVOTAL_COL (col)) ;
ASSERT (Col_tuples [col]) ;
tp = ((Tuple *) (Memory + Col_tuples [col])) + Col_tlen [col]++ ;
*tp = tuple ;
}
/* ------------------------------------------------------------------ */
/* place (e,f) in the element list of each row */
for (tuple.f = 0 ; tuple.f < fnrows ; tuple.f++)
{
row = Frows [tuple.f] ;
ASSERT (row >= 0 && row < n_row) ;
ASSERT (NON_PIVOTAL_ROW (row)) ;
ASSERT (Row_tuples [row]) ;
tp = ((Tuple *) (Memory + Row_tuples [row])) + Row_tlen [row]++ ;
*tp = tuple ;
}
}
else
{
/* ------------------------------------------------------------------ */
/* place (e,f) in the element list of each column */
/* ------------------------------------------------------------------ */
/* might not have enough space for each tuple */
for (tuple.f = 0 ; tuple.f < fncols ; tuple.f++)
{
col = Fcols [tuple.f] ;
ASSERT (col >= 0 && col < n_col) ;
ASSERT (NON_PIVOTAL_COL (col)) ;
t1 = Col_tuples [col] ;
DEBUG1 (("Placing on col:"ID" , tuples at "ID"\n",
col, Col_tuples [col])) ;
size = 0 ;
len = 0 ;
if (t1)
{
p = Memory + t1 ;
tp = (Tuple *) p ;
size = GET_BLOCK_SIZE (p) ;
len = Col_tlen [col] ;
tp2 = tp + len ;
}
needunits = UNITS (Tuple, len + 1) ;
DEBUG1 (("len: "ID" size: "ID" needunits: "ID"\n",
len, size, needunits));
if (needunits > size && t1)
{
/* prune the tuples */
tp1 = tp ;
tp2 = tp ;
tpend = tp + len ;
for ( ; tp < tpend ; tp++)
{
e = tp->e ;
ASSERT (e > 0 && e <= Work->nel) ;
if (!E [e]) continue ; /* element already deallocated */
f = tp->f ;
p = Memory + E [e] ;
ep = (Element *) p ;
p += UNITS (Element, 1) ;
Cols = (Int *) p ;
;
if (Cols [f] == EMPTY) continue ; /* already assembled */
ASSERT (col == Cols [f]) ;
*tp2++ = *tp ; /* leave the tuple in the list */
}
len = tp2 - tp1 ;
Col_tlen [col] = len ;
needunits = UNITS (Tuple, len + 1) ;
}
if (needunits > size)
{
/* no room exists - reallocate elsewhere */
DEBUG1 (("REALLOCATE Col: "ID", size "ID" to "ID"\n",
col, size, 2*needunits)) ;
#ifndef NDEBUG
UMF_allocfail = FALSE ;
if (UMF_gprob > 0) /* a double relop, but ignore NaN case */
{
double rrr = ((double) (rand ( ))) /
(((double) RAND_MAX) + 1) ;
DEBUG1 (("Check random %e %e\n", rrr, UMF_gprob)) ;
UMF_allocfail = rrr < UMF_gprob ;
if (UMF_allocfail) DEBUGm2 (("Random gar. (col tuple)\n")) ;
}
#endif
needunits = MIN (2*needunits, (Int) UNITS (Tuple, nn)) ;
t2 = UMF_mem_alloc_tail_block (Numeric, needunits) ;
if (!t2)
{
/* :: get memory in umf_create_element (1) :: */
/* get memory, reconstruct all tuple lists, and return */
/* Compact the current front if it needs to grow anyway. */
/* Note: no pivot rows or columns in the current front */
DEBUGm4 (("get_memory from umf_create_element, 1\n")) ;
return (UMF_get_memory (Numeric, Work, 0, r2, c2,do_Fcpos));
}
Col_tuples [col] = t2 ;
tp2 = (Tuple *) (Memory + t2) ;
if (t1)
{
for (i = 0 ; i < len ; i++)
{
*tp2++ = *tp1++ ;
}
UMF_mem_free_tail_block (Numeric, t1) ;
}
}
/* place the new (e,f) tuple in the element list of the column */
Col_tlen [col]++ ;
*tp2 = tuple ;
}
/* ------------------------------------------------------------------ */
/* place (e,f) in the element list of each row */
/* ------------------------------------------------------------------ */
for (tuple.f = 0 ; tuple.f < fnrows ; tuple.f++)
{
row = Frows [tuple.f] ;
ASSERT (row >= 0 && row < n_row) ;
ASSERT (NON_PIVOTAL_ROW (row)) ;
t1 = Row_tuples [row] ;
DEBUG1 (("Placing on row:"ID" , tuples at "ID"\n",
row, Row_tuples [row])) ;
size = 0 ;
len = 0 ;
if (t1)
{
p = Memory + t1 ;
tp = (Tuple *) p ;
size = GET_BLOCK_SIZE (p) ;
len = Row_tlen [row] ;
tp2 = tp + len ;
}
needunits = UNITS (Tuple, len + 1) ;
DEBUG1 (("len: "ID" size: "ID" needunits: "ID"\n",
len, size, needunits)) ;
if (needunits > size && t1)
{
/* prune the tuples */
tp1 = tp ;
tp2 = tp ;
tpend = tp + len ;
for ( ; tp < tpend ; tp++)
{
e = tp->e ;
ASSERT (e > 0 && e <= Work->nel) ;
if (!E [e])
{
continue ; /* element already deallocated */
}
f = tp->f ;
p = Memory + E [e] ;
ep = (Element *) p ;
p += UNITS (Element, 1) ;
Cols = (Int *) p ;
Rows = Cols + (ep->ncols) ;
if (Rows [f] == EMPTY) continue ; /* already assembled */
ASSERT (row == Rows [f]) ;
*tp2++ = *tp ; /* leave the tuple in the list */
}
len = tp2 - tp1 ;
Row_tlen [row] = len ;
needunits = UNITS (Tuple, len + 1) ;
}
if (needunits > size)
{
/* no room exists - reallocate elsewhere */
DEBUG1 (("REALLOCATE Row: "ID", size "ID" to "ID"\n",
row, size, 2*needunits)) ;
#ifndef NDEBUG
UMF_allocfail = FALSE ;
if (UMF_gprob > 0) /* a double relop, but ignore NaN case */
{
double rrr = ((double) (rand ( ))) /
(((double) RAND_MAX) + 1) ;
DEBUG1 (("Check random %e %e\n", rrr, UMF_gprob)) ;
UMF_allocfail = rrr < UMF_gprob ;
if (UMF_allocfail) DEBUGm2 (("Random gar. (row tuple)\n")) ;
}
#endif
needunits = MIN (2*needunits, (Int) UNITS (Tuple, nn)) ;
t2 = UMF_mem_alloc_tail_block (Numeric, needunits) ;
if (!t2)
{
/* :: get memory in umf_create_element (2) :: */
/* get memory, reconstruct all tuple lists, and return */
/* Compact the current front if it needs to grow anyway. */
/* Note: no pivot rows or columns in the current front */
DEBUGm4 (("get_memory from umf_create_element, 2\n")) ;
return (UMF_get_memory (Numeric, Work, 0, r2, c2,do_Fcpos));
}
Row_tuples [row] = t2 ;
tp2 = (Tuple *) (Memory + t2) ;
if (t1)
{
for (i = 0 ; i < len ; i++)
{
*tp2++ = *tp1++ ;
}
UMF_mem_free_tail_block (Numeric, t1) ;
}
}
/* place the new (e,f) tuple in the element list of the row */
Row_tlen [row]++ ;
*tp2 = tuple ;
}
}
/* ---------------------------------------------------------------------- */
#ifndef NDEBUG
DEBUG1 (("Done extending\nFINAL: element row pattern: len="ID"\n", fncols));
for (j = 0 ; j < fncols ; j++) DEBUG1 ((""ID"\n", Fcols [j])) ;
DEBUG1 (("FINAL: element col pattern: len="ID"\n", fnrows)) ;
for (j = 0 ; j < fnrows ; j++) DEBUG1 ((""ID"\n", Frows [j])) ;
for (j = 0 ; j < fncols ; j++)
{
col = Fcols [j] ;
ASSERT (col >= 0 && col < n_col) ;
UMF_dump_rowcol (1, Numeric, Work, col, !Symbolic->fixQ) ;
}
for (j = 0 ; j < fnrows ; j++)
{
row = Frows [j] ;
ASSERT (row >= 0 && row < n_row) ;
UMF_dump_rowcol (0, Numeric, Work, row, TRUE) ;
}
if (n_row < 1000 && n_col < 1000)
{
UMF_dump_memory (Numeric) ;
}
DEBUG1 (("New element, after filling with stuff: "ID"\n", e)) ;
UMF_dump_element (Numeric, Work, e, TRUE) ;
if (nn < 1000)
{
DEBUG4 (("Matrix dump, after New element: "ID"\n", e)) ;
UMF_dump_matrix (Numeric, Work, TRUE) ;
}
DEBUG3 (("FRONTAL WRAPUP DONE\n")) ;
#endif
return (TRUE) ;
}

View File

@ -0,0 +1,12 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL Int UMF_create_element
(
NumericType *Numeric,
WorkType *Work,
SymbolicType *Symbolic
) ;

1205
src/maths/UMFPACK/umf_dump.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,189 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/* umf_dump.h: debugging definitions. */
#ifndef NDEBUG
GLOBAL void UMF_dump_dense
(
Entry *C,
Int dim,
Int m,
Int n
) ;
GLOBAL void UMF_dump_element
(
NumericType *Numeric,
WorkType *Work,
Int e,
Int clean
) ;
GLOBAL void UMF_dump_rowcol
(
Int dump_which,
NumericType *Numeric,
WorkType *Work,
Int dump_index,
Int check_degree
) ;
GLOBAL void UMF_dump_matrix
(
NumericType *Numeric,
WorkType *Work,
Int check_degree
) ;
GLOBAL void UMF_dump_current_front
(
NumericType *Numeric,
WorkType *Work,
Int check
) ;
GLOBAL void UMF_dump_lu
(
NumericType *Numeric
) ;
GLOBAL void UMF_dump_memory
(
NumericType *Numeric
) ;
GLOBAL void UMF_dump_packed_memory
(
NumericType *Numeric,
WorkType *Work
) ;
GLOBAL void UMF_dump_col_matrix
(
const double Ax [ ],
#ifdef COMPLEX
const double Az [ ],
#endif
const Int Ai [ ],
const Int Ap [ ],
Int n_row,
Int n_col,
Int nz
) ;
GLOBAL void UMF_dump_chain
(
Int frontid,
Int Front_parent [ ],
Int Front_npivcol [ ],
Int Front_nrows [ ],
Int Front_ncols [ ],
Int nfr
) ;
GLOBAL void UMF_dump_rowmerge
(
NumericType *Numeric,
SymbolicType *Symbolic,
WorkType *Work
) ;
GLOBAL void UMF_dump_start
(
void
) ;
GLOBAL void UMF_dump_diagonal_map
(
Int Diagonal_map [ ],
Int Diagonal_imap [ ],
Int nn
) ;
#define UMF_DBMAX 50000
#ifndef EXTERN
#define EXTERN extern
#endif
GLOBAL EXTERN Int UMF_debug ;
GLOBAL EXTERN Int UMF_allocfail ;
GLOBAL EXTERN double UMF_gprob ;
#define DEBUGk(k,params) { if (UMF_debug >= (k)) { PRINTF (params) ; } }
#define DEBUGm4(params) DEBUGk (-4, params)
#define DEBUGm3(params) DEBUGk (-3, params)
#define DEBUGm2(params) DEBUGk (-2, params)
#define DEBUGm1(params) DEBUGk (-1, params)
#define DEBUG0(params) DEBUGk (0, params)
#define DEBUG1(params) DEBUGk (1, params)
#define DEBUG2(params) DEBUGk (2, params)
#define DEBUG3(params) DEBUGk (3, params)
#define DEBUG4(params) DEBUGk (4, params)
#define DEBUG5(params) DEBUGk (5, params)
#define DEBUG6(params) DEBUGk (6, params)
#define DEBUG7(params) DEBUGk (7, params)
#define DEBUG8(params) DEBUGk (8, params)
#define DEBUG9(params) DEBUGk (9, params)
#define EDEBUGk(k,a) { if (UMF_debug >= (k)) { PRINT_ENTRY (a) ; } }
#define EDEBUG0(a) EDEBUGk (0, a)
#define EDEBUG1(a) EDEBUGk (1, a)
#define EDEBUG2(a) EDEBUGk (2, a)
#define EDEBUG3(a) EDEBUGk (3, a)
#define EDEBUG4(a) EDEBUGk (4, a)
#define EDEBUG5(a) EDEBUGk (5, a)
#define EDEBUG6(a) EDEBUGk (6, a)
#define EDEBUG7(a) EDEBUGk (7, a)
#define EDEBUG8(a) EDEBUGk (8, a)
#define EDEBUG9(a) EDEBUGk (9, a)
/* ASSERT defined in amd_dump.h */
#else
/* ========================================================================== */
/* === No debugging ========================================================= */
/* ========================================================================== */
/* turn off all debugging macros */
#define DEBUGk(k,params)
#define DEBUGm4(params)
#define DEBUGm3(params)
#define DEBUGm2(params)
#define DEBUGm1(params)
#define DEBUG0(params)
#define DEBUG1(params)
#define DEBUG2(params)
#define DEBUG3(params)
#define DEBUG4(params)
#define DEBUG5(params)
#define DEBUG6(params)
#define DEBUG7(params)
#define DEBUG8(params)
#define DEBUG9(params)
#define EDEBUGk(k,a)
#define EDEBUG0(a)
#define EDEBUG1(a)
#define EDEBUG2(a)
#define EDEBUG3(a)
#define EDEBUG4(a)
#define EDEBUG5(a)
#define EDEBUG6(a)
#define EDEBUG7(a)
#define EDEBUG8(a)
#define EDEBUG9(a)
#endif /* NDEBUG */

View File

@ -0,0 +1,393 @@
/* ========================================================================== */
/* === UMF_extend_front ===================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/* Called by kernel. */
#include "umf_internal.h"
#include "umf_extend_front.h"
#include "umf_grow_front.h"
/* ========================================================================== */
/* === zero_front =========================================================== */
/* ========================================================================== */
PRIVATE void zero_front (
Entry *Flblock, Entry *Fublock, Entry *Fcblock,
Int fnrows, Int fncols, Int fnr_curr, Int fnc_curr,
Int fnpiv, Int fnrows_extended, Int fncols_extended)
{
Int j, i ;
Entry *F, *Fj, *Fi ;
Fj = Fcblock + fnrows ;
for (j = 0 ; j < fncols ; j++)
{
/* zero the new rows in the contribution block: */
F = Fj ;
Fj += fnr_curr ;
#pragma ivdep
for (i = fnrows ; i < fnrows_extended ; i++)
{
/* CLEAR (Fcblock [i + j*fnr_curr]) ; */
CLEAR_AND_INCREMENT (F) ;
}
}
Fj -= fnrows ;
for (j = fncols ; j < fncols_extended ; j++)
{
/* zero the new columns in the contribution block: */
F = Fj ;
Fj += fnr_curr ;
#pragma ivdep
for (i = 0 ; i < fnrows_extended ; i++)
{
/* CLEAR (Fcblock [i + j*fnr_curr]) ; */
CLEAR_AND_INCREMENT (F) ;
}
}
Fj = Flblock + fnrows ;
for (j = 0 ; j < fnpiv ; j++)
{
/* zero the new rows in L block: */
F = Fj ;
Fj += fnr_curr ;
#pragma ivdep
for (i = fnrows ; i < fnrows_extended ; i++)
{
/* CLEAR (Flblock [i + j*fnr_curr]) ; */
CLEAR_AND_INCREMENT (F) ;
}
}
Fi = Fublock + fncols ;
for (i = 0 ; i < fnpiv ; i++)
{
/* zero the new columns in U block: */
F = Fi ;
Fi += fnc_curr ;
#pragma ivdep
for (j = fncols ; j < fncols_extended ; j++)
{
/* CLEAR (Fublock [i*fnc_curr + j]) ; */
CLEAR_AND_INCREMENT (F) ;
}
}
}
/* ========================================================================== */
/* === UMF_extend_front ===================================================== */
/* ========================================================================== */
GLOBAL Int UMF_extend_front
(
NumericType *Numeric,
WorkType *Work
)
{
/* ---------------------------------------------------------------------- */
/* local variables */
/* ---------------------------------------------------------------------- */
Int j, i, *Frows, row, col, *Wrow, fnr2, fnc2, *Frpos, *Fcpos, *Fcols,
fnrows_extended, rrdeg, ccdeg, fncols_extended, fnr_curr, fnc_curr,
fnrows, fncols, pos, fnpiv, *Wm ;
Entry *Wx, *Wy, *Fu, *Fl ;
/* ---------------------------------------------------------------------- */
/* get current frontal matrix and check for frontal growth */
/* ---------------------------------------------------------------------- */
fnpiv = Work->fnpiv ;
#ifndef NDEBUG
DEBUG2 (("EXTEND FRONT\n")) ;
DEBUG2 (("Work->fnpiv "ID"\n", fnpiv)) ;
ASSERT (Work->Flblock == Work->Flublock + Work->nb*Work->nb) ;
ASSERT (Work->Fublock == Work->Flblock + Work->fnr_curr*Work->nb) ;
ASSERT (Work->Fcblock == Work->Fublock + Work->nb*Work->fnc_curr) ;
DEBUG7 (("C block: ")) ;
UMF_dump_dense (Work->Fcblock, Work->fnr_curr, Work->fnrows, Work->fncols) ;
DEBUG7 (("L block: ")) ;
UMF_dump_dense (Work->Flblock, Work->fnr_curr, Work->fnrows, fnpiv);
DEBUG7 (("U' block: ")) ;
UMF_dump_dense (Work->Fublock, Work->fnc_curr, Work->fncols, fnpiv) ;
DEBUG7 (("LU block: ")) ;
UMF_dump_dense (Work->Flublock, Work->nb, fnpiv, fnpiv) ;
#endif
if (Work->do_grow)
{
fnr2 = UMF_FRONTAL_GROWTH * Work->fnrows_new + 2 ;
fnc2 = UMF_FRONTAL_GROWTH * Work->fncols_new + 2 ;
if (!UMF_grow_front (Numeric, fnr2, fnc2, Work, 1))
{
DEBUGm4 (("out of memory: extend front\n")) ;
return (FALSE) ;
}
}
fnr_curr = Work->fnr_curr ;
fnc_curr = Work->fnc_curr ;
ASSERT (Work->fnrows_new + 1 <= fnr_curr) ;
ASSERT (Work->fncols_new + 1 <= fnc_curr) ;
ASSERT (fnr_curr >= 0 && fnr_curr % 2 == 1) ;
/* ---------------------------------------------------------------------- */
/* get parameters */
/* ---------------------------------------------------------------------- */
Frows = Work->Frows ;
Frpos = Work->Frpos ;
Fcols = Work->Fcols ;
Fcpos = Work->Fcpos ;
fnrows = Work->fnrows ;
fncols = Work->fncols ;
rrdeg = Work->rrdeg ;
ccdeg = Work->ccdeg ;
/* scan starts at the first new column in Fcols */
/* also scan the pivot column if it was not in the front */
Work->fscan_col = fncols ;
Work->NewCols = Fcols ;
/* scan1 starts at the first new row in Frows */
/* also scan the pivot row if it was not in the front */
Work->fscan_row = fnrows ;
Work->NewRows = Frows ;
/* ---------------------------------------------------------------------- */
/* extend row pattern of the front with the new pivot column */
/* ---------------------------------------------------------------------- */
fnrows_extended = fnrows ;
fncols_extended = fncols ;
#ifndef NDEBUG
DEBUG2 (("Pivot col, before extension: "ID"\n", fnrows)) ;
for (i = 0 ; i < fnrows ; i++)
{
DEBUG2 ((" "ID": row "ID"\n", i, Frows [i])) ;
ASSERT (Frpos [Frows [i]] == i) ;
}
DEBUG2 (("Extending pivot column: pivcol_in_front: "ID"\n",
Work->pivcol_in_front)) ;
#endif
Fl = Work->Flblock + fnpiv * fnr_curr ;
if (Work->pivcol_in_front)
{
/* extended pattern and position already in Frows, Frpos. Values above
* the diagonal are already in LU block. Values on and below the
* diagonal are in Wy [0 .. fnrows_extended-1]. Copy into the L
* block. */
fnrows_extended += ccdeg ;
Wy = Work->Wy ;
for (i = 0 ; i < fnrows_extended ; i++)
{
Fl [i] = Wy [i] ;
#ifndef NDEBUG
row = Frows [i] ;
DEBUG2 ((" "ID": row "ID" ", i, row)) ;
EDEBUG2 (Fl [i]) ;
if (row == Work->pivrow) DEBUG2 ((" <- pivrow")) ;
DEBUG2 (("\n")) ;
if (i == fnrows - 1) DEBUG2 ((" :::::::\n")) ;
ASSERT (row >= 0 && row < Work->n_row) ;
ASSERT (Frpos [row] == i) ;
#endif
}
}
else
{
/* extended pattern,values is in (Wm,Wx), not yet in the front */
Entry *F ;
Fu = Work->Flublock + fnpiv * Work->nb ;
Wm = Work->Wm ;
Wx = Work->Wx ;
F = Fu ;
for (i = 0 ; i < fnpiv ; i++)
{
CLEAR_AND_INCREMENT (F) ;
}
F = Fl ;
for (i = 0 ; i < fnrows ; i++)
{
CLEAR_AND_INCREMENT (F) ;
}
for (i = 0 ; i < ccdeg ; i++)
{
row = Wm [i] ;
#ifndef NDEBUG
DEBUG2 ((" "ID": row "ID" (ext) ", fnrows_extended, row)) ;
EDEBUG2 (Wx [i]) ;
if (row == Work->pivrow) DEBUG2 ((" <- pivrow")) ;
DEBUG2 (("\n")) ;
ASSERT (row >= 0 && row < Work->n_row) ;
#endif
pos = Frpos [row] ;
if (pos < 0)
{
pos = fnrows_extended++ ;
Frows [pos] = row ;
Frpos [row] = pos ;
}
Fl [pos] = Wx [i] ;
}
}
ASSERT (fnrows_extended <= fnr_curr) ;
/* ---------------------------------------------------------------------- */
/* extend the column pattern of the front with the new pivot row */
/* ---------------------------------------------------------------------- */
#ifndef NDEBUG
DEBUG6 (("Pivot row, before extension: "ID"\n", fncols)) ;
for (j = 0 ; j < fncols ; j++)
{
DEBUG7 ((" "ID": col "ID"\n", j, Fcols [j])) ;
ASSERT (Fcpos [Fcols [j]] == j * fnr_curr) ;
}
DEBUG6 (("Extending pivot row:\n")) ;
#endif
if (Work->pivrow_in_front)
{
if (Work->pivcol_in_front)
{
ASSERT (Fcols == Work->Wrow) ;
for (j = fncols ; j < rrdeg ; j++)
{
#ifndef NDEBUG
col = Fcols [j] ;
DEBUG2 ((" "ID": col "ID" (ext)\n", j, col)) ;
ASSERT (col != Work->pivcol) ;
ASSERT (col >= 0 && col < Work->n_col) ;
ASSERT (Fcpos [col] < 0) ;
#endif
Fcpos [Fcols [j]] = j * fnr_curr ;
}
}
else
{
/* OUT-IN option: pivcol not in front, but pivrow is in front */
Wrow = Work->Wrow ;
ASSERT (IMPLIES (Work->pivcol_in_front, Wrow == Fcols)) ;
if (Wrow == Fcols)
{
/* Wrow and Fcols are equivalenced */
for (j = fncols ; j < rrdeg ; j++)
{
col = Wrow [j] ;
DEBUG2 ((" "ID": col "ID" (ext)\n", j, col)) ;
ASSERT (Fcpos [col] < 0) ;
/* Fcols [j] = col ; not needed */
Fcpos [col] = j * fnr_curr ;
}
}
else
{
for (j = fncols ; j < rrdeg ; j++)
{
col = Wrow [j] ;
DEBUG2 ((" "ID": col "ID" (ext)\n", j, col)) ;
ASSERT (Fcpos [col] < 0) ;
Fcols [j] = col ;
Fcpos [col] = j * fnr_curr ;
}
}
}
fncols_extended = rrdeg ;
}
else
{
ASSERT (Fcols != Work->Wrow) ;
Wrow = Work->Wrow ;
for (j = 0 ; j < rrdeg ; j++)
{
col = Wrow [j] ;
ASSERT (col >= 0 && col < Work->n_col) ;
if (Fcpos [col] < 0)
{
DEBUG2 ((" col:: "ID" (ext)\n", col)) ;
Fcols [fncols_extended] = col ;
Fcpos [col] = fncols_extended * fnr_curr ;
fncols_extended++ ;
}
}
}
/* ---------------------------------------------------------------------- */
/* pivot row and column have been extended */
/* ---------------------------------------------------------------------- */
#ifndef NDEBUG
ASSERT (fncols_extended <= fnc_curr) ;
ASSERT (fnrows_extended <= fnr_curr) ;
DEBUG6 (("Pivot col, after ext: "ID" "ID"\n", fnrows,fnrows_extended)) ;
for (i = 0 ; i < fnrows_extended ; i++)
{
row = Frows [i] ;
DEBUG7 ((" "ID": row "ID" pos "ID" old: %d", i, row, Frpos [row],
i < fnrows)) ;
if (row == Work->pivrow ) DEBUG7 ((" <-- pivrow")) ;
DEBUG7 (("\n")) ;
ASSERT (Frpos [Frows [i]] == i) ;
}
DEBUG6 (("Pivot row position: "ID"\n", Frpos [Work->pivrow])) ;
ASSERT (Frpos [Work->pivrow] >= 0) ;
ASSERT (Frpos [Work->pivrow] < fnrows_extended) ;
DEBUG6 (("Pivot row, after ext: "ID" "ID"\n", fncols,fncols_extended)) ;
for (j = 0 ; j < fncols_extended ; j++)
{
col = Fcols [j] ;
DEBUG7 ((" "ID": col "ID" pos "ID" old: %d", j, col, Fcpos [col],
j < fncols)) ;
if (col == Work->pivcol ) DEBUG7 ((" <-- pivcol")) ;
DEBUG7 (("\n")) ;
ASSERT (Fcpos [Fcols [j]] == j * fnr_curr) ;
}
DEBUG6 (("Pivot col position: "ID"\n", Fcpos [Work->pivcol])) ;
ASSERT (Fcpos [Work->pivcol] >= 0) ;
ASSERT (Fcpos [Work->pivcol] < fncols_extended * fnr_curr) ;
#endif
/* ---------------------------------------------------------------------- */
/* Zero the newly extended frontal matrix */
/* ---------------------------------------------------------------------- */
zero_front (Work->Flblock, Work->Fublock, Work->Fcblock,
fnrows, fncols, fnr_curr, fnc_curr,
fnpiv, fnrows_extended, fncols_extended) ;
/* ---------------------------------------------------------------------- */
/* finalize extended row and column pattern of the frontal matrix */
/* ---------------------------------------------------------------------- */
Work->fnrows = fnrows_extended ;
Work->fncols = fncols_extended ;
ASSERT (fnrows_extended == Work->fnrows_new + 1) ;
ASSERT (fncols_extended == Work->fncols_new + 1) ;
return (TRUE) ;
}

View File

@ -0,0 +1,11 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL Int UMF_extend_front
(
NumericType *Numeric,
WorkType *Work
) ;

View File

@ -0,0 +1,46 @@
/* ========================================================================== */
/* === UMF_free ============================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/*
Free a block previously allocated by UMF_malloc and return NULL.
Usage is p = UMF_free (p), to ensure that we don't free it twice.
Also maintains the UMFPACK malloc count.
*/
#include "umf_internal.h"
#include "umf_free.h"
#if defined (UMF_MALLOC_COUNT) || !defined (NDEBUG)
#include "umf_malloc.h"
#endif
GLOBAL void *UMF_free
(
void *p
)
{
DEBUG0 (("UMF_free: "ID"\n", (Int) p)) ;
if (p)
{
/* see AMD/Source/amd_global.c for the memory allocator selection */
amd_free (p) ;
#if defined (UMF_MALLOC_COUNT) || !defined (NDEBUG)
/* One more object has been free'd. Keep track of the count. */
/* (purely for sanity checks). */
UMF_malloc_count-- ;
DEBUG0 ((" new malloc count: "ID"\n", UMF_malloc_count)) ;
#endif
}
return ((void *) NULL) ;
}

View File

@ -0,0 +1,10 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL void *UMF_free
(
void *p
) ;

View File

@ -0,0 +1,70 @@
/* ========================================================================== */
/* === UMF_fsize ============================================================ */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/* Determine the largest frontal matrix size for each subtree. Called by
* UMF_colamd and UMF_analyze. Only required to sort the children of each
* node prior to AMD_postorder. */
#include "umf_internal.h"
#include "umf_fsize.h"
GLOBAL void UMF_fsize
(
Int nn,
Int Fsize [ ],
Int Fnrows [ ],
Int Fncols [ ],
Int Parent [ ],
Int Npiv [ ]
)
{
Int j, parent, frsize, r, c ;
for (j = 0 ; j < nn ; j++)
{
Fsize [j] = EMPTY ;
}
/* ---------------------------------------------------------------------- */
/* find max front size for tree rooted at node j, for each front j */
/* ---------------------------------------------------------------------- */
DEBUG1 (("\n\n========================================FRONTS:\n")) ;
for (j = 0 ; j < nn ; j++)
{
if (Npiv [j] > 0)
{
/* this is a frontal matrix */
parent = Parent [j] ;
r = Fnrows [j] ;
c = Fncols [j] ;
frsize = r * c ;
/* avoid integer overflow */
if (INT_OVERFLOW (((double) r) * ((double) c)))
{
/* :: frsize int overflow :: */
frsize = Int_MAX ;
}
DEBUG1 ((""ID" : npiv "ID" size "ID" parent "ID" ",
j, Npiv [j], frsize, parent)) ;
Fsize [j] = MAX (Fsize [j], frsize) ;
DEBUG1 (("Fsize [j = "ID"] = "ID"\n", j, Fsize [j])) ;
if (parent != EMPTY)
{
/* find the maximum frontsize of self and children */
ASSERT (Npiv [parent] > 0) ;
ASSERT (parent > j) ;
Fsize [parent] = MAX (Fsize [parent], Fsize [j]) ;
DEBUG1 (("Fsize [parent = "ID"] = "ID"\n",
parent, Fsize [parent]));
}
}
}
}

View File

@ -0,0 +1,15 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL void UMF_fsize
(
Int nn,
Int MaxFsize [ ],
Int Fnrows [ ],
Int Fncols [ ],
Int Parent [ ],
Int Npiv [ ]
) ;

View File

@ -0,0 +1,696 @@
/* ========================================================================== */
/* === UMF_garbage_collection =============================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/*
Compress the elements at the tail of Numeric->Memory, and delete the tuples.
Elements are renumbered. The new numbering space is compressed, and
in the order of element creation (original elements of A first, followed
by the new elements in the order that they were formed).
Only called by UMF_get_memory.
There are 5 ways in which garbage collection can be performed:
Allocate a new working array for the current frontal matrix. In this
case, there are never any pivot rows/columns in the current frontal
matrix (fnpiv = 0), and the old working array for the current frontal
matrix can always be fully compacted, to fnrows-by-fncols.
UMF_kernel : UMF_extend : UMF_grow_front : UMF_get_memory
UMF_kernel : UMF_init_front : UMF_grow_front : UMF_get_memory
UMF_kernel : UMF_start_front : UMF_grow_front : UMF_get_memory
Allocate a new element. In this case, UMF_grow_front may or may not
be subsequently called, depending on Work->do_grow. There are never
any pivot rows/columns in the current frontal matrix (fnpiv=0), but one
may be added if UMF_init_front is to be called just after
UMF_create_element. If do_grow is true, then the current front can be
fully compacted, to fnrows-by-fncols. Otherwise, it can only be
partially compacted, to MAX (fnrows, fnrows_new + 1) -by-
MAX (fncols, fncols_new + 1).
UMF_kernel : UMF_create_element : UMF_get_memory
Allocate rows of L and columns of U. In this case, the current
frontal matrix is only partially compacted, to (fnrows_new + 1)-by-
(fncols_new + 1). There are pivots in the frontal matrix (fnpiv > 0).
UMF_kernel : UMF_store_lu : UMF_get_memory
*/
#include "umf_internal.h"
#include "umf_garbage_collection.h"
GLOBAL void UMF_garbage_collection
(
NumericType *Numeric,
WorkType *Work,
Int drnew, /* compact current front to drnew-by-dcnew */
Int dcnew,
Int do_Fcpos
)
{
/* ---------------------------------------------------------------------- */
/* local variables */
/* ---------------------------------------------------------------------- */
Int size, e, n_row, n_col, nrows, ncols, nrowsleft, ncolsleft, prevsize,
csize, size2, i2, j2, i, j, cdeg, rdeg, *E, row, col,
*Rows, *Cols, *Rows2, *Cols2, nel, e2, *Row_tuples, *Col_tuples,
*Row_degree, *Col_degree ;
Entry *C, *C1, *C3, *C2 ;
Unit *psrc, *pdest, *p, *pnext ;
Element *epsrc, *epdest ;
#ifndef NDEBUG
Int nmark ;
#endif
/* ---------------------------------------------------------------------- */
/* get parameters */
/* ---------------------------------------------------------------------- */
Col_degree = Numeric->Cperm ; /* for NON_PIVOTAL_COL macro */
Row_degree = Numeric->Rperm ; /* for NON_PIVOTAL_ROW macro */
Row_tuples = Numeric->Uip ;
Col_tuples = Numeric->Lip ;
E = Work->E ;
n_row = Work->n_row ;
n_col = Work->n_col ;
/* note that the tuple lengths (Col_tlen and Row_tlen) are updated, but */
/* the tuple lists themselves are stale and are about to be destroyed */
/* and recreated. Do not attempt to scan them until they are recreated. */
#ifndef NDEBUG
DEBUGm1 (("::::GARBAGE COLLECTION::::\n")) ;
UMF_dump_memory (Numeric) ;
#endif
Numeric->ngarbage++ ;
/* ---------------------------------------------------------------------- */
/* delete the tuple lists by marking the blocks as free */
/* ---------------------------------------------------------------------- */
/* do not modify Row_tlen and Col_tlen */
/* those are needed for UMF_build_tuples */
for (row = 0 ; row < n_row ; row++)
{
if (NON_PIVOTAL_ROW (row) && Row_tuples [row])
{
DEBUG2 (("row "ID" tuples "ID"\n", row, Row_tuples [row])) ;
p = Numeric->Memory + Row_tuples [row] - 1 ;
DEBUG2 (("Freeing tuple list row "ID", p-S "ID", size "ID"\n",
row, (Int) (p-Numeric->Memory), p->header.size)) ;
ASSERT (p->header.size > 0) ;
ASSERT (p >= Numeric->Memory + Numeric->itail) ;
ASSERT (p < Numeric->Memory + Numeric->size) ;
p->header.size = -p->header.size ;
Row_tuples [row] = 0 ;
}
}
for (col = 0 ; col < n_col ; col++)
{
if (NON_PIVOTAL_COL (col) && Col_tuples [col])
{
DEBUG2 (("col "ID" tuples "ID"\n", col, Col_tuples [col])) ;
p = Numeric->Memory + Col_tuples [col] - 1 ;
DEBUG2 (("Freeing tuple list col "ID", p-S "ID", size "ID"\n",
col, (Int) (p-Numeric->Memory), p->header.size)) ;
ASSERT (p->header.size > 0) ;
ASSERT (p >= Numeric->Memory + Numeric->itail) ;
ASSERT (p < Numeric->Memory + Numeric->size) ;
p->header.size = -p->header.size ;
Col_tuples [col] = 0 ;
}
}
/* ---------------------------------------------------------------------- */
/* mark the elements, and compress the name space */
/* ---------------------------------------------------------------------- */
nel = Work->nel ;
ASSERT (nel < Work->elen) ;
#ifndef NDEBUG
nmark = 0 ;
UMF_dump_current_front (Numeric, Work, FALSE) ;
DEBUGm1 (("E [0] "ID" \n", E [0])) ;
ASSERT (IMPLIES (E [0],
Work->Flublock == (Entry *) (Numeric->Memory + E [0]))) ;
ASSERT (IMPLIES (Work->Flublock,
Work->Flublock == (Entry *) (Numeric->Memory + E [0]))) ;
ASSERT ((E [0] != 0) == (Work->Flublock != (Entry *) NULL)) ;
#endif
e2 = 0 ;
for (e = 0 ; e <= nel ; e++) /* for all elements in order of creation */
{
if (E [e])
{
psrc = Numeric->Memory + E [e] ;
psrc-- ; /* get the header of this block */
if (e > 0)
{
e2++ ; /* do not renumber element zero */
}
ASSERT (psrc->header.size > 0) ;
psrc->header.size = e2 ; /* store the new name in the header */
#ifndef NDEBUG
nmark++ ;
#endif
DEBUG7 ((ID":: Mark e "ID" at psrc-S "ID", new e "ID"\n",
nmark, e, (Int) (psrc-Numeric->Memory), e2)) ;
E [e] = 0 ;
if (e == Work->prior_element)
{
Work->prior_element = e2 ;
}
}
}
/* all 1..e2 are now in use (element zero may or may not be in use) */
Work->nel = e2 ;
nel = Work->nel ;
#ifndef NDEBUG
for (e = 0 ; e < Work->elen ; e++)
{
ASSERT (!E [e]) ;
}
#endif
/* ---------------------------------------------------------------------- */
/* compress the elements */
/* ---------------------------------------------------------------------- */
/* point to tail marker block of size 1 + header */
psrc = Numeric->Memory + Numeric->size - 2 ;
pdest = psrc ;
prevsize = psrc->header.prevsize ;
DEBUG7 (("Starting the compression:\n")) ;
while (prevsize > 0)
{
/* ------------------------------------------------------------------ */
/* move up to the next element above the current header, and */
/* get the element name and size */
/* (if it is an element, the name will be positive) */
/* ------------------------------------------------------------------ */
size = prevsize ;
psrc -= (size + 1) ;
e = psrc->header.size ;
prevsize = psrc->header.prevsize ;
/* top block at tail has prevsize of 0 */
/* a free block will have a negative size, so skip it */
/* otherwise, if size >= 0, it holds the element name, not the size */
DEBUG8 (("psrc-S: "ID" prevsize: "ID" size: "ID,
(Int) (psrc-Numeric->Memory), prevsize, size)) ;
if (e == 0)
{
/* -------------------------------------------------------------- */
/* this is the current frontal matrix */
/* -------------------------------------------------------------- */
Entry *F1, *F2, *Fsrc, *Fdst ;
Int c, r, k, dr, dc, gap, gap1, gap2, nb ;
/* shift the frontal matrix down */
F1 = (Entry *) (psrc + 1) ;
/* get the size of the current front. r and c could be zero */
k = Work->fnpiv ;
dr = Work->fnr_curr ;
dc = Work->fnc_curr ;
r = Work->fnrows ;
c = Work->fncols ;
nb = Work->nb ;
ASSERT ((dr >= 0 && (dr % 2) == 1) || dr == 0) ;
ASSERT (drnew >= 0) ;
if (drnew % 2 == 0)
{
/* make sure leading frontal matrix dimension is always odd */
drnew++ ;
}
drnew = MIN (dr, drnew) ;
ASSERT ((drnew >= 0 && (drnew % 2) == 1) || drnew == 0) ;
pnext = pdest ;
#ifndef NDEBUG
DEBUGm2 (("move front: dr "ID" dc "ID" r "ID" drnew "ID" c "ID
" dcnew " ID" k "ID"\n", dr, dc, r, drnew, c, dcnew, k)) ;
DEBUG7 (("\n")) ;
DEBUG7 ((ID":: Move current frontal matrix from: psrc-S: "ID" \n",
nmark, (Int) (psrc-Numeric->Memory))) ;
nmark-- ;
ASSERT (E [e] == 0) ;
ASSERT (Work->Flublock == F1) ;
ASSERT (Work->Flblock == Work->Flublock + nb*nb) ;
ASSERT (Work->Fublock == Work->Flblock + dr*nb) ;
ASSERT (Work->Fcblock == Work->Fublock + nb*dc) ;
DEBUG7 (("C block: ")) ;
UMF_dump_dense (Work->Fcblock, dr, r, c) ;
DEBUG7 (("L block: ")) ;
UMF_dump_dense (Work->Flblock, dr, r, k);
DEBUG7 (("U' block: ")) ;
UMF_dump_dense (Work->Fublock, dc, c, k) ;
DEBUG7 (("LU block: ")) ;
UMF_dump_dense (Work->Flublock, nb, k, k) ;
ASSERT (r <= drnew && c <= dcnew && drnew <= dr && dcnew <= dc) ;
#endif
/* compact frontal matrix to drnew-by-dcnew before moving it */
/* do not compact the LU block (nb-by-nb) */
/* compact the columns of L (from dr-by-nb to drnew-by-nb) */
Fsrc = Work->Flblock ;
Fdst = Work->Flblock ;
ASSERT (Fdst == F1 + nb*nb) ;
gap1 = dr - r ;
gap2 = drnew - r ;
ASSERT (gap1 >= 0) ;
for (j = 0 ; j < k ; j++)
{
for (i = 0 ; i < r ; i++)
{
*Fdst++ = *Fsrc++ ;
}
Fsrc += gap1 ;
Fdst += gap2 ;
}
ASSERT (Fdst == F1 + nb*nb + drnew*k) ;
Fdst += drnew * (nb - k) ;
/* compact the rows of U (U' from dc-by-nb to dcnew-by-nb) */
Fsrc = Work->Fublock ;
ASSERT (Fdst == F1 + nb*nb + drnew*nb) ;
gap1 = dc - c ;
gap2 = dcnew - c ;
for (i = 0 ; i < k ; i++)
{
for (j = 0 ; j < c ; j++)
{
*Fdst++ = *Fsrc++ ;
}
Fsrc += gap1 ;
Fdst += gap2 ;
}
ASSERT (Fdst == F1 + nb*nb + drnew*nb + dcnew*k) ;
Fdst += dcnew * (nb - k) ;
/* compact the columns of C (from dr-by-dc to drnew-by-dcnew) */
Fsrc = Work->Fcblock ;
ASSERT (Fdst == F1 + nb*nb + drnew*nb + nb*dcnew) ;
gap1 = dr - r ;
gap2 = drnew - r ;
for (j = 0 ; j < c ; j++)
{
for (i = 0 ; i < r ; i++)
{
*Fdst++ = *Fsrc++ ;
}
Fsrc += gap1 ;
Fdst += gap2 ;
}
ASSERT (Fdst == F1 + nb*nb + drnew*nb + nb*dcnew + drnew*c) ;
/* recompute Fcpos, if necessary */
if (do_Fcpos)
{
Int *Fcols, *Fcpos ;
Fcols = Work->Fcols ;
Fcpos = Work->Fcpos ;
for (j = 0 ; j < c ; j++)
{
col = Fcols [j] ;
ASSERT (col >= 0 && col < Work->n_col) ;
ASSERT (Fcpos [col] == j * dr) ;
Fcpos [col] = j * drnew ;
}
#ifndef NDEBUG
{
Int cnt = 0 ;
for (j = 0 ; j < Work->n_col ; j++)
{
if (Fcpos [j] != EMPTY) cnt++ ;
}
DEBUGm2 (("Recompute Fcpos cnt "ID" c "ID"\n", cnt, c)) ;
ASSERT (cnt == c) ;
}
#endif
}
#ifndef NDEBUG
DEBUGm2 (("Compacted front, drnew "ID" dcnew "ID"\n", drnew, dcnew)) ;
DEBUG7 (("C block: ")) ;
UMF_dump_dense (F1 + nb*nb + drnew*nb + nb*dcnew, drnew, r, c) ;
DEBUG7 (("L block: ")) ;
UMF_dump_dense (F1 + nb*nb, drnew, r, k) ;
DEBUG7 (("U block: ")) ;
UMF_dump_dense (F1 + nb*nb + drnew*nb, nb, k, c) ;
DEBUG7 (("LU block: ")) ;
UMF_dump_dense (F1, nb, k, k) ;
#endif
/* Compacted dimensions of the new frontal matrix. */
Work->fnr_curr = drnew ;
Work->fnc_curr = dcnew ;
Work->fcurr_size = (drnew + nb) * (dcnew + nb) ;
size = UNITS (Entry, Work->fcurr_size) ;
/* make sure the object doesn't evaporate. The front can have
* zero size (Work->fcurr_size = 0), but the size of the memory
* block containing it cannot have zero size. */
size = MAX (1, size) ;
/* get the destination of frontal matrix */
pnext->header.prevsize = size ;
pdest -= (size + 1) ;
F2 = (Entry *) (pdest + 1) ;
ASSERT ((unsigned Int) psrc + 1 + size <= (unsigned Int) pnext) ;
ASSERT (psrc <= pdest) ;
ASSERT (F1 <= F2) ;
/* move the C block first */
Fsrc = F1 + nb*nb + drnew*nb + nb*dcnew + drnew*c ;
Fdst = F2 + nb*nb + drnew*nb + nb*dcnew + drnew*c ;
gap = drnew - r ;
for (j = c-1 ; j >= 0 ; j--)
{
Fsrc -= gap ;
Fdst -= gap ;
/* move column j of C */
for (i = r-1 ; i >= 0 ; i--)
{
*--Fdst = *--Fsrc ;
}
}
ASSERT (Fsrc == F1 + nb*nb + drnew*nb + nb*dcnew) ;
ASSERT (Fdst == F2 + nb*nb + drnew*nb + nb*dcnew) ;
/* move the U block */
Fsrc -= dcnew * (nb - k) ;
Fdst -= dcnew * (nb - k) ;
ASSERT (Fsrc == F1 + nb*nb + drnew*nb + dcnew*k) ;
ASSERT (Fdst == F2 + nb*nb + drnew*nb + dcnew*k) ;
gap = dcnew - c ;
for (i = k-1 ; i >= 0 ; i--)
{
Fsrc -= gap ;
Fdst -= gap ;
for (j = c-1 ; j >= 0 ; j--)
{
*--Fdst = *--Fsrc ;
}
}
ASSERT (Fsrc == F1 + nb*nb + drnew*nb) ;
ASSERT (Fdst == F2 + nb*nb + drnew*nb) ;
/* move the L block */
Fsrc -= drnew * (nb - k) ;
Fdst -= drnew * (nb - k) ;
ASSERT (Fsrc == F1 + nb*nb + drnew*k) ;
ASSERT (Fdst == F2 + nb*nb + drnew*k) ;
gap = drnew - r ;
for (j = k-1 ; j >= 0 ; j--)
{
Fsrc -= gap ;
Fdst -= gap ;
for (i = r-1 ; i >= 0 ; i--)
{
*--Fdst = *--Fsrc ;
}
}
ASSERT (Fsrc == F1 + nb*nb) ;
ASSERT (Fdst == F2 + nb*nb) ;
/* move the LU block */
Fsrc -= nb * (nb - k) ;
Fdst -= nb * (nb - k) ;
ASSERT (Fsrc == F1 + nb*k) ;
ASSERT (Fdst == F2 + nb*k) ;
gap = nb - k ;
for (j = k-1 ; j >= 0 ; j--)
{
Fsrc -= gap ;
Fdst -= gap ;
for (i = k-1 ; i >= 0 ; i--)
{
*--Fdst = *--Fsrc ;
}
}
ASSERT (Fsrc == F1) ;
ASSERT (Fdst == F2) ;
E [0] = (pdest + 1) - Numeric->Memory ;
Work->Flublock = (Entry *) (Numeric->Memory + E [0]) ;
ASSERT (Work->Flublock == F2) ;
Work->Flblock = Work->Flublock + nb * nb ;
Work->Fublock = Work->Flblock + drnew * nb ;
Work->Fcblock = Work->Fublock + nb * dcnew ;
pdest->header.prevsize = 0 ;
pdest->header.size = size ;
#ifndef NDEBUG
DEBUG7 (("After moving compressed current frontal matrix:\n")) ;
DEBUG7 (("C block: ")) ;
UMF_dump_dense (Work->Fcblock, drnew, r, c) ;
DEBUG7 (("L block: ")) ;
UMF_dump_dense (Work->Flblock, drnew, r, k);
DEBUG7 (("U' block: ")) ;
UMF_dump_dense (Work->Fublock, dcnew, c, k) ;
DEBUG7 (("LU block: ")) ;
UMF_dump_dense (Work->Flublock, nb, k, k) ;
#endif
}
else if (e > 0)
{
/* -------------------------------------------------------------- */
/* this is an element, compress and move from psrc down to pdest */
/* -------------------------------------------------------------- */
#ifndef NDEBUG
DEBUG7 (("\n")) ;
DEBUG7 ((ID":: Move element "ID": from: "ID" \n",
nmark, e, (Int) (psrc-Numeric->Memory))) ;
nmark-- ;
ASSERT (e <= nel) ;
ASSERT (E [e] == 0) ;
#endif
/* -------------------------------------------------------------- */
/* get the element scalars, and pointers to C, Rows, and Cols: */
/* -------------------------------------------------------------- */
p = psrc + 1 ;
GET_ELEMENT (epsrc, p, Cols, Rows, ncols, nrows, C) ;
nrowsleft = epsrc->nrowsleft ;
ncolsleft = epsrc->ncolsleft ;
cdeg = epsrc->cdeg ;
rdeg = epsrc->rdeg ;
#ifndef NDEBUG
DEBUG7 ((" nrows "ID" nrowsleft "ID"\n", nrows, nrowsleft)) ;
DEBUG7 ((" ncols "ID" ncolsleft "ID"\n", ncols, ncolsleft)) ;
DEBUG8 ((" Rows:")) ;
for (i = 0 ; i < nrows ; i++) DEBUG8 ((" "ID, Rows [i])) ;
DEBUG8 (("\n Cols:")) ;
for (j = 0 ; j < ncols ; j++) DEBUG8 ((" "ID, Cols [j])) ;
DEBUG8 (("\n")) ;
#endif
/* -------------------------------------------------------------- */
/* determine the layout of the new element */
/* -------------------------------------------------------------- */
csize = nrowsleft * ncolsleft ;
size2 = UNITS (Element, 1)
+ UNITS (Int, nrowsleft + ncolsleft)
+ UNITS (Entry, csize) ;
DEBUG7 (("Old size "ID" New size "ID"\n", size, size2)) ;
pnext = pdest ;
pnext->header.prevsize = size2 ;
pdest -= (size2 + 1) ;
ASSERT (size2 <= size) ;
ASSERT ((unsigned Int) psrc + 1 + size <= (unsigned Int) pnext) ;
ASSERT (psrc <= pdest) ;
p = pdest + 1 ;
epdest = (Element *) p ;
p += UNITS (Element, 1) ;
Cols2 = (Int *) p ;
Rows2 = Cols2 + ncolsleft ;
p += UNITS (Int, nrowsleft + ncolsleft) ;
C2 = (Entry *) p ;
ASSERT (epdest >= epsrc) ;
ASSERT (Rows2 >= Rows) ;
ASSERT (Cols2 >= Cols) ;
ASSERT (C2 >= C) ;
ASSERT (p + UNITS (Entry, csize) == pnext) ;
/* -------------------------------------------------------------- */
/* move the contribution block */
/* -------------------------------------------------------------- */
/* overlap = psrc + size + 1 > pdest ; */
if (nrowsleft < nrows || ncolsleft < ncols)
{
/* ---------------------------------------------------------- */
/* compress contribution block in place prior to moving it */
/* ---------------------------------------------------------- */
DEBUG7 (("Compress C in place prior to move:\n"));
#ifndef NDEBUG
UMF_dump_dense (C, nrows, nrows, ncols) ;
#endif
C1 = C ;
C3 = C ;
for (j = 0 ; j < ncols ; j++)
{
if (Cols [j] >= 0)
{
for (i = 0 ; i < nrows ; i++)
{
if (Rows [i] >= 0)
{
*C3++ = C1 [i] ;
}
}
}
C1 += nrows ;
}
ASSERT (C3-C == csize) ;
DEBUG8 (("Newly compressed contrib. block (all in use):\n")) ;
#ifndef NDEBUG
UMF_dump_dense (C, nrowsleft, nrowsleft, ncolsleft) ;
#endif
}
/* shift the contribution block down */
C += csize ;
C2 += csize ;
for (i = 0 ; i < csize ; i++)
{
*--C2 = *--C ;
}
/* -------------------------------------------------------------- */
/* move the row indices */
/* -------------------------------------------------------------- */
i2 = nrowsleft ;
for (i = nrows - 1 ; i >= 0 ; i--)
{
ASSERT (Rows2+i2 >= Rows+i) ;
if (Rows [i] >= 0)
{
Rows2 [--i2] = Rows [i] ;
}
}
ASSERT (i2 == 0) ;
j2 = ncolsleft ;
for (j = ncols - 1 ; j >= 0 ; j--)
{
ASSERT (Cols2+j2 >= Cols+j) ;
if (Cols [j] >= 0)
{
Cols2 [--j2] = Cols [j] ;
}
}
ASSERT (j2 == 0) ;
/* -------------------------------------------------------------- */
/* construct the new header */
/* -------------------------------------------------------------- */
/* E [0...e] is now valid */
E [e] = (pdest + 1) - Numeric->Memory ;
epdest = (Element *) (pdest + 1) ;
epdest->next = EMPTY ; /* destroys the son list */
epdest->ncols = ncolsleft ;
epdest->nrows = nrowsleft ;
epdest->ncolsleft = ncolsleft ;
epdest->nrowsleft = nrowsleft ;
epdest->rdeg = rdeg ;
epdest->cdeg = cdeg ;
ASSERT (size2 <= size) ;
pdest->header.prevsize = 0 ;
pdest->header.size = size2 ;
DEBUG7 (("After moving it:\n")) ;
#ifndef NDEBUG
UMF_dump_element (Numeric, Work, e, FALSE) ;
#endif
}
#ifndef NDEBUG
else
{
DEBUG8 ((" free\n")) ;
}
#endif
DEBUG7 (("psrc "ID" tail "ID"\n",
(Int) (psrc-Numeric->Memory), Numeric->itail)) ;
}
ASSERT (psrc == Numeric->Memory + Numeric->itail) ;
ASSERT (nmark == 0) ;
/* ---------------------------------------------------------------------- */
/* final tail pointer */
/* ---------------------------------------------------------------------- */
ASSERT (pdest >= Numeric->Memory + Numeric->itail) ;
Numeric->itail = pdest - Numeric->Memory ;
pdest->header.prevsize = 0 ;
Numeric->ibig = EMPTY ;
Numeric->tail_usage = Numeric->size - Numeric->itail ;
/* ---------------------------------------------------------------------- */
/* clear the unused E [nel+1 .. Work->elen - 1] */
/* ---------------------------------------------------------------------- */
for (e = nel+1 ; e < Work->elen ; e++)
{
E [e] = 0 ;
}
#ifndef NDEBUG
UMF_dump_packed_memory (Numeric, Work) ;
#endif
DEBUG8 (("::::GARBAGE COLLECTION DONE::::\n")) ;
}

View File

@ -0,0 +1,14 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL void UMF_garbage_collection
(
NumericType *Numeric,
WorkType *Work,
Int drnew,
Int dcnew,
Int do_Fcpos
) ;

View File

@ -0,0 +1,223 @@
/* ========================================================================== */
/* === UMF_get_memory ======================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/*
Reallocate the workspace (Numeric->Memory) and shift elements downwards.
needunits: increase in size so that the free space is at least this many
Units (to which the tuple lengths is added).
Return TRUE if successful, FALSE if out of memory.
*/
#include "umf_internal.h"
#include "umf_get_memory.h"
#include "umf_garbage_collection.h"
#include "umf_tuple_lengths.h"
#include "umf_build_tuples.h"
#include "umf_mem_free_tail_block.h"
#include "umf_realloc.h"
GLOBAL Int UMF_get_memory
(
NumericType *Numeric,
WorkType *Work,
Int needunits,
Int r2, /* compact current front to r2-by-c2 */
Int c2,
Int do_Fcpos
)
{
double nsize, bsize, tsize ;
Int i, minsize, newsize, newmem, costly, row, col, *Row_tlen, *Col_tlen,
n_row, n_col, *Row_degree, *Col_degree ;
Unit *mnew, *p ;
/* ---------------------------------------------------------------------- */
/* get and check parameters */
/* ---------------------------------------------------------------------- */
#ifndef NDEBUG
DEBUG1 (("::::GET MEMORY::::\n")) ;
UMF_dump_memory (Numeric) ;
#endif
n_row = Work->n_row ;
n_col = Work->n_col ;
Row_degree = Numeric->Rperm ; /* for NON_PIVOTAL_ROW macro */
Col_degree = Numeric->Cperm ; /* for NON_PIVOTAL_COL macro */
Row_tlen = Numeric->Uilen ;
Col_tlen = Numeric->Lilen ;
/* ---------------------------------------------------------------------- */
/* initialize the tuple list lengths */
/* ---------------------------------------------------------------------- */
for (row = 0 ; row < n_row ; row++)
{
if (NON_PIVOTAL_ROW (row))
{
Row_tlen [row] = 0 ;
}
}
for (col = 0 ; col < n_col ; col++)
{
if (NON_PIVOTAL_COL (col))
{
Col_tlen [col] = 0 ;
}
}
/* ---------------------------------------------------------------------- */
/* determine how much memory is needed for the tuples */
/* ---------------------------------------------------------------------- */
nsize = (double) needunits + 2 ;
needunits += UMF_tuple_lengths (Numeric, Work, &tsize) ;
nsize += tsize ;
needunits += 2 ; /* add 2, so that newmem >= 2 is true if realloc'd */
/* note: Col_tlen and Row_tlen are updated, but the tuple lists */
/* themselves are not. Do not attempt to scan the tuple lists. */
/* They are now stale, and are about to be destroyed and recreated. */
/* ---------------------------------------------------------------------- */
/* determine the desired new size of memory */
/* ---------------------------------------------------------------------- */
DEBUG0 (("UMF_get_memory: needunits: "ID"\n", needunits)) ;
minsize = Numeric->size + needunits ;
nsize += (double) Numeric->size ;
bsize = ((double) Int_MAX) / sizeof (Unit) - 1 ;
newsize = (Int) (UMF_REALLOC_INCREASE * ((double) minsize)) ;
nsize *= UMF_REALLOC_INCREASE ;
nsize += 1 ;
if (newsize < 0 || nsize > bsize)
{
/* :: realloc Numeric->Memory int overflow :: */
DEBUGm3 (("Realloc hit integer limit\n")) ;
newsize = (Int) bsize ; /* we cannot increase the size beyond bsize */
}
else
{
ASSERT (newsize <= nsize) ;
newsize = MAX (newsize, minsize) ;
}
newsize = MAX (newsize, Numeric->size) ;
DEBUG0 ((
"REALLOC MEMORY: needunits "ID" old size: "ID" new size: "ID" Units \n",
needunits, Numeric->size, newsize)) ;
/* Forget where the biggest free block is (we no longer need it) */
/* since garbage collection will occur shortly. */
Numeric->ibig = EMPTY ;
DEBUG0 (("Before realloc E [0] "ID"\n", Work->E [0])) ;
/* ---------------------------------------------------------------------- */
/* reallocate the memory, if possible, and make it bigger */
/* ---------------------------------------------------------------------- */
mnew = (Unit *) NULL ;
while (!mnew)
{
mnew = (Unit *) UMF_realloc (Numeric->Memory, newsize, sizeof (Unit)) ;
if (!mnew)
{
if (newsize == minsize) /* last realloc attempt failed */
{
/* We failed to get the minimum. Just stick with the */
/* current allocation and hope that garbage collection */
/* can recover enough space. */
mnew = Numeric->Memory ; /* no new memory available */
newsize = Numeric->size ;
}
else
{
/* otherwise, reduce the request and keep trying */
newsize = (Int) (UMF_REALLOC_REDUCTION * ((double) newsize)) ;
newsize = MAX (minsize, newsize) ;
}
}
}
ASSERT (mnew != (Unit *) NULL) ;
/* see if realloc had to copy, rather than just extend memory */
costly = (mnew != Numeric->Memory) ;
/* ---------------------------------------------------------------------- */
/* extend the tail portion of memory downwards */
/* ---------------------------------------------------------------------- */
Numeric->Memory = mnew ;
if (Work->E [0])
{
Int nb, dr, dc ;
nb = Work->nb ;
dr = Work->fnr_curr ;
dc = Work->fnc_curr ;
Work->Flublock = (Entry *) (Numeric->Memory + Work->E [0]) ;
Work->Flblock = Work->Flublock + nb * nb ;
Work->Fublock = Work->Flblock + dr * nb ;
Work->Fcblock = Work->Fublock + nb * dc ;
DEBUG0 (("after realloc E [0] "ID"\n", Work->E [0])) ;
}
ASSERT (IMPLIES (!(Work->E [0]), Work->Flublock == (Entry *) NULL)) ;
newmem = newsize - Numeric->size ;
ASSERT (newmem == 0 || newmem >= 2) ;
if (newmem >= 2)
{
/* reallocation succeeded */
/* point to the old tail marker block of size 1 + header */
p = Numeric->Memory + Numeric->size - 2 ;
/* create a new block out of the newly extended memory */
p->header.size = newmem - 1 ;
i = Numeric->size - 1 ;
p += newmem ;
/* create a new tail marker block */
p->header.prevsize = newmem - 1 ;
p->header.size = 1 ;
Numeric->size = newsize ;
/* free the new block */
UMF_mem_free_tail_block (Numeric, i) ;
Numeric->nrealloc++ ;
if (costly)
{
Numeric->ncostly++ ;
}
}
DEBUG1 (("Done with realloc memory\n")) ;
/* ---------------------------------------------------------------------- */
/* garbage collection on the tail of Numeric->memory (destroys tuples) */
/* ---------------------------------------------------------------------- */
UMF_garbage_collection (Numeric, Work, r2, c2, do_Fcpos) ;
/* ---------------------------------------------------------------------- */
/* rebuild the tuples */
/* ---------------------------------------------------------------------- */
return (UMF_build_tuples (Numeric, Work)) ;
}

View File

@ -0,0 +1,15 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL Int UMF_get_memory
(
NumericType *Numeric,
WorkType *Work,
Int needunits,
Int r2,
Int c2,
Int do_Fcpos
) ;

View File

@ -0,0 +1,294 @@
/* ========================================================================== */
/* === UMF_grow_front ======================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/* Current frontal matrix is too small. Make it bigger. */
#include "umf_internal.h"
#include "umf_grow_front.h"
#include "umf_mem_free_tail_block.h"
#include "umf_mem_alloc_tail_block.h"
#include "umf_get_memory.h"
GLOBAL Int UMF_grow_front
(
NumericType *Numeric,
Int fnr2, /* desired size is fnr2-by-fnc2 */
Int fnc2,
WorkType *Work,
Int do_what /* -1: UMF_start_front
* 0: UMF_init_front, do not recompute Fcpos
* 1: UMF_extend_front
* 2: UMF_init_front, recompute Fcpos */
)
{
/* ---------------------------------------------------------------------- */
/* local variables */
/* ---------------------------------------------------------------------- */
double s ;
Entry *Fcold, *Fcnew ;
Int j, i, col, *Fcpos, *Fcols, fnrows_max, fncols_max, fnr_curr, nb,
fnrows_new, fncols_new, fnr_min, fnc_min, minsize,
newsize, fnrows, fncols, *E, eloc ;
/* ---------------------------------------------------------------------- */
/* get parameters */
/* ---------------------------------------------------------------------- */
#ifndef NDEBUG
if (do_what != -1) UMF_debug++ ;
DEBUG0 (("\n\n====================GROW FRONT: do_what: "ID"\n", do_what)) ;
if (do_what != -1) UMF_debug-- ;
ASSERT (Work->do_grow) ;
ASSERT (Work->fnpiv == 0) ;
#endif
Fcols = Work->Fcols ;
Fcpos = Work->Fcpos ;
E = Work->E ;
/* ---------------------------------------------------------------------- */
/* The current front is too small, find the new size */
/* ---------------------------------------------------------------------- */
/* maximum size of frontal matrix for this chain */
nb = Work->nb ;
fnrows_max = Work->fnrows_max + nb ;
fncols_max = Work->fncols_max + nb ;
ASSERT (fnrows_max >= 0 && (fnrows_max % 2) == 1) ;
DEBUG0 (("Max size: "ID"-by-"ID" (incl. "ID" pivot block\n",
fnrows_max, fncols_max, nb)) ;
/* current dimensions of frontal matrix: fnr-by-fnc */
DEBUG0 (("Current : "ID"-by-"ID" (excl "ID" pivot blocks)\n",
Work->fnr_curr, Work->fnc_curr, nb)) ;
ASSERT (Work->fnr_curr >= 0) ;
ASSERT ((Work->fnr_curr % 2 == 1) || Work->fnr_curr == 0) ;
/* required dimensions of frontal matrix: fnr_min-by-fnc_min */
fnrows_new = Work->fnrows_new + 1 ;
fncols_new = Work->fncols_new + 1 ;
ASSERT (fnrows_new >= 0) ;
if (fnrows_new % 2 == 0) fnrows_new++ ;
fnrows_new += nb ;
fncols_new += nb ;
fnr_min = MIN (fnrows_new, fnrows_max) ;
fnc_min = MIN (fncols_new, fncols_max) ;
minsize = fnr_min * fnc_min ;
if (INT_OVERFLOW ((double) fnr_min * (double) fnc_min * sizeof (Entry)))
{
/* :: the minimum front size is bigger than the integer maximum :: */
return (FALSE) ;
}
ASSERT (fnr_min >= 0) ;
ASSERT (fnr_min % 2 == 1) ;
DEBUG0 (("Min : "ID"-by-"ID"\n", fnr_min, fnc_min)) ;
/* grow the front to fnr2-by-fnc2, but no bigger than the maximum,
* and no smaller than the minumum. */
DEBUG0 (("Desired : ("ID"+"ID")-by-("ID"+"ID")\n", fnr2, nb, fnc2, nb)) ;
fnr2 += nb ;
fnc2 += nb ;
ASSERT (fnr2 >= 0) ;
if (fnr2 % 2 == 0) fnr2++ ;
fnr2 = MAX (fnr2, fnr_min) ;
fnc2 = MAX (fnc2, fnc_min) ;
fnr2 = MIN (fnr2, fnrows_max) ;
fnc2 = MIN (fnc2, fncols_max) ;
DEBUG0 (("Try : "ID"-by-"ID"\n", fnr2, fnc2)) ;
ASSERT (fnr2 >= 0) ;
ASSERT (fnr2 % 2 == 1) ;
s = ((double) fnr2) * ((double) fnc2) ;
if (INT_OVERFLOW (s * sizeof (Entry)))
{
/* :: frontal matrix size int overflow :: */
/* the desired front size is bigger than the integer maximum */
/* compute a such that a*a*s < Int_MAX / sizeof (Entry) */
double a = 0.9 * sqrt ((Int_MAX / sizeof (Entry)) / s) ;
fnr2 = MAX (fnr_min, a * fnr2) ;
fnc2 = MAX (fnc_min, a * fnc2) ;
/* the new frontal size is a*r*a*c = a*a*s */
newsize = fnr2 * fnc2 ;
ASSERT (fnr2 >= 0) ;
if (fnr2 % 2 == 0) fnr2++ ;
fnc2 = newsize / fnr2 ;
}
fnr2 = MAX (fnr2, fnr_min) ;
fnc2 = MAX (fnc2, fnc_min) ;
newsize = fnr2 * fnc2 ;
ASSERT (fnr2 >= 0) ;
ASSERT (fnr2 % 2 == 1) ;
ASSERT (fnr2 >= fnr_min) ;
ASSERT (fnc2 >= fnc_min) ;
ASSERT (newsize >= minsize) ;
/* ---------------------------------------------------------------------- */
/* free the current front if it is empty of any numerical values */
/* ---------------------------------------------------------------------- */
if (E [0] && do_what != 1)
{
/* free the current front, if it exists and has nothing in it */
DEBUG0 (("Freeing empty front\n")) ;
UMF_mem_free_tail_block (Numeric, E [0]) ;
E [0] = 0 ;
Work->Flublock = (Entry *) NULL ;
Work->Flblock = (Entry *) NULL ;
Work->Fublock = (Entry *) NULL ;
Work->Fcblock = (Entry *) NULL ;
}
/* ---------------------------------------------------------------------- */
/* allocate the new front, doing garbage collection if necessary */
/* ---------------------------------------------------------------------- */
#ifndef NDEBUG
UMF_allocfail = FALSE ;
if (UMF_gprob > 0) /* a double relop, but ignore NaN case */
{
double rrr = ((double) (rand ( ))) / (((double) RAND_MAX) + 1) ;
DEBUG1 (("Check random %e %e\n", rrr, UMF_gprob)) ;
UMF_allocfail = rrr < UMF_gprob ;
if (UMF_allocfail) DEBUGm2 (("Random garbage collection (grow)\n")) ;
}
#endif
DEBUG0 (("Attempt size: "ID"-by-"ID"\n", fnr2, fnc2)) ;
eloc = UMF_mem_alloc_tail_block (Numeric, UNITS (Entry, newsize)) ;
if (!eloc)
{
/* Do garbage collection, realloc, and try again. Compact the current
* contribution block in the front to fnrows-by-fncols. Note that
* there are no pivot rows/columns in current front. Do not recompute
* Fcpos in UMF_garbage_collection. */
DEBUGm3 (("get_memory from umf_grow_front\n")) ;
if (!UMF_get_memory (Numeric, Work, 1 + UNITS (Entry, newsize),
Work->fnrows, Work->fncols, FALSE))
{
/* :: out of memory in umf_grow_front :: */
return (FALSE) ; /* out of memory */
}
DEBUG0 (("Attempt size: "ID"-by-"ID" again\n", fnr2, fnc2)) ;
eloc = UMF_mem_alloc_tail_block (Numeric, UNITS (Entry, newsize)) ;
}
/* try again with something smaller */
while ((fnr2 != fnr_min || fnc2 != fnc_min) && !eloc)
{
fnr2 = MIN (fnr2 - 2, fnr2 * UMF_REALLOC_REDUCTION) ;
fnc2 = MIN (fnc2 - 2, fnc2 * UMF_REALLOC_REDUCTION) ;
ASSERT (fnr_min >= 0) ;
ASSERT (fnr_min % 2 == 1) ;
fnr2 = MAX (fnr_min, fnr2) ;
fnc2 = MAX (fnc_min, fnc2) ;
ASSERT (fnr2 >= 0) ;
if (fnr2 % 2 == 0) fnr2++ ;
newsize = fnr2 * fnc2 ;
DEBUGm3 (("Attempt smaller size: "ID"-by-"ID" minsize "ID"-by-"ID"\n",
fnr2, fnc2, fnr_min, fnc_min)) ;
eloc = UMF_mem_alloc_tail_block (Numeric, UNITS (Entry, newsize)) ;
}
/* try again with the smallest possible size */
if (!eloc)
{
fnr2 = fnr_min ;
fnc2 = fnc_min ;
newsize = minsize ;
DEBUG0 (("Attempt minsize: "ID"-by-"ID"\n", fnr2, fnc2)) ;
eloc = UMF_mem_alloc_tail_block (Numeric, UNITS (Entry, newsize)) ;
}
if (!eloc)
{
/* out of memory */
return (FALSE) ;
}
ASSERT (fnr2 >= 0) ;
ASSERT (fnr2 % 2 == 1) ;
ASSERT (fnr2 >= fnr_min && fnc2 >= fnc_min) ;
/* ---------------------------------------------------------------------- */
/* copy the old frontal matrix into the new one */
/* ---------------------------------------------------------------------- */
/* old contribution block (if any) */
fnr_curr = Work->fnr_curr ; /* garbage collection can change fn*_curr */
ASSERT (fnr_curr >= 0) ;
ASSERT ((fnr_curr % 2 == 1) || fnr_curr == 0) ;
fnrows = Work->fnrows ;
fncols = Work->fncols ;
Fcold = Work->Fcblock ;
/* remove nb from the sizes */
fnr2 -= nb ;
fnc2 -= nb ;
/* new frontal matrix */
Work->Flublock = (Entry *) (Numeric->Memory + eloc) ;
Work->Flblock = Work->Flublock + nb * nb ;
Work->Fublock = Work->Flblock + nb * fnr2 ;
Work->Fcblock = Work->Fublock + nb * fnc2 ;
Fcnew = Work->Fcblock ;
if (E [0])
{
/* copy the old contribution block into the new one */
for (j = 0 ; j < fncols ; j++)
{
col = Fcols [j] ;
DEBUG1 (("copy col "ID" \n",col)) ;
ASSERT (col >= 0 && col < Work->n_col) ;
for (i = 0 ; i < fnrows ; i++)
{
Fcnew [i] = Fcold [i] ;
}
Fcnew += fnr2 ;
Fcold += fnr_curr ;
DEBUG1 (("new offset col "ID" "ID"\n",col, j * fnr2)) ;
Fcpos [col] = j * fnr2 ;
}
}
else if (do_what == 2)
{
/* just find the new column offsets */
for (j = 0 ; j < fncols ; j++)
{
col = Fcols [j] ;
DEBUG1 (("new offset col "ID" "ID"\n",col, j * fnr2)) ;
Fcpos [col] = j * fnr2 ;
}
}
/* free the old frontal matrix */
UMF_mem_free_tail_block (Numeric, E [0]) ;
/* ---------------------------------------------------------------------- */
/* new frontal matrix size */
/* ---------------------------------------------------------------------- */
E [0] = eloc ;
Work->fnr_curr = fnr2 ; /* C block is fnr2-by-fnc2 */
Work->fnc_curr = fnc2 ;
Work->fcurr_size = newsize ; /* including LU, L, U, and C blocks */
Work->do_grow = FALSE ; /* the front has just been grown */
ASSERT (Work->fnr_curr >= 0) ;
ASSERT (Work->fnr_curr % 2 == 1) ;
DEBUG0 (("Newly grown front: "ID"+"ID" by "ID"+"ID"\n", Work->fnr_curr,
nb, Work->fnc_curr, nb)) ;
return (TRUE) ;
}

View File

@ -0,0 +1,14 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL Int UMF_grow_front
(
NumericType *Numeric,
Int fnr2,
Int fnc2,
WorkType *Work,
Int do_what
) ;

View File

@ -0,0 +1,268 @@
/* ========================================================================== */
/* === UMF_init_front ======================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
#include "umf_internal.h"
#include "umf_init_front.h"
#include "umf_grow_front.h"
/* ========================================================================== */
/* === zero_init_front ====================================================== */
/* ========================================================================== */
/* Set the initial frontal matrix to zero. */
PRIVATE void zero_init_front (Int m, Int n, Entry *Fcblock, Int d)
{
Int i, j ;
Entry *F, *Fj = Fcblock ;
for (j = 0 ; j < m ; j++)
{
F = Fj ;
Fj += d ;
for (i = 0 ; i < n ; i++)
{
/* CLEAR (Fcblock [i + j*d]) ; */
CLEAR (*F) ;
F++ ;
}
}
}
/* ========================================================================== */
/* === UMF_init_front ======================================================= */
/* ========================================================================== */
GLOBAL Int UMF_init_front
(
NumericType *Numeric,
WorkType *Work
)
{
/* ---------------------------------------------------------------------- */
/* local variables */
/* ---------------------------------------------------------------------- */
Int i, j, fnr_curr, row, col, *Frows, *Fcols,
*Fcpos, *Frpos, fncols, fnrows, *Wrow, fnr2, fnc2, rrdeg, ccdeg, *Wm,
fnrows_extended ;
Entry *Fcblock, *Fl, *Wy, *Wx ;
/* ---------------------------------------------------------------------- */
/* get current frontal matrix and check for frontal growth */
/* ---------------------------------------------------------------------- */
#ifndef NDEBUG
DEBUG0 (("INIT FRONT\n")) ;
DEBUG1 (("CURR before init:\n")) ;
UMF_dump_current_front (Numeric, Work, FALSE) ;
#endif
if (Work->do_grow)
{
fnr2 = UMF_FRONTAL_GROWTH * Work->fnrows_new + 2 ;
fnc2 = UMF_FRONTAL_GROWTH * Work->fncols_new + 2 ;
if (!UMF_grow_front (Numeric, fnr2, fnc2, Work,
Work->pivrow_in_front ? 2 : 0))
{
/* :: out of memory in umf_init_front :: */
DEBUGm4 (("out of memory: init front\n")) ;
return (FALSE) ;
}
}
#ifndef NDEBUG
DEBUG1 (("CURR after grow:\n")) ;
UMF_dump_current_front (Numeric, Work, FALSE) ;
DEBUG1 (("fnrows new "ID" fncols new "ID"\n",
Work->fnrows_new, Work->fncols_new)) ;
#endif
ASSERT (Work->fnpiv == 0) ;
fnr_curr = Work->fnr_curr ;
ASSERT (Work->fnrows_new + 1 <= fnr_curr) ;
ASSERT (Work->fncols_new + 1 <= Work->fnc_curr) ;
ASSERT (fnr_curr >= 0) ;
ASSERT (fnr_curr % 2 == 1) ;
/* ---------------------------------------------------------------------- */
/* get parameters */
/* ---------------------------------------------------------------------- */
/* current front is defined by pivot row and column */
Frows = Work->Frows ;
Fcols = Work->Fcols ;
Frpos = Work->Frpos ;
Fcpos = Work->Fcpos ;
Work->fnzeros = 0 ;
ccdeg = Work->ccdeg ;
rrdeg = Work->rrdeg ;
fnrows = Work->fnrows ;
fncols = Work->fncols ;
/* if both pivrow and pivcol are in front, then we extend the old one */
/* in UMF_extend_front, rather than starting a new one here. */
ASSERT (! (Work->pivrow_in_front && Work->pivcol_in_front)) ;
/* ---------------------------------------------------------------------- */
/* place pivot column pattern in frontal matrix */
/* ---------------------------------------------------------------------- */
Fl = Work->Flblock ;
if (Work->pivcol_in_front)
{
/* Append the pivot column extension.
* Note that all we need to do is increment the size, since the
* candidate pivot column pattern is already in place in
* Frows [0 ... fnrows-1] (the old pattern), and
* Frows [fnrows ... fnrows + Work->ccdeg - 1] (the new
* pattern). Frpos is also properly defined. */
/* make a list of the new rows to scan */
Work->fscan_row = fnrows ; /* only scan the new rows */
Work->NewRows = Work->Wrp ;
Wy = Work->Wy ;
for (i = 0 ; i < fnrows ; i++)
{
Fl [i] = Wy [i] ;
}
fnrows_extended = fnrows + ccdeg ;
for (i = fnrows ; i < fnrows_extended ; i++)
{
Fl [i] = Wy [i] ;
/* flip the row, since Wrp must be < 0 */
row = Frows [i] ;
Work->NewRows [i] = FLIP (row) ;
}
fnrows = fnrows_extended ;
}
else
{
/* this is a completely new column */
Work->fscan_row = 0 ; /* scan all the rows */
Work->NewRows = Frows ;
Wm = Work->Wm ;
Wx = Work->Wx ;
for (i = 0 ; i < ccdeg ; i++)
{
Fl [i] = Wx [i] ;
row = Wm [i] ;
Frows [i] = row ;
Frpos [row] = i ;
}
fnrows = ccdeg ;
}
Work->fnrows = fnrows ;
#ifndef NDEBUG
DEBUG3 (("New Pivot col "ID" now in front, length "ID"\n",
Work->pivcol, fnrows)) ;
for (i = 0 ; i < fnrows ; i++)
{
DEBUG4 ((" "ID": row "ID"\n", i, Frows [i])) ;
ASSERT (Frpos [Frows [i]] == i) ;
}
#endif
/* ---------------------------------------------------------------------- */
/* place pivot row pattern in frontal matrix */
/* ---------------------------------------------------------------------- */
Wrow = Work->Wrow ;
if (Work->pivrow_in_front)
{
/* append the pivot row extension */
Work->fscan_col = fncols ; /* only scan the new columns */
Work->NewCols = Work->Wp ;
#ifndef NDEBUG
for (j = 0 ; j < fncols ; j++)
{
col = Fcols [j] ;
ASSERT (col >= 0 && col < Work->n_col) ;
ASSERT (Fcpos [col] == j * fnr_curr) ;
}
#endif
/* Wrow == Fcol for the IN_IN case, and for the OUT_IN case when
* the pivrow [IN][IN] happens to be the same as pivrow [OUT][IN].
* See UMF_local_search for more details. */
ASSERT (IMPLIES (Work->pivcol_in_front, Wrow == Fcols)) ;
if (Wrow == Fcols)
{
for (j = fncols ; j < rrdeg ; j++)
{
col = Wrow [j] ;
/* Fcols [j] = col ; not needed */
/* flip the col index, since Wp must be < 0 */
Work->NewCols [j] = FLIP (col) ;
Fcpos [col] = j * fnr_curr ;
}
}
else
{
for (j = fncols ; j < rrdeg ; j++)
{
col = Wrow [j] ;
Fcols [j] = col ;
/* flip the col index, since Wp must be < 0 */
Work->NewCols [j] = FLIP (col) ;
Fcpos [col] = j * fnr_curr ;
}
}
}
else
{
/* this is a completely new row */
Work->fscan_col = 0 ; /* scan all the columns */
Work->NewCols = Fcols ;
for (j = 0 ; j < rrdeg ; j++)
{
col = Wrow [j] ;
Fcols [j] = col ;
Fcpos [col] = j * fnr_curr ;
}
}
DEBUGm1 (("rrdeg "ID" fncols "ID"\n", rrdeg, fncols)) ;
fncols = rrdeg ;
Work->fncols = fncols ;
/* ---------------------------------------------------------------------- */
/* clear the frontal matrix */
/* ---------------------------------------------------------------------- */
ASSERT (fnrows == Work->fnrows_new + 1) ;
ASSERT (fncols == Work->fncols_new + 1) ;
Fcblock = Work->Fcblock ;
ASSERT (Fcblock != (Entry *) NULL) ;
zero_init_front (fncols, fnrows, Fcblock, fnr_curr) ;
#ifndef NDEBUG
DEBUG3 (("New Pivot row "ID" now in front, length "ID" fnr_curr "ID"\n",
Work->pivrow, fncols, fnr_curr)) ;
for (j = 0 ; j < fncols ; j++)
{
DEBUG4 (("col "ID" position "ID"\n", j, Fcols [j])) ;
ASSERT (Fcpos [Fcols [j]] == j * fnr_curr) ;
}
#endif
/* ---------------------------------------------------------------------- */
/* current workspace usage: */
/* ---------------------------------------------------------------------- */
/* Fcblock [0..fnr_curr-1, 0..fnc_curr-1]: space for the new frontal
* matrix. Fcblock (i,j) is located at Fcblock [i+j*fnr_curr] */
return (TRUE) ;
}

View File

@ -0,0 +1,11 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL Int UMF_init_front
(
NumericType *Numeric,
WorkType *Work
) ;

View File

@ -0,0 +1,738 @@
/* ========================================================================== */
/* === umf_internal.h ======================================================= */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/*
This file is for internal use in UMFPACK itself, and should not be included
in user code. Use umfpack.h instead. User-accessible file names and
routine names all start with the letters "umfpack_". Non-user-accessible
file names and routine names all start with "umf_".
*/
#ifndef _UMF_INTERNAL
#define _UMF_INTERNAL
/* -------------------------------------------------------------------------- */
/* ANSI standard include files */
/* -------------------------------------------------------------------------- */
/* from float.h: DBL_EPSILON */
#include <float.h>
/* from string.h: strcmp */
#include <string.h>
/* when debugging, assert.h and the assert macro are used (see umf_dump.h) */
/* -------------------------------------------------------------------------- */
/* Architecture */
/* -------------------------------------------------------------------------- */
#if defined (__sun) || defined (MSOL2) || defined (ARCH_SOL2)
#define UMF_SOL2
#define UMFPACK_ARCHITECTURE "Sun Solaris"
#elif defined (__sgi) || defined (MSGI) || defined (ARCH_SGI)
#define UMF_SGI
#define UMFPACK_ARCHITECTURE "SGI Irix"
#elif defined (__linux) || defined (MGLNX86) || defined (ARCH_GLNX86)
#define UMF_LINUX
#define UMFPACK_ARCHITECTURE "Linux"
#elif defined (__APPLE__)
#define UMF_MAC
#define UMFPACK_ARCHITECTURE "Mac"
#elif defined (_AIX) || defined (MIBM_RS) || defined (ARCH_IBM_RS)
#define UMF_AIX
#define UMFPACK_ARCHITECTURE "IBM AIX"
#elif defined (__alpha) || defined (MALPHA) || defined (ARCH_ALPHA)
#define UMF_ALPHA
#define UMFPACK_ARCHITECTURE "Compaq Alpha"
#elif defined (_WIN32) || defined (WIN32)
#if defined (__MINGW32__)
#define UMF_MINGW
#elif defined (__CYGWIN32__)
#define UMF_CYGWIN
#else
#define UMF_WINDOWS
#endif
#define UMFPACK_ARCHITECTURE "Microsoft Windows"
#elif defined (__hppa) || defined (__hpux) || defined (MHPUX) || defined (ARCH_HPUX)
#define UMF_HP
#define UMFPACK_ARCHITECTURE "HP Unix"
#elif defined (__hp700) || defined (MHP700) || defined (ARCH_HP700)
#define UMF_HP
#define UMFPACK_ARCHITECTURE "HP 700 Unix"
#else
/* If the architecture is unknown, and you call the BLAS, you may need to */
/* define BLAS_BY_VALUE, BLAS_NO_UNDERSCORE, and/or BLAS_CHAR_ARG yourself. */
#define UMFPACK_ARCHITECTURE "unknown"
#endif
/* -------------------------------------------------------------------------- */
/* basic definitions (see also amd_internal.h) */
/* -------------------------------------------------------------------------- */
#define ONES_COMPLEMENT(r) (-(r)-1)
/* -------------------------------------------------------------------------- */
/* AMD include file */
/* -------------------------------------------------------------------------- */
/* stdio.h, stdlib.h, limits.h, and math.h, NDEBUG definition, assert.h */
#include "amd_internal.h"
/* -------------------------------------------------------------------------- */
/* MATLAB include files */
/* -------------------------------------------------------------------------- */
/* only used when compiling the UMFPACK mexFunction */
#ifdef MATLAB_MEX_FILE
#include "matrix.h"
#include "mex.h"
#endif
/* -------------------------------------------------------------------------- */
/* Real/complex and int/UF_long definitions, double relops */
/* -------------------------------------------------------------------------- */
#include "umf_version.h"
/* -------------------------------------------------------------------------- */
/* Compile-time configurations */
/* -------------------------------------------------------------------------- */
#include "umf_config.h"
/* -------------------------------------------------------------------------- */
/* umfpack include file */
/* -------------------------------------------------------------------------- */
#include "ngspice/umfpack.h"
/* -------------------------------------------------------------------------- */
/* for contents of Info. This must correlate with umfpack.h */
/* -------------------------------------------------------------------------- */
#define ESTIMATE (UMFPACK_NUMERIC_SIZE_ESTIMATE - UMFPACK_NUMERIC_SIZE)
#define ACTUAL 0
/* -------------------------------------------------------------------------- */
/* get a parameter from the Control array */
/* -------------------------------------------------------------------------- */
#define GET_CONTROL(i,default) \
((Control != (double *) NULL) ? \
(SCALAR_IS_NAN (Control [i]) ? default : Control [i]) \
: default)
/* -------------------------------------------------------------------------- */
/* for clearing the external degree counters */
/* -------------------------------------------------------------------------- */
#define MAX_MARK(n) Int_MAX - (2*(n)+1)
/* -------------------------------------------------------------------------- */
/* convert number of Units to MBytes */
/* -------------------------------------------------------------------------- */
#define MBYTES(units) (((units) * sizeof (Unit)) / 1048576.0)
/* -------------------------------------------------------------------------- */
/* dense row/column macro */
/* -------------------------------------------------------------------------- */
/* In order for a row or column to be treated as "dense", it must have more */
/* entries than the value returned by this macro. n is the dimension of the */
/* matrix, and alpha is the dense row/column control parameter. */
/* Note: this is not defined if alpha is NaN or Inf: */
#define UMFPACK_DENSE_DEGREE_THRESHOLD(alpha,n) \
((Int) MAX (16.0, (alpha) * 16.0 * sqrt ((double) (n))))
/* -------------------------------------------------------------------------- */
/* PRINTF */
/* -------------------------------------------------------------------------- */
#define PRINTFk(k,params) { if (prl >= (k)) { PRINTF (params) ; } }
#define PRINTF1(params) PRINTFk (1, params)
#define PRINTF2(params) PRINTFk (2, params)
#define PRINTF3(params) PRINTFk (3, params)
#define PRINTF4(params) PRINTFk (4, params)
#define PRINTF5(params) PRINTFk (5, params)
#define PRINTF6(params) PRINTFk (6, params)
/* -------------------------------------------------------------------------- */
/* Fixed control parameters */
/* -------------------------------------------------------------------------- */
/* maximum number of columns to consider at one time, in a single front */
#define MAX_CANDIDATES 128
/* reduce Numeric->Memory request by this ratio, if allocation fails */
#define UMF_REALLOC_REDUCTION (0.95)
/* increase Numeric->Memory request by this ratio, if we need more */
#define UMF_REALLOC_INCREASE (1.2)
/* increase the dimensions of the current frontal matrix by this factor
* when it needs to grow. */
#define UMF_FRONTAL_GROWTH (1.2)
/* largest BLAS block size permitted */
#define MAXNB 64
/* if abs (y) < RECIPROCAL_TOLERANCE, then compute x/y. Otherwise x*(1/y).
* Ignored if NRECIPROCAL is defined */
#define RECIPROCAL_TOLERANCE 1e-12
/* -------------------------------------------------------------------------- */
/* Memory allocator */
/* -------------------------------------------------------------------------- */
/* See AMD/Source/amd_global.c and AMD/Source/amd.h for the
* definition of the memory allocator used by UMFPACK. Versions 4.4 and
* earlier had their memory allocator definitions here. Other global
* function pointers for UMFPACK are located in umf_global.c.
*
* The MATLAB mexFunction uses MATLAB's memory manager and mexPrintf, while the
* C-callable AMD library uses the ANSI C malloc, free, realloc, and printf
* routines.
*/
/* -------------------------------------------------------------------------- */
/* Memory space definitions */
/* -------------------------------------------------------------------------- */
/* for memory alignment - assume double has worst case alignment */
typedef double Align ;
/* get number of bytes required to hold n items of a type: */
/* note that this will not overflow, because sizeof (type) is always */
/* greater than or equal to sizeof (Int) >= 2 */
#define BYTES(type,n) (sizeof (type) * (n))
/* ceiling of (b/u). Assumes b >= 0 and u > 0 */
#define CEILING(b,u) (((b) + (u) - 1) / (u))
/* get number of Units required to hold n items of a type: */
#define UNITS(type,n) (CEILING (BYTES (type, n), sizeof (Unit)))
/* same as DUNITS, but use double instead of int to avoid overflow */
#define DUNITS(type,n) (ceil (BYTES (type, (double) n) / sizeof (Unit)))
union Unit_union
{ /* memory is allocated in multiples of Unit */
struct
{
Int
size, /* size, in Units, of the block, excl. header block */
/* size >= 0: block is in use */
/* size < 0: block is free, of |size| Units */
prevsize ; /* size, in Units, of preceding block in S->Memory */
/* during garbage_collection, prevsize is set to -e-1 */
/* for element e, or positive (and thus a free block) */
/* otherwise */
} header ; /* block header */
Align xxxxxx ; /* force alignment of blocks (xxxxxx is never used) */
} ;
typedef union Unit_union Unit ;
/* get the size of an allocated block */
#define GET_BLOCK_SIZE(p) (((p)-1)->header.size)
/* -------------------------------------------------------------------------- */
/* Numeric */
/* -------------------------------------------------------------------------- */
/*
NUMERIC_VALID and SYMBOLIC_VALID:
The different values of SYBOLIC_VALID and NUMERIC_VALID are chosen as a
first defense against corrupted *Symbolic or *Numeric pointers passed to an
UMFPACK routine. They also ensure that the objects are used only by the
same version that created them (umfpack_di_*, umfpack_dl_*, umfpack_zi_*,
or umfpack_zl_*). The values have also been changed since prior releases of
the code to ensure that all routines that operate on the objects are of the
same release. The values themselves are purely arbitrary. The are less
than the ANSI C required minimums of INT_MAX and LONG_MAX, respectively.
*/
#ifdef DINT
#define NUMERIC_VALID 15977
#define SYMBOLIC_VALID 41937
#endif
#ifdef DLONG
#define NUMERIC_VALID 399789720
#define SYMBOLIC_VALID 399192713
#endif
#ifdef ZINT
#define NUMERIC_VALID 17957
#define SYMBOLIC_VALID 40927
#endif
#ifdef ZLONG
#define NUMERIC_VALID 129987754
#define SYMBOLIC_VALID 110291734
#endif
typedef struct /* NumericType */
{
double
flops, /* "true" flop count */
relpt, /* relative pivot tolerance used */
relpt2, /* relative pivot tolerance used for sym. */
droptol,
alloc_init, /* initial allocation of Numeric->memory */
front_alloc_init, /* frontal matrix allocation parameter */
rsmin, /* smallest row sum */
rsmax, /* largest row sum */
min_udiag, /* smallest abs value on diagonal of D */
max_udiag, /* smallest abs value on diagonal of D */
rcond ; /* min (D) / max (D) */
Int
scale ;
Int valid ; /* set to NUMERIC_VALID, for validity check */
/* Memory space for A and LU factors */
Unit
*Memory ; /* working memory for A and LU factors */
Int
ihead, /* pointer to tail of LU factors, in Numeric->Memory */
itail, /* pointer to top of elements & tuples, */
/* in Numeric->Memory */
ibig, /* pointer to largest free block seen in tail */
size ; /* size of Memory, in Units */
Int
*Rperm, /* pointer to row perm array, size: n+1 */
/* after UMF_kernel: Rperm [new] = old */
/* during UMF_kernel: Rperm [old] = new */
*Cperm, /* pointer to col perm array, size: n+1 */
/* after UMF_kernel: Cperm [new] = old */
/* during UMF_kernel: Cperm [old] = new */
*Upos, /* see UMFPACK_get_numeric for a description */
*Lpos,
*Lip,
*Lilen,
*Uip,
*Uilen,
*Upattern ; /* pattern of last row of U (if singular) */
Int
ulen, /* length of Upattern */
npiv, /* number of structural pivots found (sprank approx) */
nnzpiv ; /* number of numerical (nonzero) pivots found */
Entry
*D ; /* D [i] is the diagonal entry of U */
Int do_recip ;
double *Rs ; /* scale factors for the rows of A and b */
/* do_recip FALSE: Divide row i by Rs [i] */
/* do_recip TRUE: Multiply row i by Rs [i] */
Int
n_row, n_col, /* A is n_row-by-n_row */
n1 ; /* number of singletons */
/* for information only: */
Int
tail_usage, /* amount of memory allocated in tail */
/* head_usage is Numeric->ihead */
init_usage, /* memory usage just after UMF_kernel_init */
max_usage, /* peak memory usage (excludes internal and external */
/* fragmentation in the tail) */
ngarbage, /* number of garbage collections performed */
nrealloc, /* number of reallocations performed */
ncostly, /* number of costly reallocations performed */
isize, /* size of integer pattern of L and U */
nLentries, /* number of entries in L, excluding diagonal */
nUentries, /* number of entries in U, including diagonal */
/* Some entries may be numerically zero. */
lnz, /* number of nonzero entries in L, excl. diagonal */
all_lnz, /* lnz plus entries dropped from L */
unz, /* number of nonzero entries in U, excl. diagonal */
all_unz, /* unz plus entries dropped form U */
maxfrsize ; /* largest actual front size */
Int maxnrows, maxncols ; /* not the same as Symbolic->maxnrows/cols* */
} NumericType ;
/* -------------------------------------------------------------------------- */
/* Element tuples for connecting elements together in a matrix */
/* -------------------------------------------------------------------------- */
typedef struct /* Tuple */
{
/* The (e,f) tuples for the element lists */
Int
e, /* element */
f ; /* contribution to the row/col appears at this offset */
} Tuple ;
#define TUPLES(t) MAX (4, (t) + 1)
/* Col_degree is aliased with Cperm, and Row_degree with Rperm */
#define NON_PIVOTAL_COL(col) (Col_degree [col] >= 0)
#define NON_PIVOTAL_ROW(row) (Row_degree [row] >= 0)
/* -------------------------------------------------------------------------- */
/* An element */
/* -------------------------------------------------------------------------- */
typedef struct /* Element */
{
Int
cdeg, /* external column degree + cdeg0 offset */
rdeg, /* external row degree + rdeg0 offset */
nrowsleft, /* number of rows remaining */
ncolsleft, /* number of columns remaining */
nrows, /* number of rows */
ncols, /* number of columns */
next ; /* for list link of sons, used during assembly only */
/* followed in memory by:
Int
col [0..ncols-1], column indices of this element
row [0..nrows-1] ; row indices of this element
Entry (suitably aligned, see macro below)
C [0...nrows-1, 0...ncols-1] ;
size of C is nrows*ncols Entry's
*/
} Element ;
/* macros for computing pointers to row/col indices, and contribution block: */
#define GET_ELEMENT_SIZE(nr,nc) \
(UNITS (Element, 1) + UNITS (Int, (nc) + (nr)) + UNITS (Entry, (nc) * (nr)))
#define DGET_ELEMENT_SIZE(nr,nc) \
(DUNITS (Element, 1) + DUNITS (Int, (nc) + (nr)) + DUNITS (Entry, (nc) * (nr)))
#define GET_ELEMENT_COLS(ep,p,Cols) { \
ASSERT (p != (Unit *) NULL) ; \
ASSERT (p >= Numeric->Memory + Numeric->itail) ; \
ASSERT (p <= Numeric->Memory + Numeric->size) ; \
ep = (Element *) p ; \
p += UNITS (Element, 1) ; \
Cols = (Int *) p ; \
}
#define GET_ELEMENT_PATTERN(ep,p,Cols,Rows,ncm) { \
GET_ELEMENT_COLS (ep, p, Cols) ; \
ncm = ep->ncols ; \
Rows = Cols + ncm ; \
}
#define GET_ELEMENT(ep,p,Cols,Rows,ncm,nrm,C) { \
GET_ELEMENT_PATTERN (ep, p, Cols, Rows, ncm) ; \
nrm = ep->nrows ; \
p += UNITS (Int, ncm + nrm) ; \
C = (Entry *) p ; \
}
/* -------------------------------------------------------------------------- */
/* Work data structure */
/* -------------------------------------------------------------------------- */
/*
This data structure holds items needed only during factorization.
All of this is freed when UMFPACK_numeric completes. Note that some of
it is stored in the tail end of Numeric->S (namely, the Tuples and the
Elements).
*/
typedef struct /* WorkType */
{
/* ---------------------------------------------------------------------- */
/* information about each row and col of A */
/* ---------------------------------------------------------------------- */
/*
Row_tuples: pointer to tuple list (alias with Numeric->Uip)
Row_tlen: number of tuples (alias with Numeric->Uilen)
Col_tuples: pointer to tuple list (alias with Numeric->Lip)
Col_tlen: number of tuples (alias with Numeric->Lilen)
Row_degree: degree of the row or column (alias Numeric->Rperm)
Col_degree: degree of the row or column (alias Numeric->Cperm)
The Row_degree and Col_degree are MATLAB-style colmmd approximations,
are equal to the sum of the sizes of the elements (contribution blocks)
in each row and column. They are maintained when elements are created
and assembled. They are used only during the pivot row and column
search. They are not needed to represent the pattern of the remaining
matrix.
*/
/* ---------------------------------------------------------------------- */
/* information about each element */
/* ---------------------------------------------------------------------- */
Int *E ; /* E [0 .. Work->elen-1] element "pointers" */
/* (offsets in Numeric->Memory) */
/* ---------------------------------------------------------------------- */
/* generic workspace */
/* ---------------------------------------------------------------------- */
Entry *Wx, *Wy ; /* each of size maxnrows+1 */
Int /* Sizes: nn = MAX (n_row, n_col) */
*Wp, /* nn+1 */
*Wrp, /* n_col+1 */
*Wm, /* maxnrows+1 */
*Wio, /* maxncols+1 */
*Woi, /* maxncols+1 */
*Woo, /* MAX (maxnrows,maxncols)+1 */
*Wrow, /* pointer to Fcols, Wio, or Woi */
*NewRows, /* list of rows to scan */
*NewCols ; /* list of cols to scan */
/* ---------------------------------------------------------------------- */
Int
*Lpattern, /* pattern of column of L, for one Lchain */
*Upattern, /* pattern of row of U, for one Uchain */
ulen, llen ; /* length of Upattern and Lpattern */
Int
*Diagonal_map, /* used for symmetric pivoting, of size nn+1 */
*Diagonal_imap ;/* used for symmetric pivoting, of size nn+1 */
/* ---------------------------------------------------------------------- */
Int
n_row, n_col, /* matrix is n_row-by-n_col */
nz, /* nonzeros in the elements for this matrix */
n1, /* number of row and col singletons */
elen, /* max possible number of elements */
npiv, /* number of pivot rows and columns so far */
ndiscard, /* number of discarded pivot columns */
Wrpflag,
nel, /* elements in use are in the range 1..nel */
noff_diagonal,
prior_element,
rdeg0, cdeg0,
rrdeg, ccdeg,
Candidates [MAX_CANDIDATES], /* current candidate pivot columns */
nCandidates, /* number of candidates in Candidate set */
ksuper,
firstsuper,
jsuper,
ncand, /* number of candidates (some not in Candidates[ ]) */
nextcand, /* next candidate to place in Candidate search set */
lo,
hi,
pivrow, /* current pivot row */
pivcol, /* current pivot column */
do_extend, /* true if the next pivot extends the current front */
do_update, /* true if update should be applied */
nforced, /* number of forced updates because of frontal growth */
any_skip,
do_scan2row,
do_scan2col,
do_grow,
pivot_case,
frontid, /* id of current frontal matrix */
nfr ; /* number of frontal matrices */
/* ---------------------------------------------------------------------- */
/* For row-merge tree */
/* ---------------------------------------------------------------------- */
Int
*Front_new1strow ;
/* ---------------------------------------------------------------------- */
/* current frontal matrix, F */
/* ---------------------------------------------------------------------- */
Int Pivrow [MAXNB],
Pivcol [MAXNB] ;
Entry
*Flublock, /* LU block, nb-by-nb */
*Flblock, /* L block, fnr_curr-by-nb */
*Fublock, /* U block, nb-by-fnc_curr, or U' fnc_curr-by-nb */
*Fcblock ; /* C block, fnr_curr-by-fnc_curr */
Int
*Frows, /* Frows [0.. ]: row indices of F */
*Fcols, /* Fcols [0.. ]: column indices of F */
*Frpos, /* position of row indices in F, or -1 if not present */
/* if Frows[i] == row, then Frpos[row] == i */
*Fcpos, /* position of col indices in F, or -1 if not present */
/* if Fcols[j] == col, then */
/* Fcpos[col] == j*Work->fnr_curr */
fnrows, /* number of rows in contribution block in F */
fncols, /* number of columns in contribution block in F */
fnr_curr, /* maximum # of rows in F (leading dimension) */
fnc_curr, /* maximum # of columns in F */
fcurr_size, /* current size of F */
fnrows_max, /* max possible column-dimension (max # of rows) of F */
fncols_max, /* max possible row-dimension (max # of columns) of F */
nb,
fnpiv, /* number of pivots in F */
fnzeros, /* number of explicit zero entries in LU block */
fscan_row, /* where to start scanning rows of F in UMF_assemble */
fscan_col, /* where to start scanning cols of F in UMF_assemble */
fnrows_new, /* number of new row indices in F after pivot added */
fncols_new, /* number of new col indices in F after pivot added */
pivrow_in_front, /* true if current pivot row in Frows */
pivcol_in_front ; /* true if current pivot column in Fcols */
/* ----------------------------------------------------------------------
* Current frontal matrix
* ----------------------------------------------------------------------
* The current frontal matrix is held as a single block of memory allocated
* from the "tail" end of Numeric->Memory. It is subdivided into four
* parts: an LU block, an L block, a U block, and a C block.
*
* Let k = fnpiv, r = fnrows, and c = fncols for the following discussion.
* Let dr = fnr_curr and dc = fnc_curr. Note that r <= dr and c <= dc.
*
* The LU block is of dimension nb-by-nb. The first k-by-k part holds the
* "diagonal" part of the LU factors for these k pivot rows and columns.
* The k pivot row and column indices in this part are Pivrow [0..k-1] and
* Pivcol [0..k-1], respectively.
*
* The L block is of dimension dr-by-nb. It holds the k pivot columns,
* except for the leading k-by-k part in the LU block. Only the leading
* r-by-k part is in use.
*
* The U block is of dimension dc-by-nb. It holds the k pivot rows,
* except for the leading k-by-k part in the LU block. It is stored in
* row-oriented form. Only the leading c-by-k part is in use.
*
* The C block is of dimension dr-by-dc. It holds the current contribution
* block. Only the leading r-by-c part is in use. The column indices in
* the C block are Fcols [0..c-1], and the row indices are Frows [0..r-1].
*
* dr is always odd, to avoid bad cache behavior.
*/
} WorkType ;
/* -------------------------------------------------------------------------- */
/* Symbolic */
/* -------------------------------------------------------------------------- */
/*
This is is constructed by UMFPACK_symbolic, and is needed by UMFPACK_numeric
to factor the matrix.
*/
typedef struct /* SymbolicType */
{
double
num_mem_usage_est, /* estimated max Numeric->Memory size */
num_mem_size_est, /* estimated final Numeric->Memory size */
peak_sym_usage, /* peak Symbolic and SymbolicWork usage */
sym, /* symmetry of pattern */
dnum_mem_init_usage, /* min Numeric->Memory for UMF_kernel_init */
amd_lunz, /* nz in LU for AMD, with symmetric pivoting */
lunz_bound ; /* max nx in LU, for arbitrary row pivoting */
Int valid, /* set to SYMBOLIC_VALID, for validity check */
max_nchains,
nchains,
*Chain_start,
*Chain_maxrows,
*Chain_maxcols,
maxnrows, /* largest number of rows in any front */
maxncols, /* largest number of columns in any front */
*Front_npivcol, /* Front_npivcol [j] = size of jth supercolumn*/
*Front_1strow, /* first row in front j */
*Front_leftmostdesc, /* leftmost desc of front j */
*Front_parent, /* super-column elimination tree */
*Cperm_init, /* initial column ordering */
*Rperm_init, /* initial row ordering */
*Cdeg, *Rdeg,
*Esize,
dense_row_threshold,
n1, /* number of singletons */
nempty, /* MIN (nempty_row, nempty_col) */
*Diagonal_map, /* initial "diagonal" */
esize, /* size of Esize array */
nfr,
n_row, n_col, /* matrix A is n_row-by-n_col */
nz, /* nz of original matrix */
nb, /* block size for BLAS 3 */
num_mem_init_usage, /* min Numeric->Memory for UMF_kernel_init */
nempty_row, nempty_col,
strategy,
ordering,
fixQ,
prefer_diagonal,
nzaat,
nzdiag,
amd_dmax ;
} SymbolicType ;
/* -------------------------------------------------------------------------- */
/* for debugging only: */
/* -------------------------------------------------------------------------- */
#include "umf_dump.h"
/* -------------------------------------------------------------------------- */
/* for statement coverage testing only: */
/* -------------------------------------------------------------------------- */
#ifdef TESTING
/* for testing integer overflow: */
#ifdef TEST_FOR_INTEGER_OVERFLOW
#undef MAX_MARK
#define MAX_MARK(n) (3*(n))
#endif
/* for testing out-of-memory conditions: */
#define UMF_TCOV_TEST
#ifndef EXTERN
#define EXTERN extern
#endif
GLOBAL EXTERN int umf_fail, umf_fail_lo, umf_fail_hi ;
GLOBAL EXTERN int umf_realloc_fail, umf_realloc_lo, umf_realloc_hi ;
/* for testing malloc count: */
#define UMF_MALLOC_COUNT
#endif
#endif

View File

@ -0,0 +1,56 @@
/* ========================================================================== */
/* === UMF_is_permutation =================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/* Return TRUE if P is a r-permutation vector, FALSE otherwise */
/* P [0..r-1] must be an r-permutation of 0..n-1 */
#include "umf_internal.h"
#include "umf_is_permutation.h"
GLOBAL Int UMF_is_permutation
(
const Int P [ ], /* permutation of size r */
Int W [ ], /* workspace of size n */
Int n,
Int r
)
{
Int i, k ;
if (!P)
{
/* if P is (Int *) NULL, this is the identity permutation */
return (TRUE) ;
}
ASSERT (W != (Int *) NULL) ;
for (i = 0 ; i < n ; i++)
{
W [i] = FALSE ;
}
for (k = 0 ; k < r ; k++)
{
i = P [k] ;
DEBUG5 (("k "ID" i "ID"\n", k, i)) ;
if (i < 0 || i >= n)
{
DEBUG0 (("i out of range "ID" "ID"\n", i, n)) ;
return (FALSE) ;
}
if (W [i])
{
DEBUG0 (("i duplicate "ID"\n", i)) ;
return (FALSE) ;
}
W [i] = TRUE ;
}
return (TRUE) ;
}

View File

@ -0,0 +1,13 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL Int UMF_is_permutation
(
const Int P [ ],
Int W [ ],
Int n,
Int r
) ;

View File

@ -0,0 +1,300 @@
/* ========================================================================== */
/* === UMF_kernel =========================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/*
Primary factorization routine. Called by UMFPACK_numeric.
Returns:
UMFPACK_OK if successful,
UMFPACK_ERROR_out_of_memory if out of memory, or
UMFPACK_ERROR_different_pattern if pattern of matrix (Ap and/or Ai)
has changed since the call to UMFPACK_*symbolic.
*/
#include "umf_internal.h"
#include "umf_kernel.h"
#include "umf_kernel_init.h"
#include "umf_init_front.h"
#include "umf_start_front.h"
#include "umf_assemble.h"
#include "umf_scale_column.h"
#include "umf_local_search.h"
#include "umf_create_element.h"
#include "umf_extend_front.h"
#include "umf_blas3_update.h"
#include "umf_store_lu.h"
#include "umf_kernel_wrapup.h"
/* perform an action, and return if out of memory */
#define DO(action) { if (! (action)) { return (UMFPACK_ERROR_out_of_memory) ; }}
GLOBAL Int UMF_kernel
(
const Int Ap [ ],
const Int Ai [ ],
const double Ax [ ],
#ifdef COMPLEX
const double Az [ ],
#endif
NumericType *Numeric,
WorkType *Work,
SymbolicType *Symbolic
)
{
/* ---------------------------------------------------------------------- */
/* local variables */
/* ---------------------------------------------------------------------- */
Int j, f1, f2, chain, nchains, *Chain_start, status, fixQ, evaporate,
*Front_npivcol, jmax, nb, drop ;
/* ---------------------------------------------------------------------- */
/* initialize memory space and load the matrix. Optionally scale. */
/* ---------------------------------------------------------------------- */
if (!UMF_kernel_init (Ap, Ai, Ax,
#ifdef COMPLEX
Az,
#endif
Numeric, Work, Symbolic))
{
/* UMF_kernel_init is guaranteed to succeed, since UMFPACK_numeric */
/* either allocates enough space or if not, UMF_kernel does not get */
/* called. So running out of memory here is a fatal error, and means */
/* that the user changed Ap and/or Ai since the call to */
/* UMFPACK_*symbolic. */
DEBUGm4 (("kernel init failed\n")) ;
return (UMFPACK_ERROR_different_pattern) ;
}
/* ---------------------------------------------------------------------- */
/* get the symbolic factorization */
/* ---------------------------------------------------------------------- */
nchains = Symbolic->nchains ;
Chain_start = Symbolic->Chain_start ;
Front_npivcol = Symbolic->Front_npivcol ;
nb = Symbolic->nb ;
fixQ = Symbolic->fixQ ;
drop = Numeric->droptol > 0.0 ;
#ifndef NDEBUG
for (chain = 0 ; chain < nchains ; chain++)
{
Int i ;
f1 = Chain_start [chain] ;
f2 = Chain_start [chain+1] - 1 ;
DEBUG1 (("\nCHain: "ID" start "ID" end "ID"\n", chain, f1, f2)) ;
for (i = f1 ; i <= f2 ; i++)
{
DEBUG1 (("Front "ID", npivcol "ID"\n", i, Front_npivcol [i])) ;
}
}
#endif
/* ---------------------------------------------------------------------- */
/* factorize each chain of frontal matrices */
/* ---------------------------------------------------------------------- */
for (chain = 0 ; chain < nchains ; chain++)
{
f1 = Chain_start [chain] ;
f2 = Chain_start [chain+1] - 1 ;
/* ------------------------------------------------------------------ */
/* get the initial frontal matrix size for this chain */
/* ------------------------------------------------------------------ */
DO (UMF_start_front (chain, Numeric, Work, Symbolic)) ;
/* ------------------------------------------------------------------ */
/* factorize each front in the chain */
/* ------------------------------------------------------------------ */
for (Work->frontid = f1 ; Work->frontid <= f2 ; Work->frontid++)
{
/* -------------------------------------------------------------- */
/* Initialize the pivot column candidate set */
/* -------------------------------------------------------------- */
Work->ncand = Front_npivcol [Work->frontid] ;
Work->lo = Work->nextcand ;
Work->hi = Work->nextcand + Work->ncand - 1 ;
jmax = MIN (MAX_CANDIDATES, Work->ncand) ;
DEBUGm1 ((">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Starting front "
ID", npivcol: "ID"\n", Work->frontid, Work->ncand)) ;
if (fixQ)
{
/* do not modify the column order */
jmax = 1 ;
}
DEBUGm1 (("Initial candidates: ")) ;
for (j = 0 ; j < jmax ; j++)
{
DEBUGm1 ((" "ID, Work->nextcand)) ;
ASSERT (Work->nextcand <= Work->hi) ;
Work->Candidates [j] = Work->nextcand++ ;
}
Work->nCandidates = jmax ;
DEBUGm1 (("\n")) ;
/* -------------------------------------------------------------- */
/* Assemble and factorize the current frontal matrix */
/* -------------------------------------------------------------- */
while (Work->ncand > 0)
{
/* ---------------------------------------------------------- */
/* get the pivot row and column */
/* ---------------------------------------------------------- */
status = UMF_local_search (Numeric, Work, Symbolic) ;
if (status == UMFPACK_ERROR_different_pattern)
{
/* :: pattern change detected in umf_local_search :: */
/* input matrix has changed since umfpack_*symbolic */
DEBUGm4 (("local search failed\n")) ;
return (UMFPACK_ERROR_different_pattern) ;
}
if (status == UMFPACK_WARNING_singular_matrix)
{
/* no pivot found, discard and try again */
continue ;
}
/* ---------------------------------------------------------- */
/* update if front not extended or too many zeros in L,U */
/* ---------------------------------------------------------- */
if (Work->do_update)
{
UMF_blas3_update (Work) ;
if (drop)
{
DO (UMF_store_lu_drop (Numeric, Work)) ;
}
else
{
DO (UMF_store_lu (Numeric, Work)) ;
}
}
/* ---------------------------------------------------------- */
/* extend the frontal matrix, or start a new one */
/* ---------------------------------------------------------- */
if (Work->do_extend)
{
/* extend the current front */
DO (UMF_extend_front (Numeric, Work)) ;
}
else
{
/* finish the current front (if any) and start a new one */
DO (UMF_create_element (Numeric, Work, Symbolic)) ;
DO (UMF_init_front (Numeric, Work)) ;
}
/* ---------------------------------------------------------- */
/* Numerical & symbolic assembly into current frontal matrix */
/* ---------------------------------------------------------- */
if (fixQ)
{
UMF_assemble_fixq (Numeric, Work) ;
}
else
{
UMF_assemble (Numeric, Work) ;
}
/* ---------------------------------------------------------- */
/* scale the pivot column */
/* ---------------------------------------------------------- */
UMF_scale_column (Numeric, Work) ;
/* ---------------------------------------------------------- */
/* Numerical update if enough pivots accumulated */
/* ---------------------------------------------------------- */
evaporate = Work->fnrows == 0 || Work->fncols == 0 ;
if (Work->fnpiv >= nb || evaporate)
{
UMF_blas3_update (Work) ;
if (drop)
{
DO (UMF_store_lu_drop (Numeric, Work)) ;
}
else
{
DO (UMF_store_lu (Numeric, Work)) ;
}
}
Work->pivrow_in_front = FALSE ;
Work->pivcol_in_front = FALSE ;
/* ---------------------------------------------------------- */
/* If front is empty, evaporate it */
/* ---------------------------------------------------------- */
if (evaporate)
{
/* This does not create an element, just evaporates it.
* It ensures that a front is not 0-by-c or r-by-0. No
* memory is allocated, so it is guaranteed to succeed. */
(void) UMF_create_element (Numeric, Work, Symbolic) ;
Work->fnrows = 0 ;
Work->fncols = 0 ;
}
}
}
/* ------------------------------------------------------------------
* Wrapup the current frontal matrix. This is the last in a chain
* in the column elimination tree. The next frontal matrix
* cannot overlap with the current one, which will be its sibling
* in the column etree.
* ------------------------------------------------------------------ */
UMF_blas3_update (Work) ;
if (drop)
{
DO (UMF_store_lu_drop (Numeric, Work)) ;
}
else
{
DO (UMF_store_lu (Numeric, Work)) ;
}
Work->fnrows_new = Work->fnrows ;
Work->fncols_new = Work->fncols ;
DO (UMF_create_element (Numeric, Work, Symbolic)) ;
/* ------------------------------------------------------------------ */
/* current front is now empty */
/* ------------------------------------------------------------------ */
Work->fnrows = 0 ;
Work->fncols = 0 ;
}
/* ---------------------------------------------------------------------- */
/* end the last Lchain and Uchain and finalize the LU factors */
/* ---------------------------------------------------------------------- */
UMF_kernel_wrapup (Numeric, Symbolic, Work) ;
/* note that the matrix may be singular (this is OK) */
return (UMFPACK_OK) ;
}

View File

@ -0,0 +1,18 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL Int UMF_kernel
(
const Int Ap [ ],
const Int Ai [ ],
const double Ax [ ],
#ifdef COMPLEX
const double Az [ ],
#endif
NumericType *Numeric,
WorkType *Work,
SymbolicType *Symbolic
) ;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL Int UMF_kernel_init
(
const Int Ap [ ],
const Int Ai [ ],
const double Ax [ ],
#ifdef COMPLEX
const double Az [ ],
#endif
NumericType *Numeric,
WorkType *Work,
SymbolicType *Symbolic
) ;

View File

@ -0,0 +1,467 @@
/* ========================================================================== */
/* === UMF_kernel_wrapup ==================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/* The matrix is factorized. Finish the LU data structure. */
#include "umf_internal.h"
#include "umf_kernel_wrapup.h"
GLOBAL void UMF_kernel_wrapup
(
NumericType *Numeric,
SymbolicType *Symbolic,
WorkType *Work
)
{
/* ---------------------------------------------------------------------- */
/* local variables */
/* ---------------------------------------------------------------------- */
Entry pivot_value ;
double d ;
Entry *D ;
Int i, k, col, row, llen, ulen, *ip, *Rperm, *Cperm, *Lilen, npiv, lp,
*Uilen, *Lip, *Uip, *Cperm_init, up, pivrow, pivcol, *Lpos, *Upos, *Wr,
*Wc, *Wp, *Frpos, *Fcpos, *Row_degree, *Col_degree, *Rperm_init,
n_row, n_col, n_inner, zero_pivot, nan_pivot, n1 ;
#ifndef NDEBUG
UMF_dump_matrix (Numeric, Work, FALSE) ;
#endif
DEBUG0 (("Kernel complete, Starting Kernel wrapup\n")) ;
n_row = Symbolic->n_row ;
n_col = Symbolic->n_col ;
n_inner = MIN (n_row, n_col) ;
Rperm = Numeric->Rperm ;
Cperm = Numeric->Cperm ;
Lilen = Numeric->Lilen ;
Uilen = Numeric->Uilen ;
Upos = Numeric->Upos ;
Lpos = Numeric->Lpos ;
Lip = Numeric->Lip ;
Uip = Numeric->Uip ;
D = Numeric->D ;
npiv = Work->npiv ;
Numeric->npiv = npiv ;
Numeric->ulen = Work->ulen ;
ASSERT (n_row == Numeric->n_row) ;
ASSERT (n_col == Symbolic->n_col) ;
DEBUG0 (("Wrap-up: npiv "ID" ulen "ID"\n", npiv, Numeric->ulen)) ;
ASSERT (npiv <= n_inner) ;
/* this will be nonzero only if matrix is singular or rectangular */
ASSERT (IMPLIES (npiv == n_col, Work->ulen == 0)) ;
/* ---------------------------------------------------------------------- */
/* find the smallest and largest entries in D */
/* ---------------------------------------------------------------------- */
for (k = 0 ; k < npiv ; k++)
{
pivot_value = D [k] ;
ABS (d, pivot_value) ;
zero_pivot = SCALAR_IS_ZERO (d) ;
nan_pivot = SCALAR_IS_NAN (d) ;
if (!zero_pivot)
{
/* the pivot is nonzero, but might be Inf or NaN */
Numeric->nnzpiv++ ;
}
if (k == 0)
{
Numeric->min_udiag = d ;
Numeric->max_udiag = d ;
}
else
{
/* min (abs (diag (U))) behaves as follows: If any entry is zero,
then the result is zero (regardless of the presence of NaN's).
Otherwise, if any entry is NaN, then the result is NaN.
Otherwise, the result is the smallest absolute value on the
diagonal of U.
*/
if (SCALAR_IS_NONZERO (Numeric->min_udiag))
{
if (zero_pivot || nan_pivot)
{
Numeric->min_udiag = d ;
}
else if (!SCALAR_IS_NAN (Numeric->min_udiag))
{
/* d and min_udiag are both non-NaN */
Numeric->min_udiag = MIN (Numeric->min_udiag, d) ;
}
}
/*
max (abs (diag (U))) behaves as follows: If any entry is NaN
then the result is NaN. Otherise, the result is the largest
absolute value on the diagonal of U.
*/
if (nan_pivot)
{
Numeric->max_udiag = d ;
}
else if (!SCALAR_IS_NAN (Numeric->max_udiag))
{
/* d and max_udiag are both non-NaN */
Numeric->max_udiag = MAX (Numeric->max_udiag, d) ;
}
}
}
/* ---------------------------------------------------------------------- */
/* check if matrix is singular or rectangular */
/* ---------------------------------------------------------------------- */
Col_degree = Cperm ; /* for NON_PIVOTAL_COL macro */
Row_degree = Rperm ; /* for NON_PIVOTAL_ROW macro */
if (npiv < n_row)
{
/* finalize the row permutation */
k = npiv ;
DEBUGm3 (("Singular pivot rows "ID" to "ID"\n", k, n_row-1)) ;
for (row = 0 ; row < n_row ; row++)
{
if (NON_PIVOTAL_ROW (row))
{
Rperm [row] = ONES_COMPLEMENT (k) ;
DEBUGm3 (("Singular row "ID" is k: "ID" pivot row\n", row, k)) ;
ASSERT (!NON_PIVOTAL_ROW (row)) ;
Lpos [row] = EMPTY ;
Uip [row] = EMPTY ;
Uilen [row] = 0 ;
k++ ;
}
}
ASSERT (k == n_row) ;
}
if (npiv < n_col)
{
/* finalize the col permutation */
k = npiv ;
DEBUGm3 (("Singular pivot cols "ID" to "ID"\n", k, n_col-1)) ;
for (col = 0 ; col < n_col ; col++)
{
if (NON_PIVOTAL_COL (col))
{
Cperm [col] = ONES_COMPLEMENT (k) ;
DEBUGm3 (("Singular col "ID" is k: "ID" pivot row\n", col, k)) ;
ASSERT (!NON_PIVOTAL_COL (col)) ;
Upos [col] = EMPTY ;
Lip [col] = EMPTY ;
Lilen [col] = 0 ;
k++ ;
}
}
ASSERT (k == n_col) ;
}
if (npiv < n_inner)
{
/* finalize the diagonal of U */
DEBUGm3 (("Diag of U is zero, "ID" to "ID"\n", npiv, n_inner-1)) ;
for (k = npiv ; k < n_inner ; k++)
{
CLEAR (D [k]) ;
}
}
/* save the pattern of the last row of U */
if (Numeric->ulen > 0)
{
DEBUGm3 (("Last row of U is not empty\n")) ;
Numeric->Upattern = Work->Upattern ;
Work->Upattern = (Int *) NULL ;
}
DEBUG2 (("Nnzpiv: "ID" npiv "ID"\n", Numeric->nnzpiv, npiv)) ;
ASSERT (Numeric->nnzpiv <= npiv) ;
if (Numeric->nnzpiv < n_inner && !SCALAR_IS_NAN (Numeric->min_udiag))
{
/* the rest of the diagonal is zero, so min_udiag becomes 0,
* unless it is already NaN. */
Numeric->min_udiag = 0.0 ;
}
/* ---------------------------------------------------------------------- */
/* size n_row, n_col workspaces that can be used here: */
/* ---------------------------------------------------------------------- */
Frpos = Work->Frpos ; /* of size n_row+1 */
Fcpos = Work->Fcpos ; /* of size n_col+1 */
Wp = Work->Wp ; /* of size MAX(n_row,n_col)+1 */
/* Work->Upattern ; cannot be used (in Numeric) */
Wr = Work->Lpattern ; /* of size n_row+1 */
Wc = Work->Wrp ; /* of size n_col+1 or bigger */
/* ---------------------------------------------------------------------- */
/* construct Rperm from inverse permutations */
/* ---------------------------------------------------------------------- */
/* use Frpos for temporary copy of inverse row permutation [ */
for (pivrow = 0 ; pivrow < n_row ; pivrow++)
{
k = Rperm [pivrow] ;
ASSERT (k < 0) ;
k = ONES_COMPLEMENT (k) ;
ASSERT (k >= 0 && k < n_row) ;
Wp [k] = pivrow ;
Frpos [pivrow] = k ;
}
for (k = 0 ; k < n_row ; k++)
{
Rperm [k] = Wp [k] ;
}
/* ---------------------------------------------------------------------- */
/* construct Cperm from inverse permutation */
/* ---------------------------------------------------------------------- */
/* use Fcpos for temporary copy of inverse column permutation [ */
for (pivcol = 0 ; pivcol < n_col ; pivcol++)
{
k = Cperm [pivcol] ;
ASSERT (k < 0) ;
k = ONES_COMPLEMENT (k) ;
ASSERT (k >= 0 && k < n_col) ;
Wp [k] = pivcol ;
/* save a copy of the inverse column permutation in Fcpos */
Fcpos [pivcol] = k ;
}
for (k = 0 ; k < n_col ; k++)
{
Cperm [k] = Wp [k] ;
}
#ifndef NDEBUG
for (k = 0 ; k < n_col ; k++)
{
col = Cperm [k] ;
ASSERT (col >= 0 && col < n_col) ;
ASSERT (Fcpos [col] == k) ; /* col is the kth pivot */
}
for (k = 0 ; k < n_row ; k++)
{
row = Rperm [k] ;
ASSERT (row >= 0 && row < n_row) ;
ASSERT (Frpos [row] == k) ; /* row is the kth pivot */
}
#endif
#ifndef NDEBUG
UMF_dump_lu (Numeric) ;
#endif
/* ---------------------------------------------------------------------- */
/* permute Lpos, Upos, Lilen, Lip, Uilen, and Uip */
/* ---------------------------------------------------------------------- */
for (k = 0 ; k < npiv ; k++)
{
pivrow = Rperm [k] ;
Wr [k] = Uilen [pivrow] ;
Wp [k] = Uip [pivrow] ;
}
for (k = 0 ; k < npiv ; k++)
{
Uilen [k] = Wr [k] ;
Uip [k] = Wp [k] ;
}
for (k = 0 ; k < npiv ; k++)
{
pivrow = Rperm [k] ;
Wp [k] = Lpos [pivrow] ;
}
for (k = 0 ; k < npiv ; k++)
{
Lpos [k] = Wp [k] ;
}
for (k = 0 ; k < npiv ; k++)
{
pivcol = Cperm [k] ;
Wc [k] = Lilen [pivcol] ;
Wp [k] = Lip [pivcol] ;
}
for (k = 0 ; k < npiv ; k++)
{
Lilen [k] = Wc [k] ;
Lip [k] = Wp [k] ;
}
for (k = 0 ; k < npiv ; k++)
{
pivcol = Cperm [k] ;
Wp [k] = Upos [pivcol] ;
}
for (k = 0 ; k < npiv ; k++)
{
Upos [k] = Wp [k] ;
}
/* ---------------------------------------------------------------------- */
/* terminate the last Uchain and last Lchain */
/* ---------------------------------------------------------------------- */
Upos [npiv] = EMPTY ;
Lpos [npiv] = EMPTY ;
Uip [npiv] = EMPTY ;
Lip [npiv] = EMPTY ;
Uilen [npiv] = 0 ;
Lilen [npiv] = 0 ;
/* ---------------------------------------------------------------------- */
/* convert U to the new pivot order */
/* ---------------------------------------------------------------------- */
n1 = Symbolic->n1 ;
for (k = 0 ; k < n1 ; k++)
{
/* this is a singleton row of U */
ulen = Uilen [k] ;
DEBUG4 (("K "ID" New U. ulen "ID" Singleton 1\n", k, ulen)) ;
if (ulen > 0)
{
up = Uip [k] ;
ip = (Int *) (Numeric->Memory + up) ;
for (i = 0 ; i < ulen ; i++)
{
col = *ip ;
DEBUG4 ((" old col "ID" new col "ID"\n", col, Fcpos [col]));
ASSERT (col >= 0 && col < n_col) ;
*ip++ = Fcpos [col] ;
}
}
}
for (k = n1 ; k < npiv ; k++)
{
up = Uip [k] ;
if (up < 0)
{
/* this is the start of a new Uchain (with a pattern) */
ulen = Uilen [k] ;
DEBUG4 (("K "ID" New U. ulen "ID" End_Uchain 1\n", k, ulen)) ;
if (ulen > 0)
{
up = -up ;
ip = (Int *) (Numeric->Memory + up) ;
for (i = 0 ; i < ulen ; i++)
{
col = *ip ;
DEBUG4 ((" old col "ID" new col "ID"\n", col, Fcpos [col]));
ASSERT (col >= 0 && col < n_col) ;
*ip++ = Fcpos [col] ;
}
}
}
}
ulen = Numeric->ulen ;
if (ulen > 0)
{
/* convert last pivot row of U to the new pivot order */
DEBUG4 (("K "ID" (last)\n", k)) ;
for (i = 0 ; i < ulen ; i++)
{
col = Numeric->Upattern [i] ;
DEBUG4 ((" old col "ID" new col "ID"\n", col, Fcpos [col])) ;
Numeric->Upattern [i] = Fcpos [col] ;
}
}
/* Fcpos no longer needed ] */
/* ---------------------------------------------------------------------- */
/* convert L to the new pivot order */
/* ---------------------------------------------------------------------- */
for (k = 0 ; k < n1 ; k++)
{
llen = Lilen [k] ;
DEBUG4 (("K "ID" New L. llen "ID" Singleton col\n", k, llen)) ;
if (llen > 0)
{
lp = Lip [k] ;
ip = (Int *) (Numeric->Memory + lp) ;
for (i = 0 ; i < llen ; i++)
{
row = *ip ;
DEBUG4 ((" old row "ID" new row "ID"\n", row, Frpos [row])) ;
ASSERT (row >= 0 && row < n_row) ;
*ip++ = Frpos [row] ;
}
}
}
for (k = n1 ; k < npiv ; k++)
{
llen = Lilen [k] ;
DEBUG4 (("K "ID" New L. llen "ID" \n", k, llen)) ;
if (llen > 0)
{
lp = Lip [k] ;
if (lp < 0)
{
/* this starts a new Lchain */
lp = -lp ;
}
ip = (Int *) (Numeric->Memory + lp) ;
for (i = 0 ; i < llen ; i++)
{
row = *ip ;
DEBUG4 ((" old row "ID" new row "ID"\n", row, Frpos [row])) ;
ASSERT (row >= 0 && row < n_row) ;
*ip++ = Frpos [row] ;
}
}
}
/* Frpos no longer needed ] */
/* ---------------------------------------------------------------------- */
/* combine symbolic and numeric permutations */
/* ---------------------------------------------------------------------- */
Cperm_init = Symbolic->Cperm_init ;
Rperm_init = Symbolic->Rperm_init ;
for (k = 0 ; k < n_row ; k++)
{
Rperm [k] = Rperm_init [Rperm [k]] ;
}
for (k = 0 ; k < n_col ; k++)
{
Cperm [k] = Cperm_init [Cperm [k]] ;
}
/* Work object will be freed immediately upon return (to UMF_kernel */
/* and then to UMFPACK_numeric). */
}

View File

@ -0,0 +1,12 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL void UMF_kernel_wrapup
(
NumericType *Numeric,
SymbolicType *Symbolic,
WorkType *Work
) ;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL Int UMF_local_search
(
NumericType *Numeric,
WorkType *Work,
SymbolicType *Symbolic
) ;

View File

@ -0,0 +1,152 @@
/* ========================================================================== */
/* === UMF_lsolve =========================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/* solves Lx = b, where L is the lower triangular factor of a matrix */
/* B is overwritten with the solution X. */
/* Returns the floating point operation count */
#include "umf_internal.h"
#include "umf_lsolve.h"
GLOBAL double UMF_lsolve
(
NumericType *Numeric,
Entry X [ ], /* b on input, solution x on output */
Int Pattern [ ] /* a work array of size n */
)
{
Entry xk ;
Entry *xp, *Lval ;
Int k, deg, *ip, j, row, *Lpos, *Lilen, *Lip, llen, lp, newLchain,
pos, npiv, n1, *Li ;
/* ---------------------------------------------------------------------- */
if (Numeric->n_row != Numeric->n_col) return (0.) ;
npiv = Numeric->npiv ;
Lpos = Numeric->Lpos ;
Lilen = Numeric->Lilen ;
Lip = Numeric->Lip ;
n1 = Numeric->n1 ;
#ifndef NDEBUG
DEBUG4 (("Lsolve start:\n")) ;
for (j = 0 ; j < Numeric->n_row ; j++)
{
DEBUG4 (("Lsolve start "ID": ", j)) ;
EDEBUG4 (X [j]) ;
DEBUG4 (("\n")) ;
}
#endif
/* ---------------------------------------------------------------------- */
/* singletons */
/* ---------------------------------------------------------------------- */
for (k = 0 ; k < n1 ; k++)
{
DEBUG4 (("Singleton k "ID"\n", k)) ;
xk = X [k] ;
deg = Lilen [k] ;
if (deg > 0 && IS_NONZERO (xk))
{
lp = Lip [k] ;
Li = (Int *) (Numeric->Memory + lp) ;
lp += UNITS (Int, deg) ;
Lval = (Entry *) (Numeric->Memory + lp) ;
for (j = 0 ; j < deg ; j++)
{
DEBUG4 ((" row "ID" k "ID" value", Li [j], k)) ;
EDEBUG4 (Lval [j]) ;
DEBUG4 (("\n")) ;
/* X [Li [j]] -= xk * Lval [j] ; */
MULT_SUB (X [Li [j]], xk, Lval [j]) ;
}
}
}
/* ---------------------------------------------------------------------- */
/* rest of L */
/* ---------------------------------------------------------------------- */
deg = 0 ;
for (k = n1 ; k < npiv ; k++)
{
/* ------------------------------------------------------------------ */
/* make column of L in Pattern [0..deg-1] */
/* ------------------------------------------------------------------ */
lp = Lip [k] ;
newLchain = (lp < 0) ;
if (newLchain)
{
lp = -lp ;
deg = 0 ;
DEBUG4 (("start of chain for column of L\n")) ;
}
/* remove pivot row */
pos = Lpos [k] ;
if (pos != EMPTY)
{
DEBUG4 ((" k "ID" removing row "ID" at position "ID"\n",
k, Pattern [pos], pos)) ;
ASSERT (!newLchain) ;
ASSERT (deg > 0) ;
ASSERT (pos >= 0 && pos < deg) ;
ASSERT (Pattern [pos] == k) ;
Pattern [pos] = Pattern [--deg] ;
}
/* concatenate the pattern */
ip = (Int *) (Numeric->Memory + lp) ;
llen = Lilen [k] ;
for (j = 0 ; j < llen ; j++)
{
row = *ip++ ;
DEBUG4 ((" row "ID" k "ID"\n", row, k)) ;
ASSERT (row > k) ;
Pattern [deg++] = row ;
}
/* ------------------------------------------------------------------ */
/* use column k of L */
/* ------------------------------------------------------------------ */
xk = X [k] ;
if (IS_NONZERO (xk))
{
xp = (Entry *) (Numeric->Memory + lp + UNITS (Int, llen)) ;
for (j = 0 ; j < deg ; j++)
{
DEBUG4 ((" row "ID" k "ID" value", Pattern [j], k)) ;
EDEBUG4 (*xp) ;
DEBUG4 (("\n")) ;
/* X [Pattern [j]] -= xk * (*xp) ; */
MULT_SUB (X [Pattern [j]], xk, *xp) ;
xp++ ;
}
}
}
#ifndef NDEBUG
for (j = 0 ; j < Numeric->n_row ; j++)
{
DEBUG4 (("Lsolve done "ID": ", j)) ;
EDEBUG4 (X [j]) ;
DEBUG4 (("\n")) ;
}
DEBUG4 (("Lsolve done.\n")) ;
#endif
return (MULTSUB_FLOPS * ((double) Numeric->lnz)) ;
}

View File

@ -0,0 +1,12 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL double UMF_lsolve
(
NumericType *Numeric,
Entry X [ ],
Int Pattern [ ]
) ;

View File

@ -0,0 +1,226 @@
/* ========================================================================== */
/* === UMF_ltsolve ========================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/* Solves L'x = b or L.'x=b, where L is the lower triangular factor of a */
/* matrix. B is overwritten with the solution X. */
/* Returns the floating point operation count */
#include "umf_internal.h"
#include "umf_ltsolve.h"
GLOBAL double
#ifdef CONJUGATE_SOLVE
UMF_lhsolve /* solve L'x=b (complex conjugate transpose) */
#else
UMF_ltsolve /* solve L.'x=b (array transpose) */
#endif
(
NumericType *Numeric,
Entry X [ ], /* b on input, solution x on output */
Int Pattern [ ] /* a work array of size n */
)
{
Entry xk ;
Entry *xp, *Lval ;
Int k, deg, *ip, j, row, *Lpos, *Lilen, kstart, kend, *Lip, llen,
lp, pos, npiv, n1, *Li ;
/* ---------------------------------------------------------------------- */
if (Numeric->n_row != Numeric->n_col) return (0.) ;
npiv = Numeric->npiv ;
Lpos = Numeric->Lpos ;
Lilen = Numeric->Lilen ;
Lip = Numeric->Lip ;
kstart = npiv ;
n1 = Numeric->n1 ;
#ifndef NDEBUG
DEBUG4 (("Ltsolve start:\n")) ;
for (j = 0 ; j < Numeric->n_row ; j++)
{
DEBUG4 (("Ltsolve start "ID": ", j)) ;
EDEBUG4 (X [j]) ;
DEBUG4 (("\n")) ;
}
#endif
/* ---------------------------------------------------------------------- */
/* non-singletons */
/* ---------------------------------------------------------------------- */
for (kend = npiv-1 ; kend >= n1 ; kend = kstart-1)
{
/* ------------------------------------------------------------------ */
/* find the start of this Lchain */
/* ------------------------------------------------------------------ */
/* for (kstart = kend ; kstart >= 0 && Lip [kstart] > 0 ; kstart--) ; */
kstart = kend ;
while (kstart >= 0 && Lip [kstart] > 0)
{
kstart-- ;
}
/* the Lchain goes from kstart to kend */
/* ------------------------------------------------------------------ */
/* scan the whole chain to find the pattern of the last column of L */
/* ------------------------------------------------------------------ */
deg = 0 ;
DEBUG4 (("start of chain for column of L\n")) ;
for (k = kstart ; k <= kend ; k++)
{
ASSERT (k >= 0 && k < npiv) ;
/* -------------------------------------------------------------- */
/* make column k of L in Pattern [0..deg-1] */
/* -------------------------------------------------------------- */
/* remove pivot row */
pos = Lpos [k] ;
if (pos != EMPTY)
{
DEBUG4 ((" k "ID" removing row "ID" at position "ID"\n",
k, Pattern [pos], pos)) ;
ASSERT (k != kstart) ;
ASSERT (deg > 0) ;
ASSERT (pos >= 0 && pos < deg) ;
ASSERT (Pattern [pos] == k) ;
Pattern [pos] = Pattern [--deg] ;
}
/* concatenate the pattern */
lp = Lip [k] ;
if (k == kstart)
{
lp = -lp ;
}
ASSERT (lp > 0) ;
ip = (Int *) (Numeric->Memory + lp) ;
llen = Lilen [k] ;
for (j = 0 ; j < llen ; j++)
{
row = *ip++ ;
DEBUG4 ((" row "ID" k "ID"\n", row, k)) ;
ASSERT (row > k) ;
Pattern [deg++] = row ;
}
}
/* Pattern [0..deg-1] is now the pattern of column kend */
/* ------------------------------------------------------------------ */
/* solve using this chain, in reverse order */
/* ------------------------------------------------------------------ */
DEBUG4 (("Unwinding Lchain\n")) ;
for (k = kend ; k >= kstart ; k--)
{
/* -------------------------------------------------------------- */
/* use column k of L */
/* -------------------------------------------------------------- */
ASSERT (k >= 0 && k < npiv) ;
lp = Lip [k] ;
if (k == kstart)
{
lp = -lp ;
}
ASSERT (lp > 0) ;
llen = Lilen [k] ;
xp = (Entry *) (Numeric->Memory + lp + UNITS (Int, llen)) ;
xk = X [k] ;
for (j = 0 ; j < deg ; j++)
{
DEBUG4 ((" row "ID" k "ID" value", Pattern [j], k)) ;
EDEBUG4 (*xp) ;
DEBUG4 (("\n")) ;
#ifdef CONJUGATE_SOLVE
/* xk -= X [Pattern [j]] * conjugate (*xp) ; */
MULT_SUB_CONJ (xk, X [Pattern [j]], *xp) ;
#else
/* xk -= X [Pattern [j]] * (*xp) ; */
MULT_SUB (xk, X [Pattern [j]], *xp) ;
#endif
xp++ ;
}
X [k] = xk ;
/* -------------------------------------------------------------- */
/* construct column k-1 of L */
/* -------------------------------------------------------------- */
/* un-concatenate the pattern */
deg -= llen ;
/* add pivot row */
pos = Lpos [k] ;
if (pos != EMPTY)
{
DEBUG4 ((" k "ID" adding row "ID" at position "ID"\n",
k, k, pos)) ;
ASSERT (k != kstart) ;
ASSERT (pos >= 0 && pos <= deg) ;
Pattern [deg++] = Pattern [pos] ;
Pattern [pos] = k ;
}
}
}
/* ---------------------------------------------------------------------- */
/* singletons */
/* ---------------------------------------------------------------------- */
for (k = n1 - 1 ; k >= 0 ; k--)
{
DEBUG4 (("Singleton k "ID"\n", k)) ;
deg = Lilen [k] ;
if (deg > 0)
{
xk = X [k] ;
lp = Lip [k] ;
Li = (Int *) (Numeric->Memory + lp) ;
lp += UNITS (Int, deg) ;
Lval = (Entry *) (Numeric->Memory + lp) ;
for (j = 0 ; j < deg ; j++)
{
DEBUG4 ((" row "ID" k "ID" value", Li [j], k)) ;
EDEBUG4 (Lval [j]) ;
DEBUG4 (("\n")) ;
#ifdef CONJUGATE_SOLVE
/* xk -= X [Li [j]] * conjugate (Lval [j]) ; */
MULT_SUB_CONJ (xk, X [Li [j]], Lval [j]) ;
#else
/* xk -= X [Li [j]] * Lval [j] ; */
MULT_SUB (xk, X [Li [j]], Lval [j]) ;
#endif
}
X [k] = xk ;
}
}
#ifndef NDEBUG
for (j = 0 ; j < Numeric->n_row ; j++)
{
DEBUG4 (("Ltsolve done "ID": ", j)) ;
EDEBUG4 (X [j]) ;
DEBUG4 (("\n")) ;
}
DEBUG4 (("Ltsolve done.\n")) ;
#endif
return (MULTSUB_FLOPS * ((double) Numeric->lnz)) ;
}

View File

@ -0,0 +1,19 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
GLOBAL double UMF_ltsolve
(
NumericType *Numeric,
Entry X [ ],
Int Pattern [ ]
) ;
GLOBAL double UMF_lhsolve
(
NumericType *Numeric,
Entry X [ ],
Int Pattern [ ]
) ;

View File

@ -0,0 +1,92 @@
/* ========================================================================== */
/* === UMF_malloc =========================================================== */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/*
Allocate a block of n objects, each of a given size. This routine does not
handle the case when the size is 1 (allocating char's) because of potential
integer overflow. UMFPACK never does that.
Also maintains the UMFPACK malloc count.
*/
#include "umf_internal.h"
#include "umf_malloc.h"
#if defined (UMF_MALLOC_COUNT) || !defined (NDEBUG)
/*
UMF_malloc_count is a count of the objects malloc'd by UMFPACK. If you
suspect a memory leak in your program (caused by not properly destroying
the Symbolic and Numeric objects) then compile with -DUMF_MALLOC_COUNT and
check value of UMF_malloc_count. By default, UMF_MALLOC_COUNT is not
defined, and thus UMFPACK has no global variables.
*/
GLOBAL Int UMF_malloc_count = 0 ;
#endif
#ifdef UMF_TCOV_TEST
/* For exhaustive statement coverage testing only! */
GLOBAL int umf_fail, umf_fail_lo, umf_fail_hi ;
GLOBAL int umf_realloc_fail, umf_realloc_lo, umf_realloc_hi ;
#endif
GLOBAL void *UMF_malloc
(
Int n_objects,
size_t size_of_object
)
{
size_t size ;
void *p ;
#ifdef UMF_TCOV_TEST
/* For exhaustive statement coverage testing only! */
/* Pretend to fail, to test out-of-memory conditions. */
umf_fail-- ;
if (umf_fail <= umf_fail_hi && umf_fail >= umf_fail_lo)
{
DEBUG0 (("umf_malloc: Pretend to fail %d %d %d\n",
umf_fail, umf_fail_hi, umf_fail_lo)) ;
return ((void *) NULL) ;
}
#endif
DEBUG0 (("UMF_malloc: ")) ;
/* make sure that we allocate something */
n_objects = MAX (1, n_objects) ;
size = (size_t) n_objects ;
ASSERT (size_of_object > 1) ;
if (size > Int_MAX / size_of_object)
{
/* object is too big for integer pointer arithmetic */
return ((void *) NULL) ;
}
size *= size_of_object ;
/* see AMD/Source/amd_global.c for the memory allocator selection */
p = amd_malloc (size) ;
DEBUG0 ((ID"\n", (Int) p)) ;
#if defined (UMF_MALLOC_COUNT) || !defined (NDEBUG)
if (p)
{
/* One more object has been malloc'ed. Keep track of the count. */
/* (purely for sanity checks). */
UMF_malloc_count++ ;
DEBUG0 ((" successful, new malloc count: "ID"\n", UMF_malloc_count)) ;
}
#endif
return (p) ;
}

View File

@ -0,0 +1,25 @@
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
#ifndef _UMF_MALLOC
#define _UMF_MALLOC
#if defined (UMF_MALLOC_COUNT) || !defined (NDEBUG)
#ifndef EXTERN
#define EXTERN extern
#endif
GLOBAL EXTERN Int UMF_malloc_count ;
#endif
GLOBAL void *UMF_malloc
(
Int n_objects,
size_t size_of_object
) ;
#endif

View File

@ -0,0 +1,83 @@
/* ========================================================================== */
/* === UMF_mem_alloc_element ================================================ */
/* ========================================================================== */
/* -------------------------------------------------------------------------- */
/* UMFPACK Copyright (c) Timothy A. Davis, CISE, */
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
/* -------------------------------------------------------------------------- */
/* The UMF_mem_* routines manage the Numeric->Memory memory space. */
/* Allocate a nrows-by-ncols element, and initialize it. */
/* Returns the index into Numeric->Memory if successful, or 0 on failure. */
#include "umf_internal.h"
#include "umf_mem_alloc_element.h"
#include "umf_mem_alloc_tail_block.h"
GLOBAL Int UMF_mem_alloc_element
(
NumericType *Numeric,
Int nrows,
Int ncols,
Int **Rows,
Int **Cols,
Entry **C,
Int *size,
Element **epout
)
{
Element *ep ;
Unit *p ;
Int i ;
ASSERT (Numeric != (NumericType *) NULL) ;
ASSERT (Numeric->Memory != (Unit *) NULL) ;
*size = GET_ELEMENT_SIZE (nrows, ncols) ;
if (INT_OVERFLOW (DGET_ELEMENT_SIZE (nrows, ncols) + 1))
{
/* :: allocate element, int overflow :: */
return (0) ; /* problem is too large */
}
i = UMF_mem_alloc_tail_block (Numeric, *size) ;
(*size)++ ;
if (!i)
{
DEBUG0 (("alloc element failed - out of memory\n")) ;
return (0) ; /* out of memory */
}
p = Numeric->Memory + i ;
ep = (Element *) p ;
DEBUG2 (("alloc_element done ("ID" x "ID"): p: "ID" i "ID"\n",
nrows, ncols, (Int) (p-Numeric->Memory), i)) ;
/* Element data structure, in order: */
p += UNITS (Element, 1) ; /* (1) Element header */
*Cols = (Int *) p ; /* (2) col [0..ncols-1] indices */
*Rows = *Cols + ncols ; /* (3) row [0..nrows-1] indices */
p += UNITS (Int, ncols + nrows) ;
*C = (Entry *) p ; /* (4) C [0..nrows-1, 0..ncols-1] */
ep->nrows = nrows ; /* initialize the header information */
ep->ncols = ncols ;
ep->nrowsleft = nrows ;
ep->ncolsleft = ncols ;
ep->cdeg = 0 ;
ep->rdeg = 0 ;
ep->next = EMPTY ;
DEBUG2 (("new block size: "ID" ", GET_BLOCK_SIZE (Numeric->Memory + i))) ;
DEBUG2 (("Element size needed "ID"\n", GET_ELEMENT_SIZE (nrows, ncols))) ;
*epout = ep ;
/* return the offset into Numeric->Memory */
return (i) ;
}

Some files were not shown because too many files have changed in this diff Show More