00001
00002
00003
00004
00005
00006 #include "include.h"
00007
00008 #include "newmat.h"
00009 #include "newmatrc.h"
00010
00011 #ifdef use_namespace
00012 namespace NEWMAT {
00013 #endif
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 GeneralMatrix* GeneralMatrix::MakeSolver() {
00024 REPORT
00025 GeneralMatrix* gm = new CroutMatrix(*this);
00026 MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
00027 }
00028
00029 GeneralMatrix* Matrix::MakeSolver() {
00030 REPORT
00031 GeneralMatrix* gm = new CroutMatrix(*this);
00032 MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
00033 }
00034
00035 void CroutMatrix::Solver(MatrixColX& mcout, const MatrixColX& mcin) {
00036 REPORT
00037 int i = mcin.skip; Real* el = mcin.data-i; Real* el1 = el;
00038 while (i--) *el++ = 0.0;
00039 el += mcin.storage; i = nrows - mcin.skip - mcin.storage;
00040 while (i--) *el++ = 0.0;
00041 lubksb(el1, mcout.skip);
00042 }
00043
00044
00045
00046 void UpperTriangularMatrix::Solver(MatrixColX& mcout,
00047 const MatrixColX& mcin) {
00048 REPORT
00049 int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
00050 while (i-- > 0) *elx++ = 0.0;
00051 int nr = mcin.skip+mcin.storage;
00052 elx = mcin.data+mcin.storage; Real* el = elx;
00053 int j = mcout.skip+mcout.storage-nr; int nc = ncols-nr; i = nr-mcout.skip;
00054 while (j-- > 0) *elx++ = 0.0;
00055 Real* Ael = store + (nr*(2*ncols-nr+1))/2; j = 0;
00056 while (i-- > 0) {
00057 elx = el; Real sum = 0.0; int jx = j++; Ael -= nc;
00058 while (jx--) sum += *(--Ael) * *(--elx);
00059 elx--; *elx = (*elx - sum) / *(--Ael);
00060 }
00061 }
00062
00063 void LowerTriangularMatrix::Solver(MatrixColX& mcout,
00064 const MatrixColX& mcin) {
00065 REPORT
00066 int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
00067 while (i-- > 0) *elx++ = 0.0;
00068 int nc = mcin.skip; i = nc+mcin.storage; elx = mcin.data+mcin.storage;
00069 int nr = mcout.skip+mcout.storage; int j = nr-i; i = nr-nc;
00070 while (j-- > 0) *elx++ = 0.0;
00071 Real* el = mcin.data; Real* Ael = store + (nc*(nc+1))/2; j = 0;
00072 while (i-- > 0) {
00073 elx = el; Real sum = 0.0; int jx = j++; Ael += nc;
00074 while (jx--) sum += *Ael++ * *elx++;
00075 *elx = (*elx - sum) / *Ael++;
00076 }
00077 }
00078
00079
00080
00081 static GeneralMatrix*
00082 GeneralAdd(GeneralMatrix*,GeneralMatrix*,AddedMatrix*,MatrixType);
00083 static GeneralMatrix*
00084 GeneralSub(GeneralMatrix*,GeneralMatrix*,SubtractedMatrix*,MatrixType);
00085 static GeneralMatrix*
00086 GeneralMult(GeneralMatrix*,GeneralMatrix*,MultipliedMatrix*,MatrixType);
00087 static GeneralMatrix*
00088 GeneralSolv(GeneralMatrix*,GeneralMatrix*,BaseMatrix*,MatrixType);
00089 static GeneralMatrix*
00090 GeneralSP(GeneralMatrix*,GeneralMatrix*,SPMatrix*,MatrixType);
00091 static GeneralMatrix*
00092 GeneralElmDivide(GeneralMatrix*,GeneralMatrix*,ElmDivideMatrix*,MatrixType);
00093
00094 GeneralMatrix* AddedMatrix::Evaluate(MatrixType mt) {
00095 REPORT
00096 gm1=((BaseMatrix*&)bm1)->Evaluate();
00097 gm2=((BaseMatrix*&)bm2)->Evaluate();
00098 #ifdef TEMPS_DESTROYED_QUICKLY
00099 GeneralMatrix* gmx;
00100 Try { gmx = GeneralAdd(gm1,gm2,this,mt); }
00101 CatchAll { delete this; ReThrow; }
00102 delete this; return gmx;
00103 #else
00104 return GeneralAdd(gm1,gm2,this,mt);
00105 #endif
00106 }
00107
00108 GeneralMatrix* SubtractedMatrix::Evaluate(MatrixType mt) {
00109 REPORT
00110 gm1=((BaseMatrix*&)bm1)->Evaluate();
00111 gm2=((BaseMatrix*&)bm2)->Evaluate();
00112 #ifdef TEMPS_DESTROYED_QUICKLY
00113 GeneralMatrix* gmx;
00114 Try { gmx = GeneralSub(gm1,gm2,this,mt); }
00115 CatchAll { delete this; ReThrow; }
00116 delete this; return gmx;
00117 #else
00118 return GeneralSub(gm1,gm2,this,mt);
00119 #endif
00120 }
00121
00122 GeneralMatrix* MultipliedMatrix::Evaluate(MatrixType mt) {
00123 REPORT
00124 gm2 = ((BaseMatrix*&)bm2)->Evaluate();
00125 gm2 = gm2->Evaluate(gm2->Type().MultRHS());
00126 gm1=((BaseMatrix*&)bm1)->Evaluate();
00127 #ifdef TEMPS_DESTROYED_QUICKLY
00128 GeneralMatrix* gmx;
00129 Try { gmx = GeneralMult(gm1, gm2, this, mt); }
00130 CatchAll { delete this; ReThrow; }
00131 delete this; return gmx;
00132 #else
00133 return GeneralMult(gm1, gm2, this, mt);
00134 #endif
00135 }
00136
00137 GeneralMatrix* SolvedMatrix::Evaluate(MatrixType mt) {
00138 REPORT
00139 gm1=((BaseMatrix*&)bm1)->Evaluate();
00140 gm2=((BaseMatrix*&)bm2)->Evaluate();
00141 #ifdef TEMPS_DESTROYED_QUICKLY
00142 GeneralMatrix* gmx;
00143 Try { gmx = GeneralSolv(gm1,gm2,this,mt); }
00144 CatchAll { delete this; ReThrow; }
00145 delete this; return gmx;
00146 #else
00147 return GeneralSolv(gm1,gm2,this,mt);
00148 #endif
00149 }
00150
00151 GeneralMatrix* SPMatrix::Evaluate(MatrixType mt) {
00152 REPORT
00153 gm1=((BaseMatrix*&)bm1)->Evaluate();
00154 gm2=((BaseMatrix*&)bm2)->Evaluate();
00155 #ifdef TEMPS_DESTROYED_QUICKLY
00156 GeneralMatrix* gmx;
00157 Try { gmx = GeneralSP(gm1,gm2,this,mt); }
00158 CatchAll { delete this; ReThrow; }
00159 delete this; return gmx;
00160 #else
00161 return GeneralSP(gm1,gm2,this,mt);
00162 #endif
00163 }
00164
00165 GeneralMatrix* ElmDivideMatrix::Evaluate(MatrixType mt) {
00166 REPORT
00167 gm1=((BaseMatrix*&)bm1)->Evaluate();
00168 gm2=((BaseMatrix*&)bm2)->Evaluate();
00169 #ifdef TEMPS_DESTROYED_QUICKLY
00170 GeneralMatrix* gmx;
00171 Try { gmx = GeneralElmDivide(gm1,gm2,this,mt); }
00172 CatchAll { delete this; ReThrow; }
00173 delete this; return gmx;
00174 #else
00175 return GeneralElmDivide(gm1,gm2,this,mt);
00176 #endif
00177 }
00178
00179
00180
00181 static void Add(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) {
00182 REPORT
00183 Real* s1=gm1->Store(); Real* s2=gm2->Store();
00184 Real* s=gm->Store(); int i=gm->Storage() >> 2;
00185 while (i--) {
00186 *s++ = *s1++ + *s2++; *s++ = *s1++ + *s2++;
00187 *s++ = *s1++ + *s2++; *s++ = *s1++ + *s2++;
00188 }
00189 i=gm->Storage() & 3; while (i--) *s++ = *s1++ + *s2++;
00190 }
00191
00192 static void Add(GeneralMatrix* gm, GeneralMatrix* gm2) {
00193 REPORT
00194 Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
00195 while (i--)
00196 { *s++ += *s2++; *s++ += *s2++; *s++ += *s2++; *s++ += *s2++; }
00197 i=gm->Storage() & 3; while (i--) *s++ += *s2++;
00198 }
00199
00200 static void Subtract(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) {
00201 REPORT
00202 Real* s1=gm1->Store(); Real* s2=gm2->Store();
00203 Real* s=gm->Store(); int i=gm->Storage() >> 2;
00204 while (i--) {
00205 *s++ = *s1++ - *s2++; *s++ = *s1++ - *s2++;
00206 *s++ = *s1++ - *s2++; *s++ = *s1++ - *s2++;
00207 }
00208 i=gm->Storage() & 3; while (i--) *s++ = *s1++ - *s2++;
00209 }
00210
00211 static void Subtract(GeneralMatrix* gm, GeneralMatrix* gm2) {
00212 REPORT
00213 Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
00214 while (i--)
00215 { *s++ -= *s2++; *s++ -= *s2++; *s++ -= *s2++; *s++ -= *s2++; }
00216 i=gm->Storage() & 3; while (i--) *s++ -= *s2++;
00217 }
00218
00219 static void ReverseSubtract(GeneralMatrix* gm, GeneralMatrix* gm2) {
00220 REPORT
00221 Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
00222 while (i--) {
00223 *s = *s2++ - *s; s++; *s = *s2++ - *s; s++;
00224 *s = *s2++ - *s; s++; *s = *s2++ - *s; s++;
00225 }
00226 i=gm->Storage() & 3; while (i--) { *s = *s2++ - *s; s++; }
00227 }
00228
00229 static void SP(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) {
00230 REPORT
00231 Real* s1=gm1->Store(); Real* s2=gm2->Store();
00232 Real* s=gm->Store(); int i=gm->Storage() >> 2;
00233 while (i--) {
00234 *s++ = *s1++ * *s2++; *s++ = *s1++ * *s2++;
00235 *s++ = *s1++ * *s2++; *s++ = *s1++ * *s2++;
00236 }
00237 i=gm->Storage() & 3; while (i--) *s++ = *s1++ * *s2++;
00238 }
00239
00240 static void SP(GeneralMatrix* gm, GeneralMatrix* gm2) {
00241 REPORT
00242 Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
00243 while (i--)
00244 { *s++ *= *s2++; *s++ *= *s2++; *s++ *= *s2++; *s++ *= *s2++; }
00245 i=gm->Storage() & 3; while (i--) *s++ *= *s2++;
00246 }
00247
00248 static void ElmDivide(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) {
00249 REPORT
00250 Real* s1=gm1->Store(); Real* s2=gm2->Store();
00251 Real* s=gm->Store(); int i=gm->Storage() >> 2;
00252 while (i--) {
00253 *s++ = *s1++ / *s2++; *s++ = *s1++ / *s2++;
00254 *s++ = *s1++ / *s2++; *s++ = *s1++ / *s2++;
00255 }
00256 i=gm->Storage() & 3; while (i--) *s++ = *s1++ / *s2++;
00257 }
00258
00259 static void ElmDivide(GeneralMatrix* gm, GeneralMatrix* gm2) {
00260 REPORT
00261 Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
00262 while (i--)
00263 { *s++ /= *s2++; *s++ /= *s2++; *s++ /= *s2++; *s++ /= *s2++; }
00264 i=gm->Storage() & 3; while (i--) *s++ /= *s2++;
00265 }
00266
00267
00268
00269 static void AddDS(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) {
00270 int nr = gm->Nrows();
00271 MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
00272 MatrixRow mr(gm, StoreOnExit+DirectPart);
00273 while (nr--) { mr.Add(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
00274 }
00275
00276 static void AddDS(GeneralMatrix* gm, GeneralMatrix* gm2) {
00277
00278 int nr = gm->Nrows();
00279 MatrixRow mr(gm, StoreOnExit+LoadOnEntry+DirectPart);
00280 MatrixRow mr2(gm2, LoadOnEntry);
00281 while (nr--) { mr.Add(mr2); mr.Next(); mr2.Next(); }
00282 }
00283
00284 static void SubtractDS
00285 (GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) {
00286 int nr = gm->Nrows();
00287 MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
00288 MatrixRow mr(gm, StoreOnExit+DirectPart);
00289 while (nr--) { mr.Sub(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
00290 }
00291
00292 static void SubtractDS(GeneralMatrix* gm, GeneralMatrix* gm2) {
00293 int nr = gm->Nrows();
00294 MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart);
00295 MatrixRow mr2(gm2, LoadOnEntry);
00296 while (nr--) { mr.Sub(mr2); mr.Next(); mr2.Next(); }
00297 }
00298
00299 static void ReverseSubtractDS(GeneralMatrix* gm, GeneralMatrix* gm2) {
00300 int nr = gm->Nrows();
00301 MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart);
00302 MatrixRow mr2(gm2, LoadOnEntry);
00303 while (nr--) { mr.RevSub(mr2); mr2.Next(); mr.Next(); }
00304 }
00305
00306 static void SPDS(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2) {
00307 int nr = gm->Nrows();
00308 MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
00309 MatrixRow mr(gm, StoreOnExit+DirectPart);
00310 while (nr--) { mr.Multiply(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
00311 }
00312
00313 static void SPDS(GeneralMatrix* gm, GeneralMatrix* gm2) {
00314
00315 int nr = gm->Nrows();
00316 MatrixRow mr(gm, StoreOnExit+LoadOnEntry+DirectPart);
00317 MatrixRow mr2(gm2, LoadOnEntry);
00318 while (nr--) { mr.Multiply(mr2); mr.Next(); mr2.Next(); }
00319 }
00320
00321 #ifdef __GNUG__
00322 void AddedMatrix::SelectVersion
00323 (MatrixType mtx, int& c1, int& c2) const
00324 #else
00325 void AddedMatrix::SelectVersion
00326 (MatrixType mtx, bool& c1, bool& c2) const
00327 #endif
00328 {
00329
00330
00331 MatrixBandWidth bw1 = gm1->BandWidth();
00332 MatrixBandWidth bw2 = gm2->BandWidth();
00333 MatrixBandWidth bwx(-1); if (mtx.IsBand()) bwx = bw1 + bw2;
00334 c1 = (mtx == gm1->Type()) && (bwx == bw1);
00335 c2 = (mtx == gm2->Type()) && (bwx == bw2);
00336 }
00337
00338 static GeneralMatrix* GeneralAdd(GeneralMatrix* gm1, GeneralMatrix* gm2,
00339 AddedMatrix* am, MatrixType mtx) {
00340 Tracer tr("GeneralAdd");
00341 int nr=gm1->Nrows(); int nc=gm1->Ncols();
00342 if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
00343 Throw(IncompatibleDimensionsException(*gm1, *gm2));
00344 Compare(gm1->Type() + gm2->Type(),mtx);
00345 #ifdef __GNUG__
00346 int c1,c2; am->SelectVersion(mtx,c1,c2);
00347 #else
00348 bool c1,c2; am->SelectVersion(mtx,c1,c2);
00349 #endif
00350 if (c1 && c2) {
00351 if (gm1->reuse()) { REPORT Add(gm1,gm2); gm2->tDelete(); return gm1; }
00352 else if (gm2->reuse()) { REPORT Add(gm2,gm1); return gm2; }
00353 else {
00354 REPORT GeneralMatrix* gmx = gm1->Type().New(nr,nc,am);
00355 gmx->ReleaseAndDelete(); Add(gmx,gm1,gm2); return gmx;
00356 }
00357 }
00358 else {
00359 if (c1 && gm1->reuse() )
00360 { REPORT AddDS(gm1,gm2); gm2->tDelete(); return gm1; }
00361 else if (c2 && gm2->reuse() )
00362 { REPORT AddDS(gm2,gm1); if (!c1) gm1->tDelete(); return gm2; }
00363 else {
00364 REPORT
00365 GeneralMatrix* gmx = mtx.New(nr,nc,am); AddDS(gmx,gm1,gm2);
00366 if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
00367 gmx->ReleaseAndDelete(); return gmx;
00368 }
00369 }
00370 }
00371
00372 static GeneralMatrix* GeneralSub(GeneralMatrix* gm1, GeneralMatrix* gm2,
00373 SubtractedMatrix* sm, MatrixType mtx) {
00374 Tracer tr("GeneralSub");
00375 Compare(gm1->Type() + gm2->Type(),mtx);
00376 int nr=gm1->Nrows(); int nc=gm1->Ncols();
00377 if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
00378 Throw(IncompatibleDimensionsException(*gm1, *gm2));
00379 #ifdef __GNUG__
00380 int c1,c2; sm->SelectVersion(mtx,c1,c2);
00381 #else
00382 bool c1,c2; sm->SelectVersion(mtx,c1,c2);
00383 #endif
00384 if (c1 && c2) {
00385 if (gm1->reuse())
00386 { REPORT Subtract(gm1,gm2); gm2->tDelete(); return gm1; }
00387 else if (gm2->reuse()) { REPORT ReverseSubtract(gm2,gm1); return gm2; }
00388 else {
00389 REPORT
00390 GeneralMatrix* gmx = gm1->Type().New(nr,nc,sm);
00391 gmx->ReleaseAndDelete(); Subtract(gmx,gm1,gm2); return gmx;
00392 }
00393 }
00394 else {
00395 if ( c1 && gm1->reuse() )
00396 { REPORT SubtractDS(gm1,gm2); gm2->tDelete(); return gm1; }
00397 else if ( c2 && gm2->reuse() ) {
00398 REPORT
00399 ReverseSubtractDS(gm2,gm1); if (!c1) gm1->tDelete(); return gm2;
00400 }
00401 else {
00402 REPORT
00403 GeneralMatrix* gmx = mtx.New(nr,nc,sm); SubtractDS(gmx,gm1,gm2);
00404 if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
00405 gmx->ReleaseAndDelete(); return gmx;
00406 }
00407 }
00408 }
00409
00410 static GeneralMatrix* GeneralMult1(GeneralMatrix* gm1, GeneralMatrix* gm2,
00411 MultipliedMatrix* mm, MatrixType mtx) {
00412 REPORT
00413 Tracer tr("GeneralMult1");
00414 int nr=gm1->Nrows(); int nc=gm2->Ncols();
00415 if (gm1->Ncols() !=gm2->Nrows())
00416 Throw(IncompatibleDimensionsException(*gm1, *gm2));
00417 GeneralMatrix* gmx = mtx.New(nr,nc,mm);
00418
00419 MatrixCol mcx(gmx, StoreOnExit+DirectPart);
00420 MatrixCol mc2(gm2, LoadOnEntry);
00421 while (nc--) {
00422 MatrixRow mr1(gm1, LoadOnEntry, mcx.Skip());
00423 Real* el = mcx.Data();
00424 int n = mcx.Storage();
00425 while (n--) { *(el++) = DotProd(mr1,mc2); mr1.Next(); }
00426 mc2.Next(); mcx.Next();
00427 }
00428 gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
00429 }
00430
00431 static GeneralMatrix* GeneralMult2(GeneralMatrix* gm1, GeneralMatrix* gm2,
00432 MultipliedMatrix* mm, MatrixType mtx) {
00433
00434
00435 REPORT
00436 Tracer tr("GeneralMult2");
00437 int nr=gm1->Nrows(); int nc=gm2->Ncols();
00438 if (gm1->Ncols() !=gm2->Nrows())
00439 Throw(IncompatibleDimensionsException(*gm1, *gm2));
00440 GeneralMatrix* gmx = mtx.New(nr,nc,mm);
00441
00442 Real* el = gmx->Store(); int n = gmx->Storage();
00443 while (n--) *el++ = 0.0;
00444 MatrixRow mrx(gmx, LoadOnEntry+StoreOnExit+DirectPart);
00445 MatrixRow mr1(gm1, LoadOnEntry);
00446 while (nr--) {
00447 MatrixRow mr2(gm2, LoadOnEntry, mr1.Skip());
00448 el = mr1.Data();
00449 n = mr1.Storage();
00450 while (n--) { mrx.AddScaled(mr2, *el++); mr2.Next(); }
00451 mr1.Next(); mrx.Next();
00452 }
00453 gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
00454 }
00455
00456 static GeneralMatrix* mmMult(GeneralMatrix* gm1, GeneralMatrix* gm2) {
00457
00458 REPORT
00459 Tracer tr("MatrixMult");
00460
00461 int nr=gm1->Nrows(); int ncr=gm1->Ncols(); int nc=gm2->Ncols();
00462 if (ncr != gm2->Nrows()) Throw(IncompatibleDimensionsException(*gm1,*gm2));
00463
00464 Matrix* gm = new Matrix(nr,nc); MatrixErrorNoSpace(gm);
00465
00466 Real* s1=gm1->Store(); Real* s2=gm2->Store(); Real* s=gm->Store();
00467
00468 if (ncr) {
00469 while (nr--) {
00470 Real* s2x = s2; int j = ncr;
00471 Real* sx = s; Real f = *s1++; int k = nc;
00472 while (k--) *sx++ = f * *s2x++;
00473 while (--j)
00474 { sx = s; f = *s1++; k = nc; while (k--) *sx++ += f * *s2x++; }
00475 s = sx;
00476 }
00477 }
00478 else *gm = 0.0;
00479
00480 gm->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gm;
00481 }
00482
00483 static GeneralMatrix* GeneralMult(GeneralMatrix* gm1, GeneralMatrix* gm2,
00484 MultipliedMatrix* mm, MatrixType mtx) {
00485 if ( Rectangular(gm1->Type(), gm2->Type(), mtx)) return mmMult(gm1, gm2);
00486 else {
00487 Compare(gm1->Type() * gm2->Type(),mtx);
00488 int nr = gm2->Nrows(); int nc = gm2->Ncols();
00489 if (nc <= 5 && nr > nc) return GeneralMult1(gm1, gm2, mm, mtx);
00490 else return GeneralMult2(gm1, gm2, mm, mtx);
00491 }
00492 }
00493
00494 #ifdef __GNUG__
00495 void SPMatrix::SelectVersion
00496 (MatrixType mtx, int& c1, int& c2) const
00497 #else
00498 void SPMatrix::SelectVersion
00499 (MatrixType mtx, bool& c1, bool& c2) const
00500 #endif
00501 {
00502
00503
00504 MatrixBandWidth bw1 = gm1->BandWidth();
00505 MatrixBandWidth bw2 = gm2->BandWidth();
00506 MatrixBandWidth bwx(-1); if (mtx.IsBand()) bwx = bw1.minimum(bw2);
00507 c1 = (mtx == gm1->Type()) && (bwx == bw1);
00508 c2 = (mtx == gm2->Type()) && (bwx == bw2);
00509 }
00510
00511 static GeneralMatrix* GeneralSP(GeneralMatrix* gm1, GeneralMatrix* gm2,
00512 SPMatrix* am, MatrixType mtx) {
00513 Tracer tr("GeneralSP");
00514 int nr=gm1->Nrows(); int nc=gm1->Ncols();
00515 if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
00516 Throw(IncompatibleDimensionsException(*gm1, *gm2));
00517 Compare(gm1->Type().SP(gm2->Type()),mtx);
00518 #ifdef __GNUG__
00519 int c1,c2; am->SelectVersion(mtx,c1,c2);
00520 #else
00521 bool c1,c2; am->SelectVersion(mtx,c1,c2);
00522 #endif
00523 if (c1 && c2) {
00524 if (gm1->reuse()) { REPORT SP(gm1,gm2); gm2->tDelete(); return gm1; }
00525 else if (gm2->reuse()) { REPORT SP(gm2,gm1); return gm2; }
00526 else {
00527 REPORT GeneralMatrix* gmx = gm1->Type().New(nr,nc,am);
00528 gmx->ReleaseAndDelete(); SP(gmx,gm1,gm2); return gmx;
00529 }
00530 }
00531 else {
00532 if (c1 && gm1->reuse() )
00533 { REPORT SPDS(gm1,gm2); gm2->tDelete(); return gm1; }
00534 else if (c2 && gm2->reuse() )
00535 { REPORT SPDS(gm2,gm1); if (!c1) gm1->tDelete(); return gm2; }
00536 else {
00537 REPORT
00538 GeneralMatrix* gmx = mtx.New(nr,nc,am); SPDS(gmx,gm1,gm2);
00539 if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
00540 gmx->ReleaseAndDelete(); return gmx;
00541 }
00542 }
00543 }
00544
00545
00546 static GeneralMatrix* GeneralElmDivide(GeneralMatrix* gm1, GeneralMatrix* gm2,
00547 ElmDivideMatrix* am, MatrixType mtx) {
00548 Tracer tr("GeneralElmDivide");
00549 int nr=gm1->Nrows(); int nc=gm1->Ncols();
00550 if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
00551 Throw(IncompatibleDimensionsException(*gm1, *gm2));
00552 Compare(gm1->Type().SP(gm2->Type()),mtx);
00553 #ifdef __GNUG__
00554 int c1,c2; am->SelectVersion(mtx,c1,c2);
00555 #else
00556 bool c1,c2; am->SelectVersion(mtx,c1,c2);
00557 #endif
00558 if (c1 && c2) {
00559 if (gm1->reuse()) { REPORT ElmDivide(gm1,gm2); gm2->tDelete(); return gm1; }
00560 else if (gm2->reuse()) { REPORT ElmDivide(gm2,gm1); return gm2; }
00561 else {
00562 REPORT GeneralMatrix* gmx = gm1->Type().New(nr,nc,am);
00563 gmx->ReleaseAndDelete(); ElmDivide(gmx,gm1,gm2); return gmx;
00564 }
00565 }
00566 else {
00567 return gm1;
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 }
00585 }
00586
00587 static GeneralMatrix* GeneralSolv(GeneralMatrix* gm1, GeneralMatrix* gm2,
00588 BaseMatrix* sm, MatrixType mtx) {
00589 REPORT
00590 Tracer tr("GeneralSolv");
00591 Compare(gm1->Type().i() * gm2->Type(),mtx);
00592 int nr=gm1->Nrows(); int nc=gm2->Ncols();
00593 if (gm1->Ncols() != gm2->Nrows())
00594 Throw(IncompatibleDimensionsException(*gm1, *gm2));
00595 GeneralMatrix* gmx = mtx.New(nr,nc,sm); MatrixErrorNoSpace(gmx);
00596 Real* r = new Real [nr]; MatrixErrorNoSpace(r);
00597 #ifndef ATandT
00598 MONITOR_REAL_NEW("Make (GenSolv)",nr,r)
00599
00600 #endif
00601 GeneralMatrix* gms = gm1->MakeSolver();
00602 Try {
00603
00604 MatrixColX mcx(gmx, r, StoreOnExit+DirectPart);
00605
00606 MatrixColX mc2(gm2, r, LoadOnEntry);
00607 while (nc--) { gms->Solver(mcx, mc2); mcx.Next(); mc2.Next(); }
00608 }
00609 CatchAll {
00610 gms->tDelete();
00611 delete gmx;
00612 gm2->tDelete();
00613 #ifndef ATandT
00614 MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r)
00615
00616 #endif
00617 delete [] r;
00618 ReThrow;
00619 }
00620 gms->tDelete(); gmx->ReleaseAndDelete(); gm2->tDelete();
00621 #ifndef ATandT
00622 MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r)
00623
00624 #endif
00625 delete [] r;
00626 return gmx;
00627 }
00628
00629 GeneralMatrix* InvertedMatrix::Evaluate(MatrixType mtx) {
00630
00631 Tracer tr("InvertedMatrix::Evaluate");
00632 REPORT
00633 gm=((BaseMatrix*&)bm)->Evaluate();
00634 int n = gm->Nrows(); DiagonalMatrix I(n); I=1.0;
00635 #ifdef TEMPS_DESTROYED_QUICKLY
00636 GeneralMatrix* gmx;
00637 Try {
00638 Compare(gm->Type().i(),mtx);
00639 SkipConversionCheck SCC;
00640
00641 gmx = GeneralSolv(gm,&I,this,mtx);
00642 }
00643 CatchAll { delete this; ReThrow; }
00644 delete this; return gmx;
00645 #else
00646 Compare(gm->Type().i(),mtx);
00647 SkipConversionCheck SCC;
00648
00649 return GeneralSolv(gm,&I,this,mtx);
00650 #endif
00651 }
00652
00653
00654
00655 Real BaseMatrix::Norm1() const {
00656
00657 REPORT
00658 GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
00659 int nc = gm->Ncols(); Real value = 0.0;
00660 MatrixCol mc(gm, LoadOnEntry);
00661 while (nc--)
00662 { Real v = mc.SumAbsoluteValue(); if (value < v) value = v; mc.Next(); }
00663 gm->tDelete(); return value;
00664 }
00665
00666 Real BaseMatrix::NormInfinity() const {
00667
00668 REPORT
00669 GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
00670 int nr = gm->Nrows(); Real value = 0.0;
00671 MatrixRow mr(gm, LoadOnEntry);
00672 while (nr--)
00673 { Real v = mr.SumAbsoluteValue(); if (value < v) value = v; mr.Next(); }
00674 gm->tDelete(); return value;
00675 }
00676
00677
00678
00679 GeneralMatrix* ConcatenatedMatrix::Evaluate(MatrixType mtx) {
00680 REPORT
00681 Tracer tr("Concatenate");
00682 #ifdef TEMPS_DESTROYED_QUICKLY
00683 Try {
00684 gm2 = ((BaseMatrix*&)bm2)->Evaluate();
00685 gm1 = ((BaseMatrix*&)bm1)->Evaluate();
00686 Compare(gm1->Type() | gm2->Type(),mtx);
00687 int nr=gm1->Nrows(); int nc = gm1->Ncols() + gm2->Ncols();
00688 if (nr != gm2->Nrows())
00689 Throw(IncompatibleDimensionsException(*gm1, *gm2));
00690 GeneralMatrix* gmx = mtx.New(nr,nc,this);
00691 MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
00692 MatrixRow mr(gmx, StoreOnExit+DirectPart);
00693 while (nr--) { mr.ConCat(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
00694 gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); delete this;
00695 return gmx;
00696 }
00697 CatchAll { delete this; ReThrow; }
00698 #ifndef UseExceptions
00699 return 0;
00700 #endif
00701 #else
00702 gm2 = ((BaseMatrix*&)bm2)->Evaluate();
00703 gm1 = ((BaseMatrix*&)bm1)->Evaluate();
00704 Compare(gm1->Type() | gm2->Type(),mtx);
00705 int nr=gm1->Nrows(); int nc = gm1->Ncols() + gm2->Ncols();
00706 if (nr != gm2->Nrows())
00707 Throw(IncompatibleDimensionsException(*gm1, *gm2));
00708 GeneralMatrix* gmx = mtx.New(nr,nc,this);
00709 MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
00710 MatrixRow mr(gmx, StoreOnExit+DirectPart);
00711 while (nr--) { mr.ConCat(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
00712 gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
00713 #endif
00714 }
00715
00716 GeneralMatrix* StackedMatrix::Evaluate(MatrixType mtx) {
00717 REPORT
00718 Tracer tr("Stack");
00719 #ifdef TEMPS_DESTROYED_QUICKLY
00720 Try {
00721 gm2 = ((BaseMatrix*&)bm2)->Evaluate();
00722 gm1 = ((BaseMatrix*&)bm1)->Evaluate();
00723 Compare(gm1->Type() & gm2->Type(),mtx);
00724 int nc=gm1->Ncols();
00725 int nr1 = gm1->Nrows(); int nr2 = gm2->Nrows();
00726 if (nc != gm2->Ncols())
00727 Throw(IncompatibleDimensionsException(*gm1, *gm2));
00728 GeneralMatrix* gmx = mtx.New(nr1+nr2,nc,this);
00729 MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
00730 MatrixRow mr(gmx, StoreOnExit+DirectPart);
00731 while (nr1--) { mr.Copy(mr1); mr1.Next(); mr.Next(); }
00732 while (nr2--) { mr.Copy(mr2); mr2.Next(); mr.Next(); }
00733 gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); delete this;
00734 return gmx;
00735 }
00736 CatchAll { delete this; ReThrow; }
00737 #ifndef UseExceptions
00738 return 0;
00739 #endif
00740 #else
00741 gm2 = ((BaseMatrix*&)bm2)->Evaluate();
00742 gm1 = ((BaseMatrix*&)bm1)->Evaluate();
00743 Compare(gm1->Type() & gm2->Type(),mtx);
00744 int nc=gm1->Ncols();
00745 int nr1 = gm1->Nrows(); int nr2 = gm2->Nrows();
00746 if (nc != gm2->Ncols())
00747 Throw(IncompatibleDimensionsException(*gm1, *gm2));
00748 GeneralMatrix* gmx = mtx.New(nr1+nr2,nc,this);
00749 MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
00750 MatrixRow mr(gmx, StoreOnExit+DirectPart);
00751 while (nr1--) { mr.Copy(mr1); mr1.Next(); mr.Next(); }
00752 while (nr2--) { mr.Copy(mr2); mr2.Next(); mr.Next(); }
00753 gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
00754 #endif
00755 }
00756
00757
00758
00759 static bool RealEqual(Real* s1, Real* s2, int n) {
00760 int i = n >> 2;
00761 while (i--) {
00762 if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
00763 if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
00764 }
00765 i = n & 3; while (i--) if (*s1++ != *s2++) return false;
00766 return true;
00767 }
00768
00769 static bool intEqual(int* s1, int* s2, int n) {
00770 int i = n >> 2;
00771 while (i--) {
00772 if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
00773 if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
00774 }
00775 i = n & 3; while (i--) if (*s1++ != *s2++) return false;
00776 return true;
00777 }
00778
00779 bool operator==(const BaseMatrix& A, const BaseMatrix& B) {
00780 Tracer tr("BaseMatrix ==");
00781 REPORT
00782 GeneralMatrix* gmA = ((BaseMatrix&)A).Evaluate();
00783 GeneralMatrix* gmB = ((BaseMatrix&)B).Evaluate();
00784
00785 if (gmA == gmB)
00786 { REPORT gmA->tDelete(); return true; }
00787
00788 if ( gmA->Nrows() != gmB->Nrows() || gmA->Ncols() != gmB->Ncols() )
00789
00790 { REPORT gmA->tDelete(); gmB->tDelete(); return false; }
00791
00792
00793 MatrixType AType = gmA->Type(); MatrixType BType = gmB->Type();
00794 if (AType.CannotConvert() || BType.CannotConvert() ) {
00795 REPORT
00796 bool bx = gmA->IsEqual(*gmB);
00797 gmA->tDelete(); gmB->tDelete();
00798 return bx;
00799 }
00800
00801
00802
00803 if (AType == BType && gmA->BandWidth() == gmB->BandWidth()) {
00804
00805 REPORT
00806 bool bx = RealEqual(gmA->Store(),gmB->Store(),gmA->Storage());
00807 gmA->tDelete(); gmB->tDelete();
00808 return bx;
00809 }
00810
00811
00812 REPORT return IsZero(*gmA-*gmB);
00813 }
00814
00815 bool operator==(const GeneralMatrix& A, const GeneralMatrix& B) {
00816 Tracer tr("GeneralMatrix ==");
00817
00818 REPORT
00819
00820 if (&A == &B)
00821 { REPORT return true; }
00822
00823 if ( A.Nrows() != B.Nrows() || A.Ncols() != B.Ncols() ) {
00824
00825 REPORT return false;
00826 }
00827
00828
00829 MatrixType AType = A.Type(); MatrixType BType = B.Type();
00830 if (AType.CannotConvert() || BType.CannotConvert() )
00831 { REPORT return A.IsEqual(B); }
00832
00833
00834
00835 if (AType == BType && A.BandWidth() == B.BandWidth())
00836 { REPORT return RealEqual(A.Store(),B.Store(),A.Storage()); }
00837
00838
00839 REPORT return IsZero(A-B);
00840 }
00841
00842 bool GeneralMatrix::IsZero() const {
00843 REPORT
00844 Real* s=store; int i = storage >> 2;
00845 while (i--) {
00846 if (*s++) return false; if (*s++) return false;
00847 if (*s++) return false; if (*s++) return false;
00848 }
00849 i = storage & 3; while (i--) if (*s++) return false;
00850 return true;
00851 }
00852
00853 bool IsZero(const BaseMatrix& A) {
00854 Tracer tr("BaseMatrix::IsZero");
00855 REPORT
00856 GeneralMatrix* gm1 = 0; bool bx;
00857 Try { gm1=((BaseMatrix&)A).Evaluate(); bx = gm1->IsZero(); }
00858 CatchAll { if (gm1) gm1->tDelete(); ReThrow; }
00859 gm1->tDelete();
00860 return bx;
00861 }
00862
00863
00864
00865
00866 bool GeneralMatrix::IsEqual(const GeneralMatrix& A) const {
00867 Tracer tr("GeneralMatrix IsEqual");
00868 if (A.Type() != Type())
00869 { REPORT return false; }
00870 if (&A == this)
00871 { REPORT return true; }
00872 if (A.nrows != nrows || A.ncols != ncols)
00873
00874 { REPORT return false; }
00875
00876 REPORT
00877 return RealEqual(A.store,store,storage);
00878 }
00879
00880 bool CroutMatrix::IsEqual(const GeneralMatrix& A) const {
00881 Tracer tr("CroutMatrix IsEqual");
00882 if (A.Type() != Type())
00883 { REPORT return false; }
00884 if (&A == this)
00885 { REPORT return true; }
00886 if (A.nrows != nrows || A.ncols != ncols)
00887
00888 { REPORT return false; }
00889
00890 REPORT
00891 return RealEqual(A.store,store,storage)
00892 && intEqual(((CroutMatrix&)A).indx, indx, nrows);
00893 }
00894
00895 bool BandLUMatrix::IsEqual(const GeneralMatrix& A) const {
00896 Tracer tr("BandLUMatrix IsEqual");
00897 if (A.Type() != Type())
00898 { REPORT return false; }
00899 if (&A == this)
00900 { REPORT return true; }
00901 if ( A.Nrows() != nrows || A.Ncols() != ncols
00902 || ((BandLUMatrix&)A).m1 != m1 || ((BandLUMatrix&)A).m2 != m2 )
00903
00904 { REPORT return false; }
00905
00906
00907 REPORT
00908 return RealEqual(A.Store(),store,storage)
00909 && RealEqual(((BandLUMatrix&)A).store2,store2,storage2)
00910 && intEqual(((BandLUMatrix&)A).indx, indx, nrows);
00911 }
00912
00913 #ifdef use_namespace
00914 }
00915 #endif