/// \ingroup newmat ///@{ /// \file newmat4.cpp /// Constructors, resize, basic utilities, SimpleIntArray. // Copyright (C) 1991,2,3,4,8,9: R B Davies //#define WANT_STREAM #include "include.h" #include "newmat.h" #include "newmatrc.h" #ifdef use_namespace namespace NEWMAT { #endif #ifdef DO_REPORT #define REPORT { static ExeCounter ExeCount(__LINE__,4); ++ExeCount; } #else #define REPORT {} #endif #define DO_SEARCH // search for LHS of = in RHS // ************************* general utilities *************************/ static int tristore(int n) // elements in triangular matrix { return (n*(n+1))/2; } // **************************** constructors ***************************/ GeneralMatrix::GeneralMatrix() { store=0; storage=0; nrows_val=0; ncols_val=0; tag_val=-1; } GeneralMatrix::GeneralMatrix(ArrayLengthSpecifier s) { REPORT storage=s.Value(); tag_val=-1; if (storage) { store = new Real [storage]; MatrixErrorNoSpace(store); MONITOR_REAL_NEW("Make (GenMatrix)",storage,store) } else store = 0; } Matrix::Matrix(int m, int n) : GeneralMatrix(m*n) { REPORT nrows_val=m; ncols_val=n; } SquareMatrix::SquareMatrix(ArrayLengthSpecifier n) : Matrix(n.Value(),n.Value()) { REPORT } SymmetricMatrix::SymmetricMatrix(ArrayLengthSpecifier n) : GeneralMatrix(tristore(n.Value())) { REPORT nrows_val=n.Value(); ncols_val=n.Value(); } UpperTriangularMatrix::UpperTriangularMatrix(ArrayLengthSpecifier n) : GeneralMatrix(tristore(n.Value())) { REPORT nrows_val=n.Value(); ncols_val=n.Value(); } LowerTriangularMatrix::LowerTriangularMatrix(ArrayLengthSpecifier n) : GeneralMatrix(tristore(n.Value())) { REPORT nrows_val=n.Value(); ncols_val=n.Value(); } DiagonalMatrix::DiagonalMatrix(ArrayLengthSpecifier m) : GeneralMatrix(m) { REPORT nrows_val=m.Value(); ncols_val=m.Value(); } Matrix::Matrix(const BaseMatrix& M) { REPORT // CheckConversion(M); // MatrixConversionCheck mcc; GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Rt); GetMatrix(gmx); } SquareMatrix::SquareMatrix(const BaseMatrix& M) : Matrix(M) { REPORT if (ncols_val != nrows_val) { Tracer tr("SquareMatrix"); Throw(NotSquareException(*this)); } } SquareMatrix::SquareMatrix(const Matrix& gm) { REPORT if (gm.ncols_val != gm.nrows_val) { Tracer tr("SquareMatrix(Matrix)"); Throw(NotSquareException(gm)); } GetMatrix(&gm); } RowVector::RowVector(const BaseMatrix& M) : Matrix(M) { REPORT if (nrows_val!=1) { Tracer tr("RowVector"); Throw(VectorException(*this)); } } ColumnVector::ColumnVector(const BaseMatrix& M) : Matrix(M) { REPORT if (ncols_val!=1) { Tracer tr("ColumnVector"); Throw(VectorException(*this)); } } SymmetricMatrix::SymmetricMatrix(const BaseMatrix& M) { REPORT // CheckConversion(M); // MatrixConversionCheck mcc; GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Sm); GetMatrix(gmx); } UpperTriangularMatrix::UpperTriangularMatrix(const BaseMatrix& M) { REPORT // CheckConversion(M); // MatrixConversionCheck mcc; GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::UT); GetMatrix(gmx); } LowerTriangularMatrix::LowerTriangularMatrix(const BaseMatrix& M) { REPORT // CheckConversion(M); // MatrixConversionCheck mcc; GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::LT); GetMatrix(gmx); } DiagonalMatrix::DiagonalMatrix(const BaseMatrix& M) { REPORT //CheckConversion(M); // MatrixConversionCheck mcc; GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Dg); GetMatrix(gmx); } IdentityMatrix::IdentityMatrix(const BaseMatrix& M) { REPORT //CheckConversion(M); // MatrixConversionCheck mcc; GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Id); GetMatrix(gmx); } GeneralMatrix::~GeneralMatrix() { if (store) { MONITOR_REAL_DELETE("Free (GenMatrix)",storage,store) delete [] store; } } CroutMatrix::CroutMatrix(const BaseMatrix& m) { REPORT Tracer tr("CroutMatrix"); indx = 0; // in case of exception at next line GeneralMatrix* gm = ((BaseMatrix&)m).Evaluate(); if (gm->nrows_val!=gm->ncols_val) { gm->tDelete(); Throw(NotSquareException(*gm)); } if (gm->type() == MatrixType::Ct) { REPORT ((CroutMatrix*)gm)->get_aux(*this); GetMatrix(gm); } else { REPORT GeneralMatrix* gm1 = gm->Evaluate(MatrixType::Rt); GetMatrix(gm1); d=true; sing=false; indx=new int [nrows_val]; MatrixErrorNoSpace(indx); MONITOR_INT_NEW("Index (CroutMat)",nrows_val,indx) ludcmp(); } } // could we use SetParameters instead of this void CroutMatrix::get_aux(CroutMatrix& X) { X.d = d; X.sing = sing; if (tag_val == 0 || tag_val == 1) // reuse the array { REPORT X.indx = indx; indx = 0; d = true; sing = true; return; } else if (nrows_val == 0) { REPORT indx = 0; d = true; sing = true; return; } else // copy the array { REPORT Tracer tr("CroutMatrix::get_aux"); int *ix = new int [nrows_val]; MatrixErrorNoSpace(ix); MONITOR_INT_NEW("Index (CM::get_aux)", nrows_val, ix) int n = nrows_val; int* i = ix; int* j = indx; while(n--) *i++ = *j++; X.indx = ix; } } CroutMatrix::CroutMatrix(const CroutMatrix& gm) : GeneralMatrix() { REPORT Tracer tr("CroutMatrix(const CroutMatrix&)"); ((CroutMatrix&)gm).get_aux(*this); GetMatrix(&gm); } CroutMatrix::~CroutMatrix() { MONITOR_INT_DELETE("Index (CroutMat)",nrows_val,indx) delete [] indx; } //ReturnMatrix::ReturnMatrix(GeneralMatrix& gmx) //{ // REPORT // gm = gmx.Image(); gm->ReleaseAndDelete(); //} GeneralMatrix::operator ReturnMatrix() const { REPORT GeneralMatrix* gm = Image(); gm->ReleaseAndDelete(); return ReturnMatrix(gm); } ReturnMatrix GeneralMatrix::for_return() const { REPORT GeneralMatrix* gm = Image(); gm->ReleaseAndDelete(); return ReturnMatrix(gm); } // ************ Constructors for use with NR in C++ interface *********** #ifdef SETUP_C_SUBSCRIPTS Matrix::Matrix(Real a, int m, int n) : GeneralMatrix(m * n) { REPORT nrows_val=m; ncols_val=n; operator=(a); } Matrix::Matrix(const Real* a, int m, int n) : GeneralMatrix(m * n) { REPORT nrows_val=m; ncols_val=n; *this << a; } #endif // ************************** resize matrices ***************************/ void GeneralMatrix::resize(int nr, int nc, int s) { REPORT if (store) { MONITOR_REAL_DELETE("Free (ReDimensi)",storage,store) delete [] store; } storage=s; nrows_val=nr; ncols_val=nc; tag_val=-1; if (s) { store = new Real [storage]; MatrixErrorNoSpace(store); MONITOR_REAL_NEW("Make (ReDimensi)",storage,store) } else store = 0; } void Matrix::resize(int nr, int nc) { REPORT GeneralMatrix::resize(nr,nc,nr*nc); } void SquareMatrix::resize(int n) { REPORT GeneralMatrix::resize(n,n,n*n); } void SquareMatrix::resize(int nr, int nc) { REPORT Tracer tr("SquareMatrix::resize"); if (nc != nr) Throw(NotSquareException(*this)); GeneralMatrix::resize(nr,nc,nr*nc); } void SymmetricMatrix::resize(int nr) { REPORT GeneralMatrix::resize(nr,nr,tristore(nr)); } void UpperTriangularMatrix::resize(int nr) { REPORT GeneralMatrix::resize(nr,nr,tristore(nr)); } void LowerTriangularMatrix::resize(int nr) { REPORT GeneralMatrix::resize(nr,nr,tristore(nr)); } void DiagonalMatrix::resize(int nr) { REPORT GeneralMatrix::resize(nr,nr,nr); } void RowVector::resize(int nc) { REPORT GeneralMatrix::resize(1,nc,nc); } void ColumnVector::resize(int nr) { REPORT GeneralMatrix::resize(nr,1,nr); } void RowVector::resize(int nr, int nc) { Tracer tr("RowVector::resize"); if (nr != 1) Throw(VectorException(*this)); REPORT GeneralMatrix::resize(1,nc,nc); } void ColumnVector::resize(int nr, int nc) { Tracer tr("ColumnVector::resize"); if (nc != 1) Throw(VectorException(*this)); REPORT GeneralMatrix::resize(nr,1,nr); } void IdentityMatrix::resize(int nr) { REPORT GeneralMatrix::resize(nr,nr,1); *store = 1; } void Matrix::resize(const GeneralMatrix& A) { REPORT resize(A.Nrows(), A.Ncols()); } void SquareMatrix::resize(const GeneralMatrix& A) { REPORT int n = A.Nrows(); if (n != A.Ncols()) { Tracer tr("SquareMatrix::resize(GM)"); Throw(NotSquareException(*this)); } resize(n); } void nricMatrix::resize(const GeneralMatrix& A) { REPORT resize(A.Nrows(), A.Ncols()); } void ColumnVector::resize(const GeneralMatrix& A) { REPORT resize(A.Nrows(), A.Ncols()); } void RowVector::resize(const GeneralMatrix& A) { REPORT resize(A.Nrows(), A.Ncols()); } void SymmetricMatrix::resize(const GeneralMatrix& A) { REPORT int n = A.Nrows(); if (n != A.Ncols()) { Tracer tr("SymmetricMatrix::resize(GM)"); Throw(NotSquareException(*this)); } resize(n); } void DiagonalMatrix::resize(const GeneralMatrix& A) { REPORT int n = A.Nrows(); if (n != A.Ncols()) { Tracer tr("DiagonalMatrix::resize(GM)"); Throw(NotSquareException(*this)); } resize(n); } void UpperTriangularMatrix::resize(const GeneralMatrix& A) { REPORT int n = A.Nrows(); if (n != A.Ncols()) { Tracer tr("UpperTriangularMatrix::resize(GM)"); Throw(NotSquareException(*this)); } resize(n); } void LowerTriangularMatrix::resize(const GeneralMatrix& A) { REPORT int n = A.Nrows(); if (n != A.Ncols()) { Tracer tr("LowerTriangularMatrix::resize(GM)"); Throw(NotSquareException(*this)); } resize(n); } void IdentityMatrix::resize(const GeneralMatrix& A) { REPORT int n = A.Nrows(); if (n != A.Ncols()) { Tracer tr("IdentityMatrix::resize(GM)"); Throw(NotSquareException(*this)); } resize(n); } void GeneralMatrix::resize(const GeneralMatrix&) { REPORT Tracer tr("GeneralMatrix::resize(GM)"); Throw(NotDefinedException("resize", "this type of matrix")); } //*********************** resize_keep ******************************* void Matrix::resize_keep(int nr, int nc) { Tracer tr("Matrix::resize_keep"); if (nr == nrows_val && nc == ncols_val) { REPORT return; } if (nr <= nrows_val && nc <= ncols_val) { REPORT Matrix X = submatrix(1,nr,1,nc); swap(X); } else if (nr >= nrows_val && nc >= ncols_val) { REPORT Matrix X(nr, nc); X = 0; X.submatrix(1,nrows_val,1,ncols_val) = *this; swap(X); } else { REPORT Matrix X(nr, nc); X = 0; if (nr > nrows_val) nr = nrows_val; if (nc > ncols_val) nc = ncols_val; X.submatrix(1,nr,1,nc) = submatrix(1,nr,1,nc); swap(X); } } void SquareMatrix::resize_keep(int nr) { Tracer tr("SquareMatrix::resize_keep"); if (nr < nrows_val) { REPORT SquareMatrix X = sym_submatrix(1,nr); swap(X); } else if (nr > nrows_val) { REPORT SquareMatrix X(nr); X = 0; X.sym_submatrix(1,nrows_val) = *this; swap(X); } } void SquareMatrix::resize_keep(int nr, int nc) { Tracer tr("SquareMatrix::resize_keep 2"); REPORT if (nr != nc) Throw(NotSquareException(*this)); resize_keep(nr); } void SymmetricMatrix::resize_keep(int nr) { Tracer tr("SymmetricMatrix::resize_keep"); if (nr < nrows_val) { REPORT SymmetricMatrix X = sym_submatrix(1,nr); swap(X); } else if (nr > nrows_val) { REPORT SymmetricMatrix X(nr); X = 0; X.sym_submatrix(1,nrows_val) = *this; swap(X); } } void UpperTriangularMatrix::resize_keep(int nr) { Tracer tr("UpperTriangularMatrix::resize_keep"); if (nr < nrows_val) { REPORT UpperTriangularMatrix X = sym_submatrix(1,nr); swap(X); } else if (nr > nrows_val) { REPORT UpperTriangularMatrix X(nr); X = 0; X.sym_submatrix(1,nrows_val) = *this; swap(X); } } void LowerTriangularMatrix::resize_keep(int nr) { Tracer tr("LowerTriangularMatrix::resize_keep"); if (nr < nrows_val) { REPORT LowerTriangularMatrix X = sym_submatrix(1,nr); swap(X); } else if (nr > nrows_val) { REPORT LowerTriangularMatrix X(nr); X = 0; X.sym_submatrix(1,nrows_val) = *this; swap(X); } } void DiagonalMatrix::resize_keep(int nr) { Tracer tr("DiagonalMatrix::resize_keep"); if (nr < nrows_val) { REPORT DiagonalMatrix X = sym_submatrix(1,nr); swap(X); } else if (nr > nrows_val) { REPORT DiagonalMatrix X(nr); X = 0; X.sym_submatrix(1,nrows_val) = *this; swap(X); } } void RowVector::resize_keep(int nc) { Tracer tr("RowVector::resize_keep"); if (nc < ncols_val) { REPORT RowVector X = columns(1,nc); swap(X); } else if (nc > ncols_val) { REPORT RowVector X(nc); X = 0; X.columns(1,ncols_val) = *this; swap(X); } } void RowVector::resize_keep(int nr, int nc) { Tracer tr("RowVector::resize_keep 2"); REPORT if (nr != 1) Throw(VectorException(*this)); resize_keep(nc); } void ColumnVector::resize_keep(int nr) { Tracer tr("ColumnVector::resize_keep"); if (nr < nrows_val) { REPORT ColumnVector X = rows(1,nr); swap(X); } else if (nr > nrows_val) { REPORT ColumnVector X(nr); X = 0; X.rows(1,nrows_val) = *this; swap(X); } } void ColumnVector::resize_keep(int nr, int nc) { Tracer tr("ColumnVector::resize_keep 2"); REPORT if (nc != 1) Throw(VectorException(*this)); resize_keep(nr); } /* void GeneralMatrix::resizeForAdd(const GeneralMatrix& A, const GeneralMatrix&) { REPORT resize(A); } void GeneralMatrix::resizeForSP(const GeneralMatrix& A, const GeneralMatrix&) { REPORT resize(A); } // ************************* SameStorageType ****************************** // SameStorageType checks A and B have same storage type including bandwidth // It does not check same dimensions since we assume this is already done bool GeneralMatrix::SameStorageType(const GeneralMatrix& A) const { REPORT return type() == A.type(); } */ // ******************* manipulate types, storage **************************/ int GeneralMatrix::search(const BaseMatrix* s) const { REPORT return (s==this) ? 1 : 0; } int GenericMatrix::search(const BaseMatrix* s) const { REPORT return gm->search(s); } int MultipliedMatrix::search(const BaseMatrix* s) const { REPORT return bm1->search(s) + bm2->search(s); } int ShiftedMatrix::search(const BaseMatrix* s) const { REPORT return bm->search(s); } int NegatedMatrix::search(const BaseMatrix* s) const { REPORT return bm->search(s); } int ReturnMatrix::search(const BaseMatrix* s) const { REPORT return (s==gm) ? 1 : 0; } MatrixType Matrix::type() const { return MatrixType::Rt; } MatrixType SquareMatrix::type() const { return MatrixType::Sq; } MatrixType SymmetricMatrix::type() const { return MatrixType::Sm; } MatrixType UpperTriangularMatrix::type() const { return MatrixType::UT; } MatrixType LowerTriangularMatrix::type() const { return MatrixType::LT; } MatrixType DiagonalMatrix::type() const { return MatrixType::Dg; } MatrixType RowVector::type() const { return MatrixType::RV; } MatrixType ColumnVector::type() const { return MatrixType::CV; } MatrixType CroutMatrix::type() const { return MatrixType::Ct; } MatrixType BandMatrix::type() const { return MatrixType::BM; } MatrixType UpperBandMatrix::type() const { return MatrixType::UB; } MatrixType LowerBandMatrix::type() const { return MatrixType::LB; } MatrixType SymmetricBandMatrix::type() const { return MatrixType::SB; } MatrixType IdentityMatrix::type() const { return MatrixType::Id; } MatrixBandWidth BaseMatrix::bandwidth() const { REPORT return -1; } MatrixBandWidth DiagonalMatrix::bandwidth() const { REPORT return 0; } MatrixBandWidth IdentityMatrix::bandwidth() const { REPORT return 0; } MatrixBandWidth UpperTriangularMatrix::bandwidth() const { REPORT return MatrixBandWidth(0,-1); } MatrixBandWidth LowerTriangularMatrix::bandwidth() const { REPORT return MatrixBandWidth(-1,0); } MatrixBandWidth BandMatrix::bandwidth() const { REPORT return MatrixBandWidth(lower_val,upper_val); } MatrixBandWidth BandLUMatrix::bandwidth() const { REPORT return MatrixBandWidth(m1,m2); } MatrixBandWidth GenericMatrix::bandwidth()const { REPORT return gm->bandwidth(); } MatrixBandWidth AddedMatrix::bandwidth() const { REPORT return gm1->bandwidth() + gm2->bandwidth(); } MatrixBandWidth SPMatrix::bandwidth() const { REPORT return gm1->bandwidth().minimum(gm2->bandwidth()); } MatrixBandWidth KPMatrix::bandwidth() const { int lower, upper; MatrixBandWidth bw1 = gm1->bandwidth(), bw2 = gm2->bandwidth(); if (bw1.Lower() < 0) { if (bw2.Lower() < 0) { REPORT lower = -1; } else { REPORT lower = bw2.Lower() + (gm1->Nrows() - 1) * gm2->Nrows(); } } else { if (bw2.Lower() < 0) { REPORT lower = (1 + bw1.Lower()) * gm2->Nrows() - 1; } else { REPORT lower = bw2.Lower() + bw1.Lower() * gm2->Nrows(); } } if (bw1.Upper() < 0) { if (bw2.Upper() < 0) { REPORT upper = -1; } else { REPORT upper = bw2.Upper() + (gm1->Nrows() - 1) * gm2->Nrows(); } } else { if (bw2.Upper() < 0) { REPORT upper = (1 + bw1.Upper()) * gm2->Nrows() - 1; } else { REPORT upper = bw2.Upper() + bw1.Upper() * gm2->Nrows(); } } return MatrixBandWidth(lower, upper); } MatrixBandWidth MultipliedMatrix::bandwidth() const { REPORT return gm1->bandwidth() * gm2->bandwidth(); } MatrixBandWidth ConcatenatedMatrix::bandwidth() const { REPORT return -1; } MatrixBandWidth SolvedMatrix::bandwidth() const { if (+gm1->type() & MatrixType::Diagonal) { REPORT return gm2->bandwidth(); } else { REPORT return -1; } } MatrixBandWidth ScaledMatrix::bandwidth() const { REPORT return gm->bandwidth(); } MatrixBandWidth NegatedMatrix::bandwidth() const { REPORT return gm->bandwidth(); } MatrixBandWidth TransposedMatrix::bandwidth() const { REPORT return gm->bandwidth().t(); } MatrixBandWidth InvertedMatrix::bandwidth() const { if (+gm->type() & MatrixType::Diagonal) { REPORT return MatrixBandWidth(0,0); } else { REPORT return -1; } } MatrixBandWidth RowedMatrix::bandwidth() const { REPORT return -1; } MatrixBandWidth ColedMatrix::bandwidth() const { REPORT return -1; } MatrixBandWidth DiagedMatrix::bandwidth() const { REPORT return 0; } MatrixBandWidth MatedMatrix::bandwidth() const { REPORT return -1; } MatrixBandWidth ReturnMatrix::bandwidth() const { REPORT return gm->bandwidth(); } MatrixBandWidth GetSubMatrix::bandwidth() const { if (row_skip==col_skip && row_number==col_number) { REPORT return gm->bandwidth(); } else { REPORT return MatrixBandWidth(-1); } } // ********************** the memory managment tools **********************/ // Rules regarding tDelete, reuse, GetStore, BorrowStore // All matrices processed during expression evaluation must be subject // to exactly one of reuse(), tDelete(), GetStore() or BorrowStore(). // If reuse returns true the matrix must be reused. // GetMatrix(gm) always calls gm->GetStore() // gm->Evaluate obeys rules // bm->Evaluate obeys rules for matrices in bm structure // Meaning of tag_val // tag_val = -1 memory cannot be reused (default situation) // tag_val = -2 memory has been borrowed from another matrix // (don't change values) // tag_val = i > 0 delete or reuse memory after i operations // tag_val = 0 like value 1 but matrix was created by new // so delete it void GeneralMatrix::tDelete() { if (tag_val<0) { if (tag_val<-1) { REPORT store = 0; delete this; return; } // borrowed else { REPORT return; } // not a temporary matrix - leave alone } if (tag_val==1) { if (store) { REPORT MONITOR_REAL_DELETE("Free (tDelete)",storage,store) delete [] store; } MiniCleanUp(); return; // CleanUp } if (tag_val==0) { REPORT delete this; return; } REPORT tag_val--; return; } void newmat_block_copy(int n, Real* from, Real* to) { REPORT int i = (n >> 3); while (i--) { *to++ = *from++; *to++ = *from++; *to++ = *from++; *to++ = *from++; *to++ = *from++; *to++ = *from++; *to++ = *from++; *to++ = *from++; } i = n & 7; while (i--) *to++ = *from++; } bool GeneralMatrix::reuse() { if (tag_val < -1) // borrowed storage { if (storage) { REPORT Real* s = new Real [storage]; MatrixErrorNoSpace(s); MONITOR_REAL_NEW("Make (reuse)",storage,s) newmat_block_copy(storage, store, s); store = s; } else { REPORT MiniCleanUp(); } // CleanUp tag_val = 0; return true; } if (tag_val < 0 ) { REPORT return false; } if (tag_val <= 1 ) { REPORT return true; } REPORT tag_val--; return false; } Real* GeneralMatrix::GetStore() { if (tag_val<0 || tag_val>1) { Real* s; if (storage) { s = new Real [storage]; MatrixErrorNoSpace(s); MONITOR_REAL_NEW("Make (GetStore)",storage,s) newmat_block_copy(storage, store, s); } else s = 0; if (tag_val > 1) { REPORT tag_val--; } else if (tag_val < -1) { REPORT store = 0; delete this; } // borrowed store else { REPORT } return s; } Real* s = store; // cleanup - done later if (tag_val==0) { REPORT store = 0; delete this; } else { REPORT MiniCleanUp(); } return s; } void GeneralMatrix::GetMatrix(const GeneralMatrix* gmx) { REPORT tag_val=-1; nrows_val=gmx->Nrows(); ncols_val=gmx->Ncols(); storage=gmx->storage; SetParameters(gmx); store=((GeneralMatrix*)gmx)->GetStore(); } GeneralMatrix* GeneralMatrix::BorrowStore(GeneralMatrix* gmx, MatrixType mt) // Copy storage of *this to storage of *gmx. Then convert to type mt. // If mt == 0 just let *gmx point to storage of *this if tag_val==-1. { if (!mt) { if (tag_val == -1) { REPORT gmx->tag_val = -2; gmx->store = store; } else { REPORT gmx->tag_val = 0; gmx->store = GetStore(); } } else if (Compare(gmx->type(),mt)) { REPORT gmx->tag_val = 0; gmx->store = GetStore(); } else { REPORT gmx->tag_val = -2; gmx->store = store; gmx = gmx->Evaluate(mt); gmx->tag_val = 0; tDelete(); } return gmx; } void GeneralMatrix::Eq(const BaseMatrix& X, MatrixType mt) // Count number of references to this in X. // If zero delete storage in this; // otherwise tag this to show when storage can be deleted // evaluate X and copy to this { #ifdef DO_SEARCH int counter=X.search(this); if (counter==0) { REPORT if (store) { MONITOR_REAL_DELETE("Free (operator=)",storage,store) REPORT delete [] store; storage = 0; store = 0; } } else { REPORT Release(counter); } GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt); if (gmx!=this) { REPORT GetMatrix(gmx); } else { REPORT } Protect(); #else GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt); if (gmx!=this) { REPORT if (store) { MONITOR_REAL_DELETE("Free (operator=)",storage,store) REPORT delete [] store; storage = 0; store = 0; } GetMatrix(gmx); } else { REPORT } Protect(); #endif } // version with no conversion void GeneralMatrix::Eq(const GeneralMatrix& X) { GeneralMatrix* gmx = (GeneralMatrix*)&X; if (gmx!=this) { REPORT if (store) { MONITOR_REAL_DELETE("Free (operator=)",storage,store) REPORT delete [] store; storage = 0; store = 0; } GetMatrix(gmx); } else { REPORT } Protect(); } // version to work with operator<< void GeneralMatrix::Eq(const BaseMatrix& X, MatrixType mt, bool ldok) { REPORT if (ldok) mt.SetDataLossOK(); Eq(X, mt); } void GeneralMatrix::Eq2(const BaseMatrix& X, MatrixType mt) // a cut down version of Eq for use with += etc. // we know BaseMatrix points to two GeneralMatrix objects, // the first being this (may be the same). // we know tag_val has been set correctly in each. { GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt); if (gmx!=this) { REPORT GetMatrix(gmx); } // simplify GetMatrix ? else { REPORT } Protect(); } void GeneralMatrix::inject(const GeneralMatrix& X) // copy stored values of X; otherwise leave els of *this unchanged { REPORT Tracer tr("inject"); if (nrows_val != X.nrows_val || ncols_val != X.ncols_val) Throw(IncompatibleDimensionsException()); MatrixRow mr((GeneralMatrix*)&X, LoadOnEntry); MatrixRow mrx(this, LoadOnEntry+StoreOnExit+DirectPart); int i=nrows_val; while (i--) { mrx.Inject(mr); mrx.Next(); mr.Next(); } } // ************* checking for data loss during conversion *******************/ bool Compare(const MatrixType& source, MatrixType& destination) { if (!destination) { destination=source; return true; } if (destination==source) return true; if (!destination.DataLossOK && !(destination>=source)) Throw(ProgramException("Illegal Conversion", source, destination)); return false; } // ************* Make a copy of a matrix on the heap *********************/ GeneralMatrix* Matrix::Image() const { REPORT GeneralMatrix* gm = new Matrix(*this); MatrixErrorNoSpace(gm); return gm; } GeneralMatrix* SquareMatrix::Image() const { REPORT GeneralMatrix* gm = new SquareMatrix(*this); MatrixErrorNoSpace(gm); return gm; } GeneralMatrix* SymmetricMatrix::Image() const { REPORT GeneralMatrix* gm = new SymmetricMatrix(*this); MatrixErrorNoSpace(gm); return gm; } GeneralMatrix* UpperTriangularMatrix::Image() const { REPORT GeneralMatrix* gm = new UpperTriangularMatrix(*this); MatrixErrorNoSpace(gm); return gm; } GeneralMatrix* LowerTriangularMatrix::Image() const { REPORT GeneralMatrix* gm = new LowerTriangularMatrix(*this); MatrixErrorNoSpace(gm); return gm; } GeneralMatrix* DiagonalMatrix::Image() const { REPORT GeneralMatrix* gm = new DiagonalMatrix(*this); MatrixErrorNoSpace(gm); return gm; } GeneralMatrix* RowVector::Image() const { REPORT GeneralMatrix* gm = new RowVector(*this); MatrixErrorNoSpace(gm); return gm; } GeneralMatrix* ColumnVector::Image() const { REPORT GeneralMatrix* gm = new ColumnVector(*this); MatrixErrorNoSpace(gm); return gm; } GeneralMatrix* nricMatrix::Image() const { REPORT GeneralMatrix* gm = new nricMatrix(*this); MatrixErrorNoSpace(gm); return gm; } GeneralMatrix* IdentityMatrix::Image() const { REPORT GeneralMatrix* gm = new IdentityMatrix(*this); MatrixErrorNoSpace(gm); return gm; } GeneralMatrix* CroutMatrix::Image() const { REPORT GeneralMatrix* gm = new CroutMatrix(*this); MatrixErrorNoSpace(gm); return gm; } GeneralMatrix* GeneralMatrix::Image() const { bool dummy = true; if (dummy) // get rid of warning message Throw(InternalException("Cannot apply Image to this matrix type")); return 0; } // *********************** nricMatrix routines *****************************/ void nricMatrix::MakeRowPointer() { REPORT if (nrows_val > 0) { row_pointer = new Real* [nrows_val]; MatrixErrorNoSpace(row_pointer); Real* s = Store() - 1; int i = nrows_val; Real** rp = row_pointer; if (i) for (;;) { *rp++ = s; if (!(--i)) break; s+=ncols_val; } } else row_pointer = 0; } void nricMatrix::DeleteRowPointer() { REPORT if (nrows_val) delete [] row_pointer; } void GeneralMatrix::CheckStore() const { REPORT if (!store) Throw(ProgramException("NRIC accessing matrix with unset dimensions")); } // *************************** CleanUp routines *****************************/ void GeneralMatrix::cleanup() { // set matrix dimensions to zero, delete storage REPORT if (store && storage) { MONITOR_REAL_DELETE("Free (cleanup) ",storage,store) REPORT delete [] store; } store=0; storage=0; nrows_val=0; ncols_val=0; tag_val = -1; } void nricMatrix::cleanup() { REPORT DeleteRowPointer(); GeneralMatrix::cleanup(); } void nricMatrix::MiniCleanUp() { REPORT DeleteRowPointer(); GeneralMatrix::MiniCleanUp(); } void RowVector::cleanup() { REPORT GeneralMatrix::cleanup(); nrows_val=1; } void ColumnVector::cleanup() { REPORT GeneralMatrix::cleanup(); ncols_val=1; } void CroutMatrix::cleanup() { REPORT if (nrows_val) delete [] indx; GeneralMatrix::cleanup(); } void CroutMatrix::MiniCleanUp() { REPORT if (nrows_val) delete [] indx; GeneralMatrix::MiniCleanUp(); } void BandLUMatrix::cleanup() { REPORT if (nrows_val) delete [] indx; if (storage2) delete [] store2; GeneralMatrix::cleanup(); } void BandLUMatrix::MiniCleanUp() { REPORT if (nrows_val) delete [] indx; if (storage2) delete [] store2; GeneralMatrix::MiniCleanUp(); } // ************************ simple integer array class *********************** // construct a new array of length xn. Check that xn is non-negative and // that space is available SimpleIntArray::SimpleIntArray(int xn) : n(xn) { if (n < 0) Throw(Logic_error("invalid array length")); else if (n == 0) { REPORT a = 0; } else { REPORT a = new int [n]; if (!a) Throw(Bad_alloc()); } } // destroy an array - return its space to memory SimpleIntArray::~SimpleIntArray() { REPORT if (a) delete [] a; } // access an element of an array; return a "reference" so elements // can be modified. // check index is within range // in this array class the index runs from 0 to n-1 int& SimpleIntArray::operator[](int i) { REPORT if (i < 0 || i >= n) Throw(Logic_error("array index out of range")); return a[i]; } // same thing again but for arrays declared constant so we can't // modify its elements int SimpleIntArray::operator[](int i) const { REPORT if (i < 0 || i >= n) Throw(Logic_error("array index out of range")); return a[i]; } // set all the elements equal to a given value void SimpleIntArray::operator=(int ai) { REPORT for (int i = 0; i < n; i++) a[i] = ai; } // set the elements equal to those of another array. // now allow length to be changed void SimpleIntArray::operator=(const SimpleIntArray& b) { REPORT if (b.n != n) resize(b.n); for (int i = 0; i < n; i++) a[i] = b.a[i]; } // construct a new array equal to an existing array // check that space is available SimpleIntArray::SimpleIntArray(const SimpleIntArray& b) : Janitor(), n(b.n) { if (n == 0) { REPORT a = 0; } else { REPORT a = new int [n]; if (!a) Throw(Bad_alloc()); for (int i = 0; i < n; i++) a[i] = b.a[i]; } } // change the size of an array; optionally copy data from old array to // new array void SimpleIntArray::resize(int n1, bool keep) { if (n1 == n) { REPORT return; } else if (n1 == 0) { REPORT n = 0; delete [] a; a = 0; } else if (n == 0) { REPORT a = new int [n1]; if (!a) Throw(Bad_alloc()); n = n1; if (keep) operator=(0); } else { int* a1 = a; if (keep) { REPORT int i; a = new int [n1]; if (!a) Throw(Bad_alloc()); if (n > n1) n = n1; else for (i = n; i < n1; i++) a[i] = 0; for (i = 0; i < n; i++) a[i] = a1[i]; n = n1; delete [] a1; } else { REPORT n = n1; delete [] a1; a = new int [n]; if (!a) Throw(Bad_alloc()); } } } //************************** swap values ******************************** // swap values void GeneralMatrix::swap(GeneralMatrix& gm) { REPORT int t; t = tag_val; tag_val = gm.tag_val; gm.tag_val = t; t = nrows_val; nrows_val = gm.nrows_val; gm.nrows_val = t; t = ncols_val; ncols_val = gm.ncols_val; gm.ncols_val = t; t = storage; storage = gm.storage; gm.storage = t; Real* s = store; store = gm.store; gm.store = s; } void nricMatrix::swap(nricMatrix& gm) { REPORT GeneralMatrix::swap((GeneralMatrix&)gm); Real** rp = row_pointer; row_pointer = gm.row_pointer; gm.row_pointer = rp; } void CroutMatrix::swap(CroutMatrix& gm) { REPORT GeneralMatrix::swap((GeneralMatrix&)gm); int* i = indx; indx = gm.indx; gm.indx = i; bool b; b = d; d = gm.d; gm.d = b; b = sing; sing = gm.sing; gm.sing = b; } void BandMatrix::swap(BandMatrix& gm) { REPORT GeneralMatrix::swap((GeneralMatrix&)gm); int i; i = lower_val; lower_val = gm.lower_val; gm.lower_val = i; i = upper_val; upper_val = gm.upper_val; gm.upper_val = i; } void SymmetricBandMatrix::swap(SymmetricBandMatrix& gm) { REPORT GeneralMatrix::swap((GeneralMatrix&)gm); int i; i = lower_val; lower_val = gm.lower_val; gm.lower_val = i; } void BandLUMatrix::swap(BandLUMatrix& gm) { REPORT GeneralMatrix::swap((GeneralMatrix&)gm); int* i = indx; indx = gm.indx; gm.indx = i; bool b; b = d; d = gm.d; gm.d = b; b = sing; sing = gm.sing; gm.sing = b; int m; m = storage2; storage2 = gm.storage2; gm.storage2 = m; m = m1; m1 = gm.m1; gm.m1 = m; m = m2; m2 = gm.m2; gm.m2 = m; Real* s = store2; store2 = gm.store2; gm.store2 = s; } void GenericMatrix::swap(GenericMatrix& x) { REPORT GeneralMatrix* tgm = gm; gm = x.gm; x.gm = tgm; } // ********************** C subscript classes **************************** RealStarStar::RealStarStar(Matrix& A) { REPORT Tracer tr("RealStarStar"); int n = A.ncols(); int m = A.nrows(); a = new Real*[m]; MatrixErrorNoSpace(a); Real* d = A.data(); for (int i = 0; i < m; ++i) a[i] = d + i * n; } ConstRealStarStar::ConstRealStarStar(const Matrix& A) { REPORT Tracer tr("ConstRealStarStar"); int n = A.ncols(); int m = A.nrows(); a = new const Real*[m]; MatrixErrorNoSpace(a); const Real* d = A.data(); for (int i = 0; i < m; ++i) a[i] = d + i * n; } #ifdef use_namespace } #endif /// \fn GeneralMatrix::SimpleAddOK(const GeneralMatrix* gm) /// Can we add two matrices with simple vector add. /// SimpleAddOK shows when we can add two matrices by a simple vector add /// and when we can add one matrix into another /// /// *gm must be the same type as *this /// - return 0 if simple add is OK /// - return 1 if we can add into *gm only /// - return 2 if we can add into *this only /// - return 3 if we can't add either way /// /// Also applies to subtract; /// for SP this will still be valid if we swap 1 and 2 /// /// For types Matrix, DiagonalMatrix, UpperTriangularMatrix, /// LowerTriangularMatrix, SymmetricMatrix etc return 0. /// For band matrices we will need to check bandwidths. ///@}