From 5488183118e790b521432805b9f02f43967825e4 Mon Sep 17 00:00:00 2001 From: jiri Date: Thu, 6 Apr 2006 21:45:51 +0000 Subject: [PATCH] *** empty log message *** --- davidson.h | 10 +++++---- fourindex.h | 16 ++++++++------ mat.cc | 15 +++++++------ mat.h | 3 ++- smat.cc | 29 +++++++++++++++++++++++-- smat.h | 60 ++++++++++++++++++++++++++++++++++++++++++---------- sparsemat.cc | 11 +++++----- sparsemat.h | 3 ++- test.cc | 8 +++++++ vec.cc | 10 ++++----- vec.h | 32 ++++++++++++++++++++++++++-- 11 files changed, 152 insertions(+), 45 deletions(-) diff --git a/davidson.h b/davidson.h index 81959d9..43f080d 100644 --- a/davidson.h +++ b/davidson.h @@ -11,6 +11,8 @@ //matrix can be any class which has nrows(), ncols(), diagonalof(), issymmetric(), and gemv() available //does not even have to be explicitly stored - direct CI +//therefore the whole implementation must be a template in a header +//Note that for efficiency in a direct CI case the diagonalof() should cache its result export template extern void davidson(const Matrix &bigmat, NRVec &eivals, NRVec *eivecs, const char *eivecsfile, @@ -62,10 +64,10 @@ int oldnroot; smallS=0; smallH=0; //guess based on lowest diagonal element of the matrix -bigmat.diagonalof(vec2); +const T *diagonal = bigmat.diagonalof(vec2,false,true); vec1=0; {T t=1e100; int i,j; -for(i=0, j= -1; iget(vec2,j); vec1.axpy(smallV(j,nroot),incore?v1[j]:vec2); } -bigmat.diagonalof(vec2); +diagonal = bigmat.diagonalof(vec2,false,true); eival_n = r[nroot]; for(i=0; i union packed_index { I packed[4]; @@ -565,28 +567,28 @@ for(p=rhs.begin(); p!= rhs.end(); ++p) (*this)(p->index.indiv.i,p->index.indiv.j template T& fourindex_dense::operator() (unsigned int i, unsigned int j, unsigned int k, unsigned int l) { -unsigned long I = i>j? i*(i-1)/2+j-1 : j*(j-1)/2+i-1; -unsigned long J = k>l? k*(k-1)/2+l-1 : l*(l-1)/2+k-1; +unsigned long I = SMat_index_1(i,j); +unsigned long J = SMat_index_1(k,l); //I,J act as indices of a NRSmat #ifdef DEBUG if (*count != 1) laerror("lval (i,j,k,l) with count > 1 in fourindex_dense"); if (I<0 || I>=(unsigned long)nn || J<0 || J>=(unsigned long)nn) laerror("fourindex_dense index out of range"); if (!v) laerror("access to unallocated fourindex_dense"); #endif -return I>=J ? v[I*(I+1)/2+J] : v[J*(J+1)/2+I]; +return v[SMat_index(I,J)]; } template const T& fourindex_dense::operator() (unsigned int i, unsigned int j, unsigned int k, unsigned int l) const { -unsigned long I = i>j? i*(i-1)/2+j-1 : j*(j-1)/2+i-1; -unsigned long J = k>l? k*(k-1)/2+l-1 : l*(l-1)/2+k-1; +unsigned long I = SMat_index_1(i,j); +unsigned long J = SMat_index_1(k,l); //I,J act as indices of a NRSmat #ifdef DEBUG - if (I<0 || I>=nn || J<0 || J>=nn) laerror("fourindex_dense index out of range"); + if (I<0 || I>=(unsigned long)nn || J<0 || J>=(unsigned long)nn) laerror("fourindex_dense index out of range"); if (!v) laerror("access to unallocated fourindex_dense"); #endif -return I>=J ? v[I*(I+1)/2+J] : v[J*(J+1)/2+I]; +return v[SMat_index(I,J)]; } diff --git a/mat.cc b/mat.cc index 58f3769..2707835 100644 --- a/mat.cc +++ b/mat.cc @@ -866,12 +866,12 @@ void NRMat::gemm(const double &beta, const NRMat &a, const char transa, const NRMat &b, const char transb, const double &alpha) { - int l(transa=='n'?a.nn:a.mm); int k(transa=='n'?a.mm:a.nn); - int kk(transb=='n'?b.nn:b.mm); - int ll(transb=='n'?b.mm:b.nn); #ifdef DEBUG + int l(transa=='n'?a.nn:a.mm); + int kk(transb=='n'?b.nn:b.mm); + int ll(transb=='n'?b.mm:b.nn); if (l!=nn || ll!=mm || k!=kk) laerror("incompatible matrices in Mat:gemm()"); #endif if (alpha==0.0 && beta==1.0) return; @@ -890,12 +890,12 @@ void NRMat< complex >::gemm(const complex & beta, const NRMat< complex > & b, const char transb, const complex & alpha) { - int l(transa=='n'?a.nn:a.mm); int k(transa=='n'?a.mm:a.nn); - int kk(transb=='n'?b.nn:b.mm); - int ll(transb=='n'?b.mm:b.nn); #ifdef DEBUG + int l(transa=='n'?a.nn:a.mm); + int kk(transb=='n'?b.nn:b.mm); + int ll(transb=='n'?b.mm:b.nn); if (l!=nn || ll!=mm || k!=kk) laerror("incompatible matrices in Mat:gemm()"); #endif if (alpha==CZERO && beta==CONE) return; @@ -1013,7 +1013,7 @@ const complex NRMat< complex >::trace() const //get diagonal; for compatibility with large matrices do not return newly created object //for non-square get diagonal of A^TA, will be used as preconditioner template<> -void NRMat::diagonalof(NRVec &r, const bool divide) const +const double * NRMat::diagonalof(NRVec &r, const bool divide, bool cache) const { #ifdef DEBUG if (r.size() != nn) laerror("diagonalof() incompatible vector"); @@ -1047,6 +1047,7 @@ for (int i=0; i< mm; i++) } } +return divide?NULL:&r[0]; } diff --git a/mat.h b/mat.h index b7030e4..4117695 100644 --- a/mat.h +++ b/mat.h @@ -71,7 +71,8 @@ public: const NRVec csum() const; //sum of columns const NRVec row(const int i) const; //row of, efficient const NRVec column(const int j) const {NRVec r(nn); for(int i=0; i &, const bool divide=0) const; //get diagonal + const T* diagonalof(NRVec &, const bool divide=0, bool cache=false) const; //get diagonal + void gemv(const T beta, NRVec &r, const char trans, const T alpha, const NRVec &x) const {r.gemv(beta,*this,trans,alpha,x);}; inline T* operator[](const int i); //subscripting: pointer to row i inline const T* operator[](const int i) const; inline T& operator()(const int i, const int j); // (i,j) subscripts diff --git a/smat.cc b/smat.cc index b7624ee..cb30cd6 100644 --- a/smat.cc +++ b/smat.cc @@ -85,7 +85,7 @@ NRSMat & NRSMat::operator=(const T &a) //get diagonal template -void NRSMat::diagonalof(NRVec &r, const bool divide) const +const T* NRSMat::diagonalof(NRVec &r, const bool divide, bool cache) const { #ifdef DEBUG if(r.size()!=nn) laerror("incompatible vector in diagonalof()"); @@ -97,6 +97,7 @@ if (divide) for (int i=0; i >::dot(const NRSMat< complex > &rhs) const if (nn != rhs.nn) laerror("dot of incompatible SMat's"); #endif complex dot; - cblas_zdotc_sub(nn, (void *)v, 1, (void *)rhs.v, 1, (void *)(&dot)); + cblas_zdotc_sub(NN2, (void *)v, 1, (void *)rhs.v, 1, (void *)(&dot)); + return dot; +} + + +template<> +const double NRSMat::dot(const NRVec &rhs) const +{ +#ifdef DEBUG + if (NN2 != rhs.nn) laerror("dot of incompatible SMat's"); +#endif + return cblas_ddot(NN2, v, 1, rhs.v, 1); +} + + + +template<> +const complex +NRSMat< complex >::dot(const NRVec< complex > &rhs) const +{ +#ifdef DEBUG + if (NN2 != rhs.nn) laerror("dot of incompatible SMat's"); +#endif + complex dot; + cblas_zdotc_sub(NN2, (void *)v, 1, (void *)rhs.v, 1, (void *)(&dot)); return dot; } diff --git a/smat.h b/smat.h index fadeb4b..026cd31 100644 --- a/smat.h +++ b/smat.h @@ -43,8 +43,10 @@ public: 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 T dot(const NRVec &rhs) const; //Smat(as vec).vec //@@@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 + const T* diagonalof(NRVec &, const bool divide=0, bool cache=false) const; //get diagonal + void gemv(const T beta, NRVec &r, const char trans, const T alpha, const NRVec &x) const {r.gemv(beta,*this,trans,alpha,x);}; 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; @@ -52,6 +54,7 @@ public: inline int nrows() const; inline int ncols() const; inline int size() const; + inline bool transp(const int i, const int j) const {return i>j;} //this can be used for compact storage of matrices, which are actually not symmetric, but one triangle of them is redundant 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; @@ -274,6 +277,18 @@ inline const T & NRSMat::operator[](const int ij) const return v[ij]; } +template +inline T SMat_index(T i, T j) +{ +return i>=j ? i*(i+1)/2+j : j*(j+1)/2+i; +} + +template +inline T SMat_index_1(T i, T j) +{ +return i>j? i*(i-1)/2+j-1 : j*(j-1)/2+i-1; +} + // access the element, 2-dim array case template inline T & NRSMat::operator()(const int i, const int j) @@ -283,7 +298,7 @@ inline T & NRSMat::operator()(const int i, const int j) 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 v[SMat_index(i,j)]; } template inline const T & NRSMat::operator()(const int i, const int j) const @@ -292,7 +307,7 @@ inline const T & NRSMat::operator()(const int i, const int j) const 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 v[SMat_index(i,j)]; } // return the number of rows and columns @@ -471,18 +486,10 @@ for(int i=0; i 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,-) @@ -491,4 +498,35 @@ NRVECMAT_OPER(SMat,*) NRVECMAT_OPER2(SMat,+) NRVECMAT_OPER2(SMat,-) +//optional indexing from 1 +//all possible constructors have to be given explicitly, other stuff is inherited +//with exception of the operator() which differs +template +class NRSMat_from1 : public NRSMat { +public: + NRSMat_from1(): NRSMat() {}; + explicit NRSMat_from1(const int n): NRSMat(n) {}; + NRSMat_from1(const NRSMat &rhs): NRSMat(rhs) {}; //be able to convert the parent class transparently to this + NRSMat_from1(const T &a, const int n): NRSMat(a,n) {}; + NRSMat_from1(const T *a, const int n): NRSMat(a,n) {}; + explicit NRSMat_from1(const NRMat &rhs): NRSMat(rhs) {}; + explicit NRSMat_from1(const NRVec &rhs, const int n): NRSMat(rhs,n) {}; + + inline const T& operator() (const int i, const int j) const + { +#ifdef DEBUG + if(i<=0||j<=0||i>nn||j>nn) laerror("index out of range in NRSMat_from1"); +#endif + return v[SMat_index_1(i,j)]; + } + inline T& operator() (const int i, const int j) + { +#ifdef DEBUG + if(i<=0||j<=0||i>nn||j>nn) laerror("index out of range in NRSMat_from1"); +#endif + return v[SMat_index_1(i,j)]; + } +}; + + #endif /* _LA_SMAT_H_ */ diff --git a/sparsemat.cc b/sparsemat.cc index 74a8683..ede2dad 100644 --- a/sparsemat.cc +++ b/sparsemat.cc @@ -579,7 +579,7 @@ for(i=0;i -void SparseMat::diagonalof(NRVec &r, const bool divide) const +const T* SparseMat::diagonalof(NRVec &r, const bool divide, bool cache) const { #ifdef DEBUG if((int)mm!=r.size()) laerror("incompatible vector size in diagonalof()"); @@ -607,6 +607,7 @@ if(divide) for(unsigned int i=0; i -void NRVec::gemv(const T beta, const SparseMat &a, const char trans, const T alpha, const NRVec &x) +void NRVec::gemv(const T beta, const SparseMat &a, const char trans, const T alpha, const NRVec &x, const bool treat_as_symmetric) { if((trans=='n'?a.ncols():a.nrows())!= (SPMatindex)x.size()) laerror("incompatible sizes in gemv"); copyonwrite(); @@ -893,7 +894,7 @@ T *vec=x.v; if(alpha==(T)1) { - if(a.issymmetric()) + if(a.issymmetric()||treat_as_symmetric) { while(l) { @@ -920,7 +921,7 @@ if(alpha==(T)1) } else { - if(a.issymmetric()) + if(a.issymmetric()||treat_as_symmetric) { while(l) { @@ -1350,7 +1351,7 @@ template void SparseMat::axpy(const T alpha, const SparseMat &x, const boo template const SparseMat SparseMat::operator*(const SparseMat &rhs) const; \ template const T SparseMat::dot(const SparseMat &rhs) const; \ template void SparseMat::gemm(const T beta, const SparseMat &a, const char transa, const SparseMat &b, const char transb, const T alpha); \ -template void NRVec::gemv(const T beta, const SparseMat &a, const char trans, const T alpha, const NRVec &x);\ +template void NRVec::gemv(const T beta, const SparseMat &a, const char trans, const T alpha, const NRVec &x, const bool treat_as_symmetric);\ template void SparseMat::permuterows(const NRVec &p);\ template void SparseMat::permutecolumns(const NRVec &p);\ template void SparseMat::permuteindices(const NRVec &p);\ diff --git a/sparsemat.h b/sparsemat.h index 1b611eb..b7abeb0 100644 --- a/sparsemat.h +++ b/sparsemat.h @@ -79,7 +79,8 @@ public: inline const SparseMat operator-(const SparseMat &rhs) const {return SparseMat(*this) -= rhs;} //must not be symmetric+general inline const NRVec operator*(const NRVec &rhs) const; // SparseMat * Vec inline const NRMat operator*(const NRMat &rhs) const; // SparseMat * Mat - void diagonalof(NRVec &, const bool divide=0) const; //get diagonal + const T* diagonalof(NRVec &, const bool divide=0, bool cache=false) const; //get diagonal + void gemv(const T beta, NRVec &r, const char trans, const T alpha, const NRVec &x, bool treat_as_symmetric=false) const {r.gemv(beta,*this,trans,alpha,x,treat_as_symmetric);}; const SparseMat operator*(const SparseMat &rhs) const; SparseMat & oplusequal(const SparseMat &rhs); //direct sum SparseMat & oplusequal(const NRMat &rhs); diff --git a/test.cc b/test.cc index c2a58d5..4b0a3fb 100644 --- a/test.cc +++ b/test.cc @@ -1,5 +1,7 @@ #include "bitvector.h" #include "qsort.h" +#include "la.h" +#include "fourindex.h" int main(void) @@ -31,4 +33,10 @@ ptrqsortup(&t[0],&t[9],&u[0]); cout< void NRVec::gemv(const int beta, const SparseMat &A, const char trans, - const int alpha, const NRVec &x) + const int alpha, const NRVec &x, bool s) { laerror("not yet implemented"); } @@ -385,7 +385,7 @@ laerror("not yet implemented"); template<> void NRVec::gemv(const short beta, const SparseMat &A, const char trans, - const short alpha, const NRVec &x) + const short alpha, const NRVec &x, bool s) { laerror("not yet implemented"); } @@ -394,7 +394,7 @@ laerror("not yet implemented"); template<> void NRVec::gemv(const char beta, const SparseMat &A, const char trans, - const char alpha, const NRVec &x) + const char alpha, const NRVec &x, bool s) { laerror("not yet implemented"); } @@ -402,7 +402,7 @@ laerror("not yet implemented"); template<> void NRVec::gemv(const unsigned long beta, const SparseMat &A, const char trans, - const unsigned long alpha, const NRVec &x) + const unsigned long alpha, const NRVec &x, bool s) { laerror("not yet implemented"); } @@ -410,7 +410,7 @@ laerror("not yet implemented"); template<> void NRVec::gemv(const unsigned char beta, const SparseMat &A, const char trans, - const unsigned char alpha, const NRVec &x) + const unsigned char alpha, const NRVec &x, bool s) { laerror("not yet implemented"); } diff --git a/vec.h b/vec.h index ae72268..8ab9e79 100644 --- a/vec.h +++ b/vec.h @@ -62,6 +62,8 @@ public: const NRVec operator-() const; inline NRVec & operator+=(const NRVec &rhs); inline NRVec & operator-=(const NRVec &rhs); + inline NRVec & operator*=(const NRVec &rhs); //elementwise + inline NRVec & operator/=(const NRVec &rhs); //elementwise inline NRVec & operator+=(const T &a); inline NRVec & operator-=(const T &a); inline NRVec & operator*=(const T &a); @@ -75,7 +77,7 @@ public: inline const T dot(const NRVec &rhs) const {return *this * rhs;}; //@@@for complex do conjugate void gemv(const T beta, const NRMat &a, const char trans, const T alpha, const NRVec &x); void gemv(const T beta, const NRSMat &a, const char trans /*just for compatibility*/, const T alpha, const NRVec &x); - void gemv(const T beta, const SparseMat &a, const char trans, const T alpha, const NRVec &x); + void gemv(const T beta, const SparseMat &a, const char trans, const T alpha, const NRVec &x,const bool treat_as_symmetric=false); const NRVec operator*(const NRMat &mat) const {NRVec result(mat.ncols()); result.gemv((T)0,mat,'t',(T)1,*this); return result;}; const NRVec operator*(const NRSMat &mat) const {NRVec result(mat.ncols()); result.gemv((T)0,mat,'t',(T)1,*this); return result;}; const NRVec operator*(const SparseMat &mat) const {NRVec result(mat.ncols()); result.gemv((T)0,mat,'t',(T)1,*this); return result;}; @@ -253,6 +255,32 @@ inline NRVec & NRVec::operator+=(const NRVec &rhs) return *this; } +//for general type only +template +inline NRVec & NRVec::operator*=(const NRVec &rhs) +{ +#ifdef DEBUG + if (nn != rhs.nn) laerror("*= of incompatible vectors"); +#endif + copyonwrite(); + int i; + for(i=0; i +inline NRVec & NRVec::operator/=(const NRVec &rhs) +{ +#ifdef DEBUG + if (nn != rhs.nn) laerror("/= of incompatible vectors"); +#endif + copyonwrite(); + int i; + for(i=0; i @@ -568,7 +596,7 @@ void NRVec::resize(const int n) } -// assignmet with a physical (deep) copy +// assignment with a physical (deep) copy template NRVec & NRVec::operator|=(const NRVec &rhs) {