📄 spalloc.c
字号:
/* * 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. */#ifdef notdefstatic char copyright[] = "Sparse1.3: Copyright (c) 1985,86,87,88,89,90 by Kenneth S. Kundert";static char RCSid[] = "@(#)$Header: spAllocate.c,v 1.3 88/06/24 05:00:11 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"#ifdef PARALLEL_ARCH#define COMBINE 1#endif /* PARALLEL_ARCH *//* * Function declarations */#ifdef __STDC__static void InitializeElementBlocks( MatrixPtr, int, int );static void RecordAllocation( MatrixPtr, char* );static void AllocateBlockOfAllocationList( MatrixPtr );#else /* __STDC__ */static void InitializeElementBlocks();static void RecordAllocation();static void AllocateBlockOfAllocationList();#endif /* __STDC__ *//* * 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. */char *spCreate( Size, Complex, pError )int Size, *pError;BOOLEAN Complex;{register unsigned SizePlusOne;register MatrixPtr Matrix;register int I;int AllocatedSize;/* Begin `spCreate'. *//* Clear error flag. */ *pError = spOKAY;/* Test for valid size. */ if ((Size < 0) OR (Size == 0 AND NOT EXPANDABLE)) { *pError = spPANIC; return NULL; }/* Test for valid type. */#if NOT spCOMPLEX if (Complex) { *pError = spPANIC; return NULL; }#endif#if NOT REAL if (NOT Complex) { *pError = spPANIC; return NULL; }#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->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, (char *)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 */ElementPtrspcGetElement( Matrix )MatrixPtr Matrix;{struct ElementListNodeStruct *pListNode;ElementPtr pElements;/* Begin `spcGetElement'. */#if NOT COMBINE OR STRIP OR LINT/* Allocate block of MatrixElements if necessary. */ if (Matrix->ElementsRemaining == 0) { pElements = ALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION); RecordAllocation( Matrix, (char *)pElements ); if (Matrix->Error == spNO_MEMORY) return NULL; Matrix->ElementsRemaining = ELEMENTS_PER_ALLOCATION; Matrix->NextAvailElement = pElements; }#endif#if COMBINE OR STRIP OR 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 = ALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION); RecordAllocation( Matrix, (char *)pElements ); if (Matrix->Error == spNO_MEMORY) return NULL; Matrix->ElementsRemaining = ELEMENTS_PER_ALLOCATION; Matrix->NextAvailElement = pElements;/* Allocate an element list structure. */ pListNode->Next = ALLOC(struct ElementListNodeStruct,1); RecordAllocation( Matrix, (char *)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 voidInitializeElementBlocks( Matrix, InitialNumberOfElements, NumberOfFillinsExpected )MatrixPtr Matrix;int InitialNumberOfElements, NumberOfFillinsExpected;{ElementPtr pElement;/* Begin `InitializeElementBlocks'. *//* Allocate block of MatrixElements for elements. */ pElement = ALLOC(struct MatrixElement, InitialNumberOfElements); RecordAllocation( Matrix, (char *)pElement ); if (Matrix->Error == spNO_MEMORY) return; Matrix->ElementsRemaining = InitialNumberOfElements; Matrix->NextAvailElement = pElement;/* Allocate an element list structure. */ Matrix->FirstElementListNode = ALLOC(struct ElementListNodeStruct,1); RecordAllocation( Matrix, (char *)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 = ALLOC(struct MatrixElement, NumberOfFillinsExpected); RecordAllocation( Matrix, (char *)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, (char *)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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -