MOOS 0.2375
|
00001 //$$ newmat7.cpp Invert, solve, binary operations 00002 00003 // Copyright (C) 1991,2,3,4: R B Davies 00004 00005 #include "include.h" 00006 00007 #include "newmat.h" 00008 #include "newmatrc.h" 00009 00010 #ifdef use_namespace 00011 namespace NEWMAT { 00012 #endif 00013 00014 00015 #ifdef DO_REPORT 00016 #define REPORT { static ExeCounter ExeCount(__LINE__,7); ++ExeCount; } 00017 #else 00018 #define REPORT {} 00019 #endif 00020 00021 00022 //***************************** solve routines ******************************/ 00023 00024 GeneralMatrix* GeneralMatrix::MakeSolver() 00025 { 00026 REPORT 00027 GeneralMatrix* gm = new CroutMatrix(*this); 00028 MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm; 00029 } 00030 00031 GeneralMatrix* Matrix::MakeSolver() 00032 { 00033 REPORT 00034 GeneralMatrix* gm = new CroutMatrix(*this); 00035 MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm; 00036 } 00037 00038 void CroutMatrix::Solver(MatrixColX& mcout, const MatrixColX& mcin) 00039 { 00040 REPORT 00041 int i = mcin.skip; Real* el = mcin.data-i; Real* el1 = el; 00042 while (i--) *el++ = 0.0; 00043 el += mcin.storage; i = nrows - mcin.skip - mcin.storage; 00044 while (i--) *el++ = 0.0; 00045 lubksb(el1, mcout.skip); 00046 } 00047 00048 00049 // Do we need check for entirely zero output? 00050 00051 void UpperTriangularMatrix::Solver(MatrixColX& mcout, 00052 const MatrixColX& mcin) 00053 { 00054 REPORT 00055 int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i; 00056 while (i-- > 0) *elx++ = 0.0; 00057 int nr = mcin.skip+mcin.storage; 00058 elx = mcin.data+mcin.storage; Real* el = elx; 00059 int j = mcout.skip+mcout.storage-nr; int nc = ncols-nr; i = nr-mcout.skip; 00060 while (j-- > 0) *elx++ = 0.0; 00061 Real* Ael = store + (nr*(2*ncols-nr+1))/2; j = 0; 00062 while (i-- > 0) 00063 { 00064 elx = el; Real sum = 0.0; int jx = j++; Ael -= nc; 00065 while (jx--) sum += *(--Ael) * *(--elx); 00066 elx--; *elx = (*elx - sum) / *(--Ael); 00067 } 00068 } 00069 00070 void LowerTriangularMatrix::Solver(MatrixColX& mcout, 00071 const MatrixColX& mcin) 00072 { 00073 REPORT 00074 int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i; 00075 while (i-- > 0) *elx++ = 0.0; 00076 int nc = mcin.skip; i = nc+mcin.storage; elx = mcin.data+mcin.storage; 00077 int nr = mcout.skip+mcout.storage; int j = nr-i; i = nr-nc; 00078 while (j-- > 0) *elx++ = 0.0; 00079 Real* el = mcin.data; Real* Ael = store + (nc*(nc+1))/2; j = 0; 00080 while (i-- > 0) 00081 { 00082 elx = el; Real sum = 0.0; int jx = j++; Ael += nc; 00083 while (jx--) sum += *Ael++ * *elx++; 00084 *elx = (*elx - sum) / *Ael++; 00085 } 00086 } 00087 00088 //******************* carry out binary operations *************************/ 00089 00090 static GeneralMatrix* 00091 GeneralMult(GeneralMatrix*,GeneralMatrix*,MultipliedMatrix*,MatrixType); 00092 static GeneralMatrix* 00093 GeneralSolv(GeneralMatrix*,GeneralMatrix*,BaseMatrix*,MatrixType); 00094 static GeneralMatrix* 00095 GeneralSolvI(GeneralMatrix*,BaseMatrix*,MatrixType); 00096 static GeneralMatrix* 00097 GeneralKP(GeneralMatrix*,GeneralMatrix*,KPMatrix*,MatrixType); 00098 00099 GeneralMatrix* MultipliedMatrix::Evaluate(MatrixType mt) 00100 { 00101 REPORT 00102 gm2 = ((BaseMatrix*&)bm2)->Evaluate(); 00103 gm2 = gm2->Evaluate(gm2->Type().MultRHS()); // no symmetric on RHS 00104 gm1=((BaseMatrix*&)bm1)->Evaluate(); 00105 #ifdef TEMPS_DESTROYED_QUICKLY 00106 GeneralMatrix* gmx; 00107 Try { gmx = GeneralMult(gm1, gm2, this, mt); } 00108 CatchAll { delete this; ReThrow; } 00109 delete this; return gmx; 00110 #else 00111 return GeneralMult(gm1, gm2, this, mt); 00112 #endif 00113 } 00114 00115 GeneralMatrix* SolvedMatrix::Evaluate(MatrixType mt) 00116 { 00117 REPORT 00118 gm1=((BaseMatrix*&)bm1)->Evaluate(); 00119 gm2=((BaseMatrix*&)bm2)->Evaluate(); 00120 #ifdef TEMPS_DESTROYED_QUICKLY 00121 GeneralMatrix* gmx; 00122 Try { gmx = GeneralSolv(gm1,gm2,this,mt); } 00123 CatchAll { delete this; ReThrow; } 00124 delete this; return gmx; 00125 #else 00126 return GeneralSolv(gm1,gm2,this,mt); 00127 #endif 00128 } 00129 00130 GeneralMatrix* KPMatrix::Evaluate(MatrixType mt) 00131 { 00132 REPORT 00133 gm1=((BaseMatrix*&)bm1)->Evaluate(); 00134 gm2=((BaseMatrix*&)bm2)->Evaluate(); 00135 #ifdef TEMPS_DESTROYED_QUICKLY 00136 GeneralMatrix* gmx; 00137 Try { gmx = GeneralKP(gm1,gm2,this,mt); } 00138 CatchAll { delete this; ReThrow; } 00139 delete this; return gmx; 00140 #else 00141 return GeneralKP(gm1,gm2,this,mt); 00142 #endif 00143 } 00144 00145 // routines for adding or subtracting matrices of identical storage structure 00146 00147 static void Add(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) 00148 { 00149 REPORT 00150 Real* s1=gm1->Store(); Real* s2=gm2->Store(); 00151 Real* s=gm->Store(); int i=gm->Storage() >> 2; 00152 while (i--) 00153 { 00154 *s++ = *s1++ + *s2++; *s++ = *s1++ + *s2++; 00155 *s++ = *s1++ + *s2++; *s++ = *s1++ + *s2++; 00156 } 00157 i=gm->Storage() & 3; while (i--) *s++ = *s1++ + *s2++; 00158 } 00159 00160 static void Add(GeneralMatrix* gm, GeneralMatrix* gm2) 00161 { 00162 REPORT 00163 Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2; 00164 while (i--) 00165 { *s++ += *s2++; *s++ += *s2++; *s++ += *s2++; *s++ += *s2++; } 00166 i=gm->Storage() & 3; while (i--) *s++ += *s2++; 00167 } 00168 00169 static void Subtract(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) 00170 { 00171 REPORT 00172 Real* s1=gm1->Store(); Real* s2=gm2->Store(); 00173 Real* s=gm->Store(); int i=gm->Storage() >> 2; 00174 while (i--) 00175 { 00176 *s++ = *s1++ - *s2++; *s++ = *s1++ - *s2++; 00177 *s++ = *s1++ - *s2++; *s++ = *s1++ - *s2++; 00178 } 00179 i=gm->Storage() & 3; while (i--) *s++ = *s1++ - *s2++; 00180 } 00181 00182 static void Subtract(GeneralMatrix* gm, GeneralMatrix* gm2) 00183 { 00184 REPORT 00185 Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2; 00186 while (i--) 00187 { *s++ -= *s2++; *s++ -= *s2++; *s++ -= *s2++; *s++ -= *s2++; } 00188 i=gm->Storage() & 3; while (i--) *s++ -= *s2++; 00189 } 00190 00191 static void ReverseSubtract(GeneralMatrix* gm, GeneralMatrix* gm2) 00192 { 00193 REPORT 00194 Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2; 00195 while (i--) 00196 { 00197 *s = *s2++ - *s; s++; *s = *s2++ - *s; s++; 00198 *s = *s2++ - *s; s++; *s = *s2++ - *s; s++; 00199 } 00200 i=gm->Storage() & 3; while (i--) { *s = *s2++ - *s; s++; } 00201 } 00202 00203 static void SP(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) 00204 { 00205 REPORT 00206 Real* s1=gm1->Store(); Real* s2=gm2->Store(); 00207 Real* s=gm->Store(); int i=gm->Storage() >> 2; 00208 while (i--) 00209 { 00210 *s++ = *s1++ * *s2++; *s++ = *s1++ * *s2++; 00211 *s++ = *s1++ * *s2++; *s++ = *s1++ * *s2++; 00212 } 00213 i=gm->Storage() & 3; while (i--) *s++ = *s1++ * *s2++; 00214 } 00215 00216 static void SP(GeneralMatrix* gm, GeneralMatrix* gm2) 00217 { 00218 REPORT 00219 Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2; 00220 while (i--) 00221 { *s++ *= *s2++; *s++ *= *s2++; *s++ *= *s2++; *s++ *= *s2++; } 00222 i=gm->Storage() & 3; while (i--) *s++ *= *s2++; 00223 } 00224 00225 // routines for adding or subtracting matrices of different storage structure 00226 00227 static void AddDS(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) 00228 { 00229 REPORT 00230 int nr = gm->Nrows(); 00231 MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry); 00232 MatrixRow mr(gm, StoreOnExit+DirectPart); 00233 while (nr--) { mr.Add(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); } 00234 } 00235 00236 static void AddDS(GeneralMatrix* gm, GeneralMatrix* gm2) 00237 // Add into first argument 00238 { 00239 REPORT 00240 int nr = gm->Nrows(); 00241 MatrixRow mr(gm, StoreOnExit+LoadOnEntry+DirectPart); 00242 MatrixRow mr2(gm2, LoadOnEntry); 00243 while (nr--) { mr.Add(mr2); mr.Next(); mr2.Next(); } 00244 } 00245 00246 static void SubtractDS 00247 (GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) 00248 { 00249 REPORT 00250 int nr = gm->Nrows(); 00251 MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry); 00252 MatrixRow mr(gm, StoreOnExit+DirectPart); 00253 while (nr--) { mr.Sub(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); } 00254 } 00255 00256 static void SubtractDS(GeneralMatrix* gm, GeneralMatrix* gm2) 00257 { 00258 REPORT 00259 int nr = gm->Nrows(); 00260 MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart); 00261 MatrixRow mr2(gm2, LoadOnEntry); 00262 while (nr--) { mr.Sub(mr2); mr.Next(); mr2.Next(); } 00263 } 00264 00265 static void ReverseSubtractDS(GeneralMatrix* gm, GeneralMatrix* gm2) 00266 { 00267 REPORT 00268 int nr = gm->Nrows(); 00269 MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart); 00270 MatrixRow mr2(gm2, LoadOnEntry); 00271 while (nr--) { mr.RevSub(mr2); mr2.Next(); mr.Next(); } 00272 } 00273 00274 static void SPDS(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) 00275 { 00276 REPORT 00277 int nr = gm->Nrows(); 00278 MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry); 00279 MatrixRow mr(gm, StoreOnExit+DirectPart); 00280 while (nr--) { mr.Multiply(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); } 00281 } 00282 00283 static void SPDS(GeneralMatrix* gm, GeneralMatrix* gm2) 00284 // SP into first argument 00285 { 00286 REPORT 00287 int nr = gm->Nrows(); 00288 MatrixRow mr(gm, StoreOnExit+LoadOnEntry+DirectPart); 00289 MatrixRow mr2(gm2, LoadOnEntry); 00290 while (nr--) { mr.Multiply(mr2); mr.Next(); mr2.Next(); } 00291 } 00292 00293 static GeneralMatrix* GeneralMult1(GeneralMatrix* gm1, GeneralMatrix* gm2, 00294 MultipliedMatrix* mm, MatrixType mtx) 00295 { 00296 REPORT 00297 Tracer tr("GeneralMult1"); 00298 int nr=gm1->Nrows(); int nc=gm2->Ncols(); 00299 if (gm1->Ncols() !=gm2->Nrows()) 00300 Throw(IncompatibleDimensionsException(*gm1, *gm2)); 00301 GeneralMatrix* gmx = mtx.New(nr,nc,mm); 00302 00303 MatrixCol mcx(gmx, StoreOnExit+DirectPart); 00304 MatrixCol mc2(gm2, LoadOnEntry); 00305 while (nc--) 00306 { 00307 MatrixRow mr1(gm1, LoadOnEntry, mcx.Skip()); 00308 Real* el = mcx.Data(); // pointer to an element 00309 int n = mcx.Storage(); 00310 while (n--) { *(el++) = DotProd(mr1,mc2); mr1.Next(); } 00311 mc2.Next(); mcx.Next(); 00312 } 00313 gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx; 00314 } 00315 00316 static GeneralMatrix* GeneralMult2(GeneralMatrix* gm1, GeneralMatrix* gm2, 00317 MultipliedMatrix* mm, MatrixType mtx) 00318 { 00319 // version that accesses by row only - not good for thin matrices 00320 // or column vectors in right hand term. 00321 REPORT 00322 Tracer tr("GeneralMult2"); 00323 int nr=gm1->Nrows(); int nc=gm2->Ncols(); 00324 if (gm1->Ncols() !=gm2->Nrows()) 00325 Throw(IncompatibleDimensionsException(*gm1, *gm2)); 00326 GeneralMatrix* gmx = mtx.New(nr,nc,mm); 00327 00328 MatrixRow mrx(gmx, LoadOnEntry+StoreOnExit+DirectPart); 00329 MatrixRow mr1(gm1, LoadOnEntry); 00330 while (nr--) 00331 { 00332 MatrixRow mr2(gm2, LoadOnEntry, mr1.Skip()); 00333 Real* el = mr1.Data(); // pointer to an element 00334 int n = mr1.Storage(); 00335 mrx.Zero(); 00336 while (n--) { mrx.AddScaled(mr2, *el++); mr2.Next(); } 00337 mr1.Next(); mrx.Next(); 00338 } 00339 gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx; 00340 } 00341 00342 static GeneralMatrix* mmMult(GeneralMatrix* gm1, GeneralMatrix* gm2) 00343 { 00344 // matrix multiplication for type Matrix only 00345 REPORT 00346 Tracer tr("MatrixMult"); 00347 00348 int nr=gm1->Nrows(); int ncr=gm1->Ncols(); int nc=gm2->Ncols(); 00349 if (ncr != gm2->Nrows()) Throw(IncompatibleDimensionsException(*gm1,*gm2)); 00350 00351 Matrix* gm = new Matrix(nr,nc); MatrixErrorNoSpace(gm); 00352 00353 Real* s1=gm1->Store(); Real* s2=gm2->Store(); Real* s=gm->Store(); 00354 00355 if (ncr) 00356 { 00357 while (nr--) 00358 { 00359 Real* s2x = s2; int j = ncr; 00360 Real* sx = s; Real f = *s1++; int k = nc; 00361 while (k--) *sx++ = f * *s2x++; 00362 while (--j) 00363 { sx = s; f = *s1++; k = nc; while (k--) *sx++ += f * *s2x++; } 00364 s = sx; 00365 } 00366 } 00367 else *gm = 0.0; 00368 00369 gm->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gm; 00370 } 00371 00372 static GeneralMatrix* GeneralMult(GeneralMatrix* gm1, GeneralMatrix* gm2, 00373 MultipliedMatrix* mm, MatrixType mtx) 00374 { 00375 if ( Rectangular(gm1->Type(), gm2->Type(), mtx)) 00376 { 00377 REPORT 00378 return mmMult(gm1, gm2); 00379 } 00380 else 00381 { 00382 REPORT 00383 Compare(gm1->Type() * gm2->Type(),mtx); 00384 int nr = gm2->Nrows(); int nc = gm2->Ncols(); 00385 if (nc <= 5 && nr > nc) { REPORT return GeneralMult1(gm1, gm2, mm, mtx); } 00386 else { REPORT return GeneralMult2(gm1, gm2, mm, mtx); } 00387 } 00388 } 00389 00390 static GeneralMatrix* GeneralKP(GeneralMatrix* gm1, GeneralMatrix* gm2, 00391 KPMatrix* kp, MatrixType mtx) 00392 { 00393 REPORT 00394 Tracer tr("GeneralKP"); 00395 int nr1 = gm1->Nrows(); int nc1 = gm1->Ncols(); 00396 int nr2 = gm2->Nrows(); int nc2 = gm2->Ncols(); 00397 Compare((gm1->Type()).KP(gm2->Type()),mtx); 00398 GeneralMatrix* gmx = mtx.New(nr1*nr2, nc1*nc2, kp); 00399 MatrixRow mrx(gmx, LoadOnEntry+StoreOnExit+DirectPart); 00400 MatrixRow mr1(gm1, LoadOnEntry); 00401 for (int i = 1; i <= nr1; ++i) 00402 { 00403 MatrixRow mr2(gm2, LoadOnEntry); 00404 for (int j = 1; j <= nr2; ++j) 00405 { mrx.KP(mr1,mr2); mr2.Next(); mrx.Next(); } 00406 mr1.Next(); 00407 } 00408 gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx; 00409 } 00410 00411 static GeneralMatrix* GeneralSolv(GeneralMatrix* gm1, GeneralMatrix* gm2, 00412 BaseMatrix* sm, MatrixType mtx) 00413 { 00414 REPORT 00415 Tracer tr("GeneralSolv"); 00416 Compare(gm1->Type().i() * gm2->Type(),mtx); 00417 int nr = gm1->Nrows(); 00418 if (nr != gm1->Ncols()) Throw(NotSquareException(*gm1)); 00419 int nc = gm2->Ncols(); 00420 if (gm1->Ncols() != gm2->Nrows()) 00421 Throw(IncompatibleDimensionsException(*gm1, *gm2)); 00422 GeneralMatrix* gmx = mtx.New(nr,nc,sm); MatrixErrorNoSpace(gmx); 00423 Real* r = new Real [nr]; MatrixErrorNoSpace(r); 00424 MONITOR_REAL_NEW("Make (GenSolv)",nr,r) 00425 GeneralMatrix* gms = gm1->MakeSolver(); 00426 Try 00427 { 00428 00429 MatrixColX mcx(gmx, r, StoreOnExit+DirectPart); // copy to and from r 00430 // this must be inside Try so mcx is destroyed before gmx 00431 MatrixColX mc2(gm2, r, LoadOnEntry); 00432 while (nc--) { gms->Solver(mcx, mc2); mcx.Next(); mc2.Next(); } 00433 } 00434 CatchAll 00435 { 00436 if (gms) gms->tDelete(); 00437 delete gmx; // <-------------------- 00438 gm2->tDelete(); 00439 MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r) 00440 // ATandT version 2.1 gives an internal error 00441 delete [] r; 00442 ReThrow; 00443 } 00444 gms->tDelete(); gmx->ReleaseAndDelete(); gm2->tDelete(); 00445 MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r) 00446 // ATandT version 2.1 gives an internal error 00447 delete [] r; 00448 return gmx; 00449 } 00450 00451 // version for inverses - gm2 is identity 00452 static GeneralMatrix* GeneralSolvI(GeneralMatrix* gm1, BaseMatrix* sm, 00453 MatrixType mtx) 00454 { 00455 REPORT 00456 Tracer tr("GeneralSolvI"); 00457 Compare(gm1->Type().i(),mtx); 00458 int nr = gm1->Nrows(); 00459 if (nr != gm1->Ncols()) Throw(NotSquareException(*gm1)); 00460 int nc = nr; 00461 // DiagonalMatrix I(nr); I = 1; 00462 IdentityMatrix I(nr); 00463 GeneralMatrix* gmx = mtx.New(nr,nc,sm); MatrixErrorNoSpace(gmx); 00464 Real* r = new Real [nr]; MatrixErrorNoSpace(r); 00465 MONITOR_REAL_NEW("Make (GenSolvI)",nr,r) 00466 GeneralMatrix* gms = gm1->MakeSolver(); 00467 Try 00468 { 00469 00470 MatrixColX mcx(gmx, r, StoreOnExit+DirectPart); // copy to and from r 00471 // this must be inside Try so mcx is destroyed before gmx 00472 MatrixColX mc2(&I, r, LoadOnEntry); 00473 while (nc--) { gms->Solver(mcx, mc2); mcx.Next(); mc2.Next(); } 00474 } 00475 CatchAll 00476 { 00477 if (gms) gms->tDelete(); 00478 delete gmx; 00479 MONITOR_REAL_DELETE("Delete (GenSolvI)",nr,r) 00480 // ATandT version 2.1 gives an internal error 00481 delete [] r; 00482 ReThrow; 00483 } 00484 gms->tDelete(); gmx->ReleaseAndDelete(); 00485 MONITOR_REAL_DELETE("Delete (GenSolvI)",nr,r) 00486 // ATandT version 2.1 gives an internal error 00487 delete [] r; 00488 return gmx; 00489 } 00490 00491 GeneralMatrix* InvertedMatrix::Evaluate(MatrixType mtx) 00492 { 00493 // Matrix Inversion - use solve routines 00494 Tracer tr("InvertedMatrix::Evaluate"); 00495 REPORT 00496 gm=((BaseMatrix*&)bm)->Evaluate(); 00497 #ifdef TEMPS_DESTROYED_QUICKLY 00498 GeneralMatrix* gmx; 00499 Try { gmx = GeneralSolvI(gm,this,mtx); } 00500 CatchAll { delete this; ReThrow; } 00501 delete this; return gmx; 00502 #else 00503 return GeneralSolvI(gm,this,mtx); 00504 #endif 00505 } 00506 00507 //*************************** New versions ************************ 00508 00509 GeneralMatrix* AddedMatrix::Evaluate(MatrixType mtd) 00510 { 00511 REPORT 00512 Tracer tr("AddedMatrix::Evaluate"); 00513 gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate(); 00514 int nr=gm1->Nrows(); int nc=gm1->Ncols(); 00515 if (nr!=gm2->Nrows() || nc!=gm2->Ncols()) 00516 { 00517 Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); } 00518 CatchAll 00519 { 00520 gm1->tDelete(); gm2->tDelete(); 00521 #ifdef TEMPS_DESTROYED_QUICKLY 00522 delete this; 00523 #endif 00524 ReThrow; 00525 } 00526 } 00527 MatrixType mt1 = gm1->Type(), mt2 = gm2->Type(); MatrixType mts = mt1 + mt2; 00528 if (!mtd) { REPORT mtd = mts; } 00529 else if (!(mtd.DataLossOK || mtd >= mts)) 00530 { 00531 REPORT 00532 gm1->tDelete(); gm2->tDelete(); 00533 #ifdef TEMPS_DESTROYED_QUICKLY 00534 delete this; 00535 #endif 00536 Throw(ProgramException("Illegal Conversion", mts, mtd)); 00537 } 00538 GeneralMatrix* gmx; 00539 bool c1 = (mtd == mt1), c2 = (mtd == mt2); 00540 if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) ) 00541 { 00542 if (gm1->reuse()) { REPORT Add(gm1,gm2); gm2->tDelete(); gmx = gm1; } 00543 else if (gm2->reuse()) { REPORT Add(gm2,gm1); gmx = gm2; } 00544 else 00545 { 00546 REPORT 00547 // what if new throws an exception 00548 Try { gmx = mt1.New(nr,nc,this); } 00549 CatchAll 00550 { 00551 #ifdef TEMPS_DESTROYED_QUICKLY 00552 delete this; 00553 #endif 00554 ReThrow; 00555 } 00556 gmx->ReleaseAndDelete(); Add(gmx,gm1,gm2); 00557 } 00558 } 00559 else 00560 { 00561 if (c1 && c2) 00562 { 00563 short SAO = gm1->SimpleAddOK(gm2); 00564 if (SAO & 1) { REPORT c1 = false; } 00565 if (SAO & 2) { REPORT c2 = false; } 00566 } 00567 if (c1 && gm1->reuse() ) // must have type test first 00568 { REPORT AddDS(gm1,gm2); gm2->tDelete(); gmx = gm1; } 00569 else if (c2 && gm2->reuse() ) 00570 { REPORT AddDS(gm2,gm1); if (!c1) gm1->tDelete(); gmx = gm2; } 00571 else 00572 { 00573 REPORT 00574 Try { gmx = mtd.New(nr,nc,this); } 00575 CatchAll 00576 { 00577 if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete(); 00578 #ifdef TEMPS_DESTROYED_QUICKLY 00579 delete this; 00580 #endif 00581 ReThrow; 00582 } 00583 AddDS(gmx,gm1,gm2); 00584 if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete(); 00585 gmx->ReleaseAndDelete(); 00586 } 00587 } 00588 #ifdef TEMPS_DESTROYED_QUICKLY 00589 delete this; 00590 #endif 00591 return gmx; 00592 } 00593 00594 GeneralMatrix* SubtractedMatrix::Evaluate(MatrixType mtd) 00595 { 00596 REPORT 00597 Tracer tr("SubtractedMatrix::Evaluate"); 00598 gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate(); 00599 int nr=gm1->Nrows(); int nc=gm1->Ncols(); 00600 if (nr!=gm2->Nrows() || nc!=gm2->Ncols()) 00601 { 00602 Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); } 00603 CatchAll 00604 { 00605 gm1->tDelete(); gm2->tDelete(); 00606 #ifdef TEMPS_DESTROYED_QUICKLY 00607 delete this; 00608 #endif 00609 ReThrow; 00610 } 00611 } 00612 MatrixType mt1 = gm1->Type(), mt2 = gm2->Type(); MatrixType mts = mt1 + mt2; 00613 if (!mtd) { REPORT mtd = mts; } 00614 else if (!(mtd.DataLossOK || mtd >= mts)) 00615 { 00616 gm1->tDelete(); gm2->tDelete(); 00617 #ifdef TEMPS_DESTROYED_QUICKLY 00618 delete this; 00619 #endif 00620 Throw(ProgramException("Illegal Conversion", mts, mtd)); 00621 } 00622 GeneralMatrix* gmx; 00623 bool c1 = (mtd == mt1), c2 = (mtd == mt2); 00624 if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) ) 00625 { 00626 if (gm1->reuse()) { REPORT Subtract(gm1,gm2); gm2->tDelete(); gmx = gm1; } 00627 else if (gm2->reuse()) { REPORT ReverseSubtract(gm2,gm1); gmx = gm2; } 00628 else 00629 { 00630 REPORT 00631 Try { gmx = mt1.New(nr,nc,this); } 00632 CatchAll 00633 { 00634 #ifdef TEMPS_DESTROYED_QUICKLY 00635 delete this; 00636 #endif 00637 ReThrow; 00638 } 00639 gmx->ReleaseAndDelete(); Subtract(gmx,gm1,gm2); 00640 } 00641 } 00642 else 00643 { 00644 if (c1 && c2) 00645 { 00646 short SAO = gm1->SimpleAddOK(gm2); 00647 if (SAO & 1) { REPORT c1 = false; } 00648 if (SAO & 2) { REPORT c2 = false; } 00649 } 00650 if (c1 && gm1->reuse() ) // must have type test first 00651 { REPORT SubtractDS(gm1,gm2); gm2->tDelete(); gmx = gm1; } 00652 else if (c2 && gm2->reuse() ) 00653 { 00654 REPORT ReverseSubtractDS(gm2,gm1); 00655 if (!c1) gm1->tDelete(); gmx = gm2; 00656 } 00657 else 00658 { 00659 REPORT 00660 // what if New throws and exception 00661 Try { gmx = mtd.New(nr,nc,this); } 00662 CatchAll 00663 { 00664 if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete(); 00665 #ifdef TEMPS_DESTROYED_QUICKLY 00666 delete this; 00667 #endif 00668 ReThrow; 00669 } 00670 SubtractDS(gmx,gm1,gm2); 00671 if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete(); 00672 gmx->ReleaseAndDelete(); 00673 } 00674 } 00675 #ifdef TEMPS_DESTROYED_QUICKLY 00676 delete this; 00677 #endif 00678 return gmx; 00679 } 00680 00681 GeneralMatrix* SPMatrix::Evaluate(MatrixType mtd) 00682 { 00683 REPORT 00684 Tracer tr("SPMatrix::Evaluate"); 00685 gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate(); 00686 int nr=gm1->Nrows(); int nc=gm1->Ncols(); 00687 if (nr!=gm2->Nrows() || nc!=gm2->Ncols()) 00688 { 00689 Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); } 00690 CatchAll 00691 { 00692 gm1->tDelete(); gm2->tDelete(); 00693 #ifdef TEMPS_DESTROYED_QUICKLY 00694 delete this; 00695 #endif 00696 ReThrow; 00697 } 00698 } 00699 MatrixType mt1 = gm1->Type(), mt2 = gm2->Type(); 00700 MatrixType mts = mt1.SP(mt2); 00701 if (!mtd) { REPORT mtd = mts; } 00702 else if (!(mtd.DataLossOK || mtd >= mts)) 00703 { 00704 gm1->tDelete(); gm2->tDelete(); 00705 #ifdef TEMPS_DESTROYED_QUICKLY 00706 delete this; 00707 #endif 00708 Throw(ProgramException("Illegal Conversion", mts, mtd)); 00709 } 00710 GeneralMatrix* gmx; 00711 bool c1 = (mtd == mt1), c2 = (mtd == mt2); 00712 if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) ) 00713 { 00714 if (gm1->reuse()) { REPORT SP(gm1,gm2); gm2->tDelete(); gmx = gm1; } 00715 else if (gm2->reuse()) { REPORT SP(gm2,gm1); gmx = gm2; } 00716 else 00717 { 00718 REPORT 00719 Try { gmx = mt1.New(nr,nc,this); } 00720 CatchAll 00721 { 00722 #ifdef TEMPS_DESTROYED_QUICKLY 00723 delete this; 00724 #endif 00725 ReThrow; 00726 } 00727 gmx->ReleaseAndDelete(); SP(gmx,gm1,gm2); 00728 } 00729 } 00730 else 00731 { 00732 if (c1 && c2) 00733 { 00734 short SAO = gm1->SimpleAddOK(gm2); 00735 if (SAO & 1) { REPORT c2 = false; } // c1 and c2 swapped 00736 if (SAO & 2) { REPORT c1 = false; } 00737 } 00738 if (c1 && gm1->reuse() ) // must have type test first 00739 { REPORT SPDS(gm1,gm2); gm2->tDelete(); gmx = gm1; } 00740 else if (c2 && gm2->reuse() ) 00741 { REPORT SPDS(gm2,gm1); if (!c1) gm1->tDelete(); gmx = gm2; } 00742 else 00743 { 00744 REPORT 00745 // what if New throws and exception 00746 Try { gmx = mtd.New(nr,nc,this); } 00747 CatchAll 00748 { 00749 if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete(); 00750 #ifdef TEMPS_DESTROYED_QUICKLY 00751 delete this; 00752 #endif 00753 ReThrow; 00754 } 00755 SPDS(gmx,gm1,gm2); 00756 if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete(); 00757 gmx->ReleaseAndDelete(); 00758 } 00759 } 00760 #ifdef TEMPS_DESTROYED_QUICKLY 00761 delete this; 00762 #endif 00763 return gmx; 00764 } 00765 00766 00767 00768 //*************************** norm functions ****************************/ 00769 00770 Real BaseMatrix::Norm1() const 00771 { 00772 // maximum of sum of absolute values of a column 00773 REPORT 00774 GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00775 int nc = gm->Ncols(); Real value = 0.0; 00776 MatrixCol mc(gm, LoadOnEntry); 00777 while (nc--) 00778 { Real v = mc.SumAbsoluteValue(); if (value < v) value = v; mc.Next(); } 00779 gm->tDelete(); return value; 00780 } 00781 00782 Real BaseMatrix::NormInfinity() const 00783 { 00784 // maximum of sum of absolute values of a row 00785 REPORT 00786 GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00787 int nr = gm->Nrows(); Real value = 0.0; 00788 MatrixRow mr(gm, LoadOnEntry); 00789 while (nr--) 00790 { Real v = mr.SumAbsoluteValue(); if (value < v) value = v; mr.Next(); } 00791 gm->tDelete(); return value; 00792 } 00793 00794 //********************** Concatenation and stacking *************************/ 00795 00796 GeneralMatrix* ConcatenatedMatrix::Evaluate(MatrixType mtx) 00797 { 00798 REPORT 00799 Tracer tr("Concatenate"); 00800 #ifdef TEMPS_DESTROYED_QUICKLY 00801 Try 00802 { 00803 gm2 = ((BaseMatrix*&)bm2)->Evaluate(); 00804 gm1 = ((BaseMatrix*&)bm1)->Evaluate(); 00805 Compare(gm1->Type() | gm2->Type(),mtx); 00806 int nr=gm1->Nrows(); int nc = gm1->Ncols() + gm2->Ncols(); 00807 if (nr != gm2->Nrows()) 00808 Throw(IncompatibleDimensionsException(*gm1, *gm2)); 00809 GeneralMatrix* gmx = mtx.New(nr,nc,this); 00810 MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry); 00811 MatrixRow mr(gmx, StoreOnExit+DirectPart); 00812 while (nr--) { mr.ConCat(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); } 00813 gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); delete this; 00814 return gmx; 00815 } 00816 CatchAll { delete this; ReThrow; } 00817 #ifndef UseExceptions 00818 return 0; 00819 #endif 00820 #else 00821 gm2 = ((BaseMatrix*&)bm2)->Evaluate(); 00822 gm1 = ((BaseMatrix*&)bm1)->Evaluate(); 00823 Compare(gm1->Type() | gm2->Type(),mtx); 00824 int nr=gm1->Nrows(); int nc = gm1->Ncols() + gm2->Ncols(); 00825 if (nr != gm2->Nrows()) 00826 Throw(IncompatibleDimensionsException(*gm1, *gm2)); 00827 GeneralMatrix* gmx = mtx.New(nr,nc,this); 00828 MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry); 00829 MatrixRow mr(gmx, StoreOnExit+DirectPart); 00830 while (nr--) { mr.ConCat(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); } 00831 gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx; 00832 #endif 00833 } 00834 00835 GeneralMatrix* StackedMatrix::Evaluate(MatrixType mtx) 00836 { 00837 REPORT 00838 Tracer tr("Stack"); 00839 #ifdef TEMPS_DESTROYED_QUICKLY 00840 Try 00841 { 00842 gm2 = ((BaseMatrix*&)bm2)->Evaluate(); 00843 gm1 = ((BaseMatrix*&)bm1)->Evaluate(); 00844 Compare(gm1->Type() & gm2->Type(),mtx); 00845 int nc=gm1->Ncols(); 00846 int nr1 = gm1->Nrows(); int nr2 = gm2->Nrows(); 00847 if (nc != gm2->Ncols()) 00848 Throw(IncompatibleDimensionsException(*gm1, *gm2)); 00849 GeneralMatrix* gmx = mtx.New(nr1+nr2,nc,this); 00850 MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry); 00851 MatrixRow mr(gmx, StoreOnExit+DirectPart); 00852 while (nr1--) { mr.Copy(mr1); mr1.Next(); mr.Next(); } 00853 while (nr2--) { mr.Copy(mr2); mr2.Next(); mr.Next(); } 00854 gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); delete this; 00855 return gmx; 00856 } 00857 CatchAll { delete this; ReThrow; } 00858 #ifndef UseExceptions 00859 return 0; 00860 #endif 00861 #else 00862 gm2 = ((BaseMatrix*&)bm2)->Evaluate(); 00863 gm1 = ((BaseMatrix*&)bm1)->Evaluate(); 00864 Compare(gm1->Type() & gm2->Type(),mtx); 00865 int nc=gm1->Ncols(); 00866 int nr1 = gm1->Nrows(); int nr2 = gm2->Nrows(); 00867 if (nc != gm2->Ncols()) 00868 Throw(IncompatibleDimensionsException(*gm1, *gm2)); 00869 GeneralMatrix* gmx = mtx.New(nr1+nr2,nc,this); 00870 MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry); 00871 MatrixRow mr(gmx, StoreOnExit+DirectPart); 00872 while (nr1--) { mr.Copy(mr1); mr1.Next(); mr.Next(); } 00873 while (nr2--) { mr.Copy(mr2); mr2.Next(); mr.Next(); } 00874 gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx; 00875 #endif 00876 } 00877 00878 // ************************* equality of matrices ******************** // 00879 00880 static bool RealEqual(Real* s1, Real* s2, int n) 00881 { 00882 int i = n >> 2; 00883 while (i--) 00884 { 00885 if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false; 00886 if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false; 00887 } 00888 i = n & 3; while (i--) if (*s1++ != *s2++) return false; 00889 return true; 00890 } 00891 00892 static bool intEqual(int* s1, int* s2, int n) 00893 { 00894 int i = n >> 2; 00895 while (i--) 00896 { 00897 if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false; 00898 if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false; 00899 } 00900 i = n & 3; while (i--) if (*s1++ != *s2++) return false; 00901 return true; 00902 } 00903 00904 00905 bool operator==(const BaseMatrix& A, const BaseMatrix& B) 00906 { 00907 Tracer tr("BaseMatrix =="); 00908 REPORT 00909 GeneralMatrix* gmA = ((BaseMatrix&)A).Evaluate(); 00910 GeneralMatrix* gmB = ((BaseMatrix&)B).Evaluate(); 00911 00912 if (gmA == gmB) // same matrix 00913 { REPORT gmA->tDelete(); return true; } 00914 00915 if ( gmA->Nrows() != gmB->Nrows() || gmA->Ncols() != gmB->Ncols() ) 00916 // different dimensions 00917 { REPORT gmA->tDelete(); gmB->tDelete(); return false; } 00918 00919 // check for CroutMatrix or BandLUMatrix 00920 MatrixType AType = gmA->Type(); MatrixType BType = gmB->Type(); 00921 if (AType.CannotConvert() || BType.CannotConvert() ) 00922 { 00923 REPORT 00924 bool bx = gmA->IsEqual(*gmB); 00925 gmA->tDelete(); gmB->tDelete(); 00926 return bx; 00927 } 00928 00929 // is matrix storage the same 00930 // will need to modify if further matrix structures are introduced 00931 if (AType == BType && gmA->BandWidth() == gmB->BandWidth()) 00932 { // compare store 00933 REPORT 00934 bool bx = RealEqual(gmA->Store(),gmB->Store(),gmA->Storage()); 00935 gmA->tDelete(); gmB->tDelete(); 00936 return bx; 00937 } 00938 00939 // matrix storage different - just subtract 00940 REPORT return IsZero(*gmA-*gmB); 00941 } 00942 00943 bool operator==(const GeneralMatrix& A, const GeneralMatrix& B) 00944 { 00945 Tracer tr("GeneralMatrix =="); 00946 // May or may not call tDeletes 00947 REPORT 00948 00949 if (&A == &B) // same matrix 00950 { REPORT return true; } 00951 00952 if ( A.Nrows() != B.Nrows() || A.Ncols() != B.Ncols() ) 00953 { REPORT return false; } // different dimensions 00954 00955 // check for CroutMatrix or BandLUMatrix 00956 MatrixType AType = A.Type(); MatrixType BType = B.Type(); 00957 if (AType.CannotConvert() || BType.CannotConvert() ) 00958 { REPORT return A.IsEqual(B); } 00959 00960 // is matrix storage the same 00961 // will need to modify if further matrix structures are introduced 00962 if (AType == BType && A.BandWidth() == B.BandWidth()) 00963 { REPORT return RealEqual(A.Store(),B.Store(),A.Storage()); } 00964 00965 // matrix storage different - just subtract 00966 REPORT return IsZero(A-B); 00967 } 00968 00969 bool GeneralMatrix::IsZero() const 00970 { 00971 REPORT 00972 Real* s=store; int i = storage >> 2; 00973 while (i--) 00974 { 00975 if (*s++) return false; if (*s++) return false; 00976 if (*s++) return false; if (*s++) return false; 00977 } 00978 i = storage & 3; while (i--) if (*s++) return false; 00979 return true; 00980 } 00981 00982 bool IsZero(const BaseMatrix& A) 00983 { 00984 Tracer tr("BaseMatrix::IsZero"); 00985 REPORT 00986 GeneralMatrix* gm1 = 0; bool bx; 00987 Try { gm1=((BaseMatrix&)A).Evaluate(); bx = gm1->IsZero(); } 00988 CatchAll { if (gm1) gm1->tDelete(); ReThrow; } 00989 gm1->tDelete(); 00990 return bx; 00991 } 00992 00993 // IsEqual functions - insist matrices are of same type 00994 // as well as equal values to be equal 00995 00996 bool GeneralMatrix::IsEqual(const GeneralMatrix& A) const 00997 { 00998 Tracer tr("GeneralMatrix IsEqual"); 00999 if (A.Type() != Type()) // not same types 01000 { REPORT return false; } 01001 if (&A == this) // same matrix 01002 { REPORT return true; } 01003 if (A.nrows != nrows || A.ncols != ncols) 01004 // different dimensions 01005 { REPORT return false; } 01006 // is matrix storage the same - compare store 01007 REPORT 01008 return RealEqual(A.store,store,storage); 01009 } 01010 01011 bool CroutMatrix::IsEqual(const GeneralMatrix& A) const 01012 { 01013 Tracer tr("CroutMatrix IsEqual"); 01014 if (A.Type() != Type()) // not same types 01015 { REPORT return false; } 01016 if (&A == this) // same matrix 01017 { REPORT return true; } 01018 if (A.nrows != nrows || A.ncols != ncols) 01019 // different dimensions 01020 { REPORT return false; } 01021 // is matrix storage the same - compare store 01022 REPORT 01023 return RealEqual(A.store,store,storage) 01024 && intEqual(((CroutMatrix&)A).indx, indx, nrows); 01025 } 01026 01027 01028 bool BandLUMatrix::IsEqual(const GeneralMatrix& A) const 01029 { 01030 Tracer tr("BandLUMatrix IsEqual"); 01031 if (A.Type() != Type()) // not same types 01032 { REPORT return false; } 01033 if (&A == this) // same matrix 01034 { REPORT return true; } 01035 if ( A.Nrows() != nrows || A.Ncols() != ncols 01036 || ((BandLUMatrix&)A).m1 != m1 || ((BandLUMatrix&)A).m2 != m2 ) 01037 // different dimensions 01038 { REPORT return false; } 01039 01040 // matrix storage the same - compare store 01041 REPORT 01042 return RealEqual(A.Store(),store,storage) 01043 && RealEqual(((BandLUMatrix&)A).store2,store2,storage2) 01044 && intEqual(((BandLUMatrix&)A).indx, indx, nrows); 01045 } 01046 01047 01048 #ifdef use_namespace 01049 } 01050 #endif 01051 01052