📄 sputils.c
字号:
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]);#if NOT spCOMPLEX FREE( Tm );#endif Linpack = ASy / ASz; OLeary = E / MaxY; InvNormOfInverse = MIN( Linpack, OLeary ); return InvNormOfInverse / NormOfMatrix;#endif /* REAL */}#if spCOMPLEX/* * 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;{register ElementPtr pElement;register ComplexVector T, Tm;register 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; }/* Backward Substitution. Solves Uy = w.*/ for (I = Size; I >= 1; I--) { pElement = Matrix->Diag[I]->NextInRow; while (pElement != NULL) { /* Cmplx expr: T[I] -= T[pElement->Col] * *pElement. */ CMPLX_MULT_SUBT_ASSIGN( T[I], T[pElement->Col], *pElement ); pElement = pElement->NextInRow; } if (CMPLX_1_NORM(T[I]) > SLACK) { ScaleFactor = 1.0 / MAX( SQR( SLACK ), CMPLX_1_NORM(T[I]) ); for (K = Size; K > 0; K--) SCLR_MULT_ASSIGN( 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 += CMPLX_1_NORM(T[I]); ScaleFactor = 1.0 / (SLACK * ASy); if (ScaleFactor < 0.5) { for (I = Size; I > 0; I--) SCLR_MULT_ASSIGN( 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 < CMPLX_1_NORM(T[I])) MaxY = CMPLX_1_NORM(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) { /* Cmplx expr: T[pElement->Col] -= T[I] * *pElement. */ CMPLX_MULT_SUBT_ASSIGN( T[pElement->Col], T[I], *pElement ); pElement = pElement->NextInRow; } if (CMPLX_1_NORM(T[I]) > SLACK) { ScaleFactor = 1.0 / MAX( SQR( SLACK ), CMPLX_1_NORM(T[I]) ); for (K = Size; K > 0; K--) SCLR_MULT_ASSIGN( 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 += CMPLX_1_NORM(T[I]); ScaleFactor = 1.0 / (SLACK * ASv); if (ScaleFactor < 0.5) { for (I = Size; I > 0; I--) SCLR_MULT_ASSIGN( 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) { /* Cmplx expr: T[I] -= T[pElement->Row] * *pElement. */ CMPLX_MULT_SUBT_ASSIGN( T[I], T[pElement->Row], *pElement ); pElement = pElement->NextInCol; } CMPLX_MULT_ASSIGN( T[I], *pPivot ); if (CMPLX_1_NORM(T[I]) > SLACK) { ScaleFactor = 1.0 / MAX( SQR( SLACK ), CMPLX_1_NORM(T[I]) ); for (K = Size; K > 0; K--) SCLR_MULT_ASSIGN( T[K], ScaleFactor ); ASy *= ScaleFactor; } }/* Compute 1-norm of T, which now contains z. */ for (ASz = 0.0, I = Size; I > 0; I--) ASz += CMPLX_1_NORM(T[I]); FREE( Tm ); Linpack = ASy / ASz; OLeary = E / MaxY; InvNormOfInverse = MIN( Linpack, OLeary ); return InvNormOfInverse / NormOfMatrix;}#endif /* spCOMPLEX *//* * L-INFINITY MATRIX NORM * * Computes the L-infinity norm of an unfactored matrix. It is a fatal * error to pass this routine a factored matrix. * * One difficulty is that the rows may not be linked. * * >>> Returns: * The largest absolute row sum of matrix. * * >>> Arguments: * eMatrix <input> (char *) * Pointer to the matrix. */RealNumberspNorm( eMatrix )char *eMatrix;{MatrixPtr Matrix = (MatrixPtr)eMatrix;register ElementPtr pElement;register int I;RealNumber Max = 0.0, AbsRowSum;/* Begin `spNorm'. */ ASSERT( IS_SPARSE(Matrix) AND NOT IS_FACTORED(Matrix) ); if (NOT Matrix->RowsLinked) spcLinkRows( Matrix );/* Compute row sums. */#if REAL if (NOT Matrix->Complex) { for (I = Matrix->Size; I > 0; I--) { pElement = Matrix->FirstInRow[I]; AbsRowSum = 0.0; while (pElement != NULL) { AbsRowSum += ABS( pElement->Real ); pElement = pElement->NextInRow; } if (Max < AbsRowSum) Max = AbsRowSum; } }#endif#if spCOMPLEX if (Matrix->Complex) { for (I = Matrix->Size; I > 0; I--) { pElement = Matrix->FirstInRow[I]; AbsRowSum = 0.0; while (pElement != NULL) { AbsRowSum += CMPLX_1_NORM( *pElement ); pElement = pElement->NextInRow; } if (Max < AbsRowSum) Max = AbsRowSum; } }#endif return Max;}#endif /* CONDITION */#if STABILITY/* * STABILITY OF FACTORIZATION * * The following routines are used to gauge the stability of a * factorization. If the factorization is determined to be too unstable, * then the matrix should be reordered. The routines compute quantities * that are needed in the computation of a bound on the error attributed * to any one element in the matrix during the factorization. In other * words, there is a matrix E = [e_ij] of error terms such that A+E = LU. * This routine finds a bound on |e_ij|. Erisman & Reid [1] showed that * |e_ij| < 3.01 u rho m_ij, where u is the machine rounding unit, * rho = max a_ij where the max is taken over every row i, column j, and * step k, and m_ij is the number of multiplications required in the * computation of l_ij if i > j or u_ij otherwise. Barlow [2] showed that * rho < max_i || l_i ||_p max_j || u_j ||_q where 1/p + 1/q = 1. * * The first routine finds the magnitude on the largest element in the * matrix. If the matrix has not yet been factored, the largest * element is found by direct search. If the matrix is factored, a * bound on the largest element in any of the reduced submatrices is * computed using Barlow with p = oo and q = 1. The ratio of these * two numbers is the growth, which can be used to determine if the * pivoting order is adequate. A large growth implies that * considerable error has been made in the factorization and that it * is probably a good idea to reorder the matrix. If a large growth * in encountered after using spFactor(), reconstruct the matrix and * refactor using spOrderAndFactor(). If a large growth is * encountered after using spOrderAndFactor(), refactor using * spOrderAndFactor() with the pivot threshold increased, say to 0.1. * * Using only the size of the matrix as an upper bound on m_ij and * Barlow's bound, the user can estimate the size of the matrix error * terms e_ij using the bound of Erisman and Reid. The second routine * computes a tighter bound (with more work) based on work by Gear * [3], |e_ij| < 1.01 u rho (t c^3 + (1 + t)c^2) where t is the * threshold and c is the maximum number of off-diagonal elements in * any row of L. The expensive part of computing this bound is * determining the maximum number of off-diagonals in L, which changes * only when the order of the matrix changes. This number is computed * and saved, and only recomputed if the matrix is reordered. * * [1] A. M. Erisman, J. K. Reid. Monitoring the stability of the * triangular factorization of a sparse matrix. Numerische * Mathematik. Vol. 22, No. 3, 1974, pp 183-186. * * [2] J. L. Barlow. A note on monitoring the stability of triangular * decomposition of sparse matrices. "SIAM Journal of Scientific * and Statistical Computing." Vol. 7, No. 1, January 1986, pp 166-168. * * [3] I. S. Duff, A. M. Erisman, J. K. Reid. "Direct Methods for Sparse * Matrices." Oxford 1986. pp 99. *//* * LARGEST ELEMENT IN MATRIX * * >>> Returns: * If matrix is not factored, returns the magnitude of the largest element in * the matrix. If the matrix is factored, a bound on the magnitude of the * largest element in any of the reduced submatrices is returned. * * >>> Arguments:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -