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


rl_agent
Author(s): Todd Hester
autogenerated on Thu Jun 6 2019 22:00:13