📄 spfactor.c
字号:
* the first diagonal from the pointer to the Markowitz product of the * desired element. The outer for loop is infinite, broken by using * break. * * Search proceeds from the end (high row and column numbers) to the * beginning (low row and column numbers) so that rows and columns with * large Markowitz products will tend to be move to the bottom of the * matrix. However, choosing Diag[Step] is desirable because it would * require no row and column interchanges, so inspect it first by * putting its Markowitz product at the end of the MarkowitzProd * vector. */ for (;;) /* Endless for loop. */ { while (*(--pMarkowitzProduct) >= MinMarkowitzProduct) { /* Just passing through. */ } I = pMarkowitzProduct - Matrix->MarkowitzProd; /* Assure that I is valid; if I < Step, terminate search. */ if (I < Step) break; /* Endless for loop */ if (I > Matrix->Size) I = Step; if ((pDiag = Matrix->Diag[I]) == NULL) continue; /* Endless for loop */ if ((Magnitude = ELEMENT_MAG(pDiag)) <= Matrix->AbsThreshold) continue; /* Endless for loop */ if (*pMarkowitzProduct == 1) { /* Case where only one element exists in row and column other than diagonal. */ /* Find off-diagonal elements. */ pOtherInRow = pDiag->NextInRow; pOtherInCol = pDiag->NextInCol; if (pOtherInRow == NULL && pOtherInCol == NULL) { pOtherInRow = Matrix->FirstInRow[I]; while(pOtherInRow != NULL) { if (pOtherInRow->Col >= Step && pOtherInRow->Col != I) break; pOtherInRow = pOtherInRow->NextInRow; } pOtherInCol = Matrix->FirstInCol[I]; while(pOtherInCol != NULL) { if (pOtherInCol->Row >= Step && pOtherInCol->Row != I) break; pOtherInCol = pOtherInCol->NextInCol; } } /* Accept diagonal as pivot if diagonal is larger than off-diagonals and the * off-diagonals are placed symmetricly. */ if (pOtherInRow != NULL && pOtherInCol != NULL) { if (pOtherInRow->Col == pOtherInCol->Row) { LargestOffDiagonal = MAX(ELEMENT_MAG(pOtherInRow), ELEMENT_MAG(pOtherInCol)); if (Magnitude >= LargestOffDiagonal) { /* Accept pivot, it is unlikely to contribute excess error. */ return pDiag; } } } } MinMarkowitzProduct = *pMarkowitzProduct; ChosenPivot = pDiag; } /* End of endless for loop. */ if (ChosenPivot != NULL) { LargestInCol = FindBiggestInColExclude( Matrix, ChosenPivot, Step ); if( ELEMENT_MAG(ChosenPivot) <= Matrix->RelThreshold * LargestInCol ) ChosenPivot = NULL; } return ChosenPivot;}#endif /* Not MODIFIED_MARKOWITZ *//* * SEARCH DIAGONAL FOR PIVOT WITH MODIFIED MARKOWITZ CRITERION * * Searches the diagonal looking for the best pivot. For a pivot to be * acceptable it must be larger than the pivot RelThreshold times the largest * element in its reduced column. Among the acceptable diagonals, the * one with the smallest MarkowitzProduct is sought. If a tie occurs * between elements of equal MarkowitzProduct, then the element with * the largest ratio between its magnitude and the largest element in its * column is used. The search will be terminated after a given number of * ties have occurred and the best (smallest ratio) of the tied element will * be used as the pivot. The number of ties that will trigger an early * termination is MinMarkowitzProduct * TIES_MULTIPLIER. * * >>> Returned: * A pointer to the diagonal element chosen to be pivot. If no diagonal is * acceptable, a NULL is returned. * * >>> Arguments: * Matrix <input> (MatrixPtr) * Pointer to matrix. * Step <input> (int) * Index of the diagonal currently being eliminated. * * >>> Local variables: * ChosenPivot (ElementPtr) * Pointer to the element that has been chosen to be the pivot. * Size (int) * Local version of size which is placed in a to increase speed. * Magnitude (RealNumber) * Absolute value of diagonal element. * MinMarkowitzProduct (long) * Smallest Markowitz product found of those pivot candidates which are * acceptable. * NumberOfTies (int) * A count of the number of Markowitz ties that have occurred at current * MarkowitzProduct. * pDiag (ElementPtr) * Pointer to current diagonal element. * pMarkowitzProduct (long*) * Pointer that points into MarkowitzProduct array. It is used to quickly * access successive Markowitz products. * Ratio (RealNumber) * For the current pivot candidate, Ratio is the * Ratio of the largest element in its column to its magnitude. * RatioOfAccepted (RealNumber) * For the best pivot candidate found so far, RatioOfAccepted is the * Ratio of the largest element in its column to its magnitude. */static ElementPtrSearchDiagonal( Matrix, Step )MatrixPtr Matrix;int Step;{ int J; long MinMarkowitzProduct, *pMarkowitzProduct; int I; ElementPtr pDiag; int NumberOfTies = 0; int Size = Matrix->Size; ElementPtr ChosenPivot; RealNumber Magnitude, Ratio; RealNumber RatioOfAccepted = 0; RealNumber LargestInCol; RealNumber FindBiggestInColExclude(); /* Begin `SearchDiagonal'. */ ChosenPivot = NULL; MinMarkowitzProduct = LARGEST_LONG_INTEGER; pMarkowitzProduct = &(Matrix->MarkowitzProd[Size+2]); Matrix->MarkowitzProd[Size+1] = Matrix->MarkowitzProd[Step]; /* Start search of diagonal. */ for (J = Size+1; J > Step; J--) { if (*(--pMarkowitzProduct) > MinMarkowitzProduct) continue; /* for loop */ if (J > Matrix->Size) I = Step; else I = J; if ((pDiag = Matrix->Diag[I]) == NULL) continue; /* for loop */ if ((Magnitude = ELEMENT_MAG(pDiag)) <= Matrix->AbsThreshold) continue; /* for loop */ /* Test to see if diagonal's magnitude is acceptable. */ LargestInCol = FindBiggestInColExclude( Matrix, pDiag, Step ); if (Magnitude <= Matrix->RelThreshold * LargestInCol) continue; /* for loop */ if (*pMarkowitzProduct < MinMarkowitzProduct) { /* Notice strict inequality in test. This is a new smallest MarkowitzProduct. */ ChosenPivot = pDiag; MinMarkowitzProduct = *pMarkowitzProduct; RatioOfAccepted = LargestInCol / Magnitude; NumberOfTies = 0; } else { /* This case handles Markowitz ties. */ NumberOfTies++; Ratio = LargestInCol / Magnitude; if (Ratio < RatioOfAccepted) { ChosenPivot = pDiag; RatioOfAccepted = Ratio; } if (NumberOfTies >= MinMarkowitzProduct * TIES_MULTIPLIER) return ChosenPivot; } } /* End of for(Step) */ return ChosenPivot;}#endif /* DIAGONAL_PIVOTING *//* * SEARCH ENTIRE MATRIX FOR BEST PIVOT * * Performs a search over the entire matrix looking for the acceptable * element with the lowest MarkowitzProduct. If there are several that * are tied for the smallest MarkowitzProduct, the tie is broken by using * the ratio of the magnitude of the element being considered to the largest * element in the same column. If no element is acceptable then the largest * element in the reduced submatrix is used as the pivot and the * matrix is declared to be spSMALL_PIVOT. If the largest element is * zero, the matrix is declared to be spSINGULAR. * * >>> Returned: * A pointer to the diagonal element chosen to be pivot. If no element is * found, then NULL is returned and the matrix is spSINGULAR. * * >>> Arguments: * Matrix <input> (MatrixPtr) * Pointer to matrix. * Step <input> (int) * Index of the diagonal currently being eliminated. * * >>> Local variables: * ChosenPivot (ElementPtr) * Pointer to the element that has been chosen to be the pivot. * LargestElementMag (RealNumber) * Magnitude of the largest element yet found in the reduced submatrix. * Size (int) * Local version of Size; placed in a for speed. * Magnitude (RealNumber) * Absolute value of diagonal element. * MinMarkowitzProduct (long) * Smallest Markowitz product found of pivot candidates which are * acceptable. * NumberOfTies (int) * A count of the number of Markowitz ties that have occurred at current * MarkowitzProduct. * pElement (ElementPtr) * Pointer to current element. * pLargestElement (ElementPtr) * Pointer to the largest element yet found in the reduced submatrix. * Product (long) * Markowitz product for the current row and column. * Ratio (RealNumber) * For the current pivot candidate, Ratio is the * Ratio of the largest element in its column to its magnitude. * RatioOfAccepted (RealNumber) * For the best pivot candidate found so far, RatioOfAccepted is the * Ratio of the largest element in its column to its magnitude. * * >>> Possible errors: * spSINGULAR * spSMALL_PIVOT */static ElementPtrSearchEntireMatrix( Matrix, Step )MatrixPtr Matrix;int Step;{ int I, Size = Matrix->Size; ElementPtr pElement; int NumberOfTies = 0; long Product, MinMarkowitzProduct; ElementPtr ChosenPivot; ElementPtr pLargestElement = NULL; RealNumber Magnitude, LargestElementMag, Ratio; RealNumber RatioOfAccepted = 0; RealNumber LargestInCol; RealNumber FindLargestInCol(); /* Begin `SearchEntireMatrix'. */ ChosenPivot = NULL; LargestElementMag = 0.0; MinMarkowitzProduct = LARGEST_LONG_INTEGER; /* Start search of matrix on column by column basis. */ for (I = Step; I <= Size; I++) { pElement = Matrix->FirstInCol[I]; while (pElement != NULL && pElement->Row < Step) pElement = pElement->NextInCol; if((LargestInCol = FindLargestInCol(pElement)) == 0.0) continue; /* for loop */ while (pElement != NULL) { /* Check to see if element is the largest encountered so far. If so, record its magnitude and address. */ if ((Magnitude = ELEMENT_MAG(pElement)) > LargestElementMag) { LargestElementMag = Magnitude; pLargestElement = pElement; } /* Calculate element's MarkowitzProduct. */ Product = Matrix->MarkowitzRow[pElement->Row] * Matrix->MarkowitzCol[pElement->Col]; /* Test to see if element is acceptable as a pivot candidate. */ if ((Product <= MinMarkowitzProduct) && (Magnitude > Matrix->RelThreshold * LargestInCol) && (Magnitude > Matrix->AbsThreshold)) { /* Test to see if element has lowest MarkowitzProduct yet found, or whether it is tied with an element found earlier. */ if (Product < MinMarkowitzProduct) { /* Notice strict inequality in test. This is a new smallest MarkowitzProduct. */ ChosenPivot = pElement; MinMarkowitzProduct = Product; RatioOfAccepted = LargestInCol / Magnitude; NumberOfTies = 0; } else { /* This case handles Markowitz ties. */ NumberOfTies++; Ratio = LargestInCol / Magnitude; if (Ratio < RatioOfAccepted) { ChosenPivot = pElement; RatioOfAccepted = Ratio; } if (NumberOfTies >= MinMarkowitzProduct * TIES_MULTIPLIER) return ChosenPivot; } } pElement = pElement->NextInCol; } /* End of while(pElement != NULL) */ } /* End of for(Step) */ if (ChosenPivot != NULL) return ChosenPivot; if (LargestElementMag == 0.0) { Matrix->Error = spSINGULAR; return NULL; } Matrix->Error = spSMALL_PIVOT; return pLargestElement;}/* * DETERMINE THE MAGNITUDE OF THE LARGEST ELEMENT IN A COLUMN * * Thi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -