📄 spalloc.c
字号:
/* * 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. * * >>> Returned: * A pointer to the fill-in. * * >>> Arguments: * Matrix <input> (MatrixPtr) * Pointer to matrix. * * >>> Possible errors: * spNO_MEMORY */ElementPtrspcGetFillin( Matrix )MatrixPtr Matrix;{struct FillinListNodeStruct *pListNode;ElementPtr pFillins;/* Begin `spcGetFillin'. */#if NOT STRIP OR LINT if (Matrix->FillinsRemaining == 0) return spcGetElement( Matrix );#endif#if STRIP OR LINT if (Matrix->FillinsRemaining == 0) { pListNode = Matrix->LastFillinListNode;/* First see if there are any stripped fill-ins left. */ if (pListNode->Next != NULL) { Matrix->LastFillinListNode = pListNode = pListNode->Next; Matrix->FillinsRemaining = pListNode->NumberOfFillinsInList; Matrix->NextAvailFillin = pListNode->pFillinList; } else {/* Allocate block of fill-ins. */ pFillins = ALLOC(struct MatrixElement, ELEMENTS_PER_ALLOCATION); RecordAllocation( Matrix, (char *)pFillins ); if (Matrix->Error == spNO_MEMORY) return NULL; Matrix->FillinsRemaining = ELEMENTS_PER_ALLOCATION; Matrix->NextAvailFillin = pFillins;/* Allocate a fill-in list structure. */ pListNode->Next = ALLOC(struct FillinListNodeStruct,1); RecordAllocation( Matrix, (char *)pListNode->Next ); 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. */ 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. * * >>> Arguments: * Matrix <input> (MatrixPtr) * Pointer to the matrix. * AllocatedPtr <input> (char *) * The pointer returned by malloc or calloc. These pointers are saved in * a list so that they can be easily freed. * * >>> Possible errors: * spNO_MEMORY */static voidRecordAllocation( Matrix, AllocatedPtr )MatrixPtr Matrix;char *AllocatedPtr;{/* 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; return; }/* Allocate block of MatrixElements if necessary. */ if (Matrix->RecordsRemaining == 0) { AllocateBlockOfAllocationList( Matrix ); if (Matrix->Error == spNO_MEMORY) { FREE(AllocatedPtr); return; } }/* Add Allocated pointer to Allocation List. */ (++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. * * >>> Possible errors: * spNO_MEMORY */static voidAllocateBlockOfAllocationList( Matrix )MatrixPtr Matrix;{register int I;register AllocationListPtr ListPtr;/* Begin `AllocateBlockOfAllocationList'. *//* Allocate block of records for allocation list. */ ListPtr = ALLOC(struct AllocationRecord, (ELEMENTS_PER_ALLOCATION+1)); if (ListPtr == NULL) { Matrix->Error = spNO_MEMORY; return; }/* String entries of allocation list into singly linked list. List is linked such that any record points to the one before it. */ ListPtr->NextRecord = Matrix->TopOfAllocationList; Matrix->TopOfAllocationList = ListPtr; ListPtr += ELEMENTS_PER_ALLOCATION; for (I = ELEMENTS_PER_ALLOCATION; I > 0; I--) { ListPtr->NextRecord = ListPtr - 1; ListPtr--; }/* Record allocation of space for allocation list on allocation list. */ Matrix->TopOfAllocationList->AllocatedPtr = (char *)ListPtr; Matrix->RecordsRemaining = ELEMENTS_PER_ALLOCATION; return;}/* * MATRIX DEALLOCATION * * Deallocates pointers and elements of Matrix. * * >>> Arguments: * Matrix <input> (char *) * 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. */voidspDestroy( eMatrix )register char *eMatrix;{MatrixPtr Matrix = (MatrixPtr)eMatrix;register AllocationListPtr ListPtr, NextListPtr;/* Begin `spDestroy'. */ ASSERT( IS_SPARSE( Matrix ) );/* Deallocate the vectors that are located in the matrix frame. */ 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. */ ListPtr = Matrix->TopOfAllocationList; while (ListPtr != NULL) { NextListPtr = ListPtr->NextRecord; if ((char *) ListPtr == ListPtr->AllocatedPtr) { FREE( ListPtr ); } else { FREE( ListPtr->AllocatedPtr ); } ListPtr = NextListPtr; } return;}/* * RETURN MATRIX ERROR STATUS * * This function is used to determine the error status of the given matrix. * * >>> Returned: * The error status of the given matrix. * * >>> Arguments: * eMatrix <input> (char *) * The matrix for which the error status is desired. */intspError( eMatrix )char *eMatrix;{/* Begin `spError'. */ if (eMatrix != NULL) { ASSERT(((MatrixPtr)eMatrix)->ID == SPARSE_ID); return ((MatrixPtr)eMatrix)->Error; } else return spNO_MEMORY; /* This error may actually be spPANIC, * no way to tell. */}/* * 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> (char *) * The matrix for which the error status is desired. * pRow <output> (int *) * The row number. * pCol <output> (int *) * The column number. */voidspWhereSingular( eMatrix, pRow, pCol )char *eMatrix;int *pRow, *pCol;{MatrixPtr Matrix = (MatrixPtr)eMatrix;/* Begin `spWhereSingular'. */ ASSERT( IS_SPARSE( Matrix ) ); if (Matrix->Error == spSINGULAR OR Matrix->Error == spZERO_DIAG) { *pRow = Matrix->SingularRow; *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> (char *) * Pointer to matrix. * External <input> (BOOLEAN) * 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. */intspGetSize( eMatrix, External )char *eMatrix;BOOLEAN External;{MatrixPtr Matrix = (MatrixPtr)eMatrix;/* Begin `spGetSize'. */ ASSERT( IS_SPARSE( Matrix ) );#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> (char *) * Pointer to matrix. */voidspSetReal( eMatrix )char *eMatrix;{/* Begin `spSetReal'. */ ASSERT( IS_SPARSE( (MatrixPtr)eMatrix ) AND REAL); ((MatrixPtr)eMatrix)->Complex = NO; return;}voidspSetComplex( eMatrix )char *eMatrix;{/* Begin `spSetComplex'. */ ASSERT( IS_SPARSE( (MatrixPtr)eMatrix ) AND spCOMPLEX); ((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> (char *) * Pointer to matrix. */intspFillinCount( eMatrix )char *eMatrix;{/* Begin `spFillinCount'. */ ASSERT( IS_SPARSE( (MatrixPtr)eMatrix ) ); return ((MatrixPtr)eMatrix)->Fillins;}intspElementCount( eMatrix )char *eMatrix;{/* Begin `spElementCount'. */ ASSERT( IS_SPARSE( (MatrixPtr)eMatrix ) ); return ((MatrixPtr)eMatrix)->Elements;}intspOriginalCount( eMatrix )char *eMatrix;{/* Begin `spOriginalCount'. */ ASSERT( IS_SPARSE( (MatrixPtr)eMatrix ) ); return ((MatrixPtr)eMatrix)->Originals;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -