⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spfactor.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
📖 第 1 页 / 共 5 页
字号:
 * 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 + -