📄 spbuild.c
字号:
/* * MATRIX BUILD MODULE * * Author: Advising professor: * Kenneth S. Kundert Alberto Sangiovanni-Vincentelli * UC Berkeley * * This file contains the routines associated with clearing, loading and * preprocessing the matrix for the sparse matrix routines. * * >>> User accessible functions contained in this file: * spClear * spGetElement * spFindElement * spGetAdmittance * spGetQuad * spGetOnes * spInstallInitInfo * spGetInitInfo * spInitialize * * >>> Other functions contained in this file: * spcFindElementInCol * Translate * spcCreateElement * spcLinkRows * 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. */#ifdef notdefstatic char copyright[] = "Sparse1.3: Copyright (c) 1985,86,87,88,89,90 by Kenneth S. Kundert";static char RCSid[] = "@(#)$Header: spBuild.c,v 1.3 88/06/24 05:00:31 kundert Exp $";#endif/* * 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 "spconfig.h"#include "spmatrix.h"#include "spdefs.h"/* * Function declarations */#ifdef __STDC__static void Translate( MatrixPtr, int*, int* );static void EnlargeMatrix( MatrixPtr, int );static void ExpandTranslationArrays( MatrixPtr, int );#else /* __STDC__ */static void Translate();static void EnlargeMatrix();static void ExpandTranslationArrays();#endif /* __STDC__ *//* * CLEAR MATRIX * * Sets every element of the matrix to zero and clears the error flag. * * >>> Arguments: * Matrix <input> (char *) * Pointer to matrix that is to be cleared. * * >>> Local variables: * pElement (ElementPtr) * A pointer to the element being cleared. */voidspClear( eMatrix )char *eMatrix;{MatrixPtr Matrix = (MatrixPtr)eMatrix;register ElementPtr pElement;register int I;/* Begin `spClear'. */ ASSERT( IS_SPARSE( Matrix ) );/* Clear matrix. */#if spCOMPLEX if (Matrix->PreviousMatrixWasComplex OR Matrix->Complex) { for (I = Matrix->Size; I > 0; I--) { pElement = Matrix->FirstInCol[I]; while (pElement != NULL) { pElement->Real = 0.0; pElement->Imag = 0.0; pElement = pElement->NextInCol; } } } else#endif { for (I = Matrix->Size; I > 0; I--) { pElement = Matrix->FirstInCol[I]; while (pElement != NULL) { pElement->Real = 0.0; pElement = pElement->NextInCol; } } }/* Empty the trash. */ Matrix->TrashCan.Real = 0.0;#if spCOMPLEX Matrix->TrashCan.Imag = 0.0;#endif Matrix->Error = spOKAY; Matrix->Factored = NO; Matrix->SingularCol = 0; Matrix->SingularRow = 0; Matrix->PreviousMatrixWasComplex = Matrix->Complex; return;}/* * SINGLE ELEMENT LOCATION IN MATRIX BY INDEX * * Finds element [Row,Col] and returns a pointer to it. If element is * not found then it is created and spliced into matrix. This routine * is only to be used after spCreate() and before spMNA_Preorder(), * spFactor() or spOrderAndFactor(). Returns a pointer to the * Real portion of a MatrixElement. This pointer is later used by * spADD_xxx_ELEMENT to directly access element. * * >>> Returns: * Returns a pointer to the element. This pointer is then used to directly * access the element during successive builds. * * >>> Arguments: * Matrix <input> (char *) * Pointer to the matrix that the element is to be added to. * Row <input> (int) * Row index for element. Must be in the range of [0..Size] unless * the options EXPANDABLE or TRANSLATE are used. Elements placed in * row zero are discarded. In no case may Row be less than zero. * Col <input> (int) * Column index for element. Must be in the range of [0..Size] unless * the options EXPANDABLE or TRANSLATE are used. Elements placed in * column zero are discarded. In no case may Col be less than zero. * * >>> Local variables: * pElement (RealNumber *) * Pointer to the element. * * >>> Possible errors: * spNO_MEMORY * Error is not cleared in this routine. */RealNumber *spFindElement( eMatrix, Row, Col )char *eMatrix;int Row, Col;{MatrixPtr Matrix = (MatrixPtr)eMatrix;RealNumber *pElement;int index;ElementPtr spcFindElementInCol();void Translate();/* Begin `spFindElement'. */ ASSERT( IS_SPARSE( Matrix ) AND Row >= 0 AND Col >= 0 ); if ((Row == 0) OR (Col == 0)) return &Matrix->TrashCan.Real;#if TRANSLATE Translate( Matrix, &Row, &Col ); if (Matrix->Error == spNO_MEMORY) return NULL;#endif#if NOT TRANSLATE ASSERT(Row <= Matrix->Size AND Col <= Matrix->Size);#endif/* * The condition part of the following if statement tests to see if the * element resides along the diagonal, if it does then it tests to see * if the element has been created yet (Diag pointer not NULL). The * pointer to the element is then assigned to Element after it is cast * into a pointer to a RealNumber. This casting makes the pointer into * a pointer to Real. This statement depends on the fact that Real * is the first record in the MatrixElement structure. */ if ((Row != Col) OR ((pElement = (RealNumber *)Matrix->Diag[Row]) == NULL)) {/* * Element does not exist or does not reside along diagonal. Search * column for element. As in the if statement above, the pointer to the * element which is returned by spcFindElementInCol is cast into a * pointer to Real, a RealNumber. */ pElement = (RealNumber*)spcFindElementInCol( Matrix, &(Matrix->FirstInCol[Col]), Row, Col, NO ); } return pElement;}/* * SINGLE ELEMENT ADDITION TO MATRIX BY INDEX * * Finds element [Row,Col] and returns a pointer to it. If element is * not found then it is created and spliced into matrix. This routine * is only to be used after spCreate() and before spMNA_Preorder(), * spFactor() or spOrderAndFactor(). Returns a pointer to the * Real portion of a MatrixElement. This pointer is later used by * spADD_xxx_ELEMENT to directly access element. * * >>> Returns: * Returns a pointer to the element. This pointer is then used to directly * access the element during successive builds. * * >>> Arguments: * Matrix <input> (char *) * Pointer to the matrix that the element is to be added to. * Row <input> (int) * Row index for element. Must be in the range of [0..Size] unless * the options EXPANDABLE or TRANSLATE are used. Elements placed in * row zero are discarded. In no case may Row be less than zero. * Col <input> (int) * Column index for element. Must be in the range of [0..Size] unless * the options EXPANDABLE or TRANSLATE are used. Elements placed in * column zero are discarded. In no case may Col be less than zero. * * >>> Local variables: * pElement (RealNumber *) * Pointer to the element. * * >>> Possible errors: * spNO_MEMORY * Error is not cleared in this routine. */RealNumber *spGetElement( eMatrix, Row, Col )char *eMatrix;int Row, Col;{MatrixPtr Matrix = (MatrixPtr)eMatrix;RealNumber *pElement;ElementPtr spcFindElementInCol();void Translate();/* Begin `spGetElement'. */ ASSERT( IS_SPARSE( Matrix ) AND Row >= 0 AND Col >= 0 ); if ((Row == 0) OR (Col == 0)) return &Matrix->TrashCan.Real;#if NOT TRANSLATE ASSERT(Matrix->NeedsOrdering);#endif#if TRANSLATE Translate( Matrix, &Row, &Col ); if (Matrix->Error == spNO_MEMORY) return NULL;#endif#if NOT TRANSLATE#if NOT EXPANDABLE ASSERT(Row <= Matrix->Size AND Col <= Matrix->Size);#endif#if EXPANDABLE/* Re-size Matrix if necessary. */ if ((Row > Matrix->Size) OR (Col > Matrix->Size)) EnlargeMatrix( Matrix, MAX(Row, Col) ); if (Matrix->Error == spNO_MEMORY) return NULL;#endif#endif/* * The condition part of the following if statement tests to see if the * element resides along the diagonal, if it does then it tests to see * if the element has been created yet (Diag pointer not NULL). The * pointer to the element is then assigned to Element after it is cast * into a pointer to a RealNumber. This casting makes the pointer into * a pointer to Real. This statement depends on the fact that Real * is the first record in the MatrixElement structure. */ if ((Row != Col) OR ((pElement = (RealNumber *)Matrix->Diag[Row]) == NULL)) {/* * Element does not exist or does not reside along diagonal. Search * column for element. As in the if statement above, the pointer to the * element which is returned by spcFindElementInCol is cast into a * pointer to Real, a RealNumber. */ pElement = (RealNumber*)spcFindElementInCol( Matrix, &(Matrix->FirstInCol[Col]), Row, Col, YES ); } return pElement;}/* * FIND ELEMENT BY SEARCHING COLUMN * * Searches column starting at element specified at PtrAddr and finds element * in Row. If Element does not exists, it is created. The pointer to the * element is returned. * * >>> Returned: * A pointer to the desired element: * * >>> Arguments: * Matrix <input> (MatrixPtr) * Pointer to Matrix. * LastAddr <input-output> (ElementPtr *) * Address of pointer that initially points to the element in Col at which * the search is started. The pointer in this location may be changed if * a fill-in is required in and adjacent element. For this reason it is * important that LastAddr be the address of a FirstInCol or a NextInCol * rather than a temporary variable. * Row <input> (int) * Row being searched for. * Col (int) * Column being searched. * CreateIfMissing <input> (BOOLEAN) * Indicates what to do if element is not found, create one or return a * NULL pointer. * * Local variables: * pElement (ElementPtr) * Pointer used to search through matrix. */ElementPtrspcFindElementInCol( Matrix, LastAddr, Row, Col, CreateIfMissing )MatrixPtr Matrix;register ElementPtr *LastAddr;register int Row;int Col;BOOLEAN CreateIfMissing;{register ElementPtr pElement;ElementPtr spcCreateElement();/* Begin `spcFindElementInCol'. */ pElement = *LastAddr;/* Search for element. */ while (pElement != NULL) { if (pElement->Row < Row) {/* Have not reached element yet. */ LastAddr = &(pElement->NextInCol); pElement = pElement->NextInCol; } else if (pElement->Row == Row) {/* Reached element. */ return pElement; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -