📄 sputils.c
字号:
#if spCOMPLEX
if (Matrix->Complex)
{ ScaleComplexMatrix( Matrix, RHS_ScaleFactors, SolutionScaleFactors );
return;
}
#endif
#if REAL
lSize = Matrix->Size;
/* Correct pointers to arrays for ARRAY_OFFSET */
#if NOT ARRAY_OFFSET
--RHS_ScaleFactors;
--SolutionScaleFactors;
#endif
/* Scale Rows */
pExtOrder = &Matrix->IntToExtRowMap[1];
for (I = 1; I <= lSize; I++)
{ if ((ScaleFactor = RHS_ScaleFactors[*(pExtOrder++)]) != 1.0)
{ pElement = Matrix->FirstInRow[I];
while (pElement != NULL)
{ pElement->Real *= ScaleFactor;
pElement = pElement->NextInRow;
}
}
}
/* Scale Columns */
pExtOrder = &Matrix->IntToExtColMap[1];
for (I = 1; I <= lSize; I++)
{ if ((ScaleFactor = SolutionScaleFactors[*(pExtOrder++)]) != 1.0)
{ pElement = Matrix->FirstInCol[I];
while (pElement != NULL)
{ pElement->Real *= ScaleFactor;
pElement = pElement->NextInCol;
}
}
}
return;
#endif /* REAL */
}
#endif /* SCALING */
#if spCOMPLEX AND SCALING
/*
* SCALE COMPLEX MATRIX
*
* This function scales the matrix to enhance the possibility of
* finding a good pivoting order. Note that scaling enhances accuracy
* of the solution only if it affects the pivoting order, so it makes
* no sense to scale the matrix before spFactor(). If scaling is
* desired it should be done before spOrderAndFactor(). There
* are several things to take into account when choosing the scale
* factors. First, the scale factors are directly multiplied against
* the elements in the matrix. To prevent roundoff, each scale factor
* should be equal to an integer power of the number base of the
* machine. Since most machines operate in base two, scale factors
* should be a power of two. Second, the matrix should be scaled such
* that the matrix of element uncertainties is equilibrated. Third,
* this function multiplies the scale factors by the elements, so if
* one row tends to have uncertainties 1000 times smaller than the
* other rows, then its scale factor should be 1024, not 1/1024.
* Fourth, to save time, this function does not scale rows or columns
* if their scale factors are equal to one. Thus, the scale factors
* should be normalized to the most common scale factor. Rows and
* columns should be normalized separately. For example, if the size
* of the matrix is 100 and 10 rows tend to have uncertainties near
* 1e-6 and the remaining 90 have uncertainties near 1e-12, then the
* scale factor for the 10 should be 1/1,048,576 and the scale factors
* for the remaining 90 should be 1. Fifth, since this routine
* directly operates on the matrix, it is necessary to apply the scale
* factors to the RHS and Solution vectors. It may be easier to
* simply use spOrderAndFactor() on a scaled matrix to choose the
* pivoting order, and then throw away the matrix. Subsequent
* factorizations, performed with spFactor(), will not need to have
* the RHS and Solution vectors descaled. Lastly, this function
* should not be executed before the function spMNA_Preorder.
*
* >>> Arguments:
* Matrix <input> (char *)
* Pointer to the matrix to be scaled.
* SolutionScaleFactors <input> (RealVector)
* The array of Solution scale factors. These factors scale the columns.
* All scale factors are real valued.
* RHS_ScaleFactors <input> (RealVector)
* The array of RHS scale factors. These factors scale the rows.
* All scale factors are real valued.
*
* >>> Local variables:
* lSize (int)
* Local version of the size of the matrix.
* pElement (ElementPtr)
* Pointer to an element in the matrix.
* pExtOrder (int *)
* Pointer into either IntToExtRowMap or IntToExtColMap vector. Used to
* compensate for any row or column swaps that have been performed.
* ScaleFactor (RealNumber)
* The scale factor being used on the current row or column.
*/
static void
ScaleComplexMatrix(
MatrixPtr Matrix,
register RealVector RHS_ScaleFactors,
register RealVector SolutionScaleFactors
)
{
register ElementPtr pElement;
register int I, lSize, *pExtOrder;
RealNumber ScaleFactor;
/* Begin `ScaleComplexMatrix'. */
lSize = Matrix->Size;
/* Correct pointers to arrays for ARRAY_OFFSET */
#if NOT ARRAY_OFFSET
--RHS_ScaleFactors;
--SolutionScaleFactors;
#endif
/* Scale Rows */
pExtOrder = &Matrix->IntToExtRowMap[1];
for (I = 1; I <= lSize; I++)
{ if ((ScaleFactor = RHS_ScaleFactors[*(pExtOrder++)]) != 1.0)
{ pElement = Matrix->FirstInRow[I];
while (pElement != NULL)
{ pElement->Real *= ScaleFactor;
pElement->Imag *= ScaleFactor;
pElement = pElement->NextInRow;
}
}
}
/* Scale Columns */
pExtOrder = &Matrix->IntToExtColMap[1];
for (I = 1; I <= lSize; I++)
{ if ((ScaleFactor = SolutionScaleFactors[*(pExtOrder++)]) != 1.0)
{ pElement = Matrix->FirstInCol[I];
while (pElement != NULL)
{ pElement->Real *= ScaleFactor;
pElement->Imag *= ScaleFactor;
pElement = pElement->NextInCol;
}
}
}
return;
}
#endif /* SCALING AND spCOMPLEX */
#if MULTIPLICATION
/*!
* Multiplies matrix by solution vector to find source vector.
* Assumes matrix has not been factored. This routine can be used
* as a test to see if solutions are correct. It should not be used
* before spMNA_Preorder().
*
* \param eMatrix
* Pointer to the matrix.
* \param RHS
* RHS is the right hand side. This is what is being solved for.
* \param Solution
* Solution is the vector being multiplied by the matrix.
* \param iRHS
* iRHS is the imaginary portion of the right hand side. This is
* what is being solved for. This is only necessary if the matrix is
* complex and \a spSEPARATED_COMPLEX_VECTORS is true.
* \param iSolution
* iSolution is the imaginary portion of the vector being multiplied
* by the matrix. This is only necessary if the matrix is
* complex and \a spSEPARATED_COMPLEX_VECTORS is true.
*/
void
spMultiply(
spMatrix eMatrix,
spREAL RHS[],
spREAL Solution[]
#if spCOMPLEX AND spSEPARATED_COMPLEX_VECTORS
, spREAL iRHS[]
, spREAL iSolution[]
#endif
)
{
register ElementPtr pElement;
register RealVector Vector;
register RealNumber Sum;
register int I, *pExtOrder;
MatrixPtr Matrix = (MatrixPtr)eMatrix;
extern void ComplexMatrixMultiply();
/* Begin `spMultiply'. */
ASSERT_IS_SPARSE( Matrix );
ASSERT_IS_NOT_FACTORED( Matrix );
if (NOT Matrix->RowsLinked)
spcLinkRows(Matrix);
if (NOT Matrix->InternalVectorsAllocated)
spcCreateInternalVectors( Matrix );
#if spCOMPLEX
if (Matrix->Complex)
{ ComplexMatrixMultiply( Matrix, RHS, Solution IMAG_VECTORS );
return;
}
#endif
#if REAL
#if NOT ARRAY_OFFSET
/* Correct array pointers for ARRAY_OFFSET. */
--RHS;
--Solution;
#endif
/* Initialize Intermediate vector with reordered Solution vector. */
Vector = Matrix->Intermediate;
pExtOrder = &Matrix->IntToExtColMap[Matrix->Size];
for (I = Matrix->Size; I > 0; I--)
Vector[I] = Solution[*(pExtOrder--)];
pExtOrder = &Matrix->IntToExtRowMap[Matrix->Size];
for (I = Matrix->Size; I > 0; I--)
{ pElement = Matrix->FirstInRow[I];
Sum = 0.0;
while (pElement != NULL)
{ Sum += pElement->Real * Vector[pElement->Col];
pElement = pElement->NextInRow;
}
RHS[*pExtOrder--] = Sum;
}
return;
#endif /* REAL */
}
#endif /* MULTIPLICATION */
#if spCOMPLEX AND MULTIPLICATION
/*
* COMPLEX MATRIX MULTIPLICATION
*
* Multiplies matrix by solution vector to find source vector.
* Assumes matrix has not been factored. This routine can be used
* as a test to see if solutions are correct.
*
* >>> Arguments:
* Matrix <input> (char *)
* Pointer to the matrix.
* RHS <output> (RealVector)
* RHS is the right hand side. This is what is being solved for.
* This is only the real portion of the right-hand side if the matrix
* is complex and spSEPARATED_COMPLEX_VECTORS is set true.
* Solution <input> (RealVector)
* Solution is the vector being multiplied by the matrix. This is only
* the real portion if the matrix is complex and
* spSEPARATED_COMPLEX_VECTORS is set true.
* iRHS <output> (RealVector)
* iRHS is the imaginary portion of the right hand side. This is
* what is being solved for. This is only necessary if the matrix is
* complex and spSEPARATED_COMPLEX_VECTORS is true.
* iSolution <input> (RealVector)
* iSolution is the imaginary portion of the vector being multiplied
* by the matrix. This is only necessary if the matrix is
* complex and spSEPARATED_COMPLEX_VECTORS is true.
*/
static void
ComplexMatrixMultiply(
MatrixPtr Matrix,
RealVector RHS,
RealVector Solution
#if spSEPARATED_COMPLEX_VECTORS
, RealVector iRHS
, RealVector iSolution
#endif
)
{
register ElementPtr pElement;
register ComplexVector Vector;
ComplexNumber Sum;
register int I, *pExtOrder;
/* Begin `ComplexMatrixMultiply'. */
/* Correct array pointers for ARRAY_OFFSET. */
#if NOT ARRAY_OFFSET
#if spSEPARATED_COMPLEX_VECTORS
--RHS; --iRHS;
--Solution; --iSolution;
#else
RHS -= 2; Solution -= 2;
#endif
#endif
/* Initialize Intermediate vector with reordered Solution vector. */
Vector = (ComplexVector)Matrix->Intermediate;
pExtOrder = &Matrix->IntToExtColMap[Matrix->Size];
#if spSEPARATED_COMPLEX_VECTORS
for (I = Matrix->Size; I > 0; I--)
{ Vector[I].Real = Solution[*pExtOrder];
Vector[I].Imag = iSolution[*(pExtOrder--)];
}
#else
for (I = Matrix->Size; I > 0; I--)
Vector[I] = ((ComplexVector)Solution)[*(pExtOrder--)];
#endif
pExtOrder = &Matrix->IntToExtRowMap[Matrix->Size];
for (I = Matrix->Size; I > 0; I--)
{ pElement = Matrix->FirstInRow[I];
Sum.Real = Sum.Imag = 0.0;
while (pElement != NULL)
{ /* Cmplx expression : Sum += Element * Vector[Col] */
CMPLX_MULT_ADD_ASSIGN( Sum, *pElement, Vector[pElement->Col] );
pElement = pElement->NextInRow;
}
#if spSEPARATED_COMPLEX_VECTORS
RHS[*pExtOrder] = Sum.Real;
iRHS[*pExtOrder--] = Sum.Imag;
#else
((ComplexVector)RHS)[*pExtOrder--] = Sum;
#endif
}
return;
}
#endif /* spCOMPLEX AND MULTIPLICATION */
#if MULTIPLICATION AND TRANSPOSE
/*!
* Multiplies transposed matrix by solution vector to find source vector.
* Assumes matrix has not been factored. This routine can be used
* as a test to see if solutions are correct. It should not be used
* before spMNA_Preorder().
*
* \param eMatrix
* Pointer to the matrix.
* \param RHS
* RHS is the right hand side. This is what is being solved for.
* \param Solution
* Solution is the vector being multiplied by the matrix.
* \param iRHS
* iRHS is the imaginary portion of the right hand side. This is
* what is being solved for. This is only necessary if the matrix is
* complex and \a spSEPARATED_COMPLEX_VECTORS is true.
* \param iSolution
* iSolution is the imaginary portion of the vector being multiplied
* by the matrix. This is only necessary if the matrix is
* complex and \a spSEPARATED_COMPLEX_VECTORS is true.
*/
void
spMultTransposed(
spMatrix eMatrix,
spREAL RHS[],
spREAL Solution[]
#if spCOMPLEX AND spSEPARATED_COMPLEX_VECTORS
, spREAL iRHS[]
, spREAL iSolution[]
#endif
)
{
register ElementPtr pElement;
register RealVector Vector;
register RealNumber Sum;
register int I, *pExtOrder;
MatrixPtr Matrix = (MatrixPtr)eMatrix;
extern void ComplexTransposedMatrixMultiply();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -