1 /* EXPORTS for sparse matrix routines. */ 2 /*! 3 * \file 4 * 5 * This file contains definitions that are useful to the calling 6 * program. In particular, this file contains error keyword 7 * definitions, some macro functions that are used to quickly enter 8 * data into the matrix and the type definition of a data structure 9 * that acts as a template for entering admittances into the matrix. 10 * Also included is the type definitions for the various functions 11 * available to the user. 12 * 13 * Objects that begin with the \a spc prefix are considered private 14 * and should not be used. 15 * 16 * \author 17 * Kenneth S. Kundert <kundert@users.sourceforge.net> 18 */ 19 20 21 /* 22 * Revision and copyright information. 23 * 24 * Copyright (c) 1985-2003 by Kenneth S. Kundert 25 * 26 */ 27 28 29 #ifndef spOKAY 30 31 /* 32 * IMPORTS 33 * 34 * >>> Import descriptions: 35 * spConfig.h 36 * Macros that customize the sparse matrix routines. 37 */ 38 39 #include "spConfig.h" 40 41 /* 42 * ERROR KEYWORDS 43 * 44 * The actual numbers used in the error codes are not sacred, they can be 45 * changed under the condition that the codes for the nonfatal errors are 46 * less than the code for spFATAL and similarly the codes for the fatal 47 * errors are greater than that for spFATAL. 48 */ 49 50 /* Begin error macros. */ 51 #define spOKAY 0 /*!< 52 * Error code that indicates that no error has 53 * occurred. 54 */ 55 #define spSMALL_PIVOT 1 /*!< 56 * Non-fatal error code that indicates that, when 57 * reordering the matrix, no element was found that 58 * satisfies the absolute threshold criteria. The 59 * largest element in the matrix was chosen as pivot. 60 */ 61 #define spZERO_DIAG 2 /*!< 62 * Fatal error code that indicates that, a zero was 63 * encountered on the diagonal the matrix. This does 64 * not necessarily imply that the matrix is singular. 65 * When this error occurs, the matrix should be 66 * reconstructed and factored using 67 * spOrderAndFactor(). 68 */ 69 #define spSINGULAR 3 /*!< 70 * Fatal error code that indicates that, matrix is 71 * singular, so no unique solution exists. 72 */ 73 #define spMANGLED 4 /*!< 74 * Fatal error code that indicates that, matrix has 75 * been mangled, results of requested operation are 76 * garbage. 77 */ 78 #define spNO_MEMORY 5 /*!< 79 * Fatal error code that indicates that not enough 80 * memory is available. 81 */ 82 #define spPANIC 6 /*!< 83 * Fatal error code that indicates that the routines 84 * are not prepared to handle the matrix that has 85 * been requested. This may occur when the matrix 86 * is specified to be real and the routines are not 87 * compiled for real matrices, or when the matrix is 88 * specified to be complex and the routines are not 89 * compiled to handle complex matrices. 90 */ 91 #define spFATAL 2 /*!< 92 * Error code that is not an error flag, but rather 93 * the dividing line between fatal errors and 94 * warnings. 95 */ 96 97 98 /* 99 * KEYWORD DEFINITIONS 100 */ 101 102 #define spREAL double /*!< 103 * Defines the precision of the arithmetic used by 104 * \a Sparse will use. Double precision is suggested 105 * as being most appropriate for circuit simulation 106 * and for C. However, it is possible to change spREAL 107 * to a float for single precision arithmetic. Note 108 * that in C, single precision arithmetic is often 109 * slower than double precision. Sparse 110 * internally refers to spREALs as RealNumbers. 111 */ 112 113 114 /* 115 * PARTITION TYPES 116 * 117 * When factoring a previously ordered matrix using spFactor(), Sparse 118 * operates on a row-at-a-time basis. For speed, on each step, the row 119 * being updated is copied into a full vector and the operations are 120 * performed on that vector. This can be done one of two ways, either 121 * using direct addressing or indirect addressing. Direct addressing 122 * is fastest when the matrix is relatively dense and indirect addressing 123 * is quite sparse. The user can select which partitioning mode is used. 124 * The following keywords are passed to spPartition() and indicate that 125 * Sparse should use only direct addressing, only indirect addressing, or 126 * that it should choose the best mode on a row-by-row basis. The time 127 * required to choose a partition is of the same order of the cost to factor 128 * the matrix. 129 * 130 * If you plan to factor a large number of matrices with the same structure, 131 * it is best to let Sparse choose the partition. Otherwise, you should 132 * choose the partition based on the predicted density of the matrix. 133 */ 134 135 /* Begin partition keywords. */ 136 137 #define spDEFAULT_PARTITION 0 /*!< 138 * Partition code for spPartition(). 139 * Indicates that the default partitioning 140 * mode should be used. 141 * \see spPartition() 142 */ 143 #define spDIRECT_PARTITION 1 /*!< 144 * Partition code for spPartition(). 145 * Indicates that all rows should be placed 146 * in the direct addressing partition. 147 * \see spPartition() 148 */ 149 #define spINDIRECT_PARTITION 2 /*!< 150 * Partition code for spPartition(). 151 * Indicates that all rows should be placed 152 * in the indirect addressing partition. 153 * \see spPartition() 154 */ 155 #define spAUTO_PARTITION 3 /*!< 156 * Partition code for spPartition(). 157 * Indicates that \a Sparse should chose 158 * the best partition for each row based 159 * on some simple rules. This is generally 160 * preferred. 161 * \see spPartition() 162 */ 163 164 /* 165 * MACRO FUNCTION DEFINITIONS 166 */ 167 168 /* Begin Macros. */ 169 /*! 170 * Macro function that adds data to a real element in the matrix by a pointer. 171 */ 172 #define spADD_REAL_ELEMENT(element,real) *(element) += real 173 174 /*! 175 * Macro function that adds data to a imaginary element in the matrix by 176 * a pointer. 177 */ 178 #define spADD_IMAG_ELEMENT(element,imag) *((element)+1) += imag 179 180 /*! 181 * Macro function that adds data to a complex element in the matrix by 182 * a pointer. 183 */ 184 #define spADD_COMPLEX_ELEMENT(element,real,imag) \ 185 { *(element) += (real); \ 186 *((element)+1) += (imag); \ 187 } 188 189 /*! 190 * Macro function that adds data to each of the four real matrix elements 191 * specified by the given template. 192 */ 193 #define spADD_REAL_QUAD(template,real) \ 194 { *((template).Element1) += (real); \ 195 *((template).Element2) += (real); \ 196 *((template).Element3Negated) -= (real); \ 197 *((template).Element4Negated) -= (real); \ 198 } 199 200 /*! 201 * Macro function that adds data to each of the four imaginary matrix 202 * elements specified by the given template. 203 */ 204 #define spADD_IMAG_QUAD(template,imag) \ 205 { *((template).Element1+1) += (imag); \ 206 *((template).Element2+1) += (imag); \ 207 *((template).Element3Negated+1) -= (imag); \ 208 *((template).Element4Negated+1) -= (imag); \ 209 } 210 211 /*! 212 * Macro function that adds data to each of the four complex matrix 213 * elements specified by the given template. 214 */ 215 #define spADD_COMPLEX_QUAD(template,real,imag) \ 216 { *((template).Element1) += (real); \ 217 *((template).Element2) += (real); \ 218 *((template).Element3Negated) -= (real); \ 219 *((template).Element4Negated) -= (real); \ 220 *((template).Element1+1) += (imag); \ 221 *((template).Element2+1) += (imag); \ 222 *((template).Element3Negated+1) -= (imag); \ 223 *((template).Element4Negated+1) -= (imag); \ 224 } 225 226 /* 227 * TYPE DEFINITION FOR EXTERNAL MATRIX ELEMENT REFERENCES 228 * 229 * External type definitions for Sparse data objects. 230 */ 231 232 /*! Declares the type of the a pointer to a matrix. */ 233 typedef spGenericPtr spMatrix; 234 235 /*! Declares the type of the a pointer to a matrix element. */ 236 typedef spREAL spElement; 237 238 /*! Declares the type of the Sparse error codes. */ 239 typedef int spError; 240 241 /* TYPE DEFINITION FOR COMPONENT TEMPLATE */ 242 /*! 243 * This data structure is used to hold pointers to four related elements in 244 * matrix. It is used in conjunction with the routines spGetAdmittance(), 245 * spGetQuad(), and spGetOnes(). These routines stuff the structure which 246 * is later used by the \a spADD_QUAD macro functions above. It is also 247 * possible for the user to collect four pointers returned by spGetElement() 248 * and stuff them into the template. The \a spADD_QUAD routines stuff data 249 * into the matrix in locations specified by \a Element1 and \a Element2 250 * without changing the data. The data is negated before being placed in 251 * \a Element3 and \a Element4. 252 */ 253 254 /* Begin `spTemplate'. */ 255 struct spTemplate 256 { spElement *Element1; 257 spElement *Element2; 258 spElement *Element3Negated; 259 spElement *Element4Negated; 260 }; 261 262 263 /* 264 * FUNCTION TYPE DEFINITIONS 265 * 266 * The type of every user accessible function is declared here. 267 */ 268 269 /* Begin function declarations. */ 270 271 spcEXTERN void spClear( spMatrix ); 272 spcEXTERN spREAL spCondition( spMatrix, spREAL, int* ); 273 spcEXTERN spMatrix spCreate( int, int, spError* ); 274 spcEXTERN void spDeleteRowAndCol( spMatrix, int, int ); 275 spcEXTERN void spDestroy( spMatrix ); 276 spcEXTERN int spElementCount( spMatrix ); 277 spcEXTERN spError spErrorState( spMatrix ); 278 279 spcEXTERN spError spFactor( spMatrix ); 280 /* Remove file IO due to archaic fopen method which gives warnings in windoz 281 spcEXTERN int spFileMatrix( spMatrix, char*, char*, int, int, int ); 282 spcEXTERN int spFileStats( spMatrix, char*, char* ); 283 */ 284 spcEXTERN int spFillinCount( spMatrix ); 285 spcEXTERN spElement *spFindElement( spMatrix, int, int ); 286 spcEXTERN spError spGetAdmittance( spMatrix, int, int, 287 struct spTemplate* ); 288 spcEXTERN spElement *spGetElement( spMatrix, int, int ); 289 spcEXTERN spGenericPtr spGetInitInfo( spElement* ); 290 spcEXTERN spError spGetOnes( spMatrix, int, int, int, 291 struct spTemplate* ); 292 spcEXTERN spError spGetQuad( spMatrix, int, int, int, int, 293 struct spTemplate* ); 294 spcEXTERN int spGetSize( spMatrix, int ); 295 spcEXTERN int spInitialize( spMatrix, int (*pInit)(spElement *, spGenericPtr, int, int) ); 296 spcEXTERN void spInstallInitInfo( spElement*, spGenericPtr ); 297 spcEXTERN spREAL spLargestElement( spMatrix ); 298 spcEXTERN void spMNA_Preorder( spMatrix ); 299 spcEXTERN spREAL spNorm( spMatrix ); 300 spcEXTERN spError spOrderAndFactor( spMatrix, spREAL[], spREAL, 301 spREAL, int ); 302 spcEXTERN void spPartition( spMatrix, int ); 303 spcEXTERN void spPrint( spMatrix, int, int, int ); 304 spcEXTERN void spRowColOrder( spMatrix, int*, int*); 305 spcEXTERN spREAL spPseudoCondition( spMatrix ); 306 spcEXTERN spREAL spRoundoff( spMatrix, spREAL ); 307 spcEXTERN void spScale( spMatrix, spREAL[], spREAL[] ); 308 spcEXTERN void spSetComplex( spMatrix ); 309 spcEXTERN void spSetReal( spMatrix ); 310 spcEXTERN void spStripFills( spMatrix ); 311 spcEXTERN void spWhereSingular( spMatrix, int*, int* ); 312 313 /* Functions with argument lists that are dependent on options. */ 314 315 #if spCOMPLEX 316 spcEXTERN void spDeterminant( spMatrix, int*, spREAL*, spREAL* ); 317 #else /* NOT spCOMPLEX */ 318 spcEXTERN void spDeterminant( spMatrix, int*, spREAL* ); 319 #endif /* NOT spCOMPLEX */ 320 #if spCOMPLEX && spSEPARATED_COMPLEX_VECTORS 321 /* Get rid of arcaic file IO 322 spcEXTERN int spFileVector( spMatrix, char* , 323 spREAL[], spREAL[]); 324 */ 325 spcEXTERN void spMultiply( spMatrix, spREAL[], spREAL[], 326 spREAL[], spREAL[] ); 327 spcEXTERN void spMultTransposed( spMatrix, spREAL[], spREAL[], 328 spREAL[], spREAL[] ); 329 spcEXTERN void spSolve( spMatrix, spREAL[], spREAL[], spREAL[], 330 spREAL[] ); 331 spcEXTERN void spSolveTransposed( spMatrix, spREAL[], spREAL[], 332 spREAL[], spREAL[] ); 333 #else /* NOT (spCOMPLEX && spSEPARATED_COMPLEX_VECTORS) */ 334 /* Get rid of arcaic file IO 335 spcEXTERN int spFileVector( spMatrix, char* , spREAL[] ); 336 */ 337 spcEXTERN void spMultiply( spMatrix, spREAL[], spREAL[] ); 338 spcEXTERN void spMultTransposed( spMatrix, 339 spREAL[], spREAL[] ); 340 spcEXTERN void spSolve( spMatrix, spREAL[], spREAL[] ); 341 spcEXTERN void spSolveTransposed( spMatrix, 342 spREAL[], spREAL[] ); 343 #endif /* NOT (spCOMPLEX && spSEPARATED_COMPLEX_VECTORS) */ 344 #endif /* spOKAY */ 345