📄 spfactor.c
字号:
* Pointer to matrix. * * >>> Local variables: * SizePlusOne (unsigned) * Size of the arrays to be allocated. * * >>> Possible errors: * spNO_MEMORY */voidspcCreateInternalVectors( Matrix )MatrixPtr Matrix;{int Size;/* Begin `spcCreateInternalVectors'. *//* Create Markowitz arrays. */ Size= Matrix->Size; if (Matrix->MarkowitzRow == NULL) { if (( Matrix->MarkowitzRow = ALLOC(int, Size+1)) == NULL) Matrix->Error = spNO_MEMORY; } if (Matrix->MarkowitzCol == NULL) { if (( Matrix->MarkowitzCol = ALLOC(int, Size+1)) == NULL) Matrix->Error = spNO_MEMORY; } if (Matrix->MarkowitzProd == NULL) { if (( Matrix->MarkowitzProd = ALLOC(long, Size+2)) == NULL) Matrix->Error = spNO_MEMORY; }/* Create DoDirect vectors for use in spFactor(). */#if REAL if (Matrix->DoRealDirect == NULL) { if (( Matrix->DoRealDirect = ALLOC(BOOLEAN, Size+1)) == NULL) Matrix->Error = spNO_MEMORY; }#endif#if spCOMPLEX if (Matrix->DoCmplxDirect == NULL) { if (( Matrix->DoCmplxDirect = ALLOC(BOOLEAN, Size+1)) == NULL) Matrix->Error = spNO_MEMORY; }#endif/* Create Intermediate vectors for use in MatrixSolve. */#if spCOMPLEX if (Matrix->Intermediate == NULL) { if ((Matrix->Intermediate = ALLOC(RealNumber,2*(Size+1))) == NULL) Matrix->Error = spNO_MEMORY; }#else if (Matrix->Intermediate == NULL) { if ((Matrix->Intermediate = ALLOC(RealNumber, Size+1)) == NULL) Matrix->Error = spNO_MEMORY; }#endif if (Matrix->Error != spNO_MEMORY) Matrix->InternalVectorsAllocated = YES; return;}/* * COUNT MARKOWITZ * * Scans Matrix to determine the Markowitz counts for each row and column. * * >>> Arguments: * Matrix <input> (MatrixPtr) * Pointer to matrix. * RHS <input> (RealVector) * Representative right-hand side vector that is used to determine * pivoting order when the right hand side vector is sparse. If * RHS is a NULL pointer then the RHS vector is assumed to be full * and it is not used when determining the pivoting order. * Step <input> (int) * Index of the diagonal currently being eliminated. * * >>> Local variables: * Count (int) * Temporary counting variable. * ExtRow (int) * The external row number that corresponds to I. * pElement (ElementPtr) * Pointer to matrix elements. * Size (int) * The size of the matrix. */static voidCountMarkowitz( Matrix, RHS, Step )MatrixPtr Matrix;register RealVector RHS;int Step;{register int Count, I, Size = Matrix->Size;register ElementPtr pElement;int ExtRow;/* Begin `CountMarkowitz'. *//* Correct array pointer for ARRAY_OFFSET. */#if NOT ARRAY_OFFSET#if spSEPARATED_COMPLEX_VECTORS OR NOT spCOMPLEX if (RHS != NULL) --RHS;#else if (RHS != NULL) { if (Matrix->Complex) RHS -= 2; else --RHS; }#endif#endif/* Generate MarkowitzRow Count for each row. */ for (I = Step; I <= Size; I++) {/* Set Count to -1 initially to remove count due to pivot element. */ Count = -1; pElement = Matrix->FirstInRow[I]; while (pElement != NULL AND pElement->Col < Step) pElement = pElement->NextInRow; while (pElement != NULL) { Count++; pElement = pElement->NextInRow; }/* Include nonzero elements in the RHS vector. */ ExtRow = Matrix->IntToExtRowMap[I];#if spSEPARATED_COMPLEX_VECTORS OR NOT spCOMPLEX if (RHS != NULL) if (RHS[ExtRow] != 0.0) Count++;#else if (RHS != NULL) { if (Matrix->Complex) { if ((RHS[2*ExtRow] != 0.0) OR (RHS[2*ExtRow+1] != 0.0)) Count++; } else if (RHS[I] != 0.0) Count++; }#endif Matrix->MarkowitzRow[I] = Count; }/* Generate the MarkowitzCol count for each column. */ for (I = Step; I <= Size; I++) {/* Set Count to -1 initially to remove count due to pivot element. */ Count = -1; pElement = Matrix->FirstInCol[I]; while (pElement != NULL AND pElement->Row < Step) pElement = pElement->NextInCol; while (pElement != NULL) { Count++; pElement = pElement->NextInCol; } Matrix->MarkowitzCol[I] = Count; } return;}/* * MARKOWITZ PRODUCTS * * Calculates MarkowitzProduct for each diagonal element from the Markowitz * counts. * * >>> Arguments: * Matrix <input> (MatrixPtr) * Pointer to matrix. * Step <input> (int) * Index of the diagonal currently being eliminated. * * >>> Local Variables: * pMarkowitzProduct (long *) * Pointer that points into MarkowitzProduct array. Is used to * sequentially access entries quickly. * pMarkowitzRow (int *) * Pointer that points into MarkowitzRow array. Is used to sequentially * access entries quickly. * pMarkowitzCol (int *) * Pointer that points into MarkowitzCol array. Is used to sequentially * access entries quickly. * Product (long) * Temporary storage for Markowitz product./ * Size (int) * The size of the matrix. */static voidMarkowitzProducts( Matrix, Step )MatrixPtr Matrix;int Step;{register int I, *pMarkowitzRow, *pMarkowitzCol;register long Product, *pMarkowitzProduct;register int Size = Matrix->Size;double fProduct;/* Begin `MarkowitzProducts'. */ Matrix->Singletons = 0; pMarkowitzProduct = &(Matrix->MarkowitzProd[Step]); pMarkowitzRow = &(Matrix->MarkowitzRow[Step]); pMarkowitzCol = &(Matrix->MarkowitzCol[Step]); for (I = Step; I <= Size; I++) {/* If chance of overflow, use real numbers. */ if ((*pMarkowitzRow > LARGEST_SHORT_INTEGER AND *pMarkowitzCol != 0) OR (*pMarkowitzCol > LARGEST_SHORT_INTEGER AND *pMarkowitzRow != 0)) { fProduct = (double)(*pMarkowitzRow++) * (double)(*pMarkowitzCol++); if (fProduct >= LARGEST_LONG_INTEGER) *pMarkowitzProduct++ = LARGEST_LONG_INTEGER; else *pMarkowitzProduct++ = fProduct; } else { Product = *pMarkowitzRow++ * *pMarkowitzCol++; if ((*pMarkowitzProduct++ = Product) == 0) Matrix->Singletons++; } } return;}/* * SEARCH FOR BEST PIVOT * * Performs a search to determine the element with the lowest Markowitz * Product that is also acceptable. An acceptable element is one that is * larger than the AbsThreshold and at least as large as RelThreshold times * the largest element in the same column. The first step is to look for * singletons if any exist. If none are found, then all the diagonals are * searched. The diagonal is searched once quickly using the assumption that * elements on the diagonal are large compared to other elements in their * column, and so the pivot can be chosen only on the basis of the Markowitz * criterion. After a element has been chosen to be pivot on the basis of * its Markowitz product, it is checked to see if it is large enough. * Waiting to the end of the Markowitz search to check the size of a pivot * candidate saves considerable time, but is not guaranteed to find an * acceptable pivot. Thus if unsuccessful a second pass of the diagonal is * made. This second pass checks to see if an element is large enough during * the search, not after it. If still no acceptable pivot candidate has * been found, the search expands to cover the entire matrix. * * >>> Returned: * A pointer to the element chosen to be pivot. If every element in the * matrix is zero, then NULL is returned. * * >>> Arguments: * Matrix <input> (MatrixPtr) * Pointer to matrix. * Step <input> (int) * The row and column number of the beginning of the reduced submatrix. * * >>> Local variables: * ChosenPivot (ElementPtr) * Pointer to element that has been chosen to be the pivot. * * >>> Possible errors: * spSINGULAR * spSMALL_PIVOT */static ElementPtrSearchForPivot( Matrix, Step, DiagPivoting )MatrixPtr Matrix;int Step, DiagPivoting;{register ElementPtr ChosenPivot;ElementPtr SearchForSingleton();ElementPtr QuicklySearchDiagonal();ElementPtr SearchDiagonal();ElementPtr SearchEntireMatrix();/* Begin `SearchForPivot'. *//* If singletons exist, look for an acceptable one to use as pivot. */ if (Matrix->Singletons) { ChosenPivot = SearchForSingleton( Matrix, Step ); if (ChosenPivot != NULL) { Matrix->PivotSelectionMethod = 's'; return ChosenPivot; } }#if DIAGONAL_PIVOTING if (DiagPivoting) {/* * Either no singletons exist or they weren't acceptable. Take quick first * pass at searching diagonal. First search for element on diagonal of * remaining submatrix with smallest Markowitz product, then check to see * if it okay numerically. If not, QuicklySearchDiagonal fails. */ ChosenPivot = QuicklySearchDiagonal( Matrix, Step ); if (ChosenPivot != NULL) { Matrix->PivotSelectionMethod = 'q'; return ChosenPivot; }/* * Quick search of diagonal failed, carefully search diagonal and check each * pivot candidate numerically before even tentatively accepting it. */ ChosenPivot = SearchDiagonal( Matrix, Step ); if (ChosenPivot != NULL) { Matrix->PivotSelectionMethod = 'd'; return ChosenPivot; } }#endif /* DIAGONAL_PIVOTING *//* No acceptable pivot found yet, search entire matrix. */ ChosenPivot = SearchEntireMatrix( Matrix, Step ); Matrix->PivotSelectionMethod = 'e'; return ChosenPivot;}/* * SEARCH FOR SINGLETON TO USE AS PIVOT * * Performs a search to find a singleton to use as the pivot. The * first acceptable singleton is used. A singleton is acceptable if * it is larger in magnitude than the AbsThreshold and larger * than RelThreshold times the largest of any other elements in the same * column. It may seem that a singleton need not satisfy the * relative threshold criterion, however it is necessary to prevent * excessive growth in the RHS from resulting in overflow during the * forward and backward substitution. A singleton does not need to * be on the diagonal to be selected. * * >>> Returned: * A pointer to the singleton chosen to be pivot. In no singleton is * acceptable, return NULL. * * >>> Arguments: * Matrix <input> (MatrixPtr) * Pointer to matrix. * Step <input> (int)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -