#ifndef _LA_SMAT_H_ #define _LA_SMAT_H_ #include "la_traits.h" #define NN2 (nn*(nn+1)/2) template class NRSMat { // symmetric or complex hermitean matrix in packed form protected: int nn; T *v; int *count; public: friend class NRVec; friend class NRMat; inline NRSMat::NRSMat() : nn(0),v(0),count(0) {}; inline explicit NRSMat(const int n); // Zero-based array inline NRSMat(const T &a, const int n); //Initialize to constant inline NRSMat(const T *a, const int n); // Initialize to array inline NRSMat(const NRSMat &rhs); // Copy constructor explicit NRSMat(const NRMat &rhs); // symmetric part of general matrix explicit NRSMat(const NRVec &rhs, const int n); //construct matrix from vector NRSMat & operator|=(const NRSMat &rhs); //assignment to a new copy NRSMat & operator=(const NRSMat &rhs); //assignment NRSMat & operator=(const T &a); //assign a to diagonal const bool operator!=(const NRSMat &rhs) const {if(nn!=rhs.nn) return 1; return LA_traits::gencmp(v,rhs.v,NN2);} //memcmp for scalars else elementwise const bool operator==(const NRSMat &rhs) const {return !(*this != rhs);}; inline NRSMat & operator*=(const T &a); inline NRSMat & operator+=(const T &a); inline NRSMat & operator-=(const T &a); inline NRSMat & operator+=(const NRSMat &rhs); inline NRSMat & operator-=(const NRSMat &rhs); const NRSMat operator-() const; //unary minus inline int getcount() const {return count?*count:0;} inline const NRSMat operator*(const T &a) const; inline const NRSMat operator+(const T &a) const; inline const NRSMat operator-(const T &a) const; inline const NRSMat operator+(const NRSMat &rhs) const; inline const NRSMat operator-(const NRSMat &rhs) const; inline const NRMat operator+(const NRMat &rhs) const; inline const NRMat operator-(const NRMat &rhs) const; const NRMat operator*(const NRSMat &rhs) const; // SMat*SMat const NRMat operator*(const NRMat &rhs) const; // SMat*Mat const T dot(const NRSMat &rhs) const; // Smat.Smat//@@@for complex do conjugate const NRVec operator*(const NRVec &rhs) const {NRVec result(nn); result.gemv((T)0,*this,'n',(T)1,rhs); return result;}; // Mat * Vec void diagonalof(NRVec &, const bool divide=0) const; //get diagonal inline const T& operator[](const int ij) const; inline T& operator[](const int ij); inline const T& operator()(const int i, const int j) const; inline T& operator()(const int i, const int j); inline int nrows() const; inline int ncols() const; inline int size() const; const double norm(const T scalar=(T)0) const; void axpy(const T alpha, const NRSMat &x); // this+= a*x inline const T amax() const; const T trace() const; void get(int fd, bool dimensions=1, bool transp=0); void put(int fd, bool dimensions=1, bool transp=0) const; void copyonwrite(); void resize(const int n); inline operator T*(); //get a pointer to the data inline operator const T*() const; //get a pointer to the data ~NRSMat(); void fprintf(FILE *f, const char *format, const int modulo) const; void fscanf(FILE *f, const char *format); //members concerning sparse matrix explicit NRSMat(const SparseMat &rhs); // dense from sparse inline void simplify() {}; //just for compatibility with sparse ones bool issymmetric() const {return 1;} }; //due to mutual includes this has to be after full class declaration #include "vec.h" #include "mat.h" #include "sparsemat.h" // ctors template inline NRSMat::NRSMat(const int n) : nn(n), v(new T[NN2]), count(new int) {*count = 1;} template inline NRSMat::NRSMat(const T& a, const int n) : nn(n), v(new T[NN2]), count(new int) { *count =1; if(a != (T)0) for(int i=0; i inline NRSMat::NRSMat(const T *a, const int n) : nn(n), v(new T[NN2]), count(new int) { *count = 1; memcpy(v, a, NN2*sizeof(T)); } template inline NRSMat::NRSMat(const NRSMat &rhs) //copy constructor { v = rhs.v; nn = rhs.nn; count = rhs.count; if (count) (*count)++; } template NRSMat::NRSMat(const NRVec &rhs, const int n) // type conversion { nn = n; #ifdef DEBUG if (NN2 != rhs.size()) laerror("matrix dimensions incompatible with vector length"); #endif count = rhs.count; v = rhs.v; (*count)++; } // S *= a inline NRSMat & NRSMat::operator*=(const double & a) { copyonwrite(); cblas_dscal(NN2, a, v, 1); return *this; } inline NRSMat< complex > & NRSMat< complex >::operator*=(const complex & a) { copyonwrite(); cblas_zscal(NN2, (void *)(&a), (void *)v, 1); return *this; } template inline NRSMat & NRSMat::operator*=(const T & a) { copyonwrite(); for(int i=0; i inline NRSMat & NRSMat::operator+=(const T &a) { copyonwrite(); for (int i=0; i inline NRSMat & NRSMat::operator-=(const T &a) { copyonwrite(); for (int i=0; i & NRSMat::operator+=(const NRSMat & rhs) { #ifdef DEBUG if (nn != rhs.nn) laerror("incompatible SMats in SMat::operator+="); #endif copyonwrite(); cblas_daxpy(NN2, 1.0, rhs.v, 1, v, 1); return *this; } NRSMat< complex > & NRSMat< complex >::operator+=(const NRSMat< complex > & rhs) { #ifdef DEBUG if (nn != rhs.nn) laerror("incompatible SMats in SMat::operator+="); #endif copyonwrite(); cblas_zaxpy(NN2, (void *)(&CONE), (void *)(&rhs.v), 1, (void *)(&v), 1); return *this; } template inline NRSMat & NRSMat::operator+=(const NRSMat & rhs) { #ifdef DEBUG if (nn != rhs.nn) laerror("incompatible SMats in SMat::operator+="); #endif copyonwrite(); for(int i=0; i & NRSMat::operator-=(const NRSMat & rhs) { #ifdef DEBUG if (nn != rhs.nn) laerror("incompatible SMats in SMat::operator-="); #endif copyonwrite(); cblas_daxpy(NN2, -1.0, rhs.v, 1, v, 1); return *this; } inline NRSMat< complex > & NRSMat< complex >::operator-=(const NRSMat< complex > & rhs) { #ifdef DEBUG if (nn != rhs.nn) laerror("incompatible SMats in SMat::operator-="); #endif copyonwrite(); cblas_zaxpy(NN2, (void *)(&CMONE), (void *)(&rhs.v), 1, (void *)(&v), 1); return *this; } template inline NRSMat & NRSMat::operator-=(const NRSMat & rhs) { #ifdef DEBUG if (nn != rhs.nn) laerror("incompatible SMats in SMat::operator-="); #endif copyonwrite(); for(int i=0; i inline const NRMat NRSMat::operator+(const NRMat &rhs) const { return NRMat(rhs) += *this; } // SMat - Mat template inline const NRMat NRSMat::operator-(const NRMat &rhs) const { return NRMat(-rhs) += *this; } // access the element, linear array case template inline T & NRSMat::operator[](const int ij) { #ifdef DEBUG if (*count != 1) laerror("lval [] with count > 1 in Smat"); if (ij<0 || ij>=NN2) laerror("SMat [] out of range"); if (!v) laerror("[] for unallocated Smat"); #endif return v[ij]; } template inline const T & NRSMat::operator[](const int ij) const { #ifdef DEBUG if (ij<0 || ij>=NN2) laerror("SMat [] out of range"); if (!v) laerror("[] for unallocated Smat"); #endif return v[ij]; } // access the element, 2-dim array case template inline T & NRSMat::operator()(const int i, const int j) { #ifdef DEBUG if (*count != 1) laerror("lval (i,j) with count > 1 in Smat"); if (i<0 || i>=nn || j<0 || j>=nn) laerror("SMat (i,j) out of range"); if (!v) laerror("(i,j) for unallocated Smat"); #endif return i>=j ? v[i*(i+1)/2+j] : v[j*(j+1)/2+i]; } template inline const T & NRSMat::operator()(const int i, const int j) const { #ifdef DEBUG if (i<0 || i>=nn || j<0 || j>=nn) laerror("SMat (i,j) out of range"); if (!v) laerror("(i,j) for unallocated Smat"); #endif return i>=j ? v[i*(i+1)/2+j] : v[j*(j+1)/2+i]; } // return the number of rows and columns template inline int NRSMat::nrows() const { return nn; } template inline int NRSMat::ncols() const { return nn; } template inline int NRSMat::size() const { return NN2; } // max value inline const double NRSMat::amax() const { return v[cblas_idamax(NN2, v, 1)]; } inline const complex NRSMat< complex >::amax() const { return v[cblas_izamax(NN2, (void *)v, 1)]; } // reference pointer to Smat template inline NRSMat:: operator T*() { #ifdef DEBUG if (!v) laerror("unallocated SMat in operator T*"); #endif return v; } template inline NRSMat:: operator const T*() const { #ifdef DEBUG if (!v) laerror("unallocated SMat in operator T*"); #endif return v; } //basic stuff to be available for any type ... must be in .h // dtor template NRSMat::~NRSMat() { if (!count) return; if (--(*count) <= 0) { if (v) delete[] (v); delete count; } } // assignment with a physical copy template NRSMat & NRSMat::operator|=(const NRSMat &rhs) { if (this != &rhs) { if(!rhs.v) laerror("unallocated rhs in NRSMat operator |="); if(count) if(*count > 1) { // detach from the other --(*count); nn = 0; count = 0; v = 0; } if (nn != rhs.nn) { if(v) delete [] (v); nn = rhs.nn; } if (!v) v = new T[NN2]; if (!count) count = new int; *count = 1; memcpy(v, rhs.v, NN2*sizeof(T)); } return *this; } // assignment template NRSMat & NRSMat::operator=(const NRSMat & rhs) { if (this == & rhs) return *this; if (count) if(--(*count) == 0) { delete [] v; delete count; } v = rhs.v; nn = rhs.nn; count = rhs.count; if (count) (*count)++; return *this; } // make new instation of the Smat, deep copy template void NRSMat::copyonwrite() { #ifdef DEBUG if (!count) laerror("probably an assignment to undefined Smat"); #endif if (*count > 1) { (*count)--; count = new int; *count = 1; T *newv = new T[NN2]; memcpy(newv, v, NN2*sizeof(T)); v = newv; } } // resize Smat template void NRSMat::resize(const int n) { #ifdef DEBUG if (n < 0) laerror("illegal matrix dimension in resize of Smat"); #endif if (count) { if(n==0) { if(--(*count) <= 0) { if(v) delete[] (v); delete count; } count=0; nn=0; v=0; return; } if(*count > 1) { //detach from previous (*count)--; count = 0; v = 0; nn = 0; } } if (!count) { //new uninitialized vector or just detached count = new int; *count = 1; nn = n; v = new T[NN2]; return; } if (n != nn) { nn = n; delete[] v; v = new T[NN2]; } } // I/O template extern ostream& operator<<(ostream &s, const NRSMat &x); template extern istream& operator>>(istream &s, NRSMat &x); // generate operators: SMat + a, a + SMat, SMat * a NRVECMAT_OPER(SMat,+) NRVECMAT_OPER(SMat,-) NRVECMAT_OPER(SMat,*) // generate SMat + SMat, SMat - SMat NRVECMAT_OPER2(SMat,+) NRVECMAT_OPER2(SMat,-) #endif /* _LA_SMAT_H_ */