init sparse v1.4b
This commit is contained in:
parent
10e86d72d3
commit
9f95c79537
|
|
@ -1,9 +1,6 @@
|
|||
/*
|
||||
* EXPORTS for sparse matrix routines with SPICE3.
|
||||
*
|
||||
* Author: Advising professor:
|
||||
* Kenneth S. Kundert Alberto Sangiovanni-Vincentelli
|
||||
* UC Berkeley
|
||||
/* EXPORTS for sparse matrix routines. */
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* This file contains definitions that are useful to the calling
|
||||
* program. In particular, this file contains error keyword
|
||||
|
|
@ -13,25 +10,21 @@
|
|||
* Also included is the type definitions for the various functions
|
||||
* available to the user.
|
||||
*
|
||||
* This file is a modified version of spMatrix.h that is used when
|
||||
* interfacing to Spice3.
|
||||
* Objects that begin with the \a spc prefix are considered private
|
||||
* and should not be used.
|
||||
*
|
||||
* \author
|
||||
* Kenneth S. Kundert <kundert@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Revision and copyright information.
|
||||
*
|
||||
* Copyright (c) 1985,86,87,88,89,90
|
||||
* by Kenneth S. Kundert and the University of California.
|
||||
* Copyright (c) 1985-2003 by Kenneth S. Kundert
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the copyright notices appear in all copies and
|
||||
* supporting documentation and that the authors and the University of
|
||||
* California are properly credited. The authors and the University of
|
||||
* California make no representations as to the suitability of this
|
||||
* software for any purpose. It is provided `as is', without express
|
||||
* or implied warranty.
|
||||
* $Date: 2003/06/29 04:19:52 $
|
||||
* $Revision: 1.2 $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -39,6 +32,17 @@
|
|||
|
||||
#ifndef spOKAY
|
||||
|
||||
/*
|
||||
* IMPORTS
|
||||
*
|
||||
* >>> Import descriptions:
|
||||
* spConfig.h
|
||||
* Macros that customize the sparse matrix routines.
|
||||
*/
|
||||
|
||||
#include "../../maths/sparse/spConfig.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -50,47 +54,54 @@
|
|||
* changed under the condition that the codes for the nonfatal errors are
|
||||
* less than the code for spFATAL and similarly the codes for the fatal
|
||||
* errors are greater than that for spFATAL.
|
||||
*
|
||||
* >>> Error descriptions:
|
||||
* spOKAY
|
||||
* No error has occurred.
|
||||
* spSMALL_PIVOT
|
||||
* When reordering the matrix, no element was found which satisfies the
|
||||
* threshold criteria. The largest element in the matrix was chosen
|
||||
* as pivot. Non-fatal.
|
||||
* spZERO_DIAG
|
||||
* Fatal error. A zero was encountered on the diagonal the matrix. This
|
||||
* does not necessarily imply that the matrix is singular. When this
|
||||
* error occurs, the matrix should be reconstructed and factored using
|
||||
* spOrderAndFactor().
|
||||
* spSINGULAR
|
||||
* Fatal error. Matrix is singular, so no unique solution exists.
|
||||
* spNO_MEMORY
|
||||
* Fatal error. Indicates that not enough memory is available to handle
|
||||
* the matrix.
|
||||
* spPANIC
|
||||
* Fatal error indicating that the routines are not prepared to
|
||||
* handle the matrix that has been requested. This may occur when
|
||||
* the matrix is specified to be real and the routines are not
|
||||
* compiled for real matrices, or when the matrix is specified to
|
||||
* be complex and the routines are not compiled to handle complex
|
||||
* matrices.
|
||||
* spFATAL
|
||||
* Not an error flag, but rather the dividing line between fatal errors
|
||||
* and warnings.
|
||||
*/
|
||||
|
||||
#include "ngspice/sperror.h" /* Spice error definitions. */
|
||||
|
||||
/* Begin error macros. */
|
||||
#define spOKAY OK
|
||||
#define spSMALL_PIVOT OK
|
||||
#define spZERO_DIAG E_SINGULAR
|
||||
#define spSINGULAR E_SINGULAR
|
||||
#define spNO_MEMORY E_NOMEM
|
||||
#define spPANIC E_BADMATRIX
|
||||
|
||||
#define spFATAL E_BADMATRIX
|
||||
#define spOKAY 0 /*!<
|
||||
* Error code that indicates that no error has
|
||||
* occurred.
|
||||
*/
|
||||
#define spSMALL_PIVOT 1 /*!<
|
||||
* Non-fatal error code that indicates that, when
|
||||
* reordering the matrix, no element was found that
|
||||
* satisfies the absolute threshold criteria. The
|
||||
* largest element in the matrix was chosen as pivot.
|
||||
*/
|
||||
#define spZERO_DIAG 2 /*!<
|
||||
* Fatal error code that indicates that, a zero was
|
||||
* encountered on the diagonal the matrix. This does
|
||||
* not necessarily imply that the matrix is singular.
|
||||
* When this error occurs, the matrix should be
|
||||
* reconstructed and factored using
|
||||
* spOrderAndFactor().
|
||||
*/
|
||||
#define spSINGULAR 3 /*!<
|
||||
* Fatal error code that indicates that, matrix is
|
||||
* singular, so no unique solution exists.
|
||||
*/
|
||||
#define spMANGLED 4 /*!<
|
||||
* Fatal error code that indicates that, matrix has
|
||||
* been mangled, results of requested operation are
|
||||
* garbage.
|
||||
*/
|
||||
#define spNO_MEMORY 5 /*!<
|
||||
* Fatal error code that indicates that not enough
|
||||
* memory is available.
|
||||
*/
|
||||
#define spPANIC 6 /*!<
|
||||
* Fatal error code that indicates that the routines
|
||||
* are not prepared to handle the matrix that has
|
||||
* been requested. This may occur when the matrix
|
||||
* is specified to be real and the routines are not
|
||||
* compiled for real matrices, or when the matrix is
|
||||
* specified to be complex and the routines are not
|
||||
* compiled to handle complex matrices.
|
||||
*/
|
||||
#define spFATAL 2 /*!<
|
||||
* Error code that is not an error flag, but rather
|
||||
* the dividing line between fatal errors and
|
||||
* warnings.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
|
@ -99,21 +110,18 @@
|
|||
|
||||
/*
|
||||
* KEYWORD DEFINITIONS
|
||||
*
|
||||
* Here we define what precision arithmetic Sparse will use. Double
|
||||
* precision is suggested as being most appropriate for circuit
|
||||
* simulation and for C. However, it is possible to change spREAL
|
||||
* to a float for single precision arithmetic. Note that in C, single
|
||||
* precision arithmetic is often slower than double precision. Sparse
|
||||
* internally refers to spREALs as RealNumbers.
|
||||
*
|
||||
* Some C compilers, notably the old VMS compiler, do not handle the keyword
|
||||
* "void" correctly. If this is true for your compiler, remove the
|
||||
* comment delimiters from the redefinition of void to int below.
|
||||
*/
|
||||
|
||||
#define spREAL double
|
||||
/* #define void int */
|
||||
#define spREAL double /*!<
|
||||
* Defines the precision of the arithmetic used by
|
||||
* \a Sparse will use. Double precision is suggested
|
||||
* as being most appropriate for circuit simulation
|
||||
* and for C. However, it is possible to change spREAL
|
||||
* to a float for single precision arithmetic. Note
|
||||
* that in C, single precision arithmetic is often
|
||||
* slower than double precision. Sparse
|
||||
* internally refers to spREALs as RealNumbers.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
|
@ -140,10 +148,32 @@
|
|||
|
||||
/* Begin partition keywords. */
|
||||
|
||||
#define spDEFAULT_PARTITION 0
|
||||
#define spDIRECT_PARTITION 1
|
||||
#define spINDIRECT_PARTITION 2
|
||||
#define spAUTO_PARTITION 3
|
||||
#define spDEFAULT_PARTITION 0 /*!<
|
||||
* Partition code for spPartition().
|
||||
* Indicates that the default partitioning
|
||||
* mode should be used.
|
||||
* \see spPartition()
|
||||
*/
|
||||
#define spDIRECT_PARTITION 1 /*!<
|
||||
* Partition code for spPartition().
|
||||
* Indicates that all rows should be placed
|
||||
* in the direct addressing partition.
|
||||
* \see spPartition()
|
||||
*/
|
||||
#define spINDIRECT_PARTITION 2 /*!<
|
||||
* Partition code for spPartition().
|
||||
* Indicates that all rows should be placed
|
||||
* in the indirect addressing partition.
|
||||
* \see spPartition()
|
||||
*/
|
||||
#define spAUTO_PARTITION 3 /*!<
|
||||
* Partition code for spPartition().
|
||||
* Indicates that \a Sparse should chose
|
||||
* the best partition for each row based
|
||||
* on some simple rules. This is generally
|
||||
* preferred.
|
||||
* \see spPartition()
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
|
@ -151,38 +181,33 @@
|
|||
|
||||
/*
|
||||
* MACRO FUNCTION DEFINITIONS
|
||||
*
|
||||
* >>> Macro descriptions:
|
||||
* spADD_REAL_ELEMENT
|
||||
* Macro function that adds data to a real element in the matrix by a
|
||||
* pointer.
|
||||
* spADD_IMAG_ELEMENT
|
||||
* Macro function that adds data to a imaginary element in the matrix by
|
||||
* a pointer.
|
||||
* spADD_COMPLEX_ELEMENT
|
||||
* Macro function that adds data to a complex element in the matrix by a
|
||||
* pointer.
|
||||
* spADD_REAL_QUAD
|
||||
* Macro function that adds data to each of the four real matrix elements
|
||||
* specified by the given template.
|
||||
* spADD_IMAG_QUAD
|
||||
* Macro function that adds data to each of the four imaginary matrix
|
||||
* elements specified by the given template.
|
||||
* spADD_COMPLEX_QUAD
|
||||
* Macro function that adds data to each of the four complex matrix
|
||||
* elements specified by the given template.
|
||||
*/
|
||||
|
||||
/* Begin Macros. */
|
||||
/*!
|
||||
* Macro function that adds data to a real element in the matrix by a pointer.
|
||||
*/
|
||||
#define spADD_REAL_ELEMENT(element,real) *(element) += real
|
||||
|
||||
/*!
|
||||
* Macro function that adds data to a imaginary element in the matrix by
|
||||
* a pointer.
|
||||
*/
|
||||
#define spADD_IMAG_ELEMENT(element,imag) *(element+1) += imag
|
||||
|
||||
/*!
|
||||
* Macro function that adds data to a complex element in the matrix by
|
||||
* a pointer.
|
||||
*/
|
||||
#define spADD_COMPLEX_ELEMENT(element,real,imag) \
|
||||
{ *(element) += real; \
|
||||
*(element+1) += imag; \
|
||||
}
|
||||
|
||||
/*!
|
||||
* Macro function that adds data to each of the four real matrix elements
|
||||
* specified by the given template.
|
||||
*/
|
||||
#define spADD_REAL_QUAD(template,real) \
|
||||
{ *((template).Element1) += real; \
|
||||
*((template).Element2) += real; \
|
||||
|
|
@ -190,6 +215,10 @@
|
|||
*((template).Element4Negated) -= real; \
|
||||
}
|
||||
|
||||
/*!
|
||||
* Macro function that adds data to each of the four imaginary matrix
|
||||
* elements specified by the given template.
|
||||
*/
|
||||
#define spADD_IMAG_QUAD(template,imag) \
|
||||
{ *((template).Element1+1) += imag; \
|
||||
*((template).Element2+1) += imag; \
|
||||
|
|
@ -197,6 +226,10 @@
|
|||
*((template).Element4Negated+1) -= imag; \
|
||||
}
|
||||
|
||||
/*!
|
||||
* Macro function that adds data to each of the four complex matrix
|
||||
* elements specified by the given template.
|
||||
*/
|
||||
#define spADD_COMPLEX_QUAD(template,real,imag) \
|
||||
{ *((template).Element1) += real; \
|
||||
*((template).Element2) += real; \
|
||||
|
|
@ -212,33 +245,50 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* TYPE DEFINITION FOR COMPONENT TEMPLATE
|
||||
* TYPE DEFINITION FOR EXTERNAL MATRIX ELEMENT REFERENCES
|
||||
*
|
||||
* External type definitions for Sparse data objects.
|
||||
*/
|
||||
|
||||
/*! Declares the type of the a pointer to a matrix. */
|
||||
typedef spGenericPtr spMatrix;
|
||||
|
||||
/*! Declares the type of the a pointer to a matrix element. */
|
||||
typedef spREAL spElement;
|
||||
|
||||
/*! Declares the type of the Sparse error codes. */
|
||||
typedef int spError;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* TYPE DEFINITION FOR COMPONENT TEMPLATE */
|
||||
/*!
|
||||
* This data structure is used to hold pointers to four related elements in
|
||||
* matrix. It is used in conjunction with the routines
|
||||
* spGetAdmittance
|
||||
* spGetQuad
|
||||
* spGetOnes
|
||||
* These routines stuff the structure which is later used by the spADD_QUAD
|
||||
* macro functions above. It is also possible for the user to collect four
|
||||
* pointers returned by spGetElement and stuff them into the template.
|
||||
* The spADD_QUAD routines stuff data into the matrix in locations specified
|
||||
* by Element1 and Element2 without changing the data. The data is negated
|
||||
* before being placed in Element3 and Element4.
|
||||
* matrix. It is used in conjunction with the routines spGetAdmittance(),
|
||||
* spGetQuad(), and spGetOnes(). These routines stuff the structure which
|
||||
* is later used by the \a spADD_QUAD macro functions above. It is also
|
||||
* possible for the user to collect four pointers returned by spGetElement()
|
||||
* and stuff them into the template. The \a spADD_QUAD routines stuff data
|
||||
* into the matrix in locations specified by \a Element1 and \a Element2
|
||||
* without changing the data. The data is negated before being placed in
|
||||
* \a Element3 and \a Element4.
|
||||
*/
|
||||
|
||||
/* Begin `spTemplate'. */
|
||||
struct spTemplate
|
||||
{ spREAL *Element1 ;
|
||||
spREAL *Element2 ;
|
||||
spREAL *Element3Negated;
|
||||
spREAL *Element4Negated;
|
||||
{ spElement *Element1;
|
||||
spElement *Element2;
|
||||
spElement *Element3Negated;
|
||||
spElement *Element4Negated;
|
||||
};
|
||||
|
||||
|
||||
typedef struct MatrixFrame *MatrixPtr;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -249,49 +299,78 @@ typedef struct MatrixFrame *MatrixPtr;
|
|||
|
||||
/* Begin function declarations. */
|
||||
|
||||
extern void spClear( MatrixPtr );
|
||||
extern spREAL spCondition( MatrixPtr, spREAL, int* );
|
||||
extern MatrixPtr spCreate( int, int, int* );
|
||||
extern void spDeleteRowAndCol( MatrixPtr, int, int );
|
||||
extern void spDestroy( MatrixPtr);
|
||||
extern int spElementCount( MatrixPtr );
|
||||
extern int spError( MatrixPtr );
|
||||
extern int spFactor( MatrixPtr );
|
||||
extern int spFileMatrix( MatrixPtr, char *, char *, int, int, int );
|
||||
extern int spFileStats( MatrixPtr, char *, char * );
|
||||
extern int spFillinCount( MatrixPtr );
|
||||
extern int spGetAdmittance( MatrixPtr, int, int, struct spTemplate* );
|
||||
extern spREAL *spFindElement(MatrixPtr Matrix, int Row, int Col );
|
||||
extern spREAL *spGetElement(MatrixPtr, int, int );
|
||||
extern void *spGetInitInfo( spREAL* );
|
||||
extern int spGetOnes( MatrixPtr, int, int, int, struct spTemplate* );
|
||||
extern int spGetQuad( MatrixPtr, int, int, int, int, struct spTemplate* );
|
||||
extern int spGetSize( MatrixPtr, int );
|
||||
extern int spInitialize(MatrixPtr, int (*pInit)(spREAL*, void *InitInfo, int, int Col));
|
||||
extern void spInstallInitInfo( spREAL*, void * );
|
||||
extern spREAL spLargestElement( MatrixPtr );
|
||||
extern void spMNA_Preorder( MatrixPtr );
|
||||
extern spREAL spNorm( MatrixPtr );
|
||||
extern int spOrderAndFactor(MatrixPtr, spREAL*, spREAL, spREAL, int );
|
||||
extern int spOriginalCount( MatrixPtr);
|
||||
extern void spPartition( MatrixPtr, int );
|
||||
extern void spPrint(MatrixPtr, int, int, int );
|
||||
extern spREAL spPseudoCondition( MatrixPtr );
|
||||
extern spREAL spRoundoff( MatrixPtr, spREAL );
|
||||
extern void spScale( MatrixPtr, spREAL*, spREAL* );
|
||||
extern void spSetComplex( MatrixPtr );
|
||||
extern void spSetReal( MatrixPtr );
|
||||
extern void spStripFills( MatrixPtr );
|
||||
extern void spWhereSingular(MatrixPtr, int*, int* );
|
||||
extern void spConstMult(MatrixPtr, double);
|
||||
spcEXTERN void spClear( spMatrix );
|
||||
spcEXTERN spREAL spCondition( spMatrix, spREAL, int* );
|
||||
spcEXTERN spMatrix spCreate( int, int, spError* );
|
||||
spcEXTERN void spDeleteRowAndCol( spMatrix, int, int );
|
||||
spcEXTERN void spDestroy( spMatrix );
|
||||
spcEXTERN int spElementCount( spMatrix );
|
||||
spcEXTERN int spOriginalCount( spMatrix );
|
||||
spcEXTERN spError spErrorState( spMatrix );
|
||||
#ifdef EOF
|
||||
spcEXTERN void spErrorMessage( spMatrix, FILE*, char* );
|
||||
#else
|
||||
# define spErrorMessage(a,b,c) spcFUNC_NEEDS_FILE(_spErrorMessage,stdio)
|
||||
#endif
|
||||
|
||||
|
||||
spcEXTERN spError spFactor( spMatrix );
|
||||
spcEXTERN int spFileMatrix( spMatrix, char*, char*, int, int, int );
|
||||
spcEXTERN int spFileStats( spMatrix, char*, char* );
|
||||
spcEXTERN int spFillinCount( spMatrix );
|
||||
spcEXTERN spElement *spFindElement( spMatrix, int, int );
|
||||
spcEXTERN spError spGetAdmittance( spMatrix, int, int,
|
||||
struct spTemplate* );
|
||||
spcEXTERN spElement *spGetElement( spMatrix, int, int );
|
||||
spcEXTERN spGenericPtr spGetInitInfo( spElement* );
|
||||
spcEXTERN spError spGetOnes( spMatrix, int, int, int,
|
||||
struct spTemplate* );
|
||||
spcEXTERN spError spGetQuad( spMatrix, int, int, int, int,
|
||||
struct spTemplate* );
|
||||
spcEXTERN int spGetSize( spMatrix, int );
|
||||
spcEXTERN int spInitialize( spMatrix, int (*pInit)(spElement *, spGenericPtr, int, int) );
|
||||
spcEXTERN void spInstallInitInfo( spElement*, spGenericPtr );
|
||||
spcEXTERN spREAL spLargestElement( spMatrix );
|
||||
spcEXTERN void spMNA_Preorder( spMatrix );
|
||||
spcEXTERN spREAL spNorm( spMatrix );
|
||||
spcEXTERN spError spOrderAndFactor( spMatrix, spREAL[], spREAL,
|
||||
spREAL, int );
|
||||
spcEXTERN void spPartition( spMatrix, int );
|
||||
spcEXTERN void spPrint( spMatrix, int, int, int );
|
||||
spcEXTERN spREAL spPseudoCondition( spMatrix );
|
||||
spcEXTERN spREAL spRoundoff( spMatrix, spREAL );
|
||||
spcEXTERN void spScale( spMatrix, spREAL[], spREAL[] );
|
||||
spcEXTERN void spSetComplex( spMatrix );
|
||||
spcEXTERN void spSetReal( spMatrix );
|
||||
spcEXTERN void spStripFills( spMatrix );
|
||||
spcEXTERN void spWhereSingular( spMatrix, int*, int* );
|
||||
|
||||
/* Functions with argument lists that are dependent on options. */
|
||||
|
||||
extern void spDeterminant ( MatrixPtr, int*, spREAL*, spREAL* );
|
||||
extern int spFileVector( MatrixPtr, char * , spREAL*, spREAL*);
|
||||
extern void spMultiply( MatrixPtr, spREAL*, spREAL*, spREAL*, spREAL* );
|
||||
extern void spMultTransposed(MatrixPtr,spREAL*,spREAL*,spREAL*,spREAL*);
|
||||
extern void spSolve( MatrixPtr, spREAL*, spREAL*, spREAL*, spREAL* );
|
||||
extern void spSolveTransposed(MatrixPtr,spREAL*,spREAL*,spREAL*,spREAL*);
|
||||
|
||||
#if spCOMPLEX
|
||||
spcEXTERN void spDeterminant( spMatrix, int*, spREAL*, spREAL* );
|
||||
#else /* NOT spCOMPLEX */
|
||||
spcEXTERN void spDeterminant( spMatrix, int*, spREAL* );
|
||||
#endif /* NOT spCOMPLEX */
|
||||
#if spCOMPLEX && spSEPARATED_COMPLEX_VECTORS
|
||||
spcEXTERN int spFileVector( spMatrix, char* ,
|
||||
spREAL[], spREAL[]);
|
||||
spcEXTERN void spMultiply( spMatrix, spREAL[], spREAL[],
|
||||
spREAL[], spREAL[] );
|
||||
spcEXTERN void spMultTransposed( spMatrix, spREAL[], spREAL[],
|
||||
spREAL[], spREAL[] );
|
||||
spcEXTERN void spSolve( spMatrix, spREAL[], spREAL[], spREAL[],
|
||||
spREAL[] );
|
||||
spcEXTERN void spSolveTransposed( spMatrix, spREAL[], spREAL[],
|
||||
spREAL[], spREAL[] );
|
||||
#else /* NOT (spCOMPLEX && spSEPARATED_COMPLEX_VECTORS) */
|
||||
spcEXTERN int spFileVector( spMatrix, char* , spREAL[] );
|
||||
spcEXTERN void spMultiply( spMatrix, spREAL[], spREAL[] );
|
||||
spcEXTERN void spMultTransposed( spMatrix,
|
||||
spREAL[], spREAL[] );
|
||||
spcEXTERN void spSolve( spMatrix, spREAL[], spREAL[] );
|
||||
spcEXTERN void spSolveTransposed( spMatrix,
|
||||
spREAL[], spREAL[] );
|
||||
#endif /* NOT (spCOMPLEX && spSEPARATED_COMPLEX_VECTORS) */
|
||||
#endif /* spOKAY */
|
||||
//spcEXTERN void spConstMult(spMatrix, double);
|
||||
|
|
|
|||
|
|
@ -3,16 +3,16 @@
|
|||
noinst_LTLIBRARIES = libsparse.la
|
||||
|
||||
libsparse_la_SOURCES = \
|
||||
spalloc.c \
|
||||
spbuild.c \
|
||||
spconfig.h \
|
||||
spdefs.h \
|
||||
spAllocate.c \
|
||||
spBuild.c \
|
||||
spConfig.h \
|
||||
spDefs.h \
|
||||
spextra.c \
|
||||
spfactor.c \
|
||||
spoutput.c \
|
||||
spsmp.c \
|
||||
spsolve.c \
|
||||
sputils.c
|
||||
spFactor.c \
|
||||
spOutput.c \
|
||||
spSMP.c \
|
||||
spSolve.c \
|
||||
spUtils.c
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,863 @@
|
|||
/*
|
||||
* MATRIX ALLOCATION MODULE
|
||||
*
|
||||
* Author: Advising professor:
|
||||
* Kenneth S. Kundert Alberto Sangiovanni-Vincentelli
|
||||
* UC Berkeley
|
||||
*/
|
||||
/*!\file
|
||||
* This file contains functions for allocating and freeing matrices, configuring them, and for
|
||||
* accessing global information about the matrix (size, error status, etc.).
|
||||
*
|
||||
* Objects that begin with the \a spc prefix are considered private
|
||||
* and should not be used.
|
||||
*
|
||||
* \author
|
||||
* Kenneth S. Kundert <kundert@users.sourceforge.net>
|
||||
*/
|
||||
/* >>> User accessible functions contained in this file:
|
||||
* spCreate
|
||||
* spDestroy
|
||||
* spErrorState
|
||||
* spWhereSingular
|
||||
* spGetSize
|
||||
* spSetReal
|
||||
* spSetComplex
|
||||
* spFillinCount
|
||||
* spElementCount
|
||||
*
|
||||
* >>> Other functions contained in this file:
|
||||
* spcGetElement
|
||||
* InitializeElementBlocks
|
||||
* spcGetFillin
|
||||
* RecordAllocation
|
||||
* AllocateBlockOfAllocationList
|
||||
* EnlargeMatrix
|
||||
* ExpandTranslationArrays
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Revision and copyright information.
|
||||
*
|
||||
* Copyright (c) 1985-2003 by Kenneth S. Kundert
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* IMPORTS
|
||||
*
|
||||
* >>> Import descriptions:
|
||||
* spConfig.h
|
||||
* Macros that customize the sparse matrix routines.
|
||||
* spMatrix.h
|
||||
* Macros and declarations to be imported by the user.
|
||||
* spDefs.h
|
||||
* Matrix type and macro definitions for the sparse matrix routines.
|
||||
*/
|
||||
|
||||
#define spINSIDE_SPARSE
|
||||
#include <stdio.h>
|
||||
#include "spConfig.h"
|
||||
#include "ngspice/spmatrix.h"
|
||||
#include "spDefs.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Global strings
|
||||
*/
|
||||
|
||||
char spcMatrixIsNotValid[] = "Matrix passed to Sparse is not valid";
|
||||
char spcErrorsMustBeCleared[] = "Error not cleared";
|
||||
char spcMatrixMustBeFactored[] = "Matrix must be factored";
|
||||
char spcMatrixMustNotBeFactored[] = "Matrix must not be factored";
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Function declarations
|
||||
*/
|
||||
|
||||
//static spError ReserveElements( MatrixPtr, int );
|
||||
static void InitializeElementBlocks( MatrixPtr, int, int );
|
||||
static void RecordAllocation( MatrixPtr, void* );
|
||||
static void AllocateBlockOfAllocationList( MatrixPtr );
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* Allocates and initializes the data structures associated with a matrix.
|
||||
*
|
||||
* \return
|
||||
* A pointer to the matrix is returned cast into \a spMatrix (typically a
|
||||
* pointer to a void). This pointer is then passed and used by the other
|
||||
* matrix routines to refer to a particular matrix. If an error occurs,
|
||||
* the \a NULL pointer is returned.
|
||||
*
|
||||
* \param Size
|
||||
* Size of matrix or estimate of size of matrix if matrix is \a EXPANDABLE.
|
||||
* \param Complex
|
||||
* Type of matrix. If \a Complex is 0 then the matrix is real, otherwise
|
||||
* the matrix will be complex. Note that if the routines are not set up
|
||||
* to handle the type of matrix requested, then an \a spPANIC error will occur.
|
||||
* Further note that if a matrix will be both real and complex, it must
|
||||
* be specified here as being complex.
|
||||
* \param pError
|
||||
* Returns error flag, needed because function \a spErrorState() will
|
||||
* not work correctly if \a spCreate() returns \a NULL. Possible errors
|
||||
* include \a spNO_MEMORY and \a spPANIC.
|
||||
*/
|
||||
/* >>> Local variables:
|
||||
* AllocatedSize (int)
|
||||
* The size of the matrix being allocated.
|
||||
* Matrix (MatrixPtr)
|
||||
* A pointer to the matrix frame being created.
|
||||
*/
|
||||
|
||||
spMatrix
|
||||
spCreate(
|
||||
int Size,
|
||||
int Complex,
|
||||
int *pError
|
||||
)
|
||||
{
|
||||
register unsigned SizePlusOne;
|
||||
register MatrixPtr Matrix;
|
||||
register int I;
|
||||
int AllocatedSize;
|
||||
|
||||
/* Begin `spCreate'. */
|
||||
/* Clear error flag. */
|
||||
*pError = spOKAY;
|
||||
|
||||
/* Test for valid size. */
|
||||
vASSERT( (Size >= 0) AND (Size != 0 OR EXPANDABLE), "Invalid size" );
|
||||
|
||||
/* Test for valid type. */
|
||||
#if NOT spCOMPLEX
|
||||
ASSERT( NOT Complex );
|
||||
#endif
|
||||
#if NOT REAL
|
||||
ASSERT( Complex );
|
||||
#endif
|
||||
|
||||
/* Create Matrix. */
|
||||
AllocatedSize = MAX( Size, MINIMUM_ALLOCATED_SIZE );
|
||||
SizePlusOne = (unsigned)(AllocatedSize + 1);
|
||||
|
||||
if ((Matrix = ALLOC(struct MatrixFrame, 1)) == NULL)
|
||||
{ *pError = spNO_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize matrix */
|
||||
Matrix->ID = SPARSE_ID;
|
||||
Matrix->Complex = Complex;
|
||||
Matrix->PreviousMatrixWasComplex = Complex;
|
||||
Matrix->Factored = NO;
|
||||
Matrix->Elements = 0;
|
||||
Matrix->Error = *pError;
|
||||
Matrix->Fillins = 0;
|
||||
Matrix->Reordered = NO;
|
||||
Matrix->NeedsOrdering = YES;
|
||||
Matrix->NumberOfInterchangesIsOdd = NO;
|
||||
Matrix->Partitioned = NO;
|
||||
Matrix->RowsLinked = NO;
|
||||
Matrix->InternalVectorsAllocated = NO;
|
||||
Matrix->SingularCol = 0;
|
||||
Matrix->SingularRow = 0;
|
||||
Matrix->Size = Size;
|
||||
Matrix->AllocatedSize = AllocatedSize;
|
||||
Matrix->ExtSize = Size;
|
||||
Matrix->AllocatedExtSize = AllocatedSize;
|
||||
Matrix->CurrentSize = 0;
|
||||
Matrix->ExtToIntColMap = NULL;
|
||||
Matrix->ExtToIntRowMap = NULL;
|
||||
Matrix->IntToExtColMap = NULL;
|
||||
Matrix->IntToExtRowMap = NULL;
|
||||
Matrix->MarkowitzRow = NULL;
|
||||
Matrix->MarkowitzCol = NULL;
|
||||
Matrix->MarkowitzProd = NULL;
|
||||
Matrix->DoCmplxDirect = NULL;
|
||||
Matrix->DoRealDirect = NULL;
|
||||
Matrix->Intermediate = NULL;
|
||||
Matrix->RelThreshold = DEFAULT_THRESHOLD;
|
||||
Matrix->AbsThreshold = 0.0;
|
||||
|
||||
Matrix->TopOfAllocationList = NULL;
|
||||
Matrix->RecordsRemaining = 0;
|
||||
Matrix->ElementsRemaining = 0;
|
||||
Matrix->FillinsRemaining = 0;
|
||||
|
||||
RecordAllocation( Matrix, (void *)Matrix );
|
||||
if (Matrix->Error == spNO_MEMORY) goto MemoryError;
|
||||
|
||||
/* Take out the trash. */
|
||||
Matrix->TrashCan.Real = 0.0;
|
||||
#if spCOMPLEX
|
||||
Matrix->TrashCan.Imag = 0.0;
|
||||
#endif
|
||||
Matrix->TrashCan.Row = 0;
|
||||
Matrix->TrashCan.Col = 0;
|
||||
Matrix->TrashCan.NextInRow = NULL;
|
||||
Matrix->TrashCan.NextInCol = NULL;
|
||||
#if INITIALIZE
|
||||
Matrix->TrashCan.pInitInfo = NULL;
|
||||
#endif
|
||||
|
||||
/* Allocate space in memory for Diag pointer vector. */
|
||||
CALLOC( Matrix->Diag, ElementPtr, SizePlusOne);
|
||||
if (Matrix->Diag == NULL)
|
||||
goto MemoryError;
|
||||
|
||||
/* Allocate space in memory for FirstInCol pointer vector. */
|
||||
CALLOC( Matrix->FirstInCol, ElementPtr, SizePlusOne);
|
||||
if (Matrix->FirstInCol == NULL)
|
||||
goto MemoryError;
|
||||
|
||||
/* Allocate space in memory for FirstInRow pointer vector. */
|
||||
CALLOC( Matrix->FirstInRow, ElementPtr, SizePlusOne);
|
||||
if (Matrix->FirstInRow == NULL)
|
||||
goto MemoryError;
|
||||
|
||||
/* Allocate space in memory for IntToExtColMap vector. */
|
||||
if (( Matrix->IntToExtColMap = ALLOC(int, SizePlusOne)) == NULL)
|
||||
goto MemoryError;
|
||||
|
||||
/* Allocate space in memory for IntToExtRowMap vector. */
|
||||
if (( Matrix->IntToExtRowMap = ALLOC(int, SizePlusOne)) == NULL)
|
||||
goto MemoryError;
|
||||
|
||||
/* Initialize MapIntToExt vectors. */
|
||||
for (I = 1; I <= AllocatedSize; I++)
|
||||
{ Matrix->IntToExtRowMap[I] = I;
|
||||
Matrix->IntToExtColMap[I] = I;
|
||||
}
|
||||
|
||||
#if TRANSLATE
|
||||
/* Allocate space in memory for ExtToIntColMap vector. */
|
||||
if (( Matrix->ExtToIntColMap = ALLOC(int, SizePlusOne)) == NULL)
|
||||
goto MemoryError;
|
||||
|
||||
/* Allocate space in memory for ExtToIntRowMap vector. */
|
||||
if (( Matrix->ExtToIntRowMap = ALLOC(int, SizePlusOne)) == NULL)
|
||||
goto MemoryError;
|
||||
|
||||
/* Initialize MapExtToInt vectors. */
|
||||
for (I = 1; I <= AllocatedSize; I++)
|
||||
{ Matrix->ExtToIntColMap[I] = -1;
|
||||
Matrix->ExtToIntRowMap[I] = -1;
|
||||
}
|
||||
Matrix->ExtToIntColMap[0] = 0;
|
||||
Matrix->ExtToIntRowMap[0] = 0;
|
||||
#endif
|
||||
|
||||
/* Allocate space for fill-ins and initial set of elements. */
|
||||
InitializeElementBlocks( Matrix, SPACE_FOR_ELEMENTS*AllocatedSize,
|
||||
SPACE_FOR_FILL_INS*AllocatedSize );
|
||||
if (Matrix->Error == spNO_MEMORY)
|
||||
goto MemoryError;
|
||||
|
||||
return (char *)Matrix;
|
||||
|
||||
MemoryError:
|
||||
|
||||
/* Deallocate matrix and return no pointer to matrix if there is not enough
|
||||
memory. */
|
||||
*pError = spNO_MEMORY;
|
||||
spDestroy( (char *)Matrix);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ELEMENT ALLOCATION
|
||||
*
|
||||
* This routine allocates space for matrix elements. It requests large blocks
|
||||
* of storage from the system and doles out individual elements as required.
|
||||
* This technique, as opposed to allocating elements individually, tends to
|
||||
* speed the allocation process.
|
||||
*
|
||||
* >>> Returned:
|
||||
* A pointer to an element.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (MatrixPtr)
|
||||
* Pointer to matrix.
|
||||
*
|
||||
* >>> Local variables:
|
||||
* pElement (ElementPtr)
|
||||
* A pointer to the first element in the group of elements being allocated.
|
||||
*
|
||||
* >>> Possible errors:
|
||||
* spNO_MEMORY
|
||||
*/
|
||||
|
||||
ElementPtr
|
||||
spcGetElement( MatrixPtr Matrix )
|
||||
{
|
||||
ElementPtr pElement;
|
||||
|
||||
/* Begin `spcGetElement'. */
|
||||
|
||||
/* Allocate block of MatrixElements if necessary. */
|
||||
if (Matrix->ElementsRemaining == 0)
|
||||
{ pElement = ALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION);
|
||||
RecordAllocation( Matrix, (void *)pElement );
|
||||
if (Matrix->Error == spNO_MEMORY) return NULL;
|
||||
Matrix->ElementsRemaining = ELEMENTS_PER_ALLOCATION;
|
||||
Matrix->NextAvailElement = pElement;
|
||||
}
|
||||
|
||||
/* Update Element counter and return pointer to Element. */
|
||||
Matrix->ElementsRemaining--;
|
||||
return Matrix->NextAvailElement++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ELEMENT ALLOCATION INITIALIZATION
|
||||
*
|
||||
* This routine allocates space for matrix fill-ins and an initial set of
|
||||
* elements. Besides being faster than allocating space for elements one
|
||||
* at a time, it tends to keep the fill-ins physically close to the other
|
||||
* matrix elements in the computer memory. This keeps virtual memory paging
|
||||
* to a minimum.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (MatrixPtr)
|
||||
* Pointer to the matrix.
|
||||
* InitialNumberOfElements <input> (int)
|
||||
* This number is used as the size of the block of memory, in
|
||||
* MatrixElements, reserved for elements. If more than this number of
|
||||
* elements are generated, then more space is allocated later.
|
||||
* NumberOfFillinsExpected <input> (int)
|
||||
* This number is used as the size of the block of memory, in
|
||||
* MatrixElements, reserved for fill-ins. If more than this number of
|
||||
* fill-ins are generated, then more space is allocated, but they may
|
||||
* not be physically close in computer's memory.
|
||||
*
|
||||
* >>> Local variables:
|
||||
* pElement (ElementPtr)
|
||||
* A pointer to the first element in the group of elements being allocated.
|
||||
*
|
||||
* >>> Possible errors:
|
||||
* spNO_MEMORY
|
||||
*/
|
||||
|
||||
static void
|
||||
InitializeElementBlocks(
|
||||
MatrixPtr Matrix,
|
||||
int InitialNumberOfElements,
|
||||
int NumberOfFillinsExpected
|
||||
)
|
||||
{
|
||||
ElementPtr pElement;
|
||||
|
||||
/* Begin `InitializeElementBlocks'. */
|
||||
|
||||
/* Allocate block of MatrixElements for elements. */
|
||||
pElement = ALLOC(struct MatrixElement, InitialNumberOfElements);
|
||||
RecordAllocation( Matrix, (void *)pElement );
|
||||
if (Matrix->Error == spNO_MEMORY) return;
|
||||
Matrix->ElementsRemaining = InitialNumberOfElements;
|
||||
Matrix->NextAvailElement = pElement;
|
||||
|
||||
/* Allocate block of MatrixElements for fill-ins. */
|
||||
pElement = ALLOC(struct MatrixElement, NumberOfFillinsExpected);
|
||||
RecordAllocation( Matrix, (void *)pElement );
|
||||
if (Matrix->Error == spNO_MEMORY) return;
|
||||
Matrix->FillinsRemaining = NumberOfFillinsExpected;
|
||||
Matrix->NextAvailFillin = pElement;
|
||||
|
||||
/* Allocate a fill-in list structure. */
|
||||
Matrix->FirstFillinListNode = ALLOC(struct FillinListNodeStruct,1);
|
||||
RecordAllocation( Matrix, (void *)Matrix->FirstFillinListNode );
|
||||
if (Matrix->Error == spNO_MEMORY) return;
|
||||
Matrix->LastFillinListNode = Matrix->FirstFillinListNode;
|
||||
|
||||
Matrix->FirstFillinListNode->pFillinList = pElement;
|
||||
Matrix->FirstFillinListNode->NumberOfFillinsInList =NumberOfFillinsExpected;
|
||||
Matrix->FirstFillinListNode->Next = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* FILL-IN ALLOCATION
|
||||
*
|
||||
* This routine allocates space for matrix fill-ins. It requests large blocks
|
||||
* of storage from the system and doles out individual elements as required.
|
||||
* This technique, as opposed to allocating elements individually, tends to
|
||||
* speed the allocation process.
|
||||
*
|
||||
* >>> Returned:
|
||||
* A pointer to the fill-in.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (MatrixPtr)
|
||||
* Pointer to matrix.
|
||||
*
|
||||
* >>> Possible errors:
|
||||
* spNO_MEMORY
|
||||
*/
|
||||
|
||||
ElementPtr
|
||||
spcGetFillin( MatrixPtr Matrix )
|
||||
{
|
||||
#if STRIP OR LINT
|
||||
struct FillinListNodeStruct *pListNode;
|
||||
ElementPtr pFillins;
|
||||
#endif
|
||||
|
||||
/* Begin `spcGetFillin'. */
|
||||
|
||||
#if NOT STRIP OR LINT
|
||||
if (Matrix->FillinsRemaining == 0)
|
||||
return spcGetElement( Matrix );
|
||||
#endif
|
||||
#if STRIP OR LINT
|
||||
|
||||
if (Matrix->FillinsRemaining == 0)
|
||||
{ pListNode = Matrix->LastFillinListNode;
|
||||
|
||||
/* First see if there are any stripped fill-ins left. */
|
||||
if (pListNode->Next != NULL)
|
||||
{ Matrix->LastFillinListNode = pListNode = pListNode->Next;
|
||||
Matrix->FillinsRemaining = pListNode->NumberOfFillinsInList;
|
||||
Matrix->NextAvailFillin = pListNode->pFillinList;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate block of fill-ins. */
|
||||
pFillins = ALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION);
|
||||
RecordAllocation( Matrix, (void *)pFillins );
|
||||
if (Matrix->Error == spNO_MEMORY) return NULL;
|
||||
Matrix->FillinsRemaining = ELEMENTS_PER_ALLOCATION;
|
||||
Matrix->NextAvailFillin = pFillins;
|
||||
|
||||
/* Allocate a fill-in list structure. */
|
||||
pListNode->Next = ALLOC(struct FillinListNodeStruct,1);
|
||||
RecordAllocation( Matrix, (void *)pListNode->Next );
|
||||
if (Matrix->Error == spNO_MEMORY) return NULL;
|
||||
Matrix->LastFillinListNode = pListNode = pListNode->Next;
|
||||
|
||||
pListNode->pFillinList = pFillins;
|
||||
pListNode->NumberOfFillinsInList = ELEMENTS_PER_ALLOCATION;
|
||||
pListNode->Next = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update Fill-in counter and return pointer to Fill-in. */
|
||||
Matrix->FillinsRemaining--;
|
||||
return Matrix->NextAvailFillin++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* RECORD A MEMORY ALLOCATION
|
||||
*
|
||||
* This routine is used to record all memory allocations so that the memory
|
||||
* can be freed later.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (MatrixPtr)
|
||||
* Pointer to the matrix.
|
||||
* AllocatedPtr <input> (void *)
|
||||
* The pointer returned by malloc or calloc. These pointers are saved in
|
||||
* a list so that they can be easily freed.
|
||||
*
|
||||
* >>> Possible errors:
|
||||
* spNO_MEMORY
|
||||
*/
|
||||
|
||||
static void
|
||||
RecordAllocation(
|
||||
MatrixPtr Matrix,
|
||||
void *AllocatedPtr
|
||||
)
|
||||
{
|
||||
/* Begin `RecordAllocation'. */
|
||||
/*
|
||||
* If Allocated pointer is NULL, assume that malloc returned a NULL pointer,
|
||||
* which indicates a spNO_MEMORY error.
|
||||
*/
|
||||
if (AllocatedPtr == NULL)
|
||||
{ Matrix->Error = spNO_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate block of MatrixElements if necessary. */
|
||||
if (Matrix->RecordsRemaining == 0)
|
||||
{ AllocateBlockOfAllocationList( Matrix );
|
||||
if (Matrix->Error == spNO_MEMORY)
|
||||
{ FREE(AllocatedPtr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add Allocated pointer to Allocation List. */
|
||||
(++Matrix->TopOfAllocationList)->AllocatedPtr = AllocatedPtr;
|
||||
Matrix->RecordsRemaining--;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ADD A BLOCK OF SLOTS TO ALLOCATION LIST
|
||||
*
|
||||
* This routine increases the size of the allocation list.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (MatrixPtr)
|
||||
* Pointer to the matrix.
|
||||
*
|
||||
* >>> Local variables:
|
||||
* ListPtr (AllocationListPtr)
|
||||
* Pointer to the list that contains the pointers to segments of memory
|
||||
* that were allocated by the operating system for the current matrix.
|
||||
*
|
||||
* >>> Possible errors:
|
||||
* spNO_MEMORY
|
||||
*/
|
||||
|
||||
static void
|
||||
AllocateBlockOfAllocationList( MatrixPtr Matrix )
|
||||
{
|
||||
register int I;
|
||||
register AllocationListPtr ListPtr;
|
||||
|
||||
/* Begin `AllocateBlockOfAllocationList'. */
|
||||
/* Allocate block of records for allocation list. */
|
||||
ListPtr = ALLOC(struct AllocationRecord, (ELEMENTS_PER_ALLOCATION+1));
|
||||
if (ListPtr == NULL)
|
||||
{ Matrix->Error = spNO_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
/* String entries of allocation list into singly linked list. List is linked
|
||||
such that any record points to the one before it. */
|
||||
|
||||
ListPtr->NextRecord = Matrix->TopOfAllocationList;
|
||||
Matrix->TopOfAllocationList = ListPtr;
|
||||
ListPtr += ELEMENTS_PER_ALLOCATION;
|
||||
for (I = ELEMENTS_PER_ALLOCATION; I > 0; I--)
|
||||
{ ListPtr->NextRecord = ListPtr - 1;
|
||||
ListPtr--;
|
||||
}
|
||||
|
||||
/* Record allocation of space for allocation list on allocation list. */
|
||||
Matrix->TopOfAllocationList->AllocatedPtr = (void *)ListPtr;
|
||||
Matrix->RecordsRemaining = ELEMENTS_PER_ALLOCATION;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* Destroys a matrix and frees all memory associated with it.
|
||||
*
|
||||
* \param eMatrix
|
||||
* Pointer to the matrix frame which is to be destroyed.
|
||||
*/
|
||||
/* >>> Local variables:
|
||||
* ListPtr (AllocationListPtr)
|
||||
* Pointer into the linked list of pointers to allocated data structures.
|
||||
* Points to pointer to structure to be freed.
|
||||
* NextListPtr (AllocationListPtr)
|
||||
* Pointer into the linked list of pointers to allocated data structures.
|
||||
* Points to the next pointer to structure to be freed. This is needed
|
||||
* because the data structure to be freed could include the current node
|
||||
* in the allocation list.
|
||||
*/
|
||||
|
||||
void
|
||||
spDestroy( spMatrix eMatrix )
|
||||
{
|
||||
MatrixPtr Matrix = (MatrixPtr)eMatrix;
|
||||
register AllocationListPtr ListPtr, NextListPtr;
|
||||
|
||||
/* Begin `spDestroy'. */
|
||||
ASSERT_IS_SPARSE( Matrix );
|
||||
|
||||
/* Deallocate the vectors that are located in the matrix frame. */
|
||||
FREE( Matrix->IntToExtColMap );
|
||||
FREE( Matrix->IntToExtRowMap );
|
||||
FREE( Matrix->ExtToIntColMap );
|
||||
FREE( Matrix->ExtToIntRowMap );
|
||||
FREE( Matrix->Diag );
|
||||
FREE( Matrix->FirstInRow );
|
||||
FREE( Matrix->FirstInCol );
|
||||
FREE( Matrix->MarkowitzRow );
|
||||
FREE( Matrix->MarkowitzCol );
|
||||
FREE( Matrix->MarkowitzProd );
|
||||
FREE( Matrix->DoCmplxDirect );
|
||||
FREE( Matrix->DoRealDirect );
|
||||
FREE( Matrix->Intermediate );
|
||||
|
||||
/* Sequentially step through the list of allocated pointers freeing pointers
|
||||
* along the way. */
|
||||
ListPtr = Matrix->TopOfAllocationList;
|
||||
while (ListPtr != NULL)
|
||||
{ NextListPtr = ListPtr->NextRecord;
|
||||
free( ListPtr->AllocatedPtr );
|
||||
ListPtr = NextListPtr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* This function returns the error status of the given matrix.
|
||||
*
|
||||
* \return
|
||||
* The error status of the given matrix.
|
||||
*
|
||||
* \param eMatrix
|
||||
* The pointer to the matrix for which the error status is desired.
|
||||
*/
|
||||
|
||||
int
|
||||
spErrorState( spMatrix eMatrix )
|
||||
{
|
||||
/* Begin `spErrorState'. */
|
||||
|
||||
if (eMatrix != NULL)
|
||||
{ ASSERT_IS_SPARSE( (MatrixPtr)eMatrix );
|
||||
return ((MatrixPtr)eMatrix)->Error;
|
||||
}
|
||||
else return spNO_MEMORY; /* This error may actually be spPANIC,
|
||||
* no way to tell. */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* This function returns the row and column number where the matrix was
|
||||
* detected as singular (if pivoting was allowed on the last factorization)
|
||||
* or where a zero was detected on the diagonal (if pivoting was not
|
||||
* allowed on the last factorization). Pivoting is performed only in
|
||||
* spOrderAndFactor().
|
||||
*
|
||||
* \param eMatrix
|
||||
* The matrix for which the error status is desired.
|
||||
* \param pRow
|
||||
* The row number.
|
||||
* \param pCol
|
||||
* The column number.
|
||||
*/
|
||||
|
||||
void
|
||||
spWhereSingular(
|
||||
spMatrix eMatrix,
|
||||
int *pRow,
|
||||
int *pCol
|
||||
)
|
||||
{
|
||||
MatrixPtr Matrix = (MatrixPtr)eMatrix;
|
||||
|
||||
/* Begin `spWhereSingular'. */
|
||||
ASSERT_IS_SPARSE( Matrix );
|
||||
|
||||
if (Matrix->Error == spSINGULAR OR Matrix->Error == spZERO_DIAG)
|
||||
{ *pRow = Matrix->SingularRow;
|
||||
*pCol = Matrix->SingularCol;
|
||||
}
|
||||
else *pRow = *pCol = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* Returns the size of the matrix. Either the internal or external size of
|
||||
* the matrix is returned.
|
||||
*
|
||||
* \param eMatrix
|
||||
* Pointer to matrix.
|
||||
* \param External
|
||||
* If \a External is set true, the external size , i.e., the value of the
|
||||
* largest external row or column number encountered is returned.
|
||||
* Otherwise the true size of the matrix is returned. These two sizes
|
||||
* may differ if the \a TRANSLATE option is set true.
|
||||
*/
|
||||
|
||||
int
|
||||
spGetSize(
|
||||
spMatrix eMatrix,
|
||||
int External
|
||||
)
|
||||
{
|
||||
MatrixPtr Matrix = (MatrixPtr)eMatrix;
|
||||
|
||||
/* Begin `spGetSize'. */
|
||||
ASSERT_IS_SPARSE( Matrix );
|
||||
|
||||
#if TRANSLATE
|
||||
if (External)
|
||||
return Matrix->ExtSize;
|
||||
else
|
||||
return Matrix->Size;
|
||||
#else
|
||||
return Matrix->Size;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* Forces matrix to be real.
|
||||
*
|
||||
* \param eMatrix
|
||||
* Pointer to matrix.
|
||||
*/
|
||||
|
||||
void
|
||||
spSetReal( spMatrix eMatrix )
|
||||
{
|
||||
/* Begin `spSetReal'. */
|
||||
|
||||
ASSERT_IS_SPARSE( (MatrixPtr)eMatrix );
|
||||
vASSERT( REAL, "Sparse not compiled to handle real matrices" );
|
||||
((MatrixPtr)eMatrix)->Complex = NO;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* Forces matrix to be complex.
|
||||
*
|
||||
* \param eMatrix
|
||||
* Pointer to matrix.
|
||||
*/
|
||||
|
||||
void
|
||||
spSetComplex( spMatrix eMatrix )
|
||||
{
|
||||
/* Begin `spSetComplex'. */
|
||||
|
||||
ASSERT_IS_SPARSE( (MatrixPtr)eMatrix );
|
||||
vASSERT( spCOMPLEX, "Sparse not compiled to handle complex matrices" );
|
||||
((MatrixPtr)eMatrix)->Complex = YES;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* This function returns the number of fill-ins that currently exists in a matrix.
|
||||
*
|
||||
* \param eMatrix
|
||||
* Pointer to matrix.
|
||||
*/
|
||||
|
||||
int
|
||||
spFillinCount( spMatrix eMatrix )
|
||||
{
|
||||
/* Begin `spFillinCount'. */
|
||||
|
||||
ASSERT_IS_SPARSE( (MatrixPtr)eMatrix );
|
||||
return ((MatrixPtr)eMatrix)->Fillins;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* This function returns the total number of elements (including fill-ins) that currently exists in a matrix.
|
||||
*
|
||||
* \param eMatrix
|
||||
* Pointer to matrix.
|
||||
*/
|
||||
|
||||
/* FIXME: Seems no different size entries available anymore */
|
||||
|
||||
int
|
||||
spElementCount( spMatrix eMatrix )
|
||||
{
|
||||
/* Begin `spElementCount'. */
|
||||
|
||||
ASSERT_IS_SPARSE( (MatrixPtr)eMatrix );
|
||||
return ((MatrixPtr)eMatrix)->Elements;
|
||||
}
|
||||
|
||||
int
|
||||
spOriginalCount( spMatrix eMatrix )
|
||||
{
|
||||
/* Begin `spOriginalCount'. */
|
||||
|
||||
ASSERT_IS_SPARSE( (MatrixPtr)eMatrix );
|
||||
return ((MatrixPtr)eMatrix)->Elements;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,572 @@
|
|||
/* CONFIGURATION MACRO DEFINITIONS for sparse matrix routines */
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* This file contains macros for the sparse matrix routines that are used
|
||||
* to define the personality of the routines. The user is expected to
|
||||
* modify this file to maximize the performance of the routines with
|
||||
* his/her matrices.
|
||||
*
|
||||
* Macros are distinguished by using solely capital letters in their
|
||||
* identifiers. This contrasts with C defined identifiers which are
|
||||
* strictly lower case, and program variable and procedure names which use
|
||||
* both upper and lower case.
|
||||
*
|
||||
* Objects that begin with the \a spc prefix are considered private
|
||||
* and should not be used.
|
||||
*
|
||||
* \author
|
||||
* Kenneth S. Kundert <kundert@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Revision and copyright information.
|
||||
*
|
||||
* Copyright (c) 1985-2003 by Kenneth S. Kundert
|
||||
*
|
||||
* $Date: 2003/06/30 19:41:29 $
|
||||
* $Revision: 1.5 $
|
||||
*/
|
||||
|
||||
|
||||
#ifndef spCONFIG_DEFS
|
||||
#define spCONFIG_DEFS
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef spINSIDE_SPARSE
|
||||
/*
|
||||
* OPTIONS
|
||||
*
|
||||
* These are compiler options. Set each option to one to compile that
|
||||
* section of the code. If a feature is not desired, set the macro
|
||||
* to NO.
|
||||
*/
|
||||
|
||||
/* Begin options. */
|
||||
|
||||
/* Arithmetic Precision
|
||||
*
|
||||
* The precision of the arithmetic used by Sparse can be set by
|
||||
* changing changing the spREAL macro. This macro is
|
||||
* contained in the file spMatrix.h. It is strongly suggested to
|
||||
* used double precision with circuit simulators. Note that
|
||||
* because C always performs arithmetic operations in double
|
||||
* precision, the only benefit to using single precision is that
|
||||
* less storage is required. There is often a noticeable speed
|
||||
* penalty when using single precision. Sparse internally refers
|
||||
* to a spREAL as a RealNumber.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* This specifies that the routines are expected to handle real
|
||||
* systems of equations. The routines can be compiled to handle
|
||||
* both real and complex systems at the same time, but there is a
|
||||
* slight speed and memory advantage if the routines are complied
|
||||
* to handle only real systems of equations.
|
||||
*/
|
||||
#define REAL YES
|
||||
|
||||
/*!
|
||||
* Setting this compiler flag true (1) makes the matrix
|
||||
* expandable before it has been factored. If the matrix is
|
||||
* expandable, then if an element is added that would be
|
||||
* considered out of bounds in the current matrix, the size of
|
||||
* the matrix is increased to hold that element. As a result,
|
||||
* the size of the matrix need not be known before the matrix is
|
||||
* built. The matrix can be allocated with size zero and expanded.
|
||||
*/
|
||||
#define EXPANDABLE YES
|
||||
|
||||
/*!
|
||||
* This option allows the set of external row and column numbers
|
||||
* to be non-packed. In other words, the row and column numbers
|
||||
* do not have to be contiguous. The priced paid for this
|
||||
* flexibility is that when \a TRANSLATE is set true, the time
|
||||
* required to initially build the matrix will be greater because
|
||||
* the external row and column number must be translated into
|
||||
* internal equivalents. This translation brings about other
|
||||
* benefits though. First, the spGetElement() and
|
||||
* spGetAdmittance() routines may be used after the matrix has
|
||||
* been factored. Further, elements, and even rows and columns,
|
||||
* may be added to the matrix, and row and columns may be deleted
|
||||
* from the matrix, after it has been factored. Note that when
|
||||
* the set of row and column number is not a packed set, neither
|
||||
* are the \a RHS and \a Solution vectors. Thus the size of these
|
||||
* vectors must be at least as large as the external size, which
|
||||
* is the value of the largest given row or column numbers.
|
||||
*/
|
||||
#define TRANSLATE YES
|
||||
|
||||
/*!
|
||||
* Causes the spInitialize(), spGetInitInfo(), and
|
||||
* spInstallInitInfo() routines to be compiled. These routines
|
||||
* allow the user to store and read one pointer in each nonzero
|
||||
* element in the matrix. spInitialize() then calls a user
|
||||
* specified function for each structural nonzero in the matrix,
|
||||
* and includes this pointer as well as the external row and
|
||||
* column numbers as arguments. This allows the user to write
|
||||
* custom matrix initialization routines.
|
||||
*/
|
||||
#define INITIALIZE NO
|
||||
|
||||
/*!
|
||||
* Many matrices, and in particular node- and modified-node
|
||||
* admittance matrices, tend to be nearly symmetric and nearly
|
||||
* diagonally dominant. For these matrices, it is a good idea to
|
||||
* select pivots from the diagonal. With this option enabled,
|
||||
* this is exactly what happens, though if no satisfactory pivot
|
||||
* can be found on the diagonal, an off-diagonal pivot will be
|
||||
* used. If this option is disabled, Sparse does not
|
||||
* preferentially search the diagonal. Because of this, Sparse
|
||||
* has a wider variety of pivot candidates available, and so
|
||||
* presumably fewer fill-ins will be created. However, the
|
||||
* initial pivot selection process will take considerably longer.
|
||||
* If working with node admittance matrices, or other matrices
|
||||
* with a strong diagonal, it is probably best to use
|
||||
* \a DIAGONAL_PIVOTING for two reasons. First, accuracy will be
|
||||
* better because pivots will be chosen from the large diagonal
|
||||
* elements, thus reducing the chance of growth. Second, a near
|
||||
* optimal ordering will be chosen quickly. If the class of
|
||||
* matrices you are working with does not have a strong diagonal,
|
||||
* do not use \a DIAGONAL_PIVOTING, but consider using a larger
|
||||
* threshold. When \a DIAGONAL_PIVOTING is turned off, the following
|
||||
* options and constants are not used: \a MODIFIED_MARKOWITZ,
|
||||
* \a MAX_MARKOWITZ_TIES, and \a TIES_MULTIPLIER.
|
||||
*/
|
||||
#define DIAGONAL_PIVOTING YES
|
||||
|
||||
/*!
|
||||
* This determines whether arrays start at an index of zero or one.
|
||||
* This option is necessitated by the fact that standard C
|
||||
* convention dictates that arrays begin with an index of zero but
|
||||
* the standard mathematic convention states that arrays begin with
|
||||
* an index of one. So if you prefer to start your arrays with
|
||||
* zero, or your calling Sparse from FORTRAN, set ARRAY_OFFSET to
|
||||
* NO or 0. Otherwise, set ARRAY_OFFSET to YES or 1. Note that if
|
||||
* you use an offset of one, the arrays that you pass to Sparse
|
||||
* must have an allocated length of one plus the size of the
|
||||
* matrix. ARRAY_OFFSET must be either 0 or 1, no other offsets
|
||||
* are valid.
|
||||
*/
|
||||
#define ARRAY_OFFSET YES
|
||||
|
||||
/*!
|
||||
* This specifies that the modified Markowitz method of pivot
|
||||
* selection is to be used. The modified Markowitz method differs
|
||||
* from standard Markowitz in two ways. First, under modified
|
||||
* Markowitz, the search for a pivot can be terminated early if a
|
||||
* adequate (in terms of sparsity) pivot candidate is found.
|
||||
* Thus, when using modified Markowitz, the initial factorization
|
||||
* can be faster, but at the expense of a suboptimal pivoting
|
||||
* order that may slow subsequent factorizations. The second
|
||||
* difference is in the way modified Markowitz breaks Markowitz
|
||||
* ties. When two or more elements are pivot candidates and they
|
||||
* all have the same Markowitz product, then the tie is broken by
|
||||
* choosing the element that is best numerically. The numerically
|
||||
* best element is the one with the largest ratio of its magnitude
|
||||
* to the magnitude of the largest element in the same column,
|
||||
* excluding itself. The modified Markowitz method results in
|
||||
* marginally better accuracy. This option is most appropriate
|
||||
* for use when working with very large matrices where the initial
|
||||
* factor time represents an unacceptable burden. \a NO is recommended.
|
||||
*/
|
||||
#define MODIFIED_MARKOWITZ NO
|
||||
|
||||
/*!
|
||||
* This specifies that the spDeleteRowAndCol() routine
|
||||
* should be compiled. Note that for this routine to be
|
||||
* compiled, both \a DELETE and \a TRANSLATE should be set true.
|
||||
*/
|
||||
#define DELETE NO
|
||||
|
||||
/*!
|
||||
* This specifies that the spStripFills() routine should be compiled.
|
||||
*/
|
||||
#define STRIP NO
|
||||
|
||||
/*!
|
||||
* This specifies that the routine that preorders modified node
|
||||
* admittance matrices should be compiled. This routine results
|
||||
* in greater speed and accuracy if used with this type of
|
||||
* matrix.
|
||||
*/
|
||||
#define MODIFIED_NODAL YES
|
||||
|
||||
/*!
|
||||
* This specifies that the routines that allow four related
|
||||
* elements to be entered into the matrix at once should be
|
||||
* compiled. These elements are usually related to an
|
||||
* admittance. The routines affected by \a QUAD_ELEMENT are the
|
||||
* spGetAdmittance(), spGetQuad() and spGetOnes() routines.
|
||||
*/
|
||||
#define QUAD_ELEMENT NO
|
||||
|
||||
/*!
|
||||
* This specifies that the routines that solve the matrix as if
|
||||
* it was transposed should be compiled. These routines are
|
||||
* useful when performing sensitivity analysis using the adjoint
|
||||
* method.
|
||||
*/
|
||||
#define TRANSPOSE YES
|
||||
|
||||
/*!
|
||||
* This specifies that the routine that performs scaling on the
|
||||
* matrix should be complied. Scaling is not strongly
|
||||
* supported. The routine to scale the matrix is provided, but
|
||||
* no routines are provided to scale and descale the RHS and
|
||||
* Solution vectors. It is suggested that if scaling is desired,
|
||||
* it only be preformed when the pivot order is being chosen [in
|
||||
* spOrderAndFactor()]. This is the only time scaling has
|
||||
* an effect. The scaling may then either be removed from the
|
||||
* solution by the user or the scaled factors may simply be
|
||||
* thrown away. \a NO is recommended.
|
||||
*/
|
||||
#define SCALING NO
|
||||
|
||||
/*!
|
||||
* This specifies that routines that are used to document the
|
||||
* matrix, such as spPrint() and spFileMatrix(), should be
|
||||
* compiled.
|
||||
*/
|
||||
#define DOCUMENTATION YES
|
||||
|
||||
/*!
|
||||
* This specifies that routines that are used to multily the
|
||||
* matrix by a vector, such as spMultiply() and spMultTransposed(), should be
|
||||
* compiled.
|
||||
*/
|
||||
#define MULTIPLICATION YES
|
||||
|
||||
/*!
|
||||
* This specifies that the routine spDeterminant() should be complied.
|
||||
*/
|
||||
#define DETERMINANT YES
|
||||
|
||||
/*!
|
||||
* This specifies that spLargestElement() and spRoundoff() should
|
||||
* be compiled. These routines are used to check the stability (and
|
||||
* hence the quality of the pivoting) of the factorization by
|
||||
* computing a bound on the size of the element is the matrix
|
||||
* \f$ E = A - LU \f$. If this bound is very high after applying
|
||||
* spOrderAndFactor(), then the pivot threshold should be raised.
|
||||
* If the bound increases greatly after using spFactor(), then the
|
||||
* matrix should probably be reordered. Recomend \a NO.
|
||||
*/
|
||||
#define STABILITY NO
|
||||
|
||||
/*!
|
||||
* This specifies that spCondition() and spNorm(), the code that
|
||||
* computes a good estimate of the condition number of the matrix,
|
||||
* should be compiled. Recomend \a NO.
|
||||
*/
|
||||
#define CONDITION NO
|
||||
|
||||
/*!
|
||||
* This specifies that spPseudoCondition(), the code that computes
|
||||
* a crude and easily fooled indicator of ill-conditioning in the
|
||||
* matrix, should be compiled. Recomend \a NO.
|
||||
*/
|
||||
#define PSEUDOCONDITION NO
|
||||
|
||||
/*!
|
||||
* This specifies that the \a FORTRAN interface routines should be
|
||||
* compiled. When interfacing to \a FORTRAN programs, the \a ARRAY_OFFSET
|
||||
* options should be set to NO.
|
||||
*/
|
||||
#define FORTRAN NO
|
||||
|
||||
/*!
|
||||
* This specifies that additional error checking will be compiled.
|
||||
* The type of error checked are those that are common when the
|
||||
* matrix routines are first integrated into a user's program. Once
|
||||
* the routines have been integrated in and are running smoothly, this
|
||||
* option should be turned off. \a YES is recommended.
|
||||
*/
|
||||
#define DEBUG YES
|
||||
|
||||
#endif /* spINSIDE_SPARSE */
|
||||
|
||||
/*
|
||||
* The following options affect Sparse exports and so are exported as a
|
||||
* side effect. For this reason they use the `sp' prefix. The boolean
|
||||
* constants YES an NO are not defined in spMatrix.h to avoid conflicts
|
||||
* with user code, so use 0 for NO and 1 for YES.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* This specifies that the routines will be complied to handle
|
||||
* complex systems of equations.
|
||||
*/
|
||||
#define spCOMPLEX 1
|
||||
|
||||
/*!
|
||||
* This specifies the format for complex vectors. If this is set
|
||||
* false then a complex vector is made up of one double sized
|
||||
* array of RealNumber's in which the real and imaginary numbers
|
||||
* are placed alternately in the array. In other
|
||||
* words, the first entry would be Complex[1].Real, then comes
|
||||
* Complex[1].Imag, then Complex[2].Real, etc. If
|
||||
* \a spSEPARATED_COMPLEX_VECTORS is set true, then each complex
|
||||
* vector is represented by two arrays of \a spREALs, one with
|
||||
* the real terms, the other with the imaginary. \a NO is recommended.
|
||||
*/
|
||||
#define spSEPARATED_COMPLEX_VECTORS 1
|
||||
|
||||
#ifdef spINSIDE_SPARSE
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* MATRIX CONSTANTS
|
||||
*
|
||||
* These constants are used throughout the sparse matrix routines. They
|
||||
* should be set to suit the type of matrix being solved.
|
||||
*/
|
||||
|
||||
/* Begin constants. */
|
||||
|
||||
/*!
|
||||
* The relative threshold used if the user enters an invalid
|
||||
* threshold. Also the threshold used by spFactor() when
|
||||
* calling spOrderAndFactor(). The default threshold should
|
||||
* not be less than or equal to zero nor larger than one.
|
||||
* 0.001 is recommended.
|
||||
*/
|
||||
#define DEFAULT_THRESHOLD 1.0e-3
|
||||
|
||||
/*!
|
||||
* This indicates whether spOrderAndFactor() should use diagonal
|
||||
* pivoting as default. This issue only arises when
|
||||
* spOrderAndFactor() is called from spFactor(). \a YES is recommended.
|
||||
*/
|
||||
#define DIAG_PIVOTING_AS_DEFAULT YES
|
||||
|
||||
/*!
|
||||
* This number multiplied by the size of the matrix equals the number
|
||||
* of elements for which memory is initially allocated in spCreate().
|
||||
* 6 is recommended.
|
||||
*/
|
||||
#define SPACE_FOR_ELEMENTS 6
|
||||
|
||||
/*!
|
||||
* This number multiplied by the size of the matrix equals the number
|
||||
* of elements for which memory is initially allocated and specifically
|
||||
* reserved for fill-ins in spCreate(). 4 is recommended.
|
||||
*/
|
||||
#define SPACE_FOR_FILL_INS 4
|
||||
|
||||
/*!
|
||||
* The number of matrix elements requested from the malloc utility on
|
||||
* each call to it. Setting this value greater than 1 reduces the
|
||||
* amount of overhead spent in this system call. On a virtual memory
|
||||
* machine, its good to allocate slightly less than a page worth of
|
||||
* elements at a time (or some multiple thereof).
|
||||
* 31 is recommended.
|
||||
*/
|
||||
#define ELEMENTS_PER_ALLOCATION 31
|
||||
|
||||
/*!
|
||||
* The minimum allocated size of a matrix. Note that this does not
|
||||
* limit the minimum size of a matrix. This just prevents having to
|
||||
* resize a matrix many times if the matrix is expandable, large and
|
||||
* allocated with an estimated size of zero. This number should not
|
||||
* be less than one.
|
||||
*/
|
||||
#define MINIMUM_ALLOCATED_SIZE 6
|
||||
|
||||
/*!
|
||||
* The amount the allocated size of the matrix is increased when it
|
||||
* is expanded.
|
||||
*/
|
||||
#define EXPANSION_FACTOR 1.5
|
||||
|
||||
/*!
|
||||
* Some terminology should be defined. The Markowitz row count is the number
|
||||
* of non-zero elements in a row excluding the one being considered as pivot.
|
||||
* There is one Markowitz row count for every row. The Markowitz column
|
||||
* is defined similarly for columns. The Markowitz product for an element
|
||||
* is the product of its row and column counts. It is a measure of how much
|
||||
* work would be required on the next step of the factorization if that
|
||||
* element were chosen to be pivot. A small Markowitz product is desirable.
|
||||
*
|
||||
* This number is used for two slightly different things, both of which
|
||||
* relate to the search for the best pivot. First, it is the maximum
|
||||
* number of elements that are Markowitz tied that will be sifted
|
||||
* through when trying to find the one that is numerically the best.
|
||||
* Second, it creates an upper bound on how large a Markowitz product
|
||||
* can be before it eliminates the possibility of early termination
|
||||
* of the pivot search. In other words, if the product of the smallest
|
||||
* Markowitz product yet found and \a TIES_MULTIPLIER is greater than
|
||||
* \a MAX_MARKOWITZ_TIES, then no early termination takes place.
|
||||
* Set \a MAX_MARKOWITZ_TIES to some small value if no early termination of
|
||||
* the pivot search is desired. An array of RealNumbers is allocated
|
||||
* of size \a MAX_MARKOWITZ_TIES so it must be positive and shouldn't
|
||||
* be too large. Active when MODIFIED_MARKOWITZ is 1 (YES).
|
||||
* 100 is recommended.
|
||||
* \see TIES_MULTIPLIER
|
||||
*/
|
||||
#define MAX_MARKOWITZ_TIES 100
|
||||
|
||||
/*!
|
||||
* Specifies the number of Markowitz ties that are allowed to occur
|
||||
* before the search for the pivot is terminated early. Set to some
|
||||
* large value if no early termination of the pivot search is desired.
|
||||
* This number is multiplied times the Markowitz product to determine
|
||||
* how many ties are required for early termination. This means that
|
||||
* more elements will be searched before early termination if a large
|
||||
* number of fill-ins could be created by accepting what is currently
|
||||
* considered the best choice for the pivot. Active when
|
||||
* \a MODIFIED_MARKOWITZ is 1 (YES). Setting this number to zero
|
||||
* effectively eliminates all pivoting, which should be avoided.
|
||||
* This number must be positive. \a TIES_MULTIPLIER is also used when
|
||||
* diagonal pivoting breaks down. 5 is recommended.
|
||||
* \see MAX_MARKOWITZ_TIES
|
||||
*/
|
||||
#define TIES_MULTIPLIER 5
|
||||
|
||||
/*!
|
||||
* Which partition mode is used by spPartition() as default.
|
||||
* Possibilities include \a spDIRECT_PARTITION (each row used direct
|
||||
* addressing, best for a few relatively dense matrices),
|
||||
* \a spINDIRECT_PARTITION (each row used indirect addressing, best
|
||||
* for a few very sparse matrices), and \a spAUTO_PARTITION (direct or
|
||||
* indirect addressing is chosen on a row-by-row basis, carries a large
|
||||
* overhead, but speeds up both dense and sparse matrices, best if there
|
||||
* is a large number of matrices that can use the same ordering.
|
||||
*/
|
||||
#define DEFAULT_PARTITION spAUTO_PARTITION
|
||||
|
||||
/*!
|
||||
* The number of characters per page width. Set to 80 for terminal,
|
||||
* 132 for line printer. Controls how many columns printed by
|
||||
* spPrint() per page width.
|
||||
*/
|
||||
#define PRINTER_WIDTH 80
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* spINSIDE_SPARSE */
|
||||
/*
|
||||
* PORTABILITY MACROS
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
# define spcCONCAT(prefix,suffix) prefix ## suffix
|
||||
# define spcQUOTE(x) # x
|
||||
# define spcFUNC_NEEDS_FILE(func,file) \
|
||||
func ## _requires_ ## file ## _to_be_included_
|
||||
#else
|
||||
# define spcCONCAT(prefix,suffix) prefix/**/suffix
|
||||
# define spcQUOTE(x) "x"
|
||||
# define spcFUNC_NEEDS_FILE(func,file) \
|
||||
func/**/_requires_/**/file/**/_to_be_included_
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
/*
|
||||
* Definitions for C++
|
||||
*/
|
||||
# define spcEXTERN extern "C"
|
||||
# define spcNO_ARGS
|
||||
# define spcCONST const
|
||||
typedef void *spGenericPtr;
|
||||
#else
|
||||
#ifdef __STDC__
|
||||
/*
|
||||
* Definitions for ANSI C
|
||||
*/
|
||||
# define spcEXTERN extern
|
||||
# define spcNO_ARGS void
|
||||
# define spcCONST const
|
||||
typedef void *spGenericPtr;
|
||||
# else
|
||||
/*
|
||||
* Definitions for K&R C -- ignore function prototypes
|
||||
*/
|
||||
# define spcEXTERN extern
|
||||
# define spcNO_ARGS
|
||||
# define spcCONST
|
||||
typedef char *spGenericPtr;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef spINSIDE_SPARSE
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* MACHINE CONSTANTS
|
||||
*
|
||||
* These numbers must be updated when the program is ported to a new machine.
|
||||
*/
|
||||
|
||||
/* Begin machine constants. */
|
||||
#include <limits.h>
|
||||
#include <float.h>
|
||||
|
||||
/*! The resolution of spREAL. */
|
||||
#define MACHINE_RESOLUTION DBL_EPSILON
|
||||
|
||||
/*! The largest possible value of spREAL. */
|
||||
#define LARGEST_REAL DBL_MAX
|
||||
|
||||
/*! The smalles possible positive value of spREAL. */
|
||||
#define SMALLEST_REAL DBL_MIN
|
||||
|
||||
/*! The largest possible value of shorts. */
|
||||
#define LARGEST_SHORT_INTEGER SHRT_MAX
|
||||
|
||||
/*! The largest possible value of longs. */
|
||||
#define LARGEST_LONG_INTEGER LONG_MAX
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ANNOTATION */
|
||||
/*!
|
||||
* This macro changes the amount of annotation produced by the matrix
|
||||
* routines. The annotation is used as a debugging aid. Change the number
|
||||
* associated with \a ANNOTATE to change the amount of annotation produced by
|
||||
* the program. Possible values include \a NONE, \a ON_STRANGE_BEHAVIOR, and
|
||||
* \a FULL. \a NONE is recommended.
|
||||
*/
|
||||
#define ANNOTATE NONE
|
||||
|
||||
/*!
|
||||
* A possible value for \a ANNOTATE. Disables all annotation.
|
||||
*/
|
||||
#define NONE 0
|
||||
|
||||
/*!
|
||||
* A possible value for \a ANNOTATE. Causes annotation to be produce
|
||||
* upon unusual occurances only.
|
||||
*/
|
||||
#define ON_STRANGE_BEHAVIOR 1
|
||||
|
||||
/*!
|
||||
* A possible value for \a ANNOTATE. Enables full annotation.
|
||||
*/
|
||||
#define FULL 2
|
||||
|
||||
#endif /* spINSIDE_SPARSE */
|
||||
#endif /* spCONFIG_DEFS */
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
#ifndef ngspice_SPDEFS_H
|
||||
#define ngspice_SPDEFS_H
|
||||
/*
|
||||
* DATA STRUCTURE AND MACRO DEFINITIONS for Sparse.
|
||||
*
|
||||
|
|
@ -15,30 +13,67 @@
|
|||
/*
|
||||
* Revision and copyright information.
|
||||
*
|
||||
* Copyright (c) 1985,86,87,88,89,90
|
||||
* by Kenneth S. Kundert and the University of California.
|
||||
* Copyright (c) 1985-2003 by Kenneth S. Kundert
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the copyright notices appear in all copies and
|
||||
* supporting documentation and that the authors and the University of
|
||||
* California are properly credited. The authors and the University of
|
||||
* California make no representations as to the suitability of this
|
||||
* software for any purpose. It is provided `as is', without express
|
||||
* or implied warranty.
|
||||
* $Date: 2003/06/29 04:19:52 $
|
||||
* $Revision: 1.2 $
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* IMPORTS
|
||||
* If running lint, change some of the compiler options to get a more
|
||||
* complete inspection.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef lint
|
||||
#undef REAL
|
||||
#undef spCOMPLEX
|
||||
#undef EXPANDABLE
|
||||
#undef TRANSLATE
|
||||
#undef INITIALIZE
|
||||
#undef DELETE
|
||||
#undef STRIP
|
||||
#undef MODIFIED_NODAL
|
||||
#undef QUAD_ELEMENT
|
||||
#undef TRANSPOSE
|
||||
#undef SCALING
|
||||
#undef DOCUMENTATION
|
||||
#undef MULTIPLICATION
|
||||
#undef DETERMINANT
|
||||
#undef CONDITION
|
||||
#undef PSEUDOCONDITION
|
||||
#undef FORTRAN
|
||||
#undef DEBUG
|
||||
|
||||
#define REAL YES
|
||||
#define spCOMPLEX YES
|
||||
#define EXPANDABLE YES
|
||||
#define TRANSLATE YES
|
||||
#define INITIALIZE YES
|
||||
#define DELETE YES
|
||||
#define STRIP YES
|
||||
#define MODIFIED_NODAL YES
|
||||
#define QUAD_ELEMENT YES
|
||||
#define TRANSPOSE YES
|
||||
#define SCALING YES
|
||||
#define DOCUMENTATION YES
|
||||
#define MULTIPLICATION YES
|
||||
#define DETERMINANT YES
|
||||
#define CONDITION YES
|
||||
#define PSEUDOCONDITION YES
|
||||
#define FORTRAN YES
|
||||
#define DEBUG YES
|
||||
|
||||
#define LINT YES
|
||||
#else /* not lint */
|
||||
#define LINT NO
|
||||
#endif /* not lint */
|
||||
|
||||
|
||||
|
||||
|
||||
#undef ABORT
|
||||
#undef FREE
|
||||
|
||||
|
||||
|
||||
|
|
@ -46,9 +81,10 @@
|
|||
* MACRO DEFINITIONS
|
||||
*
|
||||
* Macros are distinguished by using solely capital letters in their
|
||||
* identifiers. This contrasts with C defined identifiers which are
|
||||
* strictly lower case, and program variable and procedure names
|
||||
* which use both upper and lower case. */
|
||||
* identifiers. This contrasts with C defined identifiers which are strictly
|
||||
* lower case, and program variable and procedure names which use both upper
|
||||
* and lower case.
|
||||
*/
|
||||
|
||||
/* Begin macros. */
|
||||
|
||||
|
|
@ -56,15 +92,32 @@
|
|||
#define BOOLEAN int
|
||||
#define NO 0
|
||||
#define YES 1
|
||||
#define NOT !
|
||||
#define AND &&
|
||||
#define OR ||
|
||||
|
||||
#define SPARSE_ID 0x772773 /* Arbitrary (is Sparse on phone). */
|
||||
#define IS_SPARSE(matrix) ((matrix) != NULL && \
|
||||
(matrix)->ID == SPARSE_ID)
|
||||
#define IS_VALID(matrix) ((matrix) != NULL && \
|
||||
(matrix)->ID == SPARSE_ID && \
|
||||
(matrix)->Error >= spOKAY && \
|
||||
(matrix)->Error < spFATAL)
|
||||
#define IS_FACTORED(matrix) ((matrix)->Factored && !(matrix)->NeedsOrdering)
|
||||
/* NULL pointer */
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
/* Define macros for validating matrix. */
|
||||
#define SPARSE_ID 0xDeadBeef /* Arbitrary. */
|
||||
#define IS_SPARSE(matrix) (((matrix) != NULL) AND \
|
||||
((matrix)->ID == SPARSE_ID))
|
||||
#define NO_ERRORS(matrix) (((matrix)->Error >= spOKAY) AND \
|
||||
((matrix)->Error < spFATAL))
|
||||
#define IS_FACTORED(matrix) ((matrix)->Factored AND \
|
||||
NOT (matrix)->NeedsOrdering)
|
||||
|
||||
#define ASSERT_IS_SPARSE(matrix) vASSERT( IS_SPARSE(matrix), \
|
||||
spcMatrixIsNotValid )
|
||||
#define ASSERT_NO_ERRORS(matrix) vASSERT( NO_ERRORS(matrix), \
|
||||
spcErrorsMustBeCleared )
|
||||
#define ASSERT_IS_FACTORED(matrix) vASSERT( IS_FACTORED(matrix), \
|
||||
spcMatrixMustBeFactored )
|
||||
#define ASSERT_IS_NOT_FACTORED(matrix) vASSERT( NOT (matrix)->Factored, \
|
||||
spcMatrixMustNotBeFactored )
|
||||
|
||||
/* Macro commands */
|
||||
/* Macro functions that return the maximum or minimum independent of type. */
|
||||
|
|
@ -78,36 +131,20 @@
|
|||
#define SQR(a) ((a)*(a))
|
||||
|
||||
/* Macro procedure that swaps two entities. */
|
||||
#define SWAP(type, a, b) \
|
||||
do { \
|
||||
type SWAP_macro_local = a; \
|
||||
a = b; \
|
||||
b = SWAP_macro_local; \
|
||||
} while(0)
|
||||
#define SWAP(type, a, b) {type swapx; swapx = a; a = b; b = swapx;}
|
||||
|
||||
|
||||
/*
|
||||
* COMPLEX OPERATION MACROS
|
||||
*/
|
||||
#ifndef ngspice_COMPLEX_H
|
||||
|
||||
/* Real and Complex numbers definition */
|
||||
|
||||
#define spREAL double
|
||||
|
||||
/* Begin `realNumber'. */
|
||||
typedef spREAL RealNumber, *RealVector;
|
||||
|
||||
/* Begin `ComplexNumber'. */
|
||||
typedef struct
|
||||
{ RealNumber Real;
|
||||
RealNumber Imag;
|
||||
} ComplexNumber, *ComplexVector;
|
||||
|
||||
/* Macro function that returns the approx absolute value of a complex
|
||||
number. */
|
||||
/* Macro function that returns the approx absolute value of a complex number. */
|
||||
#if spCOMPLEX
|
||||
#define ELEMENT_MAG(ptr) (ABS((ptr)->Real) + ABS((ptr)->Imag))
|
||||
|
||||
#define CMPLX_ASSIGN_VALUE(cnum, vReal, vImag) \
|
||||
{ (cnum).Real = vReal; \
|
||||
(cnum).Imag = vImag; \
|
||||
}
|
||||
#else
|
||||
#define ELEMENT_MAG(ptr) ((ptr)->Real < 0.0 ? -(ptr)->Real : (ptr)->Real)
|
||||
#endif
|
||||
|
||||
/* Complex assignment statements. */
|
||||
#define CMPLX_ASSIGN(to,from) \
|
||||
|
|
@ -126,21 +163,12 @@ typedef struct
|
|||
{ (to).Real = -(from).Real; \
|
||||
(to).Imag = (from).Imag; \
|
||||
}
|
||||
|
||||
#define CMPLX_CONJ(a) (a).Imag = -(a).Imag
|
||||
|
||||
#define CONJUGATE(a) (a).Imag = -(a).Imag
|
||||
|
||||
#define CMPLX_NEGATE(a) \
|
||||
{ (a).Real = -(a).Real; \
|
||||
(a).Imag = -(a).Imag; \
|
||||
}
|
||||
|
||||
#define CMPLX_NEGATE_SELF(cnum) \
|
||||
{ (cnum).Real = -(cnum).Real; \
|
||||
(cnum).Imag = -(cnum).Imag; \
|
||||
}
|
||||
|
||||
/* Macro that returns the approx magnitude (L-1 norm) of a complex number. */
|
||||
#define CMPLX_1_NORM(a) (ABS((a).Real) + ABS((a).Imag))
|
||||
|
||||
|
|
@ -148,7 +176,7 @@ typedef struct
|
|||
#define CMPLX_INF_NORM(a) (MAX (ABS((a).Real),ABS((a).Imag)))
|
||||
|
||||
/* Macro function that returns the magnitude (L-2 norm) of a complex number. */
|
||||
#define CMPLX_2_NORM(a) (hypot((a).Real, (a).Imag))
|
||||
#define CMPLX_2_NORM(a) (sqrt((a).Real*(a).Real + (a).Imag*(a).Imag))
|
||||
|
||||
/* Macro function that performs complex addition. */
|
||||
#define CMPLX_ADD(to,from_a,from_b) \
|
||||
|
|
@ -156,11 +184,6 @@ typedef struct
|
|||
(to).Imag = (from_a).Imag + (from_b).Imag; \
|
||||
}
|
||||
|
||||
/* Macro function that performs addition of a complex and a scalar. */
|
||||
#define CMPLX_ADD_SELF_SCALAR(cnum, scalar) \
|
||||
{ (cnum).Real += scalar; \
|
||||
}
|
||||
|
||||
/* Macro function that performs complex subtraction. */
|
||||
#define CMPLX_SUBT(to,from_a,from_b) \
|
||||
{ (to).Real = (from_a).Real - (from_b).Real; \
|
||||
|
|
@ -178,7 +201,7 @@ typedef struct
|
|||
{ (to).Real -= (from).Real; \
|
||||
(to).Imag -= (from).Imag; \
|
||||
}
|
||||
|
||||
|
||||
/* Macro function that multiplies a complex number by a scalar. */
|
||||
#define SCLR_MULT(to,sclr,cmplx) \
|
||||
{ (to).Real = (sclr) * (cmplx).Real; \
|
||||
|
|
@ -198,32 +221,13 @@ typedef struct
|
|||
(to).Imag = (from_a).Real * (from_b).Imag + \
|
||||
(from_a).Imag * (from_b).Real; \
|
||||
}
|
||||
|
||||
/* Macro function that multiplies a complex number and a scalar. */
|
||||
#define CMPLX_MULT_SCALAR(to,from, scalar) \
|
||||
{ (to).Real = (from).Real * scalar; \
|
||||
(to).Imag = (from).Imag * scalar; \
|
||||
}
|
||||
|
||||
/* Macro function that implements *= for a complex and a scalar number. */
|
||||
|
||||
#define CMPLX_MULT_SELF_SCALAR(cnum, scalar) \
|
||||
{ (cnum).Real *= scalar; \
|
||||
(cnum).Imag *= scalar; \
|
||||
}
|
||||
|
||||
/* Macro function that multiply-assigns a complex number by a scalar. */
|
||||
#define SCLR_MULT_ASSIGN(to,sclr) \
|
||||
{ (to).Real *= (sclr); \
|
||||
(to).Imag *= (sclr); \
|
||||
}
|
||||
|
||||
/* Macro function that implements to *= from for complex numbers. */
|
||||
#define CMPLX_MULT_ASSIGN(to,from) \
|
||||
{ RealNumber to_Real_ = (to).Real; \
|
||||
(to).Real = to_Real_ * (from).Real - \
|
||||
{ RealNumber to_real_ = (to).Real; \
|
||||
(to).Real = to_real_ * (from).Real - \
|
||||
(to).Imag * (from).Imag; \
|
||||
(to).Imag = to_Real_ * (from).Imag + \
|
||||
(to).Imag = to_real_ * (from).Imag + \
|
||||
(to).Imag * (from).Real; \
|
||||
}
|
||||
|
||||
|
|
@ -309,8 +313,8 @@ typedef struct
|
|||
/* Complex division: to = num / den */
|
||||
#define CMPLX_DIV(to,num,den) \
|
||||
{ RealNumber r_, s_; \
|
||||
if (((den).Real >= (den).Imag && (den).Real > -(den).Imag) || \
|
||||
((den).Real < (den).Imag && (den).Real <= -(den).Imag)) \
|
||||
if (((den).Real >= (den).Imag AND (den).Real > -(den).Imag) OR \
|
||||
((den).Real < (den).Imag AND (den).Real <= -(den).Imag)) \
|
||||
{ r_ = (den).Imag / (den).Real; \
|
||||
s_ = (den).Real + r_*(den).Imag; \
|
||||
(to).Real = ((num).Real + r_*(num).Imag)/s_; \
|
||||
|
|
@ -327,8 +331,8 @@ typedef struct
|
|||
/* Complex division and assignment: num /= den */
|
||||
#define CMPLX_DIV_ASSIGN(num,den) \
|
||||
{ RealNumber r_, s_, t_; \
|
||||
if (((den).Real >= (den).Imag && (den).Real > -(den).Imag) || \
|
||||
((den).Real < (den).Imag && (den).Real <= -(den).Imag)) \
|
||||
if (((den).Real >= (den).Imag AND (den).Real > -(den).Imag) OR \
|
||||
((den).Real < (den).Imag AND (den).Real <= -(den).Imag)) \
|
||||
{ r_ = (den).Imag / (den).Real; \
|
||||
s_ = (den).Real + r_*(den).Imag; \
|
||||
t_ = ((num).Real + r_*(num).Imag)/s_; \
|
||||
|
|
@ -347,8 +351,8 @@ typedef struct
|
|||
/* Complex reciprocation: to = 1.0 / den */
|
||||
#define CMPLX_RECIPROCAL(to,den) \
|
||||
{ RealNumber r_; \
|
||||
if (((den).Real >= (den).Imag && (den).Real > -(den).Imag) || \
|
||||
((den).Real < (den).Imag && (den).Real <= -(den).Imag)) \
|
||||
if (((den).Real >= (den).Imag AND (den).Real > -(den).Imag) OR \
|
||||
((den).Real < (den).Imag AND (den).Real <= -(den).Imag)) \
|
||||
{ r_ = (den).Imag / (den).Real; \
|
||||
(to).Imag = -r_*((to).Real = 1.0/((den).Real + r_*(den).Imag)); \
|
||||
} \
|
||||
|
|
@ -360,40 +364,184 @@ typedef struct
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Allocation */
|
||||
|
||||
extern void * tmalloc(size_t);
|
||||
extern void txfree(const void *);
|
||||
extern void * trealloc(const void *, size_t);
|
||||
|
||||
#define SP_MALLOC(type,number) (type *) tmalloc((size_t)(number) * sizeof(type))
|
||||
#define SP_REALLOC(ptr,type,number) \
|
||||
ptr = (type *) trealloc(ptr, (size_t)(number) * sizeof(type))
|
||||
#define SP_FREE(ptr) { if ((ptr) != NULL) txfree(ptr); (ptr) = NULL; }
|
||||
|
||||
|
||||
#include "ngspice/config.h"
|
||||
|
||||
/* A new calloc */
|
||||
#ifndef HAVE_LIBGC
|
||||
#define SP_CALLOC(ptr,type,number) \
|
||||
{ ptr = (type *) calloc((size_t)(number), sizeof(type)); \
|
||||
}
|
||||
#else /* HAVE_LIBCG */
|
||||
#define SP_CALLOC(ptr,type,number) \
|
||||
{ ptr = (type *) tmalloc((size_t)(number) * sizeof(type)); \
|
||||
}
|
||||
#include <gc/gc.h>
|
||||
#define tmalloc(m) GC_malloc(m)
|
||||
#define trealloc(m, n) GC_realloc((m), (n))
|
||||
#define tfree(m)
|
||||
#define txfree(m)
|
||||
#endif
|
||||
|
||||
#include "ngspice/defines.h"
|
||||
|
||||
|
||||
/*
|
||||
* ASSERT and ABORT
|
||||
*
|
||||
* Macro used to assert that if the code is working correctly, then
|
||||
* a condition must be true. If not, then execution is terminated
|
||||
* and an error message is issued stating that there is an internal
|
||||
* error and giving the file and line number. These assertions are
|
||||
* not evaluated unless the DEBUG flag is true.
|
||||
*/
|
||||
|
||||
#if DEBUG
|
||||
#define ASSERT(condition) \
|
||||
{ if (NOT(condition)) \
|
||||
{ (void)fflush(stdout); \
|
||||
(void)fprintf(stderr, "sparse: internal error detected in file `%s' at line %d.\n assertion `%s' failed.\n",\
|
||||
__FILE__, __LINE__, spcQUOTE(condition) ); \
|
||||
(void)fflush(stderr); \
|
||||
abort(); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define ASSERT(condition)
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
#define vASSERT(condition,message) \
|
||||
{ if (NOT(condition)) \
|
||||
vABORT(message); \
|
||||
}
|
||||
#else
|
||||
#define vASSERT(condition,message)
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
#define vABORT(message) \
|
||||
{ (void)fflush(stdout); \
|
||||
(void)fprintf(stderr, "sparse: internal error detected in file `%s' at line %d.\n %s.\n", __FILE__, __LINE__, message );\
|
||||
(void)fflush(stderr); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#define ABORT() \
|
||||
{ (void)fflush(stdout); \
|
||||
(void)fprintf(stderr, "sparse: internal error detected in file `%s' at line %d.\n", __FILE__, __LINE__ ); \
|
||||
(void)fflush(stderr); \
|
||||
abort(); \
|
||||
}
|
||||
#else
|
||||
#define vABORT(message) abort()
|
||||
#define ABORT() abort()
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* IMAGINARY VECTORS
|
||||
*
|
||||
* The imaginary vectors iRHS and iSolution are only needed when the
|
||||
* options spCOMPLEX and spSEPARATED_COMPLEX_VECTORS are set. The following
|
||||
* macro makes it easy to include or exclude these vectors as needed.
|
||||
*/
|
||||
|
||||
#if spCOMPLEX AND spSEPARATED_COMPLEX_VECTORS
|
||||
#define IMAG_VECTORS , iRHS, iSolution
|
||||
#define IMAG_RHS , iRHS
|
||||
#define IMAG_RHS_DECL , RealVector iRHS
|
||||
#define IMAG_VECT_DECL , RealVector iRHS, RealVector iSolution
|
||||
#else
|
||||
#define IMAG_VECTORS
|
||||
#define IMAG_RHS
|
||||
#define IMAG_RHS_DECL
|
||||
#define IMAG_VECT_DECL
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* MEMORY ALLOCATION
|
||||
*/
|
||||
#include <stddef.h>
|
||||
spcEXTERN void *malloc(size_t size);
|
||||
spcEXTERN void *calloc(size_t nmemb, size_t size);
|
||||
spcEXTERN void *realloc(void *ptr, size_t size);
|
||||
spcEXTERN void free(void *ptr);
|
||||
spcEXTERN void abort(void);
|
||||
|
||||
#define ALLOC(type,number) ((type *)malloc((unsigned)(sizeof(type)*(number))))
|
||||
#define REALLOC(ptr,type,number) \
|
||||
ptr = (type *)realloc((char *)ptr,(unsigned)(sizeof(type)*(number)))
|
||||
#define FREE(ptr) { if ((ptr) != NULL) free((char *)(ptr)); (ptr) = NULL; }
|
||||
|
||||
|
||||
/* Calloc that properly handles allocating a cleared vector. */
|
||||
#define CALLOC(ptr,type,number) \
|
||||
{ int i; ptr = ALLOC(type, number); \
|
||||
if (ptr != (type *)NULL) \
|
||||
for(i=(number)-1;i>=0; i--) ptr[i] = (type) 0; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Utility Functions
|
||||
*/
|
||||
/*
|
||||
* Compute the product of two intergers while avoiding overflow.
|
||||
* Used when computing Markowitz products.
|
||||
*/
|
||||
|
||||
#define spcMarkoProd(product, op1, op2) \
|
||||
if (( (op1) > LARGEST_SHORT_INTEGER AND (op2) != 0) OR \
|
||||
( (op2) > LARGEST_SHORT_INTEGER AND (op1) != 0)) \
|
||||
{ double fProduct = (double)(op1) * (double)(op2); \
|
||||
if (fProduct >= LARGEST_LONG_INTEGER) \
|
||||
(product) = LARGEST_LONG_INTEGER; \
|
||||
else \
|
||||
(product) = (long)fProduct; \
|
||||
} \
|
||||
else (product) = (op1)*(op2);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* REAL NUMBER
|
||||
*/
|
||||
|
||||
/* Begin `RealNumber'. */
|
||||
|
||||
typedef spREAL RealNumber, *RealVector;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* COMPLEX NUMBER DATA STRUCTURE
|
||||
*
|
||||
* >>> Structure fields:
|
||||
* Real (RealNumber)
|
||||
* The real portion of the number. Real must be the first
|
||||
* field in this structure.
|
||||
* Imag (RealNumber)
|
||||
* The imaginary portion of the number. This field must follow
|
||||
* immediately after Real.
|
||||
*/
|
||||
|
||||
/* Begin `ComplexNumber'. */
|
||||
|
||||
typedef struct
|
||||
{ RealNumber Real;
|
||||
RealNumber Imag;
|
||||
} ComplexNumber, *ComplexVector;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -427,7 +575,7 @@ extern void * trealloc(const void *, size_t);
|
|||
* NextInCol contains a pointer to the next element in the column below
|
||||
* this element. If this element is the last nonzero in the column then
|
||||
* NextInCol contains NULL.
|
||||
* pInitInfo (void *)
|
||||
* pInitInfo (spGenericPtr)
|
||||
* Pointer to user data used for initialization of the matrix element.
|
||||
* Initialized to NULL.
|
||||
*
|
||||
|
|
@ -442,15 +590,16 @@ extern void * trealloc(const void *, size_t);
|
|||
/* Begin `MatrixElement'. */
|
||||
|
||||
struct MatrixElement
|
||||
{
|
||||
RealNumber Real;
|
||||
{ RealNumber Real;
|
||||
#if spCOMPLEX
|
||||
RealNumber Imag;
|
||||
#endif
|
||||
int Row;
|
||||
int Col;
|
||||
struct MatrixElement *NextInRow;
|
||||
struct MatrixElement *NextInCol;
|
||||
#if INITIALIZE
|
||||
void *pInitInfo;
|
||||
spGenericPtr pInitInfo;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -482,8 +631,7 @@ typedef ElementPtr *ArrayOfElementPtrs;
|
|||
|
||||
/* Begin `AllocationRecord'. */
|
||||
struct AllocationRecord
|
||||
{
|
||||
void *AllocatedPtr;
|
||||
{ void *AllocatedPtr;
|
||||
struct AllocationRecord *NextRecord;
|
||||
};
|
||||
|
||||
|
|
@ -518,21 +666,11 @@ typedef struct AllocationRecord *AllocationListPtr;
|
|||
|
||||
/* Begin `FillinListNodeStruct'. */
|
||||
struct FillinListNodeStruct
|
||||
{
|
||||
ElementPtr pFillinList;
|
||||
{ ElementPtr pFillinList;
|
||||
int NumberOfFillinsInList;
|
||||
struct FillinListNodeStruct *Next;
|
||||
};
|
||||
|
||||
/* Similar to above, but keeps track of the original Elements */
|
||||
/* Begin `ElementListNodeStruct'. */
|
||||
struct ElementListNodeStruct
|
||||
{
|
||||
ElementPtr pElementList;
|
||||
int NumberOfElementsInList;
|
||||
struct ElementListNodeStruct *Next;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -566,7 +704,7 @@ struct ElementListNodeStruct
|
|||
* grow to when EXPANDABLE is set true and AllocatedSize is the largest
|
||||
* the matrix can get without requiring that the matrix frame be
|
||||
* reallocated.
|
||||
* Complex (int)
|
||||
* Complex (BOOLEAN)
|
||||
* The flag which indicates whether the matrix is complex (true) or
|
||||
* real.
|
||||
* CurrentSize (int)
|
||||
|
|
@ -575,18 +713,19 @@ struct ElementListNodeStruct
|
|||
* rows and columns that have elements in them.
|
||||
* Diag (ArrayOfElementPtrs)
|
||||
* Array of pointers that points to the diagonal elements.
|
||||
* DoCmplxDirect (int *)
|
||||
* DoCmplxDirect (BOOLEAN *)
|
||||
* Array of flags, one for each column in matrix. If a flag is true
|
||||
* then corresponding column in a complex matrix should be eliminated
|
||||
* in spFactor() using direct addressing (rather than indirect
|
||||
* addressing).
|
||||
* DoRealDirect (int *)
|
||||
* DoRealDirect (BOOLEAN *)
|
||||
* Array of flags, one for each column in matrix. If a flag is true
|
||||
* then corresponding column in a real matrix should be eliminated
|
||||
* in spFactor() using direct addressing (rather than indirect
|
||||
* addressing).
|
||||
* Elements (int)
|
||||
* The total number of elements present in matrix.
|
||||
* The number of original elements (total elements minus fill ins)
|
||||
* present in matrix.
|
||||
* Error (int)
|
||||
* The error status of the sparse matrix package.
|
||||
* ExtSize (int)
|
||||
|
|
@ -597,7 +736,7 @@ struct ElementListNodeStruct
|
|||
* ExtToIntRowMap (int [])
|
||||
* An array that is used to convert external row numbers to internal
|
||||
* external row numbers. Present only if TRANSLATE option is set true.
|
||||
* Factored (int)
|
||||
* Factored (BOOLEAN)
|
||||
* Indicates if matrix has been factored. This flag is set true in
|
||||
* spFactor() and spOrderAndFactor() and set false in spCreate()
|
||||
* and spClear().
|
||||
|
|
@ -618,8 +757,8 @@ struct ElementListNodeStruct
|
|||
* array used during forward and backward substitution. It is
|
||||
* commonly called y when the forward and backward substitution process is
|
||||
* denoted Ax = b => Ly = b and Ux = y.
|
||||
* InternalVectorsAllocated (int)
|
||||
* A flag that indicates whether the Markowitz vectors and the
|
||||
* InternalVectorsAllocated (BOOLEAN)
|
||||
* A flag that indicates whether theMmarkowitz vectors and the
|
||||
* Intermediate vector have been created.
|
||||
* These vectors are created in spcCreateInternalVectors().
|
||||
* IntToExtColMap (int [])
|
||||
|
|
@ -642,19 +781,16 @@ struct ElementListNodeStruct
|
|||
* The maximum number of off-diagonal element in the rows of L, the
|
||||
* lower triangular matrix. This quantity is used when computing an
|
||||
* estimate of the roundoff error in the matrix.
|
||||
* NeedsOrdering (int)
|
||||
* NeedsOrdering (BOOLEAN)
|
||||
* This is a flag that signifies that the matrix needs to be ordered
|
||||
* or reordered. NeedsOrdering is set true in spCreate() and
|
||||
* spGetElement() or spGetAdmittance() if new elements are added to the
|
||||
* matrix after it has been previously factored. It is set false in
|
||||
* spOrderAndFactor().
|
||||
* NumberOfInterchangesIsOdd (int)
|
||||
* NumberOfInterchangesIsOdd (BOOLEAN)
|
||||
* Flag that indicates the sum of row and column interchange counts
|
||||
* is an odd number. Used when determining the sign of the determinant.
|
||||
* Originals (int)
|
||||
* The number of original elements (total elements minus fill ins)
|
||||
* present in matrix.
|
||||
* Partitioned (int)
|
||||
* Partitioned (BOOLEAN)
|
||||
* This flag indicates that the columns of the matrix have been
|
||||
* partitioned into two groups. Those that will be addressed directly
|
||||
* and those that will be addressed indirectly in spFactor().
|
||||
|
|
@ -664,7 +800,7 @@ struct ElementListNodeStruct
|
|||
* Row pivot was chosen from.
|
||||
* PivotSelectionMethod (char)
|
||||
* Character that indicates which pivot search method was successful.
|
||||
* PreviousMatrixWasComplex (int)
|
||||
* PreviousMatrixWasComplex (BOOLEAN)
|
||||
* This flag in needed to determine how to clear the matrix. When
|
||||
* dealing with real matrices, it is important that the imaginary terms
|
||||
* in the matrix elements be zero. Thus, if the previous matrix was
|
||||
|
|
@ -673,11 +809,11 @@ struct ElementListNodeStruct
|
|||
* RelThreshold (RealNumber)
|
||||
* The magnitude an element must have relative to others in its row
|
||||
* to be considered as a pivot candidate, except as a last resort.
|
||||
* Reordered (int)
|
||||
* Reordered (BOOLEAN)
|
||||
* This flag signifies that the matrix has been reordered. It
|
||||
* is cleared in spCreate(), set in spMNA_Preorder() and
|
||||
* spOrderAndFactor() and is used in spPrint().
|
||||
* RowsLinked (int)
|
||||
* RowsLinked (BOOLEAN)
|
||||
* A flag that indicates whether the row pointers exist. The AddByIndex
|
||||
* routines do not generate the row pointers, which are needed by some
|
||||
* of the other routines, such as spOrderAndFactor() and spScale().
|
||||
|
|
@ -734,44 +870,42 @@ struct ElementListNodeStruct
|
|||
|
||||
/* Begin `MatrixFrame'. */
|
||||
struct MatrixFrame
|
||||
{
|
||||
RealNumber AbsThreshold;
|
||||
{ RealNumber AbsThreshold;
|
||||
int AllocatedSize;
|
||||
int AllocatedExtSize;
|
||||
int Complex;
|
||||
BOOLEAN Complex;
|
||||
int CurrentSize;
|
||||
ArrayOfElementPtrs Diag;
|
||||
int *DoCmplxDirect;
|
||||
int *DoRealDirect;
|
||||
BOOLEAN *DoCmplxDirect;
|
||||
BOOLEAN *DoRealDirect;
|
||||
int Elements;
|
||||
int Error;
|
||||
int ExtSize;
|
||||
int *ExtToIntColMap;
|
||||
int *ExtToIntRowMap;
|
||||
int Factored;
|
||||
BOOLEAN Factored;
|
||||
int Fillins;
|
||||
ArrayOfElementPtrs FirstInCol;
|
||||
ArrayOfElementPtrs FirstInRow;
|
||||
unsigned long ID;
|
||||
RealVector Intermediate;
|
||||
int InternalVectorsAllocated;
|
||||
BOOLEAN InternalVectorsAllocated;
|
||||
int *IntToExtColMap;
|
||||
int *IntToExtRowMap;
|
||||
int *MarkowitzRow;
|
||||
int *MarkowitzCol;
|
||||
long *MarkowitzProd;
|
||||
int MaxRowCountInLowerTri;
|
||||
int NeedsOrdering;
|
||||
int NumberOfInterchangesIsOdd;
|
||||
int Originals;
|
||||
int Partitioned;
|
||||
BOOLEAN NeedsOrdering;
|
||||
BOOLEAN NumberOfInterchangesIsOdd;
|
||||
BOOLEAN Partitioned;
|
||||
int PivotsOriginalCol;
|
||||
int PivotsOriginalRow;
|
||||
char PivotSelectionMethod;
|
||||
int PreviousMatrixWasComplex;
|
||||
BOOLEAN PreviousMatrixWasComplex;
|
||||
RealNumber RelThreshold;
|
||||
int Reordered;
|
||||
int RowsLinked;
|
||||
BOOLEAN Reordered;
|
||||
BOOLEAN RowsLinked;
|
||||
int SingularCol;
|
||||
int SingularRow;
|
||||
int Singletons;
|
||||
|
|
@ -782,29 +916,32 @@ struct MatrixFrame
|
|||
int RecordsRemaining;
|
||||
ElementPtr NextAvailElement;
|
||||
int ElementsRemaining;
|
||||
struct ElementListNodeStruct *FirstElementListNode;
|
||||
struct ElementListNodeStruct *LastElementListNode;
|
||||
ElementPtr NextAvailFillin;
|
||||
int FillinsRemaining;
|
||||
struct FillinListNodeStruct *FirstFillinListNode;
|
||||
struct FillinListNodeStruct *LastFillinListNode;
|
||||
};
|
||||
typedef struct MatrixFrame *MatrixPtr;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Function declarations
|
||||
* Declarations
|
||||
*/
|
||||
|
||||
extern ElementPtr spcGetElement( MatrixPtr );
|
||||
extern ElementPtr spcGetFillin( MatrixPtr );
|
||||
extern ElementPtr spcFindElementInCol( MatrixPtr, ElementPtr*, int, int, int );
|
||||
extern ElementPtr spcCreateElement( MatrixPtr, int, int, ElementPtr*, int );
|
||||
extern void spcCreateInternalVectors( MatrixPtr );
|
||||
extern void spcLinkRows( MatrixPtr );
|
||||
extern void spcColExchange( MatrixPtr, int, int );
|
||||
extern void spcRowExchange( MatrixPtr, int, int );
|
||||
|
||||
void spErrorMessage(MatrixPtr, FILE *, char *);
|
||||
|
||||
#endif
|
||||
spcEXTERN ElementPtr spcGetElement( MatrixPtr );
|
||||
spcEXTERN ElementPtr spcGetFillin( MatrixPtr );
|
||||
spcEXTERN ElementPtr spcFindElementInCol( MatrixPtr, ElementPtr*, int, int, int );
|
||||
spcEXTERN ElementPtr spcFindDiag( MatrixPtr, int );
|
||||
spcEXTERN ElementPtr spcCreateElement( MatrixPtr, int, int,
|
||||
ElementPtr*, ElementPtr*, int );
|
||||
spcEXTERN void spcCreateInternalVectors( MatrixPtr );
|
||||
spcEXTERN void spcLinkRows( MatrixPtr );
|
||||
spcEXTERN void spcColExchange( MatrixPtr, int, int );
|
||||
spcEXTERN void spcRowExchange( MatrixPtr, int, int );
|
||||
|
||||
spcEXTERN char spcMatrixIsNotValid[];
|
||||
spcEXTERN char spcErrorsMustBeCleared[];
|
||||
spcEXTERN char spcMatrixMustBeFactored[];
|
||||
spcEXTERN char spcMatrixMustNotBeFactored[];
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -4,11 +4,19 @@
|
|||
* Author: Advisor:
|
||||
* Kenneth S. Kundert Alberto Sangiovanni-Vincentelli
|
||||
* UC Berkeley
|
||||
*
|
||||
*/
|
||||
/*! \file
|
||||
*
|
||||
* This file contains the output-to-file and output-to-screen routines for
|
||||
* the matrix package.
|
||||
*
|
||||
* >>> User accessible functions contained in this file:
|
||||
* Objects that begin with the \a spc prefix are considered private
|
||||
* and should not be used.
|
||||
*
|
||||
* \author
|
||||
* Kenneth S. Kundert <kundert@users.sourceforge.net>
|
||||
*/
|
||||
/* >>> User accessible functions contained in this file:
|
||||
* spPrint
|
||||
* spFileMatrix
|
||||
* spFileVector
|
||||
|
|
@ -21,19 +29,13 @@
|
|||
/*
|
||||
* Revision and copyright information.
|
||||
*
|
||||
* Copyright (c) 1985,86,87,88,89,90
|
||||
* by Kenneth S. Kundert and the University of California.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the copyright notices appear in all copies and
|
||||
* supporting documentation and that the authors and the University of
|
||||
* California are properly credited. The authors and the University of
|
||||
* California make no representations as to the suitability of this
|
||||
* software for any purpose. It is provided `as is', without express
|
||||
* or implied warranty.
|
||||
* Copyright (c) 1985-2003
|
||||
* by Kenneth S. Kundert
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* IMPORTS
|
||||
*
|
||||
|
|
@ -45,53 +47,44 @@
|
|||
* spDefs.h
|
||||
* Matrix type and macro definitions for the sparse matrix routines.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define spINSIDE_SPARSE
|
||||
#include "spconfig.h"
|
||||
#include <stdio.h>
|
||||
#include "spConfig.h"
|
||||
#include "ngspice/spmatrix.h"
|
||||
#include "spdefs.h"
|
||||
#include "spDefs.h"
|
||||
|
||||
int Printer_Width = PRINTER_WIDTH;
|
||||
|
||||
#include "ngspice/config.h"
|
||||
#ifdef HAS_WINGUI
|
||||
#include "ngspice/wstdio.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if DOCUMENTATION
|
||||
|
||||
/*
|
||||
* PRINT MATRIX
|
||||
*
|
||||
/*!
|
||||
* Formats and send the matrix to standard output. Some elementary
|
||||
* statistics are also output. The matrix is output in a format that is
|
||||
* readable by people.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (char *)
|
||||
* \param eMatrix
|
||||
* Pointer to matrix.
|
||||
* PrintReordered <input> (int)
|
||||
* \param PrintReordered
|
||||
* Indicates whether the matrix should be printed out in its original
|
||||
* form, as input by the user, or whether it should be printed in its
|
||||
* reordered form, as used by the matrix routines. A zero indicates that
|
||||
* the matrix should be printed as inputed, a one indicates that it
|
||||
* should be printed reordered.
|
||||
* Data <input> (int)
|
||||
* Boolean flag that when FALSE indicates that output should be
|
||||
* \param Data
|
||||
* Boolean flag that when false indicates that output should be
|
||||
* compressed such that only the existence of an element should be
|
||||
* indicated rather than giving the actual value. Thus 11 times as
|
||||
* many can be printed on a row. A zero signifies that the matrix
|
||||
* should be printed compressed. A one indicates that the matrix
|
||||
* should be printed in all its glory.
|
||||
* Header <input> (int)
|
||||
* \param Header
|
||||
* Flag indicating that extra information should be given, such as row
|
||||
* and column numbers.
|
||||
*
|
||||
* >>> Local variables:
|
||||
*/
|
||||
/* >>> Local variables:
|
||||
* Col (int)
|
||||
* Column being printed.
|
||||
* ElementCount (int)
|
||||
|
|
@ -135,75 +128,57 @@ int Printer_Width = PRINTER_WIDTH;
|
|||
*/
|
||||
|
||||
void
|
||||
spPrint(MatrixPtr Matrix, int PrintReordered, int Data, int Header)
|
||||
spPrint(
|
||||
spMatrix eMatrix,
|
||||
int PrintReordered,
|
||||
int Data,
|
||||
int Header
|
||||
)
|
||||
{
|
||||
int J = 0;
|
||||
int I, Row, Col, Size, Top;
|
||||
int StartCol = 1, StopCol, Columns, ElementCount = 0;
|
||||
double Magnitude;
|
||||
double SmallestDiag = 0;
|
||||
double SmallestElement = 0;
|
||||
double LargestElement = 0.0, LargestDiag = 0.0;
|
||||
ElementPtr pElement, *pImagElements;
|
||||
int *PrintOrdToIntRowMap, *PrintOrdToIntColMap;
|
||||
MatrixPtr Matrix = (MatrixPtr)eMatrix;
|
||||
register int J = 0;
|
||||
int I, Row, Col, Size, Top, StartCol = 1, StopCol, Columns, ElementCount = 0;
|
||||
double Magnitude, SmallestDiag, SmallestElement;
|
||||
double LargestElement = 0.0, LargestDiag = 0.0;
|
||||
ElementPtr pElement, pImagElements[PRINTER_WIDTH/10+1];
|
||||
int *PrintOrdToIntRowMap, *PrintOrdToIntColMap;
|
||||
|
||||
/* Begin `spPrint'. */
|
||||
assert( IS_SPARSE( Matrix ) );
|
||||
/* Begin `spPrint'. */
|
||||
ASSERT_IS_SPARSE( Matrix );
|
||||
Size = Matrix->Size;
|
||||
SP_CALLOC(pImagElements, ElementPtr, Printer_Width / 10 + 1);
|
||||
if ( pImagElements == NULL)
|
||||
{
|
||||
Matrix->Error = spNO_MEMORY;
|
||||
SP_FREE(pImagElements);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a packed external to internal row and column translation
|
||||
array. */
|
||||
/* Create a packed external to internal row and column translation array. */
|
||||
# if TRANSLATE
|
||||
Top = Matrix->AllocatedExtSize;
|
||||
#else
|
||||
Top = Matrix->AllocatedSize;
|
||||
#endif
|
||||
SP_CALLOC( PrintOrdToIntRowMap, int, Top + 1 );
|
||||
if ( PrintOrdToIntRowMap == NULL)
|
||||
{
|
||||
Matrix->Error = spNO_MEMORY;
|
||||
SP_FREE(pImagElements);
|
||||
return;
|
||||
}
|
||||
SP_CALLOC( PrintOrdToIntColMap, int, Top + 1 );
|
||||
if (PrintOrdToIntColMap == NULL)
|
||||
{
|
||||
Matrix->Error = spNO_MEMORY;
|
||||
SP_FREE(pImagElements);
|
||||
SP_FREE(PrintOrdToIntRowMap);
|
||||
CALLOC( PrintOrdToIntRowMap, int, Top + 1 );
|
||||
CALLOC( PrintOrdToIntColMap, int, Top + 1 );
|
||||
if ( PrintOrdToIntRowMap == NULL OR PrintOrdToIntColMap == NULL)
|
||||
{ Matrix->Error = spNO_MEMORY;
|
||||
return;
|
||||
}
|
||||
for (I = 1; I <= Size; I++)
|
||||
{
|
||||
PrintOrdToIntRowMap[ Matrix->IntToExtRowMap[I] ] = I;
|
||||
{ PrintOrdToIntRowMap[ Matrix->IntToExtRowMap[I] ] = I;
|
||||
PrintOrdToIntColMap[ Matrix->IntToExtColMap[I] ] = I;
|
||||
}
|
||||
|
||||
/* Pack the arrays. */
|
||||
/* Pack the arrays. */
|
||||
for (J = 1, I = 1; I <= Top; I++)
|
||||
{
|
||||
if (PrintOrdToIntRowMap[I] != 0)
|
||||
{ if (PrintOrdToIntRowMap[I] != 0)
|
||||
PrintOrdToIntRowMap[ J++ ] = PrintOrdToIntRowMap[ I ];
|
||||
}
|
||||
for (J = 1, I = 1; I <= Top; I++)
|
||||
{
|
||||
if (PrintOrdToIntColMap[I] != 0)
|
||||
{ if (PrintOrdToIntColMap[I] != 0)
|
||||
PrintOrdToIntColMap[ J++ ] = PrintOrdToIntColMap[ I ];
|
||||
}
|
||||
|
||||
/* Print header. */
|
||||
/* Print header. */
|
||||
if (Header)
|
||||
{
|
||||
printf("MATRIX SUMMARY\n\n");
|
||||
{ printf("MATRIX SUMMARY\n\n");
|
||||
printf("Size of matrix = %1d x %1d.\n", Size, Size);
|
||||
if ( Matrix->Reordered && PrintReordered )
|
||||
if ( Matrix->Reordered AND PrintReordered )
|
||||
printf("Matrix has been reordered.\n");
|
||||
putchar('\n');
|
||||
|
||||
|
|
@ -215,31 +190,31 @@ spPrint(MatrixPtr Matrix, int PrintReordered, int Data, int Header)
|
|||
SmallestElement = LARGEST_REAL;
|
||||
SmallestDiag = SmallestElement;
|
||||
}
|
||||
if (Size == 0) return;
|
||||
|
||||
/* Determine how many columns to use. */
|
||||
Columns = Printer_Width;
|
||||
/* Determine how many columns to use. */
|
||||
Columns = PRINTER_WIDTH;
|
||||
if (Header) Columns -= 5;
|
||||
if (Data) Columns = (Columns+1) / 10;
|
||||
|
||||
/* Print matrix by printing groups of complete columns until all
|
||||
* the columns are printed. */
|
||||
/*
|
||||
* Print matrix by printing groups of complete columns until all the columns
|
||||
* are printed.
|
||||
*/
|
||||
J = 0;
|
||||
while ( J <= Size )
|
||||
{
|
||||
/* Calculatestrchr of last column to printed in this group. */
|
||||
StopCol = StartCol + Columns - 1;
|
||||
|
||||
/* Calculate index of last column to printed in this group. */
|
||||
{ StopCol = StartCol + Columns - 1;
|
||||
if (StopCol > Size)
|
||||
StopCol = Size;
|
||||
|
||||
/* Label the columns. */
|
||||
/* Label the columns. */
|
||||
if (Header)
|
||||
{
|
||||
if (Data)
|
||||
{
|
||||
printf(" ");
|
||||
{ if (Data)
|
||||
{ printf(" ");
|
||||
for (I = StartCol; I <= StopCol; I++)
|
||||
{
|
||||
if (PrintReordered)
|
||||
{ if (PrintReordered)
|
||||
Col = I;
|
||||
else
|
||||
Col = PrintOrdToIntColMap[I];
|
||||
|
|
@ -248,70 +223,64 @@ spPrint(MatrixPtr Matrix, int PrintReordered, int Data, int Header)
|
|||
printf("\n\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PrintReordered)
|
||||
{ if (PrintReordered)
|
||||
printf("Columns %1d to %1d.\n",StartCol,StopCol);
|
||||
else
|
||||
{
|
||||
printf("Columns %1d to %1d.\n",
|
||||
Matrix->IntToExtColMap[ PrintOrdToIntColMap[StartCol] ],
|
||||
Matrix->IntToExtColMap[ PrintOrdToIntColMap[StopCol] ]);
|
||||
{ printf("Columns %1d to %1d.\n",
|
||||
Matrix->IntToExtColMap[ PrintOrdToIntColMap[StartCol] ],
|
||||
Matrix->IntToExtColMap[ PrintOrdToIntColMap[StopCol] ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Print every row ... */
|
||||
/* Print every row ... */
|
||||
for (I = 1; I <= Size; I++)
|
||||
{
|
||||
if (PrintReordered)
|
||||
{ if (PrintReordered)
|
||||
Row = I;
|
||||
else
|
||||
Row = PrintOrdToIntRowMap[I];
|
||||
|
||||
if (Header)
|
||||
{
|
||||
if (PrintReordered && !Data)
|
||||
{ if (PrintReordered AND NOT Data)
|
||||
printf("%4d", I);
|
||||
else
|
||||
printf("%4d", Matrix->IntToExtRowMap[ Row ]);
|
||||
if (!Data) putchar(' ');
|
||||
if (NOT Data) putchar(' ');
|
||||
}
|
||||
|
||||
/* ... in each column of the group. */
|
||||
/* ... in each column of the group. */
|
||||
for (J = StartCol; J <= StopCol; J++)
|
||||
{
|
||||
if (PrintReordered)
|
||||
{ if (PrintReordered)
|
||||
Col = J;
|
||||
else
|
||||
Col = PrintOrdToIntColMap[J];
|
||||
|
||||
pElement = Matrix->FirstInCol[Col];
|
||||
while(pElement != NULL && pElement->Row != Row)
|
||||
while(pElement != NULL AND pElement->Row != Row)
|
||||
pElement = pElement->NextInCol;
|
||||
|
||||
if (Data)
|
||||
pImagElements[J - StartCol] = pElement;
|
||||
|
||||
if (pElement != NULL)
|
||||
{
|
||||
/* Case where element exists */
|
||||
if (Data)
|
||||
printf(" %9.3g", pElement->Real);
|
||||
|
||||
/* Case where element exists */
|
||||
{ if (Data)
|
||||
printf(" %9.3g", (double)pElement->Real);
|
||||
else
|
||||
putchar('x');
|
||||
|
||||
/* Update status variables */
|
||||
/* Update status variables */
|
||||
if ( (Magnitude = ELEMENT_MAG(pElement)) > LargestElement )
|
||||
LargestElement = Magnitude;
|
||||
if ((Magnitude < SmallestElement) && (Magnitude != 0.0))
|
||||
if ((Magnitude < SmallestElement) AND (Magnitude != 0.0))
|
||||
SmallestElement = Magnitude;
|
||||
ElementCount++;
|
||||
}
|
||||
|
||||
/* Case where element is structurally zero */
|
||||
/* Case where element is structurally zero */
|
||||
else
|
||||
{
|
||||
if (Data)
|
||||
{ if (Data)
|
||||
printf(" ...");
|
||||
else
|
||||
putchar('.');
|
||||
|
|
@ -319,68 +288,61 @@ spPrint(MatrixPtr Matrix, int PrintReordered, int Data, int Header)
|
|||
}
|
||||
putchar('\n');
|
||||
|
||||
if (Matrix->Complex && Data)
|
||||
{
|
||||
printf(" ");
|
||||
#if spCOMPLEX
|
||||
if (Matrix->Complex AND Data)
|
||||
{ if (Header)
|
||||
printf(" ");
|
||||
for (J = StartCol; J <= StopCol; J++)
|
||||
{
|
||||
if (pImagElements[J - StartCol] != NULL)
|
||||
{
|
||||
printf(" %8.2gj",
|
||||
pImagElements[J-StartCol]->Imag);
|
||||
{ if (pImagElements[J - StartCol] != NULL)
|
||||
{ printf(" %8.2gj",
|
||||
(double)pImagElements[J-StartCol]->Imag);
|
||||
}
|
||||
else printf(" ");
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
#endif /* spCOMPLEX */
|
||||
}
|
||||
|
||||
/* Calculatestrchr of first column in next group. */
|
||||
/* Calculate index of first column in next group. */
|
||||
StartCol = StopCol;
|
||||
StartCol++;
|
||||
putchar('\n');
|
||||
}
|
||||
if (Header)
|
||||
{
|
||||
printf("\nLargest element in matrix = %-1.4g.\n", LargestElement);
|
||||
{ printf("\nLargest element in matrix = %-1.4g.\n", LargestElement);
|
||||
printf("Smallest element in matrix = %-1.4g.\n", SmallestElement);
|
||||
|
||||
/* Search for largest and smallest diagonal values */
|
||||
/* Search for largest and smallest diagonal values */
|
||||
for (I = 1; I <= Size; I++)
|
||||
{
|
||||
if (Matrix->Diag[I] != NULL)
|
||||
{
|
||||
Magnitude = ELEMENT_MAG( Matrix->Diag[I] );
|
||||
{ if (Matrix->Diag[I] != NULL)
|
||||
{ Magnitude = ELEMENT_MAG( Matrix->Diag[I] );
|
||||
if ( Magnitude > LargestDiag ) LargestDiag = Magnitude;
|
||||
if ( Magnitude < SmallestDiag ) SmallestDiag = Magnitude;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the largest and smallest diagonal values */
|
||||
/* Print the largest and smallest diagonal values */
|
||||
if ( Matrix->Factored )
|
||||
{
|
||||
printf("\nLargest diagonal element = %-1.4g.\n", LargestDiag);
|
||||
{ printf("\nLargest diagonal element = %-1.4g.\n", LargestDiag);
|
||||
printf("Smallest diagonal element = %-1.4g.\n", SmallestDiag);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\nLargest pivot element = %-1.4g.\n", LargestDiag);
|
||||
{ printf("\nLargest pivot element = %-1.4g.\n", LargestDiag);
|
||||
printf("Smallest pivot element = %-1.4g.\n", SmallestDiag);
|
||||
}
|
||||
|
||||
/* Calculate and print sparsity and number of fill-ins created. */
|
||||
printf("\nDensity = %2.2f%%.\n", ((double)(ElementCount * 100)) /
|
||||
((double)(Size * Size)));
|
||||
|
||||
printf("Number of originals = %1d.\n", Matrix->Originals);
|
||||
if (!Matrix->NeedsOrdering)
|
||||
/* Calculate and print sparsity and number of fill-ins created. */
|
||||
printf("\nDensity = %2.2f%%.\n", ((double)ElementCount * 100.0)
|
||||
/ (((double)Size * (double)Size)));
|
||||
if (NOT Matrix->NeedsOrdering)
|
||||
printf("Number of fill-ins = %1d.\n", Matrix->Fillins);
|
||||
}
|
||||
putchar('\n');
|
||||
(void)fflush(stdout);
|
||||
|
||||
SP_FREE(PrintOrdToIntColMap);
|
||||
SP_FREE(PrintOrdToIntRowMap);
|
||||
FREE(PrintOrdToIntColMap);
|
||||
FREE(PrintOrdToIntRowMap);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -394,36 +356,33 @@ spPrint(MatrixPtr Matrix, int PrintReordered, int Data, int Header)
|
|||
|
||||
|
||||
|
||||
/*
|
||||
* OUTPUT MATRIX TO FILE
|
||||
*
|
||||
/*!
|
||||
* Writes matrix to file in format suitable to be read back in by the
|
||||
* matrix test program.
|
||||
*
|
||||
* >>> Returns:
|
||||
* \return
|
||||
* One is returned if routine was successful, otherwise zero is returned.
|
||||
* The calling function can query errno (the system global error variable)
|
||||
* The calling function can query \a errno (the system global error variable)
|
||||
* as to the reason why this routine failed.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (char *)
|
||||
* \param eMatrix
|
||||
* Pointer to matrix.
|
||||
* File <input> (char *)
|
||||
* \param File
|
||||
* Name of file into which matrix is to be written.
|
||||
* Label <input> (char *)
|
||||
* \param Label
|
||||
* String that is transferred to file and is used as a label.
|
||||
* Reordered <input> (int)
|
||||
* \param Reordered
|
||||
* Specifies whether matrix should be output in reordered form,
|
||||
* or in original order.
|
||||
* Data <input> (int)
|
||||
* \param Data
|
||||
* Indicates that the element values should be output along with
|
||||
* the indices for each element. This parameter must be TRUE if
|
||||
* the indices for each element. This parameter must be true if
|
||||
* matrix is to be read by the sparse test program.
|
||||
* Header <input> (int)
|
||||
* Indicates that header is desired. This parameter must be TRUE if
|
||||
* \param Header
|
||||
* Indicates that header is desired. This parameter must be true if
|
||||
* matrix is to be read by the sparse test program.
|
||||
*
|
||||
* >>> Local variables:
|
||||
*/
|
||||
/* >>> Local variables:
|
||||
* Col (int)
|
||||
* The original column number of the element being output.
|
||||
* pElement (ElementPtr)
|
||||
|
|
@ -437,123 +396,118 @@ spPrint(MatrixPtr Matrix, int PrintReordered, int Data, int Header)
|
|||
*/
|
||||
|
||||
int
|
||||
spFileMatrix(MatrixPtr Matrix, char *File, char *Label, int Reordered,
|
||||
int Data, int Header)
|
||||
spFileMatrix(
|
||||
spMatrix eMatrix,
|
||||
char *File,
|
||||
char *Label,
|
||||
int Reordered,
|
||||
int Data,
|
||||
int Header
|
||||
)
|
||||
{
|
||||
int I, Size;
|
||||
ElementPtr pElement;
|
||||
int Row, Col, Err;
|
||||
FILE *pMatrixFile;
|
||||
MatrixPtr Matrix = (MatrixPtr)eMatrix;
|
||||
register int I, Size;
|
||||
register ElementPtr pElement;
|
||||
int Row, Col, Err;
|
||||
FILE *pMatrixFile;
|
||||
|
||||
/* Begin `spFileMatrix'. */
|
||||
assert( IS_SPARSE( Matrix ) );
|
||||
/* Begin `spFileMatrix'. */
|
||||
ASSERT_IS_SPARSE( Matrix );
|
||||
|
||||
/* Open file matrix file in write mode. */
|
||||
/* Open file matrix file in write mode. */
|
||||
if ((pMatrixFile = fopen(File, "w")) == NULL)
|
||||
return 0;
|
||||
|
||||
/* Output header. */
|
||||
/* Output header. */
|
||||
Size = Matrix->Size;
|
||||
if (Header)
|
||||
{
|
||||
if (Matrix->Factored && Data)
|
||||
{
|
||||
Err = fprintf(pMatrixFile,
|
||||
"Warning : The following matrix is "
|
||||
"factored in to LU form.\n");
|
||||
if (Err < 0)
|
||||
return 0;
|
||||
{ if (Matrix->Factored AND Data)
|
||||
{ Err = fprintf
|
||||
( pMatrixFile,
|
||||
"Warning : The following matrix is factored in to LU form.\n"
|
||||
);
|
||||
if (Err < 0) return 0;
|
||||
}
|
||||
if (fprintf(pMatrixFile, "%s\n", Label) < 0)
|
||||
return 0;
|
||||
if (fprintf(pMatrixFile, "%s\n", Label) < 0) return 0;
|
||||
Err = fprintf( pMatrixFile, "%d\t%s\n", Size,
|
||||
(Matrix->Complex ? "complex" : "real"));
|
||||
if (Err < 0)
|
||||
return 0;
|
||||
(Matrix->Complex ? "complex" : "real"));
|
||||
if (Err < 0) return 0;
|
||||
}
|
||||
if (Size == 0) return 1;
|
||||
|
||||
/* Output matrix. */
|
||||
if (!Data)
|
||||
{
|
||||
for (I = 1; I <= Size; I++)
|
||||
{
|
||||
pElement = Matrix->FirstInCol[I];
|
||||
/* Output matrix. */
|
||||
if (NOT Data)
|
||||
{ for (I = 1; I <= Size; I++)
|
||||
{ pElement = Matrix->FirstInCol[I];
|
||||
while (pElement != NULL)
|
||||
{
|
||||
if (Reordered)
|
||||
{
|
||||
Row = pElement->Row;
|
||||
{ if (Reordered)
|
||||
{ Row = pElement->Row;
|
||||
Col = I;
|
||||
}
|
||||
else
|
||||
{
|
||||
Row = Matrix->IntToExtRowMap[pElement->Row];
|
||||
{ Row = Matrix->IntToExtRowMap[pElement->Row];
|
||||
Col = Matrix->IntToExtColMap[I];
|
||||
}
|
||||
pElement = pElement->NextInCol;
|
||||
if (fprintf(pMatrixFile, "%d\t%d\n", Row, Col) < 0) return 0;
|
||||
}
|
||||
}
|
||||
/* Output terminator, a line of zeros. */
|
||||
/* Output terminator, a line of zeros. */
|
||||
if (Header)
|
||||
if (fprintf(pMatrixFile, "0\t0\n") < 0) return 0;
|
||||
}
|
||||
|
||||
if (Data && Matrix->Complex)
|
||||
{
|
||||
for (I = 1; I <= Size; I++)
|
||||
{
|
||||
pElement = Matrix->FirstInCol[I];
|
||||
#if spCOMPLEX
|
||||
if (Data AND Matrix->Complex)
|
||||
{ for (I = 1; I <= Size; I++)
|
||||
{ pElement = Matrix->FirstInCol[I];
|
||||
while (pElement != NULL)
|
||||
{
|
||||
if (Reordered)
|
||||
{
|
||||
Row = pElement->Row;
|
||||
{ if (Reordered)
|
||||
{ Row = pElement->Row;
|
||||
Col = I;
|
||||
}
|
||||
else
|
||||
{
|
||||
Row = Matrix->IntToExtRowMap[pElement->Row];
|
||||
{ Row = Matrix->IntToExtRowMap[pElement->Row];
|
||||
Col = Matrix->IntToExtColMap[I];
|
||||
}
|
||||
Err = fprintf
|
||||
( pMatrixFile,"%d\t%d\t%-.15g\t%-.15g\n",
|
||||
Row, Col, pElement->Real, pElement->Imag
|
||||
);
|
||||
( pMatrixFile,"%d\t%d\t%-.15g\t%-.15g\n",
|
||||
Row, Col, (double)pElement->Real, (double)pElement->Imag
|
||||
);
|
||||
if (Err < 0) return 0;
|
||||
pElement = pElement->NextInCol;
|
||||
}
|
||||
}
|
||||
/* Output terminator, a line of zeros. */
|
||||
/* Output terminator, a line of zeros. */
|
||||
if (Header)
|
||||
if (fprintf(pMatrixFile,"0\t0\t0.0\t0.0\n") < 0) return 0;
|
||||
|
||||
}
|
||||
#endif /* spCOMPLEX */
|
||||
|
||||
if (Data && !Matrix->Complex)
|
||||
{
|
||||
for (I = 1; I <= Size; I++)
|
||||
{
|
||||
pElement = Matrix->FirstInCol[I];
|
||||
#if REAL
|
||||
if (Data AND NOT Matrix->Complex)
|
||||
{ for (I = 1; I <= Size; I++)
|
||||
{ pElement = Matrix->FirstInCol[I];
|
||||
while (pElement != NULL)
|
||||
{
|
||||
Row = Matrix->IntToExtRowMap[pElement->Row];
|
||||
{ Row = Matrix->IntToExtRowMap[pElement->Row];
|
||||
Col = Matrix->IntToExtColMap[I];
|
||||
Err = fprintf
|
||||
( pMatrixFile,"%d\t%d\t%-.15g\n",
|
||||
Row, Col, pElement->Real
|
||||
);
|
||||
( pMatrixFile,"%d\t%d\t%-.15g\n",
|
||||
Row, Col, (double)pElement->Real
|
||||
);
|
||||
if (Err < 0) return 0;
|
||||
pElement = pElement->NextInCol;
|
||||
}
|
||||
}
|
||||
/* Output terminator, a line of zeros. */
|
||||
/* Output terminator, a line of zeros. */
|
||||
if (Header)
|
||||
if (fprintf(pMatrixFile,"0\t0\t0.0\n") < 0) return 0;
|
||||
|
||||
}
|
||||
#endif /* REAL */
|
||||
|
||||
/* Close file. */
|
||||
/* Close file. */
|
||||
if (fclose(pMatrixFile) < 0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -564,79 +518,117 @@ spFileMatrix(MatrixPtr Matrix, char *File, char *Label, int Reordered,
|
|||
|
||||
|
||||
|
||||
/*
|
||||
* OUTPUT SOURCE VECTOR TO FILE
|
||||
*
|
||||
/*!
|
||||
* Writes vector to file in format suitable to be read back in by the
|
||||
* matrix test program. This routine should be executed after the function
|
||||
* spFileMatrix.
|
||||
*
|
||||
* >>> Returns:
|
||||
* \return
|
||||
* One is returned if routine was successful, otherwise zero is returned.
|
||||
* The calling function can query errno (the system global error variable)
|
||||
* The calling function can query \a errno (the system global error variable)
|
||||
* as to the reason why this routine failed.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (char *)
|
||||
* \param eMatrix
|
||||
* Pointer to matrix.
|
||||
* File <input> (char *)
|
||||
* \param File
|
||||
* Name of file into which matrix is to be written.
|
||||
* RHS <input> (RealNumber [])
|
||||
* Right-hand side vector, real portion
|
||||
* iRHS <input> (RealNumber [])
|
||||
* Right-hand side vector, imaginary portion.
|
||||
*
|
||||
* >>> Local variables:
|
||||
* \param RHS
|
||||
* Right-hand side vector. This is only the real portion if
|
||||
* \a spSEPARATED_COMPLEX_VECTORS is true.
|
||||
* \param iRHS
|
||||
* Right-hand side vector, imaginary portion. Not necessary if matrix
|
||||
* is real or if \a spSEPARATED_COMPLEX_VECTORS is set false.
|
||||
* \a iRHS is a macro that replaces itself with `, iRHS' if the options
|
||||
* \a spCOMPLEX and \a spSEPARATED_COMPLEX_VECTORS are set, otherwise
|
||||
* it disappears without a trace.
|
||||
*/
|
||||
/* >>> Local variables:
|
||||
* pMatrixFile (FILE *)
|
||||
* File pointer to the matrix file.
|
||||
* Size (int)
|
||||
* The size of the matrix.
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
spFileVector(MatrixPtr Matrix, char *File, RealVector RHS, RealVector iRHS)
|
||||
spFileVector(
|
||||
spMatrix eMatrix,
|
||||
char *File,
|
||||
spREAL RHS[]
|
||||
#if spCOMPLEX AND spSEPARATED_COMPLEX_VECTORS
|
||||
, spREAL iRHS[]
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int I, Size, Err;
|
||||
FILE *pMatrixFile;
|
||||
MatrixPtr Matrix = (MatrixPtr)eMatrix;
|
||||
register int I, Size, Err;
|
||||
FILE *pMatrixFile;
|
||||
|
||||
/* Begin `spFileVector'. */
|
||||
assert( IS_SPARSE( Matrix ) && RHS != NULL);
|
||||
/* Begin `spFileVector'. */
|
||||
ASSERT_IS_SPARSE( Matrix );
|
||||
vASSERT( RHS != NULL, "Vector missing" );
|
||||
|
||||
if (File) {
|
||||
/* Open File in write mode. */
|
||||
pMatrixFile = fopen(File,"w");
|
||||
if (pMatrixFile == NULL)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
pMatrixFile=stdout;
|
||||
/* Open File in append mode. */
|
||||
if ((pMatrixFile = fopen(File,"a")) == NULL)
|
||||
return 0;
|
||||
|
||||
/* Output vector. */
|
||||
Size = Matrix->Size;
|
||||
/* Correct array pointers for ARRAY_OFFSET. */
|
||||
#if NOT ARRAY_OFFSET
|
||||
#if spCOMPLEX
|
||||
if (Matrix->Complex)
|
||||
{
|
||||
for (I = 1; I <= Size; I++)
|
||||
{
|
||||
Err = fprintf
|
||||
( pMatrixFile, "%-.15g\t%-.15g\n",
|
||||
RHS[I], iRHS[I]
|
||||
);
|
||||
if (Err < 0) return 0;
|
||||
}
|
||||
#if spSEPARATED_COMPLEX_VECTORS
|
||||
vASSERT( iRHS != NULL, "Imaginary vector missing" );
|
||||
--RHS;
|
||||
--iRHS;
|
||||
#else
|
||||
RHS -= 2;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif /* spCOMPLEX */
|
||||
--RHS;
|
||||
#endif /* NOT ARRAY_OFFSET */
|
||||
|
||||
|
||||
/* Output vector. */
|
||||
Size = Matrix->Size;
|
||||
if (Size == 0) return 1;
|
||||
|
||||
#if spCOMPLEX
|
||||
if (Matrix->Complex)
|
||||
{
|
||||
for (I = 1; I <= Size; I++)
|
||||
{
|
||||
if (fprintf(pMatrixFile, "%-.15g\n", RHS[I]) < 0)
|
||||
#if spSEPARATED_COMPLEX_VECTORS
|
||||
for (I = 1; I <= Size; I++)
|
||||
{ Err = fprintf
|
||||
( pMatrixFile, "%-.15g\t%-.15g\n",
|
||||
(double)RHS[I], (double)iRHS[I]
|
||||
);
|
||||
if (Err < 0) return 0;
|
||||
}
|
||||
#else
|
||||
for (I = 1; I <= Size; I++)
|
||||
{ Err = fprintf
|
||||
( pMatrixFile, "%-.15g\t%-.15g\n",
|
||||
(double)RHS[2*I], (double)RHS[2*I+1]
|
||||
);
|
||||
if (Err < 0) return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* spCOMPLEX */
|
||||
#if REAL AND spCOMPLEX
|
||||
else
|
||||
#endif
|
||||
#if REAL
|
||||
{ for (I = 1; I <= Size; I++)
|
||||
{ if (fprintf(pMatrixFile, "%-.15g\n", (double)RHS[I]) < 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif /* REAL */
|
||||
|
||||
/* Close file. */
|
||||
if (File)
|
||||
if (fclose(pMatrixFile) < 0) return 0;
|
||||
/* Close file. */
|
||||
if (fclose(pMatrixFile) < 0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -648,26 +640,23 @@ spFileVector(MatrixPtr Matrix, char *File, RealVector RHS, RealVector iRHS)
|
|||
|
||||
|
||||
|
||||
/*
|
||||
* OUTPUT STATISTICS TO FILE
|
||||
*
|
||||
/*!
|
||||
* Writes useful information concerning the matrix to a file. Should be
|
||||
* executed after the matrix is factored.
|
||||
*
|
||||
* >>> Returns:
|
||||
* \return
|
||||
* One is returned if routine was successful, otherwise zero is returned.
|
||||
* The calling function can query errno (the system global error variable)
|
||||
* The calling function can query \a errno (the system global error variable)
|
||||
* as to the reason why this routine failed.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (char *)
|
||||
* \param eMatrix
|
||||
* Pointer to matrix.
|
||||
* File <input> (char *)
|
||||
* \param File
|
||||
* Name of file into which matrix is to be written.
|
||||
* Label <input> (char *)
|
||||
* \param Label
|
||||
* String that is transferred to file and is used as a label.
|
||||
*
|
||||
* >>> Local variables:
|
||||
*/
|
||||
/* >>> Local variables:
|
||||
* Data (RealNumber)
|
||||
* The value of the matrix element being output.
|
||||
* LargestElement (RealNumber)
|
||||
|
|
@ -685,24 +674,29 @@ spFileVector(MatrixPtr Matrix, char *File, RealVector RHS, RealVector iRHS)
|
|||
*/
|
||||
|
||||
int
|
||||
spFileStats(MatrixPtr Matrix, char *File, char *Label)
|
||||
spFileStats(
|
||||
spMatrix eMatrix,
|
||||
char *File,
|
||||
char *Label
|
||||
)
|
||||
{
|
||||
int Size, I;
|
||||
ElementPtr pElement;
|
||||
int NumberOfElements;
|
||||
RealNumber Data, LargestElement, SmallestElement;
|
||||
FILE *pStatsFile;
|
||||
MatrixPtr Matrix = (MatrixPtr)eMatrix;
|
||||
register int Size, I;
|
||||
register ElementPtr pElement;
|
||||
int NumberOfElements;
|
||||
RealNumber Data, LargestElement, SmallestElement;
|
||||
FILE *pStatsFile;
|
||||
|
||||
/* Begin `spFileStats'. */
|
||||
assert( IS_SPARSE( Matrix ) );
|
||||
/* Begin `spFileStats'. */
|
||||
ASSERT_IS_SPARSE( Matrix );
|
||||
|
||||
/* Open File in append mode. */
|
||||
/* Open File in append mode. */
|
||||
if ((pStatsFile = fopen(File, "a")) == NULL)
|
||||
return 0;
|
||||
|
||||
/* Output statistics. */
|
||||
/* Output statistics. */
|
||||
Size = Matrix->Size;
|
||||
if (!Matrix->Factored)
|
||||
if (NOT Matrix->Factored)
|
||||
fprintf(pStatsFile, "Matrix has not been factored.\n");
|
||||
fprintf(pStatsFile, "||| Starting new matrix |||\n");
|
||||
fprintf(pStatsFile, "%s\n", Label);
|
||||
|
|
@ -711,22 +705,21 @@ spFileStats(MatrixPtr Matrix, char *File, char *Label)
|
|||
else
|
||||
fprintf(pStatsFile, "Matrix is real.\n");
|
||||
fprintf(pStatsFile," Size = %d\n",Size);
|
||||
if (Size == 0) return 1;
|
||||
|
||||
/* Search matrix. */
|
||||
/* Search matrix. */
|
||||
NumberOfElements = 0;
|
||||
LargestElement = 0.0;
|
||||
SmallestElement = LARGEST_REAL;
|
||||
|
||||
for (I = 1; I <= Size; I++)
|
||||
{
|
||||
pElement = Matrix->FirstInCol[I];
|
||||
{ pElement = Matrix->FirstInCol[I];
|
||||
while (pElement != NULL)
|
||||
{
|
||||
NumberOfElements++;
|
||||
{ NumberOfElements++;
|
||||
Data = ELEMENT_MAG(pElement);
|
||||
if (Data > LargestElement)
|
||||
LargestElement = Data;
|
||||
if (Data < SmallestElement && Data != 0.0)
|
||||
if (Data < SmallestElement AND Data != 0.0)
|
||||
SmallestElement = Data;
|
||||
pElement = pElement->NextInCol;
|
||||
}
|
||||
|
|
@ -734,7 +727,7 @@ spFileStats(MatrixPtr Matrix, char *File, char *Label)
|
|||
|
||||
SmallestElement = MIN( SmallestElement, LargestElement );
|
||||
|
||||
/* Output remaining statistics. */
|
||||
/* Output remaining statistics. */
|
||||
fprintf(pStatsFile, " Initial number of elements = %d\n",
|
||||
NumberOfElements - Matrix->Fillins);
|
||||
fprintf(pStatsFile,
|
||||
|
|
@ -748,13 +741,13 @@ spFileStats(MatrixPtr Matrix, char *File, char *Label)
|
|||
fprintf(pStatsFile, " Average number of elements per row = %f\n",
|
||||
(double)NumberOfElements / (double)Size);
|
||||
fprintf(pStatsFile," Density = %f%%\n",
|
||||
(double)(100.0*NumberOfElements)/(double)(Size*Size));
|
||||
(100.0*(double)NumberOfElements)/((double)Size*(double)Size));
|
||||
fprintf(pStatsFile," Relative Threshold = %e\n", Matrix->RelThreshold);
|
||||
fprintf(pStatsFile," Absolute Threshold = %e\n", Matrix->AbsThreshold);
|
||||
fprintf(pStatsFile," Largest Element = %e\n", LargestElement);
|
||||
fprintf(pStatsFile," Smallest Element = %e\n\n\n", SmallestElement);
|
||||
|
||||
/* Close file. */
|
||||
/* Close file. */
|
||||
(void)fclose(pStatsFile);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -5,11 +5,14 @@
|
|||
* Kenneth S. Kundert Alberto Sangiovanni-Vincentelli
|
||||
* UC Berkeley
|
||||
*
|
||||
* This module contains routines that make Sparse1.3 a direct
|
||||
* replacement for the SMP sparse matrix package in Spice3c1 or Spice3d1.
|
||||
* Sparse1.3 is in general a faster and more robust package than SMP.
|
||||
* This module contains routines that make Sparse1.4 a direct
|
||||
* replacement for the SMP sparse matrix package in Spice3c1 and Spice3d1.
|
||||
* Sparse1.4 is in general a faster and more robust package than SMP.
|
||||
* These advantages become significant on large circuits.
|
||||
*
|
||||
* This module is provided for convience only. It has not been tested
|
||||
* with the recent version of Spice3 and is not supported.
|
||||
*
|
||||
* >>> User accessible functions contained in this file:
|
||||
* SMPaddElt
|
||||
* SMPmakeElt
|
||||
|
|
@ -29,8 +32,6 @@
|
|||
* SMPprint
|
||||
* SMPgetError
|
||||
* SMPcProdDiag
|
||||
* LoadGmin
|
||||
* SMPfindElt
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -45,10 +46,12 @@
|
|||
* To be compatible with SPICE, the following Sparse compiler options
|
||||
* (in spConfig.h) should be set as shown below:
|
||||
*
|
||||
* REAL YES
|
||||
* EXPANDABLE YES
|
||||
* TRANSLATE NO
|
||||
* INITIALIZE NO or YES, YES for use with test prog.
|
||||
* DIAGONAL_PIVOTING YES
|
||||
* ARRAY_OFFSET YES
|
||||
* MODIFIED_MARKOWITZ NO
|
||||
* DELETE NO
|
||||
* STRIP NO
|
||||
|
|
@ -62,7 +65,10 @@
|
|||
* STABILITY NO
|
||||
* CONDITION NO
|
||||
* PSEUDOCONDITION NO
|
||||
* FORTRAN NO
|
||||
* DEBUG YES
|
||||
* spCOMPLEX 1
|
||||
* spSEPARATED_COMPLEX_VECTORS 1
|
||||
*
|
||||
* spREAL double
|
||||
*/
|
||||
|
|
@ -70,18 +76,10 @@
|
|||
/*
|
||||
* Revision and copyright information.
|
||||
*
|
||||
* Copyright (c) 1985,86,87,88,89,90
|
||||
* by Kenneth S. Kundert and the University of California.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted, provided
|
||||
* that the above copyright notice appear in all copies and supporting
|
||||
* documentation and that the authors and the University of California
|
||||
* are properly credited. The authors and the University of California
|
||||
* make no representations as to the suitability of this software for
|
||||
* any purpose. It is provided `as is', without express or implied warranty.
|
||||
* Copyright (c) 1985-2003 by Kenneth S. Kundert
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* IMPORTS
|
||||
*
|
||||
|
|
@ -92,73 +90,71 @@
|
|||
* Spice3's matrix macro definitions.
|
||||
*/
|
||||
|
||||
#include "ngspice/config.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "ngspice/spmatrix.h"
|
||||
#include "spdefs.h"
|
||||
#include "ngspice/smpdefs.h"
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
extern double scalbn(double, int);
|
||||
#define logb _logb
|
||||
extern double logb(double);
|
||||
#endif
|
||||
#define NO 0
|
||||
#define YES 1
|
||||
|
||||
static void LoadGmin(SMPmatrix *Matrix, double Gmin);
|
||||
typedef spREAL RealNumber, *RealVector;
|
||||
|
||||
static void LoadGmin(char *Matrix, double Gmin);
|
||||
|
||||
/*
|
||||
* SMPaddElt()
|
||||
*/
|
||||
int
|
||||
SMPaddElt(SMPmatrix *Matrix, int Row, int Col, double Value)
|
||||
SMPaddElt( Matrix, Row, Col, Value )
|
||||
SMPmatrix *Matrix;
|
||||
int Row, Col;
|
||||
double Value;
|
||||
{
|
||||
*spGetElement( Matrix, Row, Col ) = Value;
|
||||
return spError( Matrix );
|
||||
*spGetElement( (char *)Matrix, Row, Col ) = Value;
|
||||
return spErrorState( (char *)Matrix );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPmakeElt()
|
||||
*/
|
||||
double *
|
||||
SMPmakeElt(SMPmatrix *Matrix, int Row, int Col)
|
||||
SMPmakeElt( Matrix, Row, Col )
|
||||
SMPmatrix *Matrix;
|
||||
int Row, Col;
|
||||
{
|
||||
return spGetElement( Matrix, Row, Col );
|
||||
return spGetElement( (char *)Matrix, Row, Col );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPcClear()
|
||||
*/
|
||||
void
|
||||
SMPcClear(SMPmatrix *Matrix)
|
||||
SMPcClear( Matrix )
|
||||
SMPmatrix *Matrix;
|
||||
{
|
||||
spClear( Matrix );
|
||||
spClear( (char *)Matrix );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPclear()
|
||||
*/
|
||||
void
|
||||
SMPclear(SMPmatrix *Matrix)
|
||||
SMPclear( Matrix )
|
||||
SMPmatrix *Matrix;
|
||||
{
|
||||
spClear( Matrix );
|
||||
spClear( (char *)Matrix );
|
||||
}
|
||||
|
||||
#define NG_IGNORE(x) (void)x
|
||||
|
||||
/*
|
||||
* SMPcLUfac()
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
SMPcLUfac(SMPmatrix *Matrix, double PivTol)
|
||||
SMPcLUfac( Matrix, PivTol )
|
||||
SMPmatrix *Matrix;
|
||||
double PivTol;
|
||||
{
|
||||
NG_IGNORE(PivTol);
|
||||
|
||||
spSetComplex( Matrix );
|
||||
return spFactor( Matrix );
|
||||
spSetComplex( (char *)Matrix );
|
||||
return spFactor( (char *)Matrix );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -166,93 +162,97 @@ SMPcLUfac(SMPmatrix *Matrix, double PivTol)
|
|||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
SMPluFac(SMPmatrix *Matrix, double PivTol, double Gmin)
|
||||
SMPluFac( Matrix, PivTol, Gmin )
|
||||
SMPmatrix *Matrix;
|
||||
double PivTol, Gmin;
|
||||
{
|
||||
NG_IGNORE(PivTol);
|
||||
spSetReal( Matrix );
|
||||
LoadGmin( Matrix, Gmin );
|
||||
return spFactor( Matrix );
|
||||
spSetReal( (char *)Matrix );
|
||||
LoadGmin( (char *)Matrix, Gmin );
|
||||
return spFactor( (char *)Matrix );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPcReorder()
|
||||
*/
|
||||
int
|
||||
SMPcReorder(SMPmatrix *Matrix, double PivTol, double PivRel,
|
||||
int *NumSwaps)
|
||||
SMPcReorder( Matrix, PivTol, PivRel, NumSwaps )
|
||||
SMPmatrix *Matrix;
|
||||
double PivTol, PivRel;
|
||||
int *NumSwaps;
|
||||
{
|
||||
*NumSwaps = 1;
|
||||
spSetComplex( Matrix );
|
||||
return spOrderAndFactor( Matrix, NULL,
|
||||
PivRel, PivTol, YES );
|
||||
*NumSwaps = 0;
|
||||
spSetComplex( (char *)Matrix );
|
||||
return spOrderAndFactor( (char *)Matrix, (spREAL*)NULL,
|
||||
(spREAL)PivRel, (spREAL)PivTol, YES );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPreorder()
|
||||
*/
|
||||
int
|
||||
SMPreorder(SMPmatrix *Matrix, double PivTol, double PivRel, double Gmin)
|
||||
SMPreorder( Matrix, PivTol, PivRel, Gmin )
|
||||
SMPmatrix *Matrix;
|
||||
double PivTol, PivRel, Gmin;
|
||||
{
|
||||
spSetReal( Matrix );
|
||||
LoadGmin( Matrix, Gmin );
|
||||
return spOrderAndFactor( Matrix, NULL,
|
||||
PivRel, PivTol, YES );
|
||||
spSetComplex( (char *)Matrix );
|
||||
LoadGmin( (char *)Matrix, Gmin );
|
||||
return spOrderAndFactor( (char *)Matrix, (spREAL*)NULL,
|
||||
(spREAL)PivRel, (spREAL)PivTol, YES );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPcaSolve()
|
||||
*/
|
||||
void
|
||||
SMPcaSolve(SMPmatrix *Matrix, double RHS[], double iRHS[],
|
||||
double Spare[], double iSpare[])
|
||||
SMPcaSolve( Matrix, RHS, iRHS, Spare, iSpare)
|
||||
SMPmatrix *Matrix;
|
||||
double RHS[], iRHS[], Spare[], iSpare[];
|
||||
{
|
||||
NG_IGNORE(iSpare);
|
||||
NG_IGNORE(Spare);
|
||||
|
||||
spSolveTransposed( Matrix, RHS, RHS, iRHS, iRHS );
|
||||
spSolveTransposed( (char *)Matrix, RHS, RHS, iRHS, iRHS );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPcSolve()
|
||||
*/
|
||||
void
|
||||
SMPcSolve(SMPmatrix *Matrix, double RHS[], double iRHS[],
|
||||
double Spare[], double iSpare[])
|
||||
SMPcSolve( Matrix, RHS, iRHS, Spare, iSpare)
|
||||
SMPmatrix *Matrix;
|
||||
double RHS[], iRHS[], Spare[], iSpare[];
|
||||
{
|
||||
NG_IGNORE(iSpare);
|
||||
NG_IGNORE(Spare);
|
||||
|
||||
spSolve( Matrix, RHS, RHS, iRHS, iRHS );
|
||||
spSolve( (char *)Matrix, RHS, RHS, iRHS, iRHS );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPsolve()
|
||||
*/
|
||||
void
|
||||
SMPsolve(SMPmatrix *Matrix, double RHS[], double Spare[])
|
||||
SMPsolve( Matrix, RHS, Spare )
|
||||
SMPmatrix *Matrix;
|
||||
double RHS[], Spare[];
|
||||
{
|
||||
NG_IGNORE(Spare);
|
||||
|
||||
spSolve( Matrix, RHS, RHS, NULL, NULL );
|
||||
spSolve( (char *)Matrix, RHS, RHS, (spREAL*)NULL, (spREAL*)NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPmatSize()
|
||||
*/
|
||||
int
|
||||
SMPmatSize(SMPmatrix *Matrix)
|
||||
SMPmatSize( Matrix )
|
||||
SMPmatrix *Matrix;
|
||||
{
|
||||
return spGetSize( Matrix, 1 );
|
||||
return spGetSize( (char *)Matrix, 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPnewMatrix()
|
||||
*/
|
||||
int
|
||||
SMPnewMatrix(SMPmatrix **pMatrix, int size)
|
||||
SMPnewMatrix( pMatrix, dummy )
|
||||
SMPmatrix **pMatrix;
|
||||
int dummy;
|
||||
{
|
||||
int Error;
|
||||
*pMatrix = spCreate( size, 1, &Error );
|
||||
int Error;
|
||||
*pMatrix = (SMPmatrix *)spCreate( 0, 1, &Error );
|
||||
return Error;
|
||||
}
|
||||
|
||||
|
|
@ -260,63 +260,67 @@ SMPnewMatrix(SMPmatrix **pMatrix, int size)
|
|||
* SMPdestroy()
|
||||
*/
|
||||
void
|
||||
SMPdestroy(SMPmatrix *Matrix)
|
||||
SMPdestroy( Matrix )
|
||||
SMPmatrix *Matrix;
|
||||
{
|
||||
spDestroy( Matrix );
|
||||
spDestroy( (char *)Matrix );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPpreOrder()
|
||||
*/
|
||||
int
|
||||
SMPpreOrder(SMPmatrix *Matrix)
|
||||
SMPpreOrder( Matrix )
|
||||
SMPmatrix *Matrix;
|
||||
{
|
||||
spMNA_Preorder( Matrix );
|
||||
return spError( Matrix );
|
||||
spMNA_Preorder( (char *)Matrix );
|
||||
return spErrorState( (char *)Matrix );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPprint()
|
||||
* SMPprintRHS()
|
||||
*/
|
||||
|
||||
void
|
||||
SMPprintRHS(SMPmatrix *Matrix, char *Filename, RealVector RHS, RealVector iRHS)
|
||||
{
|
||||
spFileVector( Matrix, Filename, RHS, iRHS );
|
||||
spFileVector( Matrix, Filename, RHS, iRHS );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPprint()
|
||||
*/
|
||||
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
SMPprint(SMPmatrix *Matrix, char *Filename)
|
||||
SMPprint( Matrix, File )
|
||||
SMPmatrix *Matrix;
|
||||
char *File;
|
||||
{
|
||||
if (Filename)
|
||||
spFileMatrix(Matrix, Filename, "Circuit Matrix", 0, 1, 1 );
|
||||
else
|
||||
spPrint( Matrix, 0, 1, 1 );
|
||||
spPrint( (char *)Matrix, 0, 1, 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPgetError()
|
||||
*/
|
||||
void
|
||||
SMPgetError(SMPmatrix *Matrix, int *Col, int *Row)
|
||||
SMPgetError( Matrix, Col, Row)
|
||||
SMPmatrix *Matrix;
|
||||
int *Row, *Col;
|
||||
{
|
||||
spWhereSingular( Matrix, Row, Col );
|
||||
spWhereSingular( (char *)Matrix, Row, Col );
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPcProdDiag()
|
||||
* note: obsolete for Spice3d2 and later
|
||||
*/
|
||||
int
|
||||
SMPcProdDiag(SMPmatrix *Matrix, SPcomplex *pMantissa, int *pExponent)
|
||||
SMPcProdDiag( Matrix, pMantissa, pExponent)
|
||||
SMPmatrix *Matrix;
|
||||
SPcomplex *pMantissa;
|
||||
int *pExponent;
|
||||
{
|
||||
spDeterminant( Matrix, pExponent, &(pMantissa->real),
|
||||
spDeterminant( (char *)Matrix, pExponent, &(pMantissa->real),
|
||||
&(pMantissa->imag) );
|
||||
return spError( Matrix );
|
||||
return spErrorState( (char *)Matrix );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -325,8 +329,8 @@ SMPcProdDiag(SMPmatrix *Matrix, SPcomplex *pMantissa, int *pExponent)
|
|||
int
|
||||
SMPcDProd(SMPmatrix *Matrix, SPcomplex *pMantissa, int *pExponent)
|
||||
{
|
||||
double re, im, x, y, z;
|
||||
int p;
|
||||
double re, im, x, y, z;
|
||||
int p;
|
||||
|
||||
spDeterminant( Matrix, &p, &re, &im);
|
||||
|
||||
|
|
@ -347,7 +351,7 @@ SMPcDProd(SMPmatrix *Matrix, SPcomplex *pMantissa, int *pExponent)
|
|||
y -= x;
|
||||
|
||||
/* ASSERT
|
||||
* x = integral part of exponent, y = fraction part of exponent
|
||||
* x = integral part of exponent, y = fraction part of exponent
|
||||
*/
|
||||
|
||||
/* Fold in the fractional part */
|
||||
|
|
@ -363,51 +367,45 @@ SMPcDProd(SMPmatrix *Matrix, SPcomplex *pMantissa, int *pExponent)
|
|||
|
||||
/* Re-normalize (re or im may be > 2.0 or both < 1.0 */
|
||||
if (re != 0.0) {
|
||||
y = logb(re);
|
||||
if (im != 0.0)
|
||||
z = logb(im);
|
||||
else
|
||||
z = 0;
|
||||
y = logb(re);
|
||||
if (im != 0.0)
|
||||
z = logb(im);
|
||||
else
|
||||
z = 0;
|
||||
} else if (im != 0.0) {
|
||||
z = logb(im);
|
||||
y = 0;
|
||||
z = logb(im);
|
||||
y = 0;
|
||||
} else {
|
||||
/* Singular */
|
||||
/*printf("10 -> singular\n");*/
|
||||
y = 0;
|
||||
z = 0;
|
||||
/* Singular */
|
||||
/*printf("10 -> singular\n");*/
|
||||
y = 0;
|
||||
z = 0;
|
||||
}
|
||||
|
||||
#ifdef debug_print
|
||||
printf(" ** renormalize changes = %g,%g\n", y, z);
|
||||
#endif
|
||||
if (y < z)
|
||||
y = z;
|
||||
y = z;
|
||||
|
||||
*pExponent = (int)(x + y);
|
||||
x = scalbn(re, (int) -y);
|
||||
z = scalbn(im, (int) -y);
|
||||
#ifdef debug_print
|
||||
printf(" ** values are: re %g, im %g, y %g, re' %g, im' %g\n",
|
||||
re, im, y, x, z);
|
||||
re, im, y, x, z);
|
||||
#endif
|
||||
pMantissa->real = scalbn(re, (int) -y);
|
||||
pMantissa->imag = scalbn(im, (int) -y);
|
||||
|
||||
#ifdef debug_print
|
||||
printf("Determinant 10->2: (%20g,%20g)^%d\n", pMantissa->real,
|
||||
pMantissa->imag, *pExponent);
|
||||
pMantissa->imag, *pExponent);
|
||||
#endif
|
||||
return spError( Matrix );
|
||||
return spErrorState( Matrix );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The following routines need internal knowledge of the Sparse data
|
||||
* structures.
|
||||
*/
|
||||
|
||||
/*
|
||||
* LOAD GMIN
|
||||
*
|
||||
|
|
@ -418,47 +416,68 @@ SMPcDProd(SMPmatrix *Matrix, SPcomplex *pMantissa, int *pExponent)
|
|||
* use of this routine is not recommended. It is included here simply
|
||||
* for compatibility with Spice3.
|
||||
*/
|
||||
|
||||
static void
|
||||
LoadGmin(SMPmatrix *Matrix, double Gmin)
|
||||
#include "spDefs.h"
|
||||
void
|
||||
LoadGmin( eMatrix, Gmin )
|
||||
char *eMatrix;
|
||||
register double Gmin;
|
||||
{
|
||||
int I;
|
||||
ArrayOfElementPtrs Diag;
|
||||
ElementPtr diag;
|
||||
MatrixPtr Matrix = (MatrixPtr)eMatrix;
|
||||
register int I;
|
||||
register ArrayOfElementPtrs Diag;
|
||||
|
||||
/* Begin `LoadGmin'. */
|
||||
assert( IS_SPARSE( Matrix ) );
|
||||
/* Begin `spLoadGmin'. */
|
||||
ASSERT_IS_SPARSE( Matrix );
|
||||
|
||||
if (Gmin != 0.0) {
|
||||
Diag = Matrix->Diag;
|
||||
for (I = Matrix->Size; I > 0; I--) {
|
||||
if ((diag = Diag[I]) != NULL)
|
||||
diag->Real += Gmin;
|
||||
}
|
||||
}
|
||||
Diag = Matrix->Diag;
|
||||
for (I = Matrix->Size; I > 0; I--)
|
||||
Diag[I]->Real += Gmin;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* FIND ELEMENT
|
||||
*
|
||||
* This routine finds an element in the matrix by row and column number.
|
||||
* If the element exists, a pointer to it is returned. If not, then NULL
|
||||
* is returned unless the CreateIfMissing flag is TRUE, in which case a
|
||||
* is returned unless the CreateIfMissing flag is true, in which case a
|
||||
* pointer to the new element is returned.
|
||||
*/
|
||||
|
||||
//SMPelement *
|
||||
//SMPfindElt( Matrix, Row, Col, CreateIfMissing )
|
||||
//
|
||||
//SMPmatrix *Matrix;
|
||||
//int Row, Col;
|
||||
//int CreateIfMissing;
|
||||
//{
|
||||
////MatrixPtr Matrix = (MatrixPtr)eMatrix;
|
||||
//spREAL *Element = (spREAL *)Matrix->FirstInCol[Col];
|
||||
//
|
||||
///* Begin `SMPfindElt'. */
|
||||
// ASSERT_IS_SPARSE( Matrix );
|
||||
// if (CreateIfMissing)
|
||||
// { Element = spcCreateElement( Matrix, Row, Col,
|
||||
// &Matrix->FirstInRow[Row],
|
||||
// &Matrix->FirstInCol[Col], NO );
|
||||
// }
|
||||
// else Element = spcFindElement( Matrix, Row, Col );
|
||||
// return (SMPelement *)Element;
|
||||
//}
|
||||
|
||||
SMPelement *
|
||||
SMPfindElt(SMPmatrix *Matrix, int Row, int Col, int CreateIfMissing)
|
||||
{
|
||||
ElementPtr Element;
|
||||
|
||||
/* Begin `SMPfindElt'. */
|
||||
assert( IS_SPARSE( Matrix ) );
|
||||
ASSERT_IS_SPARSE( Matrix );
|
||||
Row = Matrix->ExtToIntRowMap[Row];
|
||||
|
||||
Col = Matrix->ExtToIntColMap[Col];
|
||||
|
||||
if (Col == -1)
|
||||
|
|
@ -470,7 +489,6 @@ SMPfindElt(SMPmatrix *Matrix, int Row, int Col, int CreateIfMissing)
|
|||
return Element;
|
||||
}
|
||||
|
||||
/* XXX The following should probably be implemented in spUtils */
|
||||
|
||||
/*
|
||||
* SMPcZeroCol()
|
||||
|
|
@ -478,19 +496,19 @@ SMPfindElt(SMPmatrix *Matrix, int Row, int Col, int CreateIfMissing)
|
|||
int
|
||||
SMPcZeroCol(SMPmatrix *Matrix, int Col)
|
||||
{
|
||||
ElementPtr Element;
|
||||
ElementPtr Element;
|
||||
|
||||
Col = Matrix->ExtToIntColMap[Col];
|
||||
|
||||
for (Element = Matrix->FirstInCol[Col];
|
||||
Element != NULL;
|
||||
Element = Element->NextInCol)
|
||||
Element != NULL;
|
||||
Element = Element->NextInCol)
|
||||
{
|
||||
Element->Real = 0.0;
|
||||
Element->Imag = 0.0;
|
||||
Element->Real = 0.0;
|
||||
Element->Imag = 0.0;
|
||||
}
|
||||
|
||||
return spError( Matrix );
|
||||
return spErrorState( Matrix );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -499,7 +517,7 @@ SMPcZeroCol(SMPmatrix *Matrix, int Col)
|
|||
int
|
||||
SMPcAddCol(SMPmatrix *Matrix, int Accum_Col, int Addend_Col)
|
||||
{
|
||||
ElementPtr Accum, Addend, *Prev;
|
||||
ElementPtr Accum, Addend, *Prev;
|
||||
|
||||
Accum_Col = Matrix->ExtToIntColMap[Accum_Col];
|
||||
Addend_Col = Matrix->ExtToIntColMap[Addend_Col];
|
||||
|
|
@ -509,52 +527,29 @@ SMPcAddCol(SMPmatrix *Matrix, int Accum_Col, int Addend_Col)
|
|||
Accum = *Prev;
|
||||
|
||||
while (Addend != NULL) {
|
||||
while (Accum && Accum->Row < Addend->Row) {
|
||||
Prev = &Accum->NextInCol;
|
||||
Accum = *Prev;
|
||||
}
|
||||
if (!Accum || Accum->Row > Addend->Row) {
|
||||
Accum = spcCreateElement(Matrix, Addend->Row, Accum_Col, Prev, 0);
|
||||
}
|
||||
Accum->Real += Addend->Real;
|
||||
Accum->Imag += Addend->Imag;
|
||||
Addend = Addend->NextInCol;
|
||||
while (Accum && Accum->Row < Addend->Row) {
|
||||
Prev = &Accum->NextInCol;
|
||||
Accum = *Prev;
|
||||
}
|
||||
if (!Accum || Accum->Row > Addend->Row) {
|
||||
Accum = spcCreateElement(Matrix, Addend->Row, Accum_Col, Prev, 0, 0);
|
||||
}
|
||||
Accum->Real += Addend->Real;
|
||||
Accum->Imag += Addend->Imag;
|
||||
Addend = Addend->NextInCol;
|
||||
}
|
||||
|
||||
return spError( Matrix );
|
||||
return spErrorState( Matrix );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SMPzeroRow()
|
||||
* SMPmultiply()
|
||||
*/
|
||||
int
|
||||
SMPzeroRow(SMPmatrix *Matrix, int Row)
|
||||
void
|
||||
SMPmultiply(SMPmatrix *Matrix, double *RHS, double *Solution, double *iRHS, double *iSolution)
|
||||
{
|
||||
ElementPtr Element;
|
||||
|
||||
Row = Matrix->ExtToIntColMap[Row];
|
||||
|
||||
if (Matrix->RowsLinked == NO)
|
||||
spcLinkRows(Matrix);
|
||||
|
||||
if (Matrix->PreviousMatrixWasComplex || Matrix->Complex) {
|
||||
for (Element = Matrix->FirstInRow[Row];
|
||||
Element != NULL;
|
||||
Element = Element->NextInRow)
|
||||
{
|
||||
Element->Real = 0.0;
|
||||
Element->Imag = 0.0;
|
||||
}
|
||||
} else {
|
||||
for (Element = Matrix->FirstInRow[Row];
|
||||
Element != NULL;
|
||||
Element = Element->NextInRow)
|
||||
{
|
||||
Element->Real = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
return spError( Matrix );
|
||||
spMultiply(Matrix, RHS, Solution, iRHS, iSolution);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -565,12 +560,3 @@ SMPconstMult(SMPmatrix *Matrix, double constant)
|
|||
{
|
||||
spConstMult(Matrix, constant);
|
||||
}
|
||||
|
||||
/*
|
||||
* SMPmultiply()
|
||||
*/
|
||||
void
|
||||
SMPmultiply(SMPmatrix *Matrix, double *RHS, double *Solution, double *iRHS, double *iSolution)
|
||||
{
|
||||
spMultiply(Matrix, RHS, Solution, iRHS, iSolution);
|
||||
}
|
||||
|
|
@ -4,11 +4,18 @@
|
|||
* Author: Advising professor:
|
||||
* Kenneth S. Kundert Alberto Sangiovanni-Vincentelli
|
||||
* UC Berkeley
|
||||
*
|
||||
*/
|
||||
/*! \file
|
||||
* This file contains the forward and backward substitution routines for
|
||||
* the sparse matrix routines.
|
||||
*
|
||||
* >>> User accessible functions contained in this file:
|
||||
* Objects that begin with the \a spc prefix are considered private
|
||||
* and should not be used.
|
||||
*
|
||||
* \author
|
||||
* Kenneth S. Kundert <kundert@users.sourceforge.net>
|
||||
*/
|
||||
/* >>> User accessible functions contained in this file:
|
||||
* spSolve
|
||||
* spSolveTransposed
|
||||
*
|
||||
|
|
@ -21,19 +28,12 @@
|
|||
/*
|
||||
* Revision and copyright information.
|
||||
*
|
||||
* Copyright (c) 1985,86,87,88,89,90
|
||||
* by Kenneth S. Kundert and the University of California.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the copyright notices appear in all copies and
|
||||
* supporting documentation and that the authors and the University of
|
||||
* California are properly credited. The authors and the University of
|
||||
* California make no representations as to the suitability of this
|
||||
* software for any purpose. It is provided `as is', without express
|
||||
* or implied warranty.
|
||||
* Copyright (c) 1985-2003
|
||||
* by Kenneth S. Kundert
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* IMPORTS
|
||||
*
|
||||
|
|
@ -45,12 +45,12 @@
|
|||
* spDefs.h
|
||||
* Matrix type and macro definitions for the sparse matrix routines.
|
||||
*/
|
||||
#include <assert.h>
|
||||
|
||||
#define spINSIDE_SPARSE
|
||||
#include "spconfig.h"
|
||||
#include <stdio.h>
|
||||
#include "spConfig.h"
|
||||
#include "ngspice/spmatrix.h"
|
||||
#include "spdefs.h"
|
||||
#include "spDefs.h"
|
||||
|
||||
|
||||
|
||||
|
|
@ -59,10 +59,16 @@
|
|||
* Function declarations
|
||||
*/
|
||||
|
||||
#if spSEPARATED_COMPLEX_VECTORS
|
||||
static void SolveComplexMatrix( MatrixPtr,
|
||||
RealVector, RealVector, RealVector, RealVector );
|
||||
static void SolveComplexTransposedMatrix( MatrixPtr,
|
||||
RealVector, RealVector, RealVector, RealVector );
|
||||
#else
|
||||
static void SolveComplexMatrix( MatrixPtr, RealVector, RealVector );
|
||||
static void SolveComplexTransposedMatrix( MatrixPtr,
|
||||
RealVector, RealVector );
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
@ -70,35 +76,35 @@ static void SolveComplexTransposedMatrix( MatrixPtr,
|
|||
|
||||
|
||||
|
||||
/*
|
||||
* SOLVE MATRIX EQUATION
|
||||
*
|
||||
/*!
|
||||
* Performs forward elimination and back substitution to find the
|
||||
* unknown vector from the RHS vector and factored matrix. This
|
||||
* unknown vector from the \a RHS vector and factored matrix. This
|
||||
* routine assumes that the pivots are associated with the lower
|
||||
* triangular (L) matrix and that the diagonal of the upper triangular
|
||||
* (U) matrix consists of ones. This routine arranges the computation
|
||||
* triangular matrix and that the diagonal of the upper triangular
|
||||
* matrix consists of ones. This routine arranges the computation
|
||||
* in different way than is traditionally used in order to exploit the
|
||||
* sparsity of the right-hand side. See the reference in spRevision.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (char *)
|
||||
* \param eMatrix
|
||||
* Pointer to matrix.
|
||||
* RHS <input> (RealVector)
|
||||
* RHS is the input data array, the right hand side. This data is
|
||||
* \param RHS
|
||||
* \a RHS is the input data array, the right hand side. This data is
|
||||
* undisturbed and may be reused for other solves.
|
||||
* Solution <output> (RealVector)
|
||||
* Solution is the output data array. This routine is constructed such that
|
||||
* RHS and Solution can be the same array.
|
||||
* iRHS <input> (RealVector)
|
||||
* iRHS is the imaginary portion of the input data array, the right
|
||||
* \param Solution
|
||||
* \a Solution is the output data array. This routine is constructed
|
||||
* such that \a RHS and \a Solution can be the same array.
|
||||
* \param iRHS
|
||||
* \a iRHS is the imaginary portion of the input data array, the right
|
||||
* hand side. This data is undisturbed and may be reused for other solves.
|
||||
* iSolution <output> (RealVector)
|
||||
* iSolution is the imaginary portion of the output data array. This
|
||||
* routine is constructed such that iRHS and iSolution can be
|
||||
* the same array.
|
||||
*
|
||||
* >>> Local variables:
|
||||
* This argument is only necessary if matrix is complex and if
|
||||
* \a spSEPARATED_COMPLEX_VECTOR is set true.
|
||||
* \param iSolution
|
||||
* \a iSolution is the imaginary portion of the output data array. This
|
||||
* routine is constructed such that \a iRHS and \a iSolution can be
|
||||
* the same array. This argument is only necessary if matrix is complex
|
||||
* and if \a spSEPARATED_COMPLEX_VECTOR is set true.
|
||||
*/
|
||||
/* >>> Local variables:
|
||||
* Intermediate (RealVector)
|
||||
* Temporary storage for use in forward elimination and backward
|
||||
* substitution. Commonly referred to as c, when the LU factorization
|
||||
|
|
@ -119,75 +125,96 @@ static void SolveComplexTransposedMatrix( MatrixPtr,
|
|||
* Size of matrix. Made local to reduce indirection.
|
||||
* Temp (RealNumber)
|
||||
* Temporary storage for entries in arrays.
|
||||
*
|
||||
* >>> Obscure Macros
|
||||
* IMAG_VECTORS
|
||||
* Replaces itself with `, iRHS, iSolution' if the options spCOMPLEX and
|
||||
* spSEPARATED_COMPLEX_VECTORS are set, otherwise it disappears
|
||||
* without a trace.
|
||||
*/
|
||||
|
||||
/*VARARGS3*/
|
||||
|
||||
void
|
||||
spSolve(MatrixPtr Matrix, RealVector RHS, RealVector Solution,
|
||||
RealVector iRHS, RealVector iSolution)
|
||||
spSolve(
|
||||
spMatrix eMatrix,
|
||||
spREAL RHS[],
|
||||
spREAL Solution[]
|
||||
# if spCOMPLEX AND spSEPARATED_COMPLEX_VECTORS
|
||||
, spREAL iRHS[]
|
||||
, spREAL iSolution[]
|
||||
# endif
|
||||
)
|
||||
{
|
||||
ElementPtr pElement;
|
||||
RealVector Intermediate;
|
||||
RealNumber Temp;
|
||||
int I, *pExtOrder, Size;
|
||||
ElementPtr pPivot;
|
||||
MatrixPtr Matrix = (MatrixPtr)eMatrix;
|
||||
register ElementPtr pElement;
|
||||
register RealVector Intermediate;
|
||||
register RealNumber Temp;
|
||||
register int I, *pExtOrder, Size;
|
||||
ElementPtr pPivot;
|
||||
void SolveComplexMatrix();
|
||||
|
||||
/* Begin `spSolve'. */
|
||||
assert( IS_VALID(Matrix) && IS_FACTORED(Matrix) );
|
||||
/* Begin `spSolve'. */
|
||||
ASSERT_IS_SPARSE( Matrix );
|
||||
ASSERT_NO_ERRORS( Matrix );
|
||||
ASSERT_IS_FACTORED( Matrix );
|
||||
|
||||
#if spCOMPLEX
|
||||
if (Matrix->Complex)
|
||||
{
|
||||
SolveComplexMatrix( Matrix, RHS, Solution, iRHS, iSolution );
|
||||
{ SolveComplexMatrix( Matrix, RHS, Solution IMAG_VECTORS );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if REAL
|
||||
Intermediate = Matrix->Intermediate;
|
||||
Size = Matrix->Size;
|
||||
|
||||
/* Initialize Intermediate vector. */
|
||||
/* Correct array pointers for ARRAY_OFFSET. */
|
||||
#if NOT ARRAY_OFFSET
|
||||
--RHS;
|
||||
--Solution;
|
||||
#endif
|
||||
|
||||
/* Initialize Intermediate vector. */
|
||||
pExtOrder = &Matrix->IntToExtRowMap[Size];
|
||||
for (I = Size; I > 0; I--)
|
||||
Intermediate[I] = RHS[*(pExtOrder--)];
|
||||
|
||||
/* Forward elimination. Solves Lc = b.*/
|
||||
/* Forward elimination. Solves Lc = b.*/
|
||||
for (I = 1; I <= Size; I++)
|
||||
{
|
||||
|
||||
/* This step of the elimination is skipped if Temp equals zero. */
|
||||
{
|
||||
/* This step of the elimination is skipped if Temp equals zero. */
|
||||
if ((Temp = Intermediate[I]) != 0.0)
|
||||
{
|
||||
pPivot = Matrix->Diag[I];
|
||||
{ pPivot = Matrix->Diag[I];
|
||||
Intermediate[I] = (Temp *= pPivot->Real);
|
||||
|
||||
pElement = pPivot->NextInCol;
|
||||
while (pElement != NULL)
|
||||
{
|
||||
Intermediate[pElement->Row] -= Temp * pElement->Real;
|
||||
{ Intermediate[pElement->Row] -= Temp * pElement->Real;
|
||||
pElement = pElement->NextInCol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Backward Substitution. Solves Ux = c.*/
|
||||
/* Backward Substitution. Solves Ux = c.*/
|
||||
for (I = Size; I > 0; I--)
|
||||
{
|
||||
Temp = Intermediate[I];
|
||||
{ Temp = Intermediate[I];
|
||||
pElement = Matrix->Diag[I]->NextInRow;
|
||||
while (pElement != NULL)
|
||||
{
|
||||
Temp -= pElement->Real * Intermediate[pElement->Col];
|
||||
{ Temp -= pElement->Real * Intermediate[pElement->Col];
|
||||
pElement = pElement->NextInRow;
|
||||
}
|
||||
Intermediate[I] = Temp;
|
||||
}
|
||||
|
||||
/* Unscramble Intermediate vector while placing data in to Solution vector. */
|
||||
/* Unscramble Intermediate vector while placing data in to Solution vector. */
|
||||
pExtOrder = &Matrix->IntToExtColMap[Size];
|
||||
for (I = Size; I > 0; I--)
|
||||
Solution[*(pExtOrder--)] = Intermediate[I];
|
||||
|
||||
return;
|
||||
#endif /* REAL */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -200,39 +227,37 @@ spSolve(MatrixPtr Matrix, RealVector RHS, RealVector Solution,
|
|||
|
||||
|
||||
|
||||
/*
|
||||
* SOLVE COMPLEX MATRIX EQUATION
|
||||
*
|
||||
#if spCOMPLEX
|
||||
/*!
|
||||
* Performs forward elimination and back substitution to find the
|
||||
* unknown vector from the RHS vector and factored matrix. This
|
||||
* routine assumes that the pivots are associated with the lower
|
||||
* triangular (L) matrix and that the diagonal of the upper triangular
|
||||
* (U) matrix consists of ones. This routine arranges the computation
|
||||
* triangular matrix and that the diagonal of the upper triangular
|
||||
* matrix consists of ones. This routine arranges the computation
|
||||
* in different way than is traditionally used in order to exploit the
|
||||
* sparsity of the right-hand side. See the reference in spRevision.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (char *)
|
||||
* \param Matrix
|
||||
* Pointer to matrix.
|
||||
* RHS <input> (RealVector)
|
||||
* \param RHS
|
||||
* RHS is the real portion of the input data array, the right hand
|
||||
* side. This data is undisturbed and may be reused for other solves.
|
||||
* Solution <output> (RealVector)
|
||||
* \param Solution
|
||||
* Solution is the real portion of the output data array. This routine
|
||||
* is constructed such that RHS and Solution can be the same
|
||||
* array.
|
||||
* iRHS <input> (RealVector)
|
||||
* \param iRHS
|
||||
* iRHS is the imaginary portion of the input data array, the right
|
||||
* hand side. This data is undisturbed and may be reused for other solves.
|
||||
* If spSEPARATED_COMPLEX_VECTOR is set FALSE, there is no need to
|
||||
* If spSEPARATED_COMPLEX_VECTOR is set false, there is no need to
|
||||
* supply this array.
|
||||
* iSolution <output> (RealVector)
|
||||
* \param iSolution
|
||||
* iSolution is the imaginary portion of the output data array. This
|
||||
* routine is constructed such that iRHS and iSolution can be
|
||||
* the same array. If spSEPARATED_COMPLEX_VECTOR is set FALSE, there is no
|
||||
* the same array. If spSEPARATED_COMPLEX_VECTOR is set false, there is no
|
||||
* need to supply this array.
|
||||
*
|
||||
* >>> Local variables:
|
||||
*/
|
||||
/* >>> Local variables:
|
||||
* Intermediate (ComplexVector)
|
||||
* Temporary storage for use in forward elimination and backward
|
||||
* substitution. Commonly referred to as c, when the LU factorization
|
||||
|
|
@ -256,44 +281,68 @@ spSolve(MatrixPtr Matrix, RealVector RHS, RealVector Solution,
|
|||
*/
|
||||
|
||||
static void
|
||||
SolveComplexMatrix( MatrixPtr Matrix, RealVector RHS, RealVector Solution , RealVector iRHS, RealVector iSolution )
|
||||
SolveComplexMatrix(
|
||||
MatrixPtr Matrix,
|
||||
RealVector RHS,
|
||||
RealVector Solution
|
||||
# if spSEPARATED_COMPLEX_VECTORS
|
||||
, RealVector iRHS
|
||||
, RealVector iSolution
|
||||
# endif
|
||||
)
|
||||
{
|
||||
ElementPtr pElement;
|
||||
ComplexVector Intermediate;
|
||||
int I, *pExtOrder, Size;
|
||||
ElementPtr pPivot;
|
||||
ComplexNumber Temp;
|
||||
register ElementPtr pElement;
|
||||
register ComplexVector Intermediate;
|
||||
register int I, *pExtOrder, Size;
|
||||
ElementPtr pPivot;
|
||||
#if NOT spSEPARATED_COMPLEX_VECTORS
|
||||
register ComplexVector ExtVector;
|
||||
#endif
|
||||
ComplexNumber Temp;
|
||||
|
||||
/* Begin `SolveComplexMatrix'. */
|
||||
/* Begin `SolveComplexMatrix'. */
|
||||
|
||||
Size = Matrix->Size;
|
||||
Intermediate = (ComplexVector)Matrix->Intermediate;
|
||||
|
||||
/* Initialize Intermediate vector. */
|
||||
/* Correct array pointers for ARRAY_OFFSET. */
|
||||
#if NOT ARRAY_OFFSET
|
||||
#if spSEPARATED_COMPLEX_VECTORS
|
||||
--RHS; --iRHS;
|
||||
--Solution; --iSolution;
|
||||
#else
|
||||
RHS -= 2; Solution -= 2;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Initialize Intermediate vector. */
|
||||
pExtOrder = &Matrix->IntToExtRowMap[Size];
|
||||
|
||||
#if spSEPARATED_COMPLEX_VECTORS
|
||||
for (I = Size; I > 0; I--)
|
||||
{
|
||||
Intermediate[I].Real = RHS[*(pExtOrder)];
|
||||
{ Intermediate[I].Real = RHS[*(pExtOrder)];
|
||||
Intermediate[I].Imag = iRHS[*(pExtOrder--)];
|
||||
}
|
||||
#else
|
||||
ExtVector = (ComplexVector)RHS;
|
||||
for (I = Size; I > 0; I--)
|
||||
Intermediate[I] = ExtVector[*(pExtOrder--)];
|
||||
#endif
|
||||
|
||||
/* Forward substitution. Solves Lc = b.*/
|
||||
/* Forward substitution. Solves Lc = b.*/
|
||||
for (I = 1; I <= Size; I++)
|
||||
{
|
||||
Temp = Intermediate[I];
|
||||
{ Temp = Intermediate[I];
|
||||
|
||||
/* This step of the substitution is skipped if Temp equals zero. */
|
||||
if ((Temp.Real != 0.0) || (Temp.Imag != 0.0))
|
||||
{
|
||||
pPivot = Matrix->Diag[I];
|
||||
/* Cmplx expr: Temp *= (1.0 / Pivot). */
|
||||
/* This step of the substitution is skipped if Temp equals zero. */
|
||||
if ((Temp.Real != 0.0) OR (Temp.Imag != 0.0))
|
||||
{ pPivot = Matrix->Diag[I];
|
||||
/* Cmplx expr: Temp *= (1.0 / Pivot). */
|
||||
CMPLX_MULT_ASSIGN(Temp, *pPivot);
|
||||
Intermediate[I] = Temp;
|
||||
pElement = pPivot->NextInCol;
|
||||
while (pElement != NULL)
|
||||
{
|
||||
/* Cmplx expr: Intermediate[Element->Row] -= Temp * *Element. */
|
||||
/* Cmplx expr: Intermediate[Element->Row] -= Temp * *Element. */
|
||||
CMPLX_MULT_SUBT_ASSIGN(Intermediate[pElement->Row],
|
||||
Temp, *pElement);
|
||||
pElement = pElement->NextInCol;
|
||||
|
|
@ -301,32 +350,37 @@ SolveComplexMatrix( MatrixPtr Matrix, RealVector RHS, RealVector Solution , Real
|
|||
}
|
||||
}
|
||||
|
||||
/* Backward Substitution. Solves Ux = c.*/
|
||||
/* Backward Substitution. Solves Ux = c.*/
|
||||
for (I = Size; I > 0; I--)
|
||||
{
|
||||
Temp = Intermediate[I];
|
||||
{ Temp = Intermediate[I];
|
||||
pElement = Matrix->Diag[I]->NextInRow;
|
||||
|
||||
while (pElement != NULL)
|
||||
{
|
||||
/* Cmplx expr: Temp -= *Element * Intermediate[Element->Col]. */
|
||||
/* Cmplx expr: Temp -= *Element * Intermediate[Element->Col]. */
|
||||
CMPLX_MULT_SUBT_ASSIGN(Temp, *pElement,Intermediate[pElement->Col]);
|
||||
pElement = pElement->NextInRow;
|
||||
}
|
||||
Intermediate[I] = Temp;
|
||||
}
|
||||
|
||||
/* Unscramble Intermediate vector while placing data in to Solution vector. */
|
||||
/* Unscramble Intermediate vector while placing data in to Solution vector. */
|
||||
pExtOrder = &Matrix->IntToExtColMap[Size];
|
||||
|
||||
#if spSEPARATED_COMPLEX_VECTORS
|
||||
for (I = Size; I > 0; I--)
|
||||
{
|
||||
Solution[*(pExtOrder)] = Intermediate[I].Real;
|
||||
{ Solution[*(pExtOrder)] = Intermediate[I].Real;
|
||||
iSolution[*(pExtOrder--)] = Intermediate[I].Imag;
|
||||
}
|
||||
#else
|
||||
ExtVector = (ComplexVector)Solution;
|
||||
for (I = Size; I > 0; I--)
|
||||
ExtVector[*(pExtOrder--)] = Intermediate[I];
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* spCOMPLEX */
|
||||
|
||||
|
||||
|
||||
|
|
@ -342,38 +396,35 @@ SolveComplexMatrix( MatrixPtr Matrix, RealVector RHS, RealVector Solution , Real
|
|||
|
||||
|
||||
#if TRANSPOSE
|
||||
/*
|
||||
* SOLVE TRANSPOSED MATRIX EQUATION
|
||||
*
|
||||
/*!
|
||||
* Performs forward elimination and back substitution to find the
|
||||
* unknown vector from the RHS vector and transposed factored
|
||||
* matrix. This routine is useful when performing sensitivity analysis
|
||||
* on a circuit using the adjoint method. This routine assumes that
|
||||
* the pivots are associated with the untransposed lower triangular
|
||||
* (L) matrix and that the diagonal of the untransposed upper
|
||||
* triangular (U) matrix consists of ones.
|
||||
* matrix and that the diagonal of the untransposed upper
|
||||
* triangular matrix consists of ones.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (char *)
|
||||
* \param eMatrix
|
||||
* Pointer to matrix.
|
||||
* RHS <input> (RealVector)
|
||||
* RHS is the input data array, the right hand side. This data is
|
||||
* \param RHS
|
||||
* \a RHS is the input data array, the right hand side. This data is
|
||||
* undisturbed and may be reused for other solves.
|
||||
* Solution <output> (RealVector)
|
||||
* Solution is the output data array. This routine is constructed such that
|
||||
* RHS and Solution can be the same array.
|
||||
* iRHS <input> (RealVector)
|
||||
* iRHS is the imaginary portion of the input data array, the right
|
||||
* \param Solution
|
||||
* \a Solution is the output data array. This routine is constructed
|
||||
* such that \a RHS and \a Solution can be the same array.
|
||||
* \param iRHS
|
||||
* \a iRHS is the imaginary portion of the input data array, the right
|
||||
* hand side. This data is undisturbed and may be reused for other solves.
|
||||
* If spSEPARATED_COMPLEX_VECTOR is set FALSE, or if matrix is real, there
|
||||
* is no need to supply this array.
|
||||
* iSolution <output> (RealVector)
|
||||
* iSolution is the imaginary portion of the output data array. This
|
||||
* routine is constructed such that iRHS and iSolution can be
|
||||
* the same array. If spSEPARATED_COMPLEX_VECTOR is set FALSE, or if
|
||||
* If \a spSEPARATED_COMPLEX_VECTOR is set false, or if matrix is real,
|
||||
* there is no need to supply this array.
|
||||
* \param iSolution
|
||||
* \a iSolution is the imaginary portion of the output data array. This
|
||||
* routine is constructed such that \a iRHS and \a iSolution can be
|
||||
* the same array. If \a spSEPARATED_COMPLEX_VECTOR is set false, or if
|
||||
* matrix is real, there is no need to supply this array.
|
||||
*
|
||||
* >>> Local variables:
|
||||
*/
|
||||
/* >>> Local variables:
|
||||
* Intermediate (RealVector)
|
||||
* Temporary storage for use in forward elimination and backward
|
||||
* substitution. Commonly referred to as c, when the LU factorization
|
||||
|
|
@ -399,70 +450,84 @@ SolveComplexMatrix( MatrixPtr Matrix, RealVector RHS, RealVector Solution , Real
|
|||
/*VARARGS3*/
|
||||
|
||||
void
|
||||
spSolveTransposed(MatrixPtr Matrix, RealVector RHS, RealVector Solution,
|
||||
RealVector iRHS, RealVector iSolution)
|
||||
spSolveTransposed(
|
||||
spMatrix eMatrix,
|
||||
spREAL RHS[],
|
||||
spREAL Solution[]
|
||||
# if spCOMPLEX AND spSEPARATED_COMPLEX_VECTORS
|
||||
, spREAL iRHS[]
|
||||
, spREAL iSolution[]
|
||||
# endif
|
||||
)
|
||||
{
|
||||
ElementPtr pElement;
|
||||
RealVector Intermediate;
|
||||
int I, *pExtOrder, Size;
|
||||
ElementPtr pPivot;
|
||||
RealNumber Temp;
|
||||
MatrixPtr Matrix = (MatrixPtr)eMatrix;
|
||||
register ElementPtr pElement;
|
||||
register RealVector Intermediate;
|
||||
register int I, *pExtOrder, Size;
|
||||
ElementPtr pPivot;
|
||||
RealNumber Temp;
|
||||
void SolveComplexTransposedMatrix();
|
||||
|
||||
/* Begin `spSolveTransposed'. */
|
||||
assert( IS_VALID(Matrix) && IS_FACTORED(Matrix) );
|
||||
/* Begin `spSolveTransposed'. */
|
||||
ASSERT_IS_SPARSE( Matrix );
|
||||
ASSERT_NO_ERRORS( Matrix );
|
||||
ASSERT_IS_FACTORED( Matrix );
|
||||
|
||||
#if spCOMPLEX
|
||||
if (Matrix->Complex)
|
||||
{
|
||||
SolveComplexTransposedMatrix( Matrix, RHS, Solution , iRHS, iSolution );
|
||||
{ SolveComplexTransposedMatrix( Matrix, RHS, Solution IMAG_VECTORS );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if REAL
|
||||
Size = Matrix->Size;
|
||||
Intermediate = Matrix->Intermediate;
|
||||
|
||||
/* Initialize Intermediate vector. */
|
||||
/* Correct array pointers for ARRAY_OFFSET. */
|
||||
#if NOT ARRAY_OFFSET
|
||||
--RHS;
|
||||
--Solution;
|
||||
#endif
|
||||
|
||||
/* Initialize Intermediate vector. */
|
||||
pExtOrder = &Matrix->IntToExtColMap[Size];
|
||||
for (I = Size; I > 0; I--)
|
||||
Intermediate[I] = RHS[*(pExtOrder--)];
|
||||
|
||||
/* Forward elimination. */
|
||||
/* Forward elimination. */
|
||||
for (I = 1; I <= Size; I++)
|
||||
{
|
||||
|
||||
/* This step of the elimination is skipped if Temp equals zero. */
|
||||
{
|
||||
/* This step of the elimination is skipped if Temp equals zero. */
|
||||
if ((Temp = Intermediate[I]) != 0.0)
|
||||
{
|
||||
pElement = Matrix->Diag[I]->NextInRow;
|
||||
{ pElement = Matrix->Diag[I]->NextInRow;
|
||||
while (pElement != NULL)
|
||||
{
|
||||
Intermediate[pElement->Col] -= Temp * pElement->Real;
|
||||
{ Intermediate[pElement->Col] -= Temp * pElement->Real;
|
||||
pElement = pElement->NextInRow;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Backward Substitution. */
|
||||
/* Backward Substitution. */
|
||||
for (I = Size; I > 0; I--)
|
||||
{
|
||||
pPivot = Matrix->Diag[I];
|
||||
{ pPivot = Matrix->Diag[I];
|
||||
Temp = Intermediate[I];
|
||||
pElement = pPivot->NextInCol;
|
||||
while (pElement != NULL)
|
||||
{
|
||||
Temp -= pElement->Real * Intermediate[pElement->Row];
|
||||
{ Temp -= pElement->Real * Intermediate[pElement->Row];
|
||||
pElement = pElement->NextInCol;
|
||||
}
|
||||
Intermediate[I] = Temp * pPivot->Real;
|
||||
}
|
||||
|
||||
/* Unscramble Intermediate vector while placing data in to
|
||||
Solution vector. */
|
||||
/* Unscramble Intermediate vector while placing data in to Solution vector. */
|
||||
pExtOrder = &Matrix->IntToExtRowMap[Size];
|
||||
for (I = Size; I > 0; I--)
|
||||
Solution[*(pExtOrder--)] = Intermediate[I];
|
||||
|
||||
return;
|
||||
#endif /* REAL */
|
||||
}
|
||||
#endif /* TRANSPOSE */
|
||||
|
||||
|
|
@ -475,38 +540,40 @@ spSolveTransposed(MatrixPtr Matrix, RealVector RHS, RealVector Solution,
|
|||
|
||||
|
||||
|
||||
#if TRANSPOSE
|
||||
/*
|
||||
* SOLVE COMPLEX TRANSPOSED MATRIX EQUATION
|
||||
*
|
||||
#if TRANSPOSE AND spCOMPLEX
|
||||
/*!
|
||||
* Performs forward elimination and back substitution to find the
|
||||
* unknown vector from the RHS vector and transposed factored
|
||||
* matrix. This routine is useful when performing sensitivity analysis
|
||||
* on a circuit using the adjoint method. This routine assumes that
|
||||
* the pivots are associated with the untransposed lower triangular
|
||||
* (L) matrix and that the diagonal of the untransposed upper
|
||||
* triangular (U) matrix consists of ones.
|
||||
* matrix and that the diagonal of the untransposed upper
|
||||
* triangular matrix consists of ones.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (char *)
|
||||
* \param Matrix
|
||||
* Pointer to matrix.
|
||||
* RHS <input> (RealVector)
|
||||
* RHS is the input data array, the right hand
|
||||
* \param RHS
|
||||
* \a RHS is the input data array, the right hand
|
||||
* side. This data is undisturbed and may be reused for other solves.
|
||||
* This vector is only the real portion if the matrix is complex.
|
||||
* Solution <output> (RealVector)
|
||||
* Solution is the real portion of the output data array. This routine
|
||||
* is constructed such that RHS and Solution can be the same array.
|
||||
* This vector is only the real portion if the matrix is complex.
|
||||
* iRHS <input> (RealVector)
|
||||
* iRHS is the imaginary portion of the input data array, the right
|
||||
* This vector is only the real portion if the matrix is complex and
|
||||
* \a spSEPARATED_COMPLEX_VECTORS is set true.
|
||||
* \param Solution
|
||||
* \a Solution is the real portion of the output data array. This routine
|
||||
* is constructed such that \a RHS and \a Solution can be the same array.
|
||||
* This vector is only the real portion if the matrix is complex and
|
||||
* \a spSEPARATED_COMPLEX_VECTORS is set true.
|
||||
* \param iRHS
|
||||
* \a iRHS is the imaginary portion of the input data array, the right
|
||||
* hand side. This data is undisturbed and may be reused for other solves.
|
||||
* iSolution <output> (RealVector)
|
||||
* iSolution is the imaginary portion of the output data array. This
|
||||
* routine is constructed such that iRHS and iSolution can be
|
||||
* the same array.
|
||||
*
|
||||
* >>> Local variables:
|
||||
* If either \a spCOMPLEX or \a spSEPARATED_COMPLEX_VECTOR is set false,
|
||||
* there is no need to supply this array.
|
||||
* \param iSolution
|
||||
* \a iSolution is the imaginary portion of the output data array. This
|
||||
* routine is constructed such that \a iRHS and \a iSolution can be
|
||||
* the same array. If \a spCOMPLEX or \a spSEPARATED_COMPLEX_VECTOR is set
|
||||
* false, there is no need to supply this array.
|
||||
*/
|
||||
/* >>> Local variables:
|
||||
* Intermediate (ComplexVector)
|
||||
* Temporary storage for use in forward elimination and backward
|
||||
* substitution. Commonly referred to as c, when the LU factorization
|
||||
|
|
@ -530,40 +597,64 @@ spSolveTransposed(MatrixPtr Matrix, RealVector RHS, RealVector Solution,
|
|||
*/
|
||||
|
||||
static void
|
||||
SolveComplexTransposedMatrix(MatrixPtr Matrix, RealVector RHS, RealVector Solution , RealVector iRHS, RealVector iSolution )
|
||||
SolveComplexTransposedMatrix(
|
||||
MatrixPtr Matrix,
|
||||
RealVector RHS,
|
||||
RealVector Solution
|
||||
# if spSEPARATED_COMPLEX_VECTORS
|
||||
, RealVector iRHS
|
||||
, RealVector iSolution
|
||||
# endif
|
||||
)
|
||||
{
|
||||
ElementPtr pElement;
|
||||
ComplexVector Intermediate;
|
||||
int I, *pExtOrder, Size;
|
||||
ElementPtr pPivot;
|
||||
ComplexNumber Temp;
|
||||
register ElementPtr pElement;
|
||||
register ComplexVector Intermediate;
|
||||
register int I, *pExtOrder, Size;
|
||||
#if NOT spSEPARATED_COMPLEX_VECTORS
|
||||
register ComplexVector ExtVector;
|
||||
#endif
|
||||
ElementPtr pPivot;
|
||||
ComplexNumber Temp;
|
||||
|
||||
/* Begin `SolveComplexTransposedMatrix'. */
|
||||
/* Begin `SolveComplexTransposedMatrix'. */
|
||||
|
||||
Size = Matrix->Size;
|
||||
Intermediate = (ComplexVector)Matrix->Intermediate;
|
||||
|
||||
/* Initialize Intermediate vector. */
|
||||
/* Correct array pointers for ARRAY_OFFSET. */
|
||||
#if NOT ARRAY_OFFSET
|
||||
#if spSEPARATED_COMPLEX_VECTORS
|
||||
--RHS; --iRHS;
|
||||
--Solution; --iSolution;
|
||||
#else
|
||||
RHS -= 2; Solution -= 2;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Initialize Intermediate vector. */
|
||||
pExtOrder = &Matrix->IntToExtColMap[Size];
|
||||
|
||||
#if spSEPARATED_COMPLEX_VECTORS
|
||||
for (I = Size; I > 0; I--)
|
||||
{
|
||||
Intermediate[I].Real = RHS[*(pExtOrder)];
|
||||
{ Intermediate[I].Real = RHS[*(pExtOrder)];
|
||||
Intermediate[I].Imag = iRHS[*(pExtOrder--)];
|
||||
}
|
||||
#else
|
||||
ExtVector = (ComplexVector)RHS;
|
||||
for (I = Size; I > 0; I--)
|
||||
Intermediate[I] = ExtVector[*(pExtOrder--)];
|
||||
#endif
|
||||
|
||||
/* Forward elimination. */
|
||||
/* Forward elimination. */
|
||||
for (I = 1; I <= Size; I++)
|
||||
{
|
||||
Temp = Intermediate[I];
|
||||
{ Temp = Intermediate[I];
|
||||
|
||||
/* This step of the elimination is skipped if Temp equals zero. */
|
||||
if ((Temp.Real != 0.0) || (Temp.Imag != 0.0))
|
||||
{
|
||||
pElement = Matrix->Diag[I]->NextInRow;
|
||||
/* This step of the elimination is skipped if Temp equals zero. */
|
||||
if ((Temp.Real != 0.0) OR (Temp.Imag != 0.0))
|
||||
{ pElement = Matrix->Diag[I]->NextInRow;
|
||||
while (pElement != NULL)
|
||||
{
|
||||
/* Cmplx expr: Intermediate[Element->Col] -= Temp * *Element. */
|
||||
/* Cmplx expr: Intermediate[Element->Col] -= Temp * *Element. */
|
||||
CMPLX_MULT_SUBT_ASSIGN( Intermediate[pElement->Col],
|
||||
Temp, *pElement);
|
||||
pElement = pElement->NextInRow;
|
||||
|
|
@ -571,34 +662,37 @@ SolveComplexTransposedMatrix(MatrixPtr Matrix, RealVector RHS, RealVector Soluti
|
|||
}
|
||||
}
|
||||
|
||||
/* Backward Substitution. */
|
||||
/* Backward Substitution. */
|
||||
for (I = Size; I > 0; I--)
|
||||
{
|
||||
pPivot = Matrix->Diag[I];
|
||||
{ pPivot = Matrix->Diag[I];
|
||||
Temp = Intermediate[I];
|
||||
pElement = pPivot->NextInCol;
|
||||
|
||||
while (pElement != NULL)
|
||||
{
|
||||
/* Cmplx expr: Temp -= Intermediate[Element->Row] * *Element. */
|
||||
/* Cmplx expr: Temp -= Intermediate[Element->Row] * *Element. */
|
||||
CMPLX_MULT_SUBT_ASSIGN(Temp,Intermediate[pElement->Row],*pElement);
|
||||
|
||||
pElement = pElement->NextInCol;
|
||||
}
|
||||
/* Cmplx expr: Intermediate = Temp * (1.0 / *pPivot). */
|
||||
/* Cmplx expr: Intermediate = Temp * (1.0 / *pPivot). */
|
||||
CMPLX_MULT(Intermediate[I], Temp, *pPivot);
|
||||
}
|
||||
|
||||
/* Unscramble Intermediate vector while placing data in to
|
||||
Solution vector. */
|
||||
/* Unscramble Intermediate vector while placing data in to Solution vector. */
|
||||
pExtOrder = &Matrix->IntToExtRowMap[Size];
|
||||
|
||||
#if spSEPARATED_COMPLEX_VECTORS
|
||||
for (I = Size; I > 0; I--)
|
||||
{
|
||||
Solution[*(pExtOrder)] = Intermediate[I].Real;
|
||||
{ Solution[*(pExtOrder)] = Intermediate[I].Real;
|
||||
iSolution[*(pExtOrder--)] = Intermediate[I].Imag;
|
||||
}
|
||||
#else
|
||||
ExtVector = (ComplexVector)Solution;
|
||||
for (I = Size; I > 0; I--)
|
||||
ExtVector[*(pExtOrder--)] = Intermediate[I];
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* TRANSPOSE */
|
||||
#endif /* TRANSPOSE AND spCOMPLEX */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,885 +0,0 @@
|
|||
/*
|
||||
* MATRIX ALLOCATION MODULE
|
||||
*
|
||||
* Author: Advising professor:
|
||||
* Kenneth S. Kundert Alberto Sangiovanni-Vincentelli
|
||||
* UC Berkeley
|
||||
*
|
||||
* This file contains the allocation and deallocation routines for the
|
||||
* sparse matrix routines.
|
||||
*
|
||||
* >>> User accessible functions contained in this file:
|
||||
* spCreate
|
||||
* spDestroy
|
||||
* spError
|
||||
* spWhereSingular
|
||||
* spGetSize
|
||||
* spSetReal
|
||||
* spSetComplex
|
||||
* spFillinCount
|
||||
* spElementCount
|
||||
* spOriginalCount
|
||||
*
|
||||
* >>> Other functions contained in this file:
|
||||
* spcGetElement
|
||||
* InitializeElementBlocks
|
||||
* spcGetFillin
|
||||
* RecordAllocation
|
||||
* AllocateBlockOfAllocationList
|
||||
* EnlargeMatrix
|
||||
* ExpandTranslationArrays
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Revision and copyright information.
|
||||
*
|
||||
* Copyright (c) 1985,86,87,88,89,90
|
||||
* by Kenneth S. Kundert and the University of California.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the copyright notices appear in all copies and
|
||||
* supporting documentation and that the authors and the University of
|
||||
* California are properly credited. The authors and the University of
|
||||
* California make no representations as to the suitability of this
|
||||
* software for any purpose. It is provided `as is', without express
|
||||
* or implied warranty.
|
||||
*/
|
||||
|
||||
/*
|
||||
* IMPORTS
|
||||
*
|
||||
* >>> Import descriptions:
|
||||
* spConfig.h
|
||||
* Macros that customize the sparse matrix routines.
|
||||
* spMatrix.h
|
||||
* Macros and declarations to be imported by the user.
|
||||
* spDefs.h
|
||||
* Matrix type and macro definitions for the sparse matrix routines.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define spINSIDE_SPARSE
|
||||
|
||||
#include "spconfig.h"
|
||||
#include "ngspice/spmatrix.h"
|
||||
#include "spdefs.h"
|
||||
|
||||
/*
|
||||
* Function declarations
|
||||
*/
|
||||
|
||||
static void InitializeElementBlocks( MatrixPtr, int, int );
|
||||
static void RecordAllocation( MatrixPtr, void *);
|
||||
static void AllocateBlockOfAllocationList( MatrixPtr );
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* MATRIX ALLOCATION
|
||||
*
|
||||
* Allocates and initializes the data structures associated with a matrix.
|
||||
*
|
||||
* >>> Returned:
|
||||
* A pointer to the matrix is returned cast into the form of a pointer to
|
||||
* a character. This pointer is then passed and used by the other matrix
|
||||
* routines to refer to a particular matrix. If an error occurs, the NULL
|
||||
* pointer is returned.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Size <input> (int)
|
||||
* Size of matrix or estimate of size of matrix if matrix is EXPANDABLE.
|
||||
* Complex <input> (int)
|
||||
* Type of matrix. If Complex is 0 then the matrix is real, otherwise
|
||||
* the matrix will be complex. Note that if the routines are not set up
|
||||
* to handle the type of matrix requested, then a spPANIC error will occur.
|
||||
* Further note that if a matrix will be both real and complex, it must
|
||||
* be specified here as being complex.
|
||||
* pError <output> (int *)
|
||||
* Returns error flag, needed because function spError() will not work
|
||||
* correctly if spCreate() returns NULL.
|
||||
*
|
||||
* >>> Local variables:
|
||||
* AllocatedSize (int)
|
||||
* The size of the matrix being allocated.
|
||||
* Matrix (MatrixPtr)
|
||||
* A pointer to the matrix frame being created.
|
||||
*
|
||||
* >>> Possible errors:
|
||||
* spNO_MEMORY
|
||||
* spPANIC
|
||||
* Error is cleared in this routine.
|
||||
*/
|
||||
|
||||
MatrixPtr
|
||||
spCreate(int Size, int Complex, int *pError)
|
||||
{
|
||||
unsigned SizePlusOne;
|
||||
MatrixPtr Matrix;
|
||||
int I;
|
||||
int AllocatedSize;
|
||||
|
||||
/* Begin `spCreate'. */
|
||||
/* Clear error flag. */
|
||||
*pError = spOKAY;
|
||||
|
||||
/* Test for valid size. */
|
||||
#if EXPANDABLE
|
||||
if (Size < 0) {
|
||||
*pError = spPANIC;
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
if (Size <= 0) {
|
||||
*pError = spPANIC;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if 0 /* pn: skipped for cider */
|
||||
/* Test for valid type. */
|
||||
if (!Complex) {
|
||||
*pError = spPANIC;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create Matrix. */
|
||||
AllocatedSize = MAX( Size, MINIMUM_ALLOCATED_SIZE );
|
||||
SizePlusOne = (unsigned)(AllocatedSize + 1);
|
||||
|
||||
if ((Matrix = SP_MALLOC(struct MatrixFrame, 1)) == NULL) {
|
||||
*pError = spNO_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize matrix */
|
||||
Matrix->ID = SPARSE_ID;
|
||||
Matrix->Complex = Complex;
|
||||
Matrix->PreviousMatrixWasComplex = Complex;
|
||||
Matrix->Factored = NO;
|
||||
Matrix->Elements = 0;
|
||||
Matrix->Error = *pError;
|
||||
Matrix->Originals = 0;
|
||||
Matrix->Fillins = 0;
|
||||
Matrix->Reordered = NO;
|
||||
Matrix->NeedsOrdering = YES;
|
||||
Matrix->NumberOfInterchangesIsOdd = NO;
|
||||
Matrix->Partitioned = NO;
|
||||
Matrix->RowsLinked = NO;
|
||||
Matrix->InternalVectorsAllocated = NO;
|
||||
Matrix->SingularCol = 0;
|
||||
Matrix->SingularRow = 0;
|
||||
Matrix->Size = Size;
|
||||
Matrix->AllocatedSize = AllocatedSize;
|
||||
Matrix->ExtSize = Size;
|
||||
Matrix->AllocatedExtSize = AllocatedSize;
|
||||
Matrix->CurrentSize = 0;
|
||||
Matrix->ExtToIntColMap = NULL;
|
||||
Matrix->ExtToIntRowMap = NULL;
|
||||
Matrix->IntToExtColMap = NULL;
|
||||
Matrix->IntToExtRowMap = NULL;
|
||||
Matrix->MarkowitzRow = NULL;
|
||||
Matrix->MarkowitzCol = NULL;
|
||||
Matrix->MarkowitzProd = NULL;
|
||||
Matrix->DoCmplxDirect = NULL;
|
||||
Matrix->DoRealDirect = NULL;
|
||||
Matrix->Intermediate = NULL;
|
||||
Matrix->RelThreshold = DEFAULT_THRESHOLD;
|
||||
Matrix->AbsThreshold = 0.0;
|
||||
|
||||
Matrix->TopOfAllocationList = NULL;
|
||||
Matrix->RecordsRemaining = 0;
|
||||
Matrix->ElementsRemaining = 0;
|
||||
Matrix->FillinsRemaining = 0;
|
||||
|
||||
RecordAllocation( Matrix, Matrix );
|
||||
if (Matrix->Error == spNO_MEMORY) goto MemoryError;
|
||||
|
||||
/* Take out the trash. */
|
||||
Matrix->TrashCan.Real = 0.0;
|
||||
Matrix->TrashCan.Imag = 0.0;
|
||||
Matrix->TrashCan.Row = 0;
|
||||
Matrix->TrashCan.Col = 0;
|
||||
Matrix->TrashCan.NextInRow = NULL;
|
||||
Matrix->TrashCan.NextInCol = NULL;
|
||||
#if INITIALIZE
|
||||
Matrix->TrashCan.pInitInfo = NULL;
|
||||
#endif
|
||||
|
||||
/* Allocate space in memory for Diag pointer vector. */
|
||||
SP_CALLOC( Matrix->Diag, ElementPtr, SizePlusOne);
|
||||
if (Matrix->Diag == NULL)
|
||||
goto MemoryError;
|
||||
|
||||
/* Allocate space in memory for FirstInCol pointer vector. */
|
||||
SP_CALLOC( Matrix->FirstInCol, ElementPtr, SizePlusOne);
|
||||
if (Matrix->FirstInCol == NULL)
|
||||
goto MemoryError;
|
||||
|
||||
/* Allocate space in memory for FirstInRow pointer vector. */
|
||||
SP_CALLOC( Matrix->FirstInRow, ElementPtr, SizePlusOne);
|
||||
if (Matrix->FirstInRow == NULL)
|
||||
goto MemoryError;
|
||||
|
||||
/* Allocate space in memory for IntToExtColMap vector. */
|
||||
if (( Matrix->IntToExtColMap = SP_MALLOC(int, SizePlusOne)) == NULL)
|
||||
goto MemoryError;
|
||||
|
||||
/* Allocate space in memory for IntToExtRowMap vector. */
|
||||
if (( Matrix->IntToExtRowMap = SP_MALLOC(int, SizePlusOne)) == NULL)
|
||||
goto MemoryError;
|
||||
|
||||
/* Initialize MapIntToExt vectors. */
|
||||
for (I = 1; I <= AllocatedSize; I++)
|
||||
{
|
||||
Matrix->IntToExtRowMap[I] = I;
|
||||
Matrix->IntToExtColMap[I] = I;
|
||||
}
|
||||
|
||||
#if TRANSLATE
|
||||
/* Allocate space in memory for ExtToIntColMap vector. */
|
||||
if (( Matrix->ExtToIntColMap = SP_MALLOC(int, SizePlusOne)) == NULL)
|
||||
goto MemoryError;
|
||||
|
||||
/* Allocate space in memory for ExtToIntRowMap vector. */
|
||||
if (( Matrix->ExtToIntRowMap = SP_MALLOC(int, SizePlusOne)) == NULL)
|
||||
goto MemoryError;
|
||||
|
||||
/* Initialize MapExtToInt vectors. */
|
||||
for (I = 1; I <= AllocatedSize; I++) {
|
||||
Matrix->ExtToIntColMap[I] = -1;
|
||||
Matrix->ExtToIntRowMap[I] = -1;
|
||||
}
|
||||
Matrix->ExtToIntColMap[0] = 0;
|
||||
Matrix->ExtToIntRowMap[0] = 0;
|
||||
#endif
|
||||
|
||||
/* Allocate space for fill-ins and initial set of elements. */
|
||||
InitializeElementBlocks( Matrix, SPACE_FOR_ELEMENTS*AllocatedSize,
|
||||
SPACE_FOR_FILL_INS*AllocatedSize );
|
||||
if (Matrix->Error == spNO_MEMORY)
|
||||
goto MemoryError;
|
||||
|
||||
return Matrix;
|
||||
|
||||
MemoryError:
|
||||
|
||||
/* Deallocate matrix and return no pointer to matrix if there is not enough
|
||||
memory. */
|
||||
*pError = spNO_MEMORY;
|
||||
spDestroy(Matrix);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ELEMENT ALLOCATION
|
||||
*
|
||||
* This routine allocates space for matrix elements. It requests large blocks
|
||||
* of storage from the system and doles out individual elements as required.
|
||||
* This technique, as opposed to allocating elements individually, tends to
|
||||
* speed the allocation process.
|
||||
*
|
||||
* >>> Returned:
|
||||
* A pointer to an element.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (MatrixPtr)
|
||||
* Pointer to matrix.
|
||||
*
|
||||
* >>> Local variables:
|
||||
* pElement (ElementPtr)
|
||||
* A pointer to the first element in the group of elements being allocated.
|
||||
*
|
||||
* >>> Possible errors:
|
||||
* spNO_MEMORY
|
||||
*/
|
||||
|
||||
ElementPtr
|
||||
spcGetElement(MatrixPtr Matrix)
|
||||
{
|
||||
ElementPtr pElements;
|
||||
|
||||
/* Begin `spcGetElement'. */
|
||||
|
||||
#if !COMBINE || STRIP || LINT
|
||||
/* Allocate block of MatrixElements if necessary. */
|
||||
if (Matrix->ElementsRemaining == 0) {
|
||||
pElements = SP_MALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION);
|
||||
RecordAllocation( Matrix, pElements );
|
||||
if (Matrix->Error == spNO_MEMORY) return NULL;
|
||||
Matrix->ElementsRemaining = ELEMENTS_PER_ALLOCATION;
|
||||
Matrix->NextAvailElement = pElements;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if COMBINE || STRIP || LINT
|
||||
if (Matrix->ElementsRemaining == 0)
|
||||
{
|
||||
pListNode = Matrix->LastElementListNode;
|
||||
|
||||
/* First see if there are any stripped elements left. */
|
||||
if (pListNode->Next != NULL) {
|
||||
Matrix->LastElementListNode = pListNode = pListNode->Next;
|
||||
Matrix->ElementsRemaining = pListNode->NumberOfElementsInList;
|
||||
Matrix->NextAvailElement = pListNode->pElementList;
|
||||
} else {
|
||||
/* Allocate block of elements. */
|
||||
pElements = SP_MALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION);
|
||||
RecordAllocation( Matrix, pElements );
|
||||
if (Matrix->Error == spNO_MEMORY) return NULL;
|
||||
Matrix->ElementsRemaining = ELEMENTS_PER_ALLOCATION;
|
||||
Matrix->NextAvailElement = pElements;
|
||||
|
||||
/* Allocate an element list structure. */
|
||||
pListNode->Next = SP_MALLOC(struct ElementListNodeStruct,1);
|
||||
RecordAllocation( Matrix, pListNode->Next );
|
||||
if (Matrix->Error == spNO_MEMORY)
|
||||
return NULL;
|
||||
Matrix->LastElementListNode = pListNode = pListNode->Next;
|
||||
|
||||
pListNode->pElementList = pElements;
|
||||
pListNode->NumberOfElementsInList = ELEMENTS_PER_ALLOCATION;
|
||||
pListNode->Next = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update Element counter and return pointer to Element. */
|
||||
Matrix->ElementsRemaining--;
|
||||
return Matrix->NextAvailElement++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ELEMENT ALLOCATION INITIALIZATION
|
||||
*
|
||||
* This routine allocates space for matrix fill-ins and an initial
|
||||
* set of elements. Besides being faster than allocating space for
|
||||
* elements one at a time, it tends to keep the fill-ins physically
|
||||
* close to the other matrix elements in the computer memory. This
|
||||
* keeps virtual memory paging to a minimum.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (MatrixPtr)
|
||||
* Pointer to the matrix.
|
||||
* InitialNumberOfElements <input> (int)
|
||||
* This number is used as the size of the block of memory, in
|
||||
* MatrixElements, reserved for elements. If more than this number of
|
||||
* elements are generated, then more space is allocated later.
|
||||
* NumberOfFillinsExpected <input> (int)
|
||||
* This number is used as the size of the block of memory, in
|
||||
* MatrixElements, reserved for fill-ins. If more than this number of
|
||||
* fill-ins are generated, then more space is allocated, but they may
|
||||
* not be physically close in computer's memory.
|
||||
*
|
||||
* >>> Local variables:
|
||||
* pElement (ElementPtr)
|
||||
* A pointer to the first element in the group of elements being allocated.
|
||||
*
|
||||
* >>> Possible errors:
|
||||
* spNO_MEMORY */
|
||||
|
||||
static void
|
||||
InitializeElementBlocks(MatrixPtr Matrix, int InitialNumberOfElements,
|
||||
int NumberOfFillinsExpected)
|
||||
{
|
||||
ElementPtr pElement;
|
||||
|
||||
/* Begin `InitializeElementBlocks'. */
|
||||
|
||||
/* Allocate block of MatrixElements for elements. */
|
||||
pElement = SP_MALLOC(struct MatrixElement, InitialNumberOfElements);
|
||||
RecordAllocation( Matrix, pElement );
|
||||
if (Matrix->Error == spNO_MEMORY) return;
|
||||
Matrix->ElementsRemaining = InitialNumberOfElements;
|
||||
Matrix->NextAvailElement = pElement;
|
||||
|
||||
/* Allocate an element list structure. */
|
||||
Matrix->FirstElementListNode = SP_MALLOC(struct ElementListNodeStruct,1);
|
||||
RecordAllocation( Matrix, Matrix->FirstElementListNode );
|
||||
if (Matrix->Error == spNO_MEMORY) return;
|
||||
Matrix->LastElementListNode = Matrix->FirstElementListNode;
|
||||
|
||||
Matrix->FirstElementListNode->pElementList = pElement;
|
||||
Matrix->FirstElementListNode->NumberOfElementsInList =
|
||||
InitialNumberOfElements;
|
||||
Matrix->FirstElementListNode->Next = NULL;
|
||||
|
||||
/* Allocate block of MatrixElements for fill-ins. */
|
||||
pElement = SP_MALLOC(struct MatrixElement, NumberOfFillinsExpected);
|
||||
RecordAllocation( Matrix, pElement );
|
||||
if (Matrix->Error == spNO_MEMORY) return;
|
||||
Matrix->FillinsRemaining = NumberOfFillinsExpected;
|
||||
Matrix->NextAvailFillin = pElement;
|
||||
|
||||
/* Allocate a fill-in list structure. */
|
||||
Matrix->FirstFillinListNode = SP_MALLOC(struct FillinListNodeStruct,1);
|
||||
RecordAllocation( Matrix, Matrix->FirstFillinListNode );
|
||||
if (Matrix->Error == spNO_MEMORY) return;
|
||||
Matrix->LastFillinListNode = Matrix->FirstFillinListNode;
|
||||
|
||||
Matrix->FirstFillinListNode->pFillinList = pElement;
|
||||
Matrix->FirstFillinListNode->NumberOfFillinsInList =NumberOfFillinsExpected;
|
||||
Matrix->FirstFillinListNode->Next = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* FILL-IN ALLOCATION
|
||||
*
|
||||
* This routine allocates space for matrix fill-ins. It requests
|
||||
* large blocks of storage from the system and doles out individual
|
||||
* elements as required. This technique, as opposed to allocating
|
||||
* elements individually, tends to speed the allocation process.
|
||||
*
|
||||
* >>> Returned:
|
||||
* A pointer to the fill-in.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (MatrixPtr)
|
||||
* Pointer to matrix.
|
||||
*
|
||||
* >>> Possible errors:
|
||||
* spNO_MEMORY */
|
||||
|
||||
ElementPtr
|
||||
spcGetFillin(MatrixPtr Matrix)
|
||||
{
|
||||
/* Begin `spcGetFillin'. */
|
||||
|
||||
#if !STRIP || LINT
|
||||
if (Matrix->FillinsRemaining == 0)
|
||||
return spcGetElement( Matrix );
|
||||
#endif
|
||||
#if STRIP || LINT
|
||||
|
||||
if (Matrix->FillinsRemaining == 0) {
|
||||
pListNode = Matrix->LastFillinListNode;
|
||||
|
||||
/* First see if there are any stripped fill-ins left. */
|
||||
if (pListNode->Next != NULL) {
|
||||
Matrix->LastFillinListNode = pListNode = pListNode->Next;
|
||||
Matrix->FillinsRemaining = pListNode->NumberOfFillinsInList;
|
||||
Matrix->NextAvailFillin = pListNode->pFillinList;
|
||||
} else {
|
||||
/* Allocate block of fill-ins. */
|
||||
pFillins = SP_MALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION);
|
||||
RecordAllocation( Matrix, pFillins );
|
||||
if (Matrix->Error == spNO_MEMORY) return NULL;
|
||||
Matrix->FillinsRemaining = ELEMENTS_PER_ALLOCATION;
|
||||
Matrix->NextAvailFillin = pFillins;
|
||||
|
||||
/* Allocate a fill-in list structure. */
|
||||
pListNode->Next = SP_MALLOC(struct FillinListNodeStruct,1);
|
||||
RecordAllocation( Matrix, pListNode->Next );
|
||||
if (Matrix->Error == spNO_MEMORY) return NULL;
|
||||
Matrix->LastFillinListNode = pListNode = pListNode->Next;
|
||||
|
||||
pListNode->pFillinList = pFillins;
|
||||
pListNode->NumberOfFillinsInList = ELEMENTS_PER_ALLOCATION;
|
||||
pListNode->Next = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update Fill-in counter and return pointer to Fill-in. */
|
||||
Matrix->FillinsRemaining--;
|
||||
return Matrix->NextAvailFillin++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* RECORD A MEMORY ALLOCATION
|
||||
*
|
||||
* This routine is used to record all memory allocations so that the
|
||||
* memory can be freed later.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (MatrixPtr)
|
||||
* Pointer to the matrix.
|
||||
* AllocatedPtr <input> (void *)
|
||||
* The pointer returned by tmalloc or calloc. These pointers are
|
||||
* saved in a list so that they can be easily freed.
|
||||
*
|
||||
* >>> Possible errors:
|
||||
* spNO_MEMORY */
|
||||
|
||||
static void
|
||||
RecordAllocation(MatrixPtr Matrix, void *AllocatedPtr )
|
||||
{
|
||||
/* Begin `RecordAllocation'. */
|
||||
/* If Allocated pointer is NULL, assume that tmalloc returned a
|
||||
* NULL pointer, which indicates a spNO_MEMORY error. */
|
||||
if (AllocatedPtr == NULL) {
|
||||
Matrix->Error = spNO_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate block of MatrixElements if necessary. */
|
||||
if (Matrix->RecordsRemaining == 0) {
|
||||
AllocateBlockOfAllocationList( Matrix );
|
||||
if (Matrix->Error == spNO_MEMORY) {
|
||||
SP_FREE(AllocatedPtr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add Allocated pointer to Allocation List. */
|
||||
(++Matrix->TopOfAllocationList)->AllocatedPtr = AllocatedPtr;
|
||||
Matrix->RecordsRemaining--;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ADD A BLOCK OF SLOTS TO ALLOCATION LIST
|
||||
*
|
||||
* This routine increases the size of the allocation list.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (MatrixPtr)
|
||||
* Pointer to the matrix.
|
||||
*
|
||||
* >>> Local variables:
|
||||
* ListPtr (AllocationListPtr)
|
||||
* Pointer to the list that contains the pointers to segments of
|
||||
* memory that were allocated by the operating system for the
|
||||
* current matrix.
|
||||
*
|
||||
* >>> Possible errors:
|
||||
* spNO_MEMORY */
|
||||
|
||||
static void
|
||||
AllocateBlockOfAllocationList(MatrixPtr Matrix)
|
||||
{
|
||||
int I;
|
||||
AllocationListPtr ListPtr;
|
||||
|
||||
/* Begin `AllocateBlockOfAllocationList'. */
|
||||
/* Allocate block of records for allocation list. */
|
||||
ListPtr = SP_MALLOC(struct AllocationRecord, (ELEMENTS_PER_ALLOCATION+1));
|
||||
if (ListPtr == NULL) {
|
||||
Matrix->Error = spNO_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
/* String entries of allocation list into singly linked list.
|
||||
List is linked such that any record points to the one before
|
||||
it. */
|
||||
|
||||
ListPtr->NextRecord = Matrix->TopOfAllocationList;
|
||||
Matrix->TopOfAllocationList = ListPtr;
|
||||
ListPtr += ELEMENTS_PER_ALLOCATION;
|
||||
for (I = ELEMENTS_PER_ALLOCATION; I > 0; I--) {
|
||||
ListPtr->NextRecord = ListPtr - 1;
|
||||
ListPtr--;
|
||||
}
|
||||
|
||||
/* Record allocation of space for allocation list on allocation list. */
|
||||
Matrix->TopOfAllocationList->AllocatedPtr = (void *)ListPtr;
|
||||
Matrix->RecordsRemaining = ELEMENTS_PER_ALLOCATION;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* MATRIX DEALLOCATION
|
||||
*
|
||||
* Deallocates pointers and elements of Matrix.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (void *)
|
||||
* Pointer to the matrix frame which is to be removed from memory.
|
||||
*
|
||||
* >>> Local variables:
|
||||
* ListPtr (AllocationListPtr)
|
||||
* Pointer into the linked list of pointers to allocated data structures.
|
||||
* Points to pointer to structure to be freed.
|
||||
* NextListPtr (AllocationListPtr)
|
||||
* Pointer into the linked list of pointers to allocated data structures.
|
||||
* Points to the next pointer to structure to be freed. This is needed
|
||||
* because the data structure to be freed could include the current node
|
||||
* in the allocation list.
|
||||
*/
|
||||
|
||||
void
|
||||
spDestroy(MatrixPtr Matrix)
|
||||
{
|
||||
AllocationListPtr ListPtr, NextListPtr;
|
||||
|
||||
|
||||
/* Begin `spDestroy'. */
|
||||
assert( IS_SPARSE( Matrix ) );
|
||||
|
||||
/* Deallocate the vectors that are located in the matrix frame. */
|
||||
SP_FREE( Matrix->IntToExtColMap );
|
||||
SP_FREE( Matrix->IntToExtRowMap );
|
||||
SP_FREE( Matrix->ExtToIntColMap );
|
||||
SP_FREE( Matrix->ExtToIntRowMap );
|
||||
SP_FREE( Matrix->Diag );
|
||||
SP_FREE( Matrix->FirstInRow );
|
||||
SP_FREE( Matrix->FirstInCol );
|
||||
SP_FREE( Matrix->MarkowitzRow );
|
||||
SP_FREE( Matrix->MarkowitzCol );
|
||||
SP_FREE( Matrix->MarkowitzProd );
|
||||
SP_FREE( Matrix->DoCmplxDirect );
|
||||
SP_FREE( Matrix->DoRealDirect );
|
||||
SP_FREE( Matrix->Intermediate );
|
||||
|
||||
/* Sequentially step through the list of allocated pointers
|
||||
* freeing pointers along the way. */
|
||||
ListPtr = Matrix->TopOfAllocationList;
|
||||
while (ListPtr != NULL) {
|
||||
NextListPtr = ListPtr->NextRecord;
|
||||
if ((void *) ListPtr == ListPtr->AllocatedPtr) {
|
||||
SP_FREE( ListPtr );
|
||||
} else {
|
||||
SP_FREE( ListPtr->AllocatedPtr );
|
||||
}
|
||||
ListPtr = NextListPtr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* RETURN MATRIX ERROR STATUS
|
||||
*
|
||||
* This function is used to determine the error status of the given
|
||||
* matrix.
|
||||
*
|
||||
* >>> Returned:
|
||||
* The error status of the given matrix.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (void *)
|
||||
* The matrix for which the error status is desired. */
|
||||
int
|
||||
spError(MatrixPtr Matrix )
|
||||
{
|
||||
/* Begin `spError'. */
|
||||
|
||||
if (Matrix != NULL) {
|
||||
assert(Matrix->ID == SPARSE_ID);
|
||||
return Matrix->Error;
|
||||
} else {
|
||||
/* This error may actually be spPANIC, no way to tell. */
|
||||
return spNO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* WHERE IS MATRIX SINGULAR
|
||||
*
|
||||
* This function returns the row and column number where the matrix was
|
||||
* detected as singular or where a zero was detected on the diagonal.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (void *)
|
||||
* The matrix for which the error status is desired.
|
||||
* pRow <output> (int *)
|
||||
* The row number.
|
||||
* pCol <output> (int *)
|
||||
* The column number.
|
||||
*/
|
||||
|
||||
void
|
||||
spWhereSingular(MatrixPtr Matrix, int *pRow, int *pCol)
|
||||
{
|
||||
/* Begin `spWhereSingular'. */
|
||||
assert( IS_SPARSE( Matrix ) );
|
||||
|
||||
if (Matrix->Error == spSINGULAR || Matrix->Error == spZERO_DIAG)
|
||||
{
|
||||
*pRow = Matrix->SingularRow;
|
||||
*pCol = Matrix->SingularCol;
|
||||
}
|
||||
else *pRow = *pCol = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* MATRIX SIZE
|
||||
*
|
||||
* Returns the size of the matrix. Either the internal or external size of
|
||||
* the matrix is returned.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (void *)
|
||||
* Pointer to matrix.
|
||||
* External <input> (int)
|
||||
* If External is set TRUE, the external size , i.e., the value of the
|
||||
* largest external row or column number encountered is returned.
|
||||
* Otherwise the TRUE size of the matrix is returned. These two sizes
|
||||
* may differ if the TRANSLATE option is set TRUE.
|
||||
*/
|
||||
|
||||
int
|
||||
spGetSize(MatrixPtr Matrix, int External)
|
||||
{
|
||||
/* Begin `spGetSize'. */
|
||||
assert( IS_SPARSE( Matrix ) );
|
||||
|
||||
#if TRANSLATE
|
||||
if (External)
|
||||
return Matrix->ExtSize;
|
||||
else
|
||||
return Matrix->Size;
|
||||
#else
|
||||
return Matrix->Size;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* SET MATRIX COMPLEX OR REAL
|
||||
*
|
||||
* Forces matrix to be either real or complex.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (void *)
|
||||
* Pointer to matrix.
|
||||
*/
|
||||
|
||||
void
|
||||
spSetReal(MatrixPtr Matrix)
|
||||
{
|
||||
/* Begin `spSetReal'. */
|
||||
|
||||
assert( IS_SPARSE( Matrix ));
|
||||
Matrix->Complex = NO;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
spSetComplex(MatrixPtr Matrix)
|
||||
{
|
||||
/* Begin `spSetComplex'. */
|
||||
|
||||
assert( IS_SPARSE( Matrix ));
|
||||
Matrix->Complex = YES;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ELEMENT, FILL-IN OR ORIGINAL COUNT
|
||||
*
|
||||
* Two functions used to return simple statistics. Either the number
|
||||
* of total elements, or the number of fill-ins, or the number
|
||||
* of original elements can be returned.
|
||||
*
|
||||
* >>> Arguments:
|
||||
* Matrix <input> (void *)
|
||||
* Pointer to matrix.
|
||||
*/
|
||||
|
||||
int
|
||||
spFillinCount(MatrixPtr Matrix)
|
||||
{
|
||||
/* Begin `spFillinCount'. */
|
||||
|
||||
assert( IS_SPARSE( Matrix ) );
|
||||
return Matrix->Fillins;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
spElementCount(MatrixPtr Matrix)
|
||||
{
|
||||
/* Begin `spElementCount'. */
|
||||
|
||||
assert( IS_SPARSE( Matrix ) );
|
||||
return Matrix->Elements;
|
||||
}
|
||||
|
||||
int
|
||||
spOriginalCount(MatrixPtr Matrix)
|
||||
{
|
||||
/* Begin `spOriginalCount'. */
|
||||
|
||||
assert( IS_SPARSE( Matrix ) );
|
||||
return Matrix->Originals;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,402 +0,0 @@
|
|||
/*
|
||||
* CONFIGURATION MACRO DEFINITIONS for sparse matrix routines
|
||||
*
|
||||
* Author: Advising professor:
|
||||
* Kenneth S. Kundert Alberto Sangiovanni-Vincentelli
|
||||
* U.C. Berkeley
|
||||
*
|
||||
* This file contains macros for the sparse matrix routines that are used
|
||||
* to define the personality of the routines. The user is expected to
|
||||
* modify this file to maximize the performance of the routines with
|
||||
* his/her matrices.
|
||||
*
|
||||
* Macros are distinguished by using solely capital letters in their
|
||||
* identifiers. This contrasts with C defined identifiers which are
|
||||
* strictly lower case, and program variable and procedure names which use
|
||||
* both upper and lower case.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Revision and copyright information.
|
||||
*
|
||||
* Copyright (c) 1985,86,87,88,89,90
|
||||
* by Kenneth S. Kundert and the University of California.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the copyright notices appear in all copies and
|
||||
* supporting documentation and that the authors and the University of
|
||||
* California are properly credited. The authors and the University of
|
||||
* California make no representations as to the suitability of this
|
||||
* software for any purpose. It is provided `as is', without express
|
||||
* or implied warranty.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ngspice_SPCONFIG_H
|
||||
#define ngspice_SPCONFIG_H
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef spINSIDE_SPARSE
|
||||
/*
|
||||
* OPTIONS
|
||||
*
|
||||
* These are compiler options. Set each option to one to compile that
|
||||
* section of the code. If a feature is not desired, set the macro
|
||||
* to NO. Recommendations are given in brackets, [ignore them].
|
||||
*
|
||||
* >>> Option descriptions:
|
||||
* Arithmetic Precision
|
||||
* The precision of the arithmetic used by Sparse can be set by
|
||||
* changing changing the spREAL macro. This macro is
|
||||
* contained in the file spMatrix.h. It is strongly suggested to
|
||||
* used double precision with circuit simulators. Note that
|
||||
* because C always performs arithmetic operations in double
|
||||
* precision, the only benefit to using single precision is that
|
||||
* less storage is required. There is often a noticeable speed
|
||||
* penalty when using single precision. Sparse internally refers
|
||||
* to a spREAL as a RealNumber.
|
||||
* EXPANDABLE
|
||||
* Setting this compiler flag true (1) makes the matrix
|
||||
* expandable before it has been factored. If the matrix is
|
||||
* expandable, then if an element is added that would be
|
||||
* considered out of bounds in the current matrix, the size of
|
||||
* the matrix is increased to hold that element. As a result,
|
||||
* the size of the matrix need not be known before the matrix is
|
||||
* built. The matrix can be allocated with size zero and
|
||||
* expanded.
|
||||
* TRANSLATE
|
||||
* This option allows the set of external row and column numbers
|
||||
* to be non-packed. In other words, the row and column numbers
|
||||
* do not have to be contiguous. The priced paid for this
|
||||
* flexibility is that when TRANSLATE is set true, the time
|
||||
* required to initially build the matrix will be greater because
|
||||
* the external row and column number must be translated into
|
||||
* internal equivalents. This translation brings about other
|
||||
* benefits though. First, the spGetElement() and
|
||||
* spGetAdmittance() routines may be used after the matrix has
|
||||
* been factored. Further, elements, and even rows and columns,
|
||||
* may be added to the matrix, and row and columns may be deleted
|
||||
* from the matrix, after it has been factored. Note that when
|
||||
* the set of row and column number is not a packed set, neither
|
||||
* are the RHS and Solution vectors. Thus the size of these
|
||||
* vectors must be at least as large as the external size, which
|
||||
* is the value of the largest given row or column numbers.
|
||||
* INITIALIZE
|
||||
* Causes the spInitialize(), spGetInitInfo(), and
|
||||
* spInstallInitInfo() routines to be compiled. These routines
|
||||
* allow the user to store and read one pointer in each nonzero
|
||||
* element in the matrix. spInitialize() then calls a user
|
||||
* specified function for each structural nonzero in the matrix,
|
||||
* and includes this pointer as well as the external row and
|
||||
* column numbers as arguments. This allows the user to write
|
||||
* custom matrix initialization routines.
|
||||
* DIAGONAL_PIVOTING
|
||||
* Many matrices, and in particular node- and modified-node
|
||||
* admittance matrices, tend to be nearly symmetric and nearly
|
||||
* diagonally dominant. For these matrices, it is a good idea to
|
||||
* select pivots from the diagonal. With this option enabled,
|
||||
* this is exactly what happens, though if no satisfactory pivot
|
||||
* can be found on the diagonal, an off-diagonal pivot will be
|
||||
* used. If this option is disabled, Sparse does not
|
||||
* preferentially search the diagonal. Because of this, Sparse
|
||||
* has a wider variety of pivot candidates available, and so
|
||||
* presumably fewer fill-ins will be created. However, the
|
||||
* initial pivot selection process will take considerably longer.
|
||||
* If working with node admittance matrices, or other matrices
|
||||
* with a strong diagonal, it is probably best to use
|
||||
* DIAGONAL_PIVOTING for two reasons. First, accuracy will be
|
||||
* better because pivots will be chosen from the large diagonal
|
||||
* elements, thus reducing the chance of growth. Second, a near
|
||||
* optimal ordering will be chosen quickly. If the class of
|
||||
* matrices you are working with does not have a strong diagonal,
|
||||
* do not use DIAGONAL_PIVOTING, but consider using a larger
|
||||
* threshold. When DIAGONAL_PIVOTING is turned off, the following
|
||||
* options and constants are not used: MODIFIED_MARKOWITZ,
|
||||
* MAX_MARKOWITZ_TIES, and TIES_MULTIPLIER.
|
||||
* MODIFIED_MARKOWITZ
|
||||
* This specifies that the modified Markowitz method of pivot
|
||||
* selection is to be used. The modified Markowitz method differs
|
||||
* from standard Markowitz in two ways. First, under modified
|
||||
* Markowitz, the search for a pivot can be terminated early if a
|
||||
* adequate (in terms of sparsity) pivot candidate is found.
|
||||
* Thus, when using modified Markowitz, the initial factorization
|
||||
* can be faster, but at the expense of a suboptimal pivoting
|
||||
* order that may slow subsequent factorizations. The second
|
||||
* difference is in the way modified Markowitz breaks Markowitz
|
||||
* ties. When two or more elements are pivot candidates and they
|
||||
* all have the same Markowitz product, then the tie is broken by
|
||||
* choosing the element that is best numerically. The numerically
|
||||
* best element is the one with the largest ratio of its magnitude
|
||||
* to the magnitude of the largest element in the same column,
|
||||
* excluding itself. The modified Markowitz method results in
|
||||
* marginally better accuracy. This option is most appropriate
|
||||
* for use when working with very large matrices where the initial
|
||||
* factor time represents an unacceptable burden. [NO]
|
||||
* DELETE
|
||||
* This specifies that the spDeleteRowAndCol() routine
|
||||
* should be compiled. Note that for this routine to be
|
||||
* compiled, both DELETE and TRANSLATE should be set true.
|
||||
* STRIP
|
||||
* This specifies that the spStripFills() routine should be compiled.
|
||||
* MODIFIED_NODAL
|
||||
* This specifies that the routine that preorders modified node
|
||||
* admittance matrices should be compiled. This routine results
|
||||
* in greater speed and accuracy if used with this type of
|
||||
* matrix.
|
||||
* QUAD_ELEMENT
|
||||
* This specifies that the routines that allow four related
|
||||
* elements to be entered into the matrix at once should be
|
||||
* compiled. These elements are usually related to an
|
||||
* admittance. The routines affected by QUAD_ELEMENT are the
|
||||
* spGetAdmittance, spGetQuad and spGetOnes routines.
|
||||
* TRANSPOSE
|
||||
* This specifies that the routines that solve the matrix as if
|
||||
* it was transposed should be compiled. These routines are
|
||||
* useful when performing sensitivity analysis using the adjoint
|
||||
* method.
|
||||
* SCALING
|
||||
* This specifies that the routine that performs scaling on the
|
||||
* matrix should be complied. Scaling is not strongly
|
||||
* supported. The routine to scale the matrix is provided, but
|
||||
* no routines are provided to scale and descale the RHS and
|
||||
* Solution vectors. It is suggested that if scaling is desired,
|
||||
* it only be preformed when the pivot order is being chosen [in
|
||||
* spOrderAndFactor()]. This is the only time scaling has
|
||||
* an effect. The scaling may then either be removed from the
|
||||
* solution by the user or the scaled factors may simply be
|
||||
* thrown away. [NO]
|
||||
* DOCUMENTATION
|
||||
* This specifies that routines that are used to document the
|
||||
* matrix, such as spPrint() and spFileMatrix(), should be
|
||||
* compiled.
|
||||
* DETERMINANT
|
||||
* This specifies that the routine spDeterminant() should be complied.
|
||||
* STABILITY
|
||||
* This specifies that spLargestElement() and spRoundoff() should
|
||||
* be compiled. These routines are used to check the stability (and
|
||||
* hence the quality of the pivoting) of the factorization by
|
||||
* computing a bound on the size of the element is the matrix E =
|
||||
* A - LU. If this bound is very high after applying
|
||||
* spOrderAndFactor(), then the pivot threshold should be raised.
|
||||
* If the bound increases greatly after using spFactor(), then the
|
||||
* matrix should probably be reordered.
|
||||
* CONDITION
|
||||
* This specifies that spCondition() and spNorm(), the code that
|
||||
* computes a good estimate of the condition number of the matrix,
|
||||
* should be compiled.
|
||||
* PSEUDOCONDITION
|
||||
* This specifies that spPseudoCondition(), the code that computes
|
||||
* a crude and easily fooled indicator of ill-conditioning in the
|
||||
* matrix, should be compiled.
|
||||
* MULTIPLICATION
|
||||
* This specifies that the routines to multiply the unfactored
|
||||
* matrix by a vector should be compiled.
|
||||
* DEBUG
|
||||
* This specifies that additional error checking will be compiled.
|
||||
* The type of error checked are those that are common when the
|
||||
* matrix routines are first integrated into a user's program. Once
|
||||
* the routines have been integrated in and are running smoothly, this
|
||||
* option should be turned off.
|
||||
*/
|
||||
|
||||
/* Begin options. */
|
||||
#define EXPANDABLE YES
|
||||
#define TRANSLATE YES
|
||||
#define INITIALIZE NO
|
||||
#define DIAGONAL_PIVOTING YES
|
||||
#define MODIFIED_MARKOWITZ NO
|
||||
#define DELETE NO
|
||||
#define STRIP NO
|
||||
#define MODIFIED_NODAL YES
|
||||
#define QUAD_ELEMENT NO
|
||||
#define TRANSPOSE YES
|
||||
#define SCALING NO
|
||||
#define DOCUMENTATION YES
|
||||
#define MULTIPLICATION YES
|
||||
#define DETERMINANT YES
|
||||
#define DETERMINANT2 YES
|
||||
#define STABILITY NO
|
||||
#define CONDITION NO
|
||||
#define PSEUDOCONDITION NO
|
||||
#ifdef HAS_MINDATA
|
||||
# define DEBUG NO
|
||||
#else
|
||||
# define DEBUG YES
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following options affect Sparse exports and so are exported as a
|
||||
* side effect. For this reason they use the `sp' prefix. The boolean
|
||||
* constants YES an NO are not defined in spMatrix.h to avoid conflicts
|
||||
* with user code, so use 0 for NO and 1 for YES.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* MATRIX CONSTANTS
|
||||
*
|
||||
* These constants are used throughout the sparse matrix routines. They
|
||||
* should be set to suit the type of matrix being solved. Recommendations
|
||||
* are given in brackets.
|
||||
*
|
||||
* Some terminology should be defined. The Markowitz row count is the number
|
||||
* of non-zero elements in a row excluding the one being considered as pivot.
|
||||
* There is one Markowitz row count for every row. The Markowitz column
|
||||
* is defined similarly for columns. The Markowitz product for an element
|
||||
* is the product of its row and column counts. It is a measure of how much
|
||||
* work would be required on the next step of the factorization if that
|
||||
* element were chosen to be pivot. A small Markowitz product is desirable.
|
||||
*
|
||||
* >>> Constants descriptions:
|
||||
* DEFAULT_THRESHOLD
|
||||
* The relative threshold used if the user enters an invalid
|
||||
* threshold. Also the threshold used by spFactor() when
|
||||
* calling spOrderAndFactor(). The default threshold should
|
||||
* not be less than or equal to zero nor larger than one. [0.001]
|
||||
* DIAG_PIVOTING_AS_DEFAULT
|
||||
* This indicates whether spOrderAndFactor() should use diagonal
|
||||
* pivoting as default. This issue only arises when
|
||||
* spOrderAndFactor() is called from spFactor().
|
||||
* SPACE_FOR_ELEMENTS
|
||||
* This number multiplied by the size of the matrix equals the number
|
||||
* of elements for which memory is initially allocated in
|
||||
* spCreate(). [6]
|
||||
* SPACE_FOR_FILL_INS
|
||||
* This number multiplied by the size of the matrix equals the number
|
||||
* of elements for which memory is initially allocated and specifically
|
||||
* reserved for fill-ins in spCreate(). [4]
|
||||
* ELEMENTS_PER_ALLOCATION
|
||||
* The number of matrix elements requested from the tmalloc utility on
|
||||
* each call to it. Setting this value greater than 1 reduces the
|
||||
* amount of overhead spent in this system call. On a virtual memory
|
||||
* machine, its good to allocate slightly less than a page worth of
|
||||
* elements at a time (or some multiple thereof).
|
||||
* [For the VAX, for real only use 41, otherwise use 31]
|
||||
* MINIMUM_ALLOCATED_SIZE
|
||||
* The minimum allocated size of a matrix. Note that this does not
|
||||
* limit the minimum size of a matrix. This just prevents having to
|
||||
* resize a matrix many times if the matrix is expandable, large and
|
||||
* allocated with an estimated size of zero. This number should not
|
||||
* be less than one.
|
||||
* EXPANSION_FACTOR
|
||||
* The amount the allocated size of the matrix is increased when it
|
||||
* is expanded.
|
||||
* MAX_MARKOWITZ_TIES
|
||||
* This number is used for two slightly different things, both of which
|
||||
* relate to the search for the best pivot. First, it is the maximum
|
||||
* number of elements that are Markowitz tied that will be sifted
|
||||
* through when trying to find the one that is numerically the best.
|
||||
* Second, it creates an upper bound on how large a Markowitz product
|
||||
* can be before it eliminates the possibility of early termination
|
||||
* of the pivot search. In other words, if the product of the smallest
|
||||
* Markowitz product yet found and TIES_MULTIPLIER is greater than
|
||||
* MAX_MARKOWITZ_TIES, then no early termination takes place.
|
||||
* Set MAX_MARKOWITZ_TIES to some small value if no early termination of
|
||||
* the pivot search is desired. An array of RealNumbers is allocated
|
||||
* of size MAX_MARKOWITZ_TIES so it must be positive and shouldn't
|
||||
* be too large. Active when MODIFIED_MARKOWITZ is 1 (true). [100]
|
||||
* TIES_MULTIPLIER
|
||||
* Specifies the number of Markowitz ties that are allowed to occur
|
||||
* before the search for the pivot is terminated early. Set to some
|
||||
* large value if no early termination of the pivot search is desired.
|
||||
* This number is multiplied times the Markowitz product to determine
|
||||
* how many ties are required for early termination. This means that
|
||||
* more elements will be searched before early termination if a large
|
||||
* number of fill-ins could be created by accepting what is currently
|
||||
* considered the best choice for the pivot. Active when
|
||||
* MODIFIED_MARKOWITZ is 1 (true). Setting this number to zero
|
||||
* effectively eliminates all pivoting, which should be avoided.
|
||||
* This number must be positive. TIES_MULTIPLIER is also used when
|
||||
* diagonal pivoting breaks down. [5]
|
||||
* DEFAULT_PARTITION
|
||||
* Which partition mode is used by spPartition() as default.
|
||||
* Possibilities include
|
||||
* spDIRECT_PARTITION -- each row used direct addressing, best for
|
||||
* a few relatively dense matrices.
|
||||
* spINDIRECT_PARTITION -- each row used indirect addressing, best
|
||||
* for a few very sparse matrices.
|
||||
* spAUTO_PARTITION -- direct or indirect addressing is chosen on
|
||||
* a row-by-row basis, carries a large overhead, but speeds up
|
||||
* both dense and sparse matrices, best if there is a large
|
||||
* number of matrices that can use the same ordering.
|
||||
*/
|
||||
|
||||
/* Begin constants. */
|
||||
#define DEFAULT_THRESHOLD 1.0e-3
|
||||
#define DIAG_PIVOTING_AS_DEFAULT YES
|
||||
#define SPACE_FOR_ELEMENTS 6
|
||||
#define SPACE_FOR_FILL_INS 4
|
||||
#define ELEMENTS_PER_ALLOCATION 31
|
||||
#define MINIMUM_ALLOCATED_SIZE 6
|
||||
#define EXPANSION_FACTOR 1.5
|
||||
#define MAX_MARKOWITZ_TIES 100
|
||||
#define TIES_MULTIPLIER 5
|
||||
#define DEFAULT_PARTITION spAUTO_PARTITION
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* PRINTER WIDTH
|
||||
*
|
||||
* This macro characterize the printer for the spPrint() routine.
|
||||
*
|
||||
* >>> Macros:
|
||||
* PRINTER_WIDTH
|
||||
* The number of characters per page width. Set to 80 for terminal,
|
||||
* 132 for line printer.
|
||||
*/
|
||||
|
||||
/* Begin printer constants. */
|
||||
#define PRINTER_WIDTH 80
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* MACHINE CONSTANTS
|
||||
*
|
||||
* These numbers must be updated when the program is ported to a new machine.
|
||||
*/
|
||||
|
||||
/* Begin machine constants. */
|
||||
|
||||
/*
|
||||
* Grab from Spice include files
|
||||
*/
|
||||
|
||||
#define MACHINE_RESOLUTION DBL_EPSILON
|
||||
#define LARGEST_REAL DBL_MAX
|
||||
#define SMALLEST_REAL DBL_MIN
|
||||
#define LARGEST_SHORT_INTEGER SHRT_MAX
|
||||
#define LARGEST_LONG_INTEGER LONG_MAX
|
||||
|
||||
|
||||
/*
|
||||
* ANNOTATION
|
||||
*
|
||||
* This macro changes the amount of annotation produced by the matrix
|
||||
* routines. The annotation is used as a debugging aid. Change the number
|
||||
* associated with ANNOTATE to change the amount of annotation produced by
|
||||
* the program.
|
||||
*/
|
||||
|
||||
/* Begin annotation definitions. */
|
||||
#define ANNOTATE NONE
|
||||
|
||||
#define NONE 0
|
||||
#define ON_STRANGE_BEHAVIOR 1
|
||||
#define FULL 2
|
||||
|
||||
#endif /* spINSIDE_SPARSE */
|
||||
#endif
|
||||
|
|
@ -23,10 +23,9 @@
|
|||
*/
|
||||
|
||||
#define spINSIDE_SPARSE
|
||||
#include "spconfig.h"
|
||||
#include "spConfig.h"
|
||||
#include "ngspice/spmatrix.h"
|
||||
#include "spdefs.h"
|
||||
|
||||
#include "spDefs.h"
|
||||
|
||||
void
|
||||
spConstMult(MatrixPtr matrix, double constant)
|
||||
|
|
|
|||
Loading…
Reference in New Issue