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

📄 sputils.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
📖 第 1 页 / 共 5 页
字号:
#if PSEUDOCONDITION/* *  CALCULATE PSEUDOCONDITION * *  Computes the magnitude of the ratio of the largest to the smallest *  pivots.  This quantity is an indicator of ill-conditioning in the *  matrix.  If this ratio is large, and if the matrix is scaled such *  that uncertainties in the RHS and the matrix entries are *  equilibrated, then the matrix is ill-conditioned.  However, a *  small ratio does not necessarily imply that the matrix is *  well-conditioned.  This routine must only be used after a matrix *  has been factored by spOrderAndFactor() or spFactor() and before *  it is cleared by spClear() or spInitialize().  The pseudocondition *  is faster to compute than the condition number calculated by *  spCondition(), but is not as informative. * *  >>> Returns: *  The magnitude of the ratio of the largest to smallest pivot used during *  previous factorization.  If the matrix was singular, zero is returned. * *  >>> Arguments: *  eMatrix  <input>  (char *) *      Pointer to the matrix.  */RealNumberspPseudoCondition(char *eMatrix){    MatrixPtr  Matrix = (MatrixPtr)eMatrix;    int I;    ArrayOfElementPtrs Diag;    RealNumber MaxPivot, MinPivot, Mag;    /* Begin `spPseudoCondition'. */    assert( IS_SPARSE(Matrix) && IS_FACTORED(Matrix) );    if (Matrix->Error == spSINGULAR || Matrix->Error == spZERO_DIAG)        return 0.0;    Diag = Matrix->Diag;    MaxPivot = MinPivot = ELEMENT_MAG( Diag[1] );    for (I = 2; I <= Matrix->Size; I++)    {	Mag = ELEMENT_MAG( Diag[I] );	if (Mag > MaxPivot)	    MaxPivot = Mag;	else if (Mag < MinPivot)	    MinPivot = Mag;    }    assert( MaxPivot > 0.0);    return MaxPivot / MinPivot;}#endif#if CONDITION/* *  ESTIMATE CONDITION NUMBER * *  Computes an estimate of the condition number using a variation on *  the LINPACK condition number estimation algorithm.  This quantity *  is an indicator of ill-conditioning in the matrix.  To avoid *  problems with overflow, the reciprocal of the condition number is *  returned.  If this number is small, and if the matrix is scaled *  such that uncertainties in the RHS and the matrix entries are *  equilibrated, then the matrix is ill-conditioned.  If the this *  number is near one, the matrix is well conditioned.  This routine *  must only be used after a matrix has been factored by *  spOrderAndFactor() or spFactor() and before it is cleared by *  spClear() or spInitialize(). * *  Unlike the LINPACK condition number estimator, this routines *  returns the L infinity condition number.  This is an artifact of *  Sparse placing ones on the diagonal of the upper triangular matrix *  rather than the lower.  This difference should be of no *  importance. * *  References: *  A.K. Cline, C.B. Moler, G.W. Stewart, J.H. Wilkinson.  An estimate *  for the condition number of a matrix.  SIAM Journal on Numerical *  Analysis.  Vol. 16, No. 2, pages 368-375, April 1979. *   *  J.J. Dongarra, C.B. Moler, J.R. Bunch, G.W. Stewart.  LINPACK *  User's Guide.  SIAM, 1979. *   *  Roger G. Grimes, John G. Lewis.  Condition number estimation for *  sparse matrices.  SIAM Journal on Scientific and Statistical *  Computing.  Vol. 2, No. 4, pages 384-388, December 1981. *   *  Dianne Prost O'Leary.  Estimating matrix condition numbers.  SIAM *  Journal on Scientific and Statistical Computing.  Vol. 1, No. 2, *  pages 205-209, June 1980. * *  >>> Returns: *  The reciprocal of the condition number.  If the matrix was singular, *  zero is returned. * *  >>> Arguments: *  eMatrix  <input>  (char *) *      Pointer to the matrix. *  NormOfMatrix  <input>  (RealNumber) *      The L-infinity norm of the unfactored matrix as computed by *      spNorm(). *  pError  <output>  (int *) *      Used to return error code. * *  >>> Possible errors: *  spSINGULAR *  spNO_MEMORY */RealNumberspCondition( eMatrix, NormOfMatrix, pError )char *eMatrix;RealNumber NormOfMatrix;int *pError;{    MatrixPtr  Matrix = (MatrixPtr)eMatrix;    ElementPtr pElement;    RealVector T, Tm;    int I, K, Row;    ElementPtr pPivot;    int Size;    RealNumber E, Em, Wp, Wm, ASp, ASm, ASw, ASy, ASv, ASz, MaxY, ScaleFactor;    RealNumber Linpack, OLeary, InvNormOfInverse, ComplexCondition();#define SLACK   1e4    /* Begin `spCondition'. */    assert( IS_SPARSE(Matrix) && IS_FACTORED(Matrix) );    *pError = Matrix->Error;    if (Matrix->Error >= spFATAL) return 0.0;    if (NormOfMatrix == 0.0)    {	*pError = spSINGULAR;        return 0.0;    }    if (Matrix->Complex)        return ComplexCondition( Matrix, NormOfMatrix, pError );    Size = Matrix->Size;    T = Matrix->Intermediate;    Tm = Matrix->Intermediate + Size;    for (I = Size; I > 0; I--) T[I] = 0.0;    /*     * Part 1.  Ay = e.     *     * Solve Ay = LUy = e where e consists of +1 and -1 terms with the     * sign chosen to maximize the size of w in Lw = e.  Since the     * terms in w can get very large, scaling is used to avoid     * overflow.  */    /* Forward elimination. Solves Lw = e while choosing e. */    E = 1.0;    for (I = 1; I <= Size; I++)    {	pPivot = Matrix->Diag[I];        if (T[I] < 0.0) Em = -E; else Em = E;        Wm = (Em + T[I]) * pPivot->Real;        if (ABS(Wm) > SLACK)        {	    ScaleFactor = 1.0 / MAX( SQR( SLACK ), ABS(Wm) );            for (K = Size; K > 0; K--) T[K] *= ScaleFactor;            E *= ScaleFactor;            Em *= ScaleFactor;            Wm = (Em + T[I]) * pPivot->Real;        }        Wp = (T[I] - Em) * pPivot->Real;        ASp = ABS(T[I] - Em);        ASm = ABS(Em + T[I]);	/* Update T for both values of W, minus value is placed in           Tm. */        pElement = pPivot->NextInCol;        while (pElement != NULL)        {	    Row = pElement->Row;            Tm[Row] = T[Row] - (Wm * pElement->Real);            T[Row] -= (Wp * pElement->Real);            ASp += ABS(T[Row]);            ASm += ABS(Tm[Row]);            pElement = pElement->NextInCol;        }	/* If minus value causes more growth, overwrite T with its           values. */        if (ASm > ASp)        {	    T[I] = Wm;            pElement = pPivot->NextInCol;            while (pElement != NULL)            {		T[pElement->Row] = Tm[pElement->Row];                pElement = pElement->NextInCol;            }        }        else T[I] = Wp;    }    /* Compute 1-norm of T, which now contains w, and scale ||T|| to       1/SLACK. */    for (ASw = 0.0, I = Size; I > 0; I--) ASw += ABS(T[I]);    ScaleFactor = 1.0 / (SLACK * ASw);    if (ScaleFactor < 0.5)    {	for (I = Size; I > 0; I--) T[I] *= ScaleFactor;        E *= ScaleFactor;    }    /* Backward Substitution. Solves Uy = w.*/    for (I = Size; I >= 1; I--)    {	pElement = Matrix->Diag[I]->NextInRow;        while (pElement != NULL)        {	    T[I] -= pElement->Real * T[pElement->Col];            pElement = pElement->NextInRow;        }        if (ABS(T[I]) > SLACK)        {	    ScaleFactor = 1.0 / MAX( SQR( SLACK ), ABS(T[I]) );            for (K = Size; K > 0; K--) T[K] *= ScaleFactor;            E *= ScaleFactor;        }    }    /* Compute 1-norm of T, which now contains y, and scale ||T|| to       1/SLACK. */    for (ASy = 0.0, I = Size; I > 0; I--) ASy += ABS(T[I]);    ScaleFactor = 1.0 / (SLACK * ASy);    if (ScaleFactor < 0.5)    {	for (I = Size; I > 0; I--) T[I] *= ScaleFactor;        ASy = 1.0 / SLACK;        E *= ScaleFactor;    }    /* Compute infinity-norm of T for O'Leary's estimate. */    for (MaxY = 0.0, I = Size; I > 0; I--)        if (MaxY < ABS(T[I])) MaxY = ABS(T[I]);    /*     * Part 2.     *     * A* z = y where the * represents the transpose.  Recall that A =     * LU implies A* = U* L*.  */    /* Forward elimination, U* v = y. */    for (I = 1; I <= Size; I++)    {	pElement = Matrix->Diag[I]->NextInRow;        while (pElement != NULL)        {	    T[pElement->Col] -= T[I] * pElement->Real;            pElement = pElement->NextInRow;        }        if (ABS(T[I]) > SLACK)        {	    ScaleFactor = 1.0 / MAX( SQR( SLACK ), ABS(T[I]) );            for (K = Size; K > 0; K--) T[K] *= ScaleFactor;            ASy *= ScaleFactor;        }    }    /* Compute 1-norm of T, which now contains v, and scale ||T|| to 1/SLACK. */    for (ASv = 0.0, I = Size; I > 0; I--) ASv += ABS(T[I]);    ScaleFactor = 1.0 / (SLACK * ASv);    if (ScaleFactor < 0.5)    {	for (I = Size; I > 0; I--) T[I] *= ScaleFactor;        ASy *= ScaleFactor;    }    /* Backward Substitution, L* z = v. */    for (I = Size; I >= 1; I--)    {	pPivot = Matrix->Diag[I];        pElement = pPivot->NextInCol;        while (pElement != NULL)        {	    T[I] -= pElement->Real * T[pElement->Row];            pElement = pElement->NextInCol;        }        T[I] *= pPivot->Real;        if (ABS(T[I]) > SLACK)        {	    ScaleFactor = 1.0 / MAX( SQR( SLACK ), ABS(T[I]) );            for (K = Size; K > 0; K--) T[K] *= ScaleFactor;            ASy *= ScaleFactor;        }    }    /* Compute 1-norm of T, which now contains z. */    for (ASz = 0.0, I = Size; I > 0; I--) ASz += ABS(T[I]);    Linpack = ASy / ASz;    OLeary = E / MaxY;    InvNormOfInverse = MIN( Linpack, OLeary );    return InvNormOfInverse / NormOfMatrix;}/* *  ESTIMATE CONDITION NUMBER * *  Complex version of spCondition(). * *  >>> Returns: *  The reciprocal of the condition number. * *  >>> Arguments: *  Matrix  <input>  (MatrixPtr) *      Pointer to the matrix. *  NormOfMatrix  <input>  (RealNumber) *      The L-infinity norm of the unfactored matrix as computed by *      spNorm(). *  pError  <output>  (int *) *      Used to return error code. * *  >>> Possible errors: *  spNO_MEMORY */static RealNumberComplexCondition( Matrix, NormOfMatrix, pError )MatrixPtr Matrix;RealNumber NormOfMatrix;int *pError;{    ElementPtr pElement;    ComplexVector T, Tm;    int I, K, Row;    ElementPtr pPivot;    int Size;    RealNumber E, Em, ASp, ASm, ASw, ASy, ASv, ASz, MaxY, ScaleFactor;    RealNumber Linpack, OLeary, InvNormOfInverse;    ComplexNumber Wp, Wm;    /* Begin `ComplexCondition'. */    Size = Matrix->Size;    T = (ComplexVector)Matrix->Intermediate;    Tm = ALLOC( ComplexNumber, Size+1 );    if (Tm == NULL)    {	*pError = spNO_MEMORY;        return 0.0;    }    for (I = Size; I > 0; I--) T[I].Real = T[I].Imag = 0.0;    /*     * Part 1.  Ay = e.     *     * Solve Ay = LUy = e where e consists of +1 and -1 terms with the     * sign chosen to maximize the size of w in Lw = e.  Since the     * terms in w can get very large, scaling is used to avoid     * overflow.  */    /* Forward elimination. Solves Lw = e while choosing e. */    E = 1.0;    for (I = 1; I <= Size; I++)    {	pPivot = Matrix->Diag[I];        if (T[I].Real < 0.0) Em = -E; else Em = E;        Wm = T[I];        Wm.Real += Em;        ASm = CMPLX_1_NORM( Wm );        CMPLX_MULT_ASSIGN( Wm, *pPivot );        if (CMPLX_1_NORM(Wm) > SLACK)        {	    ScaleFactor = 1.0 / MAX( SQR( SLACK ), CMPLX_1_NORM(Wm) );            for (K = Size; K > 0; K--) SCLR_MULT_ASSIGN( T[K], ScaleFactor );            E *= ScaleFactor;            Em *= ScaleFactor;            ASm *= ScaleFactor;            SCLR_MULT_ASSIGN( Wm, ScaleFactor );        }        Wp = T[I];        Wp.Real -= Em;        ASp = CMPLX_1_NORM( Wp );        CMPLX_MULT_ASSIGN( Wp, *pPivot );	/* Update T for both values of W, minus value is placed in Tm. */        pElement = pPivot->NextInCol;        while (pElement != NULL)        {	    Row = pElement->Row;            /* Cmplx expr: Tm[Row] = T[Row] - (Wp * *pElement). */            CMPLX_MULT_SUBT( Tm[Row], Wm, *pElement, T[Row] );            /* Cmplx expr: T[Row] -= Wp * *pElement. */            CMPLX_MULT_SUBT_ASSIGN( T[Row], Wm, *pElement );            ASp += CMPLX_1_NORM(T[Row]);            ASm += CMPLX_1_NORM(Tm[Row]);            pElement = pElement->NextInCol;        }	/* If minus value causes more growth, overwrite T with its           values. */        if (ASm > ASp)        {	    T[I] = Wm;            pElement = pPivot->NextInCol;            while (pElement != NULL)            {		T[pElement->Row] = Tm[pElement->Row];                pElement = pElement->NextInCol;            }        }        else T[I] = Wp;    }    /* Compute 1-norm of T, which now contains w, and scale ||T|| to       1/SLACK. */    for (ASw = 0.0, I = Size; I > 0; I--) ASw += CMPLX_1_NORM(T[I]);    ScaleFactor = 1.0 / (SLACK * ASw);    if (ScaleFactor < 0.5)    {	for (I = Size; I > 0; I--) SCLR_MULT_ASSIGN( T[I], ScaleFactor );        E *= ScaleFactor;    }

⌨️ 快捷键说明

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