ngspice/src/maths/sparse/spalloc.c

888 lines
23 KiB
C
Raw Normal View History

2000-04-27 22:03:57 +02:00
/*
* 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>
2000-04-27 22:03:57 +02:00
#define spINSIDE_SPARSE
#include "spconfig.h"
#include "spmatrix.h"
#include "spdefs.h"
#ifdef PARALLEL_ARCH
#define COMBINE 1
#endif /* PARALLEL_ARCH */
/*
* Function declarations
*/
static void InitializeElementBlocks( MatrixPtr, int, int );
static void RecordAllocation( MatrixPtr, void *);
2000-04-27 22:03:57 +02:00
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.
*/
void *
spCreate(int Size, int Complex, int *pError)
2000-04-27 22:03:57 +02:00
{
unsigned SizePlusOne;
MatrixPtr Matrix;
int I;
int AllocatedSize;
2000-04-27 22:03:57 +02:00
/* Begin `spCreate'. */
/* Clear error flag. */
2000-04-27 22:03:57 +02:00
*pError = spOKAY;
/* Test for valid size. */
if ((Size < 0) || (Size == 0 && !EXPANDABLE)) {
*pError = spPANIC;
2000-04-27 22:03:57 +02:00
return NULL;
}
/* Test for valid type. */
#if !REAL
if (!Complex) {
*pError = spPANIC;
return NULL;
2000-04-27 22:03:57 +02:00
}
#endif
/* Create Matrix. */
2000-04-27 22:03:57 +02:00
AllocatedSize = MAX( Size, MINIMUM_ALLOCATED_SIZE );
SizePlusOne = (unsigned)(AllocatedSize + 1);
if ((Matrix = ALLOC(struct MatrixFrame, 1)) == NULL) {
*pError = spNO_MEMORY;
return NULL;
2000-04-27 22:03:57 +02:00
}
/* Initialize matrix */
2000-04-27 22:03:57 +02:00
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, (void *)Matrix );
2000-04-27 22:03:57 +02:00
if (Matrix->Error == spNO_MEMORY) goto MemoryError;
/* Take out the trash. */
2000-04-27 22:03:57 +02:00
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. */
2000-04-27 22:03:57 +02:00
CALLOC( Matrix->Diag, ElementPtr, SizePlusOne);
if (Matrix->Diag == NULL)
goto MemoryError;
/* Allocate space in memory for FirstInCol pointer vector. */
2000-04-27 22:03:57 +02:00
CALLOC( Matrix->FirstInCol, ElementPtr, SizePlusOne);
if (Matrix->FirstInCol == NULL)
goto MemoryError;
/* Allocate space in memory for FirstInRow pointer vector. */
2000-04-27 22:03:57 +02:00
CALLOC( Matrix->FirstInRow, ElementPtr, SizePlusOne);
if (Matrix->FirstInRow == NULL)
goto MemoryError;
/* Allocate space in memory for IntToExtColMap vector. */
2000-04-27 22:03:57 +02:00
if (( Matrix->IntToExtColMap = ALLOC(int, SizePlusOne)) == NULL)
goto MemoryError;
/* Allocate space in memory for IntToExtRowMap vector. */
2000-04-27 22:03:57 +02:00
if (( Matrix->IntToExtRowMap = ALLOC(int, SizePlusOne)) == NULL)
goto MemoryError;
/* Initialize MapIntToExt vectors. */
2000-04-27 22:03:57 +02:00
for (I = 1; I <= AllocatedSize; I++)
{
Matrix->IntToExtRowMap[I] = I;
2000-04-27 22:03:57 +02:00
Matrix->IntToExtColMap[I] = I;
}
#if TRANSLATE
/* Allocate space in memory for ExtToIntColMap vector. */
2000-04-27 22:03:57 +02:00
if (( Matrix->ExtToIntColMap = ALLOC(int, SizePlusOne)) == NULL)
goto MemoryError;
/* Allocate space in memory for ExtToIntRowMap vector. */
2000-04-27 22:03:57 +02:00
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;
2000-04-27 22:03:57 +02:00
}
Matrix->ExtToIntColMap[0] = 0;
Matrix->ExtToIntRowMap[0] = 0;
#endif
/* Allocate space for fill-ins and initial set of elements. */
2000-04-27 22:03:57 +02:00
InitializeElementBlocks( Matrix, SPACE_FOR_ELEMENTS*AllocatedSize,
SPACE_FOR_FILL_INS*AllocatedSize );
2000-04-27 22:03:57 +02:00
if (Matrix->Error == spNO_MEMORY)
goto MemoryError;
return (void *)Matrix;
2000-04-27 22:03:57 +02:00
MemoryError:
2000-04-27 22:03:57 +02:00
/* Deallocate matrix and return no pointer to matrix if there is not enough
memory. */
2000-04-27 22:03:57 +02:00
*pError = spNO_MEMORY;
spDestroy( (void *)Matrix);
2000-04-27 22:03:57 +02:00
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)
2000-04-27 22:03:57 +02:00
{
ElementPtr pElements;
2000-04-27 22:03:57 +02:00
/* Begin `spcGetElement'. */
2000-04-27 22:03:57 +02:00
#if !COMBINE || STRIP || LINT
/* Allocate block of MatrixElements if necessary. */
if (Matrix->ElementsRemaining == 0) {
pElements = ALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION);
RecordAllocation( Matrix, (void *)pElements );
2000-04-27 22:03:57 +02:00
if (Matrix->Error == spNO_MEMORY) return NULL;
Matrix->ElementsRemaining = ELEMENTS_PER_ALLOCATION;
Matrix->NextAvailElement = pElements;
}
#endif
#if COMBINE || STRIP || LINT
2000-04-27 22:03:57 +02:00
if (Matrix->ElementsRemaining == 0)
{
pListNode = Matrix->LastElementListNode;
2000-04-27 22:03:57 +02:00
/* First see if there are any stripped elements left. */
if (pListNode->Next != NULL) {
Matrix->LastElementListNode = pListNode = pListNode->Next;
2000-04-27 22:03:57 +02:00
Matrix->ElementsRemaining = pListNode->NumberOfElementsInList;
Matrix->NextAvailElement = pListNode->pElementList;
} else {
/* Allocate block of elements. */
2000-04-27 22:03:57 +02:00
pElements = ALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION);
RecordAllocation( Matrix, (void *)pElements );
2000-04-27 22:03:57 +02:00
if (Matrix->Error == spNO_MEMORY) return NULL;
Matrix->ElementsRemaining = ELEMENTS_PER_ALLOCATION;
Matrix->NextAvailElement = pElements;
/* Allocate an element list structure. */
2000-04-27 22:03:57 +02:00
pListNode->Next = ALLOC(struct ElementListNodeStruct,1);
RecordAllocation( Matrix, (void *)pListNode->Next );
if (Matrix->Error == spNO_MEMORY)
return NULL;
2000-04-27 22:03:57 +02:00
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. */
2000-04-27 22:03:57 +02:00
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.
2000-04-27 22:03:57 +02:00
*
* >>> 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 */
2000-04-27 22:03:57 +02:00
static void
InitializeElementBlocks(MatrixPtr Matrix, int InitialNumberOfElements,
int NumberOfFillinsExpected)
2000-04-27 22:03:57 +02:00
{
ElementPtr pElement;
2000-04-27 22:03:57 +02:00
/* Begin `InitializeElementBlocks'. */
2000-04-27 22:03:57 +02:00
/* Allocate block of MatrixElements for elements. */
2000-04-27 22:03:57 +02:00
pElement = ALLOC(struct MatrixElement, InitialNumberOfElements);
RecordAllocation( Matrix, (void *)pElement );
2000-04-27 22:03:57 +02:00
if (Matrix->Error == spNO_MEMORY) return;
Matrix->ElementsRemaining = InitialNumberOfElements;
Matrix->NextAvailElement = pElement;
/* Allocate an element list structure. */
2000-04-27 22:03:57 +02:00
Matrix->FirstElementListNode = ALLOC(struct ElementListNodeStruct,1);
RecordAllocation( Matrix, (void *)Matrix->FirstElementListNode );
2000-04-27 22:03:57 +02:00
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. */
2000-04-27 22:03:57 +02:00
pElement = ALLOC(struct MatrixElement, NumberOfFillinsExpected);
RecordAllocation( Matrix, (void *)pElement );
2000-04-27 22:03:57 +02:00
if (Matrix->Error == spNO_MEMORY) return;
Matrix->FillinsRemaining = NumberOfFillinsExpected;
Matrix->NextAvailFillin = pElement;
/* Allocate a fill-in list structure. */
2000-04-27 22:03:57 +02:00
Matrix->FirstFillinListNode = ALLOC(struct FillinListNodeStruct,1);
RecordAllocation( Matrix, (void *)Matrix->FirstFillinListNode );
2000-04-27 22:03:57 +02:00
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.
2000-04-27 22:03:57 +02:00
*
* >>> Returned:
* A pointer to the fill-in.
*
* >>> Arguments:
* Matrix <input> (MatrixPtr)
* Pointer to matrix.
*
* >>> Possible errors:
* spNO_MEMORY */
2000-04-27 22:03:57 +02:00
ElementPtr
spcGetFillin(MatrixPtr Matrix)
2000-04-27 22:03:57 +02:00
{
/* Begin `spcGetFillin'. */
2000-04-27 22:03:57 +02:00
#if !STRIP || LINT
2000-04-27 22:03:57 +02:00
if (Matrix->FillinsRemaining == 0)
return spcGetElement( Matrix );
#endif
#if STRIP || LINT
2000-04-27 22:03:57 +02:00
if (Matrix->FillinsRemaining == 0) {
pListNode = Matrix->LastFillinListNode;
2000-04-27 22:03:57 +02:00
/* First see if there are any stripped fill-ins left. */
if (pListNode->Next != NULL) {
Matrix->LastFillinListNode = pListNode = pListNode->Next;
2000-04-27 22:03:57 +02:00
Matrix->FillinsRemaining = pListNode->NumberOfFillinsInList;
Matrix->NextAvailFillin = pListNode->pFillinList;
} else {
/* Allocate block of fill-ins. */
2000-04-27 22:03:57 +02:00
pFillins = ALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION);
RecordAllocation( Matrix, (void *)pFillins );
2000-04-27 22:03:57 +02:00
if (Matrix->Error == spNO_MEMORY) return NULL;
Matrix->FillinsRemaining = ELEMENTS_PER_ALLOCATION;
Matrix->NextAvailFillin = pFillins;
/* Allocate a fill-in list structure. */
2000-04-27 22:03:57 +02:00
pListNode->Next = ALLOC(struct FillinListNodeStruct,1);
RecordAllocation( Matrix, (void *)pListNode->Next );
2000-04-27 22:03:57 +02:00
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. */
2000-04-27 22:03:57 +02:00
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.
2000-04-27 22:03:57 +02:00
*
* >>> 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.
2000-04-27 22:03:57 +02:00
*
* >>> Possible errors:
* spNO_MEMORY */
2000-04-27 22:03:57 +02:00
static void
RecordAllocation(MatrixPtr Matrix, void *AllocatedPtr )
2000-04-27 22:03:57 +02:00
{
/* 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;
2000-04-27 22:03:57 +02:00
return;
}
/* Allocate block of MatrixElements if necessary. */
if (Matrix->RecordsRemaining == 0) {
AllocateBlockOfAllocationList( Matrix );
if (Matrix->Error == spNO_MEMORY) {
FREE(AllocatedPtr);
2000-04-27 22:03:57 +02:00
return;
}
}
/* Add Allocated pointer to Allocation List. */
2000-04-27 22:03:57 +02:00
(++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.
2000-04-27 22:03:57 +02:00
*
* >>> Possible errors:
* spNO_MEMORY */
2000-04-27 22:03:57 +02:00
static void
AllocateBlockOfAllocationList(MatrixPtr Matrix)
2000-04-27 22:03:57 +02:00
{
int I;
AllocationListPtr ListPtr;
2000-04-27 22:03:57 +02:00
/* Begin `AllocateBlockOfAllocationList'. */
/* Allocate block of records for allocation list. */
2000-04-27 22:03:57 +02:00
ListPtr = ALLOC(struct AllocationRecord, (ELEMENTS_PER_ALLOCATION+1));
if (ListPtr == NULL) {
Matrix->Error = spNO_MEMORY;
2000-04-27 22:03:57 +02:00
return;
}
/* String entries of allocation list into singly linked list.
List is linked such that any record points to the one before
it. */
2000-04-27 22:03:57 +02:00
ListPtr->NextRecord = Matrix->TopOfAllocationList;
Matrix->TopOfAllocationList = ListPtr;
ListPtr += ELEMENTS_PER_ALLOCATION;
for (I = ELEMENTS_PER_ALLOCATION; I > 0; I--) {
ListPtr->NextRecord = ListPtr - 1;
ListPtr--;
2000-04-27 22:03:57 +02:00
}
/* Record allocation of space for allocation list on allocation list. */
Matrix->TopOfAllocationList->AllocatedPtr = (void *)ListPtr;
2000-04-27 22:03:57 +02:00
Matrix->RecordsRemaining = ELEMENTS_PER_ALLOCATION;
return;
}
/*
* MATRIX DEALLOCATION
*
* Deallocates pointers and elements of Matrix.
*
* >>> Arguments:
* Matrix <input> (void *)
2000-04-27 22:03:57 +02:00
* 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(void *eMatrix)
2000-04-27 22:03:57 +02:00
{
MatrixPtr Matrix = (MatrixPtr)eMatrix;
AllocationListPtr ListPtr, NextListPtr;
2000-04-27 22:03:57 +02:00
/* Begin `spDestroy'. */
assert( IS_SPARSE( Matrix ) );
2000-04-27 22:03:57 +02:00
/* Deallocate the vectors that are located in the matrix frame. */
2000-04-27 22:03:57 +02:00
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. */
2000-04-27 22:03:57 +02:00
ListPtr = Matrix->TopOfAllocationList;
while (ListPtr != NULL) {
NextListPtr = ListPtr->NextRecord;
if ((void *) ListPtr == ListPtr->AllocatedPtr) {
2000-04-27 22:03:57 +02:00
FREE( ListPtr );
} else {
2000-04-27 22:03:57 +02:00
FREE( ListPtr->AllocatedPtr );
}
ListPtr = NextListPtr;
}
return;
}
/*
* RETURN MATRIX ERROR STATUS
*
* This function is used to determine the error status of the given
* matrix.
2000-04-27 22:03:57 +02:00
*
* >>> Returned:
* The error status of the given matrix.
*
* >>> Arguments:
* eMatrix <input> (void *)
* The matrix for which the error status is desired. */
2000-04-27 22:03:57 +02:00
int
spError(void *eMatrix )
2000-04-27 22:03:57 +02:00
{
/* Begin `spError'. */
2000-04-27 22:03:57 +02:00
if (eMatrix != NULL) {
assert(((MatrixPtr)eMatrix)->ID == SPARSE_ID);
2000-04-27 22:03:57 +02:00
return ((MatrixPtr)eMatrix)->Error;
} else {
/* This error may actually be spPANIC, no way to tell. */
return spNO_MEMORY;
2000-04-27 22:03:57 +02:00
}
}
/*
* 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:
* eMatrix <input> (void *)
2000-04-27 22:03:57 +02:00
* The matrix for which the error status is desired.
* pRow <output> (int *)
* The row number.
* pCol <output> (int *)
* The column number.
*/
void
spWhereSingular(void *eMatrix, int *pRow, int *pCol)
2000-04-27 22:03:57 +02:00
{
MatrixPtr Matrix = (MatrixPtr)eMatrix;
2000-04-27 22:03:57 +02:00
/* Begin `spWhereSingular'. */
assert( IS_SPARSE( Matrix ) );
2000-04-27 22:03:57 +02:00
if (Matrix->Error == spSINGULAR || Matrix->Error == spZERO_DIAG)
{
*pRow = Matrix->SingularRow;
2000-04-27 22:03:57 +02:00
*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:
* eMatrix <input> (void *)
2000-04-27 22:03:57 +02:00
* Pointer to matrix.
* External <input> (int)
2000-04-27 22:03:57 +02:00
* 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(void *eMatrix, int External)
2000-04-27 22:03:57 +02:00
{
MatrixPtr Matrix = (MatrixPtr)eMatrix;
2000-04-27 22:03:57 +02:00
/* Begin `spGetSize'. */
assert( IS_SPARSE( Matrix ) );
2000-04-27 22:03:57 +02:00
#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:
* eMatrix <input> (void *)
2000-04-27 22:03:57 +02:00
* Pointer to matrix.
*/
void
spSetReal(void *eMatrix)
2000-04-27 22:03:57 +02:00
{
/* Begin `spSetReal'. */
2000-04-27 22:03:57 +02:00
assert( IS_SPARSE( (MatrixPtr)eMatrix ));
2000-04-27 22:03:57 +02:00
((MatrixPtr)eMatrix)->Complex = NO;
return;
}
void
spSetComplex(void *eMatrix)
2000-04-27 22:03:57 +02:00
{
/* Begin `spSetComplex'. */
2000-04-27 22:03:57 +02:00
assert( IS_SPARSE( (MatrixPtr)eMatrix ));
2000-04-27 22:03:57 +02:00
((MatrixPtr)eMatrix)->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:
* eMatrix <input> (void *)
2000-04-27 22:03:57 +02:00
* Pointer to matrix.
*/
int
spFillinCount(void *eMatrix)
2000-04-27 22:03:57 +02:00
{
/* Begin `spFillinCount'. */
2000-04-27 22:03:57 +02:00
assert( IS_SPARSE( (MatrixPtr)eMatrix ) );
2000-04-27 22:03:57 +02:00
return ((MatrixPtr)eMatrix)->Fillins;
}
int
spElementCount(void *eMatrix)
2000-04-27 22:03:57 +02:00
{
/* Begin `spElementCount'. */
2000-04-27 22:03:57 +02:00
assert( IS_SPARSE( (MatrixPtr)eMatrix ) );
2000-04-27 22:03:57 +02:00
return ((MatrixPtr)eMatrix)->Elements;
}
int
spOriginalCount(void *eMatrix)
2000-04-27 22:03:57 +02:00
{
/* Begin `spOriginalCount'. */
2000-04-27 22:03:57 +02:00
assert( IS_SPARSE( (MatrixPtr)eMatrix ) );
2000-04-27 22:03:57 +02:00
return ((MatrixPtr)eMatrix)->Originals;
}