Added UMFPACK as new experimental linear solver, (#1 new files)
This commit is contained in:
parent
7f546a2877
commit
3560c8ee16
|
|
@ -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 */
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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).
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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.
|
||||
|
||||
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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 *) ;
|
||||
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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.
|
||||
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -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
|
||||
|
|
@ -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) ;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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) ;
|
||||
}
|
||||
|
|
@ -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))) ;
|
||||
}
|
||||
|
|
@ -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 ;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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)) ;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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 */
|
||||
}
|
||||
|
|
@ -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) ;
|
||||
}
|
||||
|
|
@ -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
|
||||
) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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) ;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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) ;
|
||||
}
|
||||
|
|
@ -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
|
||||
) ;
|
||||
|
|
@ -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] ;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
||||
) ;
|
||||
|
|
@ -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)) ;
|
||||
}
|
||||
|
|
@ -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
|
||||
) ;
|
||||
|
|
@ -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) ;
|
||||
}
|
||||
|
|
@ -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
|
||||
) ;
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
|
@ -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) ;
|
||||
}
|
||||
|
|
@ -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
|
||||
) ;
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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 */
|
||||
|
|
@ -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) ;
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
) ;
|
||||
|
|
@ -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) ;
|
||||
}
|
||||
|
|
@ -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
|
||||
) ;
|
||||
|
|
@ -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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 [ ]
|
||||
) ;
|
||||
|
|
@ -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")) ;
|
||||
}
|
||||
|
|
@ -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
|
||||
) ;
|
||||
|
|
@ -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)) ;
|
||||
}
|
||||
|
|
@ -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
|
||||
) ;
|
||||
|
|
@ -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) ;
|
||||
}
|
||||
|
|
@ -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
|
||||
) ;
|
||||
|
|
@ -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) ;
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
) ;
|
||||
|
|
@ -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
|
||||
|
|
@ -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) ;
|
||||
}
|
||||
|
|
@ -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
|
||||
) ;
|
||||
|
|
@ -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) ;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
||||
) ;
|
||||
|
|
@ -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). */
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
||||
) ;
|
||||
|
|
@ -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)) ;
|
||||
}
|
||||
|
|
@ -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 [ ]
|
||||
) ;
|
||||
|
|
@ -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)) ;
|
||||
}
|
||||
|
|
@ -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 [ ]
|
||||
) ;
|
||||
|
|
@ -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) ;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
Loading…
Reference in New Issue