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

📄 spfactor.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
📖 第 1 页 / 共 5 页
字号:
        { /* Singleton does not lie on diagonal, find it. */            if (Matrix->MarkowitzCol[I] == 0)            {    ChosenPivot = Matrix->FirstInCol[I];                while ((ChosenPivot != NULL) && (ChosenPivot->Row < Step))                    ChosenPivot = ChosenPivot->NextInCol;		if (ChosenPivot != NULL)		{    /* Reduced column has no elements, matrix is singular. */		    break;		}                PivotMag = ELEMENT_MAG(ChosenPivot);                if                (    PivotMag > Matrix->AbsThreshold &&                     PivotMag > Matrix->RelThreshold *                                FindBiggestInColExclude( Matrix, ChosenPivot,                                                         Step )                ) return ChosenPivot;                else                {    if (Matrix->MarkowitzRow[I] == 0)                    {    ChosenPivot = Matrix->FirstInRow[I];                        while((ChosenPivot != NULL) && (ChosenPivot->Col<Step))                            ChosenPivot = ChosenPivot->NextInRow;			if (ChosenPivot != NULL)			{  /* Reduced row has no elements, matrix is singular. */			    break;			}                        PivotMag = ELEMENT_MAG(ChosenPivot);                        if                        (    PivotMag > Matrix->AbsThreshold &&                             PivotMag > Matrix->RelThreshold *                                        FindBiggestInColExclude( Matrix,                                                                 ChosenPivot,                                                                 Step )                        ) return ChosenPivot;                    }                }            }            else            {    ChosenPivot = Matrix->FirstInRow[I];                while ((ChosenPivot != NULL) && (ChosenPivot->Col < Step))                    ChosenPivot = ChosenPivot->NextInRow;		if (ChosenPivot != NULL)		{    /* Reduced row has no elements, matrix is singular. */		    break;		}                PivotMag = ELEMENT_MAG(ChosenPivot);                if                (    PivotMag > Matrix->AbsThreshold &&                     PivotMag > Matrix->RelThreshold *                                FindBiggestInColExclude( Matrix, ChosenPivot,                                                         Step )                ) return ChosenPivot;            }        } /* Singleton not acceptable (too small), try another. */    } /* end of while(lSingletons>0) */ /* * All singletons were unacceptable.  Restore Matrix->Singletons count. * Initial assumption that an acceptable singleton would be found was wrong. */    Matrix->Singletons++;    return NULL;}#if DIAGONAL_PIVOTING#if MODIFIED_MARKOWITZ/* *  QUICK SEARCH OF 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.  Search terminates *  early if a diagonal is found with a MarkowitzProduct of one and its *  magnitude is larger than the other elements in its row and column. *  Since its MarkowitzProduct is one, there is only one other element in *  both its row and column, and, as a condition for early termination, *  these elements must be located symmetricly in the matrix.  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 (largest 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: *  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. *  LargestOffDiagonal  (RealNumber) *      Magnitude of the largest of the off-diagonal terms associated with *      a diagonal with MarkowitzProduct equal to one. *  Magnitude  (RealNumber) *      Absolute value of diagonal element. *  MaxRatio  (RealNumber) *      Among the elements tied with the smallest Markowitz product, MaxRatio *      is the best (smallest) ratio of LargestInCol to the diagonal Magnitude *      found so far.  The smaller the ratio, the better numerically the *      element will be as pivot. *  MinMarkowitzProduct  (long) *      Smallest Markowitz product found of pivot candidates that lie along *      diagonal. *  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 (excluding itself) to its magnitude. *  TiedElements  (ElementPtr[]) *      Array of pointers to the elements with the minimum Markowitz *      product. *  pOtherInCol  (ElementPtr) *      When there is only one other element in a column other than the *      diagonal, pOtherInCol is used to point to it.  Used when Markowitz *      product is to determine if off diagonals are placed symmetricly. *  pOtherInRow  (ElementPtr) *      When there is only one other element in a row other than the diagonal, *      pOtherInRow is used to point to it.  Used when Markowitz product is *      to determine if off diagonals are placed symmetricly. */static ElementPtrQuicklySearchDiagonal( Matrix, Step )MatrixPtr Matrix;int Step;{long  MinMarkowitzProduct, *pMarkowitzProduct; ElementPtr  pDiag, pOtherInRow, pOtherInCol;int  I, NumberOfTies;ElementPtr  ChosenPivot, TiedElements[MAX_MARKOWITZ_TIES + 1];RealNumber  Magnitude, LargestInCol, Ratio, MaxRatio;RealNumber  LargestOffDiagonal;RealNumber  FindBiggestInColExclude(); /* Begin `QuicklySearchDiagonal'. */    NumberOfTies = -1;    MinMarkowitzProduct = LARGEST_LONG_INTEGER;    pMarkowitzProduct = &(Matrix->MarkowitzProd[Matrix->Size+2]);    Matrix->MarkowitzProd[Matrix->Size+1] = Matrix->MarkowitzProd[Step]; /* Assure that following while loop will always terminate. */    Matrix->MarkowitzProd[Step-1] = -1; /* * This is tricky.  Am using a pointer in the inner while loop to * sequentially step through the MarkowitzProduct array.  Search * terminates when the Markowitz product of zero placed at location * Step-1 is found.  The row (and column)strchr on the diagonal is then * calculated by subtracting the pointer to the Markowitz product of * 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 (MinMarkowitzProduct < *(--pMarkowitzProduct))        {    /*             * N bottles of beer on the wall;             * N bottles of beer.             * You take one down and pass it around;             * N-1 bottles of beer on the wall.             */        }        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;                    }                }            }        }        if (*pMarkowitzProduct < MinMarkowitzProduct)        { /* Notice strict inequality in test. This is a new smallest MarkowitzProduct. */            TiedElements[0] = pDiag;            MinMarkowitzProduct = *pMarkowitzProduct;            NumberOfTies = 0;        }        else        { /* This case handles Markowitz ties. */            if (NumberOfTies < MAX_MARKOWITZ_TIES)            {    TiedElements[++NumberOfTies] = pDiag;                if (NumberOfTies >= MinMarkowitzProduct * TIES_MULTIPLIER)                    break; /* Endless for loop */            }        }    } /* End of endless for loop. */ /* Test to see if any element was chosen as a pivot candidate. */    if (NumberOfTies < 0)        return NULL; /* Determine which of tied elements is best numerically. */    ChosenPivot = NULL;    MaxRatio = 1.0 / Matrix->RelThreshold;    for (I = 0; I <= NumberOfTies; I++)    {    pDiag = TiedElements[I];        Magnitude = ELEMENT_MAG(pDiag);        LargestInCol = FindBiggestInColExclude( Matrix, pDiag, Step );        Ratio = LargestInCol / Magnitude;        if (Ratio < MaxRatio)        {    ChosenPivot = pDiag;            MaxRatio = Ratio;        }    }    return ChosenPivot;}#else /* Not MODIFIED_MARKOWITZ *//* *  QUICK SEARCH OF DIAGONAL FOR PIVOT WITH CONVENTIONAL 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.  Search terminates *  early if a diagonal is found with a MarkowitzProduct of one and its *  magnitude is larger than the other elements in its row and column. *  Since its MarkowitzProduct is one, there is only one other element in *  both its row and column, and, as a condition for early termination, *  these elements must be located symmetricly in the matrix. * *  >>> 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. *  LargestOffDiagonal  (RealNumber) *      Magnitude of the largest of the off-diagonal terms associated with *      a diagonal with MarkowitzProduct equal to one. *  Magnitude  (RealNumber) *      Absolute value of diagonal element. *  MinMarkowitzProduct  (long) *      Smallest Markowitz product found of pivot candidates which are *      acceptable. *  pDiag  (ElementPtr) *      Pointer to current diagonal element. *  pMarkowitzProduct  (long *) *      Pointer that points into MarkowitzProduct array. It is used to quickly *      access successive Markowitz products. *  pOtherInCol  (ElementPtr) *      When there is only one other element in a column other than the *      diagonal, pOtherInCol is used to point to it.  Used when Markowitz *      product is to determine if off diagonals are placed symmetricly. *  pOtherInRow  (ElementPtr) *      When there is only one other element in a row other than the diagonal, *      pOtherInRow is used to point to it.  Used when Markowitz product is *      to determine if off diagonals are placed symmetricly. */static ElementPtrQuicklySearchDiagonal( Matrix, Step )MatrixPtr Matrix;int Step;{long  MinMarkowitzProduct, *pMarkowitzProduct; ElementPtr  pDiag;int  I;ElementPtr  ChosenPivot, pOtherInRow, pOtherInCol;RealNumber  Magnitude, LargestInCol, LargestOffDiagonal;RealNumber  FindBiggestInColExclude(); /* Begin `QuicklySearchDiagonal'. */    ChosenPivot = NULL;    MinMarkowitzProduct = LARGEST_LONG_INTEGER;    pMarkowitzProduct = &(Matrix->MarkowitzProd[Matrix->Size+2]);    Matrix->MarkowitzProd[Matrix->Size+1] = Matrix->MarkowitzProd[Step]; /* Assure that following while loop will always terminate. */    Matrix->MarkowitzProd[Step-1] = -1; /* * This is tricky.  Am using a pointer in the inner while loop to * sequentially step through the MarkowitzProduct array.  Search * terminates when the Markowitz product of zero placed at location * Step-1 is found.  The row (and column)strchr on the diagonal is then * calculated by subtracting the pointer to the Markowitz product of

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -