00001
00002
00003
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
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
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
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());
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
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
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
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
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();
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
00320
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();
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
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);
00430
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
00441 delete [] r;
00442 ReThrow;
00443 }
00444 gms->tDelete(); gmx->ReleaseAndDelete(); gm2->tDelete();
00445 MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r)
00446
00447 delete [] r;
00448 return gmx;
00449 }
00450
00451
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
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);
00471
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
00481 delete [] r;
00482 ReThrow;
00483 }
00484 gms->tDelete(); gmx->ReleaseAndDelete();
00485 MONITOR_REAL_DELETE("Delete (GenSolvI)",nr,r)
00486
00487 delete [] r;
00488 return gmx;
00489 }
00490
00491 GeneralMatrix* InvertedMatrix::Evaluate(MatrixType mtx)
00492 {
00493
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
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
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() )
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() )
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
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; }
00736 if (SAO & 2) { REPORT c1 = false; }
00737 }
00738 if (c1 && gm1->reuse() )
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
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
00769
00770 Real BaseMatrix::Norm1() const
00771 {
00772
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
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
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
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)
00913 { REPORT gmA->tDelete(); return true; }
00914
00915 if ( gmA->Nrows() != gmB->Nrows() || gmA->Ncols() != gmB->Ncols() )
00916
00917 { REPORT gmA->tDelete(); gmB->tDelete(); return false; }
00918
00919
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
00930
00931 if (AType == BType && gmA->BandWidth() == gmB->BandWidth())
00932 {
00933 REPORT
00934 bool bx = RealEqual(gmA->Store(),gmB->Store(),gmA->Storage());
00935 gmA->tDelete(); gmB->tDelete();
00936 return bx;
00937 }
00938
00939
00940 REPORT return IsZero(*gmA-*gmB);
00941 }
00942
00943 bool operator==(const GeneralMatrix& A, const GeneralMatrix& B)
00944 {
00945 Tracer tr("GeneralMatrix ==");
00946
00947 REPORT
00948
00949 if (&A == &B)
00950 { REPORT return true; }
00951
00952 if ( A.Nrows() != B.Nrows() || A.Ncols() != B.Ncols() )
00953 { REPORT return false; }
00954
00955
00956 MatrixType AType = A.Type(); MatrixType BType = B.Type();
00957 if (AType.CannotConvert() || BType.CannotConvert() )
00958 { REPORT return A.IsEqual(B); }
00959
00960
00961
00962 if (AType == BType && A.BandWidth() == B.BandWidth())
00963 { REPORT return RealEqual(A.Store(),B.Store(),A.Storage()); }
00964
00965
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
00994
00995
00996 bool GeneralMatrix::IsEqual(const GeneralMatrix& A) const
00997 {
00998 Tracer tr("GeneralMatrix IsEqual");
00999 if (A.Type() != Type())
01000 { REPORT return false; }
01001 if (&A == this)
01002 { REPORT return true; }
01003 if (A.nrows != nrows || A.ncols != ncols)
01004
01005 { REPORT return false; }
01006
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())
01015 { REPORT return false; }
01016 if (&A == this)
01017 { REPORT return true; }
01018 if (A.nrows != nrows || A.ncols != ncols)
01019
01020 { REPORT return false; }
01021
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())
01032 { REPORT return false; }
01033 if (&A == this)
01034 { REPORT return true; }
01035 if ( A.Nrows() != nrows || A.Ncols() != ncols
01036 || ((BandLUMatrix&)A).m1 != m1 || ((BandLUMatrix&)A).m2 != m2 )
01037
01038 { REPORT return false; }
01039
01040
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