00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 #define spINSIDE_SPARSE
00063
00064
00065 #include "spConfig.h"
00066 #include "spUtils.h"
00067 #include "spmatrix.h"
00068 #include "spDefs.h"
00069 #include "spmalloc.h"
00070
00071 #if MODIFIED_NODAL
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 #undef SPBOOLEAN
00161 #define SPBOOLEAN int
00162
00163 void spMNA_Preorder( char * eMatrix )
00164 {
00165 MatrixPtr Matrix = (MatrixPtr)eMatrix;
00166 register int J, Size;
00167 ElementPtr pTwin1, pTwin2;
00168 int Twins, StartAt = 1;
00169 SPBOOLEAN Swapped, AnotherPassNeeded;
00170
00171
00172 ASSERT( IS_VALID(Matrix) AND NOT Matrix->Factored );
00173
00174 if (Matrix->RowsLinked) return;
00175 Size = Matrix->Size;
00176 Matrix->Reordered = YES;
00177
00178 do
00179 { AnotherPassNeeded = Swapped = NO;
00180
00181
00182 for (J = StartAt; J <= Size; J++)
00183 { if (Matrix->Diag[J] == NULL)
00184 { Twins = CountTwins( Matrix, J, &pTwin1, &pTwin2 );
00185 if (Twins == 1)
00186 {
00187 SwapCols( Matrix, pTwin1, pTwin2 );
00188 Swapped = YES;
00189 }
00190 else if ((Twins > 1) AND NOT AnotherPassNeeded)
00191 { AnotherPassNeeded = YES;
00192 StartAt = J;
00193 }
00194 }
00195 }
00196
00197
00198 if (AnotherPassNeeded)
00199 { for (J = StartAt; NOT Swapped AND (J <= Size); J++)
00200 { if (Matrix->Diag[J] == NULL)
00201 { Twins = CountTwins( Matrix, J, &pTwin1, &pTwin2 );
00202 SwapCols( Matrix, pTwin1, pTwin2 );
00203 Swapped = YES;
00204 }
00205 }
00206 }
00207 } while (AnotherPassNeeded);
00208 return;
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 static int
00223 CountTwins( MatrixPtr Matrix, int Col, ElementPtr *ppTwin1, ElementPtr *ppTwin2 )
00224 {
00225 int Row, Twins = 0;
00226 ElementPtr pTwin1, pTwin2;
00227
00228
00229
00230 pTwin1 = Matrix->FirstInCol[Col];
00231 while (pTwin1 != NULL)
00232 { if (ABS(pTwin1->Real) == 1.0)
00233 { Row = pTwin1->Row;
00234 pTwin2 = Matrix->FirstInCol[Row];
00235 while ((pTwin2 != NULL) AND (pTwin2->Row != Col))
00236 pTwin2 = pTwin2->NextInCol;
00237 if ((pTwin2 != NULL) AND (ABS(pTwin2->Real) == 1.0))
00238 {
00239 if (++Twins >= 2) return Twins;
00240 (*ppTwin1 = pTwin1)->Col = Col;
00241 (*ppTwin2 = pTwin2)->Col = Row;
00242 }
00243 }
00244 pTwin1 = pTwin1->NextInCol;
00245 }
00246 return Twins;
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 static int
00260 SwapCols( MatrixPtr Matrix, ElementPtr pTwin1, ElementPtr pTwin2 )
00261 {
00262 int Col1 = pTwin1->Col, Col2 = pTwin2->Col;
00263
00264
00265
00266 SWAP (ElementPtr, Matrix->FirstInCol[Col1], Matrix->FirstInCol[Col2]);
00267 SWAP (int, Matrix->IntToExtColMap[Col1], Matrix->IntToExtColMap[Col2]);
00268 #if TRANSLATE
00269 Matrix->ExtToIntColMap[Matrix->IntToExtColMap[Col2]]=Col2;
00270 Matrix->ExtToIntColMap[Matrix->IntToExtColMap[Col1]]=Col1;
00271 #endif
00272
00273 Matrix->Diag[Col1] = pTwin2;
00274 Matrix->Diag[Col2] = pTwin1;
00275 Matrix->NumberOfInterchangesIsOdd = NOT Matrix->NumberOfInterchangesIsOdd;
00276 return 0;
00277 }
00278 #endif
00279
00280 #if SCALING
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 extern void spcLinkRows(MatrixPtr Matrix);
00338
00339
00340 void
00341 spScale( eMatrix, RHS_ScaleFactors, SolutionScaleFactors )
00342
00343 char *eMatrix;
00344 register RealVector RHS_ScaleFactors, SolutionScaleFactors;
00345 {
00346 MatrixPtr Matrix = (MatrixPtr)eMatrix;
00347 register ElementPtr pElement;
00348 register int I, lSize, *pExtOrder;
00349 RealNumber ScaleFactor;
00350
00351
00352
00353 ASSERT( IS_VALID(Matrix) AND NOT Matrix->Factored );
00354 if (NOT Matrix->RowsLinked) spcLinkRows( Matrix );
00355
00356 #if spCOMPLEX
00357 if (Matrix->Complex)
00358 { ScaleComplexMatrix( Matrix, RHS_ScaleFactors, SolutionScaleFactors );
00359 return;
00360 }
00361 #endif
00362
00363 #if REAL
00364 lSize = Matrix->Size;
00365
00366
00367 #if NOT ARRAY_OFFSET
00368 --RHS_ScaleFactors;
00369 --SolutionScaleFactors;
00370 #endif
00371
00372
00373 pExtOrder = &Matrix->IntToExtRowMap[1];
00374 for (I = 1; I <= lSize; I++)
00375 { if ((ScaleFactor = RHS_ScaleFactors[*(pExtOrder++)]) != 1.0)
00376 { pElement = Matrix->FirstInRow[I];
00377
00378 while (pElement != NULL)
00379 { pElement->Real *= ScaleFactor;
00380 pElement = pElement->NextInRow;
00381 }
00382 }
00383 }
00384
00385
00386 pExtOrder = &Matrix->IntToExtColMap[1];
00387 for (I = 1; I <= lSize; I++)
00388 { if ((ScaleFactor = SolutionScaleFactors[*(pExtOrder++)]) != 1.0)
00389 { pElement = Matrix->FirstInCol[I];
00390
00391 while (pElement != NULL)
00392 { pElement->Real *= ScaleFactor;
00393 pElement = pElement->NextInCol;
00394 }
00395 }
00396 }
00397 return;
00398
00399 #endif
00400 }
00401 #endif
00402
00403 #if spCOMPLEX AND SCALING
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 static void
00461 ScaleComplexMatrix( MatrixPtr Matrix, register RealVector RHS_ScaleFactors, register RealVector SolutionScaleFactors )
00462 {
00463 register ElementPtr pElement;
00464 register int I, lSize, *pExtOrder;
00465 RealNumber ScaleFactor;
00466
00467
00468 lSize = Matrix->Size;
00469
00470
00471 #if NOT ARRAY_OFFSET
00472 --RHS_ScaleFactors;
00473 --SolutionScaleFactors;
00474 #endif
00475
00476
00477 pExtOrder = &Matrix->IntToExtRowMap[1];
00478 for (I = 1; I <= lSize; I++)
00479 { if ((ScaleFactor = RHS_ScaleFactors[*(pExtOrder++)]) != 1.0)
00480 { pElement = Matrix->FirstInRow[I];
00481
00482 while (pElement != NULL)
00483 { pElement->Real *= ScaleFactor;
00484 pElement->Imag *= ScaleFactor;
00485 pElement = pElement->NextInRow;
00486 }
00487 }
00488 }
00489
00490
00491 pExtOrder = &Matrix->IntToExtColMap[1];
00492 for (I = 1; I <= lSize; I++)
00493 { if ((ScaleFactor = SolutionScaleFactors[*(pExtOrder++)]) != 1.0)
00494 { pElement = Matrix->FirstInCol[I];
00495
00496 while (pElement != NULL)
00497 { pElement->Real *= ScaleFactor;
00498 pElement->Imag *= ScaleFactor;
00499 pElement = pElement->NextInCol;
00500 }
00501 }
00502 }
00503 return;
00504 }
00505 #endif
00506
00507 #if MULTIPLICATION
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 void
00540 spMultiply( eMatrix, RHS, Solution IMAG_VECTORS )
00541
00542 char *eMatrix;
00543 RealVector RHS, Solution IMAG_VECTORS;
00544 {
00545 register ElementPtr pElement;
00546 register RealVector Vector;
00547 register RealNumber Sum;
00548 register int I, *pExtOrder;
00549 MatrixPtr Matrix = (MatrixPtr)eMatrix;
00550
00551
00552 ASSERT( IS_SPARSE( Matrix ) AND NOT Matrix->Factored );
00553 if (NOT Matrix->RowsLinked) spcLinkRows(Matrix);
00554
00555 #if spCOMPLEX
00556 if (Matrix->Complex)
00557 { ComplexMatrixMultiply( Matrix, RHS, Solution IMAG_VECTORS );
00558 return;
00559 }
00560 #endif
00561
00562 #if REAL
00563 #if NOT ARRAY_OFFSET
00564
00565 --RHS;
00566 --Solution;
00567 #endif
00568
00569
00570 Vector = Matrix->Intermediate;
00571 pExtOrder = &Matrix->IntToExtColMap[Matrix->Size];
00572 for (I = Matrix->Size; I > 0; I--)
00573 Vector[I] = Solution[*(pExtOrder--)];
00574
00575 pExtOrder = &Matrix->IntToExtRowMap[Matrix->Size];
00576 for (I = Matrix->Size; I > 0; I--)
00577 { pElement = Matrix->FirstInRow[I];
00578 Sum = 0.0;
00579
00580 while (pElement != NULL)
00581 { Sum += pElement->Real * Vector[pElement->Col];
00582 pElement = pElement->NextInRow;
00583 }
00584 RHS[*pExtOrder--] = Sum;
00585 }
00586 return;
00587 #endif
00588 }
00589 #endif
00590
00591 #if spCOMPLEX AND MULTIPLICATION
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 static void
00627 ComplexMatrixMultiply( MatrixPtr Matrix, RealVector RHS , RealVector Solution IMAG_VECTORS )
00628 {
00629 register ElementPtr pElement;
00630 register ComplexVector Vector;
00631 register ComplexNumber Sum;
00632 register int I, *pExtOrder;
00633
00634
00635
00636
00637 #if NOT ARRAY_OFFSET
00638 #if spSEPARATED_COMPLEX_VECTORS
00639 --RHS; --iRHS;
00640 --Solution; --iSolution;
00641 #else
00642 RHS -= 2; Solution -= 2;
00643 #endif
00644 #endif
00645
00646
00647 Vector = (ComplexVector)Matrix->Intermediate;
00648 pExtOrder = &Matrix->IntToExtColMap[Matrix->Size];
00649
00650 #if spSEPARATED_COMPLEX_VECTORS
00651 for (I = Matrix->Size; I > 0; I--)
00652 { Vector[I].Real = Solution[*pExtOrder];
00653 Vector[I].Imag = iSolution[*(pExtOrder--)];
00654 }
00655 #else
00656 for (I = Matrix->Size; I > 0; I--)
00657 Vector[I] = ((ComplexVector)Solution)[*(pExtOrder--)];
00658 #endif
00659
00660 pExtOrder = &Matrix->IntToExtRowMap[Matrix->Size];
00661 for (I = Matrix->Size; I > 0; I--)
00662 { pElement = Matrix->FirstInRow[I];
00663 Sum.Real = Sum.Imag = 0.0;
00664
00665 while (pElement != NULL)
00666 {
00667 CMPLX_MULT_ADD_ASSIGN( Sum, *pElement, Vector[pElement->Col] );
00668 pElement = pElement->NextInRow;
00669 }
00670
00671 #if spSEPARATED_COMPLEX_VECTORS
00672 RHS[*pExtOrder] = Sum.Real;
00673 iRHS[*pExtOrder--] = Sum.Imag;
00674 #else
00675 ((ComplexVector)RHS)[*pExtOrder--] = Sum;
00676 #endif
00677 }
00678 return;
00679 }
00680 #endif
00681
00682 #if MULTIPLICATION AND TRANSPOSE
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 void
00715 spMultTransposed( eMatrix, RHS, Solution IMAG_VECTORS )
00716
00717 char *eMatrix;
00718 RealVector RHS, Solution IMAG_VECTORS;
00719 {
00720 register ElementPtr pElement;
00721 register RealVector Vector;
00722 register RealNumber Sum;
00723 register int I, *pExtOrder;
00724 MatrixPtr Matrix = (MatrixPtr)eMatrix;
00725
00726
00727
00728 ASSERT( IS_SPARSE( Matrix ) AND NOT Matrix->Factored );
00729
00730 #if spCOMPLEX
00731 if (Matrix->Complex)
00732 { ComplexTransposedMatrixMultiply( Matrix, RHS, Solution IMAG_VECTORS );
00733 return;
00734 }
00735 #endif
00736
00737 #if REAL
00738 #if NOT ARRAY_OFFSET
00739
00740 --RHS;
00741 --Solution;
00742 #endif
00743
00744
00745 Vector = Matrix->Intermediate;
00746 pExtOrder = &Matrix->IntToExtRowMap[Matrix->Size];
00747 for (I = Matrix->Size; I > 0; I--)
00748 Vector[I] = Solution[*(pExtOrder--)];
00749
00750 pExtOrder = &Matrix->IntToExtColMap[Matrix->Size];
00751 for (I = Matrix->Size; I > 0; I--)
00752 { pElement = Matrix->FirstInCol[I];
00753 Sum = 0.0;
00754
00755 while (pElement != NULL)
00756 { Sum += pElement->Real * Vector[pElement->Row];
00757 pElement = pElement->NextInCol;
00758 }
00759 RHS[*pExtOrder--] = Sum;
00760 }
00761 return;
00762 #endif
00763 }
00764 #endif
00765
00766 #if spCOMPLEX AND MULTIPLICATION AND TRANSPOSE
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801 static void
00802 ComplexTransposedMatrixMultiply( MatrixPtr Matrix, RealVector RHS, RealVector Solution IMAG_VECTORS )
00803 {
00804 register ElementPtr pElement;
00805 register ComplexVector Vector;
00806 register ComplexNumber Sum;
00807 register int I, *pExtOrder;
00808
00809
00810
00811
00812 #if NOT ARRAY_OFFSET
00813 #if spSEPARATED_COMPLEX_VECTORS
00814 --RHS; --iRHS;
00815 --Solution; --iSolution;
00816 #else
00817 RHS -= 2; Solution -= 2;
00818 #endif
00819 #endif
00820
00821
00822 Vector = (ComplexVector)Matrix->Intermediate;
00823 pExtOrder = &Matrix->IntToExtRowMap[Matrix->Size];
00824
00825 #if spSEPARATED_COMPLEX_VECTORS
00826 for (I = Matrix->Size; I > 0; I--)
00827 { Vector[I].Real = Solution[*pExtOrder];
00828 Vector[I].Imag = iSolution[*(pExtOrder--)];
00829 }
00830 #else
00831 for (I = Matrix->Size; I > 0; I--)
00832 Vector[I] = ((ComplexVector)Solution)[*(pExtOrder--)];
00833 #endif
00834
00835 pExtOrder = &Matrix->IntToExtColMap[Matrix->Size];
00836 for (I = Matrix->Size; I > 0; I--)
00837 { pElement = Matrix->FirstInCol[I];
00838 Sum.Real = Sum.Imag = 0.0;
00839
00840 while (pElement != NULL)
00841 {
00842 CMPLX_MULT_ADD_ASSIGN( Sum, *pElement, Vector[pElement->Row] );
00843 pElement = pElement->NextInCol;
00844 }
00845
00846 #if spSEPARATED_COMPLEX_VECTORS
00847 RHS[*pExtOrder] = Sum.Real;
00848 iRHS[*pExtOrder--] = Sum.Imag;
00849 #else
00850 ((ComplexVector)RHS)[*pExtOrder--] = Sum;
00851 #endif
00852 }
00853 return;
00854 }
00855 #endif
00856
00857 #if DETERMINANT
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898 #if spCOMPLEX
00899 void
00900 spDeterminant( char *eMatrix, int *pExponent, register RealNumber *pDeterminant, RealNumber *piDeterminant )
00901 #else
00902 void
00903 spDeterminant( char *eMatrix, int *pExponent, register RealNumber *pDeterminant )
00904 #endif
00905 {
00906 register MatrixPtr Matrix = (MatrixPtr)eMatrix;
00907 register int I, Size;
00908 RealNumber Norm, nr, ni;
00909 ComplexNumber Pivot, cDeterminant;
00910
00911 #define NORM(a) (nr = ABS((a).Real), ni = ABS((a).Imag), MAX (nr,ni))
00912
00913
00914 ASSERT( IS_SPARSE( Matrix ) AND IS_FACTORED(Matrix) );
00915 *pExponent = 0;
00916
00917 if (Matrix->Error == spSINGULAR)
00918 { *pDeterminant = 0.0;
00919 #if spCOMPLEX
00920 if (Matrix->Complex) *piDeterminant = 0.0;
00921 #endif
00922 return;
00923 }
00924
00925 Size = Matrix->Size;
00926 I = 0;
00927
00928 #if spCOMPLEX
00929 if (Matrix->Complex)
00930 { cDeterminant.Real = 1.0;
00931 cDeterminant.Imag = 0.0;
00932
00933 while (++I <= Size)
00934 { CMPLX_RECIPROCAL( Pivot, *Matrix->Diag[I] );
00935 CMPLX_MULT_ASSIGN( cDeterminant, Pivot );
00936
00937
00938 Norm = NORM( cDeterminant );
00939 if (Norm != 0.0)
00940 { while (Norm >= 1.0e12)
00941 { cDeterminant.Real *= 1.0e-12;
00942 cDeterminant.Imag *= 1.0e-12;
00943 *pExponent += 12;
00944 Norm = NORM( cDeterminant );
00945 }
00946 while (Norm < 1.0e-12)
00947 { cDeterminant.Real *= 1.0e12;
00948 cDeterminant.Imag *= 1.0e12;
00949 *pExponent -= 12;
00950 Norm = NORM( cDeterminant );
00951 }
00952 }
00953 }
00954
00955
00956 Norm = NORM( cDeterminant );
00957 if (Norm != 0.0)
00958 { while (Norm >= 10.0)
00959 { cDeterminant.Real *= 0.1;
00960 cDeterminant.Imag *= 0.1;
00961 (*pExponent)++;
00962 Norm = NORM( cDeterminant );
00963 }
00964 while (Norm < 1.0)
00965 { cDeterminant.Real *= 10.0;
00966 cDeterminant.Imag *= 10.0;
00967 (*pExponent)--;
00968 Norm = NORM( cDeterminant );
00969 }
00970 }
00971 if (Matrix->NumberOfInterchangesIsOdd)
00972 CMPLX_NEGATE( cDeterminant );
00973
00974 *pDeterminant = cDeterminant.Real;
00975 *piDeterminant = cDeterminant.Imag;
00976 }
00977 #endif
00978 #if REAL AND spCOMPLEX
00979 else
00980 #endif
00981 #if REAL
00982 {
00983 *pDeterminant = 1.0;
00984
00985 while (++I <= Size)
00986 { *pDeterminant /= Matrix->Diag[I]->Real;
00987
00988
00989 if (*pDeterminant != 0.0)
00990 { while (ABS(*pDeterminant) >= 1.0e12)
00991 { *pDeterminant *= 1.0e-12;
00992 *pExponent += 12;
00993 }
00994 while (ABS(*pDeterminant) < 1.0e-12)
00995 { *pDeterminant *= 1.0e12;
00996 *pExponent -= 12;
00997 }
00998 }
00999 }
01000
01001
01002 if (*pDeterminant != 0.0)
01003 { while (ABS(*pDeterminant) >= 10.0)
01004 { *pDeterminant *= 0.1;
01005 (*pExponent)++;
01006 }
01007 while (ABS(*pDeterminant) < 1.0)
01008 { *pDeterminant *= 10.0;
01009 (*pExponent)--;
01010 }
01011 }
01012 if (Matrix->NumberOfInterchangesIsOdd)
01013 *pDeterminant = -*pDeterminant;
01014 }
01015 #endif
01016 }
01017 #endif
01018
01019 #if STRIP
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044 void
01045 spStripFills( eMatrix )
01046
01047 char *eMatrix;
01048 {
01049 MatrixPtr Matrix = (MatrixPtr)eMatrix;
01050 struct FillinListNodeStruct *pListNode;
01051
01052
01053 ASSERT( IS_SPARSE( Matrix ) );
01054 if (Matrix->Fillins == 0) return;
01055 Matrix->NeedsOrdering = YES;
01056 Matrix->Elements -= Matrix->Fillins;
01057 Matrix->Fillins = 0;
01058
01059
01060 { register ElementPtr pFillin, pLastFillin;
01061
01062 pListNode = Matrix->LastFillinListNode = Matrix->FirstFillinListNode;
01063 Matrix->FillinsRemaining = pListNode->NumberOfFillinsInList;
01064 Matrix->NextAvailFillin = pListNode->pFillinList;
01065
01066 while (pListNode != NULL)
01067 { pFillin = pListNode->pFillinList;
01068 pLastFillin = &(pFillin[ pListNode->NumberOfFillinsInList - 1 ]);
01069 while (pFillin <= pLastFillin)
01070 (pFillin++)->Row = 0;
01071 pListNode = pListNode->Next;
01072 }
01073 }
01074
01075
01076 { register ElementPtr pElement, *ppElement;
01077 register int I, Size = Matrix->Size;
01078
01079
01080 for (I = 1; I <= Size; I++)
01081 { ppElement = &(Matrix->FirstInCol[I]);
01082 while ((pElement = *ppElement) != NULL)
01083 { if (pElement->Row == 0)
01084 { *ppElement = pElement->NextInCol;
01085 if (Matrix->Diag[pElement->Col] == pElement)
01086 Matrix->Diag[pElement->Col] = NULL;
01087 }
01088 else
01089 ppElement = &pElement->NextInCol;
01090 }
01091 }
01092
01093
01094 for (I = 1; I <= Size; I++)
01095 { ppElement = &(Matrix->FirstInRow[I]);
01096 while ((pElement = *ppElement) != NULL)
01097 { if (pElement->Row == 0)
01098 *ppElement = pElement->NextInRow;
01099 else
01100 ppElement = &pElement->NextInRow;
01101 }
01102 }
01103 }
01104 return;
01105 }
01106 #endif
01107
01108 #if TRANSLATE AND DELETE
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143 extern void spcRowExchange(MatrixPtr Matrix,int Row1,int Row2);
01144 extern void spcColExchange(MatrixPtr Matrix,int Col1,int Col2);
01145
01146 void spDeleteRowAndCol( char *eMatrix, int Row, int Col )
01147 {
01148 MatrixPtr Matrix = (MatrixPtr)eMatrix;
01149 register ElementPtr pElement, *ppElement, pLastElement;
01150 int Size, ExtRow, ExtCol;
01151 ElementPtr spcFindElementInCol();
01152
01153
01154
01155 ASSERT( IS_SPARSE(Matrix) AND Row > 0 AND Col > 0 );
01156 ASSERT( Row <= Matrix->ExtSize AND Col <= Matrix->ExtSize );
01157
01158 Size = Matrix->Size;
01159 ExtRow = Row;
01160 ExtCol = Col;
01161 if (NOT Matrix->RowsLinked) spcLinkRows( Matrix );
01162
01163 Row = Matrix->ExtToIntRowMap[Row];
01164 Col = Matrix->ExtToIntColMap[Col];
01165 ASSERT( Row > 0 AND Col > 0 );
01166
01167
01168 if (Row != Size) spcRowExchange( Matrix, Row, Size );
01169
01170
01171 if (Col != Size) spcColExchange( Matrix, Col, Size );
01172
01173
01174 if (Row == Col)
01175 SWAP( ElementPtr, Matrix->Diag[Row], Matrix->Diag[Size] )
01176 else
01177 { Matrix->Diag[Row] = spcFindElementInCol( Matrix, Matrix->FirstInCol+Row,
01178 Row, Row, NO );
01179 Matrix->Diag[Col] = spcFindElementInCol( Matrix, Matrix->FirstInCol+Col,
01180 Col, Col, NO );
01181 }
01182
01183
01184
01185
01186
01187 pLastElement = Matrix->FirstInRow[ Size ];
01188 while (pLastElement != NULL)
01189 { ppElement = &(Matrix->FirstInCol[ pLastElement->Col ]);
01190 while ((pElement = *ppElement) != NULL)
01191 { if (pElement == pLastElement)
01192 *ppElement = NULL;
01193 else
01194 ppElement = &pElement->NextInCol;
01195 }
01196 pLastElement = pLastElement->NextInRow;
01197 }
01198
01199
01200 pLastElement = Matrix->FirstInCol[ Size ];
01201 while (pLastElement != NULL)
01202 { ppElement = &(Matrix->FirstInRow[ pLastElement->Row ]);
01203 while ((pElement = *ppElement) != NULL)
01204 { if (pElement == pLastElement)
01205 *ppElement = NULL;
01206 else
01207 ppElement = &pElement->NextInRow;
01208 }
01209 pLastElement = pLastElement->NextInCol;
01210 }
01211
01212
01213 Matrix->Size = Size - 1;
01214 Matrix->Diag[Size] = NULL;
01215 Matrix->FirstInRow[Size] = NULL;
01216 Matrix->FirstInCol[Size] = NULL;
01217 Matrix->CurrentSize--;
01218 Matrix->ExtToIntRowMap[ExtRow] = -1;
01219 Matrix->ExtToIntColMap[ExtCol] = -1;
01220 Matrix->NeedsOrdering = YES;
01221
01222 return;
01223 }
01224 #endif
01225
01226 #if PSEUDOCONDITION
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251 RealNumber
01252 spPseudoCondition( eMatrix )
01253
01254 char *eMatrix;
01255 {
01256 MatrixPtr Matrix = (MatrixPtr)eMatrix;
01257 register int I;
01258 register ArrayOfElementPtrs Diag;
01259 RealNumber MaxPivot, MinPivot, Mag;
01260
01261
01262
01263 ASSERT( IS_SPARSE(Matrix) AND IS_FACTORED(Matrix) );
01264 if (Matrix->Error == spSINGULAR OR Matrix->Error == spZERO_DIAG)
01265 return 0.0;
01266
01267 Diag = Matrix->Diag;
01268 MaxPivot = MinPivot = ELEMENT_MAG( Diag[1] );
01269 for (I = 2; I <= Matrix->Size; I++)
01270 { Mag = ELEMENT_MAG( Diag[I] );
01271 if (Mag > MaxPivot)
01272 MaxPivot = Mag;
01273 else if (Mag < MinPivot)
01274 MinPivot = Mag;
01275 }
01276 ASSERT( MaxPivot > 0.0);
01277 return MaxPivot / MinPivot;
01278 }
01279 #endif
01280
01281 #if CONDITION
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335 RealNumber
01336 spCondition( eMatrix, NormOfMatrix, pError )
01337
01338 char *eMatrix;
01339 RealNumber NormOfMatrix;
01340 int *pError;
01341 {
01342 MatrixPtr Matrix = (MatrixPtr)eMatrix;
01343 register ElementPtr pElement;
01344 register RealVector T, Tm;
01345 register int I, K, Row;
01346 ElementPtr pPivot;
01347 int Size;
01348 RealNumber E, Em, Wp, Wm, ASp, ASm, ASw, ASy, ASv, ASz, MaxY, ScaleFactor;
01349 RealNumber Linpack, OLeary, InvNormOfInverse;
01350 #define SLACK 1e4
01351
01352
01353
01354 ASSERT( IS_SPARSE(Matrix) AND IS_FACTORED(Matrix) );
01355 *pError = Matrix->Error;
01356 if (Matrix->Error >= spFATAL) return 0.0;
01357 if (NormOfMatrix == 0.0)
01358 { *pError = spSINGULAR;
01359 return 0.0;
01360 }
01361
01362 #if spCOMPLEX
01363 if (Matrix->Complex)
01364 return ComplexCondition( Matrix, NormOfMatrix, pError );
01365 #endif
01366
01367 #if REAL
01368 Size = Matrix->Size;
01369 T = Matrix->Intermediate;
01370 #if spCOMPLEX
01371 Tm = Matrix->Intermediate + Size;
01372 #else
01373 Tm = SPALLOC( RealNumber, Size+1 );
01374 if (Tm == NULL)
01375 { *pError = spNO_MEMORY;
01376 return 0.0;
01377 }
01378 #endif
01379 for (I = Size; I > 0; I--) T[I] = 0.0;
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389 E = 1.0;
01390 for (I = 1; I <= Size; I++)
01391 { pPivot = Matrix->Diag[I];
01392 if (T[I] < 0.0) Em = -E; else Em = E;
01393 Wm = (Em + T[I]) * pPivot->Real;
01394 if (ABS(Wm) > SLACK)
01395 { ScaleFactor = 1.0 / MAX( SQR( SLACK ), ABS(Wm) );
01396 for (K = Size; K > 0; K--) T[K] *= ScaleFactor;
01397 E *= ScaleFactor;
01398 Em *= ScaleFactor;
01399 Wm = (Em + T[I]) * pPivot->Real;
01400 }
01401 Wp = (T[I] - Em) * pPivot->Real;
01402 ASp = ABS(T[I] - Em);
01403 ASm = ABS(Em + T[I]);
01404
01405
01406 pElement = pPivot->NextInCol;
01407 while (pElement != NULL)
01408 { Row = pElement->Row;
01409 Tm[Row] = T[Row] - (Wm * pElement->Real);
01410 T[Row] -= (Wp * pElement->Real);
01411 ASp += ABS(T[Row]);
01412 ASm += ABS(Tm[Row]);
01413 pElement = pElement->NextInCol;
01414 }
01415
01416
01417 if (ASm > ASp)
01418 { T[I] = Wm;
01419 pElement = pPivot->NextInCol;
01420 while (pElement != NULL)
01421 { T[pElement->Row] = Tm[pElement->Row];
01422 pElement = pElement->NextInCol;
01423 }
01424 }
01425 else T[I] = Wp;
01426 }
01427
01428
01429 for (ASw = 0.0, I = Size; I > 0; I--) ASw += ABS(T[I]);
01430 ScaleFactor = 1.0 / (SLACK * ASw);
01431 if (ScaleFactor < 0.5)
01432 { for (I = Size; I > 0; I--) T[I] *= ScaleFactor;
01433 E *= ScaleFactor;
01434 }
01435
01436
01437 for (I = Size; I >= 1; I--)
01438 { pElement = Matrix->Diag[I]->NextInRow;
01439 while (pElement != NULL)
01440 { T[I] -= pElement->Real * T[pElement->Col];
01441 pElement = pElement->NextInRow;
01442 }
01443 if (ABS(T[I]) > SLACK)
01444 { ScaleFactor = 1.0 / MAX( SQR( SLACK ), ABS(T[I]) );
01445 for (K = Size; K > 0; K--) T[K] *= ScaleFactor;
01446 E *= ScaleFactor;
01447 }
01448 }
01449
01450
01451 for (ASy = 0.0, I = Size; I > 0; I--) ASy += ABS(T[I]);
01452 ScaleFactor = 1.0 / (SLACK * ASy);
01453 if (ScaleFactor < 0.5)
01454 { for (I = Size; I > 0; I--) T[I] *= ScaleFactor;
01455 ASy = 1.0 / SLACK;
01456 E *= ScaleFactor;
01457 }
01458
01459
01460 for (MaxY = 0.0, I = Size; I > 0; I--)
01461 if (MaxY < ABS(T[I])) MaxY = ABS(T[I]);
01462
01463
01464
01465
01466
01467
01468
01469 for (I = 1; I <= Size; I++)
01470 { pElement = Matrix->Diag[I]->NextInRow;
01471 while (pElement != NULL)
01472 { T[pElement->Col] -= T[I] * pElement->Real;
01473 pElement = pElement->NextInRow;
01474 }
01475 if (ABS(T[I]) > SLACK)
01476 { ScaleFactor = 1.0 / MAX( SQR( SLACK ), ABS(T[I]) );
01477 for (K = Size; K > 0; K--) T[K] *= ScaleFactor;
01478 ASy *= ScaleFactor;
01479 }
01480 }
01481
01482
01483 for (ASv = 0.0, I = Size; I > 0; I--) ASv += ABS(T[I]);
01484 ScaleFactor = 1.0 / (SLACK * ASv);
01485 if (ScaleFactor < 0.5)
01486 { for (I = Size; I > 0; I--) T[I] *= ScaleFactor;
01487 ASy *= ScaleFactor;
01488 }
01489
01490
01491 for (I = Size; I >= 1; I--)
01492 { pPivot = Matrix->Diag[I];
01493 pElement = pPivot->NextInCol;
01494 while (pElement != NULL)
01495 { T[I] -= pElement->Real * T[pElement->Row];
01496 pElement = pElement->NextInCol;
01497 }
01498 T[I] *= pPivot->Real;
01499 if (ABS(T[I]) > SLACK)
01500 { ScaleFactor = 1.0 / MAX( SQR( SLACK ), ABS(T[I]) );
01501 for (K = Size; K > 0; K--) T[K] *= ScaleFactor;
01502 ASy *= ScaleFactor;
01503 }
01504 }
01505
01506
01507 for (ASz = 0.0, I = Size; I > 0; I--) ASz += ABS(T[I]);
01508
01509 #if NOT spCOMPLEX
01510 SPFREE( Tm );
01511 #endif
01512
01513 Linpack = ASy / ASz;
01514 OLeary = E / MaxY;
01515 InvNormOfInverse = MIN( Linpack, OLeary );
01516 return InvNormOfInverse / NormOfMatrix;
01517 #endif
01518 }
01519
01520 #if spCOMPLEX
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542 static RealNumber
01543 ComplexCondition( MatrixPtr Matrix, RealNumber NormOfMatrix, int *pError )
01544 {
01545 register ElementPtr pElement;
01546 register ComplexVector T, Tm;
01547 register int I, K, Row;
01548 ElementPtr pPivot;
01549 int Size;
01550 RealNumber E, Em, ASp, ASm, ASw, ASy, ASv, ASz, MaxY, ScaleFactor;
01551 RealNumber Linpack, OLeary, InvNormOfInverse;
01552 ComplexNumber Wp, Wm;
01553
01554
01555
01556 Size = Matrix->Size;
01557 T = (ComplexVector)Matrix->Intermediate;
01558 Tm = SPALLOC( ComplexNumber, Size+1 );
01559 if (Tm == NULL)
01560 { *pError = spNO_MEMORY;
01561 return 0.0;
01562 }
01563 for (I = Size; I > 0; I--) T[I].Real = T[I].Imag = 0.0;
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573 E = 1.0;
01574 for (I = 1; I <= Size; I++)
01575 { pPivot = Matrix->Diag[I];
01576 if (T[I].Real < 0.0) Em = -E; else Em = E;
01577 Wm = T[I];
01578 Wm.Real += Em;
01579 ASm = CMPLX_1_NORM( Wm );
01580 CMPLX_MULT_ASSIGN( Wm, *pPivot );
01581 if (CMPLX_1_NORM(Wm) > SLACK)
01582 { ScaleFactor = 1.0 / MAX( SQR( SLACK ), CMPLX_1_NORM(Wm) );
01583 for (K = Size; K > 0; K--) SCLR_MULT_ASSIGN( T[K], ScaleFactor );
01584 E *= ScaleFactor;
01585 Em *= ScaleFactor;
01586 ASm *= ScaleFactor;
01587 SCLR_MULT_ASSIGN( Wm, ScaleFactor );
01588 }
01589 Wp = T[I];
01590 Wp.Real -= Em;
01591 ASp = CMPLX_1_NORM( Wp );
01592 CMPLX_MULT_ASSIGN( Wp, *pPivot );
01593
01594
01595 pElement = pPivot->NextInCol;
01596 while (pElement != NULL)
01597 { Row = pElement->Row;
01598
01599 CMPLX_MULT_SUBT( Tm[Row], Wm, *pElement, T[Row] );
01600
01601 CMPLX_MULT_SUBT_ASSIGN( T[Row], Wm, *pElement );
01602 ASp += CMPLX_1_NORM(T[Row]);
01603 ASm += CMPLX_1_NORM(Tm[Row]);
01604 pElement = pElement->NextInCol;
01605 }
01606
01607
01608 if (ASm > ASp)
01609 { T[I] = Wm;
01610 pElement = pPivot->NextInCol;
01611 while (pElement != NULL)
01612 { T[pElement->Row] = Tm[pElement->Row];
01613 pElement = pElement->NextInCol;
01614 }
01615 }
01616 else T[I] = Wp;
01617 }
01618
01619
01620 for (ASw = 0.0, I = Size; I > 0; I--) ASw += CMPLX_1_NORM(T[I]);
01621 ScaleFactor = 1.0 / (SLACK * ASw);
01622 if (ScaleFactor < 0.5)
01623 { for (I = Size; I > 0; I--) SCLR_MULT_ASSIGN( T[I], ScaleFactor );
01624 E *= ScaleFactor;
01625 }
01626
01627
01628 for (I = Size; I >= 1; I--)
01629 { pElement = Matrix->Diag[I]->NextInRow;
01630 while (pElement != NULL)
01631 {
01632 CMPLX_MULT_SUBT_ASSIGN( T[I], T[pElement->Col], *pElement );
01633 pElement = pElement->NextInRow;
01634 }
01635 if (CMPLX_1_NORM(T[I]) > SLACK)
01636 { ScaleFactor = 1.0 / MAX( SQR( SLACK ), CMPLX_1_NORM(T[I]) );
01637 for (K = Size; K > 0; K--) SCLR_MULT_ASSIGN( T[K], ScaleFactor );
01638 E *= ScaleFactor;
01639 }
01640 }
01641
01642
01643 for (ASy = 0.0, I = Size; I > 0; I--) ASy += CMPLX_1_NORM(T[I]);
01644 ScaleFactor = 1.0 / (SLACK * ASy);
01645 if (ScaleFactor < 0.5)
01646 { for (I = Size; I > 0; I--) SCLR_MULT_ASSIGN( T[I], ScaleFactor );
01647 ASy = 1.0 / SLACK;
01648 E *= ScaleFactor;
01649 }
01650
01651
01652 for (MaxY = 0.0, I = Size; I > 0; I--)
01653 if (MaxY < CMPLX_1_NORM(T[I])) MaxY = CMPLX_1_NORM(T[I]);
01654
01655
01656
01657
01658
01659
01660
01661 for (I = 1; I <= Size; I++)
01662 { pElement = Matrix->Diag[I]->NextInRow;
01663 while (pElement != NULL)
01664 {
01665 CMPLX_MULT_SUBT_ASSIGN( T[pElement->Col], T[I], *pElement );
01666 pElement = pElement->NextInRow;
01667 }
01668 if (CMPLX_1_NORM(T[I]) > SLACK)
01669 { ScaleFactor = 1.0 / MAX( SQR( SLACK ), CMPLX_1_NORM(T[I]) );
01670 for (K = Size; K > 0; K--) SCLR_MULT_ASSIGN( T[K], ScaleFactor );
01671 ASy *= ScaleFactor;
01672 }
01673 }
01674
01675
01676 for (ASv = 0.0, I = Size; I > 0; I--) ASv += CMPLX_1_NORM(T[I]);
01677 ScaleFactor = 1.0 / (SLACK * ASv);
01678 if (ScaleFactor < 0.5)
01679 { for (I = Size; I > 0; I--) SCLR_MULT_ASSIGN( T[I], ScaleFactor );
01680 ASy *= ScaleFactor;
01681 }
01682
01683
01684 for (I = Size; I >= 1; I--)
01685 { pPivot = Matrix->Diag[I];
01686 pElement = pPivot->NextInCol;
01687 while (pElement != NULL)
01688 {
01689 CMPLX_MULT_SUBT_ASSIGN( T[I], T[pElement->Row], *pElement );
01690 pElement = pElement->NextInCol;
01691 }
01692 CMPLX_MULT_ASSIGN( T[I], *pPivot );
01693 if (CMPLX_1_NORM(T[I]) > SLACK)
01694 { ScaleFactor = 1.0 / MAX( SQR( SLACK ), CMPLX_1_NORM(T[I]) );
01695 for (K = Size; K > 0; K--) SCLR_MULT_ASSIGN( T[K], ScaleFactor );
01696 ASy *= ScaleFactor;
01697 }
01698 }
01699
01700
01701 for (ASz = 0.0, I = Size; I > 0; I--) ASz += CMPLX_1_NORM(T[I]);
01702
01703 SPFREE( Tm );
01704
01705 Linpack = ASy / ASz;
01706 OLeary = E / MaxY;
01707 InvNormOfInverse = MIN( Linpack, OLeary );
01708 return InvNormOfInverse / NormOfMatrix;
01709 }
01710 #endif
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728 RealNumber
01729 spNorm( eMatrix )
01730
01731 char *eMatrix;
01732 {
01733 MatrixPtr Matrix = (MatrixPtr)eMatrix;
01734 register ElementPtr pElement;
01735 register int I;
01736 RealNumber Max = 0.0, AbsRowSum;
01737
01738
01739 ASSERT( IS_SPARSE(Matrix) AND NOT IS_FACTORED(Matrix) );
01740 if (NOT Matrix->RowsLinked) spcLinkRows( Matrix );
01741
01742
01743 #if REAL
01744 if (NOT Matrix->Complex)
01745 { for (I = Matrix->Size; I > 0; I--)
01746 { pElement = Matrix->FirstInRow[I];
01747 AbsRowSum = 0.0;
01748 while (pElement != NULL)
01749 { AbsRowSum += ABS( pElement->Real );
01750 pElement = pElement->NextInRow;
01751 }
01752 if (Max < AbsRowSum) Max = AbsRowSum;
01753 }
01754 }
01755 #endif
01756 #if spCOMPLEX
01757 if (Matrix->Complex)
01758 { for (I = Matrix->Size; I > 0; I--)
01759 { pElement = Matrix->FirstInRow[I];
01760 AbsRowSum = 0.0;
01761 while (pElement != NULL)
01762 { AbsRowSum += CMPLX_1_NORM( *pElement );
01763 pElement = pElement->NextInRow;
01764 }
01765 if (Max < AbsRowSum) Max = AbsRowSum;
01766 }
01767 }
01768 #endif
01769 return Max;
01770 }
01771 #endif
01772
01773 #if STABILITY
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840 RealNumber
01841 spLargestElement( eMatrix )
01842
01843 char *eMatrix;
01844 {
01845 MatrixPtr Matrix = (MatrixPtr)eMatrix;
01846 register int I;
01847 RealNumber Mag, AbsColSum, Max = 0.0, MaxRow = 0.0, MaxCol = 0.0;
01848 RealNumber Pivot;
01849 ComplexNumber cPivot;
01850 register ElementPtr pElement, pDiag;
01851
01852
01853 ASSERT( IS_SPARSE(Matrix) );
01854
01855 #if REAL
01856 if (Matrix->Factored AND NOT Matrix->Complex)
01857 { if (Matrix->Error == spSINGULAR) return 0.0;
01858
01859
01860 for (I = 1; I <= Matrix->Size; I++)
01861 { pDiag = Matrix->Diag[I];
01862
01863
01864 Pivot = 1.0 / pDiag->Real;
01865 Mag = ABS( Pivot );
01866 if (Mag > MaxRow) MaxRow = Mag;
01867 pElement = Matrix->FirstInRow[I];
01868 while (pElement != pDiag)
01869 { Mag = ABS( pElement->Real );
01870 if (Mag > MaxRow) MaxRow = Mag;
01871 pElement = pElement->NextInRow;
01872 }
01873
01874
01875 pElement = Matrix->FirstInCol[I];
01876 AbsColSum = 1.0;
01877 while (pElement != pDiag)
01878 { AbsColSum += ABS( pElement->Real );
01879 pElement = pElement->NextInCol;
01880 }
01881 if (AbsColSum > MaxCol) MaxCol = AbsColSum;
01882 }
01883 }
01884 else if (NOT Matrix->Complex)
01885 { for (I = 1; I <= Matrix->Size; I++)
01886 { pElement = Matrix->FirstInCol[I];
01887 while (pElement != NULL)
01888 { Mag = ABS( pElement->Real );
01889 if (Mag > Max) Max = Mag;
01890 pElement = pElement->NextInCol;
01891 }
01892 }
01893 return Max;
01894 }
01895 #endif
01896 #if spCOMPLEX
01897 if (Matrix->Factored AND Matrix->Complex)
01898 { if (Matrix->Error == spSINGULAR) return 0.0;
01899
01900
01901 for (I = 1; I <= Matrix->Size; I++)
01902 { pDiag = Matrix->Diag[I];
01903
01904
01905 CMPLX_RECIPROCAL( cPivot, *pDiag );
01906 Mag = CMPLX_1_NORM( cPivot );
01907 if (Mag > MaxRow) MaxRow = Mag;
01908 pElement = Matrix->FirstInRow[I];
01909 while (pElement != pDiag)
01910 { Mag = CMPLX_1_NORM( *pElement );
01911 if (Mag > MaxRow) MaxRow = Mag;
01912 pElement = pElement->NextInRow;
01913 }
01914
01915
01916 pElement = Matrix->FirstInCol[I];
01917 AbsColSum = 1.0;
01918 while (pElement != pDiag)
01919 { AbsColSum += CMPLX_1_NORM( *pElement );
01920 pElement = pElement->NextInCol;
01921 }
01922 if (AbsColSum > MaxCol) MaxCol = AbsColSum;
01923 }
01924 }
01925 else if (Matrix->Complex)
01926 { for (I = 1; I <= Matrix->Size; I++)
01927 { pElement = Matrix->FirstInCol[I];
01928 while (pElement != NULL)
01929 { Mag = CMPLX_1_NORM( *pElement );
01930 if (Mag > Max) Max = Mag;
01931 pElement = pElement->NextInCol;
01932 }
01933 }
01934 return Max;
01935 }
01936 #endif
01937 return MaxRow * MaxCol;
01938 }
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959 RealNumber
01960 spRoundoff( eMatrix, Rho )
01961
01962 char *eMatrix;
01963 RealNumber Rho;
01964 {
01965 MatrixPtr Matrix = (MatrixPtr)eMatrix;
01966 register ElementPtr pElement;
01967 register int Count, I, MaxCount = 0;
01968 RealNumber Reid, Gear;
01969
01970
01971 ASSERT( IS_SPARSE(Matrix) AND IS_FACTORED(Matrix) );
01972
01973
01974 if (Rho < 0.0) Rho = spLargestElement( eMatrix );
01975
01976
01977 if (Matrix->MaxRowCountInLowerTri < 0)
01978 { for (I = Matrix->Size; I > 0; I--)
01979 { pElement = Matrix->FirstInRow[I];
01980 Count = 0;
01981 while (pElement->Col < I)
01982 { Count++;
01983 pElement = pElement->NextInRow;
01984 }
01985 if (Count > MaxCount) MaxCount = Count;
01986 }
01987 Matrix->MaxRowCountInLowerTri = MaxCount;
01988 }
01989 else MaxCount = Matrix->MaxRowCountInLowerTri;
01990
01991
01992 Gear = 1.01*((MaxCount + 1) * Matrix->RelThreshold + 1.0) * SQR(MaxCount);
01993 Reid = 3.01 * Matrix->Size;
01994
01995 if (Gear < Reid)
01996 return (MACHINE_RESOLUTION * Rho * Gear);
01997 else
01998 return (MACHINE_RESOLUTION * Rho * Reid);
01999 }
02000 #endif