2 #include <../../nrnconf.h> 54 "Sparse1.3: Copyright (c) 1985,86,87,88 by Kenneth S. Kundert";
73 #define spINSIDE_SPARSE 189 register int J,
Size;
191 int Twins, StartAt = 1;
192 BOOLEAN Swapped, AnotherPassNeeded;
202 { AnotherPassNeeded = Swapped =
NO;
205 for (J = StartAt; J <=
Size; J++)
207 { Twins =
CountTwins( Matrix, J, &pTwin1, &pTwin2 );
213 else if ((Twins > 1)
AND NOT AnotherPassNeeded)
214 { AnotherPassNeeded =
YES;
221 if (AnotherPassNeeded)
222 {
for (J = StartAt; NOT Swapped
AND (J <= Size); J++)
224 { Twins =
CountTwins( Matrix, J, &pTwin1, &pTwin2 );
230 }
while (AnotherPassNeeded);
258 while (pTwin1 !=
NULL)
259 {
if (
ABS(pTwin1->
Real) == 1.0)
262 while ((pTwin2 !=
NULL)
AND (pTwin2->
Row != Col))
266 if (++Twins >= 2)
return Twins;
267 (*ppTwin1 = pTwin1)->Col = Col;
268 (*ppTwin2 = pTwin2)->Col = Row;
292 int Col1 = pTwin1->
Col, Col2 = pTwin2->
Col;
303 Matrix->
Diag[Col1] = pTwin2;
304 Matrix->
Diag[Col2] = pTwin1;
376 spScale( eMatrix, RHS_ScaleFactors, SolutionScaleFactors )
379 register RealVector RHS_ScaleFactors, SolutionScaleFactors;
398 lSize = Matrix->
Size;
403 --SolutionScaleFactors;
408 for (I = 1; I <= lSize; I++)
409 {
if ((ScaleFactor = RHS_ScaleFactors[*(pExtOrder++)]) != 1.0)
412 while (pElement !=
NULL)
413 { pElement->
Real *= ScaleFactor;
421 for (I = 1; I <= lSize; I++)
422 {
if ((ScaleFactor = SolutionScaleFactors[*(pExtOrder++)]) != 1.0)
425 while (pElement !=
NULL)
426 { pElement->
Real *= ScaleFactor;
445 #if spCOMPLEX AND SCALING 506 register RealVector RHS_ScaleFactors, SolutionScaleFactors;
513 lSize = Matrix->
Size;
518 --SolutionScaleFactors;
523 for (I = 1; I <= lSize; I++)
524 {
if ((ScaleFactor = RHS_ScaleFactors[*(pExtOrder++)]) != 1.0)
527 while (pElement !=
NULL)
528 { pElement->
Real *= ScaleFactor;
529 pElement->Imag *= ScaleFactor;
537 for (I = 1; I <= lSize; I++)
538 {
if ((ScaleFactor = SolutionScaleFactors[*(pExtOrder++)]) != 1.0)
541 while (pElement !=
NULL)
542 { pElement->
Real *= ScaleFactor;
543 pElement->Imag *= ScaleFactor;
624 for (I = Matrix->
Size; I > 0; I--)
625 Vector[
I] = Solution[*(pExtOrder--)];
628 for (I = Matrix->
Size; I > 0; I--)
632 while (pElement !=
NULL)
633 { Sum += pElement->
Real * Vector[pElement->
Col];
649 #if spCOMPLEX AND MULTIPLICATION 699 #if spSEPARATED_COMPLEX_VECTORS 701 --Solution; --iSolution;
703 RHS -= 2; Solution -= 2;
709 pExtOrder = &Matrix->IntToExtColMap[Matrix->Size];
712 for (I = Matrix->Size; I > 0; I--)
714 Vector[
I].
Imag = iSolution[*(pExtOrder--)];
717 for (I = Matrix->Size; I > 0; I--)
721 pExtOrder = &Matrix->IntToExtRowMap[Matrix->Size];
722 for (I = Matrix->Size; I > 0; I--)
723 { pElement = Matrix->FirstInRow[
I];
726 while (pElement !=
NULL)
732 #if spSEPARATED_COMPLEX_VECTORS 734 iRHS[*pExtOrder--] = Sum.
Imag;
750 #if MULTIPLICATION AND TRANSPOSE 814 for (I = Matrix->
Size; I > 0; I--)
815 Vector[
I] = Solution[*(pExtOrder--)];
818 for (I = Matrix->
Size; I > 0; I--)
822 while (pElement !=
NULL)
823 { Sum += pElement->
Real * Vector[pElement->
Row];
826 RHS[*pExtOrder--] =
Sum;
839 #if spCOMPLEX AND MULTIPLICATION AND TRANSPOSE 889 #if spSEPARATED_COMPLEX_VECTORS 891 --Solution; --iSolution;
893 RHS -= 2; Solution -= 2;
899 pExtOrder = &Matrix->IntToExtRowMap[Matrix->Size];
902 for (I = Matrix->Size; I > 0; I--)
904 Vector[
I].
Imag = iSolution[*(pExtOrder--)];
907 for (I = Matrix->Size; I > 0; I--)
911 pExtOrder = &Matrix->IntToExtColMap[Matrix->Size];
912 for (I = Matrix->Size; I > 0; I--)
913 { pElement = Matrix->FirstInCol[
I];
916 while (pElement !=
NULL)
922 #if spSEPARATED_COMPLEX_VECTORS 924 iRHS[*pExtOrder--] = Sum.
Imag;
983 spDeterminant( eMatrix, pExponent, pDeterminant, piDeterminant )
995 register int I,
Size;
999 #define NORM(a) (nr = ABS((a).Real), ni = ABS((a).Imag), MAX (nr,ni)) 1006 { *pDeterminant = 0.0;
1008 if (Matrix->
Complex) *piDeterminant = 0.0;
1013 Size = Matrix->
Size;
1018 { cDeterminant.
Real = 1.0;
1019 cDeterminant.
Imag = 0.0;
1026 Norm =
NORM( cDeterminant );
1028 {
while (Norm >= 1.0e12)
1029 { cDeterminant.
Real *= 1.0e-12;
1030 cDeterminant.
Imag *= 1.0e-12;
1032 Norm =
NORM( cDeterminant );
1034 while (Norm < 1.0
e-12)
1035 { cDeterminant.
Real *= 1.0e12;
1036 cDeterminant.
Imag *= 1.0e12;
1038 Norm =
NORM( cDeterminant );
1044 Norm =
NORM( cDeterminant );
1046 {
while (Norm >= 10.0)
1047 { cDeterminant.
Real *= 0.1;
1048 cDeterminant.
Imag *= 0.1;
1050 Norm =
NORM( cDeterminant );
1053 { cDeterminant.
Real *= 10.0;
1054 cDeterminant.
Imag *= 10.0;
1056 Norm =
NORM( cDeterminant );
1062 *pDeterminant = cDeterminant.
Real;
1063 *piDeterminant = cDeterminant.
Imag;
1066 #if REAL AND spCOMPLEX 1071 *pDeterminant = 1.0;
1074 { *pDeterminant /= Matrix->
Diag[
I]->
Real;
1077 if (*pDeterminant != 0.0)
1078 {
while (
ABS(*pDeterminant) >= 1.0e12)
1079 { *pDeterminant *= 1.0e-12;
1082 while (
ABS(*pDeterminant) < 1.0
e-12)
1083 { *pDeterminant *= 1.0e12;
1090 if (*pDeterminant != 0.0)
1091 {
while (
ABS(*pDeterminant) >= 10.0)
1092 { *pDeterminant *= 0.1;
1095 while (
ABS(*pDeterminant) < 1.0)
1096 { *pDeterminant *= 10.0;
1101 *pDeterminant = -*pDeterminant;
1149 if (Matrix->
Fillins == 0)
return;
1161 while (pListNode !=
NULL)
1164 while (pFillin <= pLastFillin)
1165 (pFillin++)->Row = 0;
1166 pListNode = pListNode->
Next;
1175 for (I = 1; I <=
Size; I++)
1177 while ((pElement = *ppElement) !=
NULL)
1178 {
if (pElement->
Row == 0)
1180 if (Matrix->
Diag[pElement->
Col] == pElement)
1189 for (I = 1; I <=
Size; I++)
1191 while ((pElement = *ppElement) !=
NULL)
1192 {
if (pElement->
Row == 0)
1209 #if TRANSLATE AND DELETE 1252 int Size, ExtRow, ExtCol;
1258 ASSERT( Row <= Matrix->ExtSize
AND Col <= Matrix->ExtSize );
1260 Size = Matrix->
Size;
1290 while (pLastElement !=
NULL)
1292 while ((pElement = *ppElement) !=
NULL)
1293 {
if (pElement == pLastElement)
1303 while (pLastElement !=
NULL)
1305 while ((pElement = *ppElement) !=
NULL)
1306 {
if (pElement == pLastElement)
1315 Matrix->
Size = Size - 1;
1376 Diag = Matrix->
Diag;
1378 for (I = 2; I <= Matrix->
Size; I++)
1382 else if (Mag < MinPivot)
1386 return MaxPivot / MinPivot;
1461 register int I,
K, Row;
1464 RealNumber E, Em, Wp, Wm, ASp, ASm, ASw, ASy, ASv, ASz, MaxY, ScaleFactor;
1465 RealNumber Linpack, OLeary, InvNormOfInverse;
1471 *pError = Matrix->
Error;
1473 if (NormOfMatrix == 0.0)
1484 Size = Matrix->
Size;
1495 for (I = Size; I > 0; I--) T[I] = 0.0;
1506 for (I = 1; I <=
Size; I++)
1507 { pPivot = Matrix->
Diag[
I];
1508 if (T[I] < 0.0) Em = -E;
else Em = E;
1509 Wm = (Em + T[
I]) * pPivot->
Real;
1512 for (K = Size; K > 0; K--) T[K] *= ScaleFactor;
1515 Wm = (Em + T[
I]) * pPivot->
Real;
1517 Wp = (T[
I] - Em) * pPivot->
Real;
1518 ASp =
ABS(T[I] - Em);
1519 ASm =
ABS(Em + T[I]);
1523 while (pElement !=
NULL)
1524 { Row = pElement->
Row;
1525 Tm[Row] = T[Row] - (Wm * pElement->
Real);
1526 T[Row] -= (Wp * pElement->
Real);
1528 ASm +=
ABS(Tm[Row]);
1536 while (pElement !=
NULL)
1537 { T[pElement->
Row] = Tm[pElement->
Row];
1545 for (ASw = 0.0, I = Size; I > 0; I--) ASw +=
ABS(T[I]);
1546 ScaleFactor = 1.0 / (
SLACK * ASw);
1547 if (ScaleFactor < 0.5)
1548 {
for (I = Size; I > 0; I--) T[I] *= ScaleFactor;
1553 for (I = Size; I >= 1; I--)
1555 while (pElement !=
NULL)
1556 { T[
I] -= pElement->
Real * T[pElement->
Col];
1561 for (K = Size; K > 0; K--) T[K] *= ScaleFactor;
1567 for (ASy = 0.0, I = Size; I > 0; I--) ASy +=
ABS(T[I]);
1568 ScaleFactor = 1.0 / (
SLACK * ASy);
1569 if (ScaleFactor < 0.5)
1570 {
for (I = Size; I > 0; I--) T[I] *= ScaleFactor;
1576 for (MaxY = 0.0, I = Size; I > 0; I--)
1577 if (MaxY <
ABS(T[I])) MaxY =
ABS(T[I]);
1585 for (I = 1; I <=
Size; I++)
1587 while (pElement !=
NULL)
1588 { T[pElement->
Col] -= T[
I] * pElement->
Real;
1593 for (K = Size; K > 0; K--) T[K] *= ScaleFactor;
1599 for (ASv = 0.0, I = Size; I > 0; I--) ASv +=
ABS(T[I]);
1600 ScaleFactor = 1.0 / (
SLACK * ASv);
1601 if (ScaleFactor < 0.5)
1602 {
for (I = Size; I > 0; I--) T[I] *= ScaleFactor;
1607 for (I = Size; I >= 1; I--)
1608 { pPivot = Matrix->
Diag[
I];
1610 while (pElement !=
NULL)
1611 { T[
I] -= pElement->
Real * T[pElement->
Row];
1614 T[
I] *= pPivot->
Real;
1617 for (K = Size; K > 0; K--) T[K] *= ScaleFactor;
1623 for (ASz = 0.0, I = Size; I > 0; I--) ASz +=
ABS(T[I]);
1629 Linpack = ASy / ASz;
1631 InvNormOfInverse =
MIN( Linpack, OLeary );
1632 return InvNormOfInverse / NormOfMatrix;
1671 register int I,
K, Row;
1674 RealNumber E, Em, ASp, ASm, ASw, ASy, ASv, ASz, MaxY, ScaleFactor;
1675 RealNumber Linpack, OLeary, InvNormOfInverse;
1680 Size = Matrix->Size;
1687 for (I = Size; I > 0; I--) T[I].
Real = T[I].Imag = 0.0;
1698 for (I = 1; I <=
Size; I++)
1699 { pPivot = Matrix->Diag[
I];
1700 if (T[I].
Real < 0.0) Em = -E;
else Em = E;
1720 while (pElement !=
NULL)
1721 { Row = pElement->
Row;
1735 while (pElement !=
NULL)
1736 { T[pElement->
Row] = Tm[pElement->
Row];
1744 for (ASw = 0.0, I = Size; I > 0; I--) ASw +=
CMPLX_1_NORM(T[I]);
1745 ScaleFactor = 1.0 / (
SLACK * ASw);
1746 if (ScaleFactor < 0.5)
1752 for (I = Size; I >= 1; I--)
1754 while (pElement !=
NULL)
1767 for (ASy = 0.0, I = Size; I > 0; I--) ASy +=
CMPLX_1_NORM(T[I]);
1768 ScaleFactor = 1.0 / (
SLACK * ASy);
1769 if (ScaleFactor < 0.5)
1776 for (MaxY = 0.0, I = Size; I > 0; I--)
1785 for (I = 1; I <=
Size; I++)
1787 while (pElement !=
NULL)
1800 for (ASv = 0.0, I = Size; I > 0; I--) ASv +=
CMPLX_1_NORM(T[I]);
1801 ScaleFactor = 1.0 / (
SLACK * ASv);
1802 if (ScaleFactor < 0.5)
1808 for (I = Size; I >= 1; I--)
1809 { pPivot = Matrix->Diag[
I];
1811 while (pElement !=
NULL)
1825 for (ASz = 0.0, I = Size; I > 0; I--) ASz +=
CMPLX_1_NORM(T[I]);
1829 Linpack = ASy / ASz;
1831 InvNormOfInverse =
MIN( Linpack, OLeary );
1832 return InvNormOfInverse / NormOfMatrix;
1873 {
for (I = Matrix->
Size; I > 0; I--)
1876 while (pElement !=
NULL)
1877 { AbsRowSum +=
ABS( pElement->
Real );
1880 if (Max < AbsRowSum) Max = AbsRowSum;
1886 {
for (I = Matrix->
Size; I > 0; I--)
1889 while (pElement !=
NULL)
1893 if (Max < AbsRowSum) Max = AbsRowSum;
1980 RealNumber Mag, AbsColSum, Max = 0.0, MaxRow = 0.0, MaxCol = 0.0;
1993 for (I = 1; I <= Matrix->
Size; I++)
1994 { pDiag = Matrix->
Diag[
I];
1997 Pivot = 1.0 / pDiag->
Real;
1999 if (Mag > MaxRow) MaxRow = Mag;
2001 while (pElement != pDiag)
2002 { Mag =
ABS( pElement->
Real );
2003 if (Mag > MaxRow) MaxRow = Mag;
2010 while (pElement != pDiag)
2011 { AbsColSum +=
ABS( pElement->
Real );
2014 if (AbsColSum > MaxCol) MaxCol = AbsColSum;
2018 {
for (I = 1; I <= Matrix->
Size; I++)
2020 while (pElement !=
NULL)
2021 { Mag =
ABS( pElement->
Real );
2022 if (Mag > Max) Max = Mag;
2034 for (I = 1; I <= Matrix->
Size; I++)
2035 { pDiag = Matrix->
Diag[
I];
2040 if (Mag > MaxRow) MaxRow = Mag;
2042 while (pElement != pDiag)
2044 if (Mag > MaxRow) MaxRow = Mag;
2051 while (pElement != pDiag)
2055 if (AbsColSum > MaxCol) MaxCol = AbsColSum;
2059 {
for (I = 1; I <= Matrix->
Size; I++)
2061 while (pElement !=
NULL)
2063 if (Mag > Max) Max = Mag;
2070 return MaxRow * MaxCol;
2100 register int Count,
I, MaxCount = 0;
2111 {
for (I = Matrix->
Size; I > 0; I--)
2114 while (pElement->
Col < I)
2118 if (Count > MaxCount) MaxCount = Count;
2125 Gear = 1.01*((MaxCount + 1) * Matrix->
RelThreshold + 1.0) *
SQR(MaxCount);
2126 Reid = 3.01 * Matrix->
Size;
2129 return (MACHINE_RESOLUTION * Rho * Gear);
2131 return (MACHINE_RESOLUTION * Rho * Reid);
ArrayOfElementPtrs FirstInRow
void spMultTransposed(eMatrix, RHS, Solution IMAG_VECTORS) char *eMatrix
#define CMPLX_MULT_ASSIGN(to, from)
if(NOT Matrix->RowsLinked) spcLinkRows(Matrix)
#define ALLOC(type, number)
#define CMPLX_MULT_SUBT(to, mult_a, mult_b, subt)
#define IS_FACTORED(matrix)
void spDeterminant(char *eMatrix, int *pExponent, RealNumber *pDeterminant)
#define spSEPARATED_COMPLEX_VECTORS
int NumberOfFillinsInList
void spDeleteRowAndCol(char *eMatrix, int Row, int Col)
void spMNA_Preorder(char *eMatrix)
RealVector Solution IMAG_VECTORS
struct FillinListNodeStruct * Next
ArrayOfElementPtrs FirstInCol
struct ComplexNumber * ComplexVector
#define IS_SPARSE(matrix)
struct MatrixElement * NextInRow
RealNumber spRoundoff(char *eMatrix, RealNumber Rho)
#define CMPLX_MULT_SUBT_ASSIGN(to, from_a, from_b)
void spMultiply(eMatrix, RHS, Solution IMAG_VECTORS) char *eMatrix
RealNumber spCondition(char *eMatrix, RealNumber NormOfMatrix, int *pError)
RealNumber spLargestElement(char *eMatrix)
for(I=Matrix->Size;I, 0;I--)
register ElementPtr pElement
#define CMPLX_MULT_ADD_ASSIGN(to, from_a, from_b)
struct FillinListNodeStruct * LastFillinListNode
BOOLEAN NumberOfInterchangesIsOdd
void spcRowExchange(MatrixPtr, int row1, int row2)
static void ComplexMatrixMultiply()
#define SCLR_MULT_ASSIGN(to, sclr)
void spStripFills(char *eMatrix)
RealNumber spPseudoCondition(char *eMatrix)
void spScale(char *eMatrix, RealVector RHS_ScaleFactors, RealVector SolutionScaleFactors)
static void ScaleComplexMatrix()
static void ComplexTransposedMatrixMultiply()
ElementPtr NextAvailFillin
struct FillinListNodeStruct * FirstFillinListNode
int MaxRowCountInLowerTri
ElementPtr spcFindElementInCol(MatrixPtr Matrix, ElementPtr *LastAddr, int Row, int Col, BOOLEAN CreateIfMissing)
struct MatrixFrame * MatrixPtr
RealNumber spNorm(char *eMatrix)
static RealNumber ComplexCondition()
struct MatrixElement * NextInCol
ASSERT(IS_SPARSE(Matrix) AND NOT Matrix->Factored)
void spcLinkRows(MatrixPtr)
register RealVector Vector
#define CMPLX_RECIPROCAL(to, den)
void spcColExchange(MatrixPtr, int col1, int col2)