2 #include <../../nrnconf.h> 52 "Sparse1.3: Copyright (c) 1985,86,87,88 by Kenneth S. Kundert";
71 #define spINSIDE_SPARSE 205 int Step,
Size, ReorderingRequired;
218 ReorderingRequired =
NO;
223 for (Step = 1; Step <=
Size; Step++)
224 { pPivot = Matrix->
Diag[Step];
233 { ReorderingRequired =
YES;
237 if (NOT ReorderingRequired)
246 #if ANNOTATE >= ON_STRANGE_BEHAVIOR 247 printf(
"Reordering, Step = %1d\n", Step);
265 return Matrix->
Error;
274 for (; Step <=
Size; Step++)
288 WriteStatus( Matrix, Step );
297 return Matrix->
Error;
345 register int Step,
Size;
353 0.0, 0.0, DIAG_PIVOTING_AS_DEFAULT );
367 for (Step = 2; Step <=
Size; Step++)
374 while (pElement !=
NULL)
375 { Dest[pElement->
Row] = pElement->
Real;
381 while (pColumn->
Row < Step)
382 { pElement = Matrix->
Diag[pColumn->
Row];
383 pColumn->
Real = Dest[pColumn->
Row] * pElement->
Real;
385 Dest[pElement->
Row] -= pColumn->
Real * pElement->
Real;
391 while (pElement !=
NULL)
392 { pElement->
Real = Dest[pElement->
Row];
397 if (Dest[Step] == 0.0)
return ZeroPivot( Matrix, Step );
398 Matrix->
Diag[Step]->
Real = 1.0 / Dest[Step];
406 while (pElement !=
NULL)
407 { pDest[pElement->
Row] = &pElement->
Real;
413 while (pColumn->
Row < Step)
414 { pElement = Matrix->
Diag[pColumn->
Row];
415 Mult = (*pDest[pColumn->
Row] *= pElement->
Real);
417 *pDest[pElement->
Row] -= Mult * pElement->
Real;
422 if (Matrix->
Diag[Step]->
Real == 0.0)
464 register int Step,
Size;
477 for (Step = 2; Step <=
Size; Step++)
485 while (pElement !=
NULL)
492 while (pColumn->
Row < Step)
506 while (pElement !=
NULL)
523 while (pElement !=
NULL)
530 while (pColumn->
Row < Step)
604 register int Step,
Size;
605 register int *Nc, *No, *Nm;
619 {
for (Step = 1; Step <=
Size; Step++)
621 DoRealDirect[Step] =
YES;
624 DoCmplxDirect[Step] =
YES;
629 {
for (Step = 1; Step <=
Size; Step++)
631 DoRealDirect[Step] =
NO;
634 DoCmplxDirect[Step] =
NO;
646 for (Step = 1; Step <=
Size; Step++)
647 { Nc[Step] = No[Step] = Nm[Step] = 0;
650 while (pElement !=
NULL)
656 while (pColumn->
Row < Step)
657 { pElement = Matrix->
Diag[pColumn->
Row];
665 for (Step = 1; Step <=
Size; Step++)
682 DoRealDirect[Step] = (Nm[Step] + No[Step] > 3*Nc[Step] - 2*Nm[Step]);
686 DoCmplxDirect[Step] =
NO;
693 DoRealDirect[Step] = (Nm[Step] + No[Step] > 3*Nc[Step] - 2*Nm[Step]);
696 DoCmplxDirect[Step] = (Nm[Step] + No[Step] > 7*Nc[Step] - 4*Nm[Step]);
703 DoRealDirect[Step] = (Nm[Step] + No[Step] > 3*Nc[Step] - 2*Nm[Step]);
706 DoCmplxDirect[Step] = (Nm[Step] + No[Step] > 7*Nc[Step] - 4*Nm[Step]);
712 #if (ANNOTATE == FULL) 714 for (Step = 1; Step <=
Size; Step++)
716 printf(
"Operation count for inner loop of factorization = %d.\n", Ops);
849 #if spSEPARATED_COMPLEX_VECTORS OR NOT spCOMPLEX 860 for (I = Step; I <=
Size; I++)
865 while (pElement !=
NULL AND pElement->
Col < Step)
867 while (pElement !=
NULL)
875 #if spSEPARATED_COMPLEX_VECTORS OR NOT spCOMPLEX 877 if (
RHS[ExtRow] != 0.0) Count++;
881 {
if ((
RHS[2*ExtRow] != 0.0)
OR (
RHS[2*ExtRow+1] != 0.0))
884 else if (
RHS[I] != 0.0) Count++;
891 for (I = Step; I <=
Size; I++)
896 while (pElement !=
NULL AND pElement->
Row < Step)
898 while (pElement !=
NULL)
950 register int I, *pMarkowitzRow, *pMarkowitzCol;
951 register long Product, *pMarkowitzProduct;
962 for (I = Step; I <=
Size; I++)
965 if ((*pMarkowitzRow > LARGEST_SHORT_INTEGER
AND *pMarkowitzCol != 0)
OR 966 (*pMarkowitzCol > LARGEST_SHORT_INTEGER
AND *pMarkowitzRow != 0))
967 { fProduct = (double)(*pMarkowitzRow++) * (double)(*pMarkowitzCol++);
968 if (fProduct >= LARGEST_LONG_INTEGER)
969 *pMarkowitzProduct++ = LARGEST_LONG_INTEGER;
971 *pMarkowitzProduct++ = fProduct;
974 { Product = *pMarkowitzRow++ * *pMarkowitzCol++;
975 if ((*pMarkowitzProduct++ = Product) == 0)
1035 int Step, DiagPivoting;
1048 if (ChosenPivot !=
NULL)
1054 #if DIAGONAL_PIVOTING 1064 if (ChosenPivot !=
NULL)
1074 if (ChosenPivot !=
NULL)
1140 register long *pMarkowitzProduct;
1160 while (Singletons-- > 0)
1183 while ( *pMarkowitzProduct-- )
1194 if (I < Step)
break;
1195 if (I > Matrix->
Size) I = Step;
1198 if ((ChosenPivot = Matrix->
Diag[I]) !=
NULL)
1205 FindBiggestInColExclude( Matrix, ChosenPivot, Step )
1206 )
return ChosenPivot;
1213 while ((ChosenPivot !=
NULL)
AND (ChosenPivot->
Row < Step))
1219 FindBiggestInColExclude( Matrix, ChosenPivot,
1221 )
return ChosenPivot;
1225 while((ChosenPivot !=
NULL)
AND (ChosenPivot->
Col<Step))
1231 FindBiggestInColExclude( Matrix,
1234 )
return ChosenPivot;
1240 while ((ChosenPivot !=
NULL)
AND (ChosenPivot->
Col < Step))
1246 FindBiggestInColExclude( Matrix, ChosenPivot,
1248 )
return ChosenPivot;
1273 #if DIAGONAL_PIVOTING 1274 #if MODIFIED_MARKOWITZ 1348 register long MinMarkowitzProduct, *pMarkowitzProduct;
1349 register ElementPtr pDiag, pOtherInRow, pOtherInCol;
1350 int I, NumberOfTies;
1351 ElementPtr ChosenPivot, TiedElements[MAX_MARKOWITZ_TIES + 1];
1352 RealNumber Magnitude, LargestInCol, Ratio, MaxRatio;
1358 MinMarkowitzProduct = LARGEST_LONG_INTEGER;
1385 {
while (MinMarkowitzProduct < *(--pMarkowitzProduct))
1397 if (I < Step)
break;
1398 if (I > Matrix->
Size) I = Step;
1400 if ((pDiag = Matrix->
Diag[I]) ==
NULL)
1405 if (*pMarkowitzProduct == 1)
1414 while(pOtherInRow !=
NULL)
1415 {
if (pOtherInRow->
Col >= Step
AND pOtherInRow->
Col != I)
1420 while(pOtherInCol !=
NULL)
1421 {
if (pOtherInCol->
Row >= Step
AND pOtherInCol->
Row != I)
1430 {
if (pOtherInRow->
Col == pOtherInCol->
Row)
1433 if (Magnitude >= LargestOffDiagonal)
1442 if (*pMarkowitzProduct < MinMarkowitzProduct)
1445 TiedElements[0] = pDiag;
1446 MinMarkowitzProduct = *pMarkowitzProduct;
1452 if (NumberOfTies < MAX_MARKOWITZ_TIES)
1453 { TiedElements[++NumberOfTies] = pDiag;
1454 if (NumberOfTies >= MinMarkowitzProduct * TIES_MULTIPLIER)
1461 if (NumberOfTies < 0)
1468 for (I = 0; I <= NumberOfTies; I++)
1469 { pDiag = TiedElements[
I];
1472 Ratio = LargestInCol / Magnitude;
1473 if (Ratio < MaxRatio)
1474 { ChosenPivot = pDiag;
1547 register long MinMarkowitzProduct, *pMarkowitzProduct;
1550 ElementPtr ChosenPivot, pOtherInRow, pOtherInCol;
1551 RealNumber Magnitude, LargestInCol, LargestOffDiagonal;
1556 MinMarkowitzProduct = LARGEST_LONG_INTEGER;
1583 {
while (*(--pMarkowitzProduct) >= MinMarkowitzProduct)
1590 if (I < Step)
break;
1591 if (I > Matrix->
Size) I = Step;
1593 if ((pDiag = Matrix->
Diag[I]) ==
NULL)
1598 if (*pMarkowitzProduct == 1)
1607 while(pOtherInRow !=
NULL)
1608 {
if (pOtherInRow->
Col >= Step
AND pOtherInRow->
Col != I)
1613 while(pOtherInCol !=
NULL)
1614 {
if (pOtherInCol->
Row >= Step
AND pOtherInCol->
Row != I)
1623 {
if (pOtherInRow->
Col == pOtherInCol->
Row)
1626 if (Magnitude >= LargestOffDiagonal)
1635 MinMarkowitzProduct = *pMarkowitzProduct;
1636 ChosenPivot = pDiag;
1639 if (ChosenPivot !=
NULL)
1713 register long MinMarkowitzProduct, *pMarkowitzProduct;
1716 int NumberOfTies=0,
Size = Matrix->
Size;
1718 RealNumber Magnitude, Ratio, RatioOfAccepted=0.0, LargestInCol;
1723 MinMarkowitzProduct = LARGEST_LONG_INTEGER;
1728 for (J =
Size+1; J > Step; J--)
1730 if (*(--pMarkowitzProduct) > MinMarkowitzProduct)
1732 if (J > Matrix->
Size)
1736 if ((pDiag = Matrix->
Diag[I]) ==
NULL)
1746 if (*pMarkowitzProduct < MinMarkowitzProduct)
1749 ChosenPivot = pDiag;
1750 MinMarkowitzProduct = *pMarkowitzProduct;
1751 RatioOfAccepted = LargestInCol / Magnitude;
1758 Ratio = LargestInCol / Magnitude;
1759 if (Ratio < RatioOfAccepted)
1760 { ChosenPivot = pDiag;
1761 RatioOfAccepted = Ratio;
1763 if (NumberOfTies >= MinMarkowitzProduct * TIES_MULTIPLIER)
1844 long Product, MinMarkowitzProduct;
1846 RealNumber Magnitude, LargestElementMag, Ratio, RatioOfAccepted=0.0, LargestInCol;
1851 LargestElementMag = 0.0;
1852 MinMarkowitzProduct = LARGEST_LONG_INTEGER;
1855 for (I = Step; I <=
Size; I++)
1858 while (pElement !=
NULL AND pElement->
Row < Step)
1864 while (pElement !=
NULL)
1868 if ((Magnitude =
ELEMENT_MAG(pElement)) > LargestElementMag)
1869 { LargestElementMag = Magnitude;
1877 if ((Product <= MinMarkowitzProduct)
AND 1883 if (Product < MinMarkowitzProduct)
1887 MinMarkowitzProduct = Product;
1888 RatioOfAccepted = LargestInCol / Magnitude;
1895 Ratio = LargestInCol / Magnitude;
1896 if (Ratio < RatioOfAccepted)
1898 RatioOfAccepted = Ratio;
1900 if (NumberOfTies >= MinMarkowitzProduct * TIES_MULTIPLIER)
1908 if (ChosenPivot !=
NULL)
return ChosenPivot;
1910 if (LargestElementMag == 0.0)
1916 return pLargestElement;
1967 while (pElement !=
NULL)
1968 {
if ((Magnitude =
ELEMENT_MAG(pElement)) > Largest)
1969 Largest = Magnitude;
2036 Row = pElement->
Row;
2037 Col = pElement->
Col;
2041 while ((pElement !=
NULL)
AND (pElement->
Row < Step))
2045 if (pElement->
Row != Row)
2052 {
if ((Magnitude =
ELEMENT_MAG(pElement)) > Largest)
2053 {
if (pElement->
Row != Row)
2054 Largest = Magnitude;
2111 register int Row, Col;
2112 long OldMarkowitzProd_Step, OldMarkowitzProd_Row, OldMarkowitzProd_Col;
2121 if ((Row == Step)
AND (Col == Step))
return;
2147 if ((Matrix->
MarkowitzProd[Row]==0) != (OldMarkowitzProd_Row==0))
2148 {
if (OldMarkowitzProd_Row == 0)
2164 if ((Matrix->
MarkowitzProd[Col]==0) != (OldMarkowitzProd_Col==0))
2165 {
if (OldMarkowitzProd_Col == 0)
2187 if ((Matrix->
MarkowitzProd[Step]==0) != (OldMarkowitzProd_Step==0))
2188 {
if (OldMarkowitzProd_Step == 0)
2244 if (Row1 > Row2)
SWAP(
int, Row1, Row2);
2251 if (Row1Ptr ==
NULL)
2252 { Column = Row2Ptr->
Col;
2257 else if (Row2Ptr ==
NULL)
2258 { Column = Row1Ptr->
Col;
2263 else if (Row1Ptr->
Col < Row2Ptr->
Col)
2264 { Column = Row1Ptr->
Col;
2269 else if (Row1Ptr->
Col > Row2Ptr->
Col)
2270 { Column = Row2Ptr->
Col;
2276 { Column = Row1Ptr->
Col;
2345 if (Col1 > Col2)
SWAP(
int, Col1, Col2);
2352 if (Col1Ptr ==
NULL)
2353 { Row = Col2Ptr->
Row;
2358 else if (Col2Ptr ==
NULL)
2359 { Row = Col1Ptr->
Row;
2364 else if (Col1Ptr->
Row < Col2Ptr->
Row)
2365 { Row = Col1Ptr->
Row;
2370 else if (Col1Ptr->
Row > Col2Ptr->
Row)
2371 { Row = Col2Ptr->
Row;
2377 { Row = Col1Ptr->
Row;
2446 int Row1, Row2, Column;
2448 ElementPtr *ElementAboveRow1, *ElementAboveRow2;
2449 ElementPtr ElementBelowRow1, ElementBelowRow2;
2454 ElementAboveRow1 = &(Matrix->
FirstInCol[Column]);
2455 pElement = *ElementAboveRow1;
2456 while (pElement->
Row < Row1)
2457 { ElementAboveRow1 = &(pElement->
NextInCol);
2458 pElement = *ElementAboveRow1;
2460 if (Element1 !=
NULL)
2461 { ElementBelowRow1 = Element1->
NextInCol;
2462 if (Element2 ==
NULL)
2465 if ( ElementBelowRow1 !=
NULL AND ElementBelowRow1->
Row < Row2 )
2468 *ElementAboveRow1 = ElementBelowRow1;
2471 pElement = ElementBelowRow1;
2473 { ElementAboveRow2 = &(pElement->
NextInCol);
2474 pElement = *ElementAboveRow2;
2475 }
while (pElement !=
NULL AND pElement->
Row < Row2);
2478 *ElementAboveRow2 = Element1;
2480 *ElementAboveRow1 =ElementBelowRow1;
2482 Element1->
Row = Row2;
2487 if ( ElementBelowRow1->
Row == Row2)
2492 *ElementAboveRow1 = Element2;
2497 pElement = ElementBelowRow1;
2499 { ElementAboveRow2 = &(pElement->
NextInCol);
2500 pElement = *ElementAboveRow2;
2501 }
while (pElement->
Row < Row2);
2506 *ElementAboveRow1 = Element2;
2508 *ElementAboveRow2 = Element1;
2511 Element1->
Row = Row2;
2512 Element2->
Row = Row1;
2521 if (ElementBelowRow1->
Row != Row2)
2523 { ElementAboveRow2 = &(pElement->
NextInCol);
2524 pElement = *ElementAboveRow2;
2525 }
while (pElement->
Row < Row2);
2530 *ElementAboveRow2 = Element2->
NextInCol;
2531 *ElementAboveRow1 = Element2;
2534 Element2->
Row = Row1;
2587 int Col1, Col2, Row;
2590 ElementPtr *ElementLeftOfCol1, *ElementLeftOfCol2;
2591 ElementPtr ElementRightOfCol1, ElementRightOfCol2;
2596 ElementLeftOfCol1 = &(Matrix->
FirstInRow[Row]);
2597 pElement = *ElementLeftOfCol1;
2598 while (pElement->
Col < Col1)
2599 { ElementLeftOfCol1 = &(pElement->
NextInRow);
2600 pElement = *ElementLeftOfCol1;
2602 if (Element1 !=
NULL)
2603 { ElementRightOfCol1 = Element1->
NextInRow;
2604 if (Element2 ==
NULL)
2607 if ( ElementRightOfCol1 !=
NULL AND ElementRightOfCol1->
Col < Col2 )
2610 *ElementLeftOfCol1 = ElementRightOfCol1;
2613 pElement = ElementRightOfCol1;
2615 { ElementLeftOfCol2 = &(pElement->
NextInRow);
2616 pElement = *ElementLeftOfCol2;
2617 }
while (pElement !=
NULL AND pElement->
Col < Col2);
2620 *ElementLeftOfCol2 = Element1;
2622 *ElementLeftOfCol1 =ElementRightOfCol1;
2624 Element1->
Col = Col2;
2629 if ( ElementRightOfCol1->
Col == Col2)
2634 *ElementLeftOfCol1 = Element2;
2639 pElement = ElementRightOfCol1;
2641 { ElementLeftOfCol2 = &(pElement->
NextInRow);
2642 pElement = *ElementLeftOfCol2;
2643 }
while (pElement->
Col < Col2);
2645 ElementRightOfCol2 = Element2->
NextInRow;
2648 *ElementLeftOfCol1 = Element2;
2649 Element2->
NextInRow = ElementRightOfCol1;
2650 *ElementLeftOfCol2 = Element1;
2651 Element1->
NextInRow = ElementRightOfCol2;
2653 Element1->
Col = Col2;
2654 Element2->
Col = Col1;
2663 if (ElementRightOfCol1->
Col != Col2)
2665 { ElementLeftOfCol2 = &(pElement->
NextInRow);
2666 pElement = *ElementLeftOfCol2;
2667 }
while (pElement->
Col < Col2);
2669 ElementRightOfCol2 = Element2->
NextInRow;
2672 *ElementLeftOfCol2 = Element2->
NextInRow;
2673 *ElementLeftOfCol1 = Element2;
2674 Element2->
NextInRow = ElementRightOfCol1;
2676 Element2->
Col = Col1;
2740 while (pUpper !=
NULL)
2747 while (pLower !=
NULL)
2748 { Row = pLower->
Row;
2829 while (pUpper !=
NULL)
2837 while (pLower !=
NULL)
2838 { Row = pLower->
Row;
2897 register int Row, Col;
2906 { Row = ColPtr->
Row;
2910 if ((MarkoRow[Row] > LARGEST_SHORT_INTEGER
AND MarkoCol[Row] != 0)
OR 2911 (MarkoCol[Row] > LARGEST_SHORT_INTEGER
AND MarkoRow[Row] != 0))
2912 { Product = MarkoCol[Row] * MarkoRow[Row];
2913 if (Product >= LARGEST_LONG_INTEGER)
2918 else Matrix->
MarkowitzProd[Row] = MarkoRow[Row] * MarkoCol[Row];
2919 if (MarkoRow[Row] == 0)
2924 { Col = RowPtr->
Col;
2928 if ((MarkoRow[Col] > LARGEST_SHORT_INTEGER
AND MarkoCol[Col] != 0)
OR 2929 (MarkoCol[Col] > LARGEST_SHORT_INTEGER
AND MarkoRow[Col] != 0))
2930 { Product = MarkoCol[Col] * MarkoRow[Col];
2931 if (Product >= LARGEST_LONG_INTEGER)
2936 else Matrix->
MarkowitzProd[Col] = MarkoRow[Col] * MarkoCol[Col];
2937 if ((MarkoCol[Col] == 0)
AND (MarkoRow[Col] != 0))
2993 pElement = *ppElementAbove;
2994 while (pElement !=
NULL)
2995 {
if (pElement->
Row < Row)
2996 { ppElementAbove = &pElement->
NextInCol;
2997 pElement = *ppElementAbove;
3073 #if ANNOTATE == FULL 3082 static void WriteStatus( Matrix, Step )
3091 printf(
"Step = %1d ", Step);
3095 {
case 's':
printf(
"SearchForSingleton\n");
break;
3096 case 'q':
printf(
"QuicklySearchDiagonal\n");
break;
3097 case 'd':
printf(
"SearchDiagonal\n");
break;
3098 case 'e':
printf(
"SearchEntireMatrix\n");
break;
3101 printf(
"MarkowitzRow = ");
3102 for (I = 1; I <= Matrix->
Size; I++)
3106 printf(
"MarkowitzCol = ");
3107 for (I = 1; I <= Matrix->
Size; I++)
3111 printf(
"MarkowitzProduct = ");
3112 for (I = 1; I <= Matrix->
Size; I++)
3118 printf(
"IntToExtRowMap = ");
3119 for (I = 1; I <= Matrix->
Size; I++)
3123 printf(
"IntToExtColMap = ");
3124 for (I = 1; I <= Matrix->
Size; I++)
3128 printf(
"ExtToIntRowMap = ");
3129 for (I = 1; I <= Matrix->
ExtSize; I++)
3133 printf(
"ExtToIntColMap = ");
3134 for (I = 1; I <= Matrix->
ExtSize; I++)
ArrayOfElementPtrs FirstInRow
#define CMPLX_MULT_ASSIGN(to, from)
static RealNumber FindBiggestInColExclude()
#define spDEFAULT_PARTITION
#define ALLOC(type, number)
#define CMPLX_ASSIGN(to, from)
#define spINDIRECT_PARTITION
static void CountMarkowitz()
static RealNumber FindLargestInCol()
#define spDIRECT_PARTITION
ArrayOfElementPtrs FirstInCol
static int MatrixIsSingular()
#define IS_SPARSE(matrix)
struct MatrixElement * NextInRow
static void ExchangeRowsAndCols()
static void ExchangeRowElements()
static int FactorComplexMatrix()
#define CMPLX_MULT_SUBT_ASSIGN(to, from_a, from_b)
BOOLEAN InternalVectorsAllocated
static ElementPtr SearchEntireMatrix()
static void RealRowColElimination()
static void CreateInternalVectors()
static ElementPtr SearchDiagonal()
register ElementPtr pElement
#define ASSERT(condition)
BOOLEAN NumberOfInterchangesIsOdd
static void ComplexRowColElimination()
static void UpdateMarkowitzNumbers()
static ElementPtr SearchForPivot()
static void ExchangeColElements()
static ElementPtr SearchForSingleton()
int spOrderAndFactor(char *eMatrix, RHS, RelThreshold, AbsThreshold, BOOLEAN DiagPivoting)
ElementPtr spcCreateElement(MatrixPtr Matrix, int Row, int Col, ElementPtr *LastAddr, BOOLEAN Fillin)
int MaxRowCountInLowerTri
void spcLinkRows(MatrixPtr)
ElementPtr spcFindElementInCol(MatrixPtr Matrix, ElementPtr *LastAddr, int Row, int Col, BOOLEAN CreateIfMissing)
char PivotSelectionMethod
struct MatrixFrame * MatrixPtr
#define CMPLX_MULT(to, from_a, from_b)
struct MatrixElement * NextInCol
static ElementPtr CreateFillin()
int spFactor(char *eMatrix)
void spPartition(char *eMatrix, int Mode)
static ElementPtr QuicklySearchDiagonal()
#define CMPLX_RECIPROCAL(to, den)
static void MarkowitzProducts()