NewMatExhaustive.cpp
Go to the documentation of this file.
00001 
00002 
00003 
00008 
00009 // Copyright (C) 1991,2,3,4: R B Davies
00010 
00011 //#define WANT_STREAM
00012 
00013 #include "lo/NewMatExhaustive.h"
00017 Real fourbyfourident[] = {1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0};
00018 
00020 Real threebythreeident[] ={1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0};
00021 
00024 
00025 // Copyright (C) 1991,2,3,4,7: R B Davies
00026 
00027 #ifndef NEWMATRC_LIB
00028 #define NEWMATRC_LIB 0
00029 
00030 #ifdef use_namespace
00031 namespace NEWMAT {
00032 #endif
00033 
00036 
00040 
00041 
00042 #ifndef CONTROL_WORD_LIB
00043 #define CONTROL_WORD_LIB 0
00044 
00047 class ControlWord
00048 {
00049 protected:
00050    int cw;                                      // the control word
00051 public:
00052    ControlWord() : cw(0) {}                     // do nothing
00053    ControlWord(int i) : cw(i) {}                // load an integer
00054 
00055       // select specific bits (for testing at least one set)
00056    ControlWord operator*(ControlWord i) const
00057       { return ControlWord(cw & i.cw); }
00058    void operator*=(ControlWord i)  { cw &= i.cw; }
00059 
00060       // set bits
00061    ControlWord operator+(ControlWord i) const
00062       { return ControlWord(cw | i.cw); }
00063    void operator+=(ControlWord i)  { cw |= i.cw; }
00064 
00065       // reset bits
00066    ControlWord operator-(ControlWord i) const
00067       { return ControlWord(cw - (cw & i.cw)); }
00068    void operator-=(ControlWord i) { cw -= (cw & i.cw); }
00069 
00070       // check if all of selected bits set or reset
00071    bool operator>=(ControlWord i) const { return (cw & i.cw) == i.cw; }
00072    bool operator<=(ControlWord i) const { return (cw & i.cw) == cw; }
00073 
00074       // flip selected bits
00075    ControlWord operator^(ControlWord i) const
00076       { return ControlWord(cw ^ i.cw); }
00077    ControlWord operator~() const { return ControlWord(~cw); }
00078 
00079       // convert to integer
00080    int operator+() const { return cw; }
00081    int operator!() const { return cw==0; }
00082    FREE_CHECK(ControlWord)
00083 };
00084 
00085 
00086 #endif
00087 
00089 
00092 
00095 
00096 // Copyright (C) 1991,2,3,4: R B Davies
00097 
00098 #define WANT_MATH
00099 
00100 
00101 #ifdef use_namespace
00102 namespace NEWMAT {
00103 #endif
00104 
00105 #ifdef DO_REPORT
00106 #define REPORT { static ExeCounter ExeCount(__LINE__,12); ++ExeCount; }
00107 #else
00108 #define REPORT {}
00109 #endif
00110 
00111 
00112 // operations on rectangular matrices
00113 
00114 
00115 void RectMatrixRow::Reset (const Matrix& M, int row, int skip, int length)
00116 {
00117    REPORT
00118    RectMatrixRowCol::Reset
00119       ( M.Store()+row*M.Ncols()+skip, length, 1, M.Ncols() );
00120 }
00121 
00122 void RectMatrixRow::Reset (const Matrix& M, int row)
00123 {
00124    REPORT
00125    RectMatrixRowCol::Reset( M.Store()+row*M.Ncols(), M.Ncols(), 1, M.Ncols() );
00126 }
00127 
00128 void RectMatrixCol::Reset (const Matrix& M, int skip, int col, int length)
00129 {
00130    REPORT
00131    RectMatrixRowCol::Reset
00132       ( M.Store()+col+skip*M.Ncols(), length, M.Ncols(), 1 );
00133 }
00134 
00135 void RectMatrixCol::Reset (const Matrix& M, int col)
00136 {
00137    REPORT
00138    RectMatrixRowCol::Reset( M.Store()+col, M.Nrows(), M.Ncols(), 1 );
00139 }
00140 
00141 
00142 Real RectMatrixRowCol::SumSquare() const
00143 {
00144    REPORT
00145    long_Real sum = 0.0; int i = n; Real* s = store; int d = spacing;
00146    // while (i--) { sum += (long_Real)*s * *s; s += d; }
00147    if (i) for(;;)
00148       { sum += (long_Real)*s * *s; if (!(--i)) break; s += d; }
00149    return (Real)sum;
00150 }
00151 
00152 Real RectMatrixRowCol::operator*(const RectMatrixRowCol& rmrc) const
00153 {
00154    REPORT
00155    long_Real sum = 0.0; int i = n;
00156    Real* s = store; int d = spacing;
00157    Real* s1 = rmrc.store; int d1 = rmrc.spacing;
00158    if (i!=rmrc.n)
00159    {
00160       Tracer tr("newmatrm");
00161       Throw(InternalException("Dimensions differ in *"));
00162    }
00163    // while (i--) { sum += (long_Real)*s * *s1; s += d; s1 += d1; }
00164    if (i) for(;;)
00165       { sum += (long_Real)*s * *s1; if (!(--i)) break; s += d; s1 += d1; }
00166    return (Real)sum;
00167 }
00168 
00169 void RectMatrixRowCol::AddScaled(const RectMatrixRowCol& rmrc, Real r)
00170 {
00171    REPORT
00172    int i = n; Real* s = store; int d = spacing;
00173    Real* s1 = rmrc.store; int d1 = rmrc.spacing;
00174    if (i!=rmrc.n)
00175    {
00176       Tracer tr("newmatrm");
00177       Throw(InternalException("Dimensions differ in AddScaled"));
00178    }
00179    // while (i--) { *s += *s1 * r; s += d; s1 += d1; }
00180    if (i) for (;;)
00181       { *s += *s1 * r; if (!(--i)) break; s += d; s1 += d1; }
00182 }
00183 
00184 void RectMatrixRowCol::Divide(const RectMatrixRowCol& rmrc, Real r)
00185 {
00186    REPORT
00187    int i = n; Real* s = store; int d = spacing;
00188    Real* s1 = rmrc.store; int d1 = rmrc.spacing;
00189    if (i!=rmrc.n)
00190    {
00191       Tracer tr("newmatrm");
00192       Throw(InternalException("Dimensions differ in Divide"));
00193    }
00194    // while (i--) { *s = *s1 / r; s += d; s1 += d1; }
00195    if (i) for (;;) { *s = *s1 / r; if (!(--i)) break; s += d; s1 += d1; }
00196 }
00197 
00198 void RectMatrixRowCol::Divide(Real r)
00199 {
00200    REPORT
00201    int i = n; Real* s = store; int d = spacing;
00202    // while (i--) { *s /= r; s += d; }
00203    if (i) for (;;) { *s /= r; if (!(--i)) break; s += d; }
00204 }
00205 
00206 void RectMatrixRowCol::Negate()
00207 {
00208    REPORT
00209    int i = n; Real* s = store; int d = spacing;
00210    // while (i--) { *s = - *s; s += d; }
00211    if (i) for (;;) { *s = - *s; if (!(--i)) break; s += d; }
00212 }
00213 
00214 void RectMatrixRowCol::Zero()
00215 {
00216    REPORT
00217    int i = n; Real* s = store; int d = spacing;
00218    // while (i--) { *s = 0.0; s += d; }
00219    if (i) for (;;) { *s = 0.0; if (!(--i)) break; s += d; }
00220 }
00221 
00222 void ComplexScale(RectMatrixCol& U, RectMatrixCol& V, Real x, Real y)
00223 {
00224    REPORT
00225    int n = U.n;
00226    if (n != V.n)
00227    {
00228       Tracer tr("newmatrm");
00229       Throw(InternalException("Dimensions differ in ComplexScale"));
00230    }
00231    Real* u = U.store; Real* v = V.store; 
00232    int su = U.spacing; int sv = V.spacing;
00233    //while (n--)
00234    //{
00235    //   Real z = *u * x - *v * y;  *v =  *u * y + *v * x;  *u = z;
00236    //   u += su;  v += sv;
00237    //}
00238    if (n) for (;;)
00239    {
00240       Real z = *u * x - *v * y;  *v =  *u * y + *v * x;  *u = z;
00241       if (!(--n)) break;
00242       u += su;  v += sv;
00243    }
00244 }
00245 
00246 void Rotate(RectMatrixCol& U, RectMatrixCol& V, Real tau, Real s)
00247 {
00248    REPORT
00249    //  (U, V) = (U, V) * (c, s)  where  tau = s/(1+c), c^2 + s^2 = 1
00250    int n = U.n;
00251    if (n != V.n)
00252    {
00253       Tracer tr("newmatrm");
00254       Throw(InternalException("Dimensions differ in Rotate"));
00255    }
00256    Real* u = U.store; Real* v = V.store;
00257    int su = U.spacing; int sv = V.spacing;
00258    //while (n--)
00259    //{
00260    //   Real zu = *u; Real zv = *v;
00261    //   *u -= s * (zv + zu * tau); *v += s * (zu - zv * tau);
00262    //   u += su;  v += sv;
00263    //}
00264    if (n) for(;;)
00265    {
00266       Real zu = *u; Real zv = *v;
00267       *u -= s * (zv + zu * tau); *v += s * (zu - zv * tau);
00268       if (!(--n)) break;
00269       u += su;  v += sv;
00270    }
00271 }
00272 
00273 
00274 // misc procedures for numerical things
00275 
00276 Real pythag(Real f, Real g, Real& c, Real& s)
00277 // return z=sqrt(f*f+g*g), c=f/z, s=g/z
00278 // set c=1,s=0 if z==0
00279 // avoid floating point overflow or divide by zero
00280 {
00281    if (f==0 && g==0) { c=1.0; s=0.0; return 0.0; }
00282    Real af = f>=0 ? f : -f;
00283    Real ag = g>=0 ? g : -g;
00284    if (ag<af)
00285    {
00286       REPORT
00287       Real h = g/f; Real sq = sqrt(1.0+h*h);
00288       if (f<0) sq = -sq;           // make return value non-negative
00289       c = 1.0/sq; s = h/sq; return sq*f;
00290    }
00291    else
00292    {
00293       REPORT
00294       Real h = f/g; Real sq = sqrt(1.0+h*h);
00295       if (g<0) sq = -sq;
00296       s = 1.0/sq; c = h/sq; return sq*g;
00297    }
00298 }
00299 
00300 
00301 
00302 
00303 #ifdef use_namespace
00304 }
00305 #endif
00306 
00307 
00309 
00310 
00311 /************** classes MatrixRowCol, MatrixRow, MatrixCol *****************/
00312 
00313 // Used for accessing the rows and columns of matrices
00314 // All matrix classes must provide routines for calculating matrix rows and
00315 // columns. Assume rows can be found very efficiently.
00316 
00317 enum LSF { LoadOnEntry=1,StoreOnExit=2,DirectPart=4,StoreHere=8,HaveStore=16 };
00318 
00319 
00322 class LoadAndStoreFlag : public ControlWord
00323 {
00324 public:
00325    LoadAndStoreFlag() {}
00326    LoadAndStoreFlag(int i) : ControlWord(i) {}
00327    LoadAndStoreFlag(LSF lsf) : ControlWord(lsf) {}
00328    LoadAndStoreFlag(const ControlWord& cwx) : ControlWord(cwx) {}
00329 };
00330 
00331 
00334 class MatrixRowCol
00335 {
00336 public:                                        // these are public to avoid
00337                                                // numerous friend statements
00338    int length;                                 // row or column length
00339    int skip;                                   // initial number of zeros
00340    int storage;                                // number of stored elements
00341    int rowcol;                                 // row or column number
00342    GeneralMatrix* gm;                          // pointer to parent matrix
00343    Real* data;                                 // pointer to local storage
00344    LoadAndStoreFlag cw;                        // Load? Store? Is a Copy?
00345    void IncrMat() { rowcol++; data += storage; }   // used by NextRow
00346    void IncrDiag() { rowcol++; skip++; data++; }
00347    void IncrId() { rowcol++; skip++; }
00348    void IncrUT() { rowcol++; data += storage; storage--; skip++; }
00349    void IncrLT() { rowcol++; data += storage; storage++; }
00350 
00351 public:
00352    void Zero();                                // set elements to zero
00353    void Add(const MatrixRowCol&);              // add a row/col
00354    void AddScaled(const MatrixRowCol&, Real);  // add a multiple of a row/col
00355    void Add(const MatrixRowCol&, const MatrixRowCol&);
00356                                                // add two rows/cols
00357    void Add(const MatrixRowCol&, Real);        // add a row/col
00358    void NegAdd(const MatrixRowCol&, Real);     // Real - a row/col
00359    void Sub(const MatrixRowCol&);              // subtract a row/col
00360    void Sub(const MatrixRowCol&, const MatrixRowCol&);
00361                                                // sub a row/col from another
00362    void RevSub(const MatrixRowCol&);           // subtract from a row/col
00363    void ConCat(const MatrixRowCol&, const MatrixRowCol&);
00364                                                // concatenate two row/cols
00365    void Multiply(const MatrixRowCol&);         // multiply a row/col
00366    void Multiply(const MatrixRowCol&, const MatrixRowCol&);
00367                                                // multiply two row/cols
00368    void KP(const MatrixRowCol&, const MatrixRowCol&);
00369                                                // Kronecker Product two row/cols
00370    void Copy(const MatrixRowCol&);             // copy a row/col
00371    void CopyCheck(const MatrixRowCol&);        // ... check for data loss
00372    void Check(const MatrixRowCol&);            // just check for data loss
00373    void Check();                               // check full row/col present
00374    void Copy(const double*&);                  // copy from an array
00375    void Copy(const float*&);                   // copy from an array
00376    void Copy(const int*&);                     // copy from an array
00377    void Copy(Real);                            // copy from constant
00378    void Add(Real);                             // add a constant
00379    void Multiply(Real);                        // multiply by constant
00380    Real SumAbsoluteValue();                    // sum of absolute values
00381    Real MaximumAbsoluteValue1(Real r, int& i); // maximum of absolute values
00382    Real MinimumAbsoluteValue1(Real r, int& i); // minimum of absolute values
00383    Real Maximum1(Real r, int& i);              // maximum
00384    Real Minimum1(Real r, int& i);              // minimum
00385    Real Sum();                                 // sum of values
00386    void Inject(const MatrixRowCol&);           // copy stored els of a row/col
00387    void Negate(const MatrixRowCol&);           // change sign of a row/col
00388    void Multiply(const MatrixRowCol&, Real);   // scale a row/col
00389    friend Real DotProd(const MatrixRowCol&, const MatrixRowCol&);
00390                                                // sum of pairwise product
00391    Real* Data() { return data; }
00392    int Skip() { return skip; }                 // number of elements skipped
00393    int Storage() { return storage; }           // number of elements stored
00394    int Length() { return length; }             // length of row or column
00395    void Skip(int i) { skip=i; }
00396    void Storage(int i) { storage=i; }
00397    void Length(int i) { length=i; }
00398    void SubRowCol(MatrixRowCol&, int, int) const;
00399                                                // get part of a row or column
00400    MatrixRowCol() {}                           // to stop warning messages
00401    ~MatrixRowCol();
00402    FREE_CHECK(MatrixRowCol)
00403 };
00404 
00407 class MatrixRow : public MatrixRowCol
00408 {
00409 public:
00410    // bodies for these are inline at the end of this .h file
00411    MatrixRow(GeneralMatrix*, LoadAndStoreFlag, int=0);
00412                                                // extract a row
00413    ~MatrixRow();
00414    void Next();                                // get next row
00415    FREE_CHECK(MatrixRow)
00416 };
00417 
00420 class MatrixCol : public MatrixRowCol
00421 {
00422 public:
00423    // bodies for these are inline at the end of this .h file
00424    MatrixCol(GeneralMatrix*, LoadAndStoreFlag, int=0);
00425                                                // extract a col
00426    MatrixCol(GeneralMatrix*, Real*, LoadAndStoreFlag, int=0);
00427                                                // store/retrieve a col
00428    ~MatrixCol();
00429    void Next();                                // get next column
00430    FREE_CHECK(MatrixCol)
00431 };
00432 
00435 class MatrixColX : public MatrixRowCol
00436 {
00437 public:
00438    // bodies for these are inline at the end of this .h file
00439    MatrixColX(GeneralMatrix*, Real*, LoadAndStoreFlag, int=0);
00440                                                // store/retrieve a col
00441    ~MatrixColX();
00442    void Next();                                // get next row
00443    Real* store;                                // pointer to local storage
00444                                                //    less skip
00445    FREE_CHECK(MatrixColX)
00446 };
00447 
00448 /**************************** inline bodies ****************************/
00449 
00450 inline MatrixRow::MatrixRow(GeneralMatrix* gmx, LoadAndStoreFlag cwx, int row)
00451 { gm=gmx; cw=cwx; rowcol=row; gm->GetRow(*this); }
00452 
00453 inline void MatrixRow::Next() { gm->NextRow(*this); }
00454 
00455 inline MatrixCol::MatrixCol(GeneralMatrix* gmx, LoadAndStoreFlag cwx, int col)
00456 { gm=gmx; cw=cwx; rowcol=col; gm->GetCol(*this); }
00457 
00458 inline MatrixCol::MatrixCol(GeneralMatrix* gmx, Real* r,
00459    LoadAndStoreFlag cwx, int col)
00460 { gm=gmx; data=r; cw=cwx+StoreHere; rowcol=col; gm->GetCol(*this); }
00461 
00462 inline MatrixColX::MatrixColX(GeneralMatrix* gmx, Real* r,
00463    LoadAndStoreFlag cwx, int col)
00464 { gm=gmx; store=data=r; cw=cwx+StoreHere; rowcol=col; gm->GetCol(*this); }
00465 
00466 
00467 inline void MatrixCol::Next() { gm->NextCol(*this); }
00468 
00469 inline void MatrixColX::Next() { gm->NextCol(*this); }
00470 
00471 #ifdef use_namespace
00472 }
00473 #endif
00474 
00475 #endif
00476 
00477 
00479 
00480 #ifdef use_namespace
00481 namespace NEWMAT {
00482 #endif
00483 
00484 #ifdef DO_REPORT
00485 #define REPORT { static ExeCounter ExeCount(__LINE__,1); ++ExeCount; }
00486 #else
00487 #define REPORT {}
00488 #endif
00489 
00490 
00491 /************************* MatrixType functions *****************************/
00492 
00493 
00494 // Skew needs more work <<<<<<<<<
00495 
00496 // all operations to return MatrixTypes which correspond to valid types
00497 // of matrices.
00498 // Eg: if it has the Diagonal attribute, then it must also have
00499 // Upper, Lower, Band, Square and Symmetric.
00500 
00501 
00502 MatrixType MatrixType::operator*(const MatrixType& mt) const
00503 {
00504    REPORT
00505    int a = attribute & mt.attribute & ~(Symmetric | Skew);
00506    a |= (a & Diagonal) * 63;                   // recognise diagonal
00507    return MatrixType(a);
00508 }
00509 
00510 MatrixType MatrixType::SP(const MatrixType& mt) const
00511 // elementwise product
00512 // Lower, Upper, Diag, Band if only one is
00513 // Symmetric, Ones, Valid (and Real) if both are
00514 // Need to include Lower & Upper => Diagonal
00515 // Will need to include both Skew => Symmetric
00516 {
00517    REPORT
00518    int a = ((attribute | mt.attribute) & ~(Symmetric + Skew + Valid + Ones))
00519       | (attribute & mt.attribute);
00520    if ((a & Lower) != 0  &&  (a & Upper) != 0) a |= Diagonal;
00521    if ((attribute & Skew) != 0)
00522    {
00523       if ((mt.attribute & Symmetric) != 0) a |= Skew;  
00524       if ((mt.attribute & Skew) != 0) { a &= ~Skew; a |= Symmetric; }
00525    }
00526    else if ((mt.attribute & Skew) != 0 && (attribute & Symmetric) != 0)
00527       a |= Skew;  
00528    a |= (a & Diagonal) * 63;                   // recognise diagonal
00529    return MatrixType(a);
00530 }
00531 
00532 MatrixType MatrixType::KP(const MatrixType& mt) const
00533 // Kronecker product
00534 // Lower, Upper, Diag, Symmetric, Band, Valid if both are
00535 // Band if LHS is band & other is square 
00536 // Ones is complicated so leave this out
00537 {
00538    REPORT
00539    int a = (attribute & mt.attribute)  & ~Ones;
00540    if ((attribute & Band) != 0 && (mt.attribute & Square) != 0)
00541       a |= Band;
00542    //int a = ((attribute & mt.attribute) | (attribute & Band)) & ~Ones;
00543 
00544    return MatrixType(a);
00545 }
00546 
00547 MatrixType MatrixType::i() const               // type of inverse
00548 {
00549    REPORT
00550    int a = attribute & ~(Band+LUDeco);
00551    a |= (a & Diagonal) * 63;                   // recognise diagonal
00552    return MatrixType(a);
00553 }
00554 
00555 MatrixType MatrixType::t() const
00556 // swap lower and upper attributes
00557 // assume Upper is in bit above Lower
00558 {
00559    REPORT
00560    int a = attribute;
00561    a ^= (((a >> 1) ^ a) & Lower) * 3;
00562    return MatrixType(a);
00563 }
00564 
00565 MatrixType MatrixType::MultRHS() const
00566 {
00567    REPORT
00568    // remove symmetric attribute unless diagonal
00569    return (attribute >= Dg) ? attribute : (attribute & ~Symmetric);
00570 }
00571 
00572 // this is used for deciding type of multiplication
00573 bool Rectangular(MatrixType a, MatrixType b, MatrixType c)
00574 {
00575    REPORT
00576    return
00577       ((a.attribute | b.attribute | c.attribute)
00578       & ~(MatrixType::Valid | MatrixType::Square)) == 0;
00579 }
00580 
00581 const char* MatrixType::value() const
00582 {
00583 // make a string with the name of matrix with the given attributes
00584    switch (attribute)
00585    {
00586    case Valid:                              REPORT return "Rect ";
00587    case Valid+Square:                       REPORT return "Squ  ";
00588    case Valid+Symmetric+Square:             REPORT return "Sym  ";
00589    case Valid+Skew+Square:                  REPORT return "Skew ";
00590    case Valid+Band+Square:                  REPORT return "Band ";
00591    case Valid+Symmetric+Band+Square:        REPORT return "SmBnd";
00592    case Valid+Skew+Band+Square:             REPORT return "SkBnd";
00593    case Valid+Upper+Square:                 REPORT return "UT   ";
00594    case Valid+Diagonal+Symmetric+Band+Upper+Lower+Square:
00595                                             REPORT return "Diag ";
00596    case Valid+Diagonal+Symmetric+Band+Upper+Lower+Ones+Square:
00597                                             REPORT return "Ident";
00598    case Valid+Band+Upper+Square:            REPORT return "UpBnd";
00599    case Valid+Lower+Square:                 REPORT return "LT   ";
00600    case Valid+Band+Lower+Square:            REPORT return "LwBnd";
00601    default:
00602       REPORT
00603       if (!(attribute & Valid))             return "UnSp ";
00604       if (attribute & LUDeco)
00605          return (attribute & Band) ?     "BndLU" : "Crout";
00606                                             return "?????";
00607    }
00608 }
00609 
00610 
00611 GeneralMatrix* MatrixType::New(int nr, int nc, BaseMatrix* bm) const
00612 {
00613 // make a new matrix with the given attributes
00614 
00615    Tracer tr("New"); GeneralMatrix* gm=0;   // initialised to keep gnu happy
00616    switch (attribute)
00617    {
00618    case Valid:
00619       REPORT
00620       if (nc==1) { gm = new ColumnVector(nr); break; }
00621       if (nr==1) { gm = new RowVector(nc); break; }
00622       gm = new Matrix(nr, nc); break;
00623 
00624    case Valid+Square:
00625       REPORT
00626       if (nc!=nr) { Throw(NotSquareException()); }
00627       gm = new SquareMatrix(nr); break;
00628 
00629    case Valid+Symmetric+Square:
00630       REPORT gm = new SymmetricMatrix(nr); break;
00631 
00632    case Valid+Band+Square:
00633       {
00634          REPORT
00635          MatrixBandWidth bw = bm->bandwidth();
00636          gm = new BandMatrix(nr,bw.lower_val,bw.upper_val); break;
00637       }
00638 
00639    case Valid+Symmetric+Band+Square:
00640       REPORT gm = new SymmetricBandMatrix(nr,bm->bandwidth().lower_val); break;
00641 
00642    case Valid+Upper+Square:
00643       REPORT gm = new UpperTriangularMatrix(nr); break;
00644 
00645    case Valid+Diagonal+Symmetric+Band+Upper+Lower+Square:
00646       REPORT gm = new DiagonalMatrix(nr); break;
00647 
00648    case Valid+Band+Upper+Square:
00649       REPORT gm = new UpperBandMatrix(nr,bm->bandwidth().upper_val); break;
00650 
00651    case Valid+Lower+Square:
00652       REPORT gm = new LowerTriangularMatrix(nr); break;
00653 
00654    case Valid+Band+Lower+Square:
00655       REPORT gm = new LowerBandMatrix(nr,bm->bandwidth().lower_val); break;
00656 
00657    case Valid+Diagonal+Symmetric+Band+Upper+Lower+Ones+Square:
00658       REPORT gm = new IdentityMatrix(nr); break;
00659 
00660    default:
00661       Throw(ProgramException("Invalid matrix type"));
00662    }
00663    
00664    MatrixErrorNoSpace(gm); gm->Protect(); return gm;
00665 }
00666 
00667 
00668 #ifdef use_namespace
00669 }
00670 #endif
00671 
00672 
00673 
00677 
00680 
00681 
00682 // Copyright (C) 1991,2,3,4,8,9: R B Davies
00683 
00684 //#define WANT_STREAM
00685 
00686 
00687 #ifdef use_namespace
00688 namespace NEWMAT {
00689 #endif
00690 
00691 
00692 
00693 #ifdef DO_REPORT
00694 #define REPORT { static ExeCounter ExeCount(__LINE__,4); ++ExeCount; }
00695 #else
00696 #define REPORT {}
00697 #endif
00698 
00699 
00700 #define DO_SEARCH                   // search for LHS of = in RHS
00701 
00702 // ************************* general utilities *************************/
00703 
00704 static int tristore(int n)                    // elements in triangular matrix
00705 { return (n*(n+1))/2; }
00706 
00707 
00708 // **************************** constructors ***************************/
00709 
00710 GeneralMatrix::GeneralMatrix()
00711 { store=0; storage=0; nrows_val=0; ncols_val=0; tag_val=-1; }
00712 
00713 GeneralMatrix::GeneralMatrix(ArrayLengthSpecifier s)
00714 {
00715    REPORT
00716    storage=s.Value(); tag_val=-1;
00717    if (storage)
00718    {
00719       store = new Real [storage]; MatrixErrorNoSpace(store);
00720       MONITOR_REAL_NEW("Make (GenMatrix)",storage,store)
00721    }
00722    else store = 0;
00723 }
00724 
00725 Matrix::Matrix(int m, int n) : GeneralMatrix(m*n)
00726 { REPORT nrows_val=m; ncols_val=n; }
00727 
00728 SquareMatrix::SquareMatrix(ArrayLengthSpecifier n)
00729    : Matrix(n.Value(),n.Value())
00730 { REPORT }
00731 
00732 SymmetricMatrix::SymmetricMatrix(ArrayLengthSpecifier n)
00733    : GeneralMatrix(tristore(n.Value()))
00734 { REPORT nrows_val=n.Value(); ncols_val=n.Value(); }
00735 
00736 UpperTriangularMatrix::UpperTriangularMatrix(ArrayLengthSpecifier n)
00737    : GeneralMatrix(tristore(n.Value()))
00738 { REPORT nrows_val=n.Value(); ncols_val=n.Value(); }
00739 
00740 LowerTriangularMatrix::LowerTriangularMatrix(ArrayLengthSpecifier n)
00741    : GeneralMatrix(tristore(n.Value()))
00742 { REPORT nrows_val=n.Value(); ncols_val=n.Value(); }
00743 
00744 DiagonalMatrix::DiagonalMatrix(ArrayLengthSpecifier m) : GeneralMatrix(m)
00745 { REPORT nrows_val=m.Value(); ncols_val=m.Value(); }
00746 
00747 Matrix::Matrix(const BaseMatrix& M)
00748 {
00749    REPORT // CheckConversion(M);
00750    // MatrixConversionCheck mcc;
00751    GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Rt);
00752    GetMatrix(gmx);
00753 }
00754 
00755 SquareMatrix::SquareMatrix(const BaseMatrix& M) : Matrix(M)
00756 {
00757    REPORT
00758    if (ncols_val != nrows_val)
00759    {
00760       Tracer tr("SquareMatrix");
00761       Throw(NotSquareException(*this));
00762    }
00763 }
00764 
00765 
00766 SquareMatrix::SquareMatrix(const Matrix& gm)
00767 {
00768    REPORT
00769    if (gm.ncols_val != gm.nrows_val)
00770    {
00771       Tracer tr("SquareMatrix(Matrix)");
00772       Throw(NotSquareException(gm));
00773    }
00774    GetMatrix(&gm);
00775 }
00776 
00777 
00778 RowVector::RowVector(const BaseMatrix& M) : Matrix(M)
00779 {
00780    REPORT
00781    if (nrows_val!=1)
00782    {
00783       Tracer tr("RowVector");
00784       Throw(VectorException(*this));
00785    }
00786 }
00787 
00788 ColumnVector::ColumnVector(const BaseMatrix& M) : Matrix(M)
00789 {
00790    REPORT
00791    if (ncols_val!=1)
00792    {
00793       Tracer tr("ColumnVector");
00794       Throw(VectorException(*this));
00795    }
00796 }
00797 
00798 SymmetricMatrix::SymmetricMatrix(const BaseMatrix& M)
00799 {
00800    REPORT  // CheckConversion(M);
00801    // MatrixConversionCheck mcc;
00802    GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Sm);
00803    GetMatrix(gmx);
00804 }
00805 
00806 UpperTriangularMatrix::UpperTriangularMatrix(const BaseMatrix& M)
00807 {
00808    REPORT // CheckConversion(M);
00809    // MatrixConversionCheck mcc;
00810    GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::UT);
00811    GetMatrix(gmx);
00812 }
00813 
00814 LowerTriangularMatrix::LowerTriangularMatrix(const BaseMatrix& M)
00815 {
00816    REPORT // CheckConversion(M);
00817    // MatrixConversionCheck mcc;
00818    GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::LT);
00819    GetMatrix(gmx);
00820 }
00821 
00822 DiagonalMatrix::DiagonalMatrix(const BaseMatrix& M)
00823 {
00824    REPORT //CheckConversion(M);
00825    // MatrixConversionCheck mcc;
00826    GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Dg);
00827    GetMatrix(gmx);
00828 }
00829 
00830 IdentityMatrix::IdentityMatrix(const BaseMatrix& M)
00831 {
00832    REPORT //CheckConversion(M);
00833    // MatrixConversionCheck mcc;
00834    GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Id);
00835    GetMatrix(gmx);
00836 }
00837 
00838 GeneralMatrix::~GeneralMatrix()
00839 {
00840    if (store)
00841    {
00842       MONITOR_REAL_DELETE("Free (GenMatrix)",storage,store)
00843       delete [] store;
00844    }
00845 }
00846 
00847 CroutMatrix::CroutMatrix(const BaseMatrix& m)
00848 {
00849    REPORT
00850    Tracer tr("CroutMatrix");
00851    indx = 0;                     // in case of exception at next line
00852    GeneralMatrix* gm = ((BaseMatrix&)m).Evaluate();
00853    if (gm->nrows_val!=gm->ncols_val)
00854       { gm->tDelete(); Throw(NotSquareException(*gm)); }
00855    if (gm->type() == MatrixType::Ct)
00856       { REPORT  ((CroutMatrix*)gm)->get_aux(*this); GetMatrix(gm); }
00857    else
00858    {
00859       REPORT
00860       GeneralMatrix* gm1 = gm->Evaluate(MatrixType::Rt);
00861       GetMatrix(gm1);
00862       d=true; sing=false;
00863       indx=new int [nrows_val]; MatrixErrorNoSpace(indx);
00864       MONITOR_INT_NEW("Index (CroutMat)",nrows_val,indx)
00865       ludcmp();
00866    }
00867 }
00868 
00869 // could we use SetParameters instead of this
00870 void CroutMatrix::get_aux(CroutMatrix& X)
00871 {
00872    X.d = d; X.sing = sing;
00873    if (tag_val == 0 || tag_val == 1) // reuse the array 
00874       { REPORT  X.indx = indx; indx = 0; d = true; sing = true; return; }
00875    else if (nrows_val == 0)
00876       { REPORT indx = 0; d = true; sing = true; return; }
00877    else                              // copy the array
00878    { 
00879       REPORT
00880       Tracer tr("CroutMatrix::get_aux");
00881       int *ix = new int [nrows_val]; MatrixErrorNoSpace(ix);
00882       MONITOR_INT_NEW("Index (CM::get_aux)", nrows_val, ix)
00883       int n = nrows_val; int* i = ix; int* j = indx;
00884       while(n--) *i++ = *j++;
00885       X.indx = ix;
00886    }
00887 }
00888 
00889 CroutMatrix::CroutMatrix(const CroutMatrix& gm) : GeneralMatrix()
00890 {
00891    REPORT
00892    Tracer tr("CroutMatrix(const CroutMatrix&)");
00893    ((CroutMatrix&)gm).get_aux(*this);
00894    GetMatrix(&gm);
00895 }
00896 
00897 CroutMatrix::~CroutMatrix()
00898 {
00899    MONITOR_INT_DELETE("Index (CroutMat)",nrows_val,indx)
00900    delete [] indx;
00901 }
00902 
00903 //ReturnMatrix::ReturnMatrix(GeneralMatrix& gmx)
00904 //{
00905 //   REPORT
00906 //   gm = gmx.Image(); gm->ReleaseAndDelete();
00907 //}
00908 
00909 
00910 GeneralMatrix::operator ReturnMatrix() const
00911 {
00912    REPORT
00913    GeneralMatrix* gm = Image(); gm->ReleaseAndDelete();
00914    return ReturnMatrix(gm);
00915 }
00916 
00917 
00918 
00919 ReturnMatrix GeneralMatrix::for_return() const
00920 {
00921    REPORT
00922    GeneralMatrix* gm = Image(); gm->ReleaseAndDelete();
00923    return ReturnMatrix(gm);
00924 }
00925 
00926 // ************ Constructors for use with NR in C++ interface ***********
00927 
00928 #ifdef SETUP_C_SUBSCRIPTS
00929 
00930 Matrix::Matrix(Real a, int m, int n) : GeneralMatrix(m * n)
00931    { REPORT nrows_val=m; ncols_val=n; operator=(a); }
00932    
00933 Matrix::Matrix(const Real* a, int m, int n) : GeneralMatrix(m * n)
00934    { REPORT nrows_val=m; ncols_val=n; *this << a; }
00935 
00936 #endif
00937 
00938 
00939 
00940 // ************************** resize matrices ***************************/
00941 
00942 void GeneralMatrix::resize(int nr, int nc, int s)
00943 {
00944    REPORT
00945    if (store)
00946    {
00947       MONITOR_REAL_DELETE("Free (ReDimensi)",storage,store)
00948       delete [] store;
00949    }
00950    storage=s; nrows_val=nr; ncols_val=nc; tag_val=-1;
00951    if (s)
00952    {
00953       store = new Real [storage]; MatrixErrorNoSpace(store);
00954       MONITOR_REAL_NEW("Make (ReDimensi)",storage,store)
00955    }
00956    else store = 0;
00957 }
00958 
00959 void Matrix::resize(int nr, int nc)
00960 { REPORT GeneralMatrix::resize(nr,nc,nr*nc); }
00961 
00962 void SquareMatrix::resize(int n)
00963 { REPORT GeneralMatrix::resize(n,n,n*n); }
00964 
00965 void SquareMatrix::resize(int nr, int nc)
00966 {
00967    REPORT
00968    Tracer tr("SquareMatrix::resize");
00969    if (nc != nr) Throw(NotSquareException(*this));
00970    GeneralMatrix::resize(nr,nc,nr*nc);
00971 }
00972 
00973 void SymmetricMatrix::resize(int nr)
00974 { REPORT GeneralMatrix::resize(nr,nr,tristore(nr)); }
00975 
00976 void UpperTriangularMatrix::resize(int nr)
00977 { REPORT GeneralMatrix::resize(nr,nr,tristore(nr)); }
00978 
00979 void LowerTriangularMatrix::resize(int nr)
00980 { REPORT GeneralMatrix::resize(nr,nr,tristore(nr)); }
00981 
00982 void DiagonalMatrix::resize(int nr)
00983 { REPORT GeneralMatrix::resize(nr,nr,nr); }
00984 
00985 void RowVector::resize(int nc)
00986 { REPORT GeneralMatrix::resize(1,nc,nc); }
00987 
00988 void ColumnVector::resize(int nr)
00989 { REPORT GeneralMatrix::resize(nr,1,nr); }
00990 
00991 void RowVector::resize(int nr, int nc)
00992 {
00993    Tracer tr("RowVector::resize");
00994    if (nr != 1) Throw(VectorException(*this));
00995    REPORT GeneralMatrix::resize(1,nc,nc);
00996 }
00997 
00998 void ColumnVector::resize(int nr, int nc)
00999 {
01000    Tracer tr("ColumnVector::resize");
01001    if (nc != 1) Throw(VectorException(*this));
01002    REPORT GeneralMatrix::resize(nr,1,nr);
01003 }
01004 
01005 void IdentityMatrix::resize(int nr)
01006 { REPORT GeneralMatrix::resize(nr,nr,1); *store = 1; }
01007 
01008 
01009 void Matrix::resize(const GeneralMatrix& A)
01010 { REPORT  resize(A.Nrows(), A.Ncols()); }
01011 
01012 void SquareMatrix::resize(const GeneralMatrix& A)
01013 {
01014    REPORT
01015    int n = A.Nrows();
01016    if (n != A.Ncols())
01017    {
01018       Tracer tr("SquareMatrix::resize(GM)");
01019       Throw(NotSquareException(*this));
01020    }
01021    resize(n);
01022 }
01023 
01024 void nricMatrix::resize(const GeneralMatrix& A)
01025 { REPORT  resize(A.Nrows(), A.Ncols()); }
01026 
01027 void ColumnVector::resize(const GeneralMatrix& A)
01028 { REPORT  resize(A.Nrows(), A.Ncols()); }
01029 
01030 void RowVector::resize(const GeneralMatrix& A)
01031 { REPORT  resize(A.Nrows(), A.Ncols()); }
01032 
01033 void SymmetricMatrix::resize(const GeneralMatrix& A)
01034 {
01035    REPORT
01036    int n = A.Nrows();
01037    if (n != A.Ncols())
01038    {
01039       Tracer tr("SymmetricMatrix::resize(GM)");
01040       Throw(NotSquareException(*this));
01041    }
01042    resize(n);
01043 }
01044 
01045 void DiagonalMatrix::resize(const GeneralMatrix& A)
01046 {
01047    REPORT
01048    int n = A.Nrows();
01049    if (n != A.Ncols())
01050    {
01051       Tracer tr("DiagonalMatrix::resize(GM)");
01052       Throw(NotSquareException(*this));
01053    }
01054    resize(n);
01055 }
01056 
01057 void UpperTriangularMatrix::resize(const GeneralMatrix& A)
01058 {
01059    REPORT
01060    int n = A.Nrows();
01061    if (n != A.Ncols())
01062    {
01063       Tracer tr("UpperTriangularMatrix::resize(GM)");
01064       Throw(NotSquareException(*this));
01065    }
01066    resize(n);
01067 }
01068 
01069 void LowerTriangularMatrix::resize(const GeneralMatrix& A)
01070 {
01071    REPORT
01072    int n = A.Nrows();
01073    if (n != A.Ncols())
01074    {
01075       Tracer tr("LowerTriangularMatrix::resize(GM)");
01076       Throw(NotSquareException(*this));
01077    }
01078    resize(n);
01079 }
01080 
01081 void IdentityMatrix::resize(const GeneralMatrix& A)
01082 {
01083    REPORT
01084    int n = A.Nrows();
01085    if (n != A.Ncols())
01086    {
01087       Tracer tr("IdentityMatrix::resize(GM)");
01088       Throw(NotSquareException(*this));
01089    }
01090    resize(n);
01091 }
01092 
01093 void GeneralMatrix::resize(const GeneralMatrix&)
01094 {
01095    REPORT
01096    Tracer tr("GeneralMatrix::resize(GM)");
01097    Throw(NotDefinedException("resize", "this type of matrix"));
01098 }
01099 
01100 //*********************** resize_keep *******************************
01101 
01102 void Matrix::resize_keep(int nr, int nc)
01103 {
01104    Tracer tr("Matrix::resize_keep");
01105    if (nr == nrows_val && nc == ncols_val) { REPORT return; }
01106    
01107    if (nr <= nrows_val && nc <= ncols_val)
01108    {
01109       REPORT
01110       Matrix X = submatrix(1,nr,1,nc);
01111       swap(X);
01112    }
01113    else if (nr >= nrows_val && nc >= ncols_val)
01114    {
01115       REPORT
01116       Matrix X(nr, nc); X = 0;
01117       X.submatrix(1,nrows_val,1,ncols_val) = *this;
01118       swap(X);
01119    }
01120    else
01121    {
01122       REPORT
01123       Matrix X(nr, nc); X = 0;
01124       if (nr > nrows_val) nr = nrows_val;
01125       if (nc > ncols_val) nc = ncols_val;
01126       X.submatrix(1,nr,1,nc) = submatrix(1,nr,1,nc);
01127       swap(X);
01128    }
01129 } 
01130 
01131 void SquareMatrix::resize_keep(int nr)
01132 {
01133    Tracer tr("SquareMatrix::resize_keep");
01134    if (nr < nrows_val)
01135    {
01136       REPORT
01137       SquareMatrix X = sym_submatrix(1,nr);
01138       swap(X);
01139    }
01140    else if (nr > nrows_val)
01141    {
01142       REPORT
01143       SquareMatrix X(nr); X = 0;
01144       X.sym_submatrix(1,nrows_val) = *this;
01145       swap(X);
01146    }
01147 }
01148 
01149 void SquareMatrix::resize_keep(int nr, int nc)
01150 {
01151    Tracer tr("SquareMatrix::resize_keep 2");
01152    REPORT
01153    if (nr != nc) Throw(NotSquareException(*this));
01154    resize_keep(nr);
01155 }
01156  
01157 
01158 void SymmetricMatrix::resize_keep(int nr)
01159 {
01160    Tracer tr("SymmetricMatrix::resize_keep");
01161    if (nr < nrows_val)
01162    {
01163       REPORT
01164       SymmetricMatrix X = sym_submatrix(1,nr);
01165       swap(X);
01166    }
01167    else if (nr > nrows_val)
01168    {
01169       REPORT
01170       SymmetricMatrix X(nr); X = 0;
01171       X.sym_submatrix(1,nrows_val) = *this;
01172       swap(X);
01173    }
01174 } 
01175 
01176 void UpperTriangularMatrix::resize_keep(int nr)
01177 {
01178    Tracer tr("UpperTriangularMatrix::resize_keep");
01179    if (nr < nrows_val)
01180    {
01181       REPORT
01182       UpperTriangularMatrix X = sym_submatrix(1,nr);
01183       swap(X);
01184    }
01185    else if (nr > nrows_val)
01186    {
01187       REPORT
01188       UpperTriangularMatrix X(nr); X = 0;
01189       X.sym_submatrix(1,nrows_val) = *this;
01190       swap(X);
01191    }
01192 } 
01193 
01194 void LowerTriangularMatrix::resize_keep(int nr)
01195 {
01196    Tracer tr("LowerTriangularMatrix::resize_keep");
01197    if (nr < nrows_val)
01198    {
01199       REPORT
01200       LowerTriangularMatrix X = sym_submatrix(1,nr);
01201       swap(X);
01202    }
01203    else if (nr > nrows_val)
01204    {
01205       REPORT
01206       LowerTriangularMatrix X(nr); X = 0;
01207       X.sym_submatrix(1,nrows_val) = *this;
01208       swap(X);
01209    }
01210 } 
01211 
01212 void DiagonalMatrix::resize_keep(int nr)
01213 {
01214    Tracer tr("DiagonalMatrix::resize_keep");
01215    if (nr < nrows_val)
01216    {
01217       REPORT
01218       DiagonalMatrix X = sym_submatrix(1,nr);
01219       swap(X);
01220    }
01221    else if (nr > nrows_val)
01222    {
01223       REPORT
01224       DiagonalMatrix X(nr); X = 0;
01225       X.sym_submatrix(1,nrows_val) = *this;
01226       swap(X);
01227    }
01228 } 
01229 
01230 void RowVector::resize_keep(int nc)
01231 {
01232    Tracer tr("RowVector::resize_keep");
01233    if (nc < ncols_val)
01234    {
01235       REPORT
01236       RowVector X = columns(1,nc);
01237       swap(X);
01238    }
01239    else if (nc > ncols_val)
01240    {
01241       REPORT
01242       RowVector X(nc); X = 0;
01243       X.columns(1,ncols_val) = *this;
01244       swap(X);
01245    }
01246 }
01247 
01248 void RowVector::resize_keep(int nr, int nc)
01249 {
01250    Tracer tr("RowVector::resize_keep 2");
01251    REPORT
01252    if (nr != 1) Throw(VectorException(*this));
01253    resize_keep(nc);
01254 }
01255 
01256 void ColumnVector::resize_keep(int nr)
01257 {
01258    Tracer tr("ColumnVector::resize_keep");
01259    if (nr < nrows_val)
01260    {
01261       REPORT
01262       ColumnVector X = rows(1,nr);
01263       swap(X);
01264    }
01265    else if (nr > nrows_val)
01266    {
01267       REPORT
01268       ColumnVector X(nr); X = 0;
01269       X.rows(1,nrows_val) = *this;
01270       swap(X);
01271    }
01272 } 
01273 
01274 void ColumnVector::resize_keep(int nr, int nc)
01275 {
01276    Tracer tr("ColumnVector::resize_keep 2");
01277    REPORT
01278    if (nc != 1) Throw(VectorException(*this));
01279    resize_keep(nr);
01280 }
01281 
01282 
01283 /*
01284 void GeneralMatrix::resizeForAdd(const GeneralMatrix& A, const GeneralMatrix&)
01285 { REPORT resize(A); }
01286 
01287 void GeneralMatrix::resizeForSP(const GeneralMatrix& A, const GeneralMatrix&)
01288 { REPORT resize(A); }
01289 
01290 
01291 // ************************* SameStorageType ******************************
01292 
01293 // SameStorageType checks A and B have same storage type including bandwidth
01294 // It does not check same dimensions since we assume this is already done
01295 
01296 bool GeneralMatrix::SameStorageType(const GeneralMatrix& A) const
01297 {
01298    REPORT
01299    return type() == A.type();
01300 }
01301 */
01302 
01303 // ******************* manipulate types, storage **************************/
01304 
01305 int GeneralMatrix::search(const BaseMatrix* s) const
01306 { REPORT return (s==this) ? 1 : 0; }
01307 
01308 int GenericMatrix::search(const BaseMatrix* s) const
01309 { REPORT return gm->search(s); }
01310 
01311 int MultipliedMatrix::search(const BaseMatrix* s) const
01312 { REPORT return bm1->search(s) + bm2->search(s); }
01313 
01314 int ShiftedMatrix::search(const BaseMatrix* s) const
01315 { REPORT return bm->search(s); }
01316 
01317 int NegatedMatrix::search(const BaseMatrix* s) const
01318 { REPORT return bm->search(s); }
01319 
01320 int ReturnMatrix::search(const BaseMatrix* s) const
01321 { REPORT return (s==gm) ? 1 : 0; }
01322 
01323 MatrixType Matrix::type() const { return MatrixType::Rt; }
01324 MatrixType SquareMatrix::type() const { return MatrixType::Sq; }
01325 MatrixType SymmetricMatrix::type() const { return MatrixType::Sm; }
01326 MatrixType UpperTriangularMatrix::type() const { return MatrixType::UT; }
01327 MatrixType LowerTriangularMatrix::type() const { return MatrixType::LT; }
01328 MatrixType DiagonalMatrix::type() const { return MatrixType::Dg; }
01329 MatrixType RowVector::type() const { return MatrixType::RV; }
01330 MatrixType ColumnVector::type() const { return MatrixType::CV; }
01331 MatrixType CroutMatrix::type() const { return MatrixType::Ct; }
01332 MatrixType BandMatrix::type() const { return MatrixType::BM; }
01333 MatrixType UpperBandMatrix::type() const { return MatrixType::UB; }
01334 MatrixType LowerBandMatrix::type() const { return MatrixType::LB; }
01335 MatrixType SymmetricBandMatrix::type() const { return MatrixType::SB; }
01336 
01337 MatrixType IdentityMatrix::type() const { return MatrixType::Id; }
01338 
01339 
01340 
01341 MatrixBandWidth BaseMatrix::bandwidth() const { REPORT return -1; }
01342 MatrixBandWidth DiagonalMatrix::bandwidth() const { REPORT return 0; }
01343 MatrixBandWidth IdentityMatrix::bandwidth() const { REPORT return 0; }
01344 
01345 MatrixBandWidth UpperTriangularMatrix::bandwidth() const
01346    { REPORT return MatrixBandWidth(0,-1); }
01347 
01348 MatrixBandWidth LowerTriangularMatrix::bandwidth() const
01349    { REPORT return MatrixBandWidth(-1,0); }
01350 
01351 MatrixBandWidth BandMatrix::bandwidth() const
01352    { REPORT return MatrixBandWidth(lower_val,upper_val); }
01353 
01354 MatrixBandWidth BandLUMatrix::bandwidth() const
01355    { REPORT return MatrixBandWidth(m1,m2); }
01356    
01357 MatrixBandWidth GenericMatrix::bandwidth()const
01358    { REPORT return gm->bandwidth(); }
01359 
01360 MatrixBandWidth AddedMatrix::bandwidth() const
01361    { REPORT return gm1->bandwidth() + gm2->bandwidth(); }
01362 
01363 MatrixBandWidth SPMatrix::bandwidth() const
01364    { REPORT return gm1->bandwidth().minimum(gm2->bandwidth()); }
01365 
01366 MatrixBandWidth KPMatrix::bandwidth() const
01367 {
01368    int lower, upper;
01369    MatrixBandWidth bw1 = gm1->bandwidth(), bw2 = gm2->bandwidth();
01370    if (bw1.Lower() < 0)
01371    {
01372       if (bw2.Lower() < 0) { REPORT lower = -1; }
01373       else { REPORT lower = bw2.Lower() + (gm1->Nrows() - 1) * gm2->Nrows(); }
01374    }
01375    else
01376    {
01377       if (bw2.Lower() < 0)
01378          { REPORT lower = (1 + bw1.Lower()) * gm2->Nrows() - 1; }
01379       else { REPORT lower = bw2.Lower() + bw1.Lower() * gm2->Nrows(); }
01380    }
01381    if (bw1.Upper() < 0)
01382    {
01383       if (bw2.Upper() < 0) { REPORT upper = -1; }
01384       else { REPORT upper = bw2.Upper() + (gm1->Nrows() - 1) * gm2->Nrows(); }
01385    }
01386    else
01387    {
01388       if (bw2.Upper() < 0)
01389          { REPORT upper = (1 + bw1.Upper()) * gm2->Nrows() - 1; }
01390       else { REPORT upper = bw2.Upper() + bw1.Upper() * gm2->Nrows(); }
01391    }
01392    return MatrixBandWidth(lower, upper);
01393 }
01394 
01395 MatrixBandWidth MultipliedMatrix::bandwidth() const
01396 { REPORT return gm1->bandwidth() * gm2->bandwidth(); }
01397 
01398 MatrixBandWidth ConcatenatedMatrix::bandwidth() const { REPORT return -1; }
01399 
01400 MatrixBandWidth SolvedMatrix::bandwidth() const
01401 {
01402    if (+gm1->type() & MatrixType::Diagonal)
01403       { REPORT return gm2->bandwidth(); }
01404    else { REPORT return -1; }
01405 }
01406 
01407 MatrixBandWidth ScaledMatrix::bandwidth() const
01408    { REPORT return gm->bandwidth(); }
01409 
01410 MatrixBandWidth NegatedMatrix::bandwidth() const
01411    { REPORT return gm->bandwidth(); }
01412 
01413 MatrixBandWidth TransposedMatrix::bandwidth() const
01414    { REPORT return gm->bandwidth().t(); }
01415 
01416 MatrixBandWidth InvertedMatrix::bandwidth() const
01417 {
01418    if (+gm->type() & MatrixType::Diagonal)
01419       { REPORT return MatrixBandWidth(0,0); }
01420    else { REPORT return -1; }
01421 }
01422 
01423 MatrixBandWidth RowedMatrix::bandwidth() const { REPORT return -1; }
01424 MatrixBandWidth ColedMatrix::bandwidth() const { REPORT return -1; }
01425 MatrixBandWidth DiagedMatrix::bandwidth() const { REPORT return 0; }
01426 MatrixBandWidth MatedMatrix::bandwidth() const { REPORT return -1; }
01427 MatrixBandWidth ReturnMatrix::bandwidth() const
01428    { REPORT return gm->bandwidth(); }
01429 
01430 MatrixBandWidth GetSubMatrix::bandwidth() const
01431 {
01432 
01433    if (row_skip==col_skip && row_number==col_number)
01434       { REPORT return gm->bandwidth(); }
01435    else { REPORT return MatrixBandWidth(-1); }
01436 }
01437 
01438 // ********************** the memory managment tools **********************/
01439 
01440 //  Rules regarding tDelete, reuse, GetStore, BorrowStore
01441 //    All matrices processed during expression evaluation must be subject
01442 //    to exactly one of reuse(), tDelete(), GetStore() or BorrowStore().
01443 //    If reuse returns true the matrix must be reused.
01444 //    GetMatrix(gm) always calls gm->GetStore()
01445 //    gm->Evaluate obeys rules
01446 //    bm->Evaluate obeys rules for matrices in bm structure
01447 
01448 //  Meaning of tag_val
01449 //    tag_val = -1          memory cannot be reused (default situation)
01450 //    tag_val = -2          memory has been borrowed from another matrix
01451 //                               (don't change values)
01452 //    tag_val = i > 0       delete or reuse memory after i operations
01453 //    tag_val = 0           like value 1 but matrix was created by new
01454 //                               so delete it
01455 
01456 void GeneralMatrix::tDelete()
01457 {
01458    if (tag_val<0)
01459    {
01460       if (tag_val<-1) { REPORT store = 0; delete this; return; }  // borrowed
01461       else { REPORT return; }   // not a temporary matrix - leave alone
01462    }
01463    if (tag_val==1)
01464    {
01465       if (store)
01466       {
01467          REPORT  MONITOR_REAL_DELETE("Free   (tDelete)",storage,store)
01468          delete [] store;
01469       }
01470       MiniCleanUp(); return;                           // CleanUp
01471    }
01472    if (tag_val==0) { REPORT delete this; return; }
01473 
01474    REPORT tag_val--; return;
01475 }
01476 
01477 void newmat_block_copy(int n, Real* from, Real* to)
01478 {
01479    REPORT
01480    int i = (n >> 3);
01481    while (i--)
01482    {
01483       *to++ = *from++; *to++ = *from++; *to++ = *from++; *to++ = *from++;
01484       *to++ = *from++; *to++ = *from++; *to++ = *from++; *to++ = *from++;
01485    }
01486    i = n & 7; while (i--) *to++ = *from++;
01487 }
01488 
01489 bool GeneralMatrix::reuse()
01490 {
01491    if (tag_val < -1)                 // borrowed storage
01492    {
01493       if (storage)
01494       {
01495          REPORT
01496          Real* s = new Real [storage]; MatrixErrorNoSpace(s);
01497          MONITOR_REAL_NEW("Make     (reuse)",storage,s)
01498          newmat_block_copy(storage, store, s); store = s;
01499       }
01500       else { REPORT MiniCleanUp(); }                // CleanUp
01501       tag_val = 0; return true;
01502    }
01503    if (tag_val < 0 ) { REPORT return false; }
01504    if (tag_val <= 1 )  { REPORT return true; }
01505    REPORT tag_val--; return false;
01506 }
01507 
01508 Real* GeneralMatrix::GetStore()
01509 {
01510    if (tag_val<0 || tag_val>1)
01511    {
01512       Real* s;
01513       if (storage)
01514       {
01515          s = new Real [storage]; MatrixErrorNoSpace(s);
01516          MONITOR_REAL_NEW("Make  (GetStore)",storage,s)
01517          newmat_block_copy(storage, store, s);
01518       }
01519       else s = 0;
01520       if (tag_val > 1) { REPORT tag_val--; }
01521       else if (tag_val < -1) { REPORT store = 0; delete this; } // borrowed store
01522       else { REPORT }
01523       return s;
01524    }
01525    Real* s = store;                             // cleanup - done later
01526    if (tag_val==0) { REPORT store = 0; delete this; }
01527    else { REPORT  MiniCleanUp(); }
01528    return s;
01529 }
01530 
01531 void GeneralMatrix::GetMatrix(const GeneralMatrix* gmx)
01532 {
01533    REPORT  tag_val=-1; nrows_val=gmx->Nrows(); ncols_val=gmx->Ncols();
01534    storage=gmx->storage; SetParameters(gmx);
01535    store=((GeneralMatrix*)gmx)->GetStore();
01536 }
01537 
01538 GeneralMatrix* GeneralMatrix::BorrowStore(GeneralMatrix* gmx, MatrixType mt)
01539 // Copy storage of *this to storage of *gmx. Then convert to type mt.
01540 // If mt == 0 just let *gmx point to storage of *this if tag_val==-1.
01541 {
01542    if (!mt)
01543    {
01544       if (tag_val == -1) { REPORT gmx->tag_val = -2; gmx->store = store; }
01545       else { REPORT gmx->tag_val = 0; gmx->store = GetStore(); }
01546    }
01547    else if (Compare(gmx->type(),mt))
01548    { REPORT  gmx->tag_val = 0; gmx->store = GetStore(); }
01549    else
01550    {
01551       REPORT gmx->tag_val = -2; gmx->store = store;
01552       gmx = gmx->Evaluate(mt); gmx->tag_val = 0; tDelete();
01553    }
01554 
01555    return gmx;
01556 }
01557 
01558 void GeneralMatrix::Eq(const BaseMatrix& X, MatrixType mt)
01559 // Count number of references to this in X.
01560 // If zero delete storage in this;
01561 // otherwise tag this to show when storage can be deleted
01562 // evaluate X and copy to this
01563 {
01564 #ifdef DO_SEARCH
01565    int counter=X.search(this);
01566    if (counter==0)
01567    {
01568       REPORT
01569       if (store)
01570       {
01571          MONITOR_REAL_DELETE("Free (operator=)",storage,store)
01572          REPORT delete [] store; storage = 0; store = 0;
01573       }
01574    }
01575    else { REPORT Release(counter); }
01576    GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt);
01577    if (gmx!=this) { REPORT GetMatrix(gmx); }
01578    else { REPORT }
01579    Protect();
01580 #else
01581    GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt);
01582    if (gmx!=this)
01583    {
01584       REPORT
01585       if (store)
01586       {
01587          MONITOR_REAL_DELETE("Free (operator=)",storage,store)
01588          REPORT delete [] store; storage = 0; store = 0;
01589       }
01590       GetMatrix(gmx);
01591    }
01592    else { REPORT }
01593    Protect();
01594 #endif
01595 }
01596 
01597 // version with no conversion
01598 void GeneralMatrix::Eq(const GeneralMatrix& X)
01599 {
01600    GeneralMatrix* gmx = (GeneralMatrix*)&X;
01601    if (gmx!=this)
01602    {
01603       REPORT
01604       if (store)
01605       {
01606          MONITOR_REAL_DELETE("Free (operator=)",storage,store)
01607          REPORT delete [] store; storage = 0; store = 0;
01608       }
01609       GetMatrix(gmx);
01610    }
01611    else { REPORT }
01612    Protect();
01613 }
01614 
01615 // version to work with operator<<
01616 void GeneralMatrix::Eq(const BaseMatrix& X, MatrixType mt, bool ldok)
01617 {
01618    REPORT
01619    if (ldok) mt.SetDataLossOK();
01620    Eq(X, mt);
01621 }
01622 
01623 void GeneralMatrix::Eq2(const BaseMatrix& X, MatrixType mt)
01624 // a cut down version of Eq for use with += etc.
01625 // we know BaseMatrix points to two GeneralMatrix objects,
01626 // the first being this (may be the same).
01627 // we know tag_val has been set correctly in each.
01628 {
01629    GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt);
01630    if (gmx!=this) { REPORT GetMatrix(gmx); }  // simplify GetMatrix ?
01631    else { REPORT }
01632    Protect();
01633 }
01634 
01635 void GeneralMatrix::inject(const GeneralMatrix& X)
01636 // copy stored values of X; otherwise leave els of *this unchanged
01637 {
01638    REPORT
01639    Tracer tr("inject");
01640    if (nrows_val != X.nrows_val || ncols_val != X.ncols_val)
01641       Throw(IncompatibleDimensionsException());
01642    MatrixRow mr((GeneralMatrix*)&X, LoadOnEntry);
01643    MatrixRow mrx(this, LoadOnEntry+StoreOnExit+DirectPart);
01644    int i=nrows_val;
01645    while (i--) { mrx.Inject(mr); mrx.Next(); mr.Next(); }
01646 }
01647 
01648 // ************* checking for data loss during conversion *******************/
01649 
01650 bool Compare(const MatrixType& source, MatrixType& destination)
01651 {
01652    if (!destination) { destination=source; return true; }
01653    if (destination==source) return true;
01654    if (!destination.DataLossOK && !(destination>=source))
01655       Throw(ProgramException("Illegal Conversion", source, destination));
01656    return false;
01657 }
01658 
01659 // ************* Make a copy of a matrix on the heap *********************/
01660 
01661 GeneralMatrix* Matrix::Image() const
01662 {
01663    REPORT
01664    GeneralMatrix* gm = new Matrix(*this); MatrixErrorNoSpace(gm);
01665    return gm;
01666 }
01667 
01668 GeneralMatrix* SquareMatrix::Image() const
01669 {
01670    REPORT
01671    GeneralMatrix* gm = new SquareMatrix(*this); MatrixErrorNoSpace(gm);
01672    return gm;
01673 }
01674 
01675 GeneralMatrix* SymmetricMatrix::Image() const
01676 {
01677    REPORT
01678    GeneralMatrix* gm = new SymmetricMatrix(*this); MatrixErrorNoSpace(gm);
01679    return gm;
01680 }
01681 
01682 GeneralMatrix* UpperTriangularMatrix::Image() const
01683 {
01684    REPORT
01685    GeneralMatrix* gm = new UpperTriangularMatrix(*this);
01686    MatrixErrorNoSpace(gm); return gm;
01687 }
01688 
01689 GeneralMatrix* LowerTriangularMatrix::Image() const
01690 {
01691    REPORT
01692    GeneralMatrix* gm = new LowerTriangularMatrix(*this);
01693    MatrixErrorNoSpace(gm); return gm;
01694 }
01695 
01696 GeneralMatrix* DiagonalMatrix::Image() const
01697 {
01698    REPORT
01699    GeneralMatrix* gm = new DiagonalMatrix(*this); MatrixErrorNoSpace(gm);
01700    return gm;
01701 }
01702 
01703 GeneralMatrix* RowVector::Image() const
01704 {
01705    REPORT
01706    GeneralMatrix* gm = new RowVector(*this); MatrixErrorNoSpace(gm);
01707    return gm;
01708 }
01709 
01710 GeneralMatrix* ColumnVector::Image() const
01711 {
01712    REPORT
01713    GeneralMatrix* gm = new ColumnVector(*this); MatrixErrorNoSpace(gm);
01714    return gm;
01715 }
01716 
01717 GeneralMatrix* nricMatrix::Image() const
01718 {
01719    REPORT
01720    GeneralMatrix* gm = new nricMatrix(*this); MatrixErrorNoSpace(gm);
01721    return gm;
01722 }
01723 
01724 GeneralMatrix* IdentityMatrix::Image() const
01725 {
01726    REPORT
01727    GeneralMatrix* gm = new IdentityMatrix(*this); MatrixErrorNoSpace(gm);
01728    return gm;
01729 }
01730 
01731 GeneralMatrix* CroutMatrix::Image() const
01732 {
01733    REPORT
01734    GeneralMatrix* gm = new CroutMatrix(*this); MatrixErrorNoSpace(gm);
01735    return gm;
01736 }
01737 
01738 GeneralMatrix* GeneralMatrix::Image() const
01739 {
01740    bool dummy = true;
01741    if (dummy)                                   // get rid of warning message
01742       Throw(InternalException("Cannot apply Image to this matrix type"));
01743    return 0;
01744 }
01745 
01746 
01747 // *********************** nricMatrix routines *****************************/
01748 
01749 void nricMatrix::MakeRowPointer()
01750 {
01751    REPORT
01752    if (nrows_val > 0)
01753    {
01754       row_pointer = new Real* [nrows_val]; MatrixErrorNoSpace(row_pointer);
01755       Real* s = Store() - 1; int i = nrows_val; Real** rp = row_pointer;
01756       if (i) for (;;) { *rp++ = s; if (!(--i)) break; s+=ncols_val; }
01757    }
01758    else row_pointer = 0;
01759 }
01760 
01761 void nricMatrix::DeleteRowPointer()
01762    { REPORT if (nrows_val) delete [] row_pointer; }
01763 
01764 void GeneralMatrix::CheckStore() const
01765 {
01766    REPORT
01767    if (!store)
01768       Throw(ProgramException("NRIC accessing matrix with unset dimensions"));
01769 }
01770 
01771 
01772 // *************************** CleanUp routines *****************************/
01773 
01774 void GeneralMatrix::cleanup()
01775 {
01776    // set matrix dimensions to zero, delete storage
01777    REPORT
01778    if (store && storage)
01779    {
01780       MONITOR_REAL_DELETE("Free (cleanup)    ",storage,store)
01781       REPORT delete [] store;
01782    }
01783    store=0; storage=0; nrows_val=0; ncols_val=0; tag_val = -1;
01784 }
01785 
01786 void nricMatrix::cleanup()
01787    { REPORT DeleteRowPointer(); GeneralMatrix::cleanup(); }
01788 
01789 void nricMatrix::MiniCleanUp()
01790    { REPORT DeleteRowPointer(); GeneralMatrix::MiniCleanUp(); }
01791 
01792 void RowVector::cleanup()
01793    { REPORT GeneralMatrix::cleanup(); nrows_val=1; }
01794 
01795 void ColumnVector::cleanup()
01796    { REPORT GeneralMatrix::cleanup(); ncols_val=1; }
01797 
01798 void CroutMatrix::cleanup()
01799 {
01800    REPORT
01801    if (nrows_val) delete [] indx;
01802    GeneralMatrix::cleanup();
01803 }
01804 
01805 void CroutMatrix::MiniCleanUp()
01806 {
01807    REPORT
01808    if (nrows_val) delete [] indx;
01809    GeneralMatrix::MiniCleanUp();
01810 }
01811 
01812 void BandLUMatrix::cleanup()
01813 {
01814    REPORT
01815    if (nrows_val) delete [] indx;
01816    if (storage2) delete [] store2;
01817    GeneralMatrix::cleanup();
01818 }
01819 
01820 void BandLUMatrix::MiniCleanUp()
01821 {
01822    REPORT
01823    if (nrows_val) delete [] indx;
01824    if (storage2) delete [] store2;
01825    GeneralMatrix::MiniCleanUp();
01826 }
01827 
01828 // ************************ simple integer array class ***********************
01829 
01830 // construct a new array of length xn. Check that xn is non-negative and
01831 // that space is available
01832 
01833 SimpleIntArray::SimpleIntArray(int xn) : n(xn)
01834 {
01835    if (n < 0) Throw(Logic_error("invalid array length"));
01836    else if (n == 0) { REPORT  a = 0; }
01837    else { REPORT  a = new int [n]; if (!a) Throw(Bad_alloc()); }
01838 }
01839 
01840 // destroy an array - return its space to memory
01841 
01842 SimpleIntArray::~SimpleIntArray() { REPORT  if (a) delete [] a; }
01843 
01844 // access an element of an array; return a "reference" so elements
01845 // can be modified.
01846 // check index is within range
01847 // in this array class the index runs from 0 to n-1
01848 
01849 int& SimpleIntArray::operator[](int i)
01850 {
01851    REPORT
01852    if (i < 0 || i >= n) Throw(Logic_error("array index out of range"));
01853    return a[i];
01854 }
01855 
01856 // same thing again but for arrays declared constant so we can't
01857 // modify its elements
01858 
01859 int SimpleIntArray::operator[](int i) const
01860 {
01861    REPORT
01862    if (i < 0 || i >= n) Throw(Logic_error("array index out of range"));
01863    return a[i];
01864 }
01865 
01866 // set all the elements equal to a given value
01867 
01868 void SimpleIntArray::operator=(int ai)
01869    { REPORT  for (int i = 0; i < n; i++) a[i] = ai; }
01870 
01871 // set the elements equal to those of another array.
01872 // now allow length to be changed
01873 
01874 void SimpleIntArray::operator=(const SimpleIntArray& b)
01875 {
01876    REPORT
01877    if (b.n != n) resize(b.n);
01878    for (int i = 0; i < n; i++) a[i] = b.a[i];
01879 }
01880 
01881 // construct a new array equal to an existing array
01882 // check that space is available
01883 
01884 SimpleIntArray::SimpleIntArray(const SimpleIntArray& b) : Janitor(), n(b.n)
01885 {
01886    if (n == 0) { REPORT  a = 0; }
01887    else
01888    {
01889       REPORT
01890       a = new int [n]; if (!a) Throw(Bad_alloc());
01891       for (int i = 0; i < n; i++) a[i] = b.a[i];
01892    }
01893 }
01894 
01895 // change the size of an array; optionally copy data from old array to
01896 // new array
01897 
01898 void SimpleIntArray::resize(int n1, bool keep)
01899 {
01900    if (n1 == n) { REPORT  return; }
01901    else if (n1 == 0) { REPORT  n = 0; delete [] a; a = 0; }
01902    else if (n == 0)
01903    {
01904       REPORT
01905       a = new int [n1]; if (!a) Throw(Bad_alloc());
01906       n = n1;
01907       if (keep) operator=(0);
01908    }
01909    else
01910    {
01911       int* a1 = a;
01912       if (keep)
01913       {
01914          REPORT
01915          int i;
01916          a = new int [n1]; if (!a) Throw(Bad_alloc());
01917          if (n > n1) n = n1;
01918          else for (i = n; i < n1; i++) a[i] = 0;
01919          for (i = 0; i < n; i++) a[i] = a1[i];
01920          n = n1; delete [] a1;
01921       }
01922       else
01923       {
01924          REPORT  n = n1; delete [] a1;
01925          a = new int [n]; if (!a) Throw(Bad_alloc());
01926       }
01927    }
01928 }
01929 
01930 //************************** swap values ********************************
01931 
01932 // swap values
01933 
01934 void GeneralMatrix::swap(GeneralMatrix& gm)
01935 {
01936    REPORT
01937    int t;
01938    t = tag_val; tag_val = gm.tag_val; gm.tag_val = t;
01939    t = nrows_val; nrows_val = gm.nrows_val; gm.nrows_val = t;
01940    t = ncols_val; ncols_val = gm.ncols_val; gm.ncols_val = t;
01941    t = storage; storage = gm.storage; gm.storage = t;
01942    Real* s = store; store = gm.store; gm.store = s;
01943 }
01944    
01945 void nricMatrix::swap(nricMatrix& gm)
01946 {
01947    REPORT
01948    GeneralMatrix::swap((GeneralMatrix&)gm);
01949    Real** rp = row_pointer; row_pointer = gm.row_pointer; gm.row_pointer = rp;
01950 }
01951 
01952 void CroutMatrix::swap(CroutMatrix& gm)
01953 {
01954    REPORT
01955    GeneralMatrix::swap((GeneralMatrix&)gm);
01956    int* i = indx; indx = gm.indx; gm.indx = i;
01957    bool b;
01958    b = d; d = gm.d; gm.d = b;
01959    b = sing; sing = gm.sing; gm.sing = b;
01960 }
01961 
01962 void BandMatrix::swap(BandMatrix& gm)
01963 {
01964    REPORT
01965    GeneralMatrix::swap((GeneralMatrix&)gm);
01966    int i;
01967    i = lower_val; lower_val = gm.lower_val; gm.lower_val = i;
01968    i = upper_val; upper_val = gm.upper_val; gm.upper_val = i;
01969 }
01970 
01971 void SymmetricBandMatrix::swap(SymmetricBandMatrix& gm)
01972 {
01973    REPORT
01974    GeneralMatrix::swap((GeneralMatrix&)gm);
01975    int i;
01976    i = lower_val; lower_val = gm.lower_val; gm.lower_val = i;
01977 }
01978 
01979 void BandLUMatrix::swap(BandLUMatrix& gm)
01980 {
01981    REPORT
01982    GeneralMatrix::swap((GeneralMatrix&)gm);
01983    int* i = indx; indx = gm.indx; gm.indx = i;
01984    bool b;
01985    b = d; d = gm.d; gm.d = b;
01986    b = sing; sing = gm.sing; gm.sing = b;
01987    int m;
01988    m = storage2; storage2 = gm.storage2; gm.storage2 = m;
01989    m = m1; m1 = gm.m1; gm.m1 = m;
01990    m = m2; m2 = gm.m2; gm.m2 = m;
01991    Real* s = store2; store2 = gm.store2; gm.store2 = s;
01992 }
01993 
01994 void GenericMatrix::swap(GenericMatrix& x)
01995 {
01996    REPORT
01997    GeneralMatrix* tgm = gm; gm = x.gm; x.gm = tgm;
01998 }
01999 
02000 // ********************** C subscript classes ****************************
02001 
02002 RealStarStar::RealStarStar(Matrix& A)
02003 {
02004    REPORT
02005    Tracer tr("RealStarStar");
02006    int n = A.ncols();
02007    int m = A.nrows();
02008    a = new Real*[m];
02009    MatrixErrorNoSpace(a);
02010    Real* d = A.data();
02011    for (int i = 0; i < m; ++i) a[i] = d + i * n;
02012 } 
02013 
02014 ConstRealStarStar::ConstRealStarStar(const Matrix& A)
02015 {
02016    REPORT
02017    Tracer tr("ConstRealStarStar");
02018    int n = A.ncols();
02019    int m = A.nrows();
02020    a = new const Real*[m];
02021    MatrixErrorNoSpace(a);
02022    const Real* d = A.data();
02023    for (int i = 0; i < m; ++i) a[i] = d + i * n;
02024 } 
02025 
02026 
02027 
02028 #ifdef use_namespace
02029 }
02030 #endif
02031 
02032 
02050 
02051 
02052 
02053 
02054 
02055 
02056 
02060 
02063 
02064 // Copyright (C) 1991,2,3,4: R B Davies
02065 
02066 //#define WANT_STREAM
02067 
02068 #ifdef use_namespace
02069 namespace NEWMAT {
02070 #endif
02071 
02072 
02073 #ifdef DO_REPORT
02074 #define REPORT { static ExeCounter ExeCount(__LINE__,5); ++ExeCount; }
02075 #else
02076 #define REPORT {}
02077 #endif
02078 
02079 
02080 /************************ carry out operations ******************************/
02081 
02082 
02083 GeneralMatrix* GeneralMatrix::Transpose(TransposedMatrix* tm, MatrixType mt)
02084 {
02085    GeneralMatrix* gm1;
02086 
02087    if (Compare(Type().t(),mt))
02088    {
02089       REPORT
02090       gm1 = mt.New(ncols_val,nrows_val,tm);
02091       for (int i=0; i<ncols_val; i++)
02092       {
02093          MatrixRow mr(gm1, StoreOnExit+DirectPart, i);
02094          MatrixCol mc(this, mr.Data(), LoadOnEntry, i);
02095       }
02096    }
02097    else
02098    {
02099       REPORT
02100       gm1 = mt.New(ncols_val,nrows_val,tm);
02101       MatrixRow mr(this, LoadOnEntry);
02102       MatrixCol mc(gm1, StoreOnExit+DirectPart);
02103       int i = nrows_val;
02104       while (i--) { mc.Copy(mr); mr.Next(); mc.Next(); }
02105    }
02106    tDelete(); gm1->ReleaseAndDelete(); return gm1;
02107 }
02108 
02109 GeneralMatrix* SymmetricMatrix::Transpose(TransposedMatrix*, MatrixType mt)
02110 { REPORT  return Evaluate(mt); }
02111 
02112 
02113 GeneralMatrix* DiagonalMatrix::Transpose(TransposedMatrix*, MatrixType mt)
02114 { REPORT return Evaluate(mt); }
02115 
02116 GeneralMatrix* ColumnVector::Transpose(TransposedMatrix*, MatrixType mt)
02117 {
02118    REPORT
02119    GeneralMatrix* gmx = new RowVector; MatrixErrorNoSpace(gmx);
02120    gmx->nrows_val = 1; gmx->ncols_val = gmx->storage = storage;
02121    return BorrowStore(gmx,mt);
02122 }
02123 
02124 GeneralMatrix* RowVector::Transpose(TransposedMatrix*, MatrixType mt)
02125 {
02126    REPORT
02127    GeneralMatrix* gmx = new ColumnVector; MatrixErrorNoSpace(gmx);
02128    gmx->ncols_val = 1; gmx->nrows_val = gmx->storage = storage;
02129    return BorrowStore(gmx,mt);
02130 }
02131 
02132 GeneralMatrix* IdentityMatrix::Transpose(TransposedMatrix*, MatrixType mt)
02133 { REPORT return Evaluate(mt); }
02134 
02135 GeneralMatrix* GeneralMatrix::Evaluate(MatrixType mt)
02136 {
02137    if (Compare(this->Type(),mt)) { REPORT return this; }
02138    REPORT
02139    GeneralMatrix* gmx = mt.New(nrows_val,ncols_val,this);
02140    MatrixRow mr(this, LoadOnEntry);
02141    MatrixRow mrx(gmx, StoreOnExit+DirectPart);
02142    int i=nrows_val;
02143    while (i--) { mrx.Copy(mr); mrx.Next(); mr.Next(); }
02144    tDelete(); gmx->ReleaseAndDelete(); return gmx;
02145 }
02146 
02147 GeneralMatrix* CroutMatrix::Evaluate(MatrixType mt)
02148 {
02149    if (Compare(this->Type(),mt)) { REPORT return this; }
02150    REPORT
02151    Tracer et("CroutMatrix::Evaluate");
02152    bool dummy = true;
02153    if (dummy) Throw(ProgramException("Illegal use of CroutMatrix", *this));
02154    return this;
02155 }
02156 
02157 GeneralMatrix* GenericMatrix::Evaluate(MatrixType mt)
02158    { REPORT  return gm->Evaluate(mt); }
02159 
02160 GeneralMatrix* ShiftedMatrix::Evaluate(MatrixType mt)
02161 {
02162    gm=((BaseMatrix*&)bm)->Evaluate();
02163    int nr=gm->Nrows(); int nc=gm->Ncols();
02164    Compare(gm->Type().AddEqualEl(),mt);
02165    if (!(mt==gm->Type()))
02166    {
02167       REPORT
02168       GeneralMatrix* gmx = mt.New(nr,nc,this);
02169       MatrixRow mr(gm, LoadOnEntry);
02170       MatrixRow mrx(gmx, StoreOnExit+DirectPart);
02171       while (nr--) { mrx.Add(mr,f); mrx.Next(); mr.Next(); }
02172       gmx->ReleaseAndDelete(); gm->tDelete();
02173       return gmx;
02174    }
02175    else if (gm->reuse())
02176    {
02177       REPORT gm->Add(f);
02178       return gm;
02179    }
02180    else
02181    {
02182       REPORT GeneralMatrix* gmy = gm->Type().New(nr,nc,this);
02183       gmy->ReleaseAndDelete(); gmy->Add(gm,f);
02184       return gmy;
02185    }
02186 }
02187 
02188 GeneralMatrix* NegShiftedMatrix::Evaluate(MatrixType mt)
02189 {
02190    gm=((BaseMatrix*&)bm)->Evaluate();
02191    int nr=gm->Nrows(); int nc=gm->Ncols();
02192    Compare(gm->Type().AddEqualEl(),mt);
02193    if (!(mt==gm->Type()))
02194    {
02195       REPORT
02196       GeneralMatrix* gmx = mt.New(nr,nc,this);
02197       MatrixRow mr(gm, LoadOnEntry);
02198       MatrixRow mrx(gmx, StoreOnExit+DirectPart);
02199       while (nr--) { mrx.NegAdd(mr,f); mrx.Next(); mr.Next(); }
02200       gmx->ReleaseAndDelete(); gm->tDelete();
02201       return gmx;
02202    }
02203    else if (gm->reuse())
02204    {
02205       REPORT gm->NegAdd(f);
02206       return gm;
02207    }
02208    else
02209    {
02210       REPORT GeneralMatrix* gmy = gm->Type().New(nr,nc,this);
02211       gmy->ReleaseAndDelete(); gmy->NegAdd(gm,f);
02212       return gmy;
02213    }
02214 }
02215 
02216 GeneralMatrix* ScaledMatrix::Evaluate(MatrixType mt)
02217 {
02218    gm=((BaseMatrix*&)bm)->Evaluate();
02219    int nr=gm->Nrows(); int nc=gm->Ncols();
02220    if (Compare(gm->Type(),mt))
02221    {
02222       if (gm->reuse())
02223       {
02224          REPORT gm->Multiply(f);
02225          return gm;
02226       }
02227       else
02228       {
02229          REPORT GeneralMatrix* gmx = gm->Type().New(nr,nc,this);
02230          gmx->ReleaseAndDelete(); gmx->Multiply(gm,f);
02231          return gmx;
02232       }
02233    }
02234    else
02235    {
02236       REPORT
02237       GeneralMatrix* gmx = mt.New(nr,nc,this);
02238       MatrixRow mr(gm, LoadOnEntry);
02239       MatrixRow mrx(gmx, StoreOnExit+DirectPart);
02240       while (nr--) { mrx.Multiply(mr,f); mrx.Next(); mr.Next(); }
02241       gmx->ReleaseAndDelete(); gm->tDelete();
02242       return gmx;
02243    }
02244 }
02245 
02246 GeneralMatrix* NegatedMatrix::Evaluate(MatrixType mt)
02247 {
02248    gm=((BaseMatrix*&)bm)->Evaluate();
02249    int nr=gm->Nrows(); int nc=gm->Ncols();
02250    if (Compare(gm->Type(),mt))
02251    {
02252       if (gm->reuse())
02253       {
02254          REPORT gm->Negate();
02255          return gm;
02256       }
02257       else
02258       {
02259          REPORT
02260          GeneralMatrix* gmx = gm->Type().New(nr,nc,this);
02261          gmx->ReleaseAndDelete(); gmx->Negate(gm);
02262          return gmx;
02263       }
02264    }
02265    else
02266    {
02267       REPORT
02268       GeneralMatrix* gmx = mt.New(nr,nc,this);
02269       MatrixRow mr(gm, LoadOnEntry);
02270       MatrixRow mrx(gmx, StoreOnExit+DirectPart);
02271       while (nr--) { mrx.Negate(mr); mrx.Next(); mr.Next(); }
02272       gmx->ReleaseAndDelete(); gm->tDelete();
02273       return gmx;
02274    }
02275 }
02276 
02277 GeneralMatrix* ReversedMatrix::Evaluate(MatrixType mt)
02278 {
02279    gm=((BaseMatrix*&)bm)->Evaluate(); GeneralMatrix* gmx;
02280 
02281    if ((gm->Type()).is_band() && ! (gm->Type()).is_diagonal())
02282    {
02283       gm->tDelete();
02284       Throw(NotDefinedException("Reverse", "band matrices"));
02285    }
02286 
02287    if (gm->reuse()) { REPORT gm->ReverseElements(); gmx = gm; }
02288    else
02289    {
02290       REPORT
02291       gmx = gm->Type().New(gm->Nrows(), gm->Ncols(), this);
02292       gmx->ReverseElements(gm); gmx->ReleaseAndDelete();
02293    }
02294    return gmx->Evaluate(mt); // target matrix is different type?
02295 
02296 }
02297 
02298 GeneralMatrix* TransposedMatrix::Evaluate(MatrixType mt)
02299 {
02300    REPORT
02301    gm=((BaseMatrix*&)bm)->Evaluate();
02302    Compare(gm->Type().t(),mt);
02303    GeneralMatrix* gmx=gm->Transpose(this, mt);
02304    return gmx;
02305 }
02306 
02307 GeneralMatrix* RowedMatrix::Evaluate(MatrixType mt)
02308 {
02309    gm = ((BaseMatrix*&)bm)->Evaluate();
02310    GeneralMatrix* gmx = new RowVector; MatrixErrorNoSpace(gmx);
02311    gmx->nrows_val = 1; gmx->ncols_val = gmx->storage = gm->storage;
02312    return gm->BorrowStore(gmx,mt);
02313 }
02314 
02315 GeneralMatrix* ColedMatrix::Evaluate(MatrixType mt)
02316 {
02317    gm = ((BaseMatrix*&)bm)->Evaluate();
02318    GeneralMatrix* gmx = new ColumnVector; MatrixErrorNoSpace(gmx);
02319    gmx->ncols_val = 1; gmx->nrows_val = gmx->storage = gm->storage;
02320    return gm->BorrowStore(gmx,mt);
02321 }
02322 
02323 GeneralMatrix* DiagedMatrix::Evaluate(MatrixType mt)
02324 {
02325    gm = ((BaseMatrix*&)bm)->Evaluate();
02326    GeneralMatrix* gmx = new DiagonalMatrix; MatrixErrorNoSpace(gmx);
02327    gmx->nrows_val = gmx->ncols_val = gmx->storage = gm->storage;
02328    return gm->BorrowStore(gmx,mt);
02329 }
02330 
02331 GeneralMatrix* MatedMatrix::Evaluate(MatrixType mt)
02332 {
02333    Tracer tr("MatedMatrix::Evaluate");
02334    gm = ((BaseMatrix*&)bm)->Evaluate();
02335    GeneralMatrix* gmx = new Matrix; MatrixErrorNoSpace(gmx);
02336    gmx->nrows_val = nr; gmx->ncols_val = nc; gmx->storage = gm->storage;
02337    if (nr*nc != gmx->storage)
02338       Throw(IncompatibleDimensionsException());
02339    return gm->BorrowStore(gmx,mt);
02340 }
02341 
02342 GeneralMatrix* GetSubMatrix::Evaluate(MatrixType mt)
02343 {
02344    REPORT
02345    Tracer tr("SubMatrix(evaluate)");
02346    gm = ((BaseMatrix*&)bm)->Evaluate();
02347    if (row_number < 0) row_number = gm->Nrows();
02348    if (col_number < 0) col_number = gm->Ncols();
02349    if (row_skip+row_number > gm->Nrows() || col_skip+col_number > gm->Ncols())
02350    {
02351       gm->tDelete();
02352       Throw(SubMatrixDimensionException());
02353    }
02354    if (IsSym) Compare(gm->Type().ssub(), mt);
02355    else Compare(gm->Type().sub(), mt);
02356    GeneralMatrix* gmx = mt.New(row_number, col_number, this);
02357    int i = row_number;
02358    MatrixRow mr(gm, LoadOnEntry, row_skip); 
02359    MatrixRow mrx(gmx, StoreOnExit+DirectPart);
02360    MatrixRowCol sub;
02361    while (i--)
02362    {
02363       mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
02364       mrx.Copy(sub); mrx.Next(); mr.Next();
02365    }
02366    gmx->ReleaseAndDelete(); gm->tDelete();
02367    return gmx;
02368 }
02369 
02370 
02371 GeneralMatrix* ReturnMatrix::Evaluate(MatrixType mt)
02372 {
02373    return gm->Evaluate(mt);
02374 }
02375 
02376 
02377 void GeneralMatrix::Add(GeneralMatrix* gm1, Real f)
02378 {
02379    REPORT
02380    Real* s1=gm1->store; Real* s=store; int i=(storage >> 2);
02381    while (i--)
02382    { *s++ = *s1++ + f; *s++ = *s1++ + f; *s++ = *s1++ + f; *s++ = *s1++ + f; }
02383    i = storage & 3; while (i--) *s++ = *s1++ + f;
02384 }
02385    
02386 void GeneralMatrix::Add(Real f)
02387 {
02388    REPORT
02389    Real* s=store; int i=(storage >> 2);
02390    while (i--) { *s++ += f; *s++ += f; *s++ += f; *s++ += f; }
02391    i = storage & 3; while (i--) *s++ += f;
02392 }
02393    
02394 void GeneralMatrix::NegAdd(GeneralMatrix* gm1, Real f)
02395 {
02396    REPORT
02397    Real* s1=gm1->store; Real* s=store; int i=(storage >> 2);
02398    while (i--)
02399    { *s++ = f - *s1++; *s++ = f - *s1++; *s++ = f - *s1++; *s++ = f - *s1++; }
02400    i = storage & 3; while (i--) *s++ = f - *s1++;
02401 }
02402    
02403 void GeneralMatrix::NegAdd(Real f)
02404 {
02405    REPORT
02406    Real* s=store; int i=(storage >> 2);
02407    while (i--)
02408    {
02409       *s = f - *s; s++; *s = f - *s; s++;
02410       *s = f - *s; s++; *s = f - *s; s++;
02411    }
02412    i = storage & 3; while (i--)  { *s = f - *s; s++; }
02413 }
02414    
02415 void GeneralMatrix::Negate(GeneralMatrix* gm1)
02416 {
02417    // change sign of elements
02418    REPORT
02419    Real* s1=gm1->store; Real* s=store; int i=(storage >> 2);
02420    while (i--)
02421    { *s++ = -(*s1++); *s++ = -(*s1++); *s++ = -(*s1++); *s++ = -(*s1++); }
02422    i = storage & 3; while(i--) *s++ = -(*s1++);
02423 }
02424    
02425 void GeneralMatrix::Negate()
02426 {
02427    REPORT
02428    Real* s=store; int i=(storage >> 2);
02429    while (i--)
02430    { *s = -(*s); s++; *s = -(*s); s++; *s = -(*s); s++; *s = -(*s); s++; }
02431    i = storage & 3; while(i--) { *s = -(*s); s++; }
02432 }
02433    
02434 void GeneralMatrix::Multiply(GeneralMatrix* gm1, Real f)
02435 {
02436    REPORT
02437    Real* s1=gm1->store; Real* s=store;  int i=(storage >> 2);
02438    while (i--)
02439    { *s++ = *s1++ * f; *s++ = *s1++ * f; *s++ = *s1++ * f; *s++ = *s1++ * f; }
02440    i = storage & 3; while (i--) *s++ = *s1++ * f;
02441 }
02442    
02443 void GeneralMatrix::Multiply(Real f)
02444 {
02445    REPORT
02446    Real* s=store; int i=(storage >> 2);
02447    while (i--) { *s++ *= f; *s++ *= f; *s++ *= f; *s++ *= f; }
02448    i = storage & 3; while (i--) *s++ *= f;
02449 }
02450    
02451 
02452 /************************ MatrixInput routines ****************************/
02453 
02454 // int MatrixInput::n;          // number values still to be read
02455 // Real* MatrixInput::r;        // pointer to next location to be read to
02456 
02457 MatrixInput MatrixInput::operator<<(double f)
02458 {
02459    REPORT
02460    Tracer et("MatrixInput");
02461    if (n<=0) Throw(ProgramException("List of values too long"));
02462    *r = (Real)f; int n1 = n-1; n=0;   // n=0 so we won't trigger exception
02463    return MatrixInput(n1, r+1);
02464 }
02465 
02466 
02467 MatrixInput GeneralMatrix::operator<<(double f)
02468 {
02469    REPORT
02470    Tracer et("MatrixInput");
02471    int n = Storage();
02472    if (n<=0) Throw(ProgramException("Loading data to zero length matrix"));
02473    Real* r; r = Store(); *r = (Real)f; n--;
02474    return MatrixInput(n, r+1);
02475 }
02476 
02477 MatrixInput GetSubMatrix::operator<<(double f)
02478 {
02479    REPORT
02480    Tracer et("MatrixInput (GetSubMatrix)");
02481    SetUpLHS();
02482    if (row_number != 1 || col_skip != 0 || col_number != gm->Ncols())
02483    {
02484       Throw(ProgramException("MatrixInput requires complete rows"));
02485    }
02486    MatrixRow mr(gm, DirectPart, row_skip);  // to pick up location and length
02487    int n = mr.Storage();
02488    if (n<=0)
02489    {
02490       Throw(ProgramException("Loading data to zero length row"));
02491    }
02492    Real* r; r = mr.Data(); *r = (Real)f; n--;
02493    if (+(mr.cw*HaveStore))
02494    {
02495       Throw(ProgramException("Fails with this matrix type"));
02496    }
02497    return MatrixInput(n, r+1);
02498 }
02499 
02500 MatrixInput MatrixInput::operator<<(float f)
02501 {
02502    REPORT
02503    Tracer et("MatrixInput");
02504    if (n<=0) Throw(ProgramException("List of values too long"));
02505    *r = (Real)f; int n1 = n-1; n=0;   // n=0 so we won't trigger exception
02506    return MatrixInput(n1, r+1);
02507 }
02508 
02509 
02510 MatrixInput GeneralMatrix::operator<<(float f)
02511 {
02512    REPORT
02513    Tracer et("MatrixInput");
02514    int n = Storage();
02515    if (n<=0) Throw(ProgramException("Loading data to zero length matrix"));
02516    Real* r; r = Store(); *r = (Real)f; n--;
02517    return MatrixInput(n, r+1);
02518 }
02519 
02520 MatrixInput GetSubMatrix::operator<<(float f)
02521 {
02522    REPORT
02523    Tracer et("MatrixInput (GetSubMatrix)");
02524    SetUpLHS();
02525    if (row_number != 1 || col_skip != 0 || col_number != gm->Ncols())
02526    {
02527       Throw(ProgramException("MatrixInput requires complete rows"));
02528    }
02529    MatrixRow mr(gm, DirectPart, row_skip);  // to pick up location and length
02530    int n = mr.Storage();
02531    if (n<=0)
02532    {
02533       Throw(ProgramException("Loading data to zero length row"));
02534    }
02535    Real* r; r = mr.Data(); *r = (Real)f; n--;
02536    if (+(mr.cw*HaveStore))
02537    {
02538       Throw(ProgramException("Fails with this matrix type"));
02539    }
02540    return MatrixInput(n, r+1);
02541 }
02542 MatrixInput::~MatrixInput()
02543 {
02544    REPORT
02545    Tracer et("MatrixInput");
02546    if (n!=0) Throw(ProgramException("A list of values was too short"));
02547 }
02548 
02549 MatrixInput BandMatrix::operator<<(double)
02550 {
02551    Tracer et("MatrixInput");
02552    bool dummy = true;
02553    if (dummy)                                   // get rid of warning message
02554       Throw(ProgramException("Cannot use list read with a BandMatrix"));
02555    return MatrixInput(0, 0);
02556 }
02557 
02558 MatrixInput BandMatrix::operator<<(float)
02559 {
02560    Tracer et("MatrixInput");
02561    bool dummy = true;
02562    if (dummy)                                   // get rid of warning message
02563       Throw(ProgramException("Cannot use list read with a BandMatrix"));
02564    return MatrixInput(0, 0);
02565 }
02566 
02567 void BandMatrix::operator<<(const double*)
02568 { Throw(ProgramException("Cannot use array read with a BandMatrix")); }
02569 
02570 void BandMatrix::operator<<(const float*)
02571 { Throw(ProgramException("Cannot use array read with a BandMatrix")); }
02572 
02573 void BandMatrix::operator<<(const int*)
02574 { Throw(ProgramException("Cannot use array read with a BandMatrix")); }
02575 
02576 void SymmetricBandMatrix::operator<<(const double*)
02577 { Throw(ProgramException("Cannot use array read with a BandMatrix")); }
02578 
02579 void SymmetricBandMatrix::operator<<(const float*)
02580 { Throw(ProgramException("Cannot use array read with a BandMatrix")); }
02581 
02582 void SymmetricBandMatrix::operator<<(const int*)
02583 { Throw(ProgramException("Cannot use array read with a BandMatrix")); }
02584 
02585 // ************************* Reverse order of elements ***********************
02586 
02587 void GeneralMatrix::ReverseElements(GeneralMatrix* gm)
02588 {
02589    // reversing into a new matrix
02590    REPORT
02591    int n = Storage(); Real* rx = Store() + n; Real* x = gm->Store();
02592    while (n--) *(--rx) = *(x++);
02593 }
02594 
02595 void GeneralMatrix::ReverseElements()
02596 {
02597    // reversing in place
02598    REPORT
02599    int n = Storage(); Real* x = Store(); Real* rx = x + n;
02600    n /= 2;
02601    while (n--) { Real t = *(--rx); *rx = *x; *(x++) = t; }
02602 }
02603 
02604 
02605 #ifdef use_namespace
02606 }
02607 #endif
02608 
02612 
02615 
02616 // Copyright (C) 1991,2,3,4: R B Davies
02617 
02618 #ifdef use_namespace
02619 namespace NEWMAT {
02620 #endif
02621 
02622 
02623 
02624 #ifdef DO_REPORT
02625 #define REPORT { static ExeCounter ExeCount(__LINE__,6); ++ExeCount; }
02626 #else
02627 #define REPORT {}
02628 #endif
02629 
02630 /*************************** general utilities *************************/
02631 
02632 /****************************** operators *******************************/
02633 
02634 Real& Matrix::operator()(int m, int n)
02635 {
02636    REPORT
02637    if (m<=0 || m>nrows_val || n<=0 || n>ncols_val)
02638       Throw(IndexException(m,n,*this));
02639    return store[(m-1)*ncols_val+n-1];
02640 }
02641 
02642 Real& SymmetricMatrix::operator()(int m, int n)
02643 {
02644    REPORT
02645    if (m<=0 || n<=0 || m>nrows_val || n>ncols_val)
02646       Throw(IndexException(m,n,*this));
02647    if (m>=n) return store[tristore(m-1)+n-1];
02648    else return store[tristore(n-1)+m-1];
02649 }
02650 
02651 Real& UpperTriangularMatrix::operator()(int m, int n)
02652 {
02653    REPORT
02654    if (m<=0 || n<m || n>ncols_val)
02655       Throw(IndexException(m,n,*this));
02656    return store[(m-1)*ncols_val+n-1-tristore(m-1)];
02657 }
02658 
02659 Real& LowerTriangularMatrix::operator()(int m, int n)
02660 {
02661    REPORT
02662    if (n<=0 || m<n || m>nrows_val)
02663       Throw(IndexException(m,n,*this));
02664    return store[tristore(m-1)+n-1];
02665 }
02666 
02667 Real& DiagonalMatrix::operator()(int m, int n)
02668 {
02669    REPORT
02670    if (n<=0 || m!=n || m>nrows_val || n>ncols_val)
02671       Throw(IndexException(m,n,*this));
02672    return store[n-1];
02673 }
02674 
02675 Real& DiagonalMatrix::operator()(int m)
02676 {
02677    REPORT
02678    if (m<=0 || m>nrows_val) Throw(IndexException(m,*this));
02679    return store[m-1];
02680 }
02681 
02682 Real& ColumnVector::operator()(int m)
02683 {
02684    REPORT
02685    if (m<=0 || m> nrows_val) Throw(IndexException(m,*this));
02686    return store[m-1];
02687 }
02688 
02689 Real& RowVector::operator()(int n)
02690 {
02691    REPORT
02692    if (n<=0 || n> ncols_val) Throw(IndexException(n,*this));
02693    return store[n-1];
02694 }
02695 
02696 Real& BandMatrix::operator()(int m, int n)
02697 {
02698    REPORT
02699    int w = upper_val+lower_val+1; int i = lower_val+n-m;
02700    if (m<=0 || m>nrows_val || n<=0 || n>ncols_val || i<0 || i>=w)
02701       Throw(IndexException(m,n,*this));
02702    return store[w*(m-1)+i];
02703 }
02704 
02705 Real& UpperBandMatrix::operator()(int m, int n)
02706 {
02707    REPORT
02708    int w = upper_val+1; int i = n-m;
02709    if (m<=0 || m>nrows_val || n<=0 || n>ncols_val || i<0 || i>=w)
02710       Throw(IndexException(m,n,*this));
02711    return store[w*(m-1)+i];
02712 }
02713 
02714 Real& LowerBandMatrix::operator()(int m, int n)
02715 {
02716    REPORT
02717    int w = lower_val+1; int i = lower_val+n-m;
02718    if (m<=0 || m>nrows_val || n<=0 || n>ncols_val || i<0 || i>=w)
02719       Throw(IndexException(m,n,*this));
02720    return store[w*(m-1)+i];
02721 }
02722 
02723 Real& SymmetricBandMatrix::operator()(int m, int n)
02724 {
02725    REPORT
02726    int w = lower_val+1;
02727    if (m>=n)
02728    {
02729       REPORT
02730       int i = lower_val+n-m;
02731       if ( m>nrows_val || n<=0 || i<0 )
02732          Throw(IndexException(m,n,*this));
02733       return store[w*(m-1)+i];
02734    }
02735    else
02736    {
02737       REPORT
02738       int i = lower_val+m-n;
02739       if ( n>nrows_val || m<=0 || i<0 )
02740          Throw(IndexException(m,n,*this));
02741       return store[w*(n-1)+i];
02742    }
02743 }
02744 
02745 
02746 Real Matrix::operator()(int m, int n) const
02747 {
02748    REPORT
02749    if (m<=0 || m>nrows_val || n<=0 || n>ncols_val)
02750       Throw(IndexException(m,n,*this));
02751    return store[(m-1)*ncols_val+n-1];
02752 }
02753 
02754 Real SymmetricMatrix::operator()(int m, int n) const
02755 {
02756    REPORT
02757    if (m<=0 || n<=0 || m>nrows_val || n>ncols_val)
02758       Throw(IndexException(m,n,*this));
02759    if (m>=n) return store[tristore(m-1)+n-1];
02760    else return store[tristore(n-1)+m-1];
02761 }
02762 
02763 Real UpperTriangularMatrix::operator()(int m, int n) const
02764 {
02765    REPORT
02766    if (m<=0 || n<m || n>ncols_val)
02767       Throw(IndexException(m,n,*this));
02768    return store[(m-1)*ncols_val+n-1-tristore(m-1)];
02769 }
02770 
02771 Real LowerTriangularMatrix::operator()(int m, int n) const
02772 {
02773    REPORT
02774    if (n<=0 || m<n || m>nrows_val)
02775       Throw(IndexException(m,n,*this));
02776    return store[tristore(m-1)+n-1];
02777 }
02778 
02779 Real DiagonalMatrix::operator()(int m, int n) const
02780 {
02781    REPORT
02782    if (n<=0 || m!=n || m>nrows_val || n>ncols_val)
02783       Throw(IndexException(m,n,*this));
02784    return store[n-1];
02785 }
02786 
02787 Real DiagonalMatrix::operator()(int m) const
02788 {
02789    REPORT
02790    if (m<=0 || m>nrows_val) Throw(IndexException(m,*this));
02791    return store[m-1];
02792 }
02793 
02794 Real ColumnVector::operator()(int m) const
02795 {
02796    REPORT
02797    if (m<=0 || m> nrows_val) Throw(IndexException(m,*this));
02798    return store[m-1];
02799 }
02800 
02801 Real RowVector::operator()(int n) const
02802 {
02803    REPORT
02804    if (n<=0 || n> ncols_val) Throw(IndexException(n,*this));
02805    return store[n-1];
02806 }
02807 
02808 Real BandMatrix::operator()(int m, int n) const
02809 {
02810    REPORT
02811    int w = upper_val+lower_val+1; int i = lower_val+n-m;
02812    if (m<=0 || m>nrows_val || n<=0 || n>ncols_val || i<0 || i>=w)
02813       Throw(IndexException(m,n,*this));
02814    return store[w*(m-1)+i];
02815 }
02816 
02817 Real UpperBandMatrix::operator()(int m, int n) const
02818 {
02819    REPORT
02820    int w = upper_val+1; int i = n-m;
02821    if (m<=0 || m>nrows_val || n<=0 || n>ncols_val || i<0 || i>=w)
02822       Throw(IndexException(m,n,*this));
02823    return store[w*(m-1)+i];
02824 }
02825 
02826 Real LowerBandMatrix::operator()(int m, int n) const
02827 {
02828    REPORT
02829    int w = lower_val+1; int i = lower_val+n-m;
02830    if (m<=0 || m>nrows_val || n<=0 || n>ncols_val || i<0 || i>=w)
02831       Throw(IndexException(m,n,*this));
02832    return store[w*(m-1)+i];
02833 }
02834 
02835 Real SymmetricBandMatrix::operator()(int m, int n) const
02836 {
02837    REPORT
02838    int w = lower_val+1;
02839    if (m>=n)
02840    {
02841       REPORT
02842       int i = lower_val+n-m;
02843       if ( m>nrows_val || n<=0 || i<0 )
02844          Throw(IndexException(m,n,*this));
02845       return store[w*(m-1)+i];
02846    }
02847    else
02848    {
02849       REPORT
02850       int i = lower_val+m-n;
02851       if ( n>nrows_val || m<=0 || i<0 )
02852          Throw(IndexException(m,n,*this));
02853       return store[w*(n-1)+i];
02854    }
02855 }
02856 
02857 
02858 Real BaseMatrix::as_scalar() const
02859 {
02860    REPORT
02861    GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
02862 
02863    if (gm->nrows_val!=1 || gm->ncols_val!=1)
02864    {
02865       Tracer tr("as_scalar");
02866       Try
02867          { Throw(ProgramException("Cannot convert to scalar", *gm)); }
02868       CatchAll { gm->tDelete(); ReThrow; }
02869    }
02870 
02871    Real x = *(gm->store); gm->tDelete(); return x;
02872 }
02873 
02874 
02875 AddedMatrix BaseMatrix::operator+(const BaseMatrix& bm) const
02876 { REPORT return AddedMatrix(this, &bm); }
02877 
02878 SPMatrix SP(const BaseMatrix& bm1,const BaseMatrix& bm2)
02879 { REPORT return SPMatrix(&bm1, &bm2); }
02880 
02881 KPMatrix KP(const BaseMatrix& bm1,const BaseMatrix& bm2)
02882 { REPORT return KPMatrix(&bm1, &bm2); }
02883 
02884 MultipliedMatrix BaseMatrix::operator*(const BaseMatrix& bm) const
02885 { REPORT return MultipliedMatrix(this, &bm); }
02886 
02887 ConcatenatedMatrix BaseMatrix::operator|(const BaseMatrix& bm) const
02888 { REPORT return ConcatenatedMatrix(this, &bm); }
02889 
02890 StackedMatrix BaseMatrix::operator&(const BaseMatrix& bm) const
02891 { REPORT return StackedMatrix(this, &bm); }
02892 
02893 SolvedMatrix InvertedMatrix::operator*(const BaseMatrix& bmx) const
02894 { REPORT return SolvedMatrix(bm, &bmx); }
02895 
02896 SubtractedMatrix BaseMatrix::operator-(const BaseMatrix& bm) const
02897 { REPORT return SubtractedMatrix(this, &bm); }
02898 
02899 ShiftedMatrix BaseMatrix::operator+(Real f) const
02900 { REPORT return ShiftedMatrix(this, f); }
02901 
02902 ShiftedMatrix operator+(Real f, const BaseMatrix& BM)
02903 { REPORT return ShiftedMatrix(&BM, f); }
02904 
02905 NegShiftedMatrix operator-(Real f, const BaseMatrix& bm)
02906 { REPORT return NegShiftedMatrix(f, &bm); }
02907 
02908 ScaledMatrix BaseMatrix::operator*(Real f) const
02909 { REPORT return ScaledMatrix(this, f); }
02910 
02911 ScaledMatrix BaseMatrix::operator/(Real f) const
02912 { REPORT return ScaledMatrix(this, 1.0/f); }
02913 
02914 ScaledMatrix operator*(Real f, const BaseMatrix& BM)
02915 { REPORT return ScaledMatrix(&BM, f); }
02916 
02917 ShiftedMatrix BaseMatrix::operator-(Real f) const
02918 { REPORT return ShiftedMatrix(this, -f); }
02919 
02920 TransposedMatrix BaseMatrix::t() const
02921 { REPORT return TransposedMatrix(this); }
02922 
02923 NegatedMatrix BaseMatrix::operator-() const
02924 { REPORT return NegatedMatrix(this); }
02925 
02926 ReversedMatrix BaseMatrix::reverse() const
02927 { REPORT return ReversedMatrix(this); }
02928 
02929 InvertedMatrix BaseMatrix::i() const
02930 { REPORT return InvertedMatrix(this); }
02931 
02932 
02933 RowedMatrix BaseMatrix::as_row() const
02934 { REPORT return RowedMatrix(this); }
02935 
02936 ColedMatrix BaseMatrix::as_column() const
02937 { REPORT return ColedMatrix(this); }
02938 
02939 DiagedMatrix BaseMatrix::as_diagonal() const
02940 { REPORT return DiagedMatrix(this); }
02941 
02942 MatedMatrix BaseMatrix::as_matrix(int nrx, int ncx) const
02943 { REPORT return MatedMatrix(this,nrx,ncx); }
02944 
02945 
02946 void GeneralMatrix::operator=(Real f)
02947 { REPORT int i=storage; Real* s=store; while (i--) { *s++ = f; } }
02948 
02949 void Matrix::operator=(const BaseMatrix& X)
02950 {
02951    REPORT //CheckConversion(X);
02952    // MatrixConversionCheck mcc;
02953    Eq(X,MatrixType::Rt);
02954 } 
02955 
02956 void SquareMatrix::operator=(const BaseMatrix& X)
02957 {
02958    REPORT //CheckConversion(X);
02959    // MatrixConversionCheck mcc;
02960    Eq(X,MatrixType::Rt);
02961    if (nrows_val != ncols_val)
02962       { Tracer tr("SquareMatrix(=)"); Throw(NotSquareException(*this)); }
02963 }
02964 
02965 void SquareMatrix::operator=(const Matrix& m)
02966 {
02967    REPORT
02968    if (m.nrows_val != m.ncols_val)
02969       { Tracer tr("SquareMatrix(=Matrix)"); Throw(NotSquareException(*this)); }
02970    Eq(m);
02971 }
02972 
02973 void RowVector::operator=(const BaseMatrix& X)
02974 {
02975    REPORT  // CheckConversion(X);
02976    // MatrixConversionCheck mcc;
02977    Eq(X,MatrixType::RV);
02978    if (nrows_val!=1)
02979       { Tracer tr("RowVector(=)"); Throw(VectorException(*this)); }
02980 }
02981 
02982 void ColumnVector::operator=(const BaseMatrix& X)
02983 {
02984    REPORT //CheckConversion(X);
02985    // MatrixConversionCheck mcc;
02986    Eq(X,MatrixType::CV);
02987    if (ncols_val!=1)
02988       { Tracer tr("ColumnVector(=)"); Throw(VectorException(*this)); }
02989 }
02990 
02991 void SymmetricMatrix::operator=(const BaseMatrix& X)
02992 {
02993    REPORT // CheckConversion(X);
02994    // MatrixConversionCheck mcc;
02995    Eq(X,MatrixType::Sm);
02996 }
02997 
02998 void UpperTriangularMatrix::operator=(const BaseMatrix& X)
02999 {
03000    REPORT //CheckConversion(X);
03001    // MatrixConversionCheck mcc;
03002    Eq(X,MatrixType::UT);
03003 }
03004 
03005 void LowerTriangularMatrix::operator=(const BaseMatrix& X)
03006 {
03007    REPORT //CheckConversion(X);
03008    // MatrixConversionCheck mcc;
03009    Eq(X,MatrixType::LT);
03010 }
03011 
03012 void DiagonalMatrix::operator=(const BaseMatrix& X)
03013 {
03014    REPORT // CheckConversion(X);
03015    // MatrixConversionCheck mcc;
03016    Eq(X,MatrixType::Dg);
03017 }
03018 
03019 void IdentityMatrix::operator=(const BaseMatrix& X)
03020 {
03021    REPORT // CheckConversion(X);
03022    // MatrixConversionCheck mcc;
03023    Eq(X,MatrixType::Id);
03024 }
03025 
03026 
03027 void CroutMatrix::operator=(const CroutMatrix& gm)
03028 {
03029    if (&gm == this) { REPORT tag_val = -1; return; }
03030    REPORT
03031    if (indx > 0) { delete [] indx; indx = 0; }
03032    ((CroutMatrix&)gm).get_aux(*this);
03033    Eq(gm);
03034 }
03035    
03036 
03037 
03038 
03039 
03040 void GeneralMatrix::operator<<(const double* r)
03041 {
03042    REPORT
03043    int i = storage; Real* s=store;
03044    while(i--) *s++ = (Real)*r++;
03045 }
03046 
03047 
03048 void GeneralMatrix::operator<<(const float* r)
03049 {
03050    REPORT
03051    int i = storage; Real* s=store;
03052    while(i--) *s++ = (Real)*r++;
03053 }
03054 
03055 
03056 void GeneralMatrix::operator<<(const int* r)
03057 {
03058    REPORT
03059    int i = storage; Real* s=store;
03060    while(i--) *s++ = (Real)*r++;
03061 }
03062 
03063 
03064 void GenericMatrix::operator=(const GenericMatrix& bmx)
03065 {
03066    if (&bmx != this) { REPORT if (gm) delete gm; gm = bmx.gm->Image();}
03067    else { REPORT }
03068    gm->Protect();
03069 }
03070 
03071 void GenericMatrix::operator=(const BaseMatrix& bmx)
03072 {
03073    if (gm)
03074    {
03075       int counter=bmx.search(gm);
03076       if (counter==0) { REPORT delete gm; gm=0; }
03077       else { REPORT gm->Release(counter); }
03078    }
03079    else { REPORT }
03080    GeneralMatrix* gmx = ((BaseMatrix&)bmx).Evaluate();
03081    if (gmx != gm) { REPORT if (gm) delete gm; gm = gmx->Image(); }
03082    else { REPORT }
03083    gm->Protect();
03084 }
03085 
03086 
03087 /*************************** += etc ***************************************/
03088 
03089 
03090 // GeneralMatrix operators
03091 
03092 void GeneralMatrix::operator+=(const BaseMatrix& X)
03093 {
03094    REPORT
03095    Tracer tr("GeneralMatrix::operator+=");
03096    // MatrixConversionCheck mcc;
03097    Protect();                                   // so it cannot get deleted
03098                                                 // during Evaluate
03099    GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
03100    AddedMatrix am(this,gm);
03101    if (gm==this) Release(2); else Release();
03102    Eq2(am,type());
03103 }
03104 
03105 void GeneralMatrix::operator-=(const BaseMatrix& X)
03106 {
03107    REPORT
03108    Tracer tr("GeneralMatrix::operator-=");
03109    // MatrixConversionCheck mcc;
03110    Protect();                                   // so it cannot get deleted
03111                                                 // during Evaluate
03112    GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
03113    SubtractedMatrix am(this,gm);
03114    if (gm==this) Release(2); else Release();
03115    Eq2(am,type());
03116 }
03117 
03118 void GeneralMatrix::operator*=(const BaseMatrix& X)
03119 {
03120    REPORT
03121    Tracer tr("GeneralMatrix::operator*=");
03122    // MatrixConversionCheck mcc;
03123    Protect();                                   // so it cannot get deleted
03124                                                 // during Evaluate
03125    GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
03126    MultipliedMatrix am(this,gm);
03127    if (gm==this) Release(2); else Release();
03128    Eq2(am,type());
03129 }
03130 
03131 void GeneralMatrix::operator|=(const BaseMatrix& X)
03132 {
03133    REPORT
03134    Tracer tr("GeneralMatrix::operator|=");
03135    // MatrixConversionCheck mcc;
03136    Protect();                                   // so it cannot get deleted
03137                                                 // during Evaluate
03138    GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
03139    ConcatenatedMatrix am(this,gm);
03140    if (gm==this) Release(2); else Release();
03141    Eq2(am,type());
03142 }
03143 
03144 void GeneralMatrix::operator&=(const BaseMatrix& X)
03145 {
03146    REPORT
03147    Tracer tr("GeneralMatrix::operator&=");
03148    // MatrixConversionCheck mcc;
03149    Protect();                                   // so it cannot get deleted
03150                                                 // during Evaluate
03151    GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
03152    StackedMatrix am(this,gm);
03153    if (gm==this) Release(2); else Release();
03154    Eq2(am,type());
03155 }
03156 
03157 void GeneralMatrix::operator+=(Real r)
03158 {
03159    REPORT
03160    Tracer tr("GeneralMatrix::operator+=(Real)");
03161    // MatrixConversionCheck mcc;
03162    ShiftedMatrix am(this,r);
03163    Release(); Eq2(am,type());
03164 }
03165 
03166 void GeneralMatrix::operator*=(Real r)
03167 {
03168    REPORT
03169    Tracer tr("GeneralMatrix::operator*=(Real)");
03170    // MatrixConversionCheck mcc;
03171    ScaledMatrix am(this,r);
03172    Release(); Eq2(am,type());
03173 }
03174 
03175 
03176 // Generic matrix operators
03177 
03178 void GenericMatrix::operator+=(const BaseMatrix& X)
03179 {
03180    REPORT
03181    Tracer tr("GenericMatrix::operator+=");
03182    if (!gm) Throw(ProgramException("GenericMatrix is null"));
03183    gm->Protect();            // so it cannot get deleted during Evaluate
03184    GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
03185    AddedMatrix am(gm,gmx);
03186    if (gmx==gm) gm->Release(2); else gm->Release();
03187    GeneralMatrix* gmy = am.Evaluate();
03188    if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
03189    else { REPORT }
03190    gm->Protect();
03191 }
03192 
03193 void GenericMatrix::operator-=(const BaseMatrix& X)
03194 {
03195    REPORT
03196    Tracer tr("GenericMatrix::operator-=");
03197    if (!gm) Throw(ProgramException("GenericMatrix is null"));
03198    gm->Protect();            // so it cannot get deleted during Evaluate
03199    GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
03200    SubtractedMatrix am(gm,gmx);
03201    if (gmx==gm) gm->Release(2); else gm->Release();
03202    GeneralMatrix* gmy = am.Evaluate();
03203    if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
03204    else { REPORT }
03205    gm->Protect();
03206 }
03207 
03208 void GenericMatrix::operator*=(const BaseMatrix& X)
03209 {
03210    REPORT
03211    Tracer tr("GenericMatrix::operator*=");
03212    if (!gm) Throw(ProgramException("GenericMatrix is null"));
03213    gm->Protect();            // so it cannot get deleted during Evaluate
03214    GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
03215    MultipliedMatrix am(gm,gmx);
03216    if (gmx==gm) gm->Release(2); else gm->Release();
03217    GeneralMatrix* gmy = am.Evaluate();
03218    if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
03219    else { REPORT }
03220    gm->Protect();
03221 }
03222 
03223 void GenericMatrix::operator|=(const BaseMatrix& X)
03224 {
03225    REPORT
03226    Tracer tr("GenericMatrix::operator|=");
03227    if (!gm) Throw(ProgramException("GenericMatrix is null"));
03228    gm->Protect();            // so it cannot get deleted during Evaluate
03229    GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
03230    ConcatenatedMatrix am(gm,gmx);
03231    if (gmx==gm) gm->Release(2); else gm->Release();
03232    GeneralMatrix* gmy = am.Evaluate();
03233    if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
03234    else { REPORT }
03235    gm->Protect();
03236 }
03237 
03238 void GenericMatrix::operator&=(const BaseMatrix& X)
03239 {
03240    REPORT
03241    Tracer tr("GenericMatrix::operator&=");
03242    if (!gm) Throw(ProgramException("GenericMatrix is null"));
03243    gm->Protect();            // so it cannot get deleted during Evaluate
03244    GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
03245    StackedMatrix am(gm,gmx);
03246    if (gmx==gm) gm->Release(2); else gm->Release();
03247    GeneralMatrix* gmy = am.Evaluate();
03248    if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
03249    else { REPORT }
03250    gm->Protect();
03251 }
03252 
03253 void GenericMatrix::operator+=(Real r)
03254 {
03255    REPORT
03256    Tracer tr("GenericMatrix::operator+= (Real)");
03257    if (!gm) Throw(ProgramException("GenericMatrix is null"));
03258    ShiftedMatrix am(gm,r);
03259    gm->Release();
03260    GeneralMatrix* gmy = am.Evaluate();
03261    if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
03262    else { REPORT }
03263    gm->Protect();
03264 }
03265 
03266 void GenericMatrix::operator*=(Real r)
03267 {
03268    REPORT
03269    Tracer tr("GenericMatrix::operator*= (Real)");
03270    if (!gm) Throw(ProgramException("GenericMatrix is null"));
03271    ScaledMatrix am(gm,r);
03272    gm->Release();
03273    GeneralMatrix* gmy = am.Evaluate();
03274    if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
03275    else { REPORT }
03276    gm->Protect();
03277 }
03278 
03279 
03280 /************************* element access *********************************/
03281 
03282 Real& Matrix::element(int m, int n)
03283 {
03284    REPORT
03285    if (m<0 || m>= nrows_val || n<0 || n>= ncols_val)
03286       Throw(IndexException(m,n,*this,true));
03287    return store[m*ncols_val+n];
03288 }
03289 
03290 Real Matrix::element(int m, int n) const
03291 {
03292    REPORT
03293    if (m<0 || m>= nrows_val || n<0 || n>= ncols_val)
03294       Throw(IndexException(m,n,*this,true));
03295    return store[m*ncols_val+n];
03296 }
03297 
03298 Real& SymmetricMatrix::element(int m, int n)
03299 {
03300    REPORT
03301    if (m<0 || n<0 || m >= nrows_val || n>=ncols_val)
03302       Throw(IndexException(m,n,*this,true));
03303    if (m>=n) return store[tristore(m)+n];
03304    else return store[tristore(n)+m];
03305 }
03306 
03307 Real SymmetricMatrix::element(int m, int n) const
03308 {
03309    REPORT
03310    if (m<0 || n<0 || m >= nrows_val || n>=ncols_val)
03311       Throw(IndexException(m,n,*this,true));
03312    if (m>=n) return store[tristore(m)+n];
03313    else return store[tristore(n)+m];
03314 }
03315 
03316 Real& UpperTriangularMatrix::element(int m, int n)
03317 {
03318    REPORT
03319    if (m<0 || n<m || n>=ncols_val)
03320       Throw(IndexException(m,n,*this,true));
03321    return store[m*ncols_val+n-tristore(m)];
03322 }
03323 
03324 Real UpperTriangularMatrix::element(int m, int n) const
03325 {
03326    REPORT
03327    if (m<0 || n<m || n>=ncols_val)
03328       Throw(IndexException(m,n,*this,true));
03329    return store[m*ncols_val+n-tristore(m)];
03330 }
03331 
03332 Real& LowerTriangularMatrix::element(int m, int n)
03333 {
03334    REPORT
03335    if (n<0 || m<n || m>=nrows_val)
03336       Throw(IndexException(m,n,*this,true));
03337    return store[tristore(m)+n];
03338 }
03339 
03340 Real LowerTriangularMatrix::element(int m, int n) const
03341 {
03342    REPORT
03343    if (n<0 || m<n || m>=nrows_val)
03344       Throw(IndexException(m,n,*this,true));
03345    return store[tristore(m)+n];
03346 }
03347 
03348 Real& DiagonalMatrix::element(int m, int n)
03349 {
03350    REPORT
03351    if (n<0 || m!=n || m>=nrows_val || n>=ncols_val)
03352       Throw(IndexException(m,n,*this,true));
03353    return store[n];
03354 }
03355 
03356 Real DiagonalMatrix::element(int m, int n) const
03357 {
03358    REPORT
03359    if (n<0 || m!=n || m>=nrows_val || n>=ncols_val)
03360       Throw(IndexException(m,n,*this,true));
03361    return store[n];
03362 }
03363 
03364 Real& DiagonalMatrix::element(int m)
03365 {
03366    REPORT
03367    if (m<0 || m>=nrows_val) Throw(IndexException(m,*this,true));
03368    return store[m];
03369 }
03370 
03371 Real DiagonalMatrix::element(int m) const
03372 {
03373    REPORT
03374    if (m<0 || m>=nrows_val) Throw(IndexException(m,*this,true));
03375    return store[m];
03376 }
03377 
03378 Real& ColumnVector::element(int m)
03379 {
03380    REPORT
03381    if (m<0 || m>= nrows_val) Throw(IndexException(m,*this,true));
03382    return store[m];
03383 }
03384 
03385 Real ColumnVector::element(int m) const
03386 {
03387    REPORT
03388    if (m<0 || m>= nrows_val) Throw(IndexException(m,*this,true));
03389    return store[m];
03390 }
03391 
03392 Real& RowVector::element(int n)
03393 {
03394    REPORT
03395    if (n<0 || n>= ncols_val)  Throw(IndexException(n,*this,true));
03396    return store[n];
03397 }
03398 
03399 Real RowVector::element(int n) const
03400 {
03401    REPORT
03402    if (n<0 || n>= ncols_val)  Throw(IndexException(n,*this,true));
03403    return store[n];
03404 }
03405 
03406 Real& BandMatrix::element(int m, int n)
03407 {
03408    REPORT
03409    int w = upper_val+lower_val+1; int i = lower_val+n-m;
03410    if (m<0 || m>= nrows_val || n<0 || n>= ncols_val || i<0 || i>=w)
03411       Throw(IndexException(m,n,*this,true));
03412    return store[w*m+i];
03413 }
03414 
03415 Real BandMatrix::element(int m, int n) const
03416 {
03417    REPORT
03418    int w = upper_val+lower_val+1; int i = lower_val+n-m;
03419    if (m<0 || m>= nrows_val || n<0 || n>= ncols_val || i<0 || i>=w)
03420       Throw(IndexException(m,n,*this,true));
03421    return store[w*m+i];
03422 }
03423 
03424 Real& UpperBandMatrix::element(int m, int n)
03425 {
03426    REPORT
03427    int w = upper_val+1; int i = n-m;
03428    if (m<0 || m>= nrows_val || n<0 || n>= ncols_val || i<0 || i>=w)
03429       Throw(IndexException(m,n,*this,true));
03430    return store[w*m+i];
03431 }
03432 
03433 Real UpperBandMatrix::element(int m, int n) const
03434 {
03435    REPORT
03436    int w = upper_val+1; int i = n-m;
03437    if (m<0 || m>= nrows_val || n<0 || n>= ncols_val || i<0 || i>=w)
03438       Throw(IndexException(m,n,*this,true));
03439    return store[w*m+i];
03440 }
03441 
03442 Real& LowerBandMatrix::element(int m, int n)
03443 {
03444    REPORT
03445    int w = lower_val+1; int i = lower_val+n-m;
03446    if (m<0 || m>= nrows_val || n<0 || n>= ncols_val || i<0 || i>=w)
03447       Throw(IndexException(m,n,*this,true));
03448    return store[w*m+i];
03449 }
03450 
03451 Real LowerBandMatrix::element(int m, int n) const
03452 {
03453    REPORT
03454    int w = lower_val+1; int i = lower_val+n-m;
03455    if (m<0 || m>= nrows_val || n<0 || n>= ncols_val || i<0 || i>=w)
03456       Throw(IndexException(m,n,*this,true));
03457    return store[w*m+i];
03458 }
03459 
03460 Real& SymmetricBandMatrix::element(int m, int n)
03461 {
03462    REPORT
03463    int w = lower_val+1;
03464    if (m>=n)
03465    {
03466       REPORT
03467       int i = lower_val+n-m;
03468       if ( m>=nrows_val || n<0 || i<0 )
03469          Throw(IndexException(m,n,*this,true));
03470       return store[w*m+i];
03471    }
03472    else
03473    {
03474       REPORT
03475       int i = lower_val+m-n;
03476       if ( n>=nrows_val || m<0 || i<0 )
03477          Throw(IndexException(m,n,*this,true));
03478       return store[w*n+i];
03479    }
03480 }
03481 
03482 Real SymmetricBandMatrix::element(int m, int n) const
03483 {
03484    REPORT
03485    int w = lower_val+1;
03486    if (m>=n)
03487    {
03488       REPORT
03489       int i = lower_val+n-m;
03490       if ( m>=nrows_val || n<0 || i<0 )
03491          Throw(IndexException(m,n,*this,true));
03492       return store[w*m+i];
03493    }
03494    else
03495    {
03496       REPORT
03497       int i = lower_val+m-n;
03498       if ( n>=nrows_val || m<0 || i<0 )
03499          Throw(IndexException(m,n,*this,true));
03500       return store[w*n+i];
03501    }
03502 }
03503 
03504 #ifdef use_namespace
03505 }
03506 #endif
03507 
03508 
03512 
03515 
03516 // Copyright (C) 1991,2,3,4,8: R B Davies
03517 
03518 #define WANT_MATH
03519 
03522 
03525 
03526 #ifndef PRECISION_LIB
03527 #define PRECISION_LIB 0
03528 
03529 #define WANT_MATH
03530 
03531 #ifdef _STANDARD_                 // standard library available
03532 #include <limits>
03533 #endif
03534 
03535 #ifdef use_namespace
03536 namespace NEWMAT {
03537 #endif
03538 
03539 #ifdef _STANDARD_                 // standard library available
03540 
03541 #ifdef OPT_COMPATIBLE
03542 #include <cfloat>                 // for FLT_MAX
03543 #endif
03544 
03545 using namespace std;
03546         
03548 class FloatingPointPrecision
03549 {
03550 public:
03551    static int Dig()              // number of decimal digits or precision
03552       { return numeric_limits<Real>::digits10 ; }
03553 
03554    static Real Epsilon()         // smallest number such that 1+Eps!=Eps
03555       { return numeric_limits<Real>::epsilon(); }
03556 
03557    static int Mantissa()         // bits in mantisa
03558       { return numeric_limits<Real>::digits; }
03559 
03560    static Real Maximum()         // maximum value
03561       { return numeric_limits<Real>::max(); }
03562 
03563    static int MaximumDecimalExponent()  // maximum decimal exponent
03564       { return numeric_limits<Real>::max_exponent10; }
03565 
03566    static int MaximumExponent()  // maximum binary exponent
03567       { return numeric_limits<Real>::max_exponent; }
03568 
03569    static Real LnMaximum()       // natural log of maximum
03570       { return (Real)log(Maximum()); }
03571 
03572    static Real Minimum()         // minimum positive value
03573       { return numeric_limits<Real>::min(); } 
03574 
03575    static int MinimumDecimalExponent() // minimum decimal exponent
03576       { return numeric_limits<Real>::min_exponent10; }
03577 
03578    static int MinimumExponent()  // minimum binary exponent
03579       { return numeric_limits<Real>::min_exponent; }
03580 
03581    static Real LnMinimum()       // natural log of minimum
03582       { return (Real)log(Minimum()); }
03583 
03584    static int Radix()            // exponent radix
03585       { return numeric_limits<Real>::radix; }
03586 
03587    static int Rounds()           // addition rounding (1 = does round)
03588    {
03589           return numeric_limits<Real>::round_style ==
03590                  round_to_nearest ? 1 : 0;
03591    }
03592 
03593 };
03594 
03595 
03596 #else                              // _STANDARD_ not defined
03597 
03598 #ifndef SystemV                    // if there is float.h
03599 
03600 #ifdef USING_FLOAT
03601 
03603 class FloatingPointPrecision
03604 {
03605 public:
03606    static int Dig()
03607       { return FLT_DIG; }        // number of decimal digits or precision
03608 
03609    static Real Epsilon()
03610       { return FLT_EPSILON; }    // smallest number such that 1+Eps!=Eps
03611 
03612    static int Mantissa()
03613       { return FLT_MANT_DIG; }   // bits in mantisa
03614 
03615    static Real Maximum()
03616       { return FLT_MAX; }        // maximum value
03617 
03618    static int MaximumDecimalExponent()
03619       { return FLT_MAX_10_EXP; } // maximum decimal exponent
03620 
03621    static int MaximumExponent()
03622       { return FLT_MAX_EXP; }    // maximum binary exponent
03623 
03624    static Real LnMaximum()
03625       { return (Real)log(Maximum()); } // natural log of maximum
03626 
03627    static Real Minimum()
03628       { return FLT_MIN; }        // minimum positive value
03629 
03630    static int MinimumDecimalExponent()
03631       { return FLT_MIN_10_EXP; } // minimum decimal exponent
03632 
03633    static int MinimumExponent()
03634       { return FLT_MIN_EXP; }    // minimum binary exponent
03635 
03636    static Real LnMinimum()
03637       { return (Real)log(Minimum()); } // natural log of minimum
03638 
03639    static int Radix()
03640       { return FLT_RADIX; }      // exponent radix
03641 
03642    static int Rounds()
03643       { return FLT_ROUNDS; }     // addition rounding (1 = does round)
03644 
03645 };
03646 
03647 #endif                           // USING_FLOAT
03648 
03649 
03650 #ifdef USING_DOUBLE
03651 
03653 class FloatingPointPrecision
03654 {
03655 public:
03656 
03657    static int Dig()
03658       { return DBL_DIG; }        // number of decimal digits or precision
03659 
03660    static Real Epsilon()
03661       { return DBL_EPSILON; }    // smallest number such that 1+Eps!=Eps
03662 
03663    static int Mantissa()
03664       { return DBL_MANT_DIG; }   // bits in mantisa
03665 
03666    static Real Maximum()
03667       { return DBL_MAX; }        // maximum value
03668 
03669    static int MaximumDecimalExponent()
03670       { return DBL_MAX_10_EXP; } // maximum decimal exponent
03671 
03672    static int MaximumExponent()
03673       { return DBL_MAX_EXP; }    // maximum binary exponent
03674 
03675    static Real LnMaximum()
03676       { return (Real)log(Maximum()); } // natural log of maximum
03677 
03678    static Real Minimum()
03679    {
03680 //#ifdef __BCPLUSPLUS__
03681 //       return 2.225074e-308;     // minimum positive value
03682 //#else
03683        return DBL_MIN;
03684 //#endif
03685    }
03686 
03687    static int MinimumDecimalExponent()
03688       { return DBL_MIN_10_EXP; } // minimum decimal exponent
03689 
03690    static int MinimumExponent()
03691       { return DBL_MIN_EXP; }    // minimum binary exponent
03692 
03693    static Real LnMinimum()
03694       { return (Real)log(Minimum()); } // natural log of minimum
03695 
03696 
03697    static int Radix()
03698       { return FLT_RADIX; }      // exponent radix
03699 
03700    static int Rounds()
03701       { return FLT_ROUNDS; }     // addition rounding (1 = does round)
03702 
03703 };
03704 
03705 #endif                             // USING_DOUBLE
03706 
03707 #else                              // if there is no float.h
03708 
03709 #ifdef OPT_COMPATIBLE
03710 #define FLT_MAX MAXFLOAT
03711 #endif
03712 
03713 
03714 #ifdef USING_FLOAT
03715 
03717 class FloatingPointPrecision
03718 {
03719 public:
03720 
03721    static Real Epsilon()
03722       { return pow(2.0,(int)(1-FSIGNIF)); }
03723                                    // smallest number such that 1+Eps!=Eps
03724 
03725    static Real Maximum()
03726       { return MAXFLOAT; }            // maximum value
03727 
03728    static Real LnMaximum()
03729       { return (Real)log(Maximum()); }  // natural log of maximum
03730 
03731    static Real Minimum()
03732       { return MINFLOAT; }             // minimum positive value
03733 
03734    static Real LnMinimum()
03735       { return (Real)log(Minimum()); }  // natural log of minimum
03736 
03737 };
03738 
03739 #endif                                  // USING_FLOAT
03740 
03741 
03742 #ifdef USING_DOUBLE
03743 
03745 class FloatingPointPrecision
03746 {
03747 public:
03748 
03749    static Real Epsilon()
03750       { return pow(2.0,(int)(1-DSIGNIF)); }
03751                                       // smallest number such that 1+Eps!=Eps
03752 
03753    static Real Maximum()
03754       { return MAXDOUBLE; }           // maximum value
03755 
03756    static Real LnMaximum()
03757       { return LN_MAXDOUBLE; }        // natural log of maximum
03758 
03759    static Real Minimum()
03760       { return MINDOUBLE; }
03761 
03762    static Real LnMinimum()
03763       { return LN_MINDOUBLE; }        // natural log of minimum
03764 };
03765 
03766 #endif                                // USING_DOUBLE
03767 
03768 #endif                                // SystemV
03769 
03770 #endif                                // _STANDARD_
03771 
03772 
03773 
03774 
03775 #ifdef use_namespace
03776 }
03777 #endif                                // use_namespace
03778 
03779 
03780 
03781 #endif                                // PRECISION_LIB
03782 
03783 
03785 
03786 #ifdef use_namespace
03787 namespace NEWMAT {
03788 #endif
03789 
03790 
03791 #ifdef DO_REPORT
03792 #define REPORT { static ExeCounter ExeCount(__LINE__,8); ++ExeCount; }
03793 #else
03794 #define REPORT {}
03795 #endif
03796 
03797 
03798 /************************** LU transformation ****************************/
03799 
03800 void CroutMatrix::ludcmp()
03801 // LU decomposition from Golub & Van Loan, algorithm 3.4.1, (the "outer
03802 // product" version).
03803 // This replaces the code derived from Numerical Recipes in C in previous
03804 // versions of newmat and being row oriented runs much faster with large
03805 // matrices.
03806 {
03807    REPORT
03808    Tracer tr( "Crout(ludcmp)" ); sing = false;
03809    Real* akk = store;                    // runs down diagonal
03810 
03811    Real big = fabs(*akk); int mu = 0; Real* ai = akk; int k;
03812 
03813    for (k = 1; k < nrows_val; k++)
03814    {
03815       ai += nrows_val; const Real trybig = fabs(*ai);
03816       if (big < trybig) { big = trybig; mu = k; }
03817    }
03818 
03819 
03820    if (nrows_val) for (k = 0;;)
03821    {
03822       /*
03823       int mu1;
03824       {
03825          Real big = fabs(*akk); mu1 = k; Real* ai = akk; int i;
03826 
03827          for (i = k+1; i < nrows_val; i++)
03828          {
03829             ai += nrows_val; const Real trybig = fabs(*ai);
03830             if (big < trybig) { big = trybig; mu1 = i; }
03831          }
03832       }
03833       if (mu1 != mu) cout << k << " " << mu << " " << mu1 << endl;
03834       */
03835 
03836       indx[k] = mu;
03837 
03838       if (mu != k)                       //row swap
03839       {
03840          Real* a1 = store + nrows_val * k;
03841          Real* a2 = store + nrows_val * mu; d = !d;
03842          int j = nrows_val;
03843          while (j--) { const Real temp = *a1; *a1++ = *a2; *a2++ = temp; }
03844       }
03845 
03846       Real diag = *akk; big = 0; mu = k + 1;
03847       if (diag != 0)
03848       {
03849          ai = akk; int i = nrows_val - k - 1;
03850          while (i--)
03851          {
03852             ai += nrows_val; Real* al = ai;
03853             Real mult = *al / diag; *al = mult;
03854             int l = nrows_val - k - 1; Real* aj = akk;
03855             // work out the next pivot as part of this loop
03856             // this saves a column operation
03857             if (l-- != 0)
03858             {
03859                *(++al) -= (mult * *(++aj));
03860                const Real trybig = fabs(*al);
03861                if (big < trybig) { big = trybig; mu = nrows_val - i - 1; }
03862                while (l--) *(++al) -= (mult * *(++aj));
03863             }
03864          }
03865       }
03866       else sing = true;
03867       if (++k == nrows_val) break;          // so next line won't overflow
03868       akk += nrows_val + 1;
03869    }
03870 }
03871 
03872 void CroutMatrix::lubksb(Real* B, int mini)
03873 {
03874    REPORT
03875    // this has been adapted from Numerical Recipes in C. The code has been
03876    // substantially streamlined, so I do not think much of the original
03877    // copyright remains. However there is not much opportunity for
03878    // variation in the code, so it is still similar to the NR code.
03879    // I follow the NR code in skipping over initial zeros in the B vector.
03880 
03881    Tracer tr("Crout(lubksb)");
03882    if (sing) Throw(SingularException(*this));
03883    int i, j, ii = nrows_val;       // ii initialised : B might be all zeros
03884 
03885 
03886    // scan for first non-zero in B
03887    for (i = 0; i < nrows_val; i++)
03888    {
03889       int ip = indx[i]; Real temp = B[ip]; B[ip] = B[i]; B[i] = temp;
03890       if (temp != 0.0) { ii = i; break; }
03891    }
03892 
03893    Real* bi; Real* ai;
03894    i = ii + 1;
03895 
03896    if (i < nrows_val)
03897    {
03898       bi = B + ii; ai = store + ii + i * nrows_val;
03899       for (;;)
03900       {
03901          int ip = indx[i]; Real sum = B[ip]; B[ip] = B[i];
03902          Real* aij = ai; Real* bj = bi; j = i - ii;
03903          while (j--) sum -= *aij++ * *bj++;
03904          B[i] = sum;
03905          if (++i == nrows_val) break;
03906          ai += nrows_val;
03907       }
03908    }
03909 
03910    ai = store + nrows_val * nrows_val;
03911 
03912    for (i = nrows_val - 1; i >= mini; i--)
03913    {
03914       Real* bj = B+i; ai -= nrows_val; Real* ajx = ai+i;
03915       Real sum = *bj; Real diag = *ajx;
03916       j = nrows_val - i; while(--j) sum -= *(++ajx) * *(++bj);
03917       B[i] = sum / diag;
03918    }
03919 }
03920 
03921 /****************************** scalar functions ****************************/
03922 
03923 
03924 Real GeneralMatrix::sum_square() const
03925 {
03926    REPORT
03927    Real sum = 0.0; int i = storage; Real* s = store;
03928    while (i--) sum += square(*s++);
03929    ((GeneralMatrix&)*this).tDelete(); return sum;
03930 }
03931 
03932 Real GeneralMatrix::sum_absolute_value() const
03933 {
03934    REPORT
03935    Real sum = 0.0; int i = storage; Real* s = store;
03936    while (i--) sum += fabs(*s++);
03937    ((GeneralMatrix&)*this).tDelete(); return sum;
03938 }
03939 
03940 Real GeneralMatrix::sum() const
03941 {
03942    REPORT
03943    Real sm = 0.0; int i = storage; Real* s = store;
03944    while (i--) sm += *s++;
03945    ((GeneralMatrix&)*this).tDelete(); return sm;
03946 }
03947 
03948 // maxima and minima
03949 
03950 // There are three sets of routines
03951 // maximum_absolute_value, minimum_absolute_value, maximum, minimum
03952 // ... these find just the maxima and minima
03953 // maximum_absolute_value1, minimum_absolute_value1, maximum1, minimum1
03954 // ... these find the maxima and minima and their locations in a
03955 //     one dimensional object
03956 // maximum_absolute_value2, minimum_absolute_value2, maximum2, minimum2
03957 // ... these find the maxima and minima and their locations in a
03958 //     two dimensional object
03959 
03960 // If the matrix has no values throw an exception
03961 
03962 // If we do not want the location find the maximum or minimum on the
03963 // array stored by GeneralMatrix
03964 // This won't work for BandMatrices. We call ClearCorner for
03965 // maximum_absolute_value but for the others use the absolute_minimum_value2
03966 // version and discard the location.
03967 
03968 // For one dimensional objects, when we want the location of the
03969 // maximum or minimum, work with the array stored by GeneralMatrix
03970 
03971 // For two dimensional objects where we want the location of the maximum or
03972 // minimum proceed as follows:
03973 
03974 // For rectangular matrices use the array stored by GeneralMatrix and
03975 // deduce the location from the location in the GeneralMatrix
03976 
03977 // For other two dimensional matrices use the Matrix Row routine to find the
03978 // maximum or minimum for each row.
03979 
03980 static void NullMatrixError(const GeneralMatrix* gm)
03981 {
03982    ((GeneralMatrix&)*gm).tDelete();
03983    Throw(ProgramException("Maximum or minimum of null matrix"));
03984 }
03985 
03986 Real GeneralMatrix::maximum_absolute_value() const
03987 {
03988    REPORT
03989    if (storage == 0) NullMatrixError(this);
03990    Real maxval = 0.0; int l = storage; Real* s = store;
03991    while (l--) { Real a = fabs(*s++); if (maxval < a) maxval = a; }
03992    ((GeneralMatrix&)*this).tDelete(); return maxval;
03993 }
03994 
03995 Real GeneralMatrix::maximum_absolute_value1(int& i) const
03996 {
03997    REPORT
03998    if (storage == 0) NullMatrixError(this);
03999    Real maxval = 0.0; int l = storage; Real* s = store; int li = storage;
04000    while (l--)
04001       { Real a = fabs(*s++); if (maxval <= a) { maxval = a; li = l; }  }
04002    i = storage - li;
04003    ((GeneralMatrix&)*this).tDelete(); return maxval;
04004 }
04005 
04006 Real GeneralMatrix::minimum_absolute_value() const
04007 {
04008    REPORT
04009    if (storage == 0) NullMatrixError(this);
04010    int l = storage - 1; Real* s = store; Real minval = fabs(*s++);
04011    while (l--) { Real a = fabs(*s++); if (minval > a) minval = a; }
04012    ((GeneralMatrix&)*this).tDelete(); return minval;
04013 }
04014 
04015 Real GeneralMatrix::minimum_absolute_value1(int& i) const
04016 {
04017    REPORT
04018    if (storage == 0) NullMatrixError(this);
04019    int l = storage - 1; Real* s = store; Real minval = fabs(*s++); int li = l;
04020    while (l--)
04021       { Real a = fabs(*s++); if (minval >= a) { minval = a; li = l; }  }
04022    i = storage - li;
04023    ((GeneralMatrix&)*this).tDelete(); return minval;
04024 }
04025 
04026 Real GeneralMatrix::maximum() const
04027 {
04028    REPORT
04029    if (storage == 0) NullMatrixError(this);
04030    int l = storage - 1; Real* s = store; Real maxval = *s++;
04031    while (l--) { Real a = *s++; if (maxval < a) maxval = a; }
04032    ((GeneralMatrix&)*this).tDelete(); return maxval;
04033 }
04034 
04035 Real GeneralMatrix::maximum1(int& i) const
04036 {
04037    REPORT
04038    if (storage == 0) NullMatrixError(this);
04039    int l = storage - 1; Real* s = store; Real maxval = *s++; int li = l;
04040    while (l--) { Real a = *s++; if (maxval <= a) { maxval = a; li = l; } }
04041    i = storage - li;
04042    ((GeneralMatrix&)*this).tDelete(); return maxval;
04043 }
04044 
04045 Real GeneralMatrix::minimum() const
04046 {
04047    REPORT
04048    if (storage == 0) NullMatrixError(this);
04049    int l = storage - 1; Real* s = store; Real minval = *s++;
04050    while (l--) { Real a = *s++; if (minval > a) minval = a; }
04051    ((GeneralMatrix&)*this).tDelete(); return minval;
04052 }
04053 
04054 Real GeneralMatrix::minimum1(int& i) const
04055 {
04056    REPORT
04057    if (storage == 0) NullMatrixError(this);
04058    int l = storage - 1; Real* s = store; Real minval = *s++; int li = l;
04059    while (l--) { Real a = *s++; if (minval >= a) { minval = a; li = l; } }
04060    i = storage - li;
04061    ((GeneralMatrix&)*this).tDelete(); return minval;
04062 }
04063 
04064 Real GeneralMatrix::maximum_absolute_value2(int& i, int& j) const
04065 {
04066    REPORT
04067    if (storage == 0) NullMatrixError(this);
04068    Real maxval = 0.0; int nr = Nrows();
04069    MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart);
04070    for (int r = 1; r <= nr; r++)
04071    {
04072       int c; maxval = mr.MaximumAbsoluteValue1(maxval, c);
04073       if (c > 0) { i = r; j = c; }
04074       mr.Next();
04075    }
04076    ((GeneralMatrix&)*this).tDelete(); return maxval;
04077 }
04078 
04079 Real GeneralMatrix::minimum_absolute_value2(int& i, int& j) const
04080 {
04081    REPORT
04082    if (storage == 0)  NullMatrixError(this);
04083    Real minval = FloatingPointPrecision::Maximum(); int nr = Nrows();
04084    MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart);
04085    for (int r = 1; r <= nr; r++)
04086    {
04087       int c; minval = mr.MinimumAbsoluteValue1(minval, c);
04088       if (c > 0) { i = r; j = c; }
04089       mr.Next();
04090    }
04091    ((GeneralMatrix&)*this).tDelete(); return minval;
04092 }
04093 
04094 Real GeneralMatrix::maximum2(int& i, int& j) const
04095 {
04096    REPORT
04097    if (storage == 0) NullMatrixError(this);
04098    Real maxval = -FloatingPointPrecision::Maximum(); int nr = Nrows();
04099    MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart);
04100    for (int r = 1; r <= nr; r++)
04101    {
04102       int c; maxval = mr.Maximum1(maxval, c);
04103       if (c > 0) { i = r; j = c; }
04104       mr.Next();
04105    }
04106    ((GeneralMatrix&)*this).tDelete(); return maxval;
04107 }
04108 
04109 Real GeneralMatrix::minimum2(int& i, int& j) const
04110 {
04111    REPORT
04112    if (storage == 0) NullMatrixError(this);
04113    Real minval = FloatingPointPrecision::Maximum(); int nr = Nrows();
04114    MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart);
04115    for (int r = 1; r <= nr; r++)
04116    {
04117       int c; minval = mr.Minimum1(minval, c);
04118       if (c > 0) { i = r; j = c; }
04119       mr.Next();
04120    }
04121    ((GeneralMatrix&)*this).tDelete(); return minval;
04122 }
04123 
04124 Real Matrix::maximum_absolute_value2(int& i, int& j) const
04125 {
04126    REPORT
04127    int k; Real m = GeneralMatrix::maximum_absolute_value1(k); k--;
04128    i = k / Ncols(); j = k - i * Ncols(); i++; j++;
04129    return m;
04130 }
04131 
04132 Real Matrix::minimum_absolute_value2(int& i, int& j) const
04133 {
04134    REPORT
04135    int k; Real m = GeneralMatrix::minimum_absolute_value1(k); k--;
04136    i = k / Ncols(); j = k - i * Ncols(); i++; j++;
04137    return m;
04138 }
04139 
04140 Real Matrix::maximum2(int& i, int& j) const
04141 {
04142    REPORT
04143    int k; Real m = GeneralMatrix::maximum1(k); k--;
04144    i = k / Ncols(); j = k - i * Ncols(); i++; j++;
04145    return m;
04146 }
04147 
04148 Real Matrix::minimum2(int& i, int& j) const
04149 {
04150    REPORT
04151    int k; Real m = GeneralMatrix::minimum1(k); k--;
04152    i = k / Ncols(); j = k - i * Ncols(); i++; j++;
04153    return m;
04154 }
04155 
04156 Real SymmetricMatrix::sum_square() const
04157 {
04158    REPORT
04159    Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows_val;
04160    for (int i = 0; i<nr; i++)
04161    {
04162       int j = i;
04163       while (j--) sum2 += square(*s++);
04164       sum1 += square(*s++);
04165    }
04166    ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
04167 }
04168 
04169 Real SymmetricMatrix::sum_absolute_value() const
04170 {
04171    REPORT
04172    Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows_val;
04173    for (int i = 0; i<nr; i++)
04174    {
04175       int j = i;
04176       while (j--) sum2 += fabs(*s++);
04177       sum1 += fabs(*s++);
04178    }
04179    ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
04180 }
04181 
04182 Real IdentityMatrix::sum_absolute_value() const
04183    { REPORT  return fabs(trace()); }    // no need to do tDelete?
04184 
04185 Real SymmetricMatrix::sum() const
04186 {
04187    REPORT
04188    Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows_val;
04189    for (int i = 0; i<nr; i++)
04190    {
04191       int j = i;
04192       while (j--) sum2 += *s++;
04193       sum1 += *s++;
04194    }
04195    ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
04196 }
04197 
04198 Real IdentityMatrix::sum_square() const
04199 {
04200    Real sum = *store * *store * nrows_val;
04201    ((GeneralMatrix&)*this).tDelete(); return sum;
04202 }
04203 
04204 
04205 Real BaseMatrix::sum_square() const
04206 {
04207    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04208    Real s = gm->sum_square(); return s;
04209 }
04210 
04211 Real BaseMatrix::norm_Frobenius() const
04212    { REPORT  return sqrt(sum_square()); }
04213 
04214 Real BaseMatrix::sum_absolute_value() const
04215 {
04216    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04217    Real s = gm->sum_absolute_value(); return s;
04218 }
04219 
04220 Real BaseMatrix::sum() const
04221 {
04222    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04223    Real s = gm->sum(); return s;
04224 }
04225 
04226 Real BaseMatrix::maximum_absolute_value() const
04227 {
04228    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04229    Real s = gm->maximum_absolute_value(); return s;
04230 }
04231 
04232 Real BaseMatrix::maximum_absolute_value1(int& i) const
04233 {
04234    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04235    Real s = gm->maximum_absolute_value1(i); return s;
04236 }
04237 
04238 Real BaseMatrix::maximum_absolute_value2(int& i, int& j) const
04239 {
04240    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04241    Real s = gm->maximum_absolute_value2(i, j); return s;
04242 }
04243 
04244 Real BaseMatrix::minimum_absolute_value() const
04245 {
04246    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04247    Real s = gm->minimum_absolute_value(); return s;
04248 }
04249 
04250 Real BaseMatrix::minimum_absolute_value1(int& i) const
04251 {
04252    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04253    Real s = gm->minimum_absolute_value1(i); return s;
04254 }
04255 
04256 Real BaseMatrix::minimum_absolute_value2(int& i, int& j) const
04257 {
04258    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04259    Real s = gm->minimum_absolute_value2(i, j); return s;
04260 }
04261 
04262 Real BaseMatrix::maximum() const
04263 {
04264    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04265    Real s = gm->maximum(); return s;
04266 }
04267 
04268 Real BaseMatrix::maximum1(int& i) const
04269 {
04270    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04271    Real s = gm->maximum1(i); return s;
04272 }
04273 
04274 Real BaseMatrix::maximum2(int& i, int& j) const
04275 {
04276    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04277    Real s = gm->maximum2(i, j); return s;
04278 }
04279 
04280 Real BaseMatrix::minimum() const
04281 {
04282    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04283    Real s = gm->minimum(); return s;
04284 }
04285 
04286 Real BaseMatrix::minimum1(int& i) const
04287 {
04288    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04289    Real s = gm->minimum1(i); return s;
04290 }
04291 
04292 Real BaseMatrix::minimum2(int& i, int& j) const
04293 {
04294    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04295    Real s = gm->minimum2(i, j); return s;
04296 }
04297 
04298 Real dotproduct(const Matrix& A, const Matrix& B)
04299 {
04300    REPORT
04301    int n = A.storage;
04302    if (n != B.storage)
04303    {
04304       Tracer tr("dotproduct");
04305       Throw(IncompatibleDimensionsException(A,B));
04306    }
04307    Real sum = 0.0; Real* a = A.store; Real* b = B.store;
04308    while (n--) sum += *a++ * *b++;
04309    return sum;
04310 }
04311 
04312 Real Matrix::trace() const
04313 {
04314    REPORT
04315    Tracer tr("trace");
04316    int i = nrows_val; int d = i+1;
04317    if (i != ncols_val) Throw(NotSquareException(*this));
04318    Real sum = 0.0; Real* s = store;
04319 //   while (i--) { sum += *s; s += d; }
04320    if (i) for (;;) { sum += *s; if (!(--i)) break; s += d; }
04321    ((GeneralMatrix&)*this).tDelete(); return sum;
04322 }
04323 
04324 Real DiagonalMatrix::trace() const
04325 {
04326    REPORT
04327    int i = nrows_val; Real sum = 0.0; Real* s = store;
04328    while (i--) sum += *s++;
04329    ((GeneralMatrix&)*this).tDelete(); return sum;
04330 }
04331 
04332 Real SymmetricMatrix::trace() const
04333 {
04334    REPORT
04335    int i = nrows_val; Real sum = 0.0; Real* s = store; int j = 2;
04336    // while (i--) { sum += *s; s += j++; }
04337    if (i) for (;;) { sum += *s; if (!(--i)) break; s += j++; }
04338    ((GeneralMatrix&)*this).tDelete(); return sum;
04339 }
04340 
04341 Real LowerTriangularMatrix::trace() const
04342 {
04343    REPORT
04344    int i = nrows_val; Real sum = 0.0; Real* s = store; int j = 2;
04345    // while (i--) { sum += *s; s += j++; }
04346    if (i) for (;;) { sum += *s; if (!(--i)) break; s += j++; }
04347    ((GeneralMatrix&)*this).tDelete(); return sum;
04348 }
04349 
04350 Real UpperTriangularMatrix::trace() const
04351 {
04352    REPORT
04353    int i = nrows_val; Real sum = 0.0; Real* s = store;
04354    while (i) { sum += *s; s += i--; }             // won t cause a problem
04355    ((GeneralMatrix&)*this).tDelete(); return sum;
04356 }
04357 
04358 Real BandMatrix::trace() const
04359 {
04360    REPORT
04361    int i = nrows_val; int w = lower_val+upper_val+1;
04362    Real sum = 0.0; Real* s = store+lower_val;
04363    // while (i--) { sum += *s; s += w; }
04364    if (i) for (;;) { sum += *s; if (!(--i)) break; s += w; }
04365    ((GeneralMatrix&)*this).tDelete(); return sum;
04366 }
04367 
04368 Real SymmetricBandMatrix::trace() const
04369 {
04370    REPORT
04371    int i = nrows_val; int w = lower_val+1;
04372    Real sum = 0.0; Real* s = store+lower_val;
04373    // while (i--) { sum += *s; s += w; }
04374    if (i) for (;;) { sum += *s; if (!(--i)) break; s += w; }
04375    ((GeneralMatrix&)*this).tDelete(); return sum;
04376 }
04377 
04378 Real IdentityMatrix::trace() const
04379 {
04380    Real sum = *store * nrows_val;
04381    ((GeneralMatrix&)*this).tDelete(); return sum;
04382 }
04383 
04384 
04385 Real BaseMatrix::trace() const
04386 {
04387    REPORT
04388    MatrixType Diag = MatrixType::Dg; Diag.SetDataLossOK();
04389    GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(Diag);
04390    Real sum = gm->trace(); return sum;
04391 }
04392 
04393 void LogAndSign::operator*=(Real x)
04394 {
04395    if (x > 0.0) { log_val += log(x); }
04396    else if (x < 0.0) { log_val += log(-x); sign_val = -sign_val; }
04397    else sign_val = 0;
04398 }
04399 
04400 void LogAndSign::pow_eq(int k)
04401 {
04402    if (sign_val)
04403    {
04404       log_val *= k;
04405       if ( (k & 1) == 0 ) sign_val = 1;
04406    }
04407 }
04408 
04409 Real LogAndSign::value() const
04410 {
04411    Tracer et("LogAndSign::value");
04412    if (log_val >= FloatingPointPrecision::LnMaximum())
04413       Throw(OverflowException("Overflow in exponential"));
04414    return sign_val * exp(log_val);
04415 }
04416 
04417 LogAndSign::LogAndSign(Real f)
04418 {
04419    if (f == 0.0) { log_val = 0.0; sign_val = 0; return; }
04420    else if (f < 0.0) { sign_val = -1; f = -f; }
04421    else sign_val = 1;
04422    log_val = log(f);
04423 }
04424 
04425 LogAndSign DiagonalMatrix::log_determinant() const
04426 {
04427    REPORT
04428    int i = nrows_val; LogAndSign sum; Real* s = store;
04429    while (i--) sum *= *s++;
04430    ((GeneralMatrix&)*this).tDelete(); return sum;
04431 }
04432 
04433 LogAndSign LowerTriangularMatrix::log_determinant() const
04434 {
04435    REPORT
04436    int i = nrows_val; LogAndSign sum; Real* s = store; int j = 2;
04437    // while (i--) { sum *= *s; s += j++; }
04438    if (i) for(;;) { sum *= *s; if (!(--i)) break; s += j++; }
04439    ((GeneralMatrix&)*this).tDelete(); return sum;
04440 }
04441 
04442 LogAndSign UpperTriangularMatrix::log_determinant() const
04443 {
04444    REPORT
04445    int i = nrows_val; LogAndSign sum; Real* s = store;
04446    while (i) { sum *= *s; s += i--; }
04447    ((GeneralMatrix&)*this).tDelete(); return sum;
04448 }
04449 
04450 LogAndSign IdentityMatrix::log_determinant() const
04451 {
04452    REPORT
04453    int i = nrows_val; LogAndSign sum;
04454    if (i > 0) { sum = *store; sum.PowEq(i); }
04455    ((GeneralMatrix&)*this).tDelete(); return sum;
04456 }
04457 
04458 LogAndSign BaseMatrix::log_determinant() const
04459 {
04460    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04461    LogAndSign sum = gm->log_determinant(); return sum;
04462 }
04463 
04464 LogAndSign GeneralMatrix::log_determinant() const
04465 {
04466    REPORT
04467    Tracer tr("log_determinant");
04468    if (nrows_val != ncols_val) Throw(NotSquareException(*this));
04469    CroutMatrix C(*this); return C.log_determinant();
04470 }
04471 
04472 LogAndSign CroutMatrix::log_determinant() const
04473 {
04474    REPORT
04475    if (sing) return 0.0;
04476    int i = nrows_val; int dd = i+1; LogAndSign sum; Real* s = store;
04477    if (i) for(;;)
04478    {
04479       sum *= *s;
04480       if (!(--i)) break;
04481       s += dd;
04482    }
04483    if (!d) sum.ChangeSign(); return sum;
04484 
04485 }
04486 
04487 Real BaseMatrix::determinant() const
04488 {
04489    REPORT
04490    Tracer tr("determinant");
04491    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04492    LogAndSign ld = gm->log_determinant();
04493    return ld.Value();
04494 }
04495 
04496 LinearEquationSolver::LinearEquationSolver(const BaseMatrix& bm)
04497 {
04498    gm = ( ((BaseMatrix&)bm).Evaluate() )->MakeSolver();
04499    if (gm==&bm) { REPORT  gm = gm->Image(); }
04500    // want a copy if  *gm is actually bm
04501    else { REPORT  gm->Protect(); }
04502 }
04503 
04504 ReturnMatrix BaseMatrix::sum_square_rows() const
04505 {
04506    REPORT
04507    GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04508    int nr = gm->nrows();
04509    ColumnVector ssq(nr);
04510    if (gm->size() == 0) { REPORT ssq = 0.0; }
04511    else
04512    {
04513       MatrixRow mr(gm, LoadOnEntry);
04514       for (int i = 1; i <= nr; ++i)
04515       {
04516          Real sum = 0.0;
04517          int s = mr.Storage();
04518          Real* in = mr.Data();
04519          while (s--) sum += square(*in++);
04520          ssq(i) = sum;   
04521          mr.Next();
04522       }
04523    }
04524    gm->tDelete();
04525    ssq.release(); return ssq.for_return();
04526 }
04527 
04528 ReturnMatrix BaseMatrix::sum_square_columns() const
04529 {
04530    REPORT
04531    GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04532    int nr = gm->nrows(); int nc = gm->ncols();
04533    RowVector ssq(nc); ssq = 0.0;
04534    if (gm->size() != 0)
04535    {
04536       MatrixRow mr(gm, LoadOnEntry);
04537       for (int i = 1; i <= nr; ++i)
04538       {
04539          int s = mr.Storage();
04540          Real* in = mr.Data(); Real* out = ssq.data() + mr.Skip();
04541          while (s--) *out++ += square(*in++);
04542          mr.Next();
04543       }
04544    }
04545    gm->tDelete();
04546    ssq.release(); return ssq.for_return();
04547 }
04548 
04549 ReturnMatrix BaseMatrix::sum_rows() const
04550 {
04551    REPORT
04552    GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04553    int nr = gm->nrows();
04554    ColumnVector sum_vec(nr);
04555    if (gm->size() == 0) { REPORT sum_vec = 0.0; }
04556    else
04557    {
04558       MatrixRow mr(gm, LoadOnEntry);
04559       for (int i = 1; i <= nr; ++i)
04560       {
04561          Real sum = 0.0;
04562          int s = mr.Storage();
04563          Real* in = mr.Data();
04564          while (s--) sum += *in++;
04565          sum_vec(i) = sum;   
04566          mr.Next();
04567       }
04568    }
04569    gm->tDelete();
04570    sum_vec.release(); return sum_vec.for_return();
04571 }
04572 
04573 ReturnMatrix BaseMatrix::sum_columns() const
04574 {
04575    REPORT
04576    GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
04577    int nr = gm->nrows(); int nc = gm->ncols();
04578    RowVector sum_vec(nc); sum_vec = 0.0;
04579    if (gm->size() != 0)
04580    {
04581       MatrixRow mr(gm, LoadOnEntry);
04582       for (int i = 1; i <= nr; ++i)
04583       {
04584          int s = mr.Storage();
04585          Real* in = mr.Data(); Real* out = sum_vec.data() + mr.Skip();
04586          while (s--) *out++ += *in++;
04587          mr.Next();
04588       }
04589    }
04590    gm->tDelete();
04591    sum_vec.release(); return sum_vec.for_return();
04592 }
04593 
04594 
04595 #ifdef use_namespace
04596 }
04597 #endif
04598 
04599 
04603 
04606 
04607 // Copyright (C) 1991,2,3,4: R B Davies
04608 
04609 
04610 #ifdef use_namespace
04611 namespace NEWMAT {
04612 #endif
04613 
04614 
04615 #ifdef DO_REPORT
04616 #define REPORT { static ExeCounter ExeCount(__LINE__,7); ++ExeCount; }
04617 #else
04618 #define REPORT {}
04619 #endif
04620 
04621 
04622 //***************************** solve routines ******************************/
04623 
04624 GeneralMatrix* GeneralMatrix::MakeSolver()
04625 {
04626    REPORT
04627    GeneralMatrix* gm = new CroutMatrix(*this);
04628    MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
04629 }
04630 
04631 GeneralMatrix* Matrix::MakeSolver()
04632 {
04633    REPORT
04634    GeneralMatrix* gm = new CroutMatrix(*this);
04635    MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
04636 }
04637 
04638 void CroutMatrix::Solver(MatrixColX& mcout, const MatrixColX& mcin)
04639 {
04640    REPORT
04641    int i = mcin.skip; Real* el = mcin.data-i; Real* el1 = el;
04642    while (i--) *el++ = 0.0;
04643    el += mcin.storage; i = nrows_val - mcin.skip - mcin.storage;
04644    while (i--) *el++ = 0.0;
04645    lubksb(el1, mcout.skip);
04646 }
04647 
04648 
04649 // Do we need check for entirely zero output?
04650 
04651 void UpperTriangularMatrix::Solver(MatrixColX& mcout,
04652    const MatrixColX& mcin)
04653 {
04654    REPORT
04655    int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
04656    while (i-- > 0) *elx++ = 0.0;
04657    int nr = mcin.skip+mcin.storage;
04658    elx = mcin.data+mcin.storage; Real* el = elx;
04659    int j = mcout.skip+mcout.storage-nr;
04660    int nc = ncols_val-nr; i = nr-mcout.skip;
04661    while (j-- > 0) *elx++ = 0.0;
04662    Real* Ael = store + (nr*(2*ncols_val-nr+1))/2; j = 0;
04663    while (i-- > 0)
04664    {
04665       elx = el; Real sum = 0.0; int jx = j++; Ael -= nc;
04666       while (jx--) sum += *(--Ael) * *(--elx);
04667       elx--; *elx = (*elx - sum) / *(--Ael);
04668    }
04669 }
04670 
04671 void LowerTriangularMatrix::Solver(MatrixColX& mcout,
04672    const MatrixColX& mcin)
04673 {
04674    REPORT
04675    int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
04676    while (i-- > 0) *elx++ = 0.0;
04677    int nc = mcin.skip; i = nc+mcin.storage; elx = mcin.data+mcin.storage;
04678    int nr = mcout.skip+mcout.storage; int j = nr-i; i = nr-nc;
04679    while (j-- > 0) *elx++ = 0.0;
04680    Real* el = mcin.data; Real* Ael = store + (nc*(nc+1))/2; j = 0;
04681    while (i-- > 0)
04682    {
04683       elx = el; Real sum = 0.0; int jx = j++; Ael += nc;
04684       while (jx--) sum += *Ael++ * *elx++;
04685       *elx = (*elx - sum) / *Ael++;
04686    }
04687 }
04688 
04689 //******************* carry out binary operations *************************/
04690 
04691 static GeneralMatrix*
04692    GeneralMult(GeneralMatrix*,GeneralMatrix*,MultipliedMatrix*,MatrixType);
04693 static GeneralMatrix*
04694    GeneralSolv(GeneralMatrix*,GeneralMatrix*,BaseMatrix*,MatrixType);
04695 static GeneralMatrix*
04696    GeneralSolvI(GeneralMatrix*,BaseMatrix*,MatrixType);
04697 static GeneralMatrix*
04698    GeneralKP(GeneralMatrix*,GeneralMatrix*,KPMatrix*,MatrixType);
04699 
04700 GeneralMatrix* MultipliedMatrix::Evaluate(MatrixType mt)
04701 {
04702    REPORT
04703    gm2 = ((BaseMatrix*&)bm2)->Evaluate();
04704    gm2 = gm2->Evaluate(gm2->type().MultRHS());     // no symmetric on RHS
04705    gm1 = ((BaseMatrix*&)bm1)->Evaluate();
04706    return GeneralMult(gm1, gm2, this, mt);
04707 }
04708 
04709 GeneralMatrix* SolvedMatrix::Evaluate(MatrixType mt)
04710 {
04711    REPORT
04712    gm1 = ((BaseMatrix*&)bm1)->Evaluate();
04713    gm2 = ((BaseMatrix*&)bm2)->Evaluate();
04714    return GeneralSolv(gm1,gm2,this,mt);
04715 }
04716 
04717 GeneralMatrix* KPMatrix::Evaluate(MatrixType mt)
04718 {
04719    REPORT
04720    gm1 = ((BaseMatrix*&)bm1)->Evaluate();
04721    gm2 = ((BaseMatrix*&)bm2)->Evaluate();
04722    return GeneralKP(gm1,gm2,this,mt);
04723 }
04724 
04725 // routines for adding or subtracting matrices of identical storage structure
04726 
04727 static void Add(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
04728 {
04729    REPORT
04730    Real* s1=gm1->Store(); Real* s2=gm2->Store();
04731    Real* s=gm->Store(); int i=gm->Storage() >> 2;
04732    while (i--)
04733    {
04734        *s++ = *s1++ + *s2++; *s++ = *s1++ + *s2++;
04735        *s++ = *s1++ + *s2++; *s++ = *s1++ + *s2++;
04736    }
04737    i=gm->Storage() & 3; while (i--) *s++ = *s1++ + *s2++;
04738 }
04739 
04740 static void AddTo(GeneralMatrix* gm, const GeneralMatrix* gm2)
04741 {
04742    REPORT
04743    const Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
04744    while (i--)
04745    { *s++ += *s2++; *s++ += *s2++; *s++ += *s2++; *s++ += *s2++; }
04746    i=gm->Storage() & 3; while (i--) *s++ += *s2++;
04747 }
04748 
04749 void GeneralMatrix::PlusEqual(const GeneralMatrix& gm)
04750 {
04751    REPORT
04752    if (nrows_val != gm.nrows_val || ncols_val != gm.ncols_val)
04753       Throw(IncompatibleDimensionsException(*this, gm));
04754    AddTo(this, &gm);
04755 }
04756 
04757 static void Subtract(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
04758 {
04759    REPORT
04760    Real* s1=gm1->Store(); Real* s2=gm2->Store();
04761    Real* s=gm->Store(); int i=gm->Storage() >> 2;
04762    while (i--)
04763    {
04764        *s++ = *s1++ - *s2++; *s++ = *s1++ - *s2++;
04765        *s++ = *s1++ - *s2++; *s++ = *s1++ - *s2++;
04766    }
04767    i=gm->Storage() & 3; while (i--) *s++ = *s1++ - *s2++;
04768 }
04769 
04770 static void SubtractFrom(GeneralMatrix* gm, const GeneralMatrix* gm2)
04771 {
04772    REPORT
04773    const Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
04774    while (i--)
04775    { *s++ -= *s2++; *s++ -= *s2++; *s++ -= *s2++; *s++ -= *s2++; }
04776    i=gm->Storage() & 3; while (i--) *s++ -= *s2++;
04777 }
04778 
04779 void GeneralMatrix::MinusEqual(const GeneralMatrix& gm)
04780 {
04781    REPORT
04782    if (nrows_val != gm.nrows_val || ncols_val != gm.ncols_val)
04783       Throw(IncompatibleDimensionsException(*this, gm));
04784    SubtractFrom(this, &gm);
04785 }
04786 
04787 static void ReverseSubtract(GeneralMatrix* gm, const GeneralMatrix* gm2)
04788 {
04789    REPORT
04790    const Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
04791    while (i--)
04792    {
04793       *s = *s2++ - *s; s++; *s = *s2++ - *s; s++;
04794       *s = *s2++ - *s; s++; *s = *s2++ - *s; s++;
04795    }
04796    i=gm->Storage() & 3; while (i--) { *s = *s2++ - *s; s++; }
04797 }
04798 
04799 static void SP(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
04800 {
04801    REPORT
04802    Real* s1=gm1->Store(); Real* s2=gm2->Store();
04803    Real* s=gm->Store(); int i=gm->Storage() >> 2;
04804    while (i--)
04805    {
04806        *s++ = *s1++ * *s2++; *s++ = *s1++ * *s2++;
04807        *s++ = *s1++ * *s2++; *s++ = *s1++ * *s2++;
04808    }
04809    i=gm->Storage() & 3; while (i--) *s++ = *s1++ * *s2++;
04810 }
04811 
04812 static void SP(GeneralMatrix* gm, GeneralMatrix* gm2)
04813 {
04814    REPORT
04815    Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
04816    while (i--)
04817    { *s++ *= *s2++; *s++ *= *s2++; *s++ *= *s2++; *s++ *= *s2++; }
04818    i=gm->Storage() & 3; while (i--) *s++ *= *s2++;
04819 }
04820 
04821 // routines for adding or subtracting matrices of different storage structure
04822 
04823 static void AddDS(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
04824 {
04825    REPORT
04826    int nr = gm->Nrows();
04827    MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
04828    MatrixRow mr(gm, StoreOnExit+DirectPart);
04829    while (nr--) { mr.Add(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
04830 }
04831 
04832 static void AddDS(GeneralMatrix* gm, GeneralMatrix* gm2)
04833 // Add into first argument
04834 {
04835    REPORT
04836    int nr = gm->Nrows();
04837    MatrixRow mr(gm, StoreOnExit+LoadOnEntry+DirectPart);
04838    MatrixRow mr2(gm2, LoadOnEntry);
04839    while (nr--) { mr.Add(mr2); mr.Next(); mr2.Next(); }
04840 }
04841 
04842 static void SubtractDS
04843    (GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
04844 {
04845    REPORT
04846    int nr = gm->Nrows();
04847    MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
04848    MatrixRow mr(gm, StoreOnExit+DirectPart);
04849    while (nr--) { mr.Sub(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
04850 }
04851 
04852 static void SubtractDS(GeneralMatrix* gm, GeneralMatrix* gm2)
04853 {
04854    REPORT
04855    int nr = gm->Nrows();
04856    MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart);
04857    MatrixRow mr2(gm2, LoadOnEntry);
04858    while (nr--) { mr.Sub(mr2); mr.Next(); mr2.Next(); }
04859 }
04860 
04861 static void ReverseSubtractDS(GeneralMatrix* gm, GeneralMatrix* gm2)
04862 {
04863    REPORT
04864    int nr = gm->Nrows();
04865    MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart);
04866    MatrixRow mr2(gm2, LoadOnEntry);
04867    while (nr--) { mr.RevSub(mr2); mr2.Next(); mr.Next(); }
04868 }
04869 
04870 static void SPDS(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
04871 {
04872    REPORT
04873    int nr = gm->Nrows();
04874    MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
04875    MatrixRow mr(gm, StoreOnExit+DirectPart);
04876    while (nr--) { mr.Multiply(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
04877 }
04878 
04879 static void SPDS(GeneralMatrix* gm, GeneralMatrix* gm2)
04880 // SP into first argument
04881 {
04882    REPORT
04883    int nr = gm->Nrows();
04884    MatrixRow mr(gm, StoreOnExit+LoadOnEntry+DirectPart);
04885    MatrixRow mr2(gm2, LoadOnEntry);
04886    while (nr--) { mr.Multiply(mr2); mr.Next(); mr2.Next(); }
04887 }
04888 
04889 static GeneralMatrix* GeneralMult1(GeneralMatrix* gm1, GeneralMatrix* gm2,
04890    MultipliedMatrix* mm, MatrixType mtx)
04891 {
04892    REPORT
04893    Tracer tr("GeneralMult1");
04894    int nr=gm1->Nrows(); int nc=gm2->Ncols();
04895    if (gm1->Ncols() !=gm2->Nrows())
04896       Throw(IncompatibleDimensionsException(*gm1, *gm2));
04897    GeneralMatrix* gmx = mtx.New(nr,nc,mm);
04898 
04899    MatrixCol mcx(gmx, StoreOnExit+DirectPart);
04900    MatrixCol mc2(gm2, LoadOnEntry);
04901    while (nc--)
04902    {
04903       MatrixRow mr1(gm1, LoadOnEntry, mcx.Skip());
04904       Real* el = mcx.Data();                         // pointer to an element
04905       int n = mcx.Storage();
04906       while (n--) { *(el++) = DotProd(mr1,mc2); mr1.Next(); }
04907       mc2.Next(); mcx.Next();
04908    }
04909    gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
04910 }
04911 
04912 static GeneralMatrix* GeneralMult2(GeneralMatrix* gm1, GeneralMatrix* gm2,
04913    MultipliedMatrix* mm, MatrixType mtx)
04914 {
04915    // version that accesses by row only - not good for thin matrices
04916    // or column vectors in right hand term.
04917    REPORT
04918    Tracer tr("GeneralMult2");
04919    int nr=gm1->Nrows(); int nc=gm2->Ncols();
04920    if (gm1->Ncols() !=gm2->Nrows())
04921       Throw(IncompatibleDimensionsException(*gm1, *gm2));
04922    GeneralMatrix* gmx = mtx.New(nr,nc,mm);
04923 
04924    MatrixRow mrx(gmx, LoadOnEntry+StoreOnExit+DirectPart);
04925    MatrixRow mr1(gm1, LoadOnEntry);
04926    while (nr--)
04927    {
04928       MatrixRow mr2(gm2, LoadOnEntry, mr1.Skip());
04929       Real* el = mr1.Data();                         // pointer to an element
04930       int n = mr1.Storage();
04931       mrx.Zero();
04932       while (n--) { mrx.AddScaled(mr2, *el++); mr2.Next(); }
04933       mr1.Next(); mrx.Next();
04934    }
04935    gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
04936 }
04937 
04938 static GeneralMatrix* mmMult(GeneralMatrix* gm1, GeneralMatrix* gm2)
04939 {
04940    // matrix multiplication for type Matrix only
04941    REPORT
04942    Tracer tr("MatrixMult");
04943 
04944    int nr=gm1->Nrows(); int ncr=gm1->Ncols(); int nc=gm2->Ncols();
04945    if (ncr != gm2->Nrows()) Throw(IncompatibleDimensionsException(*gm1,*gm2));
04946 
04947    Matrix* gm = new Matrix(nr,nc); MatrixErrorNoSpace(gm);
04948 
04949    Real* s1=gm1->Store(); Real* s2=gm2->Store(); Real* s=gm->Store();
04950 
04951    if (ncr)
04952    {
04953       while (nr--)
04954       {
04955          Real* s2x = s2; int j = ncr;
04956          Real* sx = s; Real f = *s1++; int k = nc;
04957          while (k--) *sx++ = f * *s2x++;
04958          while (--j)
04959             { sx = s; f = *s1++; k = nc; while (k--) *sx++ += f * *s2x++; }
04960          s = sx;
04961       }
04962    }
04963    else *gm = 0.0;
04964 
04965    gm->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gm;
04966 }
04967 
04968 static GeneralMatrix* GeneralMult(GeneralMatrix* gm1, GeneralMatrix* gm2,
04969    MultipliedMatrix* mm, MatrixType mtx)
04970 {
04971    if ( Rectangular(gm1->type(), gm2->type(), mtx))
04972       { REPORT return mmMult(gm1, gm2); }
04973    Compare(gm1->type() * gm2->type(),mtx);
04974    int nr = gm2->Nrows(); int nc = gm2->Ncols();
04975    if (nc <= 5 && nr > nc) { REPORT return GeneralMult1(gm1, gm2, mm, mtx); }
04976    REPORT return GeneralMult2(gm1, gm2, mm, mtx);
04977 }
04978 
04979 static GeneralMatrix* GeneralKP(GeneralMatrix* gm1, GeneralMatrix* gm2,
04980    KPMatrix* kp, MatrixType mtx)
04981 {
04982    REPORT
04983    Tracer tr("GeneralKP");
04984    int nr1 = gm1->Nrows(); int nc1 = gm1->Ncols();
04985    int nr2 = gm2->Nrows(); int nc2 = gm2->Ncols();
04986    Compare((gm1->type()).KP(gm2->type()),mtx);
04987    GeneralMatrix* gmx = mtx.New(nr1*nr2, nc1*nc2, kp);
04988    MatrixRow mrx(gmx, LoadOnEntry+StoreOnExit+DirectPart);
04989    MatrixRow mr1(gm1, LoadOnEntry);
04990    for (int i = 1; i <= nr1; ++i)
04991    {
04992       MatrixRow mr2(gm2, LoadOnEntry);
04993       for (int j = 1; j <= nr2; ++j)
04994          { mrx.KP(mr1,mr2); mr2.Next(); mrx.Next(); }
04995       mr1.Next();
04996    }
04997    gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
04998 }
04999 
05000 static GeneralMatrix* GeneralSolv(GeneralMatrix* gm1, GeneralMatrix* gm2,
05001    BaseMatrix* sm, MatrixType mtx)
05002 {
05003    REPORT
05004    Tracer tr("GeneralSolv");
05005    Compare(gm1->type().i() * gm2->type(),mtx);
05006    int nr = gm1->Nrows();
05007    if (nr != gm1->Ncols()) Throw(NotSquareException(*gm1));
05008    int nc = gm2->Ncols();
05009    if (gm1->Ncols() != gm2->Nrows())
05010       Throw(IncompatibleDimensionsException(*gm1, *gm2));
05011    GeneralMatrix* gmx = mtx.New(nr,nc,sm); MatrixErrorNoSpace(gmx);
05012    Real* r = new Real [nr]; MatrixErrorNoSpace(r);
05013    MONITOR_REAL_NEW("Make   (GenSolv)",nr,r)
05014    GeneralMatrix* gms = gm1->MakeSolver();
05015    Try
05016    {
05017 
05018       MatrixColX mcx(gmx, r, StoreOnExit+DirectPart);   // copy to and from r
05019          // this must be inside Try so mcx is destroyed before gmx
05020       MatrixColX mc2(gm2, r, LoadOnEntry);
05021       while (nc--) { gms->Solver(mcx, mc2); mcx.Next(); mc2.Next(); }
05022    }
05023    CatchAll
05024    {
05025       if (gms) gms->tDelete();
05026       delete gmx;                   // <--------------------
05027       gm2->tDelete();
05028       MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r)
05029                           // AT&T version 2.1 gives an internal error
05030       delete [] r;
05031       ReThrow;
05032    }
05033    gms->tDelete(); gmx->ReleaseAndDelete(); gm2->tDelete();
05034    MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r)
05035                           // AT&T version 2.1 gives an internal error
05036    delete [] r;
05037    return gmx;
05038 }
05039 
05040 // version for inverses - gm2 is identity
05041 static GeneralMatrix* GeneralSolvI(GeneralMatrix* gm1, BaseMatrix* sm,
05042    MatrixType mtx)
05043 {
05044    REPORT
05045    Tracer tr("GeneralSolvI");
05046    Compare(gm1->type().i(),mtx);
05047    int nr = gm1->Nrows();
05048    if (nr != gm1->Ncols()) Throw(NotSquareException(*gm1));
05049    int nc = nr;
05050    // DiagonalMatrix I(nr); I = 1;
05051    IdentityMatrix I(nr);
05052    GeneralMatrix* gmx = mtx.New(nr,nc,sm); MatrixErrorNoSpace(gmx);
05053    Real* r = new Real [nr]; MatrixErrorNoSpace(r);
05054    MONITOR_REAL_NEW("Make   (GenSolvI)",nr,r)
05055    GeneralMatrix* gms = gm1->MakeSolver();
05056    Try
05057    {
05058 
05059       MatrixColX mcx(gmx, r, StoreOnExit+DirectPart);   // copy to and from r
05060          // this must be inside Try so mcx is destroyed before gmx
05061       MatrixColX mc2(&I, r, LoadOnEntry);
05062       while (nc--) { gms->Solver(mcx, mc2); mcx.Next(); mc2.Next(); }
05063    }
05064    CatchAll
05065    {
05066       if (gms) gms->tDelete();
05067       delete gmx;
05068       MONITOR_REAL_DELETE("Delete (GenSolvI)",nr,r)
05069                           // AT&T version 2.1 gives an internal error
05070       delete [] r;
05071       ReThrow;
05072    }
05073    gms->tDelete(); gmx->ReleaseAndDelete();
05074    MONITOR_REAL_DELETE("Delete (GenSolvI)",nr,r)
05075                           // AT&T version 2.1 gives an internal error
05076    delete [] r;
05077    return gmx;
05078 }
05079 
05080 GeneralMatrix* InvertedMatrix::Evaluate(MatrixType mtx)
05081 {
05082    // Matrix Inversion - use solve routines
05083    Tracer tr("InvertedMatrix::Evaluate");
05084    REPORT
05085    gm=((BaseMatrix*&)bm)->Evaluate();
05086    return GeneralSolvI(gm,this,mtx);
05087 }
05088 
05089 //*************************** New versions ************************
05090 
05091 GeneralMatrix* AddedMatrix::Evaluate(MatrixType mtd)
05092 {
05093    REPORT
05094    Tracer tr("AddedMatrix::Evaluate");
05095    gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate();
05096    int nr=gm1->Nrows(); int nc=gm1->Ncols();
05097    if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
05098    {
05099       Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); }
05100       CatchAll
05101       {
05102          gm1->tDelete(); gm2->tDelete();
05103          ReThrow;
05104       }
05105    }
05106    MatrixType mt1 = gm1->type(), mt2 = gm2->type(); MatrixType mts = mt1 + mt2;
05107    if (!mtd) { REPORT mtd = mts; }
05108    else if (!(mtd.DataLossOK || mtd >= mts))
05109    {
05110       REPORT
05111       gm1->tDelete(); gm2->tDelete();
05112       Throw(ProgramException("Illegal Conversion", mts, mtd));
05113    }
05114    GeneralMatrix* gmx;
05115    bool c1 = (mtd == mt1), c2 = (mtd == mt2);
05116    if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) )
05117    {
05118       if (gm1->reuse()) { REPORT AddTo(gm1,gm2); gm2->tDelete(); gmx = gm1; }
05119       else if (gm2->reuse()) { REPORT AddTo(gm2,gm1); gmx = gm2; }
05120       else
05121       {
05122          REPORT
05123          // what if new throws an exception
05124          Try { gmx = mt1.New(nr,nc,this); }
05125          CatchAll
05126          {
05127             ReThrow;
05128          }
05129          gmx->ReleaseAndDelete(); Add(gmx,gm1,gm2);
05130       }
05131    }
05132    else
05133    {
05134       if (c1 && c2)
05135       {
05136          short SAO = gm1->SimpleAddOK(gm2);
05137          if (SAO & 1) { REPORT c1 = false; }
05138          if (SAO & 2) { REPORT c2 = false; }
05139       }
05140       if (c1 && gm1->reuse() )               // must have type test first
05141          { REPORT AddDS(gm1,gm2); gm2->tDelete(); gmx = gm1; }
05142       else if (c2 && gm2->reuse() )
05143          { REPORT AddDS(gm2,gm1); if (!c1) gm1->tDelete(); gmx = gm2; }
05144       else
05145       {
05146          REPORT
05147          Try { gmx = mtd.New(nr,nc,this); }
05148          CatchAll
05149          {
05150             if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
05151             ReThrow;
05152          }
05153          AddDS(gmx,gm1,gm2);
05154          if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
05155          gmx->ReleaseAndDelete();
05156       }
05157    }
05158    return gmx;
05159 }
05160 
05161 GeneralMatrix* SubtractedMatrix::Evaluate(MatrixType mtd)
05162 {
05163    REPORT
05164    Tracer tr("SubtractedMatrix::Evaluate");
05165    gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate();
05166    int nr=gm1->Nrows(); int nc=gm1->Ncols();
05167    if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
05168    {
05169       Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); }
05170       CatchAll
05171       {
05172          gm1->tDelete(); gm2->tDelete();
05173          ReThrow;
05174       }
05175    }
05176    MatrixType mt1 = gm1->type(), mt2 = gm2->type(); MatrixType mts = mt1 + mt2;
05177    if (!mtd) { REPORT mtd = mts; }
05178    else if (!(mtd.DataLossOK || mtd >= mts))
05179    {
05180       gm1->tDelete(); gm2->tDelete();
05181       Throw(ProgramException("Illegal Conversion", mts, mtd));
05182    }
05183    GeneralMatrix* gmx;
05184    bool c1 = (mtd == mt1), c2 = (mtd == mt2);
05185    if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) )
05186    {
05187       if (gm1->reuse())
05188          { REPORT SubtractFrom(gm1,gm2); gm2->tDelete(); gmx = gm1; }
05189       else if (gm2->reuse()) { REPORT ReverseSubtract(gm2,gm1); gmx = gm2; }
05190       else
05191       {
05192          REPORT
05193          Try { gmx = mt1.New(nr,nc,this); }
05194          CatchAll
05195          {
05196             ReThrow;
05197          }
05198          gmx->ReleaseAndDelete(); Subtract(gmx,gm1,gm2);
05199       }
05200    }
05201    else
05202    {
05203       if (c1 && c2)
05204       {
05205          short SAO = gm1->SimpleAddOK(gm2);
05206          if (SAO & 1) { REPORT c1 = false; }
05207          if (SAO & 2) { REPORT c2 = false; }
05208       }
05209       if (c1 && gm1->reuse() )               // must have type test first
05210          { REPORT SubtractDS(gm1,gm2); gm2->tDelete(); gmx = gm1; }
05211       else if (c2 && gm2->reuse() )
05212       {
05213          REPORT ReverseSubtractDS(gm2,gm1);
05214          if (!c1) gm1->tDelete(); gmx = gm2;
05215       }
05216       else
05217       {
05218          REPORT
05219          // what if New throws and exception
05220          Try { gmx = mtd.New(nr,nc,this); }
05221          CatchAll
05222          {
05223             if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
05224             ReThrow;
05225          }
05226          SubtractDS(gmx,gm1,gm2);
05227          if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
05228          gmx->ReleaseAndDelete();
05229       }
05230    }
05231    return gmx;
05232 }
05233 
05234 GeneralMatrix* SPMatrix::Evaluate(MatrixType mtd)
05235 {
05236    REPORT
05237    Tracer tr("SPMatrix::Evaluate");
05238    gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate();
05239    int nr=gm1->Nrows(); int nc=gm1->Ncols();
05240    if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
05241    {
05242       Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); }
05243       CatchAll
05244       {
05245          gm1->tDelete(); gm2->tDelete();
05246          ReThrow;
05247       }
05248    }
05249    MatrixType mt1 = gm1->type(), mt2 = gm2->type();
05250    MatrixType mts = mt1.SP(mt2);
05251    if (!mtd) { REPORT mtd = mts; }
05252    else if (!(mtd.DataLossOK || mtd >= mts))
05253    {
05254       gm1->tDelete(); gm2->tDelete();
05255       Throw(ProgramException("Illegal Conversion", mts, mtd));
05256    }
05257    GeneralMatrix* gmx;
05258    bool c1 = (mtd == mt1), c2 = (mtd == mt2);
05259    if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) )
05260    {
05261       if (gm1->reuse()) { REPORT SP(gm1,gm2); gm2->tDelete(); gmx = gm1; }
05262       else if (gm2->reuse()) { REPORT SP(gm2,gm1); gmx = gm2; }
05263       else
05264       {
05265          REPORT
05266          Try { gmx = mt1.New(nr,nc,this); }
05267          CatchAll
05268          {
05269             ReThrow;
05270          }
05271          gmx->ReleaseAndDelete(); SP(gmx,gm1,gm2);
05272       }
05273    }
05274    else
05275    {
05276       if (c1 && c2)
05277       {
05278          short SAO = gm1->SimpleAddOK(gm2);
05279          if (SAO & 1) { REPORT c2 = false; }    // c1 and c2 swapped
05280          if (SAO & 2) { REPORT c1 = false; }
05281       }
05282       if (c1 && gm1->reuse() )               // must have type test first
05283          { REPORT SPDS(gm1,gm2); gm2->tDelete(); gmx = gm1; }
05284       else if (c2 && gm2->reuse() )
05285          { REPORT SPDS(gm2,gm1); if (!c1) gm1->tDelete(); gmx = gm2; }
05286       else
05287       {
05288          REPORT
05289          // what if New throws and exception
05290          Try { gmx = mtd.New(nr,nc,this); }
05291          CatchAll
05292          {
05293             if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
05294             ReThrow;
05295          }
05296          SPDS(gmx,gm1,gm2);
05297          if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
05298          gmx->ReleaseAndDelete();
05299       }
05300    }
05301    return gmx;
05302 }
05303 
05304 
05305 
05306 //*************************** norm functions ****************************/
05307 
05308 Real BaseMatrix::norm1() const
05309 {
05310    // maximum of sum of absolute values of a column
05311    REPORT
05312    GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
05313    int nc = gm->Ncols(); Real value = 0.0;
05314    MatrixCol mc(gm, LoadOnEntry);
05315    while (nc--)
05316       { Real v = mc.SumAbsoluteValue(); if (value < v) value = v; mc.Next(); }
05317    gm->tDelete(); return value;
05318 }
05319 
05320 Real BaseMatrix::norm_infinity() const
05321 {
05322    // maximum of sum of absolute values of a row
05323    REPORT
05324    GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
05325    int nr = gm->Nrows(); Real value = 0.0;
05326    MatrixRow mr(gm, LoadOnEntry);
05327    while (nr--)
05328       { Real v = mr.SumAbsoluteValue(); if (value < v) value = v; mr.Next(); }
05329    gm->tDelete(); return value;
05330 }
05331 
05332 //********************** Concatenation and stacking *************************/
05333 
05334 GeneralMatrix* ConcatenatedMatrix::Evaluate(MatrixType mtx)
05335 {
05336    REPORT
05337    Tracer tr("Concatenate");
05338       gm2 = ((BaseMatrix*&)bm2)->Evaluate();
05339       gm1 = ((BaseMatrix*&)bm1)->Evaluate();
05340       Compare(gm1->type() | gm2->type(),mtx);
05341       int nr=gm1->Nrows(); int nc = gm1->Ncols() + gm2->Ncols();
05342       if (nr != gm2->Nrows())
05343          Throw(IncompatibleDimensionsException(*gm1, *gm2));
05344       GeneralMatrix* gmx = mtx.New(nr,nc,this);
05345       MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
05346       MatrixRow mr(gmx, StoreOnExit+DirectPart);
05347       while (nr--) { mr.ConCat(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
05348       gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
05349 }
05350 
05351 GeneralMatrix* StackedMatrix::Evaluate(MatrixType mtx)
05352 {
05353    REPORT
05354    Tracer tr("Stack");
05355       gm2 = ((BaseMatrix*&)bm2)->Evaluate();
05356       gm1 = ((BaseMatrix*&)bm1)->Evaluate();
05357       Compare(gm1->type() & gm2->type(),mtx);
05358       int nc=gm1->Ncols();
05359       int nr1 = gm1->Nrows(); int nr2 = gm2->Nrows();
05360       if (nc != gm2->Ncols())
05361          Throw(IncompatibleDimensionsException(*gm1, *gm2));
05362       GeneralMatrix* gmx = mtx.New(nr1+nr2,nc,this);
05363       MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
05364       MatrixRow mr(gmx, StoreOnExit+DirectPart);
05365       while (nr1--) { mr.Copy(mr1); mr1.Next(); mr.Next(); }
05366       while (nr2--) { mr.Copy(mr2); mr2.Next(); mr.Next(); }
05367       gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
05368 }
05369 
05370 // ************************* equality of matrices ******************** //
05371 
05372 static bool RealEqual(Real* s1, Real* s2, int n)
05373 {
05374    int i = n >> 2;
05375    while (i--)
05376    {
05377       if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
05378       if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
05379    }
05380    i = n & 3; while (i--) if (*s1++ != *s2++) return false;
05381    return true;
05382 }
05383 
05384 static bool intEqual(int* s1, int* s2, int n)
05385 {
05386    int i = n >> 2;
05387    while (i--)
05388    {
05389       if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
05390       if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
05391    }
05392    i = n & 3; while (i--) if (*s1++ != *s2++) return false;
05393    return true;
05394 }
05395 
05396 
05397 bool operator==(const BaseMatrix& A, const BaseMatrix& B)
05398 {
05399    Tracer tr("BaseMatrix ==");
05400    REPORT
05401    GeneralMatrix* gmA = ((BaseMatrix&)A).Evaluate();
05402    GeneralMatrix* gmB = ((BaseMatrix&)B).Evaluate();
05403 
05404    if (gmA == gmB)                            // same matrix
05405       { REPORT gmA->tDelete(); return true; }
05406 
05407    if ( gmA->Nrows() != gmB->Nrows() || gmA->Ncols() != gmB->Ncols() )
05408                                               // different dimensions
05409       { REPORT gmA->tDelete(); gmB->tDelete(); return false; }
05410 
05411    // check for CroutMatrix or BandLUMatrix
05412    MatrixType AType = gmA->type(); MatrixType BType = gmB->type();
05413    if (AType.CannotConvert() || BType.CannotConvert() )
05414    {
05415       REPORT
05416       bool bx = gmA->IsEqual(*gmB);
05417       gmA->tDelete(); gmB->tDelete();
05418       return bx;
05419    }
05420 
05421    // is matrix storage the same
05422    // will need to modify if further matrix structures are introduced
05423    if (AType == BType && gmA->bandwidth() == gmB->bandwidth())
05424    {                                          // compare store
05425       REPORT
05426       bool bx = RealEqual(gmA->Store(),gmB->Store(),gmA->Storage());
05427       gmA->tDelete(); gmB->tDelete();
05428       return bx;
05429    }
05430 
05431    // matrix storage different - just subtract
05432    REPORT  return is_zero(*gmA-*gmB);
05433 }
05434 
05435 bool operator==(const GeneralMatrix& A, const GeneralMatrix& B)
05436 {
05437    Tracer tr("GeneralMatrix ==");
05438    // May or may not call tDeletes
05439    REPORT
05440 
05441    if (&A == &B)                              // same matrix
05442       { REPORT return true; }
05443 
05444    if ( A.Nrows() != B.Nrows() || A.Ncols() != B.Ncols() )
05445       { REPORT return false; }                // different dimensions
05446 
05447    // check for CroutMatrix or BandLUMatrix
05448    MatrixType AType = A.Type(); MatrixType BType = B.Type();
05449    if (AType.CannotConvert() || BType.CannotConvert() )
05450       { REPORT  return A.IsEqual(B); }
05451 
05452    // is matrix storage the same
05453    // will need to modify if further matrix structures are introduced
05454    if (AType == BType && A.bandwidth() == B.bandwidth())
05455       { REPORT return RealEqual(A.Store(),B.Store(),A.Storage()); }
05456 
05457    // matrix storage different - just subtract
05458    REPORT  return is_zero(A-B);
05459 }
05460 
05461 bool GeneralMatrix::is_zero() const
05462 {
05463    REPORT
05464    Real* s=store; int i = storage >> 2;
05465    while (i--)
05466    {
05467       if (*s++) return false; if (*s++) return false;
05468       if (*s++) return false; if (*s++) return false;
05469    }
05470    i = storage & 3; while (i--) if (*s++) return false;
05471    return true;
05472 }
05473 
05474 bool is_zero(const BaseMatrix& A)
05475 {
05476    Tracer tr("BaseMatrix::is_zero");
05477    REPORT
05478    GeneralMatrix* gm1 = 0; bool bx;
05479    Try { gm1=((BaseMatrix&)A).Evaluate(); bx = gm1->is_zero(); }
05480    CatchAll { if (gm1) gm1->tDelete(); ReThrow; }
05481    gm1->tDelete();
05482    return bx;
05483 }
05484 
05485 // IsEqual functions - insist matrices are of same type
05486 // as well as equal values to be equal
05487 
05488 bool GeneralMatrix::IsEqual(const GeneralMatrix& A) const
05489 {
05490    Tracer tr("GeneralMatrix IsEqual");
05491    if (A.type() != type())                       // not same types
05492       { REPORT return false; }
05493    if (&A == this)                               // same matrix
05494       { REPORT  return true; }
05495    if (A.nrows_val != nrows_val || A.ncols_val != ncols_val)
05496                                                  // different dimensions
05497    { REPORT return false; }
05498    // is matrix storage the same - compare store
05499    REPORT
05500    return RealEqual(A.store,store,storage);
05501 }
05502 
05503 bool CroutMatrix::IsEqual(const GeneralMatrix& A) const
05504 {
05505    Tracer tr("CroutMatrix IsEqual");
05506    if (A.type() != type())                       // not same types
05507       { REPORT return false; }
05508    if (&A == this)                               // same matrix
05509       { REPORT  return true; }
05510    if (A.nrows_val != nrows_val || A.ncols_val != ncols_val)
05511                                                  // different dimensions
05512    { REPORT return false; }
05513    // is matrix storage the same - compare store
05514    REPORT
05515    return RealEqual(A.store,store,storage)
05516       && intEqual(((CroutMatrix&)A).indx, indx, nrows_val);
05517 }
05518 
05519 
05520 bool BandLUMatrix::IsEqual(const GeneralMatrix& A) const
05521 {
05522    Tracer tr("BandLUMatrix IsEqual");
05523    if (A.type() != type())                       // not same types
05524       { REPORT  return false; }
05525    if (&A == this)                               // same matrix
05526       { REPORT  return true; }
05527    if ( A.Nrows() != nrows_val || A.Ncols() != ncols_val
05528       || ((BandLUMatrix&)A).m1 != m1 || ((BandLUMatrix&)A).m2 != m2 )
05529                                                  // different dimensions
05530    { REPORT  return false; }
05531 
05532    // matrix storage the same - compare store
05533    REPORT
05534    return RealEqual(A.Store(),store,storage)
05535       && RealEqual(((BandLUMatrix&)A).store2,store2,storage2)
05536       && intEqual(((BandLUMatrix&)A).indx, indx, nrows_val);
05537 }
05538 
05539 
05540 // ************************* cross products ******************** //
05541 
05542 inline void crossproduct_body(Real* a, Real* b, Real* c)
05543 {
05544    c[0] = a[1] * b[2] - a[2] * b[1];
05545    c[1] = a[2] * b[0] - a[0] * b[2];
05546    c[2] = a[0] * b[1] - a[1] * b[0];
05547 }
05548 
05549 Matrix crossproduct(const Matrix& A, const Matrix& B)
05550 {
05551    REPORT
05552    int ac = A.Ncols(); int ar = A.Nrows();
05553    int bc = B.Ncols(); int br = B.Nrows();
05554    Real* a = A.Store(); Real* b = B.Store();
05555    if (ac == 3)
05556    {
05557       if (bc != 3 || ar != 1 || br != 1)
05558          { Tracer et("crossproduct"); IncompatibleDimensionsException(A, B); }
05559       REPORT
05560       RowVector C(3);  Real* c = C.Store(); crossproduct_body(a, b, c);
05561       return (Matrix&)C;
05562    }
05563    else
05564    {
05565       if (ac != 1 || bc != 1 || ar != 3 || br != 3)
05566          { Tracer et("crossproduct"); IncompatibleDimensionsException(A, B); }
05567       REPORT
05568       ColumnVector C(3);  Real* c = C.Store(); crossproduct_body(a, b, c);
05569       return (Matrix&)C;
05570    }
05571 }
05572 
05573 ReturnMatrix crossproduct_rows(const Matrix& A, const Matrix& B)
05574 {
05575    REPORT
05576    int n = A.Nrows();
05577    if (A.Ncols() != 3 || B.Ncols() != 3 || n != B.Nrows())
05578    {
05579       Tracer et("crossproduct_rows"); IncompatibleDimensionsException(A, B);
05580    }
05581    Matrix C(n, 3);
05582    Real* a = A.Store(); Real* b = B.Store(); Real* c = C.Store();
05583    if (n--)
05584    {
05585       for (;;)
05586       {
05587          crossproduct_body(a, b, c);
05588          if (!(n--)) break;
05589          a += 3; b += 3; c += 3;
05590       }
05591    }
05592 
05593    return C.ForReturn();
05594 }
05595 
05596 ReturnMatrix crossproduct_columns(const Matrix& A, const Matrix& B)
05597 {
05598    REPORT
05599    int n = A.Ncols();
05600    if (A.Nrows() != 3 || B.Nrows() != 3 || n != B.Ncols())
05601    {
05602       Tracer et("crossproduct_columns");
05603       IncompatibleDimensionsException(A, B);
05604    }
05605    Matrix C(3, n);
05606    Real* a = A.Store(); Real* b = B.Store(); Real* c = C.Store();
05607    Real* an = a+n; Real* an2 = an+n;
05608    Real* bn = b+n; Real* bn2 = bn+n;
05609    Real* cn = c+n; Real* cn2 = cn+n;
05610 
05611    int i = n; 
05612    while (i--)
05613    {
05614       *c++   = *an    * *bn2   - *an2   * *bn;
05615       *cn++  = *an2++ * *b     - *a     * *bn2++;
05616       *cn2++ = *a++   * *bn++  - *an++  * *b++;
05617    }
05618 
05619    return C.ForReturn();
05620 }
05621 
05622 
05623 #ifdef use_namespace
05624 }
05625 #endif
05626 
05628 
05631 
05634 
05635 // Copyright (C) 1991,2,3,4: R B Davies
05636 
05637 //#define WANT_STREAM
05638 
05639 #ifdef use_namespace
05640 namespace NEWMAT {
05641 #endif
05642 
05643 
05644 #ifdef DO_REPORT
05645 #define REPORT { static ExeCounter ExeCount(__LINE__,3); ++ExeCount; }
05646 #else
05647 #define REPORT {}
05648 #endif
05649 
05650 //#define MONITOR(what,storage,store)
05651 //   { cout << what << " " << storage << " at " << (long)store << "\n"; }
05652 
05653 #define MONITOR(what,store,storage) {}
05654 
05655 
05656 // Control bits codes for GetRow, GetCol, RestoreRow, RestoreCol
05657 //
05658 // LoadOnEntry:
05659 //    Load data into MatrixRow or Col dummy array under GetRow or GetCol
05660 // StoreOnExit:
05661 //    Restore data to original matrix under RestoreRow or RestoreCol
05662 // DirectPart:
05663 //    Load or restore only part directly stored; must be set with StoreOnExit
05664 //    Still have decide how to handle this with symmetric
05665 // StoreHere:
05666 //    used in columns only - store data at supplied storage address;
05667 //    used for GetCol, NextCol & RestoreCol. No need to fill out zeros
05668 // HaveStore:
05669 //    dummy array has been assigned (internal use only).
05670 
05671 // For symmetric matrices, treat columns as rows unless StoreHere is set;
05672 // then stick to columns as this will give better performance for doing
05673 // inverses
05674 
05675 // How components are used:
05676 
05677 // Use rows wherever possible in preference to columns
05678 
05679 // Columns without StoreHere are used in in-exact transpose, sum column,
05680 // multiply a column vector, and maybe in future access to column,
05681 // additional multiply functions, add transpose
05682 
05683 // Columns with StoreHere are used in exact transpose (not symmetric matrices
05684 // or vectors, load only)
05685 
05686 // Columns with MatrixColX (Store to full column) are used in inverse and solve
05687 
05688 // Functions required for each matrix class
05689 
05690 // GetRow(MatrixRowCol& mrc)
05691 // GetCol(MatrixRowCol& mrc)
05692 // GetCol(MatrixColX& mrc)
05693 // RestoreRow(MatrixRowCol& mrc)
05694 // RestoreCol(MatrixRowCol& mrc)
05695 // RestoreCol(MatrixColX& mrc)
05696 // NextRow(MatrixRowCol& mrc)
05697 // NextCol(MatrixRowCol& mrc)
05698 // NextCol(MatrixColX& mrc)
05699 
05700 // The Restore routines assume StoreOnExit has already been checked
05701 // Defaults for the Next routines are given below
05702 // Assume cannot have both !DirectPart && StoreHere for MatrixRowCol routines
05703 
05704 
05705 // Default NextRow and NextCol:
05706 // will work as a default but need to override NextRow for efficiency
05707 
05708 void GeneralMatrix::NextRow(MatrixRowCol& mrc)
05709 {
05710    REPORT
05711    if (+(mrc.cw*StoreOnExit)) { REPORT this->RestoreRow(mrc); }
05712    mrc.rowcol++;
05713    if (mrc.rowcol<nrows_val) { REPORT this->GetRow(mrc); }
05714    else { REPORT mrc.cw -= StoreOnExit; }
05715 }
05716 
05717 void GeneralMatrix::NextCol(MatrixRowCol& mrc)
05718 {
05719    REPORT                                                // 423
05720    if (+(mrc.cw*StoreOnExit)) { REPORT this->RestoreCol(mrc); }
05721    mrc.rowcol++;
05722    if (mrc.rowcol<ncols_val) { REPORT this->GetCol(mrc); }
05723    else { REPORT mrc.cw -= StoreOnExit; }
05724 }
05725 
05726 void GeneralMatrix::NextCol(MatrixColX& mrc)
05727 {
05728    REPORT                                                // 423
05729    if (+(mrc.cw*StoreOnExit)) { REPORT this->RestoreCol(mrc); }
05730    mrc.rowcol++;
05731    if (mrc.rowcol<ncols_val) { REPORT this->GetCol(mrc); }
05732    else { REPORT mrc.cw -= StoreOnExit; }
05733 }
05734 
05735 
05736 // routines for matrix
05737 
05738 void Matrix::GetRow(MatrixRowCol& mrc)
05739 {
05740    REPORT
05741    mrc.skip=0; mrc.storage=mrc.length=ncols_val;
05742    mrc.data=store+mrc.rowcol*ncols_val;
05743 }
05744 
05745 
05746 void Matrix::GetCol(MatrixRowCol& mrc)
05747 {
05748    REPORT
05749    mrc.skip=0; mrc.storage=mrc.length=nrows_val;
05750    if ( ncols_val==1 && !(mrc.cw*StoreHere) )      // ColumnVector
05751       { REPORT mrc.data=store; }
05752    else
05753    {
05754       Real* ColCopy;
05755       if ( !(mrc.cw*(HaveStore+StoreHere)) )
05756       {
05757          REPORT
05758          ColCopy = new Real [nrows_val]; MatrixErrorNoSpace(ColCopy);
05759          MONITOR_REAL_NEW("Make (MatGetCol)",nrows_val,ColCopy)
05760          mrc.data = ColCopy; mrc.cw += HaveStore;
05761       }
05762       else { REPORT ColCopy = mrc.data; }
05763       if (+(mrc.cw*LoadOnEntry))
05764       {
05765          REPORT
05766          Real* Mstore = store+mrc.rowcol; int i=nrows_val;
05767          //while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols_val; }
05768          if (i) for (;;)
05769             { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols_val; }
05770       }
05771    }
05772 }
05773 
05774 void Matrix::GetCol(MatrixColX& mrc)
05775 {
05776    REPORT
05777    mrc.skip=0; mrc.storage=nrows_val; mrc.length=nrows_val;
05778    if (+(mrc.cw*LoadOnEntry))
05779    {
05780       REPORT  Real* ColCopy = mrc.data;
05781       Real* Mstore = store+mrc.rowcol; int i=nrows_val;
05782       //while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols_val; }
05783       if (i) for (;;)
05784           { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols_val; }
05785    }
05786 }
05787 
05788 void Matrix::RestoreCol(MatrixRowCol& mrc)
05789 {
05790    // always check StoreOnExit before calling RestoreCol
05791    REPORT                                   // 429
05792    if (+(mrc.cw*HaveStore))
05793    {
05794       REPORT                                // 426
05795       Real* Mstore = store+mrc.rowcol; int i=nrows_val;
05796       Real* Cstore = mrc.data;
05797       // while (i--) { *Mstore = *Cstore++; Mstore+=ncols_val; }
05798       if (i) for (;;)
05799           { *Mstore = *Cstore++; if (!(--i)) break; Mstore+=ncols_val; }
05800    }
05801 }
05802 
05803 void Matrix::RestoreCol(MatrixColX& mrc)
05804 {
05805    REPORT
05806    Real* Mstore = store+mrc.rowcol; int i=nrows_val; Real* Cstore = mrc.data;
05807    // while (i--) { *Mstore = *Cstore++; Mstore+=ncols_val; }
05808    if (i) for (;;)
05809       { *Mstore = *Cstore++; if (!(--i)) break; Mstore+=ncols_val; }
05810 }
05811 
05812 void Matrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrMat(); }  // 1808
05813 
05814 void Matrix::NextCol(MatrixRowCol& mrc)
05815 {
05816    REPORT                                        // 632
05817    if (+(mrc.cw*StoreOnExit)) { REPORT RestoreCol(mrc); }
05818    mrc.rowcol++;
05819    if (mrc.rowcol<ncols_val)
05820    {
05821       if (+(mrc.cw*LoadOnEntry))
05822       {
05823          REPORT
05824          Real* ColCopy = mrc.data;
05825          Real* Mstore = store+mrc.rowcol; int i=nrows_val;
05826          //while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols_val; }
05827          if (i) for (;;)
05828             { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols_val; }
05829       }
05830    }
05831    else { REPORT mrc.cw -= StoreOnExit; }
05832 }
05833 
05834 void Matrix::NextCol(MatrixColX& mrc)
05835 {
05836    REPORT
05837    if (+(mrc.cw*StoreOnExit)) { REPORT RestoreCol(mrc); }
05838    mrc.rowcol++;
05839    if (mrc.rowcol<ncols_val)
05840    {
05841       if (+(mrc.cw*LoadOnEntry))
05842       {
05843          REPORT
05844          Real* ColCopy = mrc.data;
05845          Real* Mstore = store+mrc.rowcol; int i=nrows_val;
05846          // while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols_val; }
05847          if (i) for (;;)
05848             { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols_val; }
05849       }
05850    }
05851    else { REPORT mrc.cw -= StoreOnExit; }
05852 }
05853 
05854 // routines for diagonal matrix
05855 
05856 void DiagonalMatrix::GetRow(MatrixRowCol& mrc)
05857 {
05858    REPORT
05859    mrc.skip=mrc.rowcol; mrc.storage=1;
05860    mrc.data=store+mrc.skip; mrc.length=ncols_val;
05861 }
05862 
05863 void DiagonalMatrix::GetCol(MatrixRowCol& mrc)
05864 {
05865    REPORT
05866    mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows_val;
05867    if (+(mrc.cw*StoreHere))              // should not happen
05868       Throw(InternalException("DiagonalMatrix::GetCol(MatrixRowCol&)"));
05869    else  { REPORT mrc.data=store+mrc.skip; }
05870                                                       // not accessed
05871 }
05872 
05873 void DiagonalMatrix::GetCol(MatrixColX& mrc)
05874 {
05875    REPORT
05876    mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows_val;
05877    mrc.data = mrc.store+mrc.skip;
05878    *(mrc.data)=*(store+mrc.skip);
05879 }
05880 
05881 void DiagonalMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrDiag(); }
05882                         // 800
05883 
05884 void DiagonalMatrix::NextCol(MatrixRowCol& mrc) { REPORT mrc.IncrDiag(); }
05885                         // not accessed
05886 
05887 void DiagonalMatrix::NextCol(MatrixColX& mrc)
05888 {
05889    REPORT
05890    if (+(mrc.cw*StoreOnExit))
05891       { REPORT *(store+mrc.rowcol)=*(mrc.data); }
05892    mrc.IncrDiag();
05893    int t1 = +(mrc.cw*LoadOnEntry);
05894    if (t1 && mrc.rowcol < ncols_val)
05895       { REPORT *(mrc.data)=*(store+mrc.rowcol); }
05896 }
05897 
05898 // routines for upper triangular matrix
05899 
05900 void UpperTriangularMatrix::GetRow(MatrixRowCol& mrc)
05901 {
05902    REPORT
05903    int row = mrc.rowcol; mrc.skip=row; mrc.length=ncols_val;
05904    mrc.storage=ncols_val-row; mrc.data=store+(row*(2*ncols_val-row+1))/2;
05905 }
05906 
05907 
05908 void UpperTriangularMatrix::GetCol(MatrixRowCol& mrc)
05909 {
05910    REPORT
05911    mrc.skip=0; int i=mrc.rowcol+1; mrc.storage=i;
05912    mrc.length=nrows_val; Real* ColCopy;
05913    if ( !(mrc.cw*(StoreHere+HaveStore)) )
05914    {
05915       REPORT                                              // not accessed
05916       ColCopy = new Real [nrows_val]; MatrixErrorNoSpace(ColCopy);
05917       MONITOR_REAL_NEW("Make (UT GetCol)",nrows_val,ColCopy)
05918       mrc.data = ColCopy; mrc.cw += HaveStore;
05919    }
05920    else { REPORT ColCopy = mrc.data; }
05921    if (+(mrc.cw*LoadOnEntry))
05922    {
05923       REPORT
05924       Real* Mstore = store+mrc.rowcol; int j = ncols_val;
05925       // while (i--) { *ColCopy++ = *Mstore; Mstore += --j; }
05926       if (i) for (;;)
05927          { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += --j; }
05928    }
05929 }
05930 
05931 void UpperTriangularMatrix::GetCol(MatrixColX& mrc)
05932 {
05933    REPORT
05934    mrc.skip=0; int i=mrc.rowcol+1; mrc.storage=i;
05935    mrc.length=nrows_val;
05936    if (+(mrc.cw*LoadOnEntry))
05937    {
05938       REPORT
05939       Real* ColCopy = mrc.data;
05940       Real* Mstore = store+mrc.rowcol; int j = ncols_val;
05941       // while (i--) { *ColCopy++ = *Mstore; Mstore += --j; }
05942       if (i) for (;;)
05943          { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += --j; }
05944    }
05945 }
05946 
05947 void UpperTriangularMatrix::RestoreCol(MatrixRowCol& mrc)
05948 {
05949   REPORT
05950   Real* Mstore = store+mrc.rowcol; int i=mrc.rowcol+1; int j = ncols_val;
05951   Real* Cstore = mrc.data;
05952   // while (i--) { *Mstore = *Cstore++; Mstore += --j; }
05953   if (i) for (;;)
05954      { *Mstore = *Cstore++; if (!(--i)) break; Mstore += --j; }
05955 }
05956 
05957 void UpperTriangularMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrUT(); }
05958                                                       // 722
05959 
05960 // routines for lower triangular matrix
05961 
05962 void LowerTriangularMatrix::GetRow(MatrixRowCol& mrc)
05963 {
05964    REPORT
05965    int row=mrc.rowcol; mrc.skip=0; mrc.storage=row+1; mrc.length=ncols_val;
05966    mrc.data=store+(row*(row+1))/2;
05967 }
05968 
05969 void LowerTriangularMatrix::GetCol(MatrixRowCol& mrc)
05970 {
05971    REPORT
05972    int col=mrc.rowcol; mrc.skip=col; mrc.length=nrows_val;
05973    int i=nrows_val-col; mrc.storage=i; Real* ColCopy;
05974    if ( +(mrc.cw*(StoreHere+HaveStore)) )
05975       { REPORT  ColCopy = mrc.data; }
05976    else
05977    {
05978       REPORT                                            // not accessed
05979       ColCopy = new Real [nrows_val]; MatrixErrorNoSpace(ColCopy);
05980       MONITOR_REAL_NEW("Make (LT GetCol)",nrows_val,ColCopy)
05981       mrc.cw += HaveStore; mrc.data = ColCopy;
05982    }
05983 
05984    if (+(mrc.cw*LoadOnEntry))
05985    {
05986       REPORT
05987       Real* Mstore = store+(col*(col+3))/2;
05988       // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
05989       if (i) for (;;)
05990          { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
05991    }
05992 }
05993 
05994 void LowerTriangularMatrix::GetCol(MatrixColX& mrc)
05995 {
05996    REPORT
05997    int col=mrc.rowcol; mrc.skip=col; mrc.length=nrows_val;
05998    int i=nrows_val-col; mrc.storage=i; mrc.data = mrc.store + col;
05999 
06000    if (+(mrc.cw*LoadOnEntry))
06001    {
06002       REPORT  Real* ColCopy = mrc.data;
06003       Real* Mstore = store+(col*(col+3))/2;
06004       // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
06005       if (i) for (;;)
06006          { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
06007    }
06008 }
06009 
06010 void LowerTriangularMatrix::RestoreCol(MatrixRowCol& mrc)
06011 {
06012    REPORT
06013    int col=mrc.rowcol; Real* Cstore = mrc.data;
06014    Real* Mstore = store+(col*(col+3))/2; int i=nrows_val-col;
06015    //while (i--) { *Mstore = *Cstore++; Mstore += ++col; }
06016    if (i) for (;;)
06017       { *Mstore = *Cstore++; if (!(--i)) break; Mstore += ++col; }
06018 }
06019 
06020 void LowerTriangularMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrLT(); }
06021                                                          //712
06022 
06023 // routines for symmetric matrix
06024 
06025 void SymmetricMatrix::GetRow(MatrixRowCol& mrc)
06026 {
06027    REPORT                                                //571
06028    mrc.skip=0; int row=mrc.rowcol; mrc.length=ncols_val;
06029    if (+(mrc.cw*DirectPart))
06030       { REPORT mrc.storage=row+1; mrc.data=store+(row*(row+1))/2; }
06031    else
06032    {
06033       // do not allow StoreOnExit and !DirectPart
06034       if (+(mrc.cw*StoreOnExit))
06035          Throw(InternalException("SymmetricMatrix::GetRow(MatrixRowCol&)"));
06036       mrc.storage=ncols_val; Real* RowCopy;
06037       if (!(mrc.cw*HaveStore))
06038       {
06039          REPORT
06040          RowCopy = new Real [ncols_val]; MatrixErrorNoSpace(RowCopy);
06041          MONITOR_REAL_NEW("Make (SymGetRow)",ncols_val,RowCopy)
06042          mrc.cw += HaveStore; mrc.data = RowCopy;
06043       }
06044       else { REPORT RowCopy = mrc.data; }
06045       if (+(mrc.cw*LoadOnEntry))
06046       {
06047          REPORT                                         // 544
06048          Real* Mstore = store+(row*(row+1))/2; int i = row;
06049          while (i--) *RowCopy++ = *Mstore++;
06050          i = ncols_val-row;
06051          // while (i--) { *RowCopy++ = *Mstore; Mstore += ++row; }
06052          if (i) for (;;)
06053             { *RowCopy++ = *Mstore; if (!(--i)) break; Mstore += ++row; }
06054       }
06055    }
06056 }
06057 
06058 void SymmetricMatrix::GetCol(MatrixRowCol& mrc)
06059 {
06060    // do not allow StoreHere
06061    if (+(mrc.cw*StoreHere))
06062       Throw(InternalException("SymmetricMatrix::GetCol(MatrixRowCol&)"));
06063 
06064    int col=mrc.rowcol; mrc.length=nrows_val;
06065    REPORT
06066    mrc.skip=0;
06067    if (+(mrc.cw*DirectPart))    // actually get row ??
06068       { REPORT mrc.storage=col+1; mrc.data=store+(col*(col+1))/2; }
06069    else
06070    {
06071       // do not allow StoreOnExit and !DirectPart
06072       if (+(mrc.cw*StoreOnExit))
06073          Throw(InternalException("SymmetricMatrix::GetCol(MatrixRowCol&)"));
06074 
06075       mrc.storage=ncols_val; Real* ColCopy;
06076       if ( +(mrc.cw*HaveStore)) { REPORT ColCopy = mrc.data; }
06077       else
06078       {
06079          REPORT                                      // not accessed
06080          ColCopy = new Real [ncols_val]; MatrixErrorNoSpace(ColCopy);
06081          MONITOR_REAL_NEW("Make (SymGetCol)",ncols_val,ColCopy)
06082          mrc.cw += HaveStore; mrc.data = ColCopy;
06083       }
06084       if (+(mrc.cw*LoadOnEntry))
06085       {
06086          REPORT
06087          Real* Mstore = store+(col*(col+1))/2; int i = col;
06088          while (i--) *ColCopy++ = *Mstore++;
06089          i = ncols_val-col;
06090          // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
06091          if (i) for (;;)
06092             { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
06093       }
06094    }
06095 }
06096 
06097 void SymmetricMatrix::GetCol(MatrixColX& mrc)
06098 {
06099    int col=mrc.rowcol; mrc.length=nrows_val;
06100    if (+(mrc.cw*DirectPart))
06101    {
06102       REPORT
06103       mrc.skip=col; int i=nrows_val-col; mrc.storage=i;
06104       mrc.data = mrc.store+col;
06105       if (+(mrc.cw*LoadOnEntry))
06106       {
06107          REPORT                           // not accessed
06108          Real* ColCopy = mrc.data;
06109          Real* Mstore = store+(col*(col+3))/2;
06110          // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
06111          if (i) for (;;)
06112             { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
06113       }
06114    }
06115    else
06116    {
06117       REPORT
06118       // do not allow StoreOnExit and !DirectPart
06119       if (+(mrc.cw*StoreOnExit))
06120          Throw(InternalException("SymmetricMatrix::GetCol(MatrixColX&)"));
06121 
06122       mrc.skip=0; mrc.storage=ncols_val;
06123       if (+(mrc.cw*LoadOnEntry))
06124       {
06125          REPORT
06126          Real* ColCopy = mrc.data;
06127          Real* Mstore = store+(col*(col+1))/2; int i = col;
06128          while (i--) *ColCopy++ = *Mstore++;
06129          i = ncols_val-col;
06130          // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
06131          if (i) for (;;)
06132             { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
06133       }
06134    }
06135 }
06136 
06137 // Do not need RestoreRow because we do not allow !DirectPart && StoreOnExit
06138 
06139 void SymmetricMatrix::RestoreCol(MatrixColX& mrc)
06140 {
06141    REPORT
06142    // Really do restore column
06143    int col=mrc.rowcol; Real* Cstore = mrc.data;
06144    Real* Mstore = store+(col*(col+3))/2; int i = nrows_val-col;
06145    // while (i--) { *Mstore = *Cstore++; Mstore+= ++col; }
06146    if (i) for (;;)
06147       { *Mstore = *Cstore++; if (!(--i)) break; Mstore+= ++col; }
06148 
06149 }
06150 
06151 // routines for row vector
06152 
06153 void RowVector::GetCol(MatrixRowCol& mrc)
06154 {
06155    REPORT
06156    // do not allow StoreHere
06157    if (+(mrc.cw*StoreHere))
06158       Throw(InternalException("RowVector::GetCol(MatrixRowCol&)"));
06159 
06160    mrc.skip=0; mrc.storage=1; mrc.length=nrows_val;
06161    mrc.data = store+mrc.rowcol;
06162 
06163 }
06164 
06165 void RowVector::GetCol(MatrixColX& mrc)
06166 {
06167    REPORT
06168    mrc.skip=0; mrc.storage=1; mrc.length=nrows_val;
06169    if (mrc.cw >= LoadOnEntry)
06170       { REPORT *(mrc.data) = *(store+mrc.rowcol); }
06171 
06172 }
06173 
06174 void RowVector::NextCol(MatrixRowCol& mrc)
06175 { REPORT mrc.rowcol++; mrc.data++; }
06176 
06177 void RowVector::NextCol(MatrixColX& mrc)
06178 {
06179    if (+(mrc.cw*StoreOnExit)) { REPORT *(store+mrc.rowcol)=*(mrc.data); }
06180 
06181    mrc.rowcol++;
06182    if (mrc.rowcol < ncols_val)
06183    {
06184       if (+(mrc.cw*LoadOnEntry)) { REPORT *(mrc.data)=*(store+mrc.rowcol); }
06185    }
06186    else { REPORT mrc.cw -= StoreOnExit; }
06187 }
06188 
06189 void RowVector::RestoreCol(MatrixColX& mrc)
06190    { REPORT *(store+mrc.rowcol)=*(mrc.data); }           // not accessed
06191 
06192 
06193 // routines for band matrices
06194 
06195 void BandMatrix::GetRow(MatrixRowCol& mrc)
06196 {
06197    REPORT
06198    int r = mrc.rowcol; int w = lower_val+1+upper_val; mrc.length=ncols_val;
06199    int s = r-lower_val;
06200    if (s<0) { mrc.data = store+(r*w-s); w += s; s = 0; }
06201    else mrc.data = store+r*w;
06202    mrc.skip = s; s += w-ncols_val; if (s>0) w -= s; mrc.storage = w;
06203 }
06204 
06205 // should make special versions of this for upper and lower band matrices
06206 
06207 void BandMatrix::NextRow(MatrixRowCol& mrc)
06208 {
06209    REPORT
06210    int r = ++mrc.rowcol;
06211    if (r<=lower_val) { mrc.storage++; mrc.data += lower_val+upper_val; }
06212    else  { mrc.skip++; mrc.data += lower_val+upper_val+1; }
06213    if (r>=ncols_val-upper_val) mrc.storage--;
06214 }
06215 
06216 void BandMatrix::GetCol(MatrixRowCol& mrc)
06217 {
06218    REPORT
06219    int c = mrc.rowcol; int n = lower_val+upper_val; int w = n+1;
06220    mrc.length=nrows_val; Real* ColCopy;
06221    int b; int s = c-upper_val;
06222    if (s<=0) { w += s; s = 0; b = c+lower_val; } else b = s*w+n;
06223    mrc.skip = s; s += w-nrows_val; if (s>0) w -= s; mrc.storage = w;
06224    if ( +(mrc.cw*(StoreHere+HaveStore)) )
06225       { REPORT ColCopy = mrc.data; }
06226    else
06227    {
06228       REPORT
06229       ColCopy = new Real [n+1]; MatrixErrorNoSpace(ColCopy);
06230       MONITOR_REAL_NEW("Make (BMGetCol)",n+1,ColCopy)
06231       mrc.cw += HaveStore; mrc.data = ColCopy;
06232    }
06233 
06234    if (+(mrc.cw*LoadOnEntry))
06235    {
06236       REPORT
06237       Real* Mstore = store+b;
06238       // while (w--) { *ColCopy++ = *Mstore; Mstore+=n; }
06239       if (w) for (;;)
06240          { *ColCopy++ = *Mstore; if (!(--w)) break; Mstore+=n; }
06241    }
06242 }
06243 
06244 void BandMatrix::GetCol(MatrixColX& mrc)
06245 {
06246    REPORT
06247    int c = mrc.rowcol; int n = lower_val+upper_val; int w = n+1;
06248    mrc.length=nrows_val; int b; int s = c-upper_val;
06249    if (s<=0) { w += s; s = 0; b = c+lower_val; } else b = s*w+n;
06250    mrc.skip = s; s += w-nrows_val; if (s>0) w -= s; mrc.storage = w;
06251    mrc.data = mrc.store+mrc.skip;
06252 
06253    if (+(mrc.cw*LoadOnEntry))
06254    {
06255       REPORT
06256       Real* ColCopy = mrc.data; Real* Mstore = store+b;
06257       // while (w--) { *ColCopy++ = *Mstore; Mstore+=n; }
06258       if (w) for (;;)
06259          { *ColCopy++ = *Mstore; if (!(--w)) break; Mstore+=n; }
06260    }
06261 }
06262 
06263 void BandMatrix::RestoreCol(MatrixRowCol& mrc)
06264 {
06265    REPORT
06266    int c = mrc.rowcol; int n = lower_val+upper_val; int s = c-upper_val;
06267    Real* Mstore = store + ((s<=0) ? c+lower_val : s*n+s+n);
06268    Real* Cstore = mrc.data;
06269    int w = mrc.storage;
06270    // while (w--) { *Mstore = *Cstore++; Mstore += n; }
06271    if (w) for (;;)
06272       { *Mstore = *Cstore++; if (!(--w)) break; Mstore += n; }
06273 }
06274 
06275 // routines for symmetric band matrix
06276 
06277 void SymmetricBandMatrix::GetRow(MatrixRowCol& mrc)
06278 {
06279    REPORT
06280    int r=mrc.rowcol; int s = r-lower_val; int w1 = lower_val+1; int o = r*w1;
06281    mrc.length = ncols_val;
06282    if (s<0) { w1 += s; o -= s; s = 0; }
06283    mrc.skip = s;
06284 
06285    if (+(mrc.cw*DirectPart))
06286       { REPORT  mrc.data = store+o; mrc.storage = w1; }
06287    else
06288    {
06289       // do not allow StoreOnExit and !DirectPart
06290       if (+(mrc.cw*StoreOnExit))
06291          Throw(InternalException("SymmetricBandMatrix::GetRow(MatrixRowCol&)"));
06292       int w = w1+lower_val; s += w-ncols_val; Real* RowCopy;
06293       if (s>0) w -= s; mrc.storage = w; int w2 = w-w1;
06294       if (!(mrc.cw*HaveStore))
06295       {
06296          REPORT
06297          RowCopy = new Real [2*lower_val+1]; MatrixErrorNoSpace(RowCopy);
06298          MONITOR_REAL_NEW("Make (SmBGetRow)",2*lower_val+1,RowCopy)
06299          mrc.cw += HaveStore; mrc.data = RowCopy;
06300       }
06301       else { REPORT  RowCopy = mrc.data; }
06302 
06303       if (+(mrc.cw*LoadOnEntry) && ncols_val > 0)
06304       {
06305          REPORT
06306          Real* Mstore = store+o;
06307          while (w1--) *RowCopy++ = *Mstore++;
06308          Mstore--;
06309          while (w2--) { Mstore += lower_val; *RowCopy++ = *Mstore; }
06310       }
06311    }
06312 }
06313 
06314 void SymmetricBandMatrix::GetCol(MatrixRowCol& mrc)
06315 {
06316    // do not allow StoreHere
06317    if (+(mrc.cw*StoreHere))
06318       Throw(InternalException("SymmetricBandMatrix::GetCol(MatrixRowCol&)"));
06319 
06320    int c=mrc.rowcol; int w1 = lower_val+1; mrc.length=nrows_val;
06321    REPORT
06322    int s = c-lower_val; int o = c*w1;
06323    if (s<0) { w1 += s; o -= s; s = 0; }
06324    mrc.skip = s;
06325 
06326    if (+(mrc.cw*DirectPart))
06327    { REPORT  mrc.data = store+o; mrc.storage = w1; }
06328    else
06329    {
06330       // do not allow StoreOnExit and !DirectPart
06331       if (+(mrc.cw*StoreOnExit))
06332          Throw(InternalException("SymmetricBandMatrix::GetCol(MatrixRowCol&)"));
06333       int w = w1+lower_val; s += w-ncols_val; Real* ColCopy;
06334       if (s>0) w -= s; mrc.storage = w; int w2 = w-w1;
06335 
06336       if ( +(mrc.cw*HaveStore) ) { REPORT ColCopy = mrc.data; }
06337       else
06338       {
06339          REPORT ColCopy = new Real [2*lower_val+1]; MatrixErrorNoSpace(ColCopy);
06340          MONITOR_REAL_NEW("Make (SmBGetCol)",2*lower_val+1,ColCopy)
06341          mrc.cw += HaveStore; mrc.data = ColCopy;
06342       }
06343 
06344       if (+(mrc.cw*LoadOnEntry))
06345       {
06346          REPORT
06347          Real* Mstore = store+o;
06348          while (w1--) *ColCopy++ = *Mstore++;
06349          Mstore--;
06350          while (w2--) { Mstore += lower_val; *ColCopy++ = *Mstore; }
06351       }
06352    }
06353 }
06354 
06355 void SymmetricBandMatrix::GetCol(MatrixColX& mrc)
06356 {
06357    int c=mrc.rowcol; int w1 = lower_val+1; mrc.length=nrows_val;
06358    if (+(mrc.cw*DirectPart))
06359    {
06360       REPORT
06361       int b = c*w1+lower_val;
06362       mrc.skip = c; c += w1-nrows_val; w1 -= c; mrc.storage = w1;
06363       Real* ColCopy = mrc.data = mrc.store+mrc.skip;
06364       if (+(mrc.cw*LoadOnEntry))
06365       {
06366          REPORT
06367          Real* Mstore = store+b;
06368          // while (w1--) { *ColCopy++ = *Mstore; Mstore += lower; }
06369          if (w1) for (;;)
06370             { *ColCopy++ = *Mstore; if (!(--w1)) break; Mstore += lower_val; }
06371       }
06372    }
06373    else
06374    {
06375       REPORT
06376       // do not allow StoreOnExit and !DirectPart
06377       if (+(mrc.cw*StoreOnExit))
06378          Throw(InternalException("SymmetricBandMatrix::GetCol(MatrixColX&)"));
06379       int s = c-lower_val; int o = c*w1;
06380       if (s<0) { w1 += s; o -= s; s = 0; }
06381       mrc.skip = s;
06382 
06383       int w = w1+lower_val; s += w-ncols_val;
06384       if (s>0) w -= s; mrc.storage = w; int w2 = w-w1;
06385 
06386       Real* ColCopy = mrc.data = mrc.store+mrc.skip;
06387 
06388       if (+(mrc.cw*LoadOnEntry))
06389       {
06390          REPORT
06391          Real* Mstore = store+o;
06392          while (w1--) *ColCopy++ = *Mstore++;
06393          Mstore--;
06394          while (w2--) { Mstore += lower_val; *ColCopy++ = *Mstore; }
06395       }
06396 
06397    }
06398 }
06399 
06400 void SymmetricBandMatrix::RestoreCol(MatrixColX& mrc)
06401 {
06402    REPORT
06403    int c = mrc.rowcol;
06404    Real* Mstore = store + c*lower_val+c+lower_val;
06405    Real* Cstore = mrc.data; int w = mrc.storage;
06406    // while (w--) { *Mstore = *Cstore++; Mstore += lower_val; }
06407    if (w) for (;;)
06408       { *Mstore = *Cstore++; if (!(--w)) break; Mstore += lower_val; }
06409 }
06410 
06411 // routines for identity matrix
06412 
06413 void IdentityMatrix::GetRow(MatrixRowCol& mrc)
06414 {
06415    REPORT
06416    mrc.skip=mrc.rowcol; mrc.storage=1; mrc.data=store; mrc.length=ncols_val;
06417 }
06418 
06419 void IdentityMatrix::GetCol(MatrixRowCol& mrc)
06420 {
06421    REPORT
06422    mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows_val;
06423    if (+(mrc.cw*StoreHere))              // should not happen
06424       Throw(InternalException("IdentityMatrix::GetCol(MatrixRowCol&)"));
06425    else  { REPORT mrc.data=store; }
06426 }
06427 
06428 void IdentityMatrix::GetCol(MatrixColX& mrc)
06429 {
06430    REPORT
06431    mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows_val;
06432    mrc.data = mrc.store+mrc.skip; *(mrc.data)=*store;
06433 }
06434 
06435 void IdentityMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrId(); }
06436 
06437 void IdentityMatrix::NextCol(MatrixRowCol& mrc) { REPORT mrc.IncrId(); }
06438 
06439 void IdentityMatrix::NextCol(MatrixColX& mrc)
06440 {
06441    REPORT
06442    if (+(mrc.cw*StoreOnExit)) { REPORT *store=*(mrc.data); }
06443    mrc.IncrDiag();            // must increase mrc.data so need IncrDiag
06444    int t1 = +(mrc.cw*LoadOnEntry);
06445    if (t1 && mrc.rowcol < ncols_val) { REPORT *(mrc.data)=*store; }
06446 }
06447 
06448 
06449 
06450 
06451 // *************************** destructors *******************************
06452 
06453 MatrixRowCol::~MatrixRowCol()
06454 {
06455    if (+(cw*HaveStore))
06456    {
06457       MONITOR_REAL_DELETE("Free    (RowCol)",-1,data)  // do not know length
06458       delete [] data;
06459    }
06460 }
06461 
06462 MatrixRow::~MatrixRow() { if (+(cw*StoreOnExit)) gm->RestoreRow(*this); }
06463 
06464 MatrixCol::~MatrixCol() { if (+(cw*StoreOnExit)) gm->RestoreCol(*this); }
06465 
06466 MatrixColX::~MatrixColX() { if (+(cw*StoreOnExit)) gm->RestoreCol(*this); }
06467 
06468 #ifdef use_namespace
06469 }
06470 #endif
06471 
06473 /*
06474 ROBOOP -- A robotics object oriented package in C++
06475 Copyright (C) 1996-2004  Richard Gourdeau
06476 
06477 This library is free software; you can redistribute it and/or modify
06478 it under the terms of the GNU Lesser General Public License as
06479 published by the Free Software Foundation; either version 2.1 of the
06480 License, or (at your option) any later version.
06481 
06482 This library is distributed in the hope that it will be useful,
06483 but WITHOUT ANY WARRANTY; without even the implied warranty of
06484 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
06485 GNU Lesser General Public License for more details.
06486 
06487 You should have received a copy of the GNU Lesser General Public
06488 License along with this library; if not, write to the Free Software
06489 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
06490 
06491 
06492 Report problems and direct all questions to:
06493 
06494 Richard Gourdeau
06495 Professeur Agrege
06496 Departement de genie electrique
06497 Ecole Polytechnique de Montreal
06498 C.P. 6079, Succ. Centre-Ville
06499 Montreal, Quebec, H3C 3A7
06500 
06501 email: richard.gourdeau@polymtl.ca
06502 
06503 -------------------------------------------------------------------------------
06504 Revision_history:
06505 
06506 2004/07/01: Etienne Lachance
06507    -Added protection on trans function.
06508    -Added doxygen documentation.
06509 
06510 2004/07/01: Ethan Tira-Thompson
06511     -Added support for newmat's use_namespace #define, using ROBOOP namespace
06512 
06513 2004/08/10: Etienne Lachance
06514     -Make sure input vector is 3x1 in trans function.
06515 
06516 2006/01/21: Etienne Lachance
06517     -Include utils.h instead of robot.h.
06518 
06519 2006/11/15: Richard Gourdeau
06520     -atan2() in irotk()
06521 -------------------------------------------------------------------------------
06522 */
06523 
06529 
06530 static const char rcsid[] = "$Id: homogen.cpp,v 1.15 2006/11/15 18:35:17 gourdeau Exp $";
06531 
06532 
06533 #ifdef use_namespace
06534 namespace ROBOOP {
06535   using namespace NEWMAT;
06536 #endif
06537 
06538 
06539 ReturnMatrix trans(const ColumnVector & a)
06541 {
06542    Matrix translation(4,4);
06543 
06544    translation << fourbyfourident; // identity matrix 
06545 
06546    if (a.Nrows() == 3) 
06547      {
06548        translation(1,4) = a(1);
06549        translation(2,4) = a(2);
06550        translation(3,4) = a(3);
06551      }
06552    else
06553        cerr << "trans: wrong size in input vector." << endl;
06554 
06555    translation.Release(); return translation;
06556 }
06557 
06558 ReturnMatrix rotx(const Real alpha)
06560 {
06561    Matrix rot(4,4);
06562    Real c, s;
06563 
06564    rot << fourbyfourident; // identity matrix 
06565 
06566    c = cos(alpha);
06567    s = sin(alpha);
06568 
06569    rot(2,2) = c;
06570    rot(3,3) = c;
06571    rot(2,3) = -s;
06572    rot(3,2) = s;
06573 
06574    rot.Release(); return rot;
06575 }
06576 
06577 
06578 ReturnMatrix roty(const Real beta)
06580 {
06581    Matrix rot(4,4);
06582    Real c, s;
06583 
06584    rot << fourbyfourident; // identity matrix
06585 
06586    c = cos(beta);
06587    s = sin(beta);
06588 
06589    rot(1,1) = c;
06590    rot(3,3) = c;
06591    rot(1,3) = s;
06592    rot(3,1) = -s;
06593 
06594    rot.Release(); return rot;
06595 }
06596 
06597 
06598 ReturnMatrix rotz(const Real gamma)
06600 {
06601    Matrix rot(4,4);
06602    Real c, s;
06603 
06604    rot << fourbyfourident; // identity matrix
06605 
06606    c = cos(gamma);
06607    s = sin(gamma);
06608 
06609    rot(1,1) = c;
06610    rot(2,2) = c;
06611    rot(1,2) = -s;
06612    rot(2,1) = s;
06613 
06614    rot.Release(); return rot;
06615 }
06616 
06617 // compound rotations 
06618 
06619 
06620 ReturnMatrix rotk(const Real theta, const ColumnVector & k)
06622 {
06623    Matrix rot(4,4);
06624    Real c, s, vers, kx, ky, kz;
06625 
06626    rot << fourbyfourident; // identity matrix
06627 
06628    vers = SumSquare(k.SubMatrix(1,3,1,1));
06629    if (vers != 0.0) { // compute the rotation if the vector norm is not 0.0
06630       vers = sqrt(1/vers);
06631       kx = k(1)*vers;
06632       ky = k(2)*vers;
06633       kz = k(3)*vers;
06634       s = sin(theta);
06635       c = cos(theta);
06636       vers = 1-c;
06637 
06638       rot(1,1) = kx*kx*vers+c;
06639       rot(1,2) = kx*ky*vers-kz*s;
06640       rot(1,3) = kx*kz*vers+ky*s;
06641       rot(2,1) = kx*ky*vers+kz*s;
06642       rot(2,2) = ky*ky*vers+c;
06643       rot(2,3) = ky*kz*vers-kx*s;
06644       rot(3,1) = kx*kz*vers-ky*s;
06645       rot(3,2) = ky*kz*vers+kx*s;
06646       rot(3,3) = kz*kz*vers+c;
06647    }
06648 
06649    rot.Release(); return rot;
06650 }
06651 
06652 
06653 ReturnMatrix rpy(const ColumnVector & a)
06655 {
06656    Matrix rot(4,4);
06657    Real ca, sa, cb, sb, cc, sc;
06658 
06659    rot << fourbyfourident; // identity matrix
06660 
06661    ca = cos(a(1));
06662    sa = sin(a(1));
06663    cb = cos(a(2));
06664    sb = sin(a(2));
06665    cc = cos(a(3));
06666    sc = sin(a(3));
06667 
06668    rot(1,1) = cb*cc;
06669    rot(1,2) = sa*sb*cc-ca*sc;
06670    rot(1,3) = ca*sb*cc+sa*sc;
06671    rot(2,1) = cb*sc;
06672    rot(2,2) = sa*sb*sc+ca*cc;
06673    rot(2,3) = ca*sb*sc-sa*cc;
06674    rot(3,1) = -sb;
06675    rot(3,2) = sa*cb;
06676    rot(3,3) = ca*cb;
06677 
06678    rot.Release(); return rot;
06679 }
06680 
06681 
06682 ReturnMatrix eulzxz(const ColumnVector & a)
06684 {
06685    Matrix rot(4,4);
06686    Real c1, s1, ca, sa, c2, s2;
06687 
06688    rot << fourbyfourident; // identity matrix
06689 
06690    c1 = cos(a(1));
06691    s1 = sin(a(1));
06692    ca = cos(a(2));
06693    sa = sin(a(2));
06694    c2 = cos(a(3));
06695    s2 = sin(a(3));
06696 
06697    rot(1,1) = c1*c2-s1*ca*s2;
06698    rot(1,2) = -c1*s2-s1*ca*c2;
06699    rot(1,3) = sa*s1;
06700    rot(2,1) = s1*c2+c1*ca*s2;
06701    rot(2,2) = -s1*s2+c1*ca*c2;
06702    rot(2,3) = -sa*c1;
06703    rot(3,1) = sa*s2;
06704    rot(3,2) = sa*c2;
06705    rot(3,3) = ca;
06706 
06707    rot.Release(); return rot;
06708 }
06709 
06710 
06711 ReturnMatrix rotd(const Real theta, const ColumnVector & k1,
06712                   const ColumnVector & k2)
06714 {
06715    Matrix rot;
06716 
06717    rot = trans(k1)*rotk(theta,k2-k1)*trans(-k1);
06718 
06719    rot.Release(); return rot;
06720 }
06721 
06722 // inverse problem for compound rotations
06723 
06724 ReturnMatrix irotk(const Matrix & R)
06726 {
06727    ColumnVector k(4);
06728    Real a, b, c;
06729 
06730    a = (R(3,2)-R(2,3));
06731    b = (R(1,3)-R(3,1));
06732    c = (R(2,1)-R(1,2));
06733    k(4) = atan2(sqrt(a*a + b*b + c*c),(R(1,1) + R(2,2) + R(3,3)-1));
06734    k(1) = (R(3,2)-R(2,3))/(2*sin(k(4)));
06735    k(2) = (R(1,3)-R(3,1))/(2*sin(k(4)));
06736    k(3) = (R(2,1)-R(1,2))/(2*sin(k(4)));
06737 
06738    k.Release(); return k;
06739 }
06740 
06741 
06742 ReturnMatrix irpy(const Matrix & R)
06744 {
06745    ColumnVector k(3);
06746 
06747    if (R(3,1)==1) {
06748       k(1) = atan2(-R(1,2),-R(1,3));
06749       k(2) = -M_PI/2;
06750       k(3) = 0.0;
06751    } else if (R(3,1)==-1) {
06752       k(1) = atan2(R(1,2),R(1,3));
06753       k(2) = M_PI/2;
06754       k(3) = 0.0;
06755    } else {
06756       k(1) = atan2(R(3,2), R(3,3));
06757       k(2) = atan2(-R(3,1), sqrt(R(1,1)*R(1,1) + R(2,1)*R(2,1)));
06758       k(3) = atan2(R(2,1), R(1,1));
06759    }
06760 
06761    k.Release(); return k;
06762 }
06763 
06764 
06765 ReturnMatrix ieulzxz(const Matrix & R)
06767 {
06768    ColumnVector  a(3);
06769 
06770    if ((R(3,3)==1)  || (R(3,3)==-1)) {
06771       a(1) = 0.0;
06772       a(2) = ((R(3,3) == 1) ? 0.0 : M_PI);
06773       a(3) = atan2(R(2,1),R(1,1));
06774    } else {
06775       a(1) = atan2(R(1,3), -R(2,3));
06776       a(2) = atan2(sqrt(R(1,3)*R(1,3) + R(2,3)*R(2,3)), R(3,3));
06777       a(3) = atan2(R(3,1), R(3,2));
06778    }
06779 
06780    a.Release(); return a;
06781 }
06782 
06783 #ifdef use_namespace
06784 }
06785 #endif
06786 
06787 
06788 
06793 
06794 
06795 // Copyright (C) 1991,2,3,4: R B Davies
06796 
06797 #define WANT_MATH
06798 
06799 
06800 #ifdef use_namespace
06801 namespace NEWMAT {
06802 #endif
06803 
06804 
06805 #ifdef DO_REPORT
06806 #define REPORT { static ExeCounter ExeCount(__LINE__,2); ++ExeCount; }
06807 #else
06808 #define REPORT {}
06809 #endif
06810 
06811 //#define MONITOR(what,storage,store) { cout << what << " " << storage << " at " << (long)store << "\n"; }
06812 
06813 #define MONITOR(what,store,storage) {}
06814 
06815 /************************** Matrix Row/Col functions ************************/
06816 
06817 void MatrixRowCol::Add(const MatrixRowCol& mrc)
06818 {
06819    // THIS += mrc
06820    REPORT
06821    int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage;
06822    if (f < skip) f = skip; if (l > lx) l = lx; l -= f;
06823    if (l<=0) return;
06824    Real* elx=data+(f-skip); Real* el=mrc.data+(f-mrc.skip);
06825    while (l--) *elx++ += *el++;
06826 }
06827 
06828 void MatrixRowCol::AddScaled(const MatrixRowCol& mrc, Real x)
06829 {
06830    REPORT
06831    // THIS += (mrc * x)
06832    int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage;
06833    if (f < skip) f = skip; if (l > lx) l = lx; l -= f;
06834    if (l<=0) return;
06835    Real* elx=data+(f-skip); Real* el=mrc.data+(f-mrc.skip);
06836    while (l--) *elx++ += *el++ * x;
06837 }
06838 
06839 void MatrixRowCol::Sub(const MatrixRowCol& mrc)
06840 {
06841    REPORT
06842    // THIS -= mrc
06843    int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage;
06844    if (f < skip) f = skip; if (l > lx) l = lx; l -= f;
06845    if (l<=0) return;
06846    Real* elx=data+(f-skip); Real* el=mrc.data+(f-mrc.skip);
06847    while (l--) *elx++ -= *el++;
06848 }
06849 
06850 void MatrixRowCol::Inject(const MatrixRowCol& mrc)
06851 // copy stored elements only
06852 {
06853    REPORT
06854    int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage;
06855    if (f < skip) f = skip; if (l > lx) l = lx; l -= f;
06856    if (l<=0) return;
06857    Real* elx=data+(f-skip); Real* ely=mrc.data+(f-mrc.skip);
06858    while (l--) *elx++ = *ely++;
06859 }
06860 
06861 Real DotProd(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
06862 {
06863    REPORT                                         // not accessed
06864    int f = mrc1.skip; int f2 = mrc2.skip;
06865    int l = f + mrc1.storage; int l2 = f2 + mrc2.storage;
06866    if (f < f2) f = f2; if (l > l2) l = l2; l -= f;
06867    if (l<=0) return 0.0;
06868 
06869    Real* el1=mrc1.data+(f-mrc1.skip); Real* el2=mrc2.data+(f-mrc2.skip);
06870    Real sum = 0.0;
06871    while (l--) sum += *el1++ * *el2++;
06872    return sum;
06873 }
06874 
06875 void MatrixRowCol::Add(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
06876 {
06877    // THIS = mrc1 + mrc2
06878    int f = skip; int l = skip + storage;
06879    int f1 = mrc1.skip; int l1 = f1 + mrc1.storage;
06880    if (f1<f) f1=f; if (l1>l) l1=l;
06881    int f2 = mrc2.skip; int l2 = f2 + mrc2.storage;
06882    if (f2<f) f2=f; if (l2>l) l2=l;
06883    Real* el = data + (f-skip);
06884    Real* el1 = mrc1.data+(f1-mrc1.skip); Real* el2 = mrc2.data+(f2-mrc2.skip);
06885    if (f1<f2)
06886    {
06887       int i = f1-f; while (i--) *el++ = 0.0;
06888       if (l1<=f2)                              // disjoint
06889       {
06890          REPORT                                // not accessed
06891          i = l1-f1;     while (i--) *el++ = *el1++;
06892          i = f2-l1;     while (i--) *el++ = 0.0;
06893          i = l2-f2;     while (i--) *el++ = *el2++;
06894          i = l-l2;      while (i--) *el++ = 0.0;
06895       }
06896       else
06897       {
06898          i = f2-f1;    while (i--) *el++ = *el1++;
06899          if (l1<=l2)
06900          {
06901             REPORT
06902             i = l1-f2; while (i--) *el++ = *el1++ + *el2++;
06903             i = l2-l1; while (i--) *el++ = *el2++;
06904             i = l-l2;  while (i--) *el++ = 0.0;
06905          }
06906          else
06907          {
06908             REPORT
06909             i = l2-f2; while (i--) *el++ = *el1++ + *el2++;
06910             i = l1-l2; while (i--) *el++ = *el1++;
06911             i = l-l1;  while (i--) *el++ = 0.0;
06912          }
06913       }
06914    }
06915    else
06916    {
06917       int i = f2-f; while (i--) *el++ = 0.0;
06918       if (l2<=f1)                              // disjoint
06919       {
06920          REPORT                                // not accessed
06921          i = l2-f2;     while (i--) *el++ = *el2++;
06922          i = f1-l2;     while (i--) *el++ = 0.0;
06923          i = l1-f1;     while (i--) *el++ = *el1++;
06924          i = l-l1;      while (i--) *el++ = 0.0;
06925       }
06926       else
06927       {
06928          i = f1-f2;    while (i--) *el++ = *el2++;
06929          if (l2<=l1)
06930          {
06931             REPORT
06932             i = l2-f1; while (i--) *el++ = *el1++ + *el2++;
06933             i = l1-l2; while (i--) *el++ = *el1++;
06934             i = l-l1;  while (i--) *el++ = 0.0;
06935          }
06936          else
06937          {
06938             REPORT
06939             i = l1-f1; while (i--) *el++ = *el1++ + *el2++;
06940             i = l2-l1; while (i--) *el++ = *el2++;
06941             i = l-l2;  while (i--) *el++ = 0.0;
06942          }
06943       }
06944    }
06945 }
06946 
06947 void MatrixRowCol::Sub(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
06948 {
06949    // THIS = mrc1 - mrc2
06950    int f = skip; int l = skip + storage;
06951    int f1 = mrc1.skip; int l1 = f1 + mrc1.storage;
06952    if (f1<f) f1=f; if (l1>l) l1=l;
06953    int f2 = mrc2.skip; int l2 = f2 + mrc2.storage;
06954    if (f2<f) f2=f; if (l2>l) l2=l;
06955    Real* el = data + (f-skip);
06956    Real* el1 = mrc1.data+(f1-mrc1.skip); Real* el2 = mrc2.data+(f2-mrc2.skip);
06957    if (f1<f2)
06958    {
06959       int i = f1-f; while (i--) *el++ = 0.0;
06960       if (l1<=f2)                              // disjoint
06961       {
06962          REPORT                                // not accessed
06963          i = l1-f1;     while (i--) *el++ = *el1++;
06964          i = f2-l1;     while (i--) *el++ = 0.0;
06965          i = l2-f2;     while (i--) *el++ = - *el2++;
06966          i = l-l2;      while (i--) *el++ = 0.0;
06967       }
06968       else
06969       {
06970          i = f2-f1;    while (i--) *el++ = *el1++;
06971          if (l1<=l2)
06972          {
06973             REPORT
06974             i = l1-f2; while (i--) *el++ = *el1++ - *el2++;
06975             i = l2-l1; while (i--) *el++ = - *el2++;
06976             i = l-l2;  while (i--) *el++ = 0.0;
06977          }
06978          else
06979          {
06980             REPORT
06981             i = l2-f2; while (i--) *el++ = *el1++ - *el2++;
06982             i = l1-l2; while (i--) *el++ = *el1++;
06983             i = l-l1;  while (i--) *el++ = 0.0;
06984          }
06985       }
06986    }
06987    else
06988    {
06989       int i = f2-f; while (i--) *el++ = 0.0;
06990       if (l2<=f1)                              // disjoint
06991       {
06992          REPORT                                // not accessed
06993          i = l2-f2;     while (i--) *el++ = - *el2++;
06994          i = f1-l2;     while (i--) *el++ = 0.0;
06995          i = l1-f1;     while (i--) *el++ = *el1++;
06996          i = l-l1;      while (i--) *el++ = 0.0;
06997       }
06998       else
06999       {
07000          i = f1-f2;    while (i--) *el++ = - *el2++;
07001          if (l2<=l1)
07002          {
07003             REPORT
07004             i = l2-f1; while (i--) *el++ = *el1++ - *el2++;
07005             i = l1-l2; while (i--) *el++ = *el1++;
07006             i = l-l1;  while (i--) *el++ = 0.0;
07007          }
07008          else
07009          {
07010             REPORT
07011             i = l1-f1; while (i--) *el++ = *el1++ - *el2++;
07012             i = l2-l1; while (i--) *el++ = - *el2++;
07013             i = l-l2;  while (i--) *el++ = 0.0;
07014          }
07015       }
07016    }
07017 }
07018 
07019 
07020 void MatrixRowCol::Add(const MatrixRowCol& mrc1, Real x)
07021 {
07022    // THIS = mrc1 + x
07023    REPORT
07024    if (!storage) return;
07025    int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
07026    if (f < skip) { f = skip; if (l < f) l = f; }
07027    if (l > lx) { l = lx; if (f > lx) f = lx; }
07028 
07029    Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
07030 
07031    int l1 = f-skip;  while (l1--) *elx++ = x;
07032        l1 = l-f;     while (l1--) *elx++ = *ely++ + x;
07033        lx -= l;      while (lx--) *elx++ = x;
07034 }
07035 
07036 void MatrixRowCol::NegAdd(const MatrixRowCol& mrc1, Real x)
07037 {
07038    // THIS = x - mrc1
07039    REPORT
07040    if (!storage) return;
07041    int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
07042    if (f < skip) { f = skip; if (l < f) l = f; }
07043    if (l > lx) { l = lx; if (f > lx) f = lx; }
07044 
07045    Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
07046 
07047    int l1 = f-skip;  while (l1--) *elx++ = x;
07048        l1 = l-f;     while (l1--) *elx++ = x - *ely++;
07049        lx -= l;      while (lx--) *elx++ = x;
07050 }
07051 
07052 void MatrixRowCol::RevSub(const MatrixRowCol& mrc1)
07053 {
07054    // THIS = mrc - THIS
07055    REPORT
07056    if (!storage) return;
07057    int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
07058    if (f < skip) { f = skip; if (l < f) l = f; }
07059    if (l > lx) { l = lx; if (f > lx) f = lx; }
07060 
07061    Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
07062 
07063    int l1 = f-skip;  while (l1--) { *elx = - *elx; elx++; }
07064        l1 = l-f;     while (l1--) { *elx = *ely++ - *elx; elx++; }
07065        lx -= l;      while (lx--) { *elx = - *elx; elx++; }
07066 }
07067 
07068 void MatrixRowCol::ConCat(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
07069 {
07070    // THIS = mrc1 | mrc2
07071    REPORT
07072    int f1 = mrc1.skip; int l1 = f1 + mrc1.storage; int lx = skip + storage;
07073    if (f1 < skip) { f1 = skip; if (l1 < f1) l1 = f1; }
07074    if (l1 > lx) { l1 = lx; if (f1 > lx) f1 = lx; }
07075 
07076    Real* elx = data;
07077 
07078    int i = f1-skip;  while (i--) *elx++ =0.0;
07079    i = l1-f1;
07080    if (i)                       // in case f1 would take ely out of range
07081       { Real* ely = mrc1.data+(f1-mrc1.skip);  while (i--) *elx++ = *ely++; }
07082 
07083    int f2 = mrc2.skip; int l2 = f2 + mrc2.storage; i = mrc1.length;
07084    int skipx = l1 - i; lx -= i; // addresses rel to second seg, maybe -ve
07085    if (f2 < skipx) { f2 = skipx; if (l2 < f2) l2 = f2; }
07086    if (l2 > lx) { l2 = lx; if (f2 > lx) f2 = lx; }
07087 
07088    i = f2-skipx; while (i--) *elx++ = 0.0;
07089    i = l2-f2;
07090    if (i)                       // in case f2 would take ely out of range
07091       { Real* ely = mrc2.data+(f2-mrc2.skip); while (i--) *elx++ = *ely++; }
07092    lx -= l2;     while (lx--) *elx++ = 0.0;
07093 }
07094 
07095 void MatrixRowCol::Multiply(const MatrixRowCol& mrc1)
07096 // element by element multiply into
07097 {
07098    REPORT
07099    if (!storage) return;
07100    int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
07101    if (f < skip) { f = skip; if (l < f) l = f; }
07102    if (l > lx) { l = lx; if (f > lx) f = lx; }
07103 
07104    Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
07105 
07106    int l1 = f-skip;  while (l1--) *elx++ = 0;
07107        l1 = l-f;     while (l1--) *elx++ *= *ely++;
07108        lx -= l;      while (lx--) *elx++ = 0;
07109 }
07110 
07111 void MatrixRowCol::Multiply(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
07112 // element by element multiply
07113 {
07114    int f = skip; int l = skip + storage;
07115    int f1 = mrc1.skip; int l1 = f1 + mrc1.storage;
07116    if (f1<f) f1=f; if (l1>l) l1=l;
07117    int f2 = mrc2.skip; int l2 = f2 + mrc2.storage;
07118    if (f2<f) f2=f; if (l2>l) l2=l;
07119    Real* el = data + (f-skip); int i;
07120    if (f1<f2) f1 = f2; if (l1>l2) l1 = l2;
07121    if (l1<=f1) { REPORT i = l-f; while (i--) *el++ = 0.0; }  // disjoint
07122    else
07123    {
07124       REPORT
07125       Real* el1 = mrc1.data+(f1-mrc1.skip);
07126       Real* el2 = mrc2.data+(f1-mrc2.skip);
07127       i = f1-f ;    while (i--) *el++ = 0.0;
07128       i = l1-f1;    while (i--) *el++ = *el1++ * *el2++;
07129       i = l-l1;     while (i--) *el++ = 0.0;
07130    }
07131 }
07132 
07133 void MatrixRowCol::KP(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
07134 // row for Kronecker product
07135 {
07136    int f = skip; int s = storage; Real* el = data; int i;
07137 
07138    i = mrc1.skip * mrc2.length;
07139    if (i > f)
07140    {
07141       i -= f; f = 0; if (i > s) { i = s; s = 0; }  else s -= i;
07142       while (i--) *el++ = 0.0;
07143       if (s == 0) return;
07144    }
07145    else f -= i;
07146 
07147    i = mrc1.storage; Real* el1 = mrc1.data;
07148    int mrc2_skip = mrc2.skip; int mrc2_storage = mrc2.storage;
07149    int mrc2_length = mrc2.length;
07150    int mrc2_remain = mrc2_length - mrc2_skip - mrc2_storage;
07151    while (i--)
07152    {
07153       int j; Real* el2 = mrc2.data; Real vel1 = *el1;
07154       if (f == 0 && mrc2_length <= s)
07155       {
07156          j = mrc2_skip; s -= j;    while (j--) *el++ = 0.0;
07157          j = mrc2_storage; s -= j; while (j--) *el++ = vel1 * *el2++;
07158          j = mrc2_remain; s -= j;  while (j--) *el++ = 0.0;
07159       }
07160       else if (f >= mrc2_length) f -= mrc2_length;
07161       else
07162       {
07163          j = mrc2_skip;
07164          if (j > f)
07165          {
07166             j -= f; f = 0; if (j > s) { j = s; s = 0; } else s -= j;
07167             while (j--) *el++ = 0.0;
07168          }
07169          else f -= j;
07170 
07171          j = mrc2_storage;
07172          if (j > f)
07173          {
07174             j -= f; el2 += f; f = 0; if (j > s) { j = s; s = 0; } else s -= j;
07175             while (j--) *el++ = vel1 * *el2++;
07176          }
07177          else f -= j;
07178 
07179          j = mrc2_remain;
07180          if (j > f)
07181          {
07182             j -= f; f = 0; if (j > s) { j = s; s = 0; } else s -= j;
07183             while (j--) *el++ = 0.0;
07184          }
07185          else f -= j;
07186       }
07187       if (s == 0) return;
07188       ++el1;
07189    }
07190 
07191    i = (mrc1.length - mrc1.skip - mrc1.storage) * mrc2.length;
07192    if (i > f)
07193    {
07194       i -= f; if (i > s) i = s;
07195       while (i--) *el++ = 0.0;
07196    }
07197 }
07198 
07199 
07200 void MatrixRowCol::Copy(const MatrixRowCol& mrc1)
07201 {
07202    // THIS = mrc1
07203    REPORT
07204    if (!storage) return;
07205    int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
07206    if (f < skip) { f = skip; if (l < f) l = f; }
07207    if (l > lx) { l = lx; if (f > lx) f = lx; }
07208 
07209    Real* elx = data; Real* ely = 0;
07210 
07211    if (l-f) ely = mrc1.data+(f-mrc1.skip);
07212 
07213    int l1 = f-skip;  while (l1--) *elx++ = 0.0;
07214        l1 = l-f;     while (l1--) *elx++ = *ely++;
07215        lx -= l;      while (lx--) *elx++ = 0.0;
07216 }
07217 
07218 void MatrixRowCol::CopyCheck(const MatrixRowCol& mrc1)
07219 // Throw an exception if this would lead to a loss of data
07220 {
07221    REPORT
07222    if (!storage) return;
07223    int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
07224    if (f < skip || l > lx) Throw(ProgramException("Illegal Conversion"));
07225 
07226    Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
07227 
07228    int l1 = f-skip;  while (l1--) *elx++ = 0.0;
07229        l1 = l-f;     while (l1--) *elx++ = *ely++;
07230        lx -= l;      while (lx--) *elx++ = 0.0;
07231 }
07232 
07233 void MatrixRowCol::Check(const MatrixRowCol& mrc1)
07234 // Throw an exception if +=, -=, copy etc would lead to a loss of data
07235 {
07236    REPORT
07237    int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
07238    if (f < skip || l > lx) Throw(ProgramException("Illegal Conversion"));
07239 }
07240 
07241 void MatrixRowCol::Check()
07242 // Throw an exception if +=, -= of constant would lead to a loss of data
07243 // that is: check full row is present
07244 // may not be appropriate for symmetric matrices
07245 {
07246    REPORT
07247    if (skip!=0 || storage!=length)
07248       Throw(ProgramException("Illegal Conversion"));
07249 }
07250 
07251 void MatrixRowCol::Negate(const MatrixRowCol& mrc1)
07252 {
07253    // THIS = -mrc1
07254    REPORT
07255    if (!storage) return;
07256    int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
07257    if (f < skip) { f = skip; if (l < f) l = f; }
07258    if (l > lx) { l = lx; if (f > lx) f = lx; }
07259 
07260    Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
07261 
07262    int l1 = f-skip;  while (l1--) *elx++ = 0.0;
07263        l1 = l-f;     while (l1--) *elx++ = - *ely++;
07264        lx -= l;      while (lx--) *elx++ = 0.0;
07265 }
07266 
07267 void MatrixRowCol::Multiply(const MatrixRowCol& mrc1, Real s)
07268 {
07269    // THIS = mrc1 * s
07270    REPORT
07271    if (!storage) return;
07272    int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
07273    if (f < skip) { f = skip; if (l < f) l = f; }
07274    if (l > lx) { l = lx; if (f > lx) f = lx; }
07275 
07276    Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
07277 
07278    int l1 = f-skip;  while (l1--) *elx++ = 0.0;
07279        l1 = l-f;     while (l1--) *elx++ = *ely++ * s;
07280        lx -= l;      while (lx--) *elx++ = 0.0;
07281 }
07282 
07283 void DiagonalMatrix::Solver(MatrixColX& mrc, const MatrixColX& mrc1)
07284 {
07285    // mrc = mrc / mrc1   (elementwise)
07286    REPORT
07287    int f = mrc1.skip; int f0 = mrc.skip;
07288    int l = f + mrc1.storage; int lx = f0 + mrc.storage;
07289    if (f < f0) { f = f0; if (l < f) l = f; }
07290    if (l > lx) { l = lx; if (f > lx) f = lx; }
07291 
07292    Real* elx = mrc.data; Real* eld = store+f;
07293 
07294    int l1 = f-f0;    while (l1--) *elx++ = 0.0;
07295        l1 = l-f;     while (l1--) *elx++ /= *eld++;
07296        lx -= l;      while (lx--) *elx++ = 0.0;
07297    // Solver makes sure input and output point to same memory
07298 }
07299 
07300 void IdentityMatrix::Solver(MatrixColX& mrc, const MatrixColX& mrc1)
07301 {
07302    // mrc = mrc / mrc1   (elementwise)
07303    REPORT
07304    int f = mrc1.skip; int f0 = mrc.skip;
07305    int l = f + mrc1.storage; int lx = f0 + mrc.storage;
07306    if (f < f0) { f = f0; if (l < f) l = f; }
07307    if (l > lx) { l = lx; if (f > lx) f = lx; }
07308 
07309    Real* elx = mrc.data; Real eldv = *store;
07310 
07311    int l1 = f-f0;    while (l1--) *elx++ = 0.0;
07312        l1 = l-f;     while (l1--) *elx++ /= eldv;
07313        lx -= l;      while (lx--) *elx++ = 0.0;
07314    // Solver makes sure input and output point to same memory
07315 }
07316 
07317 void MatrixRowCol::Copy(const double*& r)
07318 {
07319    // THIS = *r
07320    REPORT
07321    Real* elx = data; const double* ely = r+skip; r += length;
07322    int l = storage; while (l--) *elx++ = (Real)*ely++;
07323 }
07324 
07325 void MatrixRowCol::Copy(const float*& r)
07326 {
07327    // THIS = *r
07328    REPORT
07329    Real* elx = data; const float* ely = r+skip; r += length;
07330    int l = storage; while (l--) *elx++ = (Real)*ely++;
07331 }
07332 
07333 void MatrixRowCol::Copy(const int*& r)
07334 {
07335    // THIS = *r
07336    REPORT
07337    Real* elx = data; const int* ely = r+skip; r += length;
07338    int l = storage; while (l--) *elx++ = (Real)*ely++;
07339 }
07340 
07341 void MatrixRowCol::Copy(Real r)
07342 {
07343    // THIS = r
07344    REPORT  Real* elx = data; int l = storage; while (l--) *elx++ = r;
07345 }
07346 
07347 void MatrixRowCol::Zero()
07348 {
07349    // THIS = 0
07350    REPORT  Real* elx = data; int l = storage; while (l--) *elx++ = 0;
07351 }
07352 
07353 void MatrixRowCol::Multiply(Real r)
07354 {
07355    // THIS *= r
07356    REPORT  Real* elx = data; int l = storage; while (l--) *elx++ *= r;
07357 }
07358 
07359 void MatrixRowCol::Add(Real r)
07360 {
07361    // THIS += r
07362    REPORT
07363    Real* elx = data; int l = storage; while (l--) *elx++ += r;
07364 }
07365 
07366 Real MatrixRowCol::SumAbsoluteValue()
07367 {
07368    REPORT
07369    Real sum = 0.0; Real* elx = data; int l = storage;
07370    while (l--) sum += fabs(*elx++);
07371    return sum;
07372 }
07373 
07374 // max absolute value of r and elements of row/col
07375 // we use <= or >= in all of these so we are sure of getting
07376 // r reset at least once.
07377 Real MatrixRowCol::MaximumAbsoluteValue1(Real r, int& i)
07378 {
07379    REPORT
07380    Real* elx = data; int l = storage; int li = -1;
07381    while (l--) { Real f = fabs(*elx++); if (r <= f) { r = f; li = l; } }
07382    i = (li >= 0) ? storage - li + skip : 0;
07383    return r;
07384 }
07385 
07386 // min absolute value of r and elements of row/col
07387 Real MatrixRowCol::MinimumAbsoluteValue1(Real r, int& i)
07388 {
07389    REPORT
07390    Real* elx = data; int l = storage; int li = -1;
07391    while (l--) { Real f = fabs(*elx++); if (r >= f) { r = f; li = l; } }
07392    i = (li >= 0) ? storage - li + skip : 0;
07393    return r;
07394 }
07395 
07396 // max value of r and elements of row/col
07397 Real MatrixRowCol::Maximum1(Real r, int& i)
07398 {
07399    REPORT
07400    Real* elx = data; int l = storage; int li = -1;
07401    while (l--) { Real f = *elx++; if (r <= f) { r = f; li = l; } }
07402    i = (li >= 0) ? storage - li + skip : 0;
07403    return r;
07404 }
07405 
07406 // min value of r and elements of row/col
07407 Real MatrixRowCol::Minimum1(Real r, int& i)
07408 {
07409    REPORT
07410    Real* elx = data; int l = storage; int li = -1;
07411    while (l--) { Real f = *elx++; if (r >= f) { r = f; li = l; } }
07412    i = (li >= 0) ? storage - li + skip : 0;
07413    return r;
07414 }
07415 
07416 Real MatrixRowCol::Sum()
07417 {
07418    REPORT
07419    Real sum = 0.0; Real* elx = data; int l = storage;
07420    while (l--) sum += *elx++;
07421    return sum;
07422 }
07423 
07424 void MatrixRowCol::SubRowCol(MatrixRowCol& mrc, int skip1, int l1) const
07425 {
07426    mrc.length = l1;  int d = skip - skip1;
07427    if (d<0) { mrc.skip = 0; mrc.data = data - d; }
07428    else  { mrc.skip = d; mrc.data = data; }
07429    d = skip + storage - skip1;
07430    d = ((l1 < d) ? l1 : d) - mrc.skip;  mrc.storage = (d < 0) ? 0 : d;
07431    mrc.cw = 0;
07432 }
07433 
07434 #ifdef use_namespace
07435 }
07436 #endif
07437 
07438 
07442 
07445 
07446 // Copyright (C) 1991,2,3,4,5: R B Davies
07447 // Updated 17 July, 1995
07448 
07449 #define WANT_MATH
07450 
07451 #ifdef use_namespace
07452 namespace NEWMAT {
07453 #endif
07454 
07455 #ifdef DO_REPORT
07456 #define REPORT { static ExeCounter ExeCount(__LINE__,15); ++ExeCount; }
07457 #else
07458 #define REPORT {}
07459 #endif
07460 
07461 void SVD(const Matrix& A, DiagonalMatrix& Q, Matrix& U, Matrix& V,
07462    bool withU, bool withV)
07463 // from Wilkinson and Reinsch: "Handbook of Automatic Computation"
07464 {
07465    REPORT
07466    Tracer trace("SVD");
07467    Real eps = FloatingPointPrecision::Epsilon();
07468    Real tol = FloatingPointPrecision::Minimum()/eps;
07469 
07470    int m = A.Nrows(); int n = A.Ncols();
07471    if (m<n)
07472       Throw(ProgramException("Want no. Rows >= no. Cols", A));
07473    if (withV && &U == &V)
07474       Throw(ProgramException("Need different matrices for U and V", U, V));
07475    U = A; Real g = 0.0; Real f,h; Real x = 0.0; int i;
07476    RowVector E(n); RectMatrixRow EI(E,0); Q.ReSize(n);
07477    RectMatrixCol UCI(U,0); RectMatrixRow URI(U,0,1,n-1);
07478 
07479    if (n) for (i=0;;)
07480    {
07481       EI.First() = g; Real ei = g; EI.Right(); Real s = UCI.SumSquare();
07482       if (s<tol) { REPORT Q.element(i) = 0.0; }
07483       else
07484       {
07485          REPORT
07486          f = UCI.First(); g = -sign(sqrt(s), f); h = f*g-s; UCI.First() = f-g;
07487          Q.element(i) = g; RectMatrixCol UCJ = UCI; int j=n-i;
07488          while (--j) { UCJ.Right(); UCJ.AddScaled(UCI, (UCI*UCJ)/h); }
07489       }
07490 
07491       s = URI.SumSquare();
07492       if (s<tol) { REPORT g = 0.0; }
07493       else
07494       {
07495          REPORT
07496          f = URI.First(); g = -sign(sqrt(s), f); URI.First() = f-g;
07497          EI.Divide(URI,f*g-s); RectMatrixRow URJ = URI; int j=m-i;
07498          while (--j) { URJ.Down(); URJ.AddScaled(EI, URI*URJ); }
07499       }
07500 
07501       Real y = fabs(Q.element(i)) + fabs(ei); if (x<y) { REPORT x = y; }
07502       if (++i == n) { REPORT break; }
07503       UCI.DownDiag(); URI.DownDiag();
07504    }
07505 
07506    if (withV)
07507    {
07508       REPORT
07509       V.ReSize(n,n); V = 0.0; RectMatrixCol VCI(V,n-1,n-1,1);
07510       if (n) { VCI.First() = 1.0; g=E.element(n-1); if (n!=1) URI.UpDiag(); }
07511       for (i=n-2; i>=0; i--)
07512       {
07513          VCI.Left();
07514          if (g!=0.0)
07515          {
07516             VCI.Divide(URI, URI.First()*g); int j = n-i;
07517             RectMatrixCol VCJ = VCI;
07518             while (--j) { VCJ.Right(); VCJ.AddScaled( VCI, (URI*VCJ) ); }
07519          }
07520          VCI.Zero(); VCI.Up(); VCI.First() = 1.0; g=E.element(i);
07521          if (i==0) break;
07522          URI.UpDiag();
07523       }
07524    }
07525 
07526    if (withU)
07527    {
07528       REPORT
07529       for (i=n-1; i>=0; i--)
07530       {
07531          g = Q.element(i); URI.Reset(U,i,i+1,n-i-1); URI.Zero();
07532          if (g!=0.0)
07533          {
07534             h=UCI.First()*g; int j=n-i; RectMatrixCol UCJ = UCI;
07535             while (--j)
07536             {
07537                UCJ.Right(); UCI.Down(); UCJ.Down(); Real s = UCI*UCJ;
07538                UCI.Up(); UCJ.Up(); UCJ.AddScaled(UCI,s/h);
07539             }
07540             UCI.Divide(g);
07541          }
07542          else UCI.Zero();
07543          UCI.First() += 1.0;
07544          if (i==0) break;
07545          UCI.UpDiag();
07546       }
07547    }
07548 
07549    eps *= x;
07550    for (int k=n-1; k>=0; k--)
07551    {
07552       Real z = -FloatingPointPrecision::Maximum(); // to keep Gnu happy
07553       Real y; int limit = 50; int l = 0;
07554       while (limit--)
07555       {
07556          Real c, s; int i; int l1=k; bool tfc=false;
07557          for (l=k; l>=0; l--)
07558          {
07559 //          if (fabs(E.element(l))<=eps) goto test_f_convergence;
07560             if (fabs(E.element(l))<=eps) { REPORT tfc=true; break; }
07561             if (fabs(Q.element(l-1))<=eps) { REPORT l1=l; break; }
07562             REPORT
07563          }
07564          if (!tfc)
07565          {
07566             REPORT
07567             l=l1; l1=l-1; s = -1.0; c = 0.0;
07568             for (i=l; i<=k; i++)
07569             {
07570                f = - s * E.element(i); E.element(i) *= c;
07571 //             if (fabs(f)<=eps) goto test_f_convergence;
07572                if (fabs(f)<=eps) { REPORT break; }
07573                g = Q.element(i); h = pythag(g,f,c,s); Q.element(i) = h;
07574                if (withU)
07575                {
07576                   REPORT
07577                   RectMatrixCol UCI(U,i); RectMatrixCol UCJ(U,l1);
07578                   ComplexScale(UCJ, UCI, c, s);
07579                }
07580             }
07581          }
07582 //       test_f_convergence: z = Q.element(k); if (l==k) goto convergence;
07583          z = Q.element(k);  if (l==k) { REPORT break; }
07584 
07585          x = Q.element(l); y = Q.element(k-1);
07586          g = E.element(k-1); h = E.element(k);
07587          f = ((y-z)*(y+z) + (g-h)*(g+h)) / (2*h*y);
07588          if (f>1)         { REPORT g = f * sqrt(1 + square(1/f)); }
07589          else if (f<-1)   { REPORT g = -f * sqrt(1 + square(1/f)); }
07590          else             { REPORT g = sqrt(f*f + 1); }
07591             { REPORT f = ((x-z)*(x+z) + h*(y / ((f<0.0) ? f-g : f+g)-h)) / x; }
07592 
07593          c = 1.0; s = 1.0;
07594          for (i=l+1; i<=k; i++)
07595          {
07596             g = E.element(i); y = Q.element(i); h = s*g; g *= c;
07597             z = pythag(f,h,c,s); E.element(i-1) = z;
07598             f = x*c + g*s; g = -x*s + g*c; h = y*s; y *= c;
07599             if (withV)
07600             {
07601                REPORT
07602                RectMatrixCol VCI(V,i); RectMatrixCol VCJ(V,i-1);
07603                ComplexScale(VCI, VCJ, c, s);
07604             }
07605             z = pythag(f,h,c,s); Q.element(i-1) = z;
07606             f = c*g + s*y; x = -s*g + c*y;
07607             if (withU)
07608             {
07609                REPORT
07610                RectMatrixCol UCI(U,i); RectMatrixCol UCJ(U,i-1);
07611                ComplexScale(UCI, UCJ, c, s);
07612             }
07613          }
07614          E.element(l) = 0.0; E.element(k) = f; Q.element(k) = x;
07615       }
07616       if (l!=k) { Throw(ConvergenceException(A)); }
07617 // convergence:
07618       if (z < 0.0)
07619       {
07620          REPORT
07621          Q.element(k) = -z;
07622          if (withV) { RectMatrixCol VCI(V,k); VCI.Negate(); }
07623       }
07624    }
07625    if (withU & withV) SortSV(Q, U, V);
07626    else if (withU) SortSV(Q, U);
07627    else if (withV) SortSV(Q, V);
07628    else sort_descending(Q);
07629 }
07630 
07631 void SVD(const Matrix& A, DiagonalMatrix& D)
07632 { REPORT Matrix U; SVD(A, D, U, U, false, false); }
07633 
07634 
07635 
07636 #ifdef use_namespace
07637 }
07638 #endif
07639 
07643 
07644 // Copyright (C) 1992,3,4,7: R B Davies
07645 
07646 #define WANT_STREAM                  // include.h will get stream fns
07647 
07648 
07649 #ifdef use_namespace
07650 namespace NEWMAT {
07651 #endif
07652 
07653 unsigned long OverflowException::Select;
07654 unsigned long SingularException::Select;
07655 unsigned long NPDException::Select;
07656 unsigned long ConvergenceException::Select;
07657 unsigned long ProgramException::Select;
07658 unsigned long IndexException::Select;
07659 unsigned long VectorException::Select;
07660 unsigned long NotSquareException::Select;
07661 unsigned long SubMatrixDimensionException::Select;
07662 unsigned long IncompatibleDimensionsException::Select;
07663 unsigned long NotDefinedException::Select;
07664 unsigned long CannotBuildException::Select;
07665 unsigned long InternalException::Select;
07666 
07667 
07668 
07669 static void MatrixDetails(const GeneralMatrix& A)
07670 // write matrix details to Exception buffer
07671 {
07672    MatrixBandWidth bw = A.bandwidth();
07673    int ubw = bw.upper_val; int lbw = bw.lower_val;
07674    BaseException::AddMessage("MatrixType = ");
07675    BaseException::AddMessage(A.Type().Value());
07676    BaseException::AddMessage("  # Rows = "); BaseException::AddInt(A.Nrows());
07677    BaseException::AddMessage("; # Cols = "); BaseException::AddInt(A.Ncols());
07678    if (lbw >=0)
07679    {
07680       BaseException::AddMessage("; lower BW = ");
07681       BaseException::AddInt(lbw);
07682    }
07683    if (ubw >=0)
07684    {
07685       BaseException::AddMessage("; upper BW = ");
07686       BaseException::AddInt(ubw);
07687    }
07688    BaseException::AddMessage("\n");
07689 }
07690 
07691 NPDException::NPDException(const GeneralMatrix& A)
07692    : Runtime_error()
07693 {
07694    Select = BaseException::Select;
07695    AddMessage("detected by Newmat: matrix not positive definite\n\n");
07696    MatrixDetails(A);
07697    //Tracer::AddTrace();
07698 }
07699 
07700 SingularException::SingularException(const GeneralMatrix& A)
07701    : Runtime_error()
07702 {
07703    Select = BaseException::Select;
07704    AddMessage("detected by Newmat: matrix is singular\n\n");
07705    MatrixDetails(A);
07706    //Tracer::AddTrace();
07707 }
07708 
07709 ConvergenceException::ConvergenceException(const GeneralMatrix& A)
07710    : Runtime_error()
07711 {
07712    Select = BaseException::Select;
07713    AddMessage("detected by Newmat: process fails to converge\n\n");
07714    MatrixDetails(A);
07715    //Tracer::AddTrace();
07716 }
07717 
07718 ConvergenceException::ConvergenceException(const char* c) : Runtime_error()
07719 {
07720    Select = BaseException::Select;
07721    AddMessage("detected by Newmat: ");
07722    AddMessage(c); AddMessage("\n\n");
07723    //if (c) Tracer::AddTrace();
07724 }
07725 
07726 OverflowException::OverflowException(const char* c) : Runtime_error()
07727 {
07728    Select = BaseException::Select;
07729    AddMessage("detected by Newmat: ");
07730    AddMessage(c); AddMessage("\n\n");
07731    //if (c) Tracer::AddTrace();
07732 }
07733 
07734 ProgramException::ProgramException(const char* c) : Logic_error()
07735 {
07736    Select = BaseException::Select;
07737    AddMessage("detected by Newmat: ");
07738    AddMessage(c); AddMessage("\n\n");
07739    //if (c) Tracer::AddTrace();
07740 }
07741 
07742 ProgramException::ProgramException(const char* c, const GeneralMatrix& A)
07743    : Logic_error()
07744 {
07745    Select = BaseException::Select;
07746    AddMessage("detected by Newmat: ");
07747    AddMessage(c); AddMessage("\n\n");
07748    MatrixDetails(A);
07749    //if (c) Tracer::AddTrace();
07750 }
07751 
07752 ProgramException::ProgramException(const char* c, const GeneralMatrix& A,
07753    const GeneralMatrix& B) : Logic_error()
07754 {
07755    Select = BaseException::Select;
07756    AddMessage("detected by Newmat: ");
07757    AddMessage(c); AddMessage("\n\n");
07758    MatrixDetails(A); MatrixDetails(B);
07759    //if (c) Tracer::AddTrace();
07760 }
07761 
07762 ProgramException::ProgramException(const char* c, MatrixType a, MatrixType b)
07763    : Logic_error()
07764 {
07765    Select = BaseException::Select;
07766    AddMessage("detected by Newmat: ");
07767    AddMessage(c); AddMessage("\nMatrixTypes = ");
07768    AddMessage(a.Value()); AddMessage("; ");
07769    AddMessage(b.Value()); AddMessage("\n\n");
07770    //if (c) Tracer::AddTrace();
07771 }
07772 
07773 VectorException::VectorException() : Logic_error()
07774 {
07775    Select = BaseException::Select;
07776    AddMessage("detected by Newmat: cannot convert matrix to vector\n\n");
07777    //Tracer::AddTrace();
07778 }
07779 
07780 VectorException::VectorException(const GeneralMatrix& A)
07781    : Logic_error()
07782 {
07783    Select = BaseException::Select;
07784    AddMessage("detected by Newmat: cannot convert matrix to vector\n\n");
07785    MatrixDetails(A);
07786    //Tracer::AddTrace();
07787 }
07788 
07789 NotSquareException::NotSquareException(const GeneralMatrix& A)
07790    : Logic_error()
07791 {
07792    Select = BaseException::Select;
07793    AddMessage("detected by Newmat: matrix is not square\n\n");
07794    MatrixDetails(A);
07795    //Tracer::AddTrace();
07796 }
07797 
07798 NotSquareException::NotSquareException()
07799    : Logic_error()
07800 {
07801    Select = BaseException::Select;
07802    AddMessage("detected by Newmat: matrix is not square\n\n");
07803    //Tracer::AddTrace();
07804 }
07805 
07806 SubMatrixDimensionException::SubMatrixDimensionException()
07807    : Logic_error()
07808 {
07809    Select = BaseException::Select;
07810    AddMessage("detected by Newmat: incompatible submatrix dimension\n\n");
07811    //Tracer::AddTrace();
07812 }
07813 
07814 IncompatibleDimensionsException::IncompatibleDimensionsException()
07815    : Logic_error()
07816 {
07817    Select = BaseException::Select;
07818    AddMessage("detected by Newmat: incompatible dimensions\n\n");
07819    //Tracer::AddTrace();
07820 }
07821 
07822 IncompatibleDimensionsException::IncompatibleDimensionsException
07823    (const GeneralMatrix& A, const GeneralMatrix& B)
07824       : Logic_error()
07825 {
07826    Select = BaseException::Select;
07827    AddMessage("detected by Newmat: incompatible dimensions\n\n");
07828    MatrixDetails(A); MatrixDetails(B);
07829    //Tracer::AddTrace();
07830 }
07831 
07832 IncompatibleDimensionsException::IncompatibleDimensionsException
07833    (const GeneralMatrix& A)
07834       : Logic_error()
07835 {
07836    Select = BaseException::Select;
07837    AddMessage("detected by Newmat: incompatible dimensions\n\n");
07838    MatrixDetails(A);
07839    //Tracer::AddTrace();
07840 }
07841 
07842 NotDefinedException::NotDefinedException(const char* op, const char* matrix)
07843    : Logic_error()
07844 {
07845    Select = BaseException::Select;
07846    AddMessage("detected by Newmat: ");
07847    AddMessage(op);
07848    AddMessage(" not defined for ");
07849    AddMessage(matrix);
07850    AddMessage("\n\n");
07851    //Tracer::AddTrace();
07852 }
07853 
07854 CannotBuildException::CannotBuildException(const char* matrix)
07855    : Logic_error()
07856 {
07857    Select = BaseException::Select;
07858    AddMessage("detected by Newmat: cannot build matrix type ");
07859    AddMessage(matrix); AddMessage("\n\n");
07860    //Tracer::AddTrace();
07861 }
07862 
07863 IndexException::IndexException(int i, const GeneralMatrix& A)
07864    : Logic_error()
07865 {
07866    Select = BaseException::Select;
07867    AddMessage("detected by Newmat: index error: requested index = ");
07868    AddInt(i); AddMessage("\n\n");
07869    MatrixDetails(A);
07870    //Tracer::AddTrace();
07871 }
07872 
07873 IndexException::IndexException(int i, int j, const GeneralMatrix& A)
07874    : Logic_error()
07875 {
07876    Select = BaseException::Select;
07877    AddMessage("detected by Newmat: index error: requested indices = ");
07878    AddInt(i); AddMessage(", "); AddInt(j);
07879    AddMessage("\n\n");
07880    MatrixDetails(A);
07881    //Tracer::AddTrace();
07882 }
07883 
07884 
07885 IndexException::IndexException(int i, const GeneralMatrix& A, bool)
07886    : Logic_error()
07887 {
07888    Select = BaseException::Select;
07889    AddMessage("detected by Newmat: element error: requested index (wrt 0) = ");
07890    AddInt(i);
07891    AddMessage("\n\n");
07892    MatrixDetails(A);
07893    //Tracer::AddTrace();
07894 }
07895 
07896 IndexException::IndexException(int i, int j, const GeneralMatrix& A, bool)
07897    : Logic_error()
07898 {
07899    Select = BaseException::Select;
07900    AddMessage(
07901       "detected by Newmat: element error: requested indices (wrt 0) = ");
07902    AddInt(i); AddMessage(", "); AddInt(j);
07903    AddMessage("\n\n");
07904    MatrixDetails(A);
07905    //Tracer::AddTrace();
07906 }
07907 
07908 InternalException::InternalException(const char* c) : Logic_error()
07909 {
07910    Select = BaseException::Select;
07911    AddMessage("internal error detected by Newmat: please inform author\n");
07912    AddMessage(c); AddMessage("\n\n");
07913    //Tracer::AddTrace();
07914 }
07915 
07916 
07917 
07918 
07919 /************************* ExeCounter functions *****************************/
07920 
07921 #ifdef DO_REPORT
07922 
07923 int ExeCounter::nreports;                      // will be set to zero
07924 
07925 ExeCounter::ExeCounter(int xl, int xf) : line(xl), fileid(xf), nexe(0) {}
07926 
07927 ExeCounter::~ExeCounter()
07928 {
07929    nreports++;
07930    cout << "REPORT  " << setw(6) << nreports << "  "
07931       << setw(6) << fileid << "  " << setw(6) << line
07932       << "  " << setw(6) << nexe << "\n";
07933 }
07934 
07935 #endif
07936 
07937 /**************************** error handler *******************************/
07938 
07939 void MatrixErrorNoSpace(const void* v) { if (!v) Throw(Bad_alloc()); }
07940 // throw exception if v is null
07941 
07942 
07943 
07944 
07945 /************************* miscellanous errors ***************************/
07946 
07947 
07948 void CroutMatrix::GetRow(MatrixRowCol&)
07949    { Throw(NotDefinedException("GetRow","Crout")); }
07950 void CroutMatrix::GetCol(MatrixRowCol&)
07951    { Throw(NotDefinedException("GetCol","Crout")); }
07952 void BandLUMatrix::GetRow(MatrixRowCol&)
07953    { Throw(NotDefinedException("GetRow","BandLUMatrix")); }
07954 void BandLUMatrix::GetCol(MatrixRowCol&)
07955    { Throw(NotDefinedException("GetCol","BandLUMatrix")); }
07956 void BaseMatrix::IEQND() const
07957    { Throw(NotDefinedException("inequalities", "matrices")); }
07958 
07959 
07960 #ifdef use_namespace
07961 }
07962 #endif
07963 
07966 
07975 
07976 // Copyright (C) 1993,4,6: R B Davies
07977 
07978 
07979 #define WANT_STREAM                    // include.h will get stream fns
07980 #define WANT_STRING
07981 
07982 
07983 #ifdef use_namespace
07984 namespace RBD_COMMON {
07985 #endif
07986 
07987 
07988 //#define REG_DEREG                    // for print out uses of new/delete
07989 //#define CLEAN_LIST                   // to print entries being added to
07990                                        // or deleted from cleanup list
07991 
07992 #ifdef SimulateExceptions
07993 
07994 void Throw()
07995 {
07996    for (Janitor* jan = JumpBase::jl->janitor; jan; jan = jan->NextJanitor)
07997       jan->CleanUp();
07998    JumpItem* jx = JumpBase::jl->ji;    // previous jumpbase;
07999    if ( !jx ) { Terminate(); }         // jl was initial JumpItem
08000    JumpBase::jl = jx;                  // drop down a level; cannot be in front
08001                                        // of previous line
08002    Tracer::last = JumpBase::jl->trace;
08003    longjmp(JumpBase::jl->env, 1);
08004 }
08005 
08006 #endif                                 // end of simulate exceptions
08007 
08008 
08009 unsigned long BaseException::Select;
08010 char* BaseException::what_error;
08011 int BaseException::SoFar;
08012 int BaseException::LastOne;
08013 
08014 BaseException::BaseException(const char* a_what)
08015 {
08016    Select++; SoFar = 0;
08017    if (!what_error)                   // make space for exception message
08018    {
08019       LastOne = 511;
08020       what_error = new char[512];
08021       if (!what_error)                // fail to make space
08022       {
08023          LastOne = 0;
08024          what_error = (char *)"No heap space for exception message\n";
08025       }
08026    }
08027    AddMessage("\n\nAn exception has been thrown\n");
08028    AddMessage(a_what);
08029    //if (a_what) Tracer::AddTrace();
08030 }
08031 
08032 void BaseException::AddMessage(const char* a_what)
08033 {
08034    if (a_what)
08035    {
08036       int l = (int) strlen(a_what); int r = LastOne - SoFar;
08037       if (l < r) { strcpy(what_error+SoFar, a_what); SoFar += l; }
08038       else if (r > 0)
08039       {
08040          strncpy(what_error+SoFar, a_what, r);
08041          what_error[LastOne] = 0;
08042          SoFar = LastOne;
08043       }
08044    }
08045 }
08046 
08047 void BaseException::AddInt(int value)
08048 {
08049    bool negative;
08050    if (value == 0) { AddMessage("0"); return; }
08051    else if (value < 0) { value = -value; negative = true; }
08052    else negative = false;
08053    int n = 0; int v = value;        // how many digits will we need?
08054    while (v > 0) { v /= 10; n++; }
08055    if (negative) n++;
08056    if (LastOne-SoFar < n) { AddMessage("***"); return; }
08057 
08058    SoFar += n; n = SoFar; what_error[n] = 0;
08059    while (value > 0)
08060    {
08061       int nv = value / 10; int rm = value - nv * 10;  value = nv;
08062       what_error[--n] = (char)(rm + '0');
08063    }
08064    if (negative) what_error[--n] = '-';
08065    return;
08066 }
08067 
08068 void Tracer::PrintTrace()
08069 {
08070    cout << "\n";
08071    for (Tracer* et = last; et; et=et->previous)
08072       cout << "  * " << et->entry << "\n";
08073 }
08074 
08075 void Tracer::AddTrace()
08076 {
08077    if (last)
08078    {
08079       BaseException::AddMessage("Trace: ");
08080       BaseException::AddMessage(last->entry);
08081       for (Tracer* et = last->previous; et; et=et->previous)
08082       {
08083          if(et)
08084          {
08085            BaseException::AddMessage("; ");
08086            BaseException::AddMessage(et->entry);
08087          }
08088       }
08089       BaseException::AddMessage(".\n");
08090    }
08091 }
08092 
08093 #ifdef SimulateExceptions
08094 
08095 
08096 Janitor::Janitor()
08097 {
08098    if (do_not_link)
08099    {
08100       do_not_link = false; NextJanitor = 0; OnStack = false;
08101 #ifdef CLEAN_LIST
08102       cout << "Not added to clean-list " << (unsigned long)this << "\n";
08103 #endif
08104    }
08105    else
08106    {
08107       OnStack = true;
08108 #ifdef CLEAN_LIST
08109       cout << "Add to       clean-list " << (unsigned long)this << "\n";
08110 #endif
08111       NextJanitor = JumpBase::jl->janitor; JumpBase::jl->janitor=this;
08112    }
08113 }
08114 
08115 Janitor::~Janitor()
08116 {
08117    // expect the item to be deleted to be first on list
08118    // but must be prepared to search list
08119    if (OnStack)
08120    {
08121 #ifdef CLEAN_LIST
08122       cout << "Delete from  clean-list " << (unsigned long)this << "\n";
08123 #endif
08124       Janitor* lastjan = JumpBase::jl->janitor;
08125       if (this == lastjan) JumpBase::jl->janitor = NextJanitor;
08126       else
08127       {
08128          for (Janitor* jan = lastjan->NextJanitor; jan;
08129             jan = lastjan->NextJanitor)
08130          {
08131             if (jan==this)
08132                { lastjan->NextJanitor = jan->NextJanitor; return; }
08133             lastjan=jan;
08134          }
08135 
08136          Throw(BaseException(
08137 "Cannot resolve memory linked list\nSee notes in myexcept.cpp for details\n"
08138          ));
08139 
08140 
08141 // This message occurs when a call to ~Janitor() occurs, apparently
08142 // without a corresponding call to Janitor(). This could happen if my
08143 // way of deciding whether a constructor is being called by new
08144 // fails.
08145 
08146 // It may happen if you are using my simulated exceptions and also have
08147 // your compiler s exceptions turned on.
08148 
08149 // It can also happen if you have a class derived from Janitor
08150 // which does not include a copy constructor [ eg X(const &X) ].
08151 // Possibly also if delete is applied an object on the stack (ie not
08152 // called by new). Otherwise, it is a bug in myexcept or your compiler.
08153 // If you do not #define TEMPS_DESTROYED_QUICKLY you will get this
08154 // error with Microsoft C 7.0. There are probably situations where
08155 // you will get this when you do define TEMPS_DESTROYED_QUICKLY. This
08156 // is a bug in MSC. Beware of "operator" statements for defining
08157 // conversions; particularly for converting from a Base class to a
08158 // Derived class.
08159 
08160 // You may get away with simply deleting this error message and Throw
08161 // statement if you can not find a better way of overcoming the
08162 // problem. In any case please tell me if you get this error message,
08163 // particularly for compilers apart from Microsoft C 7.0.
08164 
08165 
08166       }
08167    }
08168 }
08169 
08170 JumpItem* JumpBase::jl;              // will be set to zero
08171 jmp_buf JumpBase::env;
08172 bool Janitor::do_not_link;           // will be set to false
08173 
08174 
08175 int JanitorInitializer::ref_count;
08176 
08177 JanitorInitializer::JanitorInitializer()
08178 {
08179    if (ref_count++ == 0) new JumpItem;
08180                                     // need JumpItem at head of list
08181 }
08182 
08183 #endif                              // end of SimulateExceptions
08184 
08185 Tracer* Tracer::last;               // will be set to zero
08186 
08187 
08188 void Terminate()
08189 {
08190    cout << "\n\nThere has been an exception with no handler - exiting";
08191    const char* what = BaseException::what();
08192    if (what) cout << what << "\n";
08193    exit(1);
08194 }
08195 
08196 
08197 
08198 #ifdef DO_FREE_CHECK
08199 // Routines for tracing whether new and delete calls are balanced
08200 
08201 FreeCheckLink::FreeCheckLink() : next(FreeCheck::next)
08202    { FreeCheck::next = this; }
08203 
08204 FCLClass::FCLClass(void* t, char* name) : ClassName(name) { ClassStore=t; }
08205 
08206 FCLRealArray::FCLRealArray(void* t, char* o, int s)
08207   : Operation(o), size(s) { ClassStore=t; }
08208 
08209 FCLIntArray::FCLIntArray(void* t, char* o, int s)
08210   : Operation(o), size(s) { ClassStore=t; }
08211 
08212 FreeCheckLink* FreeCheck::next;
08213 int FreeCheck::BadDelete;
08214 
08215 void FCLClass::Report()
08216 { cout << "   " << ClassName << "   " << (unsigned long)ClassStore << "\n"; }
08217 
08218 void FCLRealArray::Report()
08219 {
08220    cout << "   " << Operation << "   " << (unsigned long)ClassStore <<
08221       "   " << size << "\n";
08222 }
08223 
08224 void FCLIntArray::Report()
08225 {
08226    cout << "   " << Operation << "   " << (unsigned long)ClassStore <<
08227       "   " << size << "\n";
08228 }
08229 
08230 void FreeCheck::Register(void* t, char* name)
08231 {
08232    FCLClass* f = new FCLClass(t,name);
08233    if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
08234 #ifdef REG_DEREG
08235    cout << "Registering   " << name << "   " << (unsigned long)t << "\n";
08236 #endif
08237 }
08238 
08239 void FreeCheck::RegisterR(void* t, char* o, int s)
08240 {
08241    FCLRealArray* f = new FCLRealArray(t,o,s);
08242    if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
08243 #ifdef REG_DEREG
08244    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
08245 #endif
08246 }
08247 
08248 void FreeCheck::RegisterI(void* t, char* o, int s)
08249 {
08250    FCLIntArray* f = new FCLIntArray(t,o,s);
08251    if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
08252 #ifdef REG_DEREG
08253    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
08254 #endif
08255 }
08256 
08257 void FreeCheck::DeRegister(void* t, char* name)
08258 {
08259    FreeCheckLink* last = 0;
08260 #ifdef REG_DEREG
08261    cout << "Deregistering " << name << "   " << (unsigned long)t << "\n";
08262 #endif
08263    for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
08264    {
08265       if (fcl->ClassStore==t)
08266       {
08267          if (last) last->next = fcl->next; else next = fcl->next;
08268          delete fcl; return;
08269       }
08270       last = fcl;
08271    }
08272    cout << "\nRequest to delete non-existent object of class and location:\n";
08273    cout << "   " << name << "   " << (unsigned long)t << "\n";
08274    BadDelete++;
08275    Tracer::PrintTrace();
08276    cout << "\n";
08277 }
08278 
08279 void FreeCheck::DeRegisterR(void* t, char* o, int s)
08280 {
08281    FreeCheckLink* last = 0;
08282 #ifdef REG_DEREG
08283    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
08284 #endif
08285    for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
08286    {
08287       if (fcl->ClassStore==t)
08288       {
08289          if (last) last->next = fcl->next; else next = fcl->next;
08290          if (s >= 0 && ((FCLRealArray*)fcl)->size != s)
08291          {
08292             cout << "\nArray sizes do not agree:\n";
08293             cout << "   " << o << "   " << (unsigned long)t
08294                << "   " << ((FCLRealArray*)fcl)->size << "   " << s << "\n";
08295             Tracer::PrintTrace();
08296             cout << "\n";
08297          }
08298          delete fcl; return;
08299       }
08300       last = fcl;
08301    }
08302    cout << "\nRequest to delete non-existent real array:\n";
08303    cout << "   " << o << "   " << (unsigned long)t << "   " << s << "\n";
08304    BadDelete++;
08305    Tracer::PrintTrace();
08306    cout << "\n";
08307 }
08308 
08309 void FreeCheck::DeRegisterI(void* t, char* o, int s)
08310 {
08311    FreeCheckLink* last = 0;
08312 #ifdef REG_DEREG
08313    cout << o << "   " << s << "   " << (unsigned long)t << "\n";
08314 #endif
08315    for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
08316    {
08317       if (fcl->ClassStore==t)
08318       {
08319          if (last) last->next = fcl->next; else next = fcl->next;
08320          if (s >= 0 && ((FCLIntArray*)fcl)->size != s)
08321          {
08322             cout << "\nArray sizes do not agree:\n";
08323             cout << "   " << o << "   " << (unsigned long)t
08324                << "   " << ((FCLIntArray*)fcl)->size << "   " << s << "\n";
08325             Tracer::PrintTrace();
08326             cout << "\n";
08327          }
08328          delete fcl; return;
08329       }
08330       last = fcl;
08331    }
08332    cout << "\nRequest to delete non-existent int array:\n";
08333    cout << "   " << o << "   " << (unsigned long)t << "   " << s << "\n";
08334    BadDelete++;
08335    Tracer::PrintTrace();
08336    cout << "\n";
08337 }
08338 
08339 void FreeCheck::Status()
08340 {
08341    if (next)
08342    {
08343       cout << "\nObjects of the following classes remain undeleted:\n";
08344       for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next) fcl->Report();
08345       cout << "\n";
08346    }
08347    else cout << "\nNo objects remain undeleted\n\n";
08348    if (BadDelete)
08349    {
08350       cout << "\nThere were " << BadDelete << 
08351          " requests to delete non-existent items\n\n";
08352    }
08353 }
08354 
08355 #endif                            // end of DO_FREE_CHECK
08356 
08357 // derived exception bodies
08358 
08359 Logic_error::Logic_error(const char* a_what) : BaseException()
08360 {
08361    Select = BaseException::Select;
08362    AddMessage("Logic error:- "); AddMessage(a_what);
08363    if (a_what) Tracer::AddTrace();
08364 }
08365 
08366 Runtime_error::Runtime_error(const char* a_what)
08367    : BaseException()
08368 {
08369    Select = BaseException::Select;
08370    AddMessage("Runtime error:- "); AddMessage(a_what);
08371    if (a_what) Tracer::AddTrace();
08372 }
08373 
08374 Domain_error::Domain_error(const char* a_what) : Logic_error()
08375 {
08376    Select = BaseException::Select;
08377    AddMessage("domain error\n"); AddMessage(a_what);
08378    if (a_what) Tracer::AddTrace();
08379 }
08380 
08381 Invalid_argument::Invalid_argument(const char* a_what) : Logic_error()
08382 {
08383    Select = BaseException::Select;
08384    AddMessage("invalid argument\n"); AddMessage(a_what);
08385    if (a_what) Tracer::AddTrace();
08386 }
08387 
08388 Length_error::Length_error(const char* a_what) : Logic_error()
08389 {
08390    Select = BaseException::Select;
08391    AddMessage("length error\n"); AddMessage(a_what);
08392    if (a_what) Tracer::AddTrace();
08393 }
08394 
08395 Out_of_range::Out_of_range(const char* a_what) : Logic_error()
08396 {
08397    Select = BaseException::Select;
08398    AddMessage("out of range\n"); AddMessage(a_what);
08399    if (a_what) Tracer::AddTrace();
08400 }
08401 
08402 //Bad_cast::Bad_cast(const char* a_what) : Logic_error()
08403 //{
08404 //   Select = BaseException::Select;
08405 //   AddMessage("bad cast\n"); AddMessage(a_what);
08406 //   if (a_what) Tracer::AddTrace();
08407 //}
08408 
08409 //Bad_typeid::Bad_typeid(const char* a_what) : Logic_error()
08410 //{
08411 //   Select = BaseException::Select;
08412 //   AddMessage("bad type id.\n"); AddMessage(a_what);
08413 //   if (a_what) Tracer::AddTrace();
08414 //}
08415 
08416 Range_error::Range_error(const char* a_what) : Runtime_error()
08417 {
08418    Select = BaseException::Select;
08419    AddMessage("range error\n"); AddMessage(a_what);
08420    if (a_what) Tracer::AddTrace();
08421 }
08422 
08423 Overflow_error::Overflow_error(const char* a_what) : Runtime_error()
08424 {
08425    Select = BaseException::Select;
08426    AddMessage("overflow error\n"); AddMessage(a_what);
08427    if (a_what) Tracer::AddTrace();
08428 }
08429 
08430 Bad_alloc::Bad_alloc(const char* a_what) : BaseException()
08431 {
08432    Select = BaseException::Select;
08433    AddMessage("bad allocation\n"); AddMessage(a_what);
08434    if (a_what) Tracer::AddTrace();
08435 }
08436 
08437 
08438 
08439 
08440 unsigned long Logic_error::Select;
08441 unsigned long Runtime_error::Select;
08442 unsigned long Domain_error::Select;
08443 unsigned long Invalid_argument::Select;
08444 unsigned long Length_error::Select;
08445 unsigned long Out_of_range::Select;
08446 //unsigned long Bad_cast::Select;
08447 //unsigned long Bad_typeid::Select;
08448 unsigned long Range_error::Select;
08449 unsigned long Overflow_error::Select;
08450 unsigned long Bad_alloc::Select;
08451 
08452 #ifdef use_namespace
08453 }
08454 #endif
08455 
08456 
08458 
08461 
08464 
08465 
08466 // Copyright (C) 1991,2,3,4,9: R B Davies
08467 
08468 #define WANT_MATH                    // include.h will get math fns
08469 
08470 //#define WANT_STREAM
08471 
08472 
08473 #ifdef use_namespace
08474 namespace NEWMAT {
08475 #endif
08476 
08477 
08478 
08479 #ifdef DO_REPORT
08480 #define REPORT { static ExeCounter ExeCount(__LINE__,10); ++ExeCount; }
08481 #else
08482 #define REPORT {}
08483 #endif
08484 
08485 static inline int my_min(int x, int y) { return x < y ? x : y; }
08486 static inline int my_max(int x, int y) { return x > y ? x : y; }
08487 
08488 
08489 BandMatrix::BandMatrix(const BaseMatrix& M)
08490 {
08491    REPORT // CheckConversion(M);
08492    // MatrixConversionCheck mcc;
08493    GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::BM);
08494    GetMatrix(gmx); CornerClear();
08495 }
08496 
08497 void BandMatrix::SetParameters(const GeneralMatrix* gmx)
08498 {
08499    REPORT
08500    MatrixBandWidth bw = gmx->bandwidth();
08501    lower_val = bw.lower_val; upper_val = bw.upper_val;
08502 }
08503 
08504 void BandMatrix::resize(int n, int lb, int ub)
08505 {
08506    REPORT
08507    Tracer tr("BandMatrix::resize");
08508    if (lb<0 || ub<0) Throw(ProgramException("Undefined bandwidth"));
08509    lower_val = (lb<=n) ? lb : n-1; upper_val = (ub<=n) ? ub : n-1;
08510    GeneralMatrix::resize(n,n,n*(lower_val+1+upper_val)); CornerClear();
08511 }
08512 
08513 // SimpleAddOK shows when we can add etc two matrices by a simple vector add
08514 // and when we can add one matrix into another
08515 //
08516 // *gm must be the same type as *this
08517 // - return 0 if simple add is OK
08518 // - return 1 if we can add into *gm only
08519 // - return 2 if we can add into *this only
08520 // - return 3 if we can't add either way
08521 //
08522 // For SP this will still be valid if we swap 1 and 2
08523 
08527 
08528 short BandMatrix::SimpleAddOK(const GeneralMatrix* gm)
08529 {
08530    const BandMatrix* bm = (const BandMatrix*)gm;
08531    if (bm->lower_val == lower_val && bm->upper_val == upper_val)
08532       { REPORT return 0; }
08533    else if (bm->lower_val >= lower_val && bm->upper_val >= upper_val)
08534       { REPORT return 1; }
08535    else if (bm->lower_val <= lower_val && bm->upper_val <= upper_val)
08536       { REPORT return 2; }
08537    else { REPORT return 3; }
08538 }
08539 
08543 
08544 short SymmetricBandMatrix::SimpleAddOK(const GeneralMatrix* gm)
08545 {
08546    const SymmetricBandMatrix* bm = (const SymmetricBandMatrix*)gm;
08547    if (bm->lower_val == lower_val) { REPORT return 0; }
08548    else if (bm->lower_val > lower_val) { REPORT return 1; }
08549    else { REPORT return 2; }
08550 }
08551 
08553 void UpperBandMatrix::resize(int n, int lb, int ub)
08554 {
08555    REPORT
08556    if (lb != 0)
08557    {
08558       Tracer tr("UpperBandMatrix::resize");
08559       Throw(ProgramException("UpperBandMatrix with non-zero lower band" ));
08560    }
08561    BandMatrix::resize(n, lb, ub);
08562 }
08563 
08565 void LowerBandMatrix::resize(int n, int lb, int ub)
08566 {
08567    REPORT
08568    if (ub != 0)
08569    {
08570       Tracer tr("LowerBandMatrix::resize");
08571       Throw(ProgramException("LowerBandMatrix with non-zero upper band" ));
08572    }
08573    BandMatrix::resize(n, lb, ub);
08574 }
08575 
08577 void BandMatrix::resize(const GeneralMatrix& A)
08578 {
08579    REPORT
08580    int n = A.Nrows();
08581    if (n != A.Ncols())
08582    {
08583       Tracer tr("BandMatrix::resize(GM)");
08584       Throw(NotSquareException(*this));
08585    }
08586    MatrixBandWidth mbw = A.bandwidth();
08587    resize(n, mbw.Lower(), mbw.Upper());
08588 }
08589 
08590 /*
08591 bool BandMatrix::SameStorageType(const GeneralMatrix& A) const
08592 {
08593    if (type() != A.type()) { REPORT return false; }
08594    REPORT
08595    return bandwidth() == A.bandwidth();
08596 }
08597 
08598 void BandMatrix::resizeForAdd(const GeneralMatrix& A, const GeneralMatrix& B)
08599 {
08600    REPORT
08601    Tracer tr("BandMatrix::resizeForAdd");
08602    MatrixBandWidth A_BW = A.bandwidth(); MatrixBandWidth B_BW = B.bandwidth();
08603    if ((A_BW.Lower() < 0) | (A_BW.Upper() < 0) | (B_BW.Lower() < 0)
08604       | (A_BW.Upper() < 0))
08605          Throw(ProgramException("Can't resize to BandMatrix" ));
08606    // already know A and B are square
08607    resize(A.Nrows(), my_max(A_BW.Lower(), B_BW.Lower()),
08608       my_max(A_BW.Upper(), B_BW.Upper()));
08609 }
08610 
08611 void BandMatrix::resizeForSP(const GeneralMatrix& A, const GeneralMatrix& B)
08612 {
08613    REPORT
08614    Tracer tr("BandMatrix::resizeForSP");
08615    MatrixBandWidth A_BW = A.bandwidth(); MatrixBandWidth B_BW = B.bandwidth();
08616    if ((A_BW.Lower() < 0) | (A_BW.Upper() < 0) | (B_BW.Lower() < 0)
08617       | (A_BW.Upper() < 0))
08618          Throw(ProgramException("Can't resize to BandMatrix" ));
08619    // already know A and B are square
08620    resize(A.Nrows(), my_min(A_BW.Lower(), B_BW.Lower()),
08621       my_min(A_BW.Upper(), B_BW.Upper()));
08622 }
08623 */
08624 
08626 void BandMatrix::operator=(const BaseMatrix& X)
08627 {
08628    REPORT // CheckConversion(X);
08629    // MatrixConversionCheck mcc;
08630    Eq(X,MatrixType::BM); CornerClear();
08631 }
08632 
08634 void BandMatrix::CornerClear() const
08635 {
08636    REPORT
08637    int i = lower_val; Real* s = store; int bw = lower_val + 1 + upper_val;
08638    while (i)
08639       { int j = i--; Real* sj = s; s += bw; while (j--) *sj++ = 0.0; }
08640    i = upper_val; s = store + storage;
08641    while (i)
08642       { int j = i--; Real* sj = s; s -= bw; while (j--) *(--sj) = 0.0; }
08643 }
08644 
08645 MatrixBandWidth MatrixBandWidth::operator+(const MatrixBandWidth& bw) const
08646 {
08647    REPORT
08648    int l = bw.lower_val; int u = bw.upper_val;
08649    l = (lower_val < 0 || l < 0) ? -1 : (lower_val > l) ? lower_val : l;
08650    u = (upper_val < 0 || u < 0) ? -1 : (upper_val > u) ? upper_val : u;
08651    return MatrixBandWidth(l,u);
08652 }
08653 
08654 MatrixBandWidth MatrixBandWidth::operator*(const MatrixBandWidth& bw) const
08655 {
08656    REPORT
08657    int l = bw.lower_val; int u = bw.upper_val;
08658    l = (lower_val < 0 || l < 0) ? -1 : lower_val+l;
08659    u = (upper_val < 0 || u < 0) ? -1 : upper_val+u;
08660    return MatrixBandWidth(l,u);
08661 }
08662 
08663 MatrixBandWidth MatrixBandWidth::minimum(const MatrixBandWidth& bw) const
08664 {
08665    REPORT
08666    int l = bw.lower_val; int u = bw.upper_val;
08667    if ((lower_val >= 0) && ( (l < 0) || (l > lower_val) )) l = lower_val;
08668    if ((upper_val >= 0) && ( (u < 0) || (u > upper_val) )) u = upper_val;
08669    return MatrixBandWidth(l,u);
08670 }
08671 
08672 UpperBandMatrix::UpperBandMatrix(const BaseMatrix& M)
08673 {
08674    REPORT // CheckConversion(M);
08675    // MatrixConversionCheck mcc;
08676    GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::UB);
08677    GetMatrix(gmx); CornerClear();
08678 }
08679 
08680 void UpperBandMatrix::operator=(const BaseMatrix& X)
08681 {
08682    REPORT // CheckConversion(X);
08683    // MatrixConversionCheck mcc;
08684    Eq(X,MatrixType::UB); CornerClear();
08685 }
08686 
08687 LowerBandMatrix::LowerBandMatrix(const BaseMatrix& M)
08688 {
08689    REPORT // CheckConversion(M);
08690    // MatrixConversionCheck mcc;
08691    GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::LB);
08692    GetMatrix(gmx); CornerClear();
08693 }
08694 
08695 void LowerBandMatrix::operator=(const BaseMatrix& X)
08696 {
08697    REPORT // CheckConversion(X);
08698    // MatrixConversionCheck mcc;
08699    Eq(X,MatrixType::LB); CornerClear();
08700 }
08701 
08702 BandLUMatrix::BandLUMatrix(const BaseMatrix& m)
08703 {
08704    REPORT
08705    Tracer tr("BandLUMatrix");
08706    storage2 = 0; store2 = 0; indx = 0; // in event of exception during build
08707    GeneralMatrix* gm = ((BaseMatrix&)m).Evaluate();
08708    if (gm->nrows() != gm->ncols())
08709       { gm->tDelete(); Throw(NotSquareException(*this)); }
08710    if (gm->type() == MatrixType::BC)
08711       { REPORT  ((BandLUMatrix*)gm)->get_aux(*this); GetMatrix(gm); }
08712    else
08713    {
08714       REPORT
08715       BandMatrix* gm1 = (BandMatrix*)(gm->Evaluate(MatrixType::BM));
08716       m1 = gm1->lower_val; m2 = gm1->upper_val;
08717       GetMatrix(gm1);
08718       d = true; sing = false;
08719       indx = new int [nrows_val]; MatrixErrorNoSpace(indx);
08720       MONITOR_INT_NEW("Index (BndLUMat)",nrows_val,indx)
08721       storage2 = nrows_val * m1;
08722       store2 = new Real [storage2]; MatrixErrorNoSpace(store2);
08723       MONITOR_REAL_NEW("Make (BandLUMat)",storage2,store2)
08724       ludcmp();
08725    }
08726 }
08727 
08728 GeneralMatrix* BandLUMatrix::Evaluate(MatrixType mt)
08729 {
08730    if (Compare(this->Type(),mt)) { REPORT return this; }
08731    REPORT
08732    Tracer et("BandLUMatrix::Evaluate");
08733    bool dummy = true;
08734    if (dummy) Throw(ProgramException("Illegal use of BandLUMatrix", *this));
08735    return this;
08736 }
08737 
08738 // could we use SetParameters instead of this
08739 void BandLUMatrix::get_aux(BandLUMatrix& X)
08740 {
08741    X.d = d; X.sing = sing; X.storage2 = storage2; X.m1 = m1; X.m2 = m2;   
08742    if (tag_val == 0 || tag_val == 1) // reuse the array 
08743    {
08744       REPORT
08745       X.indx = indx; indx = 0;
08746       X.store2 = store2; store2 = 0;
08747       d = true; sing = true; storage2 = 0; m1 = 0; m2 = 0;
08748       return;
08749    }
08750    else if (nrows_val == 0)
08751    {
08752       REPORT
08753       indx = 0; store2 = 0; storage2 = 0;
08754       d = true; sing = true; m1 = m2 = 0;
08755       return;
08756    }
08757    else                              // copy the array
08758    {
08759       REPORT
08760       Tracer tr("BandLUMatrix::get_aux");
08761       int *ix = new int [nrows_val]; MatrixErrorNoSpace(ix);
08762       MONITOR_INT_NEW("Index (BLUM::get_aux)", nrows_val, ix)
08763       int n = nrows_val; int* i = ix; int* j = indx;
08764       while(n--) *i++ = *j++;
08765       X.indx = ix;
08766       Real *rx = new Real [storage2]; MatrixErrorNoSpace(indx);
08767       MONITOR_REAL_NEW("Index (BLUM::get_aux)", storage2, rx)
08768       newmat_block_copy(storage2, store2, rx);
08769       X.store2 = rx;
08770    }
08771 }
08772 
08773 BandLUMatrix::BandLUMatrix(const BandLUMatrix& gm) : GeneralMatrix()
08774 {
08775    REPORT
08776    Tracer tr("BandLUMatrix(const BandLUMatrix&)");
08777    ((BandLUMatrix&)gm).get_aux(*this);
08778    GetMatrix(&gm);
08779 }
08780 
08781 void BandLUMatrix::operator=(const BandLUMatrix& gm)
08782 {
08783    if (&gm == this) { REPORT tag_val = -1; return; }
08784    REPORT
08785    delete [] indx; indx = 0;
08786    delete [] store2; store2 = 0; storage2 = 0;
08787    ((BandLUMatrix&)gm).get_aux(*this);
08788    Eq(gm);
08789 }
08790    
08791 
08792 
08793 
08794 
08795 
08796 
08797 
08798 BandLUMatrix::~BandLUMatrix()
08799 {
08800    REPORT
08801    MONITOR_INT_DELETE("Index (BndLUMat)",nrows_val,indx)
08802    MONITOR_REAL_DELETE("Delete (BndLUMt)",storage2,store2)
08803    delete [] indx; delete [] store2;
08804 }
08805 
08806 MatrixType BandLUMatrix::type() const { REPORT return MatrixType::BC; }
08807 
08808 
08809 LogAndSign BandLUMatrix::log_determinant() const
08810 {
08811    REPORT
08812    if (sing) return 0.0;
08813    Real* a = store; int w = m1+1+m2; LogAndSign sum; int i = nrows_val;
08814    // while (i--) { sum *= *a; a += w; }
08815    if (i) for (;;) { sum *= *a; if (!(--i)) break; a += w; }
08816    if (!d) sum.ChangeSign(); return sum;
08817 }
08818 
08819 GeneralMatrix* BandMatrix::MakeSolver()
08820 {
08821    REPORT
08822    GeneralMatrix* gm = new BandLUMatrix(*this);
08823    MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
08824 }
08825 
08826 
08827 void BandLUMatrix::ludcmp()
08828 {
08829    REPORT
08830    Real* a = store2; int i = storage2;
08831    // clear store2 - so unused locations are always zero -
08832    // required by operator==
08833    while (i--) *a++ = 0.0;
08834    a = store;
08835    i = m1; int j = m2; int k; int n = nrows_val; int w = m1 + 1 + m2;
08836    while (i)
08837    {
08838       Real* ai = a + i;
08839       k = ++j; while (k--) *a++ = *ai++;
08840       k = i--; while (k--) *a++ = 0.0;
08841    }
08842 
08843    a = store; int l = m1;
08844    for (k=0; k<n; k++)
08845    {
08846       Real x = *a; i = k; Real* aj = a;
08847       if (l < n) l++;
08848       for (j=k+1; j<l; j++)
08849          { aj += w; if (fabs(x) < fabs(*aj)) { x = *aj; i = j; } }
08850       indx[k] = i;
08851       if (x==0) { sing = true; return; }
08852       if (i!=k)
08853       {
08854          d = !d; Real* ak = a; Real* ai = store + i * w; j = w;
08855          while (j--) { x = *ak; *ak++ = *ai; *ai++ = x; }
08856       }
08857       aj = a + w; Real* m = store2 + m1 * k;
08858       for (j=k+1; j<l; j++)
08859       {
08860          *m++ = x = *aj / *a; i = w; Real* ak = a;
08861          while (--i) { Real* aj1 = aj++; *aj1 = *aj - x * *(++ak); }
08862          *aj++ = 0.0;
08863       }
08864       a += w;
08865    }
08866 }
08867 
08868 void BandLUMatrix::lubksb(Real* B, int mini)
08869 {
08870    REPORT
08871    Tracer tr("BandLUMatrix::lubksb");
08872    if (sing) Throw(SingularException(*this));
08873    int n = nrows_val; int l = m1; int w = m1 + 1 + m2;
08874 
08875    for (int k=0; k<n; k++)
08876    {
08877       int i = indx[k];
08878       if (i!=k) { Real x=B[k]; B[k]=B[i]; B[i]=x; }
08879       if (l<n) l++;
08880       Real* m = store2 + k*m1; Real* b = B+k; Real* bi = b;
08881       for (i=k+1; i<l; i++)  *(++bi) -= *m++ * *b;
08882    }
08883 
08884    l = -m1;
08885    for (int i = n-1; i>=mini; i--)
08886    {
08887       Real* b = B + i; Real* bk = b; Real x = *bk;
08888       Real* a = store + w*i; Real y = *a;
08889       int k = l+m1; while (k--) x -=  *(++a) * *(++bk);
08890       *b = x / y;
08891       if (l < m2) l++;
08892    }
08893 }
08894 
08895 void BandLUMatrix::Solver(MatrixColX& mcout, const MatrixColX& mcin)
08896 {
08897    REPORT
08898    int i = mcin.skip; Real* el = mcin.data-i; Real* el1=el;
08899    while (i--) *el++ = 0.0;
08900    el += mcin.storage; i = nrows_val - mcin.skip - mcin.storage;
08901    while (i--) *el++ = 0.0;
08902    lubksb(el1, mcout.skip);
08903 }
08904 
08905 // Do we need check for entirely zero output?
08906 
08907 
08908 void UpperBandMatrix::Solver(MatrixColX& mcout,
08909    const MatrixColX& mcin)
08910 {
08911    REPORT
08912    int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
08913    while (i-- > 0) *elx++ = 0.0;
08914    int nr = mcin.skip+mcin.storage;
08915    elx = mcin.data+mcin.storage; Real* el = elx;
08916    int j = mcout.skip+mcout.storage-nr; i = nr-mcout.skip;
08917    while (j-- > 0) *elx++ = 0.0;
08918 
08919    Real* Ael = store + (upper_val+1)*(i-1)+1; j = 0;
08920    if (i > 0) for(;;)
08921    {
08922       elx = el; Real sum = 0.0; int jx = j;
08923       while (jx--) sum += *(--Ael) * *(--elx);
08924       elx--; *elx = (*elx - sum) / *(--Ael);
08925       if (--i <= 0) break;
08926       if (j<upper_val) Ael -= upper_val - (++j); else el--;
08927    }
08928 }
08929 
08930 void LowerBandMatrix::Solver(MatrixColX& mcout,
08931    const MatrixColX& mcin)
08932 {
08933    REPORT
08934    int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
08935    while (i-- > 0) *elx++ = 0.0;
08936    int nc = mcin.skip; i = nc+mcin.storage; elx = mcin.data+mcin.storage;
08937    int nr = mcout.skip+mcout.storage; int j = nr-i; i = nr-nc;
08938    while (j-- > 0) *elx++ = 0.0;
08939 
08940    Real* el = mcin.data;
08941    Real* Ael = store + (lower_val+1)*nc + lower_val;
08942    j = 0;
08943    if (i > 0) for(;;)
08944    {
08945       elx = el; Real sum = 0.0; int jx = j;
08946       while (jx--) sum += *Ael++ * *elx++;
08947       *elx = (*elx - sum) / *Ael++;
08948       if (--i <= 0) break;
08949       if (j<lower_val) Ael += lower_val - (++j); else el++;
08950    }
08951 }
08952 
08953 
08954 LogAndSign BandMatrix::log_determinant() const
08955 {
08956    REPORT
08957    BandLUMatrix C(*this); return C.log_determinant();
08958 }
08959 
08960 LogAndSign LowerBandMatrix::log_determinant() const
08961 {
08962    REPORT
08963    int i = nrows_val; LogAndSign sum;
08964    Real* s = store + lower_val; int j = lower_val + 1;
08965 //   while (i--) { sum *= *s; s += j; }
08966    if (i) for (;;) { sum *= *s; if (!(--i)) break; s += j; }
08967    ((GeneralMatrix&)*this).tDelete(); return sum;
08968 }
08969 
08970 LogAndSign UpperBandMatrix::log_determinant() const
08971 {
08972    REPORT
08973    int i = nrows_val; LogAndSign sum; Real* s = store; int j = upper_val + 1;
08974 //   while (i--) { sum *= *s; s += j; }
08975    if (i) for (;;) { sum *= *s; if (!(--i)) break; s += j; }
08976    ((GeneralMatrix&)*this).tDelete(); return sum;
08977 }
08978 
08979 GeneralMatrix* SymmetricBandMatrix::MakeSolver()
08980 {
08981    REPORT
08982    GeneralMatrix* gm = new BandLUMatrix(*this);
08983    MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
08984 }
08985 
08986 SymmetricBandMatrix::SymmetricBandMatrix(const BaseMatrix& M)
08987 {
08988    REPORT  // CheckConversion(M);
08989    // MatrixConversionCheck mcc;
08990    GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::SB);
08991    GetMatrix(gmx);
08992 }
08993 
08994 GeneralMatrix* SymmetricBandMatrix::Transpose(TransposedMatrix*, MatrixType mt)
08995 { REPORT  return Evaluate(mt); }
08996 
08997 LogAndSign SymmetricBandMatrix::log_determinant() const
08998 {
08999    REPORT
09000    BandLUMatrix C(*this); return C.log_determinant();
09001 }
09002 
09003 void SymmetricBandMatrix::SetParameters(const GeneralMatrix* gmx)
09004 { REPORT lower_val = gmx->bandwidth().lower_val; }
09005 
09006 void SymmetricBandMatrix::resize(int n, int lb)
09007 {
09008    REPORT
09009    Tracer tr("SymmetricBandMatrix::resize");
09010    if (lb<0) Throw(ProgramException("Undefined bandwidth"));
09011    lower_val = (lb<=n) ? lb : n-1;
09012    GeneralMatrix::resize(n,n,n*(lower_val+1));
09013 }
09014 
09015 void SymmetricBandMatrix::resize(const GeneralMatrix& A)
09016 {
09017    REPORT
09018    int n = A.Nrows();
09019    if (n != A.Ncols())
09020    {
09021       Tracer tr("SymmetricBandMatrix::resize(GM)");
09022       Throw(NotSquareException(*this));
09023    }
09024    MatrixBandWidth mbw = A.bandwidth(); int b = mbw.Lower();
09025    if (b != mbw.Upper())
09026    {
09027       Tracer tr("SymmetricBandMatrix::resize(GM)");
09028       Throw(ProgramException("Upper and lower band-widths not equal"));
09029    }
09030    resize(n, b);
09031 }
09032 /*
09033 bool SymmetricBandMatrix::SameStorageType(const GeneralMatrix& A) const
09034 {
09035    if (type() != A.type()) { REPORT return false; }
09036    REPORT
09037    return bandwidth() == A.bandwidth();
09038 }
09039 
09040 void SymmetricBandMatrix::resizeForAdd(const GeneralMatrix& A,
09041    const GeneralMatrix& B)
09042 {
09043    REPORT
09044    Tracer tr("SymmetricBandMatrix::resizeForAdd");
09045    MatrixBandWidth A_BW = A.bandwidth(); MatrixBandWidth B_BW = B.bandwidth();
09046    if ((A_BW.Lower() < 0) | (B_BW.Lower() < 0))
09047          Throw(ProgramException("Can't resize to SymmetricBandMatrix" ));
09048    // already know A and B are square
09049    resize(A.Nrows(), my_max(A_BW.Lower(), B_BW.Lower()));
09050 }
09051 
09052 void SymmetricBandMatrix::resizeForSP(const GeneralMatrix& A,
09053    const GeneralMatrix& B)
09054 {
09055    REPORT
09056    Tracer tr("SymmetricBandMatrix::resizeForSP");
09057    MatrixBandWidth A_BW = A.bandwidth(); MatrixBandWidth B_BW = B.bandwidth();
09058    if ((A_BW.Lower() < 0) | (B_BW.Lower() < 0))
09059          Throw(ProgramException("Can't resize to SymmetricBandMatrix" ));
09060    // already know A and B are square
09061    resize(A.Nrows(), my_min(A_BW.Lower(), B_BW.Lower()));
09062 }
09063 */
09064 
09065 void SymmetricBandMatrix::operator=(const BaseMatrix& X)
09066 {
09067    REPORT // CheckConversion(X);
09068    // MatrixConversionCheck mcc;
09069    Eq(X,MatrixType::SB);
09070 }
09071 
09072 void SymmetricBandMatrix::CornerClear() const
09073 {
09074    // set unused parts of BandMatrix to zero
09075    REPORT
09076    int i = lower_val; Real* s = store; int bw = lower_val + 1;
09077    if (i) for(;;)
09078    {
09079       int j = i;
09080       Real* sj = s;
09081       while (j--) *sj++ = 0.0;
09082       if (!(--i)) break;
09083       s += bw;
09084    }
09085 }
09086 
09087 MatrixBandWidth SymmetricBandMatrix::bandwidth() const
09088    { REPORT return MatrixBandWidth(lower_val,lower_val); }
09089 
09090 GeneralMatrix* BandMatrix::Image() const
09091 {
09092    REPORT
09093    GeneralMatrix* gm = new BandMatrix(*this); MatrixErrorNoSpace(gm);
09094    return gm;
09095 }
09096 
09097 GeneralMatrix* UpperBandMatrix::Image() const
09098 {
09099    REPORT
09100    GeneralMatrix* gm = new UpperBandMatrix(*this); MatrixErrorNoSpace(gm);
09101    return gm;
09102 }
09103 
09104 GeneralMatrix* LowerBandMatrix::Image() const
09105 {
09106    REPORT
09107    GeneralMatrix* gm = new LowerBandMatrix(*this); MatrixErrorNoSpace(gm);
09108    return gm;
09109 }
09110 
09111 GeneralMatrix* SymmetricBandMatrix::Image() const
09112 {
09113    REPORT
09114    GeneralMatrix* gm = new SymmetricBandMatrix(*this); MatrixErrorNoSpace(gm);
09115    return gm;
09116 }
09117 
09118 GeneralMatrix* BandLUMatrix::Image() const
09119 {
09120    REPORT
09121    GeneralMatrix* gm = new BandLUMatrix(*this); MatrixErrorNoSpace(gm);
09122    return gm;
09123 }
09124 
09125 
09126 Real SymmetricBandMatrix::sum_square() const
09127 {
09128    REPORT
09129    CornerClear();
09130    Real sum1=0.0; Real sum2=0.0; Real* s=store; int i=nrows_val;
09131    int l=lower_val;
09132    while (i--)
09133       { int j = l; while (j--) sum2 += square(*s++); sum1 += square(*s++); }
09134    ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
09135 }
09136 
09137 Real SymmetricBandMatrix::sum_absolute_value() const
09138 {
09139    REPORT
09140    CornerClear();
09141    Real sum1=0.0; Real sum2=0.0; Real* s=store; int i=nrows_val;
09142    int l=lower_val;
09143    while (i--)
09144       { int j = l; while (j--) sum2 += fabs(*s++); sum1 += fabs(*s++); }
09145    ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
09146 }
09147 
09148 Real SymmetricBandMatrix::sum() const
09149 {
09150    REPORT
09151    CornerClear();
09152    Real sum1=0.0; Real sum2=0.0; Real* s=store; int i=nrows_val;
09153    int l=lower_val;
09154    while (i--)
09155       { int j = l; while (j--) sum2 += *s++; sum1 += *s++; }
09156    ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
09157 }
09158 
09159 
09160 
09161 
09162 
09163 #ifdef use_namespace
09164 }
09165 #endif
09166 
09168 
09169 
09172 
09175 
09176 // Copyright (C) 1991,2,3,4: R B Davies
09177 
09178 #ifdef use_namespace
09179 namespace NEWMAT {
09180 #endif
09181 
09182 #ifdef DO_REPORT
09183 #define REPORT { static ExeCounter ExeCount(__LINE__,11); ++ExeCount; }
09184 #else
09185 #define REPORT {}
09186 #endif
09187 
09188 
09189 /****************************** submatrices *********************************/
09190 
09191 GetSubMatrix BaseMatrix::submatrix(int first_row, int last_row, int first_col,
09192    int last_col) const
09193 {
09194    REPORT
09195    Tracer tr("submatrix");
09196    int a = first_row - 1; int b = last_row - first_row + 1;
09197    int c = first_col - 1; int d = last_col - first_col + 1;
09198    if (a<0 || b<0 || c<0 || d<0) Throw(SubMatrixDimensionException());
09199                              // allow zero rows or columns
09200    return GetSubMatrix(this, a, b, c, d, false);
09201 }
09202 
09203 GetSubMatrix BaseMatrix::sym_submatrix(int first_row, int last_row) const
09204 {
09205    REPORT
09206    Tracer tr("sym_submatrix");
09207    int a = first_row - 1; int b = last_row - first_row + 1;
09208    if (a<0 || b<0) Throw(SubMatrixDimensionException());
09209                              // allow zero rows or columns
09210    return GetSubMatrix( this, a, b, a, b, true);
09211 }
09212 
09213 GetSubMatrix BaseMatrix::row(int first_row) const
09214 {
09215    REPORT
09216    Tracer tr("SubMatrix(row)");
09217    int a = first_row - 1;
09218    if (a<0) Throw(SubMatrixDimensionException());
09219    return GetSubMatrix(this, a, 1, 0, -1, false);
09220         }
09221 
09222 GetSubMatrix BaseMatrix::rows(int first_row, int last_row) const
09223 {
09224    REPORT
09225    Tracer tr("SubMatrix(rows)");
09226    int a = first_row - 1; int b = last_row - first_row + 1;
09227    if (a<0 || b<0) Throw(SubMatrixDimensionException());
09228                              // allow zero rows or columns
09229    return GetSubMatrix(this, a, b, 0, -1, false);
09230 }
09231 
09232 GetSubMatrix BaseMatrix::column(int first_col) const
09233 {
09234    REPORT
09235    Tracer tr("SubMatrix(column)");
09236    int c = first_col - 1;
09237    if (c<0) Throw(SubMatrixDimensionException());
09238    return GetSubMatrix(this, 0, -1, c, 1, false);
09239 }
09240 
09241 GetSubMatrix BaseMatrix::columns(int first_col, int last_col) const
09242 {
09243    REPORT
09244    Tracer tr("SubMatrix(columns)");
09245    int c = first_col - 1; int d = last_col - first_col + 1;
09246    if (c<0 || d<0) Throw(SubMatrixDimensionException());
09247                              // allow zero rows or columns
09248    return GetSubMatrix(this, 0, -1, c, d, false);
09249 }
09250 
09251 void GetSubMatrix::SetUpLHS()
09252 {
09253    REPORT
09254    Tracer tr("SubMatrix(LHS)");
09255    const BaseMatrix* bm1 = bm;
09256    GeneralMatrix* gm1 = ((BaseMatrix*&)bm)->Evaluate();
09257    if ((BaseMatrix*)gm1!=bm1)
09258       Throw(ProgramException("Invalid LHS"));
09259    if (row_number < 0) row_number = gm1->Nrows();
09260    if (col_number < 0) col_number = gm1->Ncols();
09261    if (row_skip+row_number > gm1->Nrows()
09262       || col_skip+col_number > gm1->Ncols())
09263          Throw(SubMatrixDimensionException());
09264 }
09265 
09266 void GetSubMatrix::operator<<(const BaseMatrix& bmx)
09267 {
09268    REPORT
09269    Tracer tr("SubMatrix(<<)"); GeneralMatrix* gmx = 0;
09270    Try
09271    {
09272       SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate();
09273       if (row_number != gmx->Nrows() || col_number != gmx->Ncols())
09274          Throw(IncompatibleDimensionsException());
09275       MatrixRow mrx(gmx, LoadOnEntry);
09276       MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
09277                                      // do need LoadOnEntry
09278       MatrixRowCol sub; int i = row_number;
09279       while (i--)
09280       {
09281          mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
09282          sub.Copy(mrx); mr.Next(); mrx.Next();
09283       }
09284       gmx->tDelete();
09285    }
09286 
09287    CatchAll
09288    {
09289       if (gmx) gmx->tDelete();
09290       ReThrow;
09291    }
09292 }
09293 
09294 void GetSubMatrix::operator=(const BaseMatrix& bmx)
09295 {
09296    REPORT
09297    Tracer tr("SubMatrix(=)"); GeneralMatrix* gmx = 0;
09298    // MatrixConversionCheck mcc;         // Check for loss of info
09299    Try
09300    {
09301       SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate();
09302       if (row_number != gmx->Nrows() || col_number != gmx->Ncols())
09303          Throw(IncompatibleDimensionsException());
09304       LoadAndStoreFlag lasf =
09305          (  row_skip == col_skip
09306             && gm->type().is_symmetric()
09307             && gmx->type().is_symmetric() )
09308         ? LoadOnEntry+DirectPart
09309         : LoadOnEntry;
09310       MatrixRow mrx(gmx, lasf);
09311       MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
09312                                      // do need LoadOnEntry
09313       MatrixRowCol sub; int i = row_number;
09314       while (i--)
09315       {
09316          mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
09317          sub.CopyCheck(mrx); mr.Next(); mrx.Next();
09318       }
09319       gmx->tDelete();
09320    }
09321 
09322    CatchAll
09323    {
09324       if (gmx) gmx->tDelete();
09325       ReThrow;
09326    }
09327 }
09328 
09329 void GetSubMatrix::operator<<(const double* r)
09330 {
09331    REPORT
09332    Tracer tr("SubMatrix(<<double*)");
09333    SetUpLHS();
09334    if (row_skip+row_number > gm->Nrows() || col_skip+col_number > gm->Ncols())
09335       Throw(SubMatrixDimensionException());
09336    MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
09337                                   // do need LoadOnEntry
09338    MatrixRowCol sub; int i = row_number;
09339    while (i--)
09340    {
09341       mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
09342       sub.Copy(r); mr.Next();
09343    }
09344 }
09345 
09346 void GetSubMatrix::operator<<(const float* r)
09347 {
09348    REPORT
09349    Tracer tr("SubMatrix(<<float*)");
09350    SetUpLHS();
09351    if (row_skip+row_number > gm->Nrows() || col_skip+col_number > gm->Ncols())
09352       Throw(SubMatrixDimensionException());
09353    MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
09354                                   // do need LoadOnEntry
09355    MatrixRowCol sub; int i = row_number;
09356    while (i--)
09357    {
09358       mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
09359       sub.Copy(r); mr.Next();
09360    }
09361 }
09362 
09363 void GetSubMatrix::operator<<(const int* r)
09364 {
09365    REPORT
09366    Tracer tr("SubMatrix(<<int*)");
09367    SetUpLHS();
09368    if (row_skip+row_number > gm->Nrows() || col_skip+col_number > gm->Ncols())
09369       Throw(SubMatrixDimensionException());
09370    MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
09371                                   // do need LoadOnEntry
09372    MatrixRowCol sub; int i = row_number;
09373    while (i--)
09374    {
09375       mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
09376       sub.Copy(r); mr.Next();
09377    }
09378 }
09379 
09380 void GetSubMatrix::operator=(Real r)
09381 {
09382    REPORT
09383    Tracer tr("SubMatrix(=Real)");
09384    SetUpLHS();
09385    MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
09386                                   // do need LoadOnEntry
09387    MatrixRowCol sub; int i = row_number;
09388    while (i--)
09389    {
09390       mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
09391       sub.Copy(r); mr.Next();
09392    }
09393 }
09394 
09395 void GetSubMatrix::inject(const GeneralMatrix& gmx)
09396 {
09397    REPORT
09398    Tracer tr("SubMatrix(inject)");
09399    SetUpLHS();
09400    if (row_number != gmx.Nrows() || col_number != gmx.Ncols())
09401       Throw(IncompatibleDimensionsException());
09402    MatrixRow mrx((GeneralMatrix*)(&gmx), LoadOnEntry);
09403    MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
09404                                   // do need LoadOnEntry
09405    MatrixRowCol sub; int i = row_number;
09406    while (i--)
09407    {
09408       mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
09409       sub.Inject(mrx); mr.Next(); mrx.Next();
09410    }
09411 }
09412 
09413 void GetSubMatrix::operator+=(const BaseMatrix& bmx)
09414 {
09415    REPORT
09416    Tracer tr("SubMatrix(+=)"); GeneralMatrix* gmx = 0;
09417    // MatrixConversionCheck mcc;         // Check for loss of info
09418    Try
09419    {
09420       SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate();
09421       if (row_number != gmx->Nrows() || col_number != gmx->Ncols())
09422          Throw(IncompatibleDimensionsException());
09423       MatrixRow mrx(gmx, LoadOnEntry);
09424       MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
09425                                      // do need LoadOnEntry
09426       MatrixRowCol sub; int i = row_number;
09427       while (i--)
09428       {
09429          mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
09430          sub.Check(mrx);                            // check for loss of info
09431          sub.Add(mrx); mr.Next(); mrx.Next();
09432       }
09433       gmx->tDelete();
09434    }
09435 
09436    CatchAll
09437    {
09438       if (gmx) gmx->tDelete();
09439       ReThrow;
09440    }
09441 }
09442 
09443 void GetSubMatrix::operator-=(const BaseMatrix& bmx)
09444 {
09445    REPORT
09446    Tracer tr("SubMatrix(-=)"); GeneralMatrix* gmx = 0;
09447    // MatrixConversionCheck mcc;         // Check for loss of info
09448    Try
09449    {
09450       SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate();
09451       if (row_number != gmx->Nrows() || col_number != gmx->Ncols())
09452          Throw(IncompatibleDimensionsException());
09453       MatrixRow mrx(gmx, LoadOnEntry);
09454       MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
09455                                      // do need LoadOnEntry
09456       MatrixRowCol sub; int i = row_number;
09457       while (i--)
09458       {
09459          mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
09460          sub.Check(mrx);                            // check for loss of info
09461          sub.Sub(mrx); mr.Next(); mrx.Next();
09462       }
09463       gmx->tDelete();
09464    }
09465 
09466    CatchAll
09467    {
09468       if (gmx) gmx->tDelete();
09469       ReThrow;
09470    }
09471 }
09472 
09473 void GetSubMatrix::operator+=(Real r)
09474 {
09475    REPORT
09476    Tracer tr("SubMatrix(+= or -= Real)");
09477    // MatrixConversionCheck mcc;         // Check for loss of info
09478    Try
09479    {
09480       SetUpLHS();
09481       MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
09482                                      // do need LoadOnEntry
09483       MatrixRowCol sub; int i = row_number;
09484       while (i--)
09485       {
09486          mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
09487          sub.Check();                               // check for loss of info
09488          sub.Add(r); mr.Next();
09489       }
09490    }
09491 
09492    CatchAll
09493    {
09494       ReThrow;
09495    }
09496 }
09497 
09498 void GetSubMatrix::operator*=(Real r)
09499 {
09500    REPORT
09501    Tracer tr("SubMatrix(*= or /= Real)");
09502    // MatrixConversionCheck mcc;         // Check for loss of info
09503    Try
09504    {
09505       SetUpLHS();
09506       MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
09507                                      // do need LoadOnEntry
09508       MatrixRowCol sub; int i = row_number;
09509       while (i--)
09510       {
09511          mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
09512          sub.Multiply(r); mr.Next();
09513       }
09514    }
09515 
09516    CatchAll
09517    {
09518       ReThrow;
09519    }
09520 }
09521 
09522 #ifdef use_namespace
09523 }
09524 #endif
09525 
09527 
09530 
09533 
09534 // Copyright (C) 1991,2,3,4: R B Davies
09535 
09536 #define WANT_MATH
09537 
09538 #ifdef use_namespace
09539 namespace NEWMAT {
09540 #endif
09541 
09542 #ifdef DO_REPORT
09543 #define REPORT { static ExeCounter ExeCount(__LINE__,13); ++ExeCount; }
09544 #else
09545 #define REPORT {}
09546 #endif
09547 
09548 /******************************** Quick sort ********************************/
09549 
09550 // Quicksort.
09551 // Essentially the method described in Sedgewick s algorithms in C++
09552 // My version is still partially recursive, unlike Segewick s, but the
09553 // smallest segment of each split is used in the recursion, so it should
09554 // not overlead the stack.
09555 
09556 // If the process does not seems to be converging an exception is thrown.
09557 
09558 
09559 #define DoSimpleSort 17            // when to switch to insert sort
09560 #define MaxDepth 50                // maximum recursion depth
09561 
09562 static void MyQuickSortDescending(Real* first, Real* last, int depth);
09563 static void InsertionSortDescending(Real* first, const int length,
09564    int guard);
09565 static Real SortThreeDescending(Real* a, Real* b, Real* c);
09566 
09567 static void MyQuickSortAscending(Real* first, Real* last, int depth);
09568 static void InsertionSortAscending(Real* first, const int length,
09569    int guard);
09570 
09571 
09572 void sort_descending(GeneralMatrix& GM)
09573 {
09574    REPORT
09575    Tracer et("sort_descending");
09576 
09577    Real* data = GM.Store(); int max = GM.Storage();
09578 
09579    if (max > DoSimpleSort) MyQuickSortDescending(data, data + max - 1, 0);
09580    InsertionSortDescending(data, max, DoSimpleSort);
09581 
09582 }
09583 
09584 static Real SortThreeDescending(Real* a, Real* b, Real* c)
09585 {
09586    // sort *a, *b, *c; return *b; optimise for already sorted
09587    if (*a >= *b)
09588    {
09589       if (*b >= *c) { REPORT return *b; }
09590       else if (*a >= *c) { REPORT Real x = *c; *c = *b; *b = x; return x; }
09591       else { REPORT Real x = *a; *a = *c; *c = *b; *b = x; return x; }
09592    }
09593    else if (*c >= *b) { REPORT Real x = *c; *c = *a; *a = x; return *b; }
09594    else if (*a >= *c) { REPORT Real x = *a; *a = *b; *b = x; return x; }
09595    else { REPORT Real x = *c; *c = *a; *a = *b; *b = x; return x; }
09596 }
09597 
09598 static void InsertionSortDescending(Real* first, const int length,
09599    int guard)
09600 // guard gives the length of the sequence to scan to find first
09601 // element (eg = length)
09602 {
09603    REPORT
09604    if (length <= 1) return;
09605 
09606    // scan for first element
09607    Real* f = first; Real v = *f; Real* h = f;
09608    if (guard > length) { REPORT guard = length; }
09609    int i = guard - 1;
09610    while (i--) if (v < *(++f)) { v = *f; h = f; }
09611    *h = *first; *first = v;
09612 
09613    // do the sort
09614    i = length - 1; f = first;
09615    while (i--)
09616    {
09617       Real* g = f++; h = f; v = *h;
09618       while (*g < v) *h-- = *g--;
09619       *h = v;
09620    }
09621 }
09622 
09623 static void MyQuickSortDescending(Real* first, Real* last, int depth)
09624 {
09625    REPORT
09626    for (;;)
09627    {
09628       const int length = last - first + 1;
09629       if (length < DoSimpleSort) { REPORT return; }
09630       if (depth++ > MaxDepth)
09631          Throw(ConvergenceException("QuickSortDescending fails: "));
09632       Real* centre = first + length/2;
09633       const Real test = SortThreeDescending(first, centre, last);
09634       Real* f = first; Real* l = last;
09635       for (;;)
09636       {
09637          while (*(++f) > test) {}
09638          while (*(--l) < test) {}
09639          if (l <= f) break;
09640          const Real temp = *f; *f = *l; *l = temp;
09641       }
09642       if (f > centre)
09643          { REPORT MyQuickSortDescending(l+1, last, depth); last = f-1; }
09644       else { REPORT MyQuickSortDescending(first, f-1, depth); first = l+1; }
09645    }
09646 }
09647 
09648 void sort_ascending(GeneralMatrix& GM)
09649 {
09650    REPORT
09651    Tracer et("sort_ascending");
09652 
09653    Real* data = GM.Store(); int max = GM.Storage();
09654 
09655    if (max > DoSimpleSort) MyQuickSortAscending(data, data + max - 1, 0);
09656    InsertionSortAscending(data, max, DoSimpleSort);
09657 
09658 }
09659 
09660 static void InsertionSortAscending(Real* first, const int length,
09661    int guard)
09662 // guard gives the length of the sequence to scan to find first
09663 // element (eg guard = length)
09664 {
09665    REPORT
09666    if (length <= 1) return;
09667 
09668    // scan for first element
09669    Real* f = first; Real v = *f; Real* h = f;
09670    if (guard > length) { REPORT guard = length; }
09671    int i = guard - 1;
09672    while (i--) if (v > *(++f)) { v = *f; h = f; }
09673    *h = *first; *first = v;
09674 
09675    // do the sort
09676    i = length - 1; f = first;
09677    while (i--)
09678    {
09679       Real* g = f++; h = f; v = *h;
09680       while (*g > v) *h-- = *g--;
09681       *h = v;
09682    }
09683 }
09684 static void MyQuickSortAscending(Real* first, Real* last, int depth)
09685 {
09686    REPORT
09687    for (;;)
09688    {
09689       const int length = last - first + 1;
09690       if (length < DoSimpleSort) { REPORT return; }
09691       if (depth++ > MaxDepth)
09692          Throw(ConvergenceException("QuickSortAscending fails: "));
09693       Real* centre = first + length/2;
09694       const Real test = SortThreeDescending(last, centre, first);
09695       Real* f = first; Real* l = last;
09696       for (;;)
09697       {
09698          while (*(++f) < test) {}
09699          while (*(--l) > test) {}
09700          if (l <= f) break;
09701          const Real temp = *f; *f = *l; *l = temp;
09702       }
09703       if (f > centre)
09704          { REPORT MyQuickSortAscending(l+1, last, depth); last = f-1; }
09705       else { REPORT MyQuickSortAscending(first, f-1, depth); first = l+1; }
09706    }
09707 }
09708 
09709 //********* sort diagonal matrix & rearrange matrix columns ****************
09710 
09711 // used by SVD
09712 
09713 // these are for sorting singular values - should be updated with faster
09714 // sorts that handle exchange of columns better
09715 // however time is probably not significant compared with SVD time
09716 
09717 void SortSV(DiagonalMatrix& D, Matrix& U, bool ascending)
09718 {
09719    REPORT
09720    Tracer trace("SortSV_DU");
09721    int m = U.Nrows(); int n = U.Ncols();
09722    if (n != D.Nrows()) Throw(IncompatibleDimensionsException(D,U));
09723    Real* u = U.Store();
09724    for (int i=0; i<n; i++)
09725    {
09726       int k = i; Real p = D.element(i);
09727       if (ascending)
09728       {
09729          for (int j=i+1; j<n; j++)
09730             { if (D.element(j) < p) { k = j; p = D.element(j); } }
09731       }
09732       else
09733       {
09734          for (int j=i+1; j<n; j++)
09735          { if (D.element(j) > p) { k = j; p = D.element(j); } }
09736       }
09737       if (k != i)
09738       {
09739          D.element(k) = D.element(i); D.element(i) = p; int j = m;
09740          Real* uji = u + i; Real* ujk = u + k;
09741          if (j) for(;;)
09742          {
09743             p = *uji; *uji = *ujk; *ujk = p;
09744             if (!(--j)) break;
09745             uji += n; ujk += n;
09746          }
09747       }
09748    }
09749 }
09750 
09751 void SortSV(DiagonalMatrix& D, Matrix& U, Matrix& V, bool ascending)
09752 {
09753    REPORT
09754    Tracer trace("SortSV_DUV");
09755    int mu = U.Nrows(); int mv = V.Nrows(); int n = D.Nrows();
09756    if (n != U.Ncols()) Throw(IncompatibleDimensionsException(D,U));
09757    if (n != V.Ncols()) Throw(IncompatibleDimensionsException(D,V));
09758    Real* u = U.Store(); Real* v = V.Store();
09759    for (int i=0; i<n; i++)
09760    {
09761       int k = i; Real p = D.element(i);
09762       if (ascending)
09763       {
09764          for (int j=i+1; j<n; j++)
09765             { if (D.element(j) < p) { k = j; p = D.element(j); } }
09766       }
09767       else
09768       {
09769          for (int j=i+1; j<n; j++)
09770          { if (D.element(j) > p) { k = j; p = D.element(j); } }
09771       }
09772       if (k != i)
09773       {
09774          D.element(k) = D.element(i); D.element(i) = p;
09775          Real* uji = u + i; Real* ujk = u + k;
09776          Real* vji = v + i; Real* vjk = v + k;
09777          int j = mu;
09778          if (j) for(;;)
09779          {
09780             p = *uji; *uji = *ujk; *ujk = p; if (!(--j)) break;
09781             uji += n; ujk += n;
09782          }
09783          j = mv;
09784          if (j) for(;;)
09785          {
09786             p = *vji; *vji = *vjk; *vjk = p; if (!(--j)) break;
09787             vji += n; vjk += n;
09788          }
09789       }
09790    }
09791 }
09792 
09793 
09794 
09795 
09796 #ifdef use_namespace
09797 }
09798 #endif
09799 
09803 
09806 
09807 // Copyright (C) 1991,2,3,4: R B Davies
09808 
09809 
09810 #define WANT_FSTREAM
09811 
09812 #ifdef use_namespace
09813 namespace NEWMAT {
09814 #endif
09815 
09816 
09817 
09818 #ifdef DO_REPORT
09819 #define REPORT { static ExeCounter ExeCount(__LINE__,9); ++ExeCount; }
09820 #else
09821 #define REPORT {}
09822 #endif
09823 
09824 // for G++ 3.01
09825 #ifndef ios_format_flags
09826 #define ios_format_flags long
09827 #endif
09828 
09829 ostream& operator<<(ostream& s, const BaseMatrix& X)
09830 {
09831    GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate(); operator<<(s, *gm);
09832    gm->tDelete(); return s;
09833 }
09834 
09835 
09836 ostream& operator<<(ostream& s, const GeneralMatrix& X)
09837 {
09838    MatrixRow mr((GeneralMatrix*)&X, LoadOnEntry);
09839    int w = s.width();  int nr = X.Nrows();  ios_format_flags f = s.flags();
09840    s.setf(ios::fixed, ios::floatfield);
09841    for (int i=1; i<=nr; i++)
09842    {
09843       int skip = mr.skip;  int storage = mr.storage;
09844       Real* store = mr.data;  skip *= w+1;
09845       while (skip--) s << " ";
09846       while (storage--) { s.width(w); s << *store++ << " "; }
09847 //      while (storage--) s << setw(w) << *store++ << " ";
09848       mr.Next();  s << "\n";
09849    }
09850    s << flush;  s.flags(f); return s;
09851 }
09852 
09853 // include this stuff if you are using an old version of G++
09854 // with an incomplete io library
09855 
09856 /*
09857 
09858 ostream& operator<<(ostream& os, Omanip_precision i)
09859    { os.precision(i.x); return os; }
09860 
09861 Omanip_precision setprecision(int i) { return Omanip_precision(i); }
09862 
09863 ostream& operator<<(ostream& os, Omanip_width i)
09864    { os.width(i.x); return os; }
09865 
09866 Omanip_width setw(int i) { return Omanip_width(i); }
09867 
09868 */
09869 
09870 static void tred2(const SymmetricMatrix& A, DiagonalMatrix& D,
09871    DiagonalMatrix& E, Matrix& Z)
09872 {
09873    Tracer et("Evalue(tred2)");
09874    REPORT
09875    Real tol =
09876       FloatingPointPrecision::Minimum()/FloatingPointPrecision::Epsilon();
09877    int n = A.Nrows(); Z.resize(n,n); Z.Inject(A);
09878    D.resize(n); E.resize(n);
09879    Real* z = Z.Store(); int i;
09880 
09881    for (i=n-1; i > 0; i--)                   // i=0 is excluded
09882    {
09883       Real f = Z.element(i,i-1); Real g = 0.0;
09884       int k = i-1; Real* zik = z + i*n;
09885       while (k--) g += square(*zik++);
09886       Real h = g + square(f);
09887       if (g <= tol) { REPORT E.element(i) = f; h = 0.0; }
09888       else
09889       {
09890          REPORT
09891          g = sign(-sqrt(h), f); E.element(i) = g; h -= f*g;
09892          Z.element(i,i-1) = f-g; f = 0.0;
09893          Real* zji = z + i; Real* zij = z + i*n; Real* ej = E.Store();
09894          int j;
09895          for (j=0; j<i; j++)
09896          {
09897             *zji = (*zij++)/h; g = 0.0;
09898             Real* zjk = z + j*n; zik = z + i*n;
09899             k = j; while (k--) g += *zjk++ * (*zik++);
09900             k = i-j;
09901             if (k) for(;;)
09902                { g += *zjk * (*zik++); if (!(--k)) break; zjk += n; }
09903             *ej++ = g/h; f += g * (*zji); zji += n;
09904          }
09905          Real hh = f / (h + h); zij = z + i*n; ej = E.Store();
09906          for (j=0; j<i; j++)
09907          {
09908             f = *zij++; g = *ej - hh * f; *ej++ = g;
09909             Real* zjk = z + j*n; Real* zik = z + i*n;
09910             Real* ek = E.Store(); k = j+1;
09911             while (k--)  *zjk++ -= ( f*(*ek++) + g*(*zik++) ); 
09912          }
09913       }
09914       D.element(i) = h;
09915    }
09916 
09917    D.element(0) = 0.0; E.element(0) = 0.0;
09918    for (i=0; i<n; i++)
09919    {
09920       if (D.element(i) != 0.0)
09921       {
09922          REPORT
09923          for (int j=0; j<i; j++)
09924          {
09925             Real g = 0.0;
09926             Real* zik = z + i*n; Real* zkj = z + j;
09927             int k = i;
09928             if (k) for (;;)
09929                { g += *zik++ * (*zkj); if (!(--k)) break; zkj += n; }
09930             Real* zki = z + i; zkj = z + j;
09931             k = i;
09932             if (k) for (;;)
09933                { *zkj -= g * (*zki); if (!(--k)) break; zkj += n; zki += n; }
09934          }
09935       }
09936       Real* zij = z + i*n; Real* zji = z + i;
09937       int j = i;
09938       if (j) for (;;)
09939          { *zij++ = 0.0; *zji = 0.0; if (!(--j)) break; zji += n; }
09940       D.element(i) = *zij; *zij = 1.0;
09941    }
09942 }
09943 
09944 static void tql2(DiagonalMatrix& D, DiagonalMatrix& E, Matrix& Z)
09945 {
09946    Tracer et("Evalue(tql2)");
09947    REPORT
09948    Real eps = FloatingPointPrecision::Epsilon();
09949    int n = D.Nrows(); Real* z = Z.Store(); int l;
09950    for (l=1; l<n; l++) E.element(l-1) = E.element(l);
09951    Real b = 0.0; Real f = 0.0; E.element(n-1) = 0.0;
09952    for (l=0; l<n; l++)
09953    {
09954       int i,j;
09955       Real& dl = D.element(l); Real& el = E.element(l);
09956       Real h = eps * ( fabs(dl) + fabs(el) );
09957       if (b < h) { REPORT b = h; }
09958       int m;
09959       for (m=l; m<n; m++) if (fabs(E.element(m)) <= b) break;
09960       bool test = false;
09961       for (j=0; j<30; j++)
09962       {
09963          if (m==l) { REPORT test = true; break; }
09964          Real& dl1 = D.element(l+1);
09965          Real g = dl; Real p = (dl1-g) / (2.0*el); Real r = sqrt(p*p + 1.0);
09966          dl = el / (p < 0.0 ? p-r : p+r); Real h = g - dl; f += h;
09967          Real* dlx = &dl1; i = n-l-1; while (i--) *dlx++ -= h;
09968 
09969          p = D.element(m); Real c = 1.0; Real s = 0.0;
09970          for (i=m-1; i>=l; i--)
09971          {
09972             Real ei = E.element(i); Real di = D.element(i);
09973             Real& ei1 = E.element(i+1);
09974             g = c * ei; h = c * p;
09975             if ( fabs(p) >= fabs(ei))
09976             {
09977                REPORT
09978                c = ei / p; r = sqrt(c*c + 1.0);
09979                ei1 = s*p*r; s = c/r; c = 1.0/r;
09980             }
09981             else
09982             {
09983                REPORT
09984                c = p / ei; r = sqrt(c*c + 1.0);
09985                ei1 = s * ei * r; s = 1.0/r; c /= r;
09986             }
09987             p = c * di - s*g; D.element(i+1) = h + s * (c*g + s*di);
09988 
09989             Real* zki = z + i; Real* zki1 = zki + 1; int k = n;
09990             if (k) for (;;)
09991             {
09992                REPORT
09993                h = *zki1; *zki1 = s*(*zki) + c*h; *zki = c*(*zki) - s*h;
09994                if (!(--k)) break;
09995                zki += n; zki1 += n;
09996             }
09997          }
09998          el = s*p; dl = c*p;
09999          if (fabs(el) <= b) { REPORT; test = true; break; }
10000       }
10001       if (!test) Throw ( ConvergenceException(D) );
10002       dl += f;
10003    }
10004 /*
10005    for (int i=0; i<n; i++)
10006    {
10007       int k = i; Real p = D.element(i);
10008       for (int j=i+1; j<n; j++)
10009          { if (D.element(j) < p) { k = j; p = D.element(j); } }
10010       if (k != i)
10011       {
10012          D.element(k) = D.element(i); D.element(i) = p; int j = n;
10013          Real* zji = z + i; Real* zjk = z + k;
10014          if (j) for(;;)
10015          {
10016             p = *zji; *zji = *zjk; *zjk = p;
10017             if (!(--j)) break;
10018             zji += n; zjk += n;
10019          }
10020       }
10021    }
10022 */
10023 }
10024 
10025 static void tred3(const SymmetricMatrix& X, DiagonalMatrix& D,
10026    DiagonalMatrix& E, SymmetricMatrix& A)
10027 {
10028    Tracer et("Evalue(tred3)");
10029    REPORT
10030    Real tol =
10031       FloatingPointPrecision::Minimum()/FloatingPointPrecision::Epsilon();
10032    int n = X.Nrows(); A = X; D.resize(n); E.resize(n);
10033    Real* ei = E.Store() + n;
10034    for (int i = n-1; i >= 0; i--)
10035    {
10036       Real h = 0.0; Real f = - FloatingPointPrecision::Maximum();
10037       Real* d = D.Store(); Real* a = A.Store() + (i*(i+1))/2; int k = i;
10038       while (k--) { f = *a++; *d++ = f; h += square(f); }
10039       if (h <= tol) { REPORT *(--ei) = 0.0; h = 0.0; }
10040       else
10041       {
10042          REPORT
10043          Real g = sign(-sqrt(h), f); *(--ei) = g; h -= f*g;
10044          f -= g; *(d-1) = f; *(a-1) = f; f = 0.0;
10045          Real* dj = D.Store(); Real* ej = E.Store(); int j;
10046          for (j = 0; j < i; j++)
10047          {
10048             Real* dk = D.Store(); Real* ak = A.Store()+(j*(j+1))/2;
10049             Real g = 0.0; k = j;
10050             while (k--)  g += *ak++ * *dk++;
10051             k = i-j; int l = j; 
10052             if (k) for (;;) { g += *ak * *dk++; if (!(--k)) break; ak += ++l; }
10053             g /= h; *ej++ = g; f += g * *dj++;
10054          }  
10055          Real hh = f / (2 * h); Real* ak = A.Store();
10056          dj = D.Store(); ej = E.Store();
10057          for (j = 0; j < i; j++)
10058          {
10059             f = *dj++; g = *ej - hh * f; *ej++ = g;
10060             Real* dk = D.Store(); Real* ek = E.Store(); k = j+1;
10061             while (k--) { *ak++ -= (f * *ek++ + g * *dk++); }
10062          }
10063       }
10064       *d = *a; *a = h;
10065    }
10066 }
10067 
10068 static void tql1(DiagonalMatrix& D, DiagonalMatrix& E)
10069 {
10070    Tracer et("Evalue(tql1)");
10071    REPORT
10072    Real eps = FloatingPointPrecision::Epsilon();
10073    int n = D.Nrows(); int l;
10074    for (l=1; l<n; l++) E.element(l-1) = E.element(l);
10075    Real b = 0.0; Real f = 0.0; E.element(n-1) = 0.0;
10076    for (l=0; l<n; l++)
10077    {
10078       int i,j;
10079       Real& dl = D.element(l); Real& el = E.element(l);
10080       Real h = eps * ( fabs(dl) + fabs(el) );
10081       if (b < h) b = h;
10082       int m;
10083       for (m=l; m<n; m++) if (fabs(E.element(m)) <= b) break;
10084       bool test = false;
10085       for (j=0; j<30; j++)
10086       {
10087          if (m==l) { REPORT test = true; break; }
10088          Real& dl1 = D.element(l+1);
10089          Real g = dl; Real p = (dl1-g) / (2.0*el); Real r = sqrt(p*p + 1.0);
10090          dl = el / (p < 0.0 ? p-r : p+r); Real h = g - dl; f += h;
10091          Real* dlx = &dl1; i = n-l-1; while (i--) *dlx++ -= h;
10092 
10093          p = D.element(m); Real c = 1.0; Real s = 0.0;
10094          for (i=m-1; i>=l; i--)
10095          {
10096             Real ei = E.element(i); Real di = D.element(i);
10097             Real& ei1 = E.element(i+1);
10098             g = c * ei; h = c * p;
10099             if ( fabs(p) >= fabs(ei))
10100             {
10101                REPORT
10102                c = ei / p; r = sqrt(c*c + 1.0);
10103                ei1 = s*p*r; s = c/r; c = 1.0/r;
10104             }
10105             else
10106             {
10107                REPORT
10108                c = p / ei; r = sqrt(c*c + 1.0);
10109                ei1 = s * ei * r; s = 1.0/r; c /= r;
10110             }
10111             p = c * di - s*g; D.element(i+1) = h + s * (c*g + s*di);
10112          }
10113          el = s*p; dl = c*p;
10114          if (fabs(el) <= b) { REPORT test = true; break; }
10115       }
10116       if (!test) Throw ( ConvergenceException(D) );
10117       Real p = dl + f;
10118       test = false;
10119       for (i=l; i>0; i--)
10120       {
10121          if (p < D.element(i-1)) { REPORT D.element(i) = D.element(i-1); }
10122          else { REPORT test = true; break; }
10123       }
10124       if (!test) i=0;
10125       D.element(i) = p;
10126    }
10127 }
10128 
10129 void eigenvalues(const SymmetricMatrix& A, DiagonalMatrix& D, Matrix& Z)
10130 { REPORT DiagonalMatrix E; tred2(A, D, E, Z); tql2(D, E, Z); SortSV(D,Z,true); }
10131 
10132 void eigenvalues(const SymmetricMatrix& X, DiagonalMatrix& D)
10133 { REPORT DiagonalMatrix E; SymmetricMatrix A; tred3(X,D,E,A); tql1(D,E); }
10134 
10135 void eigenvalues(const SymmetricMatrix& X, DiagonalMatrix& D,
10136    SymmetricMatrix& A)
10137 { REPORT DiagonalMatrix E; tred3(X,D,E,A); tql1(D,E); }
10138 
10139 
10140 
10141 #ifdef use_namespace
10142 }
10143 #endif
10144 
10145 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


lo
Author(s): U. Klank
autogenerated on Thu May 23 2013 07:34:45