Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

newmat7.cpp

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_value - 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;
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 //******************* carry out binary operations *************************/
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());     // no symmetric on RHS
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 // routines for adding or subtracting matrices of identical storage structure
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 // routines for adding or subtracting matrices of different storage structure
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 // Add into first argument
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 // SP into first argument
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();                         // pointer to an element
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    // version that accesses by row only - not good for thin matrices
00316    // or column vectors in right hand term.
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();                         // pointer to an element
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    // matrix multiplication for type Matrix only
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);   // copy to and from r
00426          // this must be inside Try so mcx is destroyed before gmx
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                           // AT&T version 2.1 gives an internal error
00437       delete [] r;
00438       ReThrow;
00439    }
00440    gms->tDelete(); gmx->ReleaseAndDelete(); gm2->tDelete();
00441    MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r)
00442                           // AT&T version 2.1 gives an internal error
00443    delete [] r;
00444    return gmx;
00445 }
00446 
00447 // version for inverses - gm2 is identity
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    // DiagonalMatrix I(nr); I = 1;
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);   // copy to and from r
00467          // this must be inside Try so mcx is destroyed before gmx
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                           // AT&T version 2.1 gives an internal error
00477       delete [] r;
00478       ReThrow;
00479    }
00480    gms->tDelete(); gmx->ReleaseAndDelete();
00481    MONITOR_REAL_DELETE("Delete (GenSolvI)",nr,r)
00482                           // AT&T version 2.1 gives an internal error
00483    delete [] r;
00484    return gmx;
00485 }
00486 
00487 GeneralMatrix* InvertedMatrix::Evaluate(MatrixType mtx)
00488 {
00489    // Matrix Inversion - use solve routines
00490    Tracer tr("InvertedMatrix::Evaluate");
00491    REPORT
00492    gm=(const_cast<BaseMatrix*&>(bm))->Evaluate();
00493    return GeneralSolvI(gm,this,mtx);
00494 }
00495 
00496 //*************************** New versions ************************
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          // what if new throws an exception
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() )               // must have type test first
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() )               // must have type test first
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          // what if New throws and exception
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; }    // c1 and c2 swapped
00687          if (SAO & 2) { REPORT c1 = false; }
00688       }
00689       if (c1 && gm1->reuse() )               // must have type test first
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          // what if New throws and exception
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 //*************************** norm functions ****************************/
00714 
00715 Real BaseMatrix::Norm1() const
00716 {
00717    // maximum of sum of absolute values of a column
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    // maximum of sum of absolute values of a row
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 //********************** Concatenation and stacking *************************/
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 // ************************* equality of matrices ******************** //
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)                            // same matrix
00812       { REPORT gmA->tDelete(); return true; }
00813 
00814    if ( gmA->Nrows() != gmB->Nrows() || gmA->Ncols() != gmB->Ncols() )
00815                                               // different dimensions
00816       { REPORT gmA->tDelete(); gmB->tDelete(); return false; }
00817 
00818    // check for CroutMatrix or BandLUMatrix
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    // is matrix storage the same
00829    // will need to modify if further matrix structures are introduced
00830    if (AType == BType && gmA->BandWidth() == gmB->BandWidth())
00831    {                                          // compare store
00832       REPORT
00833       bool bx = RealEqual(gmA->Store(),gmB->Store(),gmA->Storage());
00834       gmA->tDelete(); gmB->tDelete();
00835       return bx;
00836    }
00837 
00838    // matrix storage different - just subtract
00839    REPORT  return IsZero(*gmA-*gmB);
00840 }
00841 
00842 bool operator==(const GeneralMatrix& A, const GeneralMatrix& B)
00843 {
00844    Tracer tr("GeneralMatrix ==");
00845    // May or may not call tDeletes
00846    REPORT
00847 
00848    if (&A == &B)                              // same matrix
00849       { REPORT return true; }
00850 
00851    if ( A.Nrows() != B.Nrows() || A.Ncols() != B.Ncols() )
00852       { REPORT return false; }                // different dimensions
00853 
00854    // check for CroutMatrix or BandLUMatrix
00855    MatrixType AType = A.Type(); MatrixType BType = B.Type();
00856    if (AType.CannotConvert() || BType.CannotConvert() )
00857       { REPORT  return A.IsEqual(B); }
00858 
00859    // is matrix storage the same
00860    // will need to modify if further matrix structures are introduced
00861    if (AType == BType && A.BandWidth() == B.BandWidth())
00862       { REPORT return RealEqual(A.Store(),B.Store(),A.Storage()); }
00863 
00864    // matrix storage different - just subtract
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 // IsEqual functions - insist matrices are of same type
00893 // as well as equal values to be equal
00894 
00895 bool GeneralMatrix::IsEqual(const GeneralMatrix& A) const
00896 {
00897    Tracer tr("GeneralMatrix IsEqual");
00898    if (A.Type() != Type())                       // not same types
00899       { REPORT return false; }
00900    if (&A == this)                               // same matrix
00901       { REPORT  return true; }
00902    if (A.nrows_value != nrows_value || A.ncols_value != ncols_value)
00903                                                  // different dimensions
00904    { REPORT return false; }
00905    // is matrix storage the same - compare store
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())                       // not same types
00914       { REPORT return false; }
00915    if (&A == this)                               // same matrix
00916       { REPORT  return true; }
00917    if (A.nrows_value != nrows_value || A.ncols_value != ncols_value)
00918                                                  // different dimensions
00919    { REPORT return false; }
00920    // is matrix storage the same - compare store
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())                       // not same types
00931       { REPORT  return false; }
00932    if (&A == this)                               // same matrix
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                                                  // different dimensions
00937    { REPORT  return false; }
00938 
00939    // matrix storage the same - compare store
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 // ************************* quaternions ******************** //
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 // ************************* cross products ******************** //
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 

newmat11b
Generated Mon May 9 04:54:18 2016 by Doxygen 1.6.3