00001 /* 00002 * MATRIX SOLVE MODULE 00003 * 00004 * Author: Advising professor: 00005 * Kenneth S. Kundert Alberto Sangiovanni-Vincentelli 00006 * UC Berkeley 00007 * 00008 * This file contains the forward and backward substitution routines for 00009 * the sparse matrix routines. 00010 * 00011 * >>> User accessible functions contained in this file: 00012 * spSolve 00013 * spSolveTransposed 00014 * 00015 * >>> Other functions contained in this file: 00016 * SolveComplexMatrix 00017 * SolveComplexTransposedMatrix 00018 */ 00019 00020 00021 /* 00022 * Revision and copyright information. 00023 * 00024 * Copyright (c) 1985,86,87,88 00025 * by Kenneth S. Kundert and the University of California. 00026 * 00027 * Permission to use, copy, modify, and distribute this software and 00028 * its documentation for any purpose and without fee is hereby granted, 00029 * provided that the copyright notices appear in all copies and 00030 * supporting documentation and that the authors and the University of 00031 * California are properly credited. The authors and the University of 00032 * California make no representations as to the suitability of this 00033 * software for any purpose. It is provided `as is', without express 00034 * or implied warranty. 00035 */ 00036 00037 00038 /* 00039 * IMPORTS 00040 * 00041 * >>> Import descriptions: 00042 * spConfig.h 00043 * Macros that customize the sparse matrix routines. 00044 * spmatrix.h 00045 * Macros and declarations to be imported by the user. 00046 * spDefs.h 00047 * Matrix type and macro definitions for the sparse matrix routines. 00048 */ 00049 00050 #define spINSIDE_SPARSE 00051 #include "spSolve.h" 00052 00053 /* 00054 * SOLVE MATRIX EQUATION 00055 * 00056 * Performs forward elimination and back substitution to find the 00057 * unknown vector from the RHS vector and factored matrix. This 00058 * routine assumes that the pivots are associated with the lower 00059 * triangular (L) matrix and that the diagonal of the upper triangular 00060 * (U) matrix consists of ones. This routine arranges the computation 00061 * in different way than is traditionally used in order to exploit the 00062 * sparsity of the right-hand side. See the reference in spRevision. 00063 * 00064 * >>> Arguments: 00065 * Matrix <input> (char *) 00066 * Pointer to matrix. 00067 * RHS <input> (RealVector) 00068 * RHS is the input data array, the right hand side. This data is 00069 * undisturbed and may be reused for other solves. 00070 * Solution <output> (RealVector) 00071 * Solution is the output data array. This routine is constructed such that 00072 * RHS and Solution can be the same array. 00073 * iRHS <input> (RealVector) 00074 * iRHS is the imaginary portion of the input data array, the right 00075 * hand side. This data is undisturbed and may be reused for other solves. 00076 * This argument is only necessary if matrix is complex and if 00077 * spSEPARATED_COMPLEX_VECTOR is set true. 00078 * iSolution <output> (RealVector) 00079 * iSolution is the imaginary portion of the output data array. This 00080 * routine is constructed such that iRHS and iSolution can be 00081 * the same array. This argument is only necessary if matrix is complex 00082 * and if spSEPARATED_COMPLEX_VECTOR is set true. 00083 * 00084 * >>> Local variables: 00085 * Intermediate (RealVector) 00086 * Temporary storage for use in forward elimination and backward 00087 * substitution. Commonly referred to as c, when the LU factorization 00088 * equations are given as Ax = b, Lc = b, Ux = c Local version of 00089 * Matrix->Intermediate, which was created during the initial 00090 * factorization in function CreateInternalVectors() in the matrix 00091 * factorization module. 00092 * pElement (ElementPtr) 00093 * Pointer used to address elements in both the lower and upper triangle 00094 * matrices. 00095 * pExtOrder (int *) 00096 * Pointer used to sequentially access each entry in IntToExtRowMap 00097 * and IntToExtColMap arrays. Used to quickly scramble and unscramble 00098 * RHS and Solution to account for row and column interchanges. 00099 * pPivot (ElementPtr) 00100 * Pointer that points to current pivot or diagonal element. 00101 * Size (int) 00102 * Size of matrix. Made local to reduce indirection. 00103 * Temp (RealNumber) 00104 * Temporary storage for entries in arrays. 00105 * 00106 * >>> Obscure Macros 00107 * IMAG_VECTORS 00108 * Replaces itself with `, iRHS, iSolution' if the options spCOMPLEX and 00109 * spSEPARATED_COMPLEX_VECTORS are set, otherwise it disappears 00110 * without a trace. 00111 */ 00112 00113 /*VARARGS3*/ 00114 00115 void 00116 spSolve( eMatrix, RHS, Solution IMAG_VECTORS ) 00117 00118 char *eMatrix; 00119 RealVector RHS, Solution IMAG_VECTORS; 00120 { 00121 MatrixPtr Matrix = (MatrixPtr)eMatrix; 00122 register ElementPtr pElement; 00123 register RealVector Intermediate; 00124 register RealNumber Temp; 00125 register int I, *pExtOrder, Size; 00126 ElementPtr pPivot; 00127 00128 /* Begin `spSolve'. */ 00129 ASSERT( IS_VALID(Matrix) AND IS_FACTORED(Matrix) ); 00130 00131 #if spCOMPLEX 00132 if (Matrix->Complex) 00133 { SolveComplexMatrix( Matrix, RHS, Solution IMAG_VECTORS ); 00134 return; 00135 } 00136 #endif 00137 00138 #if REAL 00139 Intermediate = Matrix->Intermediate; 00140 Size = Matrix->Size; 00141 00142 /* Correct array pointers for ARRAY_OFFSET. */ 00143 #if NOT ARRAY_OFFSET 00144 --RHS; 00145 --Solution; 00146 #endif 00147 00148 /* Initialize Intermediate vector. */ 00149 pExtOrder = &Matrix->IntToExtRowMap[Size]; 00150 for (I = Size; I > 0; I--) 00151 Intermediate[I] = RHS[*(pExtOrder--)]; 00152 00153 /* Forward elimination. Solves Lc = b.*/ 00154 for (I = 1; I <= Size; I++) 00155 { 00156 00157 /* This step of the elimination is skipped if Temp equals zero. */ 00158 if ((Temp = Intermediate[I]) != 0.0) 00159 { 00160 pPivot = Matrix->Diag[I]; 00161 if ( pPivot != 0 && ELEMENT_MAG(pPivot) > Matrix->AbsThreshold ) 00162 { 00163 /*jpc Intermediate[I] = (Temp *= pPivot->Real);*/ 00164 Intermediate[I] = (Temp /= pPivot->Real); 00165 00166 pElement = pPivot->NextInCol; 00167 while (pElement != NULL) 00168 { Intermediate[pElement->Row] -= Temp * pElement->Real; 00169 pElement = pElement->NextInCol; 00170 } 00171 } 00172 else 00173 Intermediate[I]= 0.0; 00174 } 00175 } 00176 00177 /* Backward Substitution. Solves Ux = c.*/ 00178 /* modification for singular matrix a diagonal element can be a null pointer */ 00179 00180 for (I = Size ; I > 0; I--) 00181 { Temp = Intermediate[I]; 00182 if ( Matrix->Diag[I] == 0) /* test for nul pointer */ 00183 { 00184 Intermediate[I]=0.0; 00185 } 00186 else 00187 { 00188 pElement = Matrix->Diag[I]->NextInRow; 00189 while (pElement != NULL) 00190 { Temp -= pElement->Real * Intermediate[pElement->Col]; 00191 pElement = pElement->NextInRow; 00192 } 00193 Intermediate[I] = Temp; 00194 } 00195 } 00196 00197 /* Unscramble Intermediate vector while placing data in to Solution vector. */ 00198 pExtOrder = &Matrix->IntToExtColMap[Size]; 00199 for (I = Size; I > 0; I--) 00200 Solution[*(pExtOrder--)] = Intermediate[I]; 00201 00202 return; 00203 #endif /* REAL */ 00204 } 00205 00206 00207 00208 00209 00210 00211 00212 00213 00214 00215 00216 #if spCOMPLEX 00217 /* 00218 * SOLVE COMPLEX MATRIX EQUATION 00219 * 00220 * Performs forward elimination and back substitution to find the 00221 * unknown vector from the RHS vector and factored matrix. This 00222 * routine assumes that the pivots are associated with the lower 00223 * triangular (L) matrix and that the diagonal of the upper triangular 00224 * (U) matrix consists of ones. This routine arranges the computation 00225 * in different way than is traditionally used in order to exploit the 00226 * sparsity of the right-hand side. See the reference in spRevision. 00227 * 00228 * >>> Arguments: 00229 * Matrix <input> (char *) 00230 * Pointer to matrix. 00231 * RHS <input> (RealVector) 00232 * RHS is the real portion of the input data array, the right hand 00233 * side. This data is undisturbed and may be reused for other solves. 00234 * Solution <output> (RealVector) 00235 * Solution is the real portion of the output data array. This routine 00236 * is constructed such that RHS and Solution can be the same 00237 * array. 00238 * iRHS <input> (RealVector) 00239 * iRHS is the imaginary portion of the input data array, the right 00240 * hand side. This data is undisturbed and may be reused for other solves. 00241 * If spSEPARATED_COMPLEX_VECTOR is set false, there is no need to 00242 * supply this array. 00243 * iSolution <output> (RealVector) 00244 * iSolution is the imaginary portion of the output data array. This 00245 * routine is constructed such that iRHS and iSolution can be 00246 * the same array. If spSEPARATED_COMPLEX_VECTOR is set false, there is no 00247 * need to supply this array. 00248 * 00249 * >>> Local variables: 00250 * Intermediate (ComplexVector) 00251 * Temporary storage for use in forward elimination and backward 00252 * substitution. Commonly referred to as c, when the LU factorization 00253 * equations are given as Ax = b, Lc = b, Ux = c. 00254 * Local version of Matrix->Intermediate, which was created during 00255 * the initial factorization in function CreateInternalVectors() in the 00256 * matrix factorization module. 00257 * pElement (ElementPtr) 00258 * Pointer used to address elements in both the lower and upper triangle 00259 * matrices. 00260 * pExtOrder (int *) 00261 * Pointer used to sequentially access each entry in IntToExtRowMap 00262 * and IntToExtColMap arrays. Used to quickly scramble and unscramble 00263 * RHS and Solution to account for row and column interchanges. 00264 * pPivot (ElementPtr) 00265 * Pointer that points to current pivot or diagonal element. 00266 * Size (int) 00267 * Size of matrix. Made local to reduce indirection. 00268 * Temp (ComplexNumber) 00269 * Temporary storage for entries in arrays. 00270 * 00271 * >>> Obscure Macros 00272 * IMAG_VECTORS 00273 * Replaces itself with `, iRHS, iSolution' if the options spCOMPLEX and 00274 * spSEPARATED_COMPLEX_VECTORS are set, otherwise it disappears 00275 * without a trace. 00276 */ 00277 00278 static void 00279 SolveComplexMatrix( MatrixPtr Matrix, RealVector RHS, RealVector Solution IMAG_VECTORS ) 00280 { 00281 register ElementPtr pElement; 00282 register ComplexVector Intermediate; 00283 register int I, *pExtOrder, Size; 00284 ElementPtr pPivot; 00285 register ComplexVector ExtVector; 00286 ComplexNumber Temp; 00287 00288 /* Begin `SolveComplexMatrix'. */ 00289 00290 Size = Matrix->Size; 00291 Intermediate = (ComplexVector)Matrix->Intermediate; 00292 00293 /* Correct array pointers for ARRAY_OFFSET. */ 00294 #if NOT ARRAY_OFFSET 00295 #if spSEPARATED_COMPLEX_VECTORS 00296 --RHS; --iRHS; 00297 --Solution; --iSolution; 00298 #else 00299 RHS -= 2; Solution -= 2; 00300 #endif 00301 #endif 00302 00303 /* Initialize Intermediate vector. */ 00304 pExtOrder = &Matrix->IntToExtRowMap[Size]; 00305 00306 #if spSEPARATED_COMPLEX_VECTORS 00307 for (I = Size; I > 0; I--) 00308 { Intermediate[I].Real = RHS[*(pExtOrder)]; 00309 Intermediate[I].Imag = iRHS[*(pExtOrder--)]; 00310 } 00311 #else 00312 ExtVector = (ComplexVector)RHS; 00313 for (I = Size; I > 0; I--) 00314 Intermediate[I] = ExtVector[*(pExtOrder--)]; 00315 #endif 00316 00317 /* Forward substitution. Solves Lc = b.*/ 00318 for (I = 1; I <= Size; I++) 00319 { Temp = Intermediate[I]; 00320 00321 /* This step of the substitution is skipped if Temp equals zero. */ 00322 if ((Temp.Real != 0.0) OR (Temp.Imag != 0.0)) 00323 { pPivot = Matrix->Diag[I]; 00324 /* Cmplx expr: Temp *= (1.0 / Pivot). */ 00325 CMPLX_MULT_ASSIGN(Temp, *pPivot); 00326 Intermediate[I] = Temp; 00327 pElement = pPivot->NextInCol; 00328 while (pElement != NULL) 00329 { 00330 /* Cmplx expr: Intermediate[Element->Row] -= Temp * *Element. */ 00331 CMPLX_MULT_SUBT_ASSIGN(Intermediate[pElement->Row], 00332 Temp, *pElement); 00333 pElement = pElement->NextInCol; 00334 } 00335 } 00336 } 00337 00338 /* Backward Substitution. Solves Ux = c.*/ 00339 for (I = Size; I > 0; I--) 00340 { Temp = Intermediate[I]; 00341 pElement = Matrix->Diag[I]->NextInRow; 00342 00343 while (pElement != NULL) 00344 { 00345 /* Cmplx expr: Temp -= *Element * Intermediate[Element->Col]. */ 00346 CMPLX_MULT_SUBT_ASSIGN(Temp, *pElement,Intermediate[pElement->Col]); 00347 pElement = pElement->NextInRow; 00348 } 00349 Intermediate[I] = Temp; 00350 } 00351 00352 /* Unscramble Intermediate vector while placing data in to Solution vector. */ 00353 pExtOrder = &Matrix->IntToExtColMap[Size]; 00354 00355 #if spSEPARATED_COMPLEX_VECTORS 00356 for (I = Size; I > 0; I--) 00357 { Solution[*(pExtOrder)] = Intermediate[I].Real; 00358 iSolution[*(pExtOrder--)] = Intermediate[I].Imag; 00359 } 00360 #else 00361 ExtVector = (ComplexVector)Solution; 00362 for (I = Size; I > 0; I--) 00363 ExtVector[*(pExtOrder--)] = Intermediate[I]; 00364 #endif 00365 00366 return; 00367 } 00368 #endif /* spCOMPLEX */ 00369 00370 00371 00372 00373 00374 00375 00376 00377 00378 00379 00380 00381 00382 00383 #if TRANSPOSE 00384 /* 00385 * SOLVE TRANSPOSED MATRIX EQUATION 00386 * 00387 * Performs forward elimination and back substitution to find the 00388 * unknown vector from the RHS vector and transposed factored 00389 * matrix. This routine is useful when performing sensitivity analysis 00390 * on a circuit using the adjoint method. This routine assumes that 00391 * the pivots are associated with the untransposed lower triangular 00392 * (L) matrix and that the diagonal of the untransposed upper 00393 * triangular (U) matrix consists of ones. 00394 * 00395 * >>> Arguments: 00396 * Matrix <input> (char *) 00397 * Pointer to matrix. 00398 * RHS <input> (RealVector) 00399 * RHS is the input data array, the right hand side. This data is 00400 * undisturbed and may be reused for other solves. 00401 * Solution <output> (RealVector) 00402 * Solution is the output data array. This routine is constructed such that 00403 * RHS and Solution can be the same array. 00404 * iRHS <input> (RealVector) 00405 * iRHS is the imaginary portion of the input data array, the right 00406 * hand side. This data is undisturbed and may be reused for other solves. 00407 * If spSEPARATED_COMPLEX_VECTOR is set false, or if matrix is real, there 00408 * is no need to supply this array. 00409 * iSolution <output> (RealVector) 00410 * iSolution is the imaginary portion of the output data array. This 00411 * routine is constructed such that iRHS and iSolution can be 00412 * the same array. If spSEPARATED_COMPLEX_VECTOR is set false, or if 00413 * matrix is real, there is no need to supply this array. 00414 * 00415 * >>> Local variables: 00416 * Intermediate (RealVector) 00417 * Temporary storage for use in forward elimination and backward 00418 * substitution. Commonly referred to as c, when the LU factorization 00419 * equations are given as Ax = b, Lc = b, Ux = c. Local version of 00420 * Matrix->Intermediate, which was created during the initial 00421 * factorization in function CreateInternalVectors() in the matrix 00422 * factorization module. 00423 * pElement (ElementPtr) 00424 * Pointer used to address elements in both the lower and upper triangle 00425 * matrices. 00426 * pExtOrder (int *) 00427 * Pointer used to sequentially access each entry in IntToExtRowMap 00428 * and IntToExtRowMap arrays. Used to quickly scramble and unscramble 00429 * RHS and Solution to account for row and column interchanges. 00430 * pPivot (ElementPtr) 00431 * Pointer that points to current pivot or diagonal element. 00432 * Size (int) 00433 * Size of matrix. Made local to reduce indirection. 00434 * Temp (RealNumber) 00435 * Temporary storage for entries in arrays. 00436 * 00437 * >>> Obscure Macros 00438 * IMAG_VECTORS 00439 * Replaces itself with `, iRHS, iSolution' if the options spCOMPLEX and 00440 * spSEPARATED_COMPLEX_VECTORS are set, otherwise it disappears 00441 * without a trace. 00442 */ 00443 00444 /*VARARGS3*/ 00445 00446 void 00447 spSolveTransposed( char *eMatrix, RealVector RHS, RealVector Solution IMAG_VECTORS ) 00448 { 00449 MatrixPtr Matrix = (MatrixPtr)eMatrix; 00450 register ElementPtr pElement; 00451 register RealVector Intermediate; 00452 register int I, *pExtOrder, Size; 00453 ElementPtr pPivot; 00454 RealNumber Temp; 00455 00456 00457 /* Begin `spSolveTransposed'. */ 00458 ASSERT( IS_VALID(Matrix) AND IS_FACTORED(Matrix) ); 00459 00460 #if spCOMPLEX 00461 if (Matrix->Complex) 00462 { SolveComplexTransposedMatrix( Matrix, RHS, Solution IMAG_VECTORS ); 00463 return; 00464 } 00465 #endif 00466 00467 #if REAL 00468 Size = Matrix->Size; 00469 Intermediate = Matrix->Intermediate; 00470 00471 /* Correct array pointers for ARRAY_OFFSET. */ 00472 #if NOT ARRAY_OFFSET 00473 --RHS; 00474 --Solution; 00475 #endif 00476 00477 /* Initialize Intermediate vector. */ 00478 pExtOrder = &Matrix->IntToExtColMap[Size]; 00479 for (I = Size; I > 0; I--) 00480 Intermediate[I] = RHS[*(pExtOrder--)]; 00481 00482 /* Forward elimination. */ 00483 for (I = 1; I <= Size; I++) 00484 { 00485 /* This step of the elimination is skipped if Temp equals zero. */ 00486 if ((Temp = Intermediate[I]) != 0.0) 00487 { pElement = Matrix->Diag[I]->NextInRow; 00488 while (pElement != NULL) 00489 { Intermediate[pElement->Col] -= Temp * pElement->Real; 00490 pElement = pElement->NextInRow; 00491 } 00492 00493 } 00494 } 00495 00496 /* Backward Substitution. */ 00497 for (I = Size; I > 0; I--) 00498 { pPivot = Matrix->Diag[I]; 00499 Temp = Intermediate[I]; 00500 pElement = pPivot->NextInCol; 00501 while (pElement != NULL) 00502 { Temp -= pElement->Real * Intermediate[pElement->Row]; 00503 pElement = pElement->NextInCol; 00504 } 00505 Intermediate[I] = Temp * pPivot->Real; 00506 } 00507 00508 /* Unscramble Intermediate vector while placing data in to Solution vector. */ 00509 pExtOrder = &Matrix->IntToExtRowMap[Size]; 00510 for (I = Size; I > 0; I--) 00511 Solution[*(pExtOrder--)] = Intermediate[I]; 00512 00513 return; 00514 #endif /* REAL */ 00515 } 00516 #endif /* TRANSPOSE */ 00517 00518 00519 00520 00521 00522 00523 00524 00525 00526 00527 #if TRANSPOSE AND spCOMPLEX 00528 /* 00529 * SOLVE COMPLEX TRANSPOSED MATRIX EQUATION 00530 * 00531 * Performs forward elimination and back substitution to find the 00532 * unknown vector from the RHS vector and transposed factored 00533 * matrix. This routine is useful when performing sensitivity analysis 00534 * on a circuit using the adjoint method. This routine assumes that 00535 * the pivots are associated with the untransposed lower triangular 00536 * (L) matrix and that the diagonal of the untransposed upper 00537 * triangular (U) matrix consists of ones. 00538 * 00539 * >>> Arguments: 00540 * Matrix <input> (char *) 00541 * Pointer to matrix. 00542 * RHS <input> (RealVector) 00543 * RHS is the input data array, the right hand 00544 * side. This data is undisturbed and may be reused for other solves. 00545 * This vector is only the real portion if the matrix is complex and 00546 * spSEPARATED_COMPLEX_VECTORS is set true. 00547 * Solution <output> (RealVector) 00548 * Solution is the real portion of the output data array. This routine 00549 * is constructed such that RHS and Solution can be the same array. 00550 * This vector is only the real portion if the matrix is complex and 00551 * spSEPARATED_COMPLEX_VECTORS is set true. 00552 * iRHS <input> (RealVector) 00553 * iRHS is the imaginary portion of the input data array, the right 00554 * hand side. This data is undisturbed and may be reused for other solves. 00555 * If either spCOMPLEX or spSEPARATED_COMPLEX_VECTOR is set false, there 00556 * is no need to supply this array. 00557 * iSolution <output> (RealVector) 00558 * iSolution is the imaginary portion of the output data array. This 00559 * routine is constructed such that iRHS and iSolution can be 00560 * the same array. If spCOMPLEX or spSEPARATED_COMPLEX_VECTOR is set 00561 * false, there is no need to supply this array. 00562 * 00563 * >>> Local variables: 00564 * Intermediate (ComplexVector) 00565 * Temporary storage for use in forward elimination and backward 00566 * substitution. Commonly referred to as c, when the LU factorization 00567 * equations are given as Ax = b, Lc = b, Ux = c. Local version of 00568 * Matrix->Intermediate, which was created during 00569 * the initial factorization in function CreateInternalVectors() in the 00570 * matrix factorization module. 00571 * pElement (ElementPtr) 00572 * Pointer used to address elements in both the lower and upper triangle 00573 * matrices. 00574 * pExtOrder (int *) 00575 * Pointer used to sequentially access each entry in IntToExtRowMap 00576 * and IntToExtColMap arrays. Used to quickly scramble and unscramble 00577 * RHS and Solution to account for row and column interchanges. 00578 * pPivot (ElementPtr) 00579 * Pointer that points to current pivot or diagonal element. 00580 * Size (int) 00581 * Size of matrix. Made local to reduce indirection. 00582 * Temp (ComplexNumber) 00583 * Temporary storage for entries in arrays. 00584 * 00585 * >>> Obscure Macros 00586 * IMAG_VECTORS 00587 * Replaces itself with `, iRHS, iSolution' if the options spCOMPLEX and 00588 * spSEPARATED_COMPLEX_VECTORS are set, otherwise it disappears 00589 * without a trace. 00590 */ 00591 00592 static void 00593 SolveComplexTransposedMatrix(MatrixPtr Matrix, RealVector RHS, RealVector Solution IMAG_VECTORS ) 00594 { 00595 register ElementPtr pElement; 00596 register ComplexVector Intermediate; 00597 register int I, *pExtOrder, Size; 00598 register ComplexVector ExtVector; 00599 ElementPtr pPivot; 00600 ComplexNumber Temp; 00601 00602 /* Begin `SolveComplexTransposedMatrix'. */ 00603 00604 Size = Matrix->Size; 00605 Intermediate = (ComplexVector)Matrix->Intermediate; 00606 00607 /* Correct array pointers for ARRAY_OFFSET. */ 00608 #if NOT ARRAY_OFFSET 00609 #if spSEPARATED_COMPLEX_VECTORS 00610 --RHS; --iRHS; 00611 --Solution; --iSolution; 00612 #else 00613 RHS -= 2; Solution -= 2; 00614 #endif 00615 #endif 00616 00617 /* Initialize Intermediate vector. */ 00618 pExtOrder = &Matrix->IntToExtColMap[Size]; 00619 00620 #if spSEPARATED_COMPLEX_VECTORS 00621 for (I = Size; I > 0; I--) 00622 { Intermediate[I].Real = RHS[*(pExtOrder)]; 00623 Intermediate[I].Imag = iRHS[*(pExtOrder--)]; 00624 } 00625 #else 00626 ExtVector = (ComplexVector)RHS; 00627 for (I = Size; I > 0; I--) 00628 Intermediate[I] = ExtVector[*(pExtOrder--)]; 00629 #endif 00630 00631 /* Forward elimination. */ 00632 for (I = 1; I <= Size; I++) 00633 { Temp = Intermediate[I]; 00634 00635 /* This step of the elimination is skipped if Temp equals zero. */ 00636 if ((Temp.Real != 0.0) OR (Temp.Imag != 0.0)) 00637 { pElement = Matrix->Diag[I]->NextInRow; 00638 while (pElement != NULL) 00639 { 00640 /* Cmplx expr: Intermediate[Element->Col] -= Temp * *Element. */ 00641 CMPLX_MULT_SUBT_ASSIGN( Intermediate[pElement->Col], 00642 Temp, *pElement); 00643 pElement = pElement->NextInRow; 00644 } 00645 } 00646 } 00647 00648 /* Backward Substitution. */ 00649 for (I = Size; I > 0; I--) 00650 { pPivot = Matrix->Diag[I]; 00651 Temp = Intermediate[I]; 00652 pElement = pPivot->NextInCol; 00653 00654 while (pElement != NULL) 00655 { 00656 /* Cmplx expr: Temp -= Intermediate[Element->Row] * *Element. */ 00657 CMPLX_MULT_SUBT_ASSIGN(Temp,Intermediate[pElement->Row],*pElement); 00658 00659 pElement = pElement->NextInCol; 00660 } 00661 /* Cmplx expr: Intermediate = Temp * (1.0 / *pPivot). */ 00662 CMPLX_MULT(Intermediate[I], Temp, *pPivot); 00663 } 00664 00665 /* Unscramble Intermediate vector while placing data in to Solution vector. */ 00666 pExtOrder = &Matrix->IntToExtRowMap[Size]; 00667 00668 #if spSEPARATED_COMPLEX_VECTORS 00669 for (I = Size; I > 0; I--) 00670 { Solution[*(pExtOrder)] = Intermediate[I].Real; 00671 iSolution[*(pExtOrder--)] = Intermediate[I].Imag; 00672 } 00673 #else 00674 ExtVector = (ComplexVector)Solution; 00675 for (I = Size; I > 0; I--) 00676 ExtVector[*(pExtOrder--)] = Intermediate[I]; 00677 #endif 00678 00679 return; 00680 } 00681 #endif /* TRANSPOSE AND spCOMPLEX */
1.5.1