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

📄 spfactor.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
📖 第 1 页 / 共 5 页
字号:
                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. */            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);}/* *  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;{     ElementPtr  pElement;     ElementPtr  pColumn;     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. */             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. */             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);}/* *  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(void *eMatrix, int Mode){    MatrixPtr  Matrix = (MatrixPtr)eMatrix;    ElementPtr  pElement, pColumn;    int  Step, Size;    int  *Nc, *No, *Nm;    int *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++) {            DoRealDirect[Step] = YES;	    DoCmplxDirect[Step] = YES;	}        return;    }    else if (Mode == spINDIRECT_PARTITION)    {	for (Step = 1; Step <= Size; Step++)	{            DoRealDirect[Step] = NO;	    DoCmplxDirect[Step] = NO;	}        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        DoRealDirect[Step] = (Nm[Step] + No[Step] > 3*Nc[Step] - 2*Nm[Step]);        /* On the hp350, it is never profitable to use direct for complex. */        DoCmplxDirect[Step] = NO;#undef generic#endif#ifdef vax        DoRealDirect[Step] = (Nm[Step] + No[Step] > 3*Nc[Step] - 2*Nm[Step]);        DoCmplxDirect[Step] = (Nm[Step] + No[Step] > 7*Nc[Step] - 4*Nm[Step]);#undef generic#endif#ifdef generic        DoRealDirect[Step] = (Nm[Step] + No[Step] > 3*Nc[Step] - 2*Nm[Step]);        DoCmplxDirect[Step] = (Nm[Step] + No[Step] > 7*Nc[Step] - 4*Nm[Step]);#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) *      Pointer to matrix. * *  >>> Local variables: *  SizePlusOne  (unsigned) *      Size of the arrays to be allocated. * *  >>> Possible errors: *  spNO_MEMORY */voidspcCreateInternalVectors( Matrix )MatrixPtr  Matrix;{    int  Size;    /* Begin `spcCreateInternalVectors'. */    /* Create Markowitz arrays. */    Size= Matrix->Size;    if (Matrix->MarkowitzRow == NULL)    {	if (( Matrix->MarkowitzRow = ALLOC(int, Size+1)) == NULL)	    Matrix->Error = spNO_MEMORY;    }    if (Matrix->MarkowitzCol == NULL)    {	if (( Matrix->MarkowitzCol = ALLOC(int, Size+1)) == NULL)	    Matrix->Error = spNO_MEMORY;    }    if (Matrix->MarkowitzProd == NULL)    {	if (( Matrix->MarkowitzProd = ALLOC(long, Size+2)) == NULL)	    Matrix->Error = spNO_MEMORY;    }    /* Create DoDirect vectors for use in spFactor(). */    if (Matrix->DoRealDirect == NULL) {	if (( Matrix->DoRealDirect = ALLOC(int, Size+1)) == NULL)	    Matrix->Error = spNO_MEMORY;    }    if (Matrix->DoCmplxDirect == NULL) {	if (( Matrix->DoCmplxDirect = ALLOC(int, Size+1)) == NULL)	    Matrix->Error = spNO_MEMORY;    }    /* Create Intermediate vectors for use in MatrixSolve. */    if (Matrix->Intermediate == NULL) {	if ((Matrix->Intermediate = ALLOC(RealNumber,2*(Size+1))) == NULL)

⌨️ 快捷键说明

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