diff --git a/fourindex.h b/fourindex.h index 02451d3..d1b5167 100644 --- a/fourindex.h +++ b/fourindex.h @@ -1,5 +1,6 @@ #ifndef _fourindex_included #define _fourindex_included +#include #include //element of a linked list, indices in a portable way, no bit shifts and endianity problems any more! @@ -23,7 +24,7 @@ struct matel4 packedindex index; }; -typedef enum {nosymmetry=0, twoelectronrealmullikan=1, twoelectronrealdirac=2, T2ijab_real=3} fourindexsymtype; //if twoelectron, only permutation-nonequivalent elements are stored +typedef enum {nosymmetry=0, twoelectronrealmullikan=1, twoelectronrealdirac=2, T2ijab_real=3} fourindexsymtype; //only permutation-nonequivalent elements are stored // these should actually be static private members of the fourindex class, but leads to an ICE on gcc3.2 static const int fourindex_n_symmetrytypes=4; static const int fourindex_permnumbers[fourindex_n_symmetrytypes]={1,8,8,4}; diff --git a/la_traits.h b/la_traits.h index 77bb29b..43efda4 100644 --- a/la_traits.h +++ b/la_traits.h @@ -31,6 +31,26 @@ template class NRMat; template class NRSMat; template class SparseMat; +//we will need to treat char and unsigned char as numbers in << and >> I/O operators +template +struct LA_traits_io + { + typedef C IOtype; + }; + +template<> +struct LA_traits_io + { + typedef int IOtype; + }; + +template<> +struct LA_traits_io + { + typedef unsigned int IOtype; + }; + + //let's do some simple template metaprogramming and preprocessing //to keep the thing general and compact @@ -90,7 +110,7 @@ static inline void get(int fd, complex &x, bool dimensions=0, bool transp=0) static inline void put(int fd, const complex &x, bool dimensions=0, bool transp=0) {if(sizeof(complex)!=write(fd,&x,sizeof(complex))) laerror("write error");} static void multiget(unsigned int n,int fd, complex *x, bool dimensions=0){if((ssize_t)(n*sizeof(complex))!=read(fd,x,n*sizeof(complex))) laerror("read error");} static void multiput(unsigned int n, int fd, const complex *x, bool dimensions=0) {if((ssize_t)(n*sizeof(complex))!=write(fd,x,n*sizeof(complex))) laerror("write error");} - +static void copy(complex *dest, complex *src, unsigned int n) {memcpy(dest,src,n*sizeof(complex));} }; //non-complex scalars @@ -108,6 +128,7 @@ static inline void put(int fd, const C &x, bool dimensions=0, bool transp=0) {if static inline void get(int fd, C &x, bool dimensions=0, bool transp=0) {if(sizeof(C)!=read(fd,&x,sizeof(C))) laerror("read error");} static void multiput(unsigned int n,int fd, const C *x, bool dimensions=0){if((ssize_t)(n*sizeof(C))!=write(fd,x,n*sizeof(C))) laerror("write error");} static void multiget(unsigned int n, int fd, C *x, bool dimensions=0) {if((ssize_t)(n*sizeof(C))!=read(fd,x,n*sizeof(C))) laerror("read error");} +static void copy(C *dest, C *src, unsigned int n) {memcpy(dest,src,n*sizeof(C));} }; @@ -131,6 +152,7 @@ static void put(int fd, const C &x, bool dimensions=1, bool transp=0) {x.put(fd, static void get(int fd, C &x, bool dimensions=1, bool transp=0) {x.get(fd,dimensions,transp);} \ static void multiput(unsigned int n,int fd, const C *x, bool dimensions=1) {for(unsigned int i=0; i; -template class NRMat< complex >; +template class NRMat >; template class NRMat; template class NRMat; template class NRMat; +template class NRMat; +template class NRMat; /* * Templates first, specializations for BLAS next - */ +*/ + +//row of +template +const NRVec NRMat::row(const int i) const +{ +#ifdef DEBUG +if(i<0||i>=nn) laerror("illegal index in row()"); +#endif +NRVec r(mm); +LA_traits::copy(&r[0], +#ifdef MATPTR + v[i] +#else + v+i*mm +#endif +,mm); +return r; +} + //raw I/O template @@ -288,6 +309,101 @@ void NRMat::fscanf(FILE *f, const char *format) * BLAS specializations for double and complex */ +template<> +const NRSMat NRMat::transposedtimes() const +{ +NRSMat r(mm,mm); +int i,j; +for(i=0; i +const NRSMat > NRMat >::transposedtimes() const +{ +NRSMat > r(mm,mm); +int i,j; +for(i=0; i +const NRSMat NRMat::transposedtimes() const +{ +NRSMat r(mm,mm); +int i,j; +for(i=0; i +const NRSMat NRMat::timestransposed() const +{ +NRSMat r(nn,nn); +int i,j; +for(i=0; i +const NRSMat > NRMat >::timestransposed() const +{ +NRSMat > r(nn,nn); +int i,j; +for(i=0; i +const NRSMat NRMat::timestransposed() const +{ +NRSMat r(nn,nn); +int i,j; +for(i=0; i NRMat & NRMat::operator*=(const double &a) @@ -946,6 +1062,8 @@ INSTANTIZE(complex) INSTANTIZE(int) INSTANTIZE(short) INSTANTIZE(char) +INSTANTIZE(unsigned char) +INSTANTIZE(unsigned long) export template @@ -957,7 +1075,7 @@ ostream& operator<<(ostream &s, const NRMat &x) s << n << ' ' << m << '\n'; for(i=0;i::IOtype) x[i][j] << (j==m-1 ? '\n' : ' '); // endl cannot be used in the conditional expression, since it is an overloaded function } return s; } @@ -968,7 +1086,8 @@ istream& operator>>(istream &s, NRMat &x) int i,j,n,m; s >> n >> m; x.resize(n,m); - for(i=0;i>x[i][j] ; + typename LA_traits_io::IOtype tmp; + for(i=0;i>tmp; x[i][j]=tmp;} return s; } diff --git a/mat.h b/mat.h index 548d053..b7030e4 100644 --- a/mat.h +++ b/mat.h @@ -61,12 +61,16 @@ public: const NRMat otimes(const NRMat &rhs) const; //direct product void diagmultl(const NRVec &rhs); //multiply by a diagonal matrix from L void diagmultr(const NRVec &rhs); //multiply by a diagonal matrix from R + const NRSMat transposedtimes() const; //A^T . A + const NRSMat timestransposed() const; //A . A^T const NRMat operator*(const NRSMat &rhs) const; // Mat * Smat const NRMat operator&(const NRMat &rhs) const; // direct sum const NRMat operator|(const NRMat &rhs) const; // direct product const NRVec operator*(const NRVec &rhs) const {NRVec result(nn); result.gemv((T)0,*this,'n',(T)1,rhs); return result;}; // Mat * Vec const NRVec rsum() const; //sum of rows 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 inline T* operator[](const int i); //subscripting: pointer to row i inline const T* operator[](const int i) const; @@ -530,6 +534,14 @@ void NRMat::resize(const int n, const int m) +template +NRMat > complexify(const NRMat &rhs) +{ +NRMat > r(rhs.nrows(),rhs.ncols()); +for(int i=0; i) INSTANTIZE(int) INSTANTIZE(short) INSTANTIZE(char) +INSTANTIZE(unsigned char) +INSTANTIZE(unsigned long) #define EPSDET 1e-300 @@ -643,7 +645,7 @@ NRMat matrixfunction(NRSMat a, double (*f) (double)) return r; } -NRMat realmatrixfunction(NRMat a, double (*f) (double)) +NRMat realmatrixfunction(NRMat a, double (*f) (const double)) { int n = a.nrows(); NRVec w(n); @@ -657,6 +659,28 @@ NRMat realmatrixfunction(NRMat a, double (*f) (double)) return r; } +NRMat > complexmatrixfunction(NRMat a, double (*fre) (const double), double (*fim) (const double)) +{ + int n = a.nrows(); + NRVec wre(n),wim(n); + diagonalize(a, wre, true, false); + for (int i=0; i u = a; + NRMat b = a; + a.diagmultl(wre); + b.diagmultl(wim); + NRMat t(n,n),tt(n,n); + t.gemm(0.0, u, 't', a, 'n', 1.0); + tt.gemm(0.0, u, 't', b, 'n', 1.0); + NRMat > r(n, n); + for (int i=0; i(t(i,j),tt(i,j)); + return r; +} + + + + // instantize template to an addresable function complex myclog (const complex &x) @@ -664,6 +688,17 @@ complex myclog (const complex &x) return log(x); } +complex sqrtinv (const complex &x) +{ + return 1./sqrt(x); +} + +double sqrtinv (const double x) +{ + return 1./sqrt(x); +} + + NRMat log(const NRMat &a) { return matrixfunction(a, &myclog, 1); diff --git a/nonclass.h b/nonclass.h index abb9602..93ddd0a 100644 --- a/nonclass.h +++ b/nonclass.h @@ -74,11 +74,17 @@ extern void gdiagonalize(NRMat &a, NRVec< complex > &w, NRMat *b=NULL, NRVec *beta=NULL); extern NRMat matrixfunction(NRSMat a, double (*f) (double)); extern NRMat realmatrixfunction(NRMat a, double (*f) (double)); //a has to by in fact symmetric +extern NRMat > complexmatrixfunction(NRMat a, double (*fre) (double), double (*fim) (double)); //a has to by in fact symmetric extern NRMat matrixfunction(NRMat a, complex (*f)(const complex &),const bool adjust=0); +extern complex sqrtinv(const complex &); +extern double sqrtinv(const double); + //functions on matrices inline NRMat sqrt(const NRSMat &a) { return matrixfunction(a,&sqrt); } +inline NRMat sqrtinv(const NRSMat &a) { return matrixfunction(a,&sqrtinv); } inline NRMat realsqrt(const NRMat &a) { return realmatrixfunction(a,&sqrt); } +inline NRMat realsqrtinv(const NRMat &a) { return realmatrixfunction(a,&sqrtinv); } inline NRMat log(const NRSMat &a) { return matrixfunction(a,&log); } extern NRMat log(const NRMat &a); @@ -170,4 +176,11 @@ return r; //auxiliary routine to adjust eigenvectors to guarantee real logarithm extern void adjustphases(NRMat &v); +template +T abssqr(const complex &x) +{ +return x.real()*x.real()+x.imag()*x.imag(); +} + + #endif diff --git a/qsort.h b/qsort.h index 8051b2a..7eed5b1 100644 --- a/qsort.h +++ b/qsort.h @@ -42,4 +42,44 @@ else return parity; } + +template +int genqsort2(INDEX l, INDEX r, bool (*bigger)(const INDEX, const INDEX), void (*swap)(const INDEX,const INDEX)) +{ +INDEX i,j,piv; +int parity=0; + +if(r<=l) return parity; //1 element +if(bigger(l,r)) {parity^=1; swap(l,r);} +if(r-l==1) return parity; //2 elements and preparation for median +piv= (l+r)/2; //pivoting by median of 3 - safer +if(bigger(l,piv)) {parity^=1; swap(l,piv);} //and change the pivot element implicitly +if(bigger(piv,r)) {parity^=1; swap(r,piv);} //and change the pivot element implicitly +if(r-l==2) return parity; //in the case of 3 elements we are finished too + +//general case , l-th r-th already processed +i=l+1; j=r-1; +do{ + //important sharp inequality - stops at sentinel element for efficiency + // this is inefficient if all keys are equal - unnecessary n log n swaps are done, but we assume that it is atypical input + while(bigger(piv,i++)); + i--; + while(bigger(j--,piv)); + j++; + if(i >; template class NRSMat; template class NRSMat; template class NRSMat; +template class NRSMat; @@ -343,7 +344,7 @@ ostream& operator<<(ostream &s, const NRSMat &x) s << n << ' ' << n << '\n'; for(i=0;i::IOtype)x(i,j) << (j==n-1 ? '\n' : ' '); } return s; } @@ -356,7 +357,8 @@ istream& operator>>(istream &s, NRSMat &x) s >> n >> m; if(n!=m) laerror("input symmetric matrix not square"); x.resize(n); - for(i=0;i>x(i,j); + typename LA_traits_io::IOtype tmp; + for(i=0;i>tmp; x(i,j)=tmp;} return s; } @@ -374,4 +376,5 @@ INSTANTIZE(complex) INSTANTIZE(int) INSTANTIZE(short) INSTANTIZE(char) +INSTANTIZE(unsigned long) diff --git a/smat.h b/smat.h index 5c139cc..fadeb4b 100644 --- a/smat.h +++ b/smat.h @@ -462,6 +462,17 @@ void NRSMat::resize(const int n) } +template +NRSMat > complexify(const NRSMat &rhs) +{ +NRSMat > r(rhs.nrows()); +for(int i=0; i #include "sparsemat.h" +template +static inline const T MAX(const T &a, const T &b) + {return b > a ? (b) : (a);} + +template +static inline void SWAP(T &a, T &b) + {T dum=a; a=b; b=dum;} + + + ////////////////////////////////////////////////////////////////////////////// //// forced instantization in the corresponding object file template class SparseMat; @@ -24,7 +34,7 @@ ostream& operator<<(ostream &s, const SparseMat &x) matel *list=x.getlist(); while(list) { - s << (int)list->row << ' ' << (int)list->col << ' ' << list->elem << '\n'; + s << (int)list->row << ' ' << (int)list->col << ' ' << (typename LA_traits_io::IOtype)list->elem << '\n'; list=list->next; } s << "-1 -1\n"; @@ -47,7 +57,9 @@ istream& operator>>(istream &s, SparseMat &x) l->next= ll; l->row=i; l->col=j; - s >> l->elem; + typename LA_traits_io::IOtype tmp; + s >> tmp; + l->elem=tmp; s >> i >> j; } x.setlist(l); @@ -188,7 +200,8 @@ inline static SPMatindexdiff EXEC(register const SPMatindex i, register const SP register matel *ii,*jj; ii=((matel **)globsorted)[i]; jj=((matel **)globsorted)[j]; - if (k=ii->col-jj->col) return k; else return ii->row-jj->row;} + if (k=ii->col-jj->col) return k; else return ii->row-jj->row; + } }; @@ -200,7 +213,8 @@ inline static SPMatindexdiff EXEC(register const SPMatindex i, register const SP register matel *ii,*jj; ii=((matel **)globsorted)[i]; jj=((matel **)globsorted)[j]; - if (k=ii->row-jj->row) return k; else return ii->col-jj->col;} + if (k=ii->row-jj->row) return k; else return ii->col-jj->col; + } }; @@ -215,7 +229,7 @@ SWAP(((matel **)globsorted)[i],((matel **)globsorted)[j]); template -void genqsort(SPMatindex l,SPMatindex r) /*safer version for worst case*/ +void myqsort(SPMatindex l,SPMatindex r) /*safer version for worst case*/ { register SPMatindex i,j,piv; @@ -250,9 +264,9 @@ do{ }while(i<=j); if(j-l < r-i) /*because of the stack in bad case process first the shorter subarray*/ - {if(l(l,j); if(i(i,r);} + {if(l(l,j); if(i(i,r);} else - {if(i(i,r); if(l(l,j);} + {if(i(i,r); if(l(l,j);} } @@ -302,8 +316,8 @@ while(l) //now sort the array of pointers according to type globsorted =sorted; -if(type==0) {genqsort(0,nonzero-1); ((SparseMat *)this)->rowsorted=sorted;} //type handled at compile time for more efficiency -else {genqsort(0,nonzero-1); ((SparseMat *)this)->colsorted=sorted;} //should better be const cast +if(type==0) {myqsort(0,nonzero-1); ((SparseMat *)this)->rowsorted=sorted;} //type handled at compile time for more efficiency +else {myqsort(0,nonzero-1); ((SparseMat *)this)->colsorted=sorted;} //should better be const cast //cout <<"sort: nonzero ="< &x); diff --git a/t2.cc b/t2.cc index 349f971..58f8768 100644 --- a/t2.cc +++ b/t2.cc @@ -5,6 +5,7 @@ #include "sparsemat.h" #include "matexp.h" #include "fourindex.h" +#include "bitvector.h" void test(const NRVec &x) diff --git a/test.cc b/test.cc index c689cc6..ed9e14d 100644 --- a/test.cc +++ b/test.cc @@ -1,8 +1,28 @@ -#include "vec.h" +#include "bitvector.h" int main(void) { -NRVec *p = new NRVec[1000]; -NRVec q(10); q=1.; -p[500]|=q; +bitvector v(100); +v.fill(); +bitvector x(50); x=v; +v.copyonwrite(); +for(unsigned int i=0; i<100; i+=2) v.reset(i); +x.fill(); +x= ~x; +for(unsigned int i=0; i<100; ++i) x.assign(i,i&1); +cout < t(10); +for(int i=0; i<10; ++i) t[i]=i; +cout < #include #include +#include "qsort.h" extern "C" { extern ssize_t read(int, void *, size_t); extern ssize_t write(int, const void *, size_t); @@ -29,11 +30,14 @@ INSTANTIZE(short) INSTANTIZE(unsigned short) INSTANTIZE(char) INSTANTIZE(unsigned char) +INSTANTIZE(unsigned long) + template class NRVec; template class NRVec >; template class NRVec; template class NRVec; template class NRVec; +template class NRVec; @@ -65,7 +69,7 @@ ostream & operator<<(ostream &s, const NRVec &x) n = x.size(); s << n << endl; - for(i=0; i::IOtype)x[i] << (i == n-1 ? '\n' : ' '); return s; } @@ -76,7 +80,8 @@ istream & operator>>(istream &s, NRVec &x) s >> n; x.resize(n); - for(i=0; i> x[i]; + typename LA_traits_io::IOtype tmp; + for(i=0; i> tmp; x[i]=tmp;} return s; } @@ -281,6 +286,10 @@ template<> NRVec & NRVec::normalize() {laerror("normalize() impossible for integer types"); return *this;} template<> NRVec & NRVec::normalize() {laerror("normalize() impossible for integer types"); return *this;} +template<> +NRVec & NRVec::normalize() {laerror("normalize() impossible for integer types"); return *this;} + + template<> void NRVec::gemv(const int beta, const NRSMat &A, const char trans, @@ -297,6 +306,22 @@ void NRVec::gemv(const short beta, laerror("not yet implemented"); } +template<> +void NRVec::gemv(const unsigned long beta, + const NRSMat &A, const char trans, + const unsigned long alpha, const NRVec &x) +{ +laerror("not yet implemented"); +} + +template<> +void NRVec::gemv(const unsigned char beta, + const NRSMat &A, const char trans, + const unsigned char alpha, const NRVec &x) +{ +laerror("not yet implemented"); +} + template<> void NRVec::gemv(const char beta, @@ -322,6 +347,24 @@ void NRVec::gemv(const short beta, laerror("not yet implemented"); } +template<> +void NRVec::gemv(const unsigned long beta, + const NRMat &A, const char trans, + const unsigned long alpha, const NRVec &x) +{ +laerror("not yet implemented"); +} + +template<> +void NRVec::gemv(const unsigned char beta, + const NRMat &A, const char trans, + const unsigned char alpha, const NRVec &x) +{ +laerror("not yet implemented"); +} + + + template<> void NRVec::gemv(const char beta, @@ -356,6 +399,22 @@ void NRVec::gemv(const char beta, 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) +{ +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) +{ +laerror("not yet implemented"); +} + @@ -434,3 +493,36 @@ NRVec< complex >::operator|(const NRVec< complex > &b) const } +//sorting of elements in the vector +template +static inline void SWAP(T &a, T &b) + {T dum=a; a=b; b=dum;} + +static void *sortbase; //global for sort !!! is not thread-safe + +template +static void myswap(int i, int j) +{ +SWAP(((T *)sortbase)[i],((T *)sortbase)[j]); +} + +template +static bool mybigger(int i, int j) +{ +return LA_traits::bigger(((T *)sortbase)[i],((T *)sortbase)[j]); +} + +template +static bool mysmaller(int i, int j) +{ +return LA_traits::smaller(((T *)sortbase)[i],((T *)sortbase)[j]); +} + +template +int NRVec::sort(int direction) +{ +copyonwrite(); +sortbase = v; +if(direction) return genqsort2(0,nn-1,mysmaller,myswap); +else return genqsort2(0,nn-1,mybigger,myswap); +} diff --git a/vec.h b/vec.h index 8e59b97..85c7b85 100644 --- a/vec.h +++ b/vec.h @@ -103,6 +103,7 @@ public: //sparse matrix concerning members explicit NRVec(const SparseMat &rhs); // dense from sparse matrix with one of dimensions =1 inline void simplify() {}; //just for compatibility with sparse ones + int sort(int direction=0); //sort, ascending by default, returns parity of permutation }; //due to mutual includes this has to be after full class declaration @@ -591,5 +592,14 @@ NRVec & NRVec::operator|=(const NRVec &rhs) } +template +NRVec > complexify(const NRVec &rhs) +{ +NRVec > r(rhs.size()); +for(int i=0; i