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

📄 spfactor.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 *      Index of the diagonal currently being eliminated. * *  >>> Local variables: *  ChosenPivot  (ElementPtr) *      Pointer to element that has been chosen to be the pivot. *  PivotMag  (RealNumber) *      Magnitude of ChosenPivot. *  Singletons  (int) *      The count of the number of singletons that can be used as pivots. *      A local version of Matrix->Singletons. *  pMarkowitzProduct  (long *) *      Pointer that points into MarkowitzProduct array. It is used to quickly *      access successive Markowitz products. */static ElementPtrSearchForSingleton( Matrix, Step )MatrixPtr Matrix;int Step;{register  ElementPtr  ChosenPivot;register  int  I;register  long  *pMarkowitzProduct;int  Singletons;RealNumber  PivotMag, FindBiggestInColExclude();/* Begin `SearchForSingleton'. *//* Initialize pointer that is to scan through MarkowitzProduct vector. */    pMarkowitzProduct = &(Matrix->MarkowitzProd[Matrix->Size+1]);    Matrix->MarkowitzProd[Matrix->Size+1] = Matrix->MarkowitzProd[Step];/* Decrement the count of available singletons, on the assumption that an * acceptable one will be found. */    Singletons = Matrix->Singletons--;/* * Assure that following while loop will always terminate, this is just * preventive medicine, if things are working right this should never * be needed. */    Matrix->MarkowitzProd[Step-1] = 0;    while (Singletons-- > 0)    {/* Singletons exist, find them. *//* * This is tricky.  Am using a pointer to sequentially step through the * MarkowitzProduct array.  Search terminates when singleton (Product = 0) * is found.  Note that the conditional in the while statement * ( *pMarkowitzProduct ) is true as long as the MarkowitzProduct is not * equal to zero.  The row (and column) index 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 singleton. * * 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. */        while ( *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 + 1;/* Assure that I is valid. */        if (I < Step) break;  /* while (Singletons-- > 0) */        if (I > Matrix->Size) I = Step;/* Singleton has been found in either/both row or/and column I. */        if ((ChosenPivot = Matrix->Diag[I]) != NULL)        {/* Singleton lies on the diagonal. */            PivotMag = ELEMENT_MAG(ChosenPivot);            if            (    PivotMag > Matrix->AbsThreshold AND                 PivotMag > Matrix->RelThreshold *                            FindBiggestInColExclude( Matrix, ChosenPivot, Step )            ) return ChosenPivot;        }        else        {/* Singleton does not lie on diagonal, find it. */            if (Matrix->MarkowitzCol[I] == 0)            {   ChosenPivot = Matrix->FirstInCol[I];                while ((ChosenPivot != NULL) AND (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 AND                     PivotMag > Matrix->RelThreshold *                                FindBiggestInColExclude( Matrix, ChosenPivot,                                                         Step )                ) return ChosenPivot;                else                {   if (Matrix->MarkowitzRow[I] == 0)                    {   ChosenPivot = Matrix->FirstInRow[I];                        while((ChosenPivot != NULL) AND (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 AND                             PivotMag > Matrix->RelThreshold *                                        FindBiggestInColExclude( Matrix,                                                                 ChosenPivot,                                                                 Step )                        ) return ChosenPivot;                    }                }            }            else            {   ChosenPivot = Matrix->FirstInRow[I];                while ((ChosenPivot != NULL) AND (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 AND                     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;{register long  MinMarkowitzProduct, *pMarkowitzProduct;register  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) index 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 AND pOtherInCol == NULL)            {    pOtherInRow = Matrix->FirstInRow[I];                 while(pOtherInRow != NULL)                 {   if (pOtherInRow->Col >= Step AND pOtherInRow->Col != I)                         break;                     pOtherInRow = pOtherInRow->NextInRow;                 }                 pOtherInCol = Matrix->FirstInCol[I];                 while(pOtherInCol != NULL)                 {   if (pOtherInCol->Row >= Step AND 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  AND  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;}

⌨️ 快捷键说明

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