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