00001 /* 00002 * MATRIX BUILD MODULE 00003 * 00004 * Author: Advising professor: 00005 * Kenneth S. Kundert Alberto Sangiovanni-Vincentelli 00006 * UC Berkeley 00007 * 00008 * This file contains the routines associated with clearing, loading and 00009 * preprocessing the matrix for the sparse matrix routines. 00010 * 00011 * >>> User accessible functions contained in this file: 00012 * spClear 00013 * spGetElement 00014 * spGetAdmittance 00015 * spGetQuad 00016 * spGetOnes 00017 * spInstallInitInfo 00018 * spGetInitInfo 00019 * spInitialize 00020 * 00021 * >>> Other functions contained in this file: 00022 * spcFindElementInCol 00023 * Translate 00024 * spcCreateElement 00025 * spcLinkRows 00026 * EnlargeMatrix 00027 * ExpandTranslationArrays 00028 */ 00029 00030 00031 /* 00032 * Revision and copyright information. 00033 * 00034 * Copyright (c) 1985,86,87,88 00035 * by Kenneth S. Kundert and the University of California. 00036 * 00037 * Permission to use, copy, modify, and distribute this software and 00038 * its documentation for any purpose and without fee is hereby granted, 00039 * provided that the copyright notices appear in all copies and 00040 * supporting documentation and that the authors and the University of 00041 * California are properly credited. The authors and the University of 00042 * California make no representations as to the suitability of this 00043 * software for any purpose. It is provided `as is', without express 00044 * or implied warranty. 00045 * 00046 * IMPORTS 00047 * 00048 * >>> Import descriptions: 00049 * spConfig.h 00050 * Macros that customize the sparse matrix routines. 00051 * spmatrix.h 00052 * Macros and declarations to be imported by the user. 00053 * spDefs.h 00054 * Matrix type and macro definitions for the sparse matrix routines. 00055 */ 00056 00057 #define spINSIDE_SPARSE 00058 #include "spconfig.h" 00059 #include "spmatrix.h" 00060 /* 00061 * CLEAR MATRIX 00062 * 00063 * Sets every element of the matrix to zero and clears the error flag. 00064 * 00065 * >>> Arguments: 00066 * Matrix <input> (char *) 00067 * Pointer to matrix that is to be cleared. 00068 * 00069 * >>> Local variables: 00070 * pElement (ElementPtr) 00071 * A pointer to the element being cleared. 00072 */ 00073 //static void ExpandTranslationArrays(MatrixPtr Matrix, int NewSize ); 00074 static void EnlargeMatrix(MatrixPtr Matrix, int NewSize ); 00075 extern ElementPtr spcGetFillin(MatrixPtr Matrix); 00076 extern ElementPtr spcGetElement(MatrixPtr Matrix); 00077 00078 void spClear(MatrixPtr Matrix) 00079 { 00080 ElementPtr pElement; 00081 int I; 00082 00083 /* Begin `spClear'. */ 00084 ASSERT( IS_SPARSE( Matrix ) ); 00085 00086 /* Clear matrix. */ 00087 { for (I = Matrix->Size; I > 0; I--) 00088 { pElement = Matrix->FirstInCol[I]; 00089 while (pElement != NULL) 00090 { pElement->Real = 0.0; 00091 pElement = pElement->NextInCol; 00092 } 00093 } 00094 } 00095 00096 /* Empty the trash. */ 00097 Matrix->TrashCan.Real = 0.0; 00098 Matrix->Error = spOKAY; 00099 Matrix->Factored = 0; 00100 Matrix->SingularCol = 0; 00101 Matrix->SingularRow = 0; 00102 return; 00103 } 00104 00105 #if TRANSLATE 00106 /* 00107 * TRANSLATE EXTERNAL INDICES TO INTERNAL 00108 * 00109 * Convert internal row and column numbers to internal row and column numbers. 00110 * Also updates Ext/Int maps. 00111 * 00112 * 00113 * >>> Arguments: 00114 * Matrix <input> (MatrixPtr) 00115 * Pointer to the matrix. 00116 * Row <input/output> (int *) 00117 * Upon entry Row is either a external row number of an external node 00118 * number. Upon entry, the internal equivalent is supplied. 00119 * Col <input/output> (int *) 00120 * Upon entry Column is either a external column number of an external node 00121 * number. Upon entry, the internal equivalent is supplied. 00122 * 00123 * >>> Local variables: 00124 * ExtCol (int) 00125 * Temporary variable used to hold the external column or node number 00126 * during the external to internal column number translation. 00127 * ExtRow (int) 00128 * Temporary variable used to hold the external row or node number during 00129 * the external to internal row number translation. 00130 * IntCol (int) 00131 * Temporary variable used to hold the internal column or node number 00132 * during the external to internal column number translation. 00133 * IntRow (int) 00134 * Temporary variable used to hold the internal row or node number during 00135 * the external to internal row number translation. 00136 */ 00137 00138 static void Translate(MatrixPtr Matrix, int *Row, int *Col ) 00139 { 00140 int IntRow, IntCol, ExtRow = *Row, ExtCol = *Col; 00141 00142 /* Expand translation arrays if necessary. */ 00143 if ((ExtRow > Matrix->AllocatedExtSize) || (ExtCol > Matrix->AllocatedExtSize)) 00144 { 00145 ExpandTranslationArrays( Matrix, MAX(ExtRow, ExtCol)); 00146 if (Matrix->Error == spNO_MEMORY) return; 00147 } 00148 00149 /* Set ExtSize if necessary. */ 00150 if ((ExtRow > Matrix->ExtSize) || (ExtCol > Matrix->ExtSize)) 00151 Matrix->ExtSize = MAX(ExtRow, ExtCol); 00152 00153 /* Translate external row or node number to internal row or node number. */ 00154 if ((IntRow = Matrix->ExtToIntRowMap[ExtRow]) == -1) 00155 { Matrix->ExtToIntRowMap[ExtRow] = ++Matrix->CurrentSize; 00156 Matrix->ExtToIntColMap[ExtRow] = Matrix->CurrentSize; 00157 IntRow = Matrix->CurrentSize; 00158 00159 #if !EXPANDABLE 00160 ASSERT(IntRow <= Matrix->Size); 00161 #endif 00162 00163 #if EXPANDABLE 00164 /* Re-size Matrix if necessary. */ 00165 if (IntRow > Matrix->Size) 00166 EnlargeMatrix( Matrix, IntRow ); 00167 if (Matrix->Error == spNO_MEMORY) return; 00168 #endif 00169 00170 Matrix->IntToExtRowMap[IntRow] = ExtRow; 00171 Matrix->IntToExtColMap[IntRow] = ExtRow; 00172 } 00173 00174 /* Translate external column or node number to internal column or node number.*/ 00175 if ((IntCol = Matrix->ExtToIntColMap[ExtCol]) == -1) 00176 { Matrix->ExtToIntRowMap[ExtCol] = ++Matrix->CurrentSize; 00177 Matrix->ExtToIntColMap[ExtCol] = Matrix->CurrentSize; 00178 IntCol = Matrix->CurrentSize; 00179 00180 #if !EXPANDABLE 00181 ASSERT(IntCol <= Matrix->Size); 00182 #endif 00183 00184 #if EXPANDABLE 00185 /* Re-size Matrix if necessary. */ 00186 if (IntCol > Matrix->Size) 00187 EnlargeMatrix( Matrix, IntCol ); 00188 if (Matrix->Error == spNO_MEMORY) return; 00189 #endif 00190 00191 Matrix->IntToExtRowMap[IntCol] = ExtCol; 00192 Matrix->IntToExtColMap[IntCol] = ExtCol; 00193 } 00194 00195 *Row = IntRow; 00196 *Col = IntCol; 00197 return; 00198 } 00199 #endif 00200 00201 /* 00202 * 00203 * CREATE && SPLICE ELEMENT INTO MATRIX 00204 * 00205 * This routine is used to create new matrix elements and splice them into the 00206 * matrix. 00207 * 00208 * >>> Returned: 00209 * A pointer to the element that was created is returned. 00210 * 00211 * >>> Arguments: 00212 * Matrix <input> (MatrixPtr) 00213 * Pointer to matrix. 00214 * Row <input> (int) 00215 * Row index for element. 00216 * Col <input> (int) 00217 * Column index for element. 00218 * LastAddr <input-output> (ElementPtr *) 00219 * This contains the address of the pointer to the element just above the 00220 * one being created. It is used to speed the search and it is updated with 00221 * address of the created element. 00222 * Fillin <input> (BOOLEAN) 00223 * Flag that indicates if created element is to be a fill-in. 00224 * 00225 * >>> Local variables: 00226 * pElement (ElementPtr) 00227 * Pointer to an element in the matrix. It is used to refer to the newly 00228 * created element and to restring the pointers of the element's row and 00229 * column. 00230 * pLastElement (ElementPtr) 00231 * Pointer to the element in the matrix that was just previously pointed 00232 * to by pElement. It is used to restring the pointers of the element's 00233 * row and column. 00234 * pCreatedElement (ElementPtr) 00235 * Pointer to the desired element, the one that was just created. 00236 * 00237 * >>> Possible errors: 00238 * spNO_MEMORY 00239 */ 00240 ElementPtr spcCreateElement(MatrixPtr Matrix, int Row, int Col, ElementPtr *LastAddr, BOOLEAN Fillin) 00241 { 00242 ElementPtr pElement, pLastElement, pCreatedElement; 00243 00244 if (Matrix->RowsLinked) 00245 { 00246 /* Row pointers cannot be ignored. */ 00247 if (Fillin) 00248 { 00249 pElement = spcGetFillin(Matrix); 00250 Matrix->Fillins++; 00251 } 00252 else 00253 { 00254 pElement = spcGetElement(Matrix); 00255 Matrix->NeedsOrdering = 1; 00256 } 00257 if (pElement == NULL) return NULL; 00258 00259 /* If element is on diagonal, store pointer in Diag. */ 00260 if (Row == Col) Matrix->Diag[Row] = pElement; 00261 00262 /* Initialize Element. */ 00263 pCreatedElement = pElement; 00264 pElement->Row = Row; 00265 pElement->Col = Col; 00266 pElement->Real = 0.0; 00267 #if INITIALIZE 00268 pElement->pInitInfo = NULL; 00269 #endif 00270 00271 /* Splice element into column. */ 00272 pElement->NextInCol = *LastAddr; 00273 *LastAddr = pElement; 00274 00275 /* Search row for proper element position. */ 00276 pElement = Matrix->FirstInRow[Row]; 00277 pLastElement = NULL; 00278 while (pElement != NULL) 00279 { 00280 /* Search for element row position. */ 00281 if (pElement->Col < Col) 00282 { 00283 /* Have not reached desired element. */ 00284 pLastElement = pElement; 00285 pElement = pElement->NextInRow; 00286 } 00287 else pElement = NULL; 00288 } 00289 00290 /* Splice element into row. */ 00291 pElement = pCreatedElement; 00292 if (pLastElement == NULL) 00293 { 00294 /* Element is first in row. */ 00295 pElement->NextInRow = Matrix->FirstInRow[Row]; 00296 Matrix->FirstInRow[Row] = pElement; 00297 } 00298 else 00299 /* Element is not first in row. */ 00300 { 00301 pElement->NextInRow = pLastElement->NextInRow; 00302 pLastElement->NextInRow = pElement; 00303 } 00304 } 00305 else 00306 { 00307 /* 00308 * Matrix has not been factored yet. Thus get element rather than fill-in. 00309 * Also, row pointers can be ignored. 00310 */ 00311 /* Allocate memory for Element. */ 00312 pElement = spcGetElement(Matrix); 00313 if (pElement == NULL) return NULL; 00314 00315 /* If element is on diagonal, store pointer in Diag. */ 00316 if (Row == Col) Matrix->Diag[Row] = pElement; 00317 00318 /* Initialize Element. */ 00319 pCreatedElement = pElement; 00320 pElement->Row = Row; 00321 #if DEBUG 00322 pElement->Col = Col; 00323 #endif 00324 pElement->Real = 0.0; 00325 #if INITIALIZE 00326 pElement->pInitInfo = NULL; 00327 #endif 00328 00329 /* Splice element into column. */ 00330 pElement->NextInCol = *LastAddr; 00331 *LastAddr = pElement; 00332 } 00333 00334 Matrix->Elements++; 00335 return pCreatedElement; 00336 } 00337 00338 00339 00340 /* 00341 * FIND ELEMENT BY SEARCHING COLUMN 00342 * 00343 * Searches column starting at element specified at PtrAddr and finds element 00344 * in Row. If Element does not exists, it is created. The pointer to the 00345 * element is returned. 00346 * 00347 * >>> Returned: 00348 * A pointer to the desired element: 00349 * 00350 * >>> Arguments: 00351 * Matrix <input> (MatrixPtr) 00352 * Pointer to Matrix. 00353 * LastAddr <input-output> (ElementPtr *) 00354 * Address of pointer that initially points to the element in Col at which 00355 * the search is started. The pointer in this location may be changed if 00356 * a fill-in is required in and adjacent element. For this reason it is 00357 * important that LastAddr be the address of a FirstInCol or a NextInCol 00358 * rather than a temporary variable. 00359 * Row <input> (int) 00360 * Row being searched for. 00361 * Col (int) 00362 * Column being searched. 00363 * CreateIfMissing <input> (BOOLEAN) 00364 * Indicates what to do if element is not found, create one or return a 00365 * NULL pointer. 00366 * 00367 * Local variables: 00368 * pElement (ElementPtr) 00369 * Pointer used to search through matrix. 00370 */ 00371 00372 ElementPtr spcFindElementInCol(MatrixPtr Matrix, ElementPtr *LastAddr, int Row, int Col, BOOLEAN CreateIfMissing) 00373 { 00374 ElementPtr pElement = *LastAddr; 00375 //ElementPtr spcCreateElement(); 00376 00377 /* Search for element. */ 00378 while (pElement != NULL) 00379 { 00380 if (pElement->Row < Row) 00381 { 00382 /* Have not reached element yet. */ 00383 LastAddr = &(pElement->NextInCol); 00384 pElement = pElement->NextInCol; 00385 } 00386 else if (pElement->Row == Row) 00387 { 00388 /* Reached element. */ 00389 return pElement; 00390 } 00391 else break; /* while loop */ 00392 } 00393 00394 /* Element does not exist and must be created. */ 00395 if (CreateIfMissing) 00396 return spcCreateElement( Matrix, Row, Col, LastAddr, 0); 00397 else 00398 return NULL; 00399 } 00400 /* 00401 * SINGLE ELEMENT ADDITION TO MATRIX BY INDEX 00402 * 00403 * Finds element [Row,Col] and returns a pointer to it. If element is 00404 * not found then it is created and spliced into matrix. This routine 00405 * is only to be used after spCreate() and before spMNA_Preorder(), 00406 * spFactor() or spOrderAndFactor(). Returns a pointer to the 00407 * Real portion of a MatrixElement. This pointer is later used by 00408 * spADD_xxx_ELEMENT to directly access element. 00409 * 00410 * >>> Returns: 00411 * Returns a pointer to the element. This pointer is then used to directly 00412 * access the element during successive builds. 00413 * 00414 * >>> Arguments: 00415 * Matrix <input> (char *) 00416 * Pointer to the matrix that the element is to be added to. 00417 * Row <input> (int) 00418 * Row index for element. Must be in the range of [0..Size] unless 00419 * the options EXPANDABLE or TRANSLATE are used. Elements placed in 00420 * row zero are discarded. In no case may Row be less than zero. 00421 * Col <input> (int) 00422 * Column index for element. Must be in the range of [0..Size] unless 00423 * the options EXPANDABLE or TRANSLATE are used. Elements placed in 00424 * column zero are discarded. In no case may Col be less than zero. 00425 * 00426 * >>> Local variables: 00427 * pElement (double *) 00428 * Pointer to the element. 00429 * 00430 * >>> Possible errors: 00431 * spNO_MEMORY 00432 * Error is not cleared in this routine. 00433 */ 00434 ElementPtr spGetElement(MatrixPtr Matrix, int Row, int Col) 00435 { 00436 ElementPtr pElement; 00437 ASSERT( IS_SPARSE( Matrix ) && Row >= 0 && Col >= 0 ); 00438 if ((Row == 0) || (Col == 0)) 00439 return &Matrix->TrashCan; 00440 00441 #if !TRANSLATE 00442 ASSERT(Matrix->NeedsOrdering); 00443 #endif 00444 00445 #if TRANSLATE 00446 Translate(Matrix, &Row, &Col); 00447 if (Matrix->Error == spNO_MEMORY) return NULL; 00448 #endif 00449 00450 #if !TRANSLATE 00451 #if !EXPANDABLE 00452 ASSERT(Row <= Matrix->Size && Col <= Matrix->Size); 00453 #endif 00454 00455 #if EXPANDABLE 00456 /* Re-size Matrix if necessary. */ 00457 if ((Row > Matrix->Size) || (Col > Matrix->Size)) 00458 EnlargeMatrix( Matrix, MAX(Row, Col) ); 00459 if (Matrix->Error == spNO_MEMORY) return NULL; 00460 #endif 00461 #endif 00462 /* 00463 * The condition part of the following if statement tests to see if the 00464 * element resides along the diagonal, if it does then it tests to see 00465 * if the element has been created yet (Diag pointer not NULL). The 00466 * pointer to the element is then assigned to Element after it is cast 00467 * into a pointer to a double. This casting makes the pointer into 00468 * a pointer to Real. This statement depends on the fact that Real 00469 * is the first record in the MatrixElement structure. 00470 */ 00471 if (Row != Col || (pElement = Matrix->Diag[Row]) == NULL) 00472 return spcFindElementInCol(Matrix, &(Matrix->FirstInCol[Col]), Row, Col, 1); 00473 return pElement; 00474 } 00475 00476 #if QUAD_ELEMENT 00477 /* 00478 * ADDITION OF ADMITTANCE TO MATRIX BY INDEX 00479 * 00480 * Performs same function as spGetElement except rather than one 00481 * element, all four Matrix elements for a floating component are 00482 * added. This routine also works if component is grounded. Positive 00483 * elements are placed at [Node1,Node2] and [Node2,Node1]. This 00484 * routine is only to be used after spCreate() and before 00485 * spMNA_Preorder(), spFactor() or spOrderAndFactor(). 00486 * 00487 * >>> Returns: 00488 * Error code. 00489 * 00490 * >>> Arguments: 00491 * Matrix <input> (char *) 00492 * Pointer to the matrix that component is to be entered in. 00493 * Node1 <input> (int) 00494 * Row and column indices for elements. Must be in the range of [0..Size] 00495 * unless the options EXPANDABLE or TRANSLATE are used. Node zero is the 00496 * ground node. In no case may Node1 be less than zero. 00497 * Node2 <input> (int) 00498 * Row and column indices for elements. Must be in the range of [0..Size] 00499 * unless the options EXPANDABLE or TRANSLATE are used. Node zero is the 00500 * ground node. In no case may Node2 be less than zero. 00501 * Template <output> (struct spTemplate *) 00502 * Collection of pointers to four elements that are later used to directly 00503 * address elements. User must supply the template, this routine will 00504 * fill it. 00505 * 00506 * Possible errors: 00507 * spNO_MEMORY 00508 * Error is not cleared in this routine. 00509 */ 00510 00511 int spGetAdmittance(MatrixPtr Matrix, int Node1, int Node2, struct spTemplate *Template) 00512 { 00513 Template->Element1 = spGetElement(Matrix, Node1, Node1 ); 00514 Template->Element2 = spGetElement(Matrix, Node2, Node2 ); 00515 Template->Element3Negated = spGetElement( Matrix, Node2, Node1 ); 00516 Template->Element4Negated = spGetElement( Matrix, Node1, Node2 ); 00517 if (Template->Element1 == NULL || Template->Element2 == NULL 00518 || Template->Element3Negated == NULL || Template->Element4Negated == NULL) 00519 return spNO_MEMORY; 00520 if (Node1 == 0) 00521 SWAP( ElementPtr, Template->Element1, Template->Element2 ); 00522 return spOKAY; 00523 } 00524 #endif /* QUAD_ELEMENT */ 00525 00526 #if QUAD_ELEMENT 00527 /* 00528 * ADDITION OF FOUR ELEMENTS TO MATRIX BY INDEX 00529 * 00530 * Similar to spGetAdmittance, except that spGetAdmittance only 00531 * handles 2-terminal components, whereas spGetQuad handles simple 00532 * 4-terminals as well. These 4-terminals are simply generalized 00533 * 2-terminals with the option of having the sense terminals different 00534 * from the source and sink terminals. spGetQuad adds four 00535 * elements to the matrix. Positive elements occur at Row1,Col1 00536 * Row2,Col2 while negative elements occur at Row1,Col2 and Row2,Col1. 00537 * The routine works fine if any of the rows and columns are zero. 00538 * This routine is only to be used after spCreate() and before 00539 * spMNA_Preorder(), spFactor() or spOrderAndFactor() 00540 * unless TRANSLATE is set true. 00541 * 00542 * >>> Returns: 00543 * Error code. 00544 * 00545 * >>> Arguments: 00546 * Matrix <input> (char *) 00547 * Pointer to the matrix that component is to be entered in. 00548 * Row1 <input> (int) 00549 * First row index for elements. Must be in the range of [0..Size] 00550 * unless the options EXPANDABLE or TRANSLATE are used. Zero is the 00551 * ground row. In no case may Row1 be less than zero. 00552 * Row2 <input> (int) 00553 * Second row index for elements. Must be in the range of [0..Size] 00554 * unless the options EXPANDABLE or TRANSLATE are used. Zero is the 00555 * ground row. In no case may Row2 be less than zero. 00556 * Col1 <input> (int) 00557 * First column index for elements. Must be in the range of [0..Size] 00558 * unless the options EXPANDABLE or TRANSLATE are used. Zero is the 00559 * ground column. In no case may Col1 be less than zero. 00560 * Col2 <input> (int) 00561 * Second column index for elements. Must be in the range of [0..Size] 00562 * unless the options EXPANDABLE or TRANSLATE are used. Zero is the 00563 * ground column. In no case may Col2 be less than zero. 00564 * Template <output> (struct spTemplate *) 00565 * Collection of pointers to four elements that are later used to directly 00566 * address elements. User must supply the template, this routine will 00567 * fill it. 00568 * Real <input> (double) 00569 * Real data to be added to elements. 00570 * Imag <input> (double) 00571 * Imag data to be added to elements. If matrix is real, this argument 00572 * may be deleted. 00573 * 00574 * Possible errors: 00575 * spNO_MEMORY 00576 * Error is not cleared in this routine. 00577 */ 00578 int spGetQuad( MatrixPtr Matrix, int Row1, int Row2, int Col1, int Col2, struct spTemplate *Template ) 00579 { 00580 Template->Element1 = spGetElement( Matrix, Row1, Col1); 00581 Template->Element2 = spGetElement( Matrix, Row2, Col2 ); 00582 Template->Element3Negated = spGetElement( Matrix, Row2, Col1 ); 00583 Template->Element4Negated = spGetElement( Matrix, Row1, Col2 ); 00584 if (Template->Element1 == NULL || Template->Element2 == NULL 00585 || Template->Element3Negated == NULL || Template->Element4Negated == NULL) 00586 return spNO_MEMORY; 00587 if (Template->Element1 == &(Matrix->TrashCan)) 00588 SWAP(ElementPtr, Template->Element1, Template->Element2 ); 00589 return spOKAY; 00590 } 00591 #endif /* QUAD_ELEMENT */ 00592 00593 #if QUAD_ELEMENT 00594 /* 00595 * ADDITION OF FOUR STRUCTURAL ONES TO MATRIX BY INDEX 00596 * 00597 * Performs similar function to spGetQuad() except this routine is 00598 * meant for components that do not have an admittance representation. 00599 * 00600 * The following stamp is used: 00601 * Pos Neg Eqn 00602 * Pos [ . . 1 ] 00603 * Neg [ . . -1 ] 00604 * Eqn [ 1 -1 . ] 00605 * 00606 * >>> Returns: 00607 * Error code. 00608 * 00609 * >>> Arguments: 00610 * Matrix <input> (char *) 00611 * Pointer to the matrix that component is to be entered in. 00612 * Pos <input> (int) 00613 * See stamp above. Must be in the range of [0..Size] 00614 * unless the options EXPANDABLE or TRANSLATE are used. Zero is the 00615 * ground row. In no case may Pos be less than zero. 00616 * Neg <input> (int) 00617 * See stamp above. Must be in the range of [0..Size] 00618 * unless the options EXPANDABLE or TRANSLATE are used. Zero is the 00619 * ground row. In no case may Neg be less than zero. 00620 * Eqn <input> (int) 00621 * See stamp above. Must be in the range of [0..Size] 00622 * unless the options EXPANDABLE or TRANSLATE are used. Zero is the 00623 * ground row. In no case may Eqn be less than zero. 00624 * Template <output> (struct spTemplate *) 00625 * Collection of pointers to four elements that are later used to directly 00626 * address elements. User must supply the template, this routine will 00627 * fill it. 00628 * 00629 * Possible errors: 00630 * spNO_MEMORY 00631 * Error is not cleared in this routine. 00632 */ 00633 int spGetOnes(MatrixPtr Matrix, int Pos, int Neg, int Eqn, struct spTemplate *Template) 00634 { 00635 Template->Element4Negated = spGetElement( Matrix, Neg, Eqn ); 00636 Template->Element3Negated = spGetElement( Matrix, Eqn, Neg ); 00637 Template->Element2 = spGetElement( Matrix, Pos, Eqn ); 00638 Template->Element1 = spGetElement( Matrix, Eqn, Pos ); 00639 if (Template->Element1 == NULL || Template->Element2 == NULL 00640 || Template->Element3Negated == NULL || Template->Element4Negated == NULL) 00641 return spNO_MEMORY; 00642 spADD_REAL_QUAD(Template, 1.0); 00643 return spOKAY; 00644 } 00645 #endif /* QUAD_ELEMENT */ 00646 /* 00647 * 00648 * LINK ROWS 00649 * 00650 * This routine is used to generate the row links. The spGetElement() 00651 * routines do not create row links, which are needed by the spFactor() 00652 * routines. 00653 * 00654 * >>> Arguments: 00655 * Matrix <input> (MatrixPtr) 00656 * Pointer to the matrix. 00657 * 00658 * >>> Local variables: 00659 * pElement (ElementPtr) 00660 * Pointer to an element in the matrix. 00661 * FirstInRowEntry (ElementPtr *) 00662 * A pointer into the FirstInRow array. Points to the FirstInRow entry 00663 * currently being operated upon. 00664 * FirstInRowArray (ArrayOfElementPtrs) 00665 * A pointer to the FirstInRow array. Same as Matrix->FirstInRow but 00666 * resides in a and requires less indirection so is faster to 00667 * use. 00668 * Col (int) 00669 * Column currently being operated upon. 00670 */ 00671 00672 void spcLinkRows(MatrixPtr Matrix) 00673 { 00674 ElementPtr pElement, *FirstInRowEntry; 00675 ArrayOfElementPtrs FirstInRowArray; 00676 int Col; 00677 00678 FirstInRowArray = Matrix->FirstInRow; 00679 for (Col = Matrix->Size; Col >= 1; Col--) 00680 { 00681 /* Generate row links for the elements in the Col'th column. */ 00682 pElement = Matrix->FirstInCol[Col]; 00683 while (pElement != NULL) 00684 { 00685 pElement->Col = Col; 00686 FirstInRowEntry = &FirstInRowArray[pElement->Row]; 00687 pElement->NextInRow = *FirstInRowEntry; 00688 *FirstInRowEntry = pElement; 00689 pElement = pElement->NextInCol; 00690 } 00691 } 00692 Matrix->RowsLinked = 1; 00693 return; 00694 } 00695 00696 /* 00697 * ENLARGE MATRIX 00698 * 00699 * Increases the size of the matrix. 00700 * 00701 * >>> Arguments: 00702 * Matrix <input> (MatrixPtr) 00703 * Pointer to the matrix. 00704 * NewSize <input> (int) 00705 * The new size of the matrix. 00706 * 00707 * >>> Local variables: 00708 * OldAllocatedSize (int) 00709 * The allocated size of the matrix before it is expanded. 00710 */ 00711 00712 static void EnlargeMatrix(MatrixPtr Matrix, int NewSize) 00713 { 00714 int I, OldAllocatedSize = Matrix->AllocatedSize; 00715 00716 Matrix->Size = NewSize; 00717 if (NewSize <= OldAllocatedSize) 00718 return; 00719 00720 /* Expand the matrix frame. */ 00721 NewSize = (int)MAX( NewSize, EXPANSION_FACTOR * OldAllocatedSize ); 00722 Matrix->AllocatedSize = NewSize; 00723 if (( REALLOC(Matrix->IntToExtColMap, int, NewSize+1)) == NULL) 00724 { 00725 Matrix->Error = spNO_MEMORY; return; 00726 } 00727 if (( REALLOC(Matrix->IntToExtRowMap, int, NewSize+1)) == NULL) 00728 { 00729 Matrix->Error = spNO_MEMORY; return; 00730 } 00731 if (( REALLOC(Matrix->Diag, ElementPtr, NewSize+1)) == NULL) 00732 { 00733 Matrix->Error = spNO_MEMORY; return; 00734 } 00735 if (( REALLOC(Matrix->FirstInCol, ElementPtr, NewSize+1)) == NULL) 00736 { 00737 Matrix->Error = spNO_MEMORY; return; 00738 } 00739 if (( REALLOC(Matrix->FirstInRow, ElementPtr, NewSize+1)) == NULL) 00740 { 00741 Matrix->Error = spNO_MEMORY; return; 00742 } 00743 /* 00744 * Destroy the Markowitz and Intermediate vectors, they will be recreated 00745 * in spOrderAndFactor(). 00746 */ 00747 FREE( Matrix->MarkowitzRow ); 00748 FREE( Matrix->MarkowitzCol ); 00749 FREE( Matrix->MarkowitzProd ); 00750 FREE( Matrix->DoRealDirect ); 00751 FREE( Matrix->DoCmplxDirect ); 00752 FREE( Matrix->Intermediate ); 00753 Matrix->InternalVectorsAllocated = 0; 00754 00755 /* Initialize the new portion of the vectors. */ 00756 for (I = OldAllocatedSize+1; I <= NewSize; I++) 00757 { Matrix->IntToExtColMap[I] = I; 00758 Matrix->IntToExtRowMap[I] = I; 00759 Matrix->Diag[I] = NULL; 00760 Matrix->FirstInRow[I] = NULL; 00761 Matrix->FirstInCol[I] = NULL; 00762 } 00763 00764 return; 00765 } 00766 00767 #if TRANSLATE 00768 /* 00769 * EXPAND TRANSLATION ARRAYS 00770 * 00771 * Increases the size arrays that are used to translate external to internal 00772 * row and column numbers. 00773 * 00774 * >>> Arguments: 00775 * Matrix <input> (MatrixPtr) 00776 * Pointer to the matrix. 00777 * NewSize <input> (int) 00778 * The new size of the translation arrays. 00779 * 00780 * >>> Local variables: 00781 * OldAllocatedSize (int) 00782 * The allocated size of the translation arrays before being expanded. 00783 */ 00784 00785 static void ExpandTranslationArrays(MatrixPtr Matrix, int NewSize) 00786 { 00787 int I, OldAllocatedSize = Matrix->AllocatedExtSize; 00788 00789 /* Begin `ExpandTranslationArrays'. */ 00790 Matrix->ExtSize = NewSize; 00791 00792 if (NewSize <= OldAllocatedSize) 00793 return; 00794 00795 /* Expand the translation arrays ExtToIntRowMap and ExtToIntColMap. */ 00796 NewSize = (int)MAX( NewSize, EXPANSION_FACTOR * OldAllocatedSize); 00797 Matrix->AllocatedExtSize = NewSize; 00798 00799 if (( REALLOC(Matrix->ExtToIntRowMap, int, NewSize+1)) == NULL) 00800 { 00801 Matrix->Error = spNO_MEMORY; return; 00802 } 00803 if (( REALLOC(Matrix->ExtToIntColMap, int, NewSize+1)) == NULL) 00804 { 00805 Matrix->Error = spNO_MEMORY; return; 00806 } 00807 00808 /* Initialize the new portion of the vectors. */ 00809 for (I = OldAllocatedSize+1; I <= NewSize; I++) 00810 Matrix->ExtToIntRowMap[I] = Matrix->ExtToIntColMap[I] = -1; 00811 return; 00812 } 00813 #endif 00814 00815 #if INITIALIZE 00816 /* 00817 * INITIALIZE MATRIX 00818 * 00819 * With the INITIALIZE compiler option (see spConfig.h) set true, 00820 * Sparse allows the user to keep initialization information with each 00821 * structurally nonzero matrix element. Each element has a pointer 00822 * that is set and used by the user. The user can set this pointer 00823 * using spInstallInitInfo and may be read using spGetInitInfo. Both 00824 * may be used only after the element exists. The function 00825 * spInitialize() is a user customizable way to initialize the matrix. 00826 * Passed to this routine is a function pointer. spInitialize() sweeps 00827 * through every element in the matrix and checks the pInitInfo 00828 * pointer (the user supplied pointer). If the pInitInfo is NULL, 00829 * which is true unless the user changes it (almost always true for 00830 * fill-ins), then the element is zeroed. Otherwise, the function 00831 * pointer is called and passed the pInitInfo pointer as well as the 00832 * element pointer and the external row and column numbers. If the 00833 * user sets the value of each element, then spInitialize() replaces 00834 * spClear(). 00835 * 00836 * The user function is expected to return a nonzero integer if there 00837 * is a fatal error and zero otherwise. Upon encountering a nonzero 00838 * return code, spInitialize() terminates and returns the error code. 00839 * 00840 * >>> Arguments: 00841 * Matrix <input> (char *) 00842 * Pointer to matrix. 00843 * 00844 * >>> Possible Errors: 00845 * Returns nonzero if error, zero otherwise. 00846 */ 00847 00848 void spInstallInitInfo(ElementPtr pElement, double *pInitInfo ) 00849 { 00850 ASSERT(pElement != NULL); 00851 pElement->pInitInfo = pInitInfo; 00852 } 00853 00854 double * spGetInitInfo(ElementPtr pElement) 00855 { 00856 ASSERT(pElement != NULL); 00857 return pElement->pInitInfo; 00858 } 00859 00860 /* 00861 int spInitialize(MatrixPtr Matrix, int (*pInit)()) 00862 { 00863 ElementPtr pElement; 00864 int J, Error, Col; 00865 ASSERT(IS_SPARSE(Matrix)); 00866 00867 // Initialize the matrix. 00868 for (J = Matrix->Size; J > 0; J--) 00869 { 00870 pElement = Matrix->FirstInCol[J]; 00871 Col = Matrix->IntToExtColMap[J]; 00872 while (pElement != NULL) 00873 { 00874 if (pElement->pInitInfo == NULL) 00875 pElement->Real = 0.0; 00876 else 00877 { 00878 Error = (*pInit)(pElement, pElement->pInitInfo);//, Matrix->IntToExtRowMap[pElement->Row], Col); 00879 if (Error) 00880 { 00881 Matrix->Error = spFATAL; return Error; 00882 } 00883 } 00884 pElement = pElement->NextInCol; 00885 } 00886 } 00887 // Empty the trash. 00888 Matrix->TrashCan.Real = 0.0; 00889 Matrix->Error = spOKAY; 00890 Matrix->Factored = 0; 00891 Matrix->SingularCol = 0; 00892 Matrix->SingularRow = 0; 00893 Matrix->PreviousMatrixWasComplex = Matrix->Complex; 00894 return 0; 00895 } 00896 */ 00897 #endif /* INITIALIZE */