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

📄 spfactor.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 5 页
字号:
                                 0.0, 0.0, DIAG_PIVOTING_AS_DEFAULT );    }    if (NOT Matrix->Partitioned) spPartition( eMatrix, spDEFAULT_PARTITION );#if spCOMPLEX    if (Matrix->Complex) return FactorComplexMatrix( Matrix );#endif#if REAL    Size = Matrix->Size;    if (Matrix->Diag[1]->Real == 0.0) return ZeroPivot( Matrix, 1 );    Matrix->Diag[1]->Real = 1.0 / Matrix->Diag[1]->Real;/* Start factorization. */    for (Step = 2; Step <= Size; Step++)    {   if (Matrix->DoRealDirect[Step])        {   /* Update column using direct addressing scatter-gather. */            register RealNumber *Dest = (RealNumber *)Matrix->Intermediate;/* Scatter. */            pElement = Matrix->FirstInCol[Step];            while (pElement != NULL)            {   Dest[pElement->Row] = pElement->Real;                pElement = pElement->NextInCol;            }/* Update column. */            pColumn = Matrix->FirstInCol[Step];            while (pColumn->Row < Step)            {   pElement = Matrix->Diag[pColumn->Row];                pColumn->Real = Dest[pColumn->Row] * pElement->Real;                while ((pElement = pElement->NextInCol) != NULL)                    Dest[pElement->Row] -= pColumn->Real * pElement->Real;                pColumn = pColumn->NextInCol;            }/* Gather. */            pElement = Matrix->Diag[Step]->NextInCol;            while (pElement != NULL)            {   pElement->Real = Dest[pElement->Row];                pElement = pElement->NextInCol;            }/* Check for singular matrix. */            if (Dest[Step] == 0.0) return ZeroPivot( Matrix, Step );            Matrix->Diag[Step]->Real = 1.0 / Dest[Step];        }        else        {   /* Update column using indirect addressing scatter-gather. */            register RealNumber **pDest = (RealNumber **)Matrix->Intermediate;/* Scatter. */            pElement = Matrix->FirstInCol[Step];            while (pElement != NULL)            {   pDest[pElement->Row] = &pElement->Real;                pElement = pElement->NextInCol;            }/* Update column. */            pColumn = Matrix->FirstInCol[Step];            while (pColumn->Row < Step)            {   pElement = Matrix->Diag[pColumn->Row];                Mult = (*pDest[pColumn->Row] *= pElement->Real);                while ((pElement = pElement->NextInCol) != NULL)                    *pDest[pElement->Row] -= Mult * pElement->Real;                pColumn = pColumn->NextInCol;            }/* Check for singular matrix. */            if (Matrix->Diag[Step]->Real == 0.0)                return ZeroPivot( Matrix, Step );            Matrix->Diag[Step]->Real = 1.0 / Matrix->Diag[Step]->Real;        }    }    Matrix->Factored = YES;    return (Matrix->Error = spOKAY);#endif /* REAL */}#if spCOMPLEX/* *  FACTOR COMPLEX MATRIX * *  This routine is the companion routine to spFactor(), it *  handles complex matrices.  It is otherwise identical. * *  >>> Returned: *  The error code is returned.  Possible errors are listed below. * *  >>> Arguments: *  Matrix  <input>  (char *) *      Pointer to matrix. * *  >>> Possible errors: *  spSINGULAR *  Error is cleared in this function. */static intFactorComplexMatrix( Matrix )MatrixPtr  Matrix;{register  ElementPtr  pElement;register  ElementPtr  pColumn;register  int  Step, Size;ComplexNumber Mult, Pivot;/* Begin `FactorComplexMatrix'. */    ASSERT(Matrix->Complex);    Size = Matrix->Size;    pElement = Matrix->Diag[1];    if (ELEMENT_MAG(pElement) == 0.0) return ZeroPivot( Matrix, 1 );/* Cmplx expr: *pPivot = 1.0 / *pPivot. */    CMPLX_RECIPROCAL( *pElement, *pElement );/* Start factorization. */    for (Step = 2; Step <= Size; Step++)    {   if (Matrix->DoCmplxDirect[Step])        {   /* Update column using direct addressing scatter-gather. */            register  ComplexNumber  *Dest;            Dest = (ComplexNumber *)Matrix->Intermediate;/* Scatter. */            pElement = Matrix->FirstInCol[Step];            while (pElement != NULL)            {   Dest[pElement->Row] = *(ComplexNumber *)pElement;                pElement = pElement->NextInCol;            }/* Update column. */            pColumn = Matrix->FirstInCol[Step];            while (pColumn->Row < Step)            {   pElement = Matrix->Diag[pColumn->Row];                /* Cmplx expr: Mult = Dest[pColumn->Row] * (1.0 / *pPivot). */                CMPLX_MULT(Mult, Dest[pColumn->Row], *pElement);                CMPLX_ASSIGN(*pColumn, Mult);                while ((pElement = pElement->NextInCol) != NULL)                {   /* Cmplx expr: Dest[pElement->Row] -= Mult * pElement */                    CMPLX_MULT_SUBT_ASSIGN(Dest[pElement->Row],Mult,*pElement);                }                pColumn = pColumn->NextInCol;            }/* Gather. */            pElement = Matrix->Diag[Step]->NextInCol;            while (pElement != NULL)            {   *(ComplexNumber *)pElement = Dest[pElement->Row];                pElement = pElement->NextInCol;            }/* Check for singular matrix. */            Pivot = Dest[Step];            if (CMPLX_1_NORM(Pivot) == 0.0) return ZeroPivot( Matrix, Step );            CMPLX_RECIPROCAL( *Matrix->Diag[Step], Pivot );          }        else        {   /* Update column using direct addressing scatter-gather. */            register  ComplexNumber  **pDest;            pDest = (ComplexNumber **)Matrix->Intermediate;/* Scatter. */            pElement = Matrix->FirstInCol[Step];            while (pElement != NULL)            {   pDest[pElement->Row] = (ComplexNumber *)pElement;                pElement = pElement->NextInCol;            }/* Update column. */            pColumn = Matrix->FirstInCol[Step];            while (pColumn->Row < Step)            {   pElement = Matrix->Diag[pColumn->Row];                /* Cmplx expr: Mult = *pDest[pColumn->Row] * (1.0 / *pPivot). */                CMPLX_MULT(Mult, *pDest[pColumn->Row], *pElement);                CMPLX_ASSIGN(*pDest[pColumn->Row], Mult);                while ((pElement = pElement->NextInCol) != NULL)                {  /* Cmplx expr: *pDest[pElement->Row] -= Mult * pElement */                   CMPLX_MULT_SUBT_ASSIGN(*pDest[pElement->Row],Mult,*pElement);                }                pColumn = pColumn->NextInCol;            }/* Check for singular matrix. */            pElement = Matrix->Diag[Step];            if (ELEMENT_MAG(pElement) == 0.0) return ZeroPivot( Matrix, Step );            CMPLX_RECIPROCAL( *pElement, *pElement );          }    }    Matrix->Factored = YES;    return (Matrix->Error = spOKAY);}#endif /* spCOMPLEX *//* *  PARTITION MATRIX * *  This routine determines the cost to factor each row using both *  direct and indirect addressing and decides, on a row-by-row basis, *  which addressing mode is fastest.  This information is used in *  spFactor() to speed the factorization. * *  When factoring a previously ordered matrix using spFactor(), Sparse *  operates on a row-at-a-time basis.  For speed, on each step, the *  row being updated is copied into a full vector and the operations *  are performed on that vector.  This can be done one of two ways, *  either using direct addressing or indirect addressing.  Direct *  addressing is fastest when the matrix is relatively dense and *  indirect addressing is best when the matrix is quite sparse.  The *  user selects the type of partition used with Mode.  If Mode is set *  to spDIRECT_PARTITION, then the all rows are placed in the direct *  addressing partition.  Similarly, if Mode is set to *  spINDIRECT_PARTITION, then the all rows are placed in the indirect *  addressing partition.  By setting Mode to spAUTO_PARTITION, the *  user allows Sparse to select the partition for each row *  individually.  spFactor() generally runs faster if Sparse is *  allowed to choose its own partitioning, however choosing a *  partition is expensive.  The time required to choose a partition is *  of the same order of the cost to factor the matrix.  If you plan to *  factor a large number of matrices with the same structure, it is *  best to let Sparse choose the partition.  Otherwise, you should *  choose the partition based on the predicted density of the matrix. * *  >>> Arguments: *  Matrix  <input>  (char *) *      Pointer to matrix. *  Mode  <input>  (int) *      Mode must be one of three special codes: spDIRECT_PARTITION, *      spINDIRECT_PARTITION, or spAUTO_PARTITION. */voidspPartition( eMatrix, Mode )char *eMatrix;int Mode;{MatrixPtr  Matrix = (MatrixPtr)eMatrix;register  ElementPtr  pElement, pColumn;register  int  Step, Size;register  int  *Nc, *No, *Nm;BOOLEAN *DoRealDirect, *DoCmplxDirect;/* Begin `spPartition'. */    ASSERT( IS_SPARSE( Matrix ) );    if (Matrix->Partitioned) return;    Size = Matrix->Size;    DoRealDirect = Matrix->DoRealDirect;    DoCmplxDirect = Matrix->DoCmplxDirect;    Matrix->Partitioned = YES;/* If partition is specified by the user, this is easy. */    if (Mode == spDEFAULT_PARTITION) Mode = DEFAULT_PARTITION;    if (Mode == spDIRECT_PARTITION)    {   for (Step = 1; Step <= Size; Step++)#if REAL            DoRealDirect[Step] = YES;#endif#if spCOMPLEX            DoCmplxDirect[Step] = YES;#endif        return;    }    else if (Mode == spINDIRECT_PARTITION)    {   for (Step = 1; Step <= Size; Step++)#if REAL            DoRealDirect[Step] = NO;#endif#if spCOMPLEX            DoCmplxDirect[Step] = NO;#endif        return;    }    else ASSERT( Mode == spAUTO_PARTITION );/* Otherwise, count all operations needed in when factoring matrix. */    Nc = (int *)Matrix->MarkowitzRow;    No = (int *)Matrix->MarkowitzCol;    Nm = (int *)Matrix->MarkowitzProd;/* Start mock-factorization. */    for (Step = 1; Step <= Size; Step++)    {   Nc[Step] = No[Step] = Nm[Step] = 0;        pElement = Matrix->FirstInCol[Step];        while (pElement != NULL)        {   Nc[Step]++;            pElement = pElement->NextInCol;        }        pColumn = Matrix->FirstInCol[Step];        while (pColumn->Row < Step)        {   pElement = Matrix->Diag[pColumn->Row];            Nm[Step]++;            while ((pElement = pElement->NextInCol) != NULL)                No[Step]++;            pColumn = pColumn->NextInCol;        }    }    for (Step = 1; Step <= Size; Step++)    {/* * The following are just estimates based on a count on the number of * machine instructions used on each machine to perform the various * tasks.  It was assumed that each machine instruction required the * same amount of time (I don't believe this is true for the VAX, and * have no idea if this is true for the 68000 family).  For optimum * performance, these numbers should be tuned to the machine. *   Nc is the number of nonzero elements in the column. *   Nm is the number of multipliers in the column. *   No is the number of operations in the inner loop. */#define generic#ifdef hp9000s300#if REAL        DoRealDirect[Step] = (Nm[Step] + No[Step] > 3*Nc[Step] - 2*Nm[Step]);#endif#if spCOMPLEX        /* On the hp350, it is never profitable to use direct for complex. */        DoCmplxDirect[Step] = NO;#endif#undef generic#endif#ifdef vax#if REAL        DoRealDirect[Step] = (Nm[Step] + No[Step] > 3*Nc[Step] - 2*Nm[Step]);#endif#if spCOMPLEX        DoCmplxDirect[Step] = (Nm[Step] + No[Step] > 7*Nc[Step] - 4*Nm[Step]);#endif#undef generic#endif#ifdef generic#if REAL        DoRealDirect[Step] = (Nm[Step] + No[Step] > 3*Nc[Step] - 2*Nm[Step]);#endif#if spCOMPLEX        DoCmplxDirect[Step] = (Nm[Step] + No[Step] > 7*Nc[Step] - 4*Nm[Step]);#endif#undef generic#endif    }#if (ANNOTATE == FULL)    {   int Ops = 0;        for (Step = 1; Step <= Size; Step++)            Ops += No[Step];        printf("Operation count for inner loop of factorization = %d.\n", Ops);    }#endif    return;}/* *  CREATE INTERNAL VECTORS * *  Creates the Markowitz and Intermediate vectors. * *  >>> Arguments: *  Matrix  <input>  (MatrixPtr)

⌨️ 快捷键说明

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