diff --git a/auxstorage.h b/auxstorage.h index 04fc3ac..0ea219b 100644 --- a/auxstorage.h +++ b/auxstorage.h @@ -17,6 +17,7 @@ */ #ifndef _AUXSTORAGE_H_ #define _AUXSTORAGE_H_ + #include "vec.h" #include "mat.h" #include "smat.h" @@ -27,6 +28,8 @@ #include #include +namespace LA { + //CAUTION: //it will not work if T is itself a class with dynamically allocated components //it cannot be implemented for SparseMat, which lacks fixed record length @@ -136,6 +139,6 @@ if(0>write(fd,&x(0,0),recl)) {perror(""); laerror("write failed in AuxStorage"); } - +}//namespace #endif diff --git a/bisection.h b/bisection.h index b3ae9e7..349e31d 100644 --- a/bisection.h +++ b/bisection.h @@ -17,6 +17,9 @@ */ #ifndef _BISECTION_H #define _BISECTION_H + +namespace LA { + //general bisection search between dm and hm //returns dm-1 on failure, otherwise number between dm and hm //cmp returns 0 on equal, >0 if first > second argument @@ -75,5 +78,5 @@ int interpolation_find(INDEX dm0, INDEX high, const SUBJECT *x, const SUBJECT *b } - +}//namespace #endif diff --git a/bitvector.cc b/bitvector.cc index 9c19a5f..d61c0b9 100644 --- a/bitvector.cc +++ b/bitvector.cc @@ -18,14 +18,16 @@ #include "bitvector.h" +namespace LA { + //inefficient I/O operators -ostream & operator<<(ostream &s, const bitvector &x) +std::ostream & operator<<(std::ostream &s, const bitvector &x) { for(unsigned int i=0; i>(istream &s, bitvector &x) +std::istream & operator>>(std::istream &s, bitvector &x) { bool a; x.copyonwrite(); @@ -168,3 +170,4 @@ if(modulo) return s+word_popul(a); } +}//namespace diff --git a/bitvector.h b/bitvector.h index d930d3b..bdcfa9c 100644 --- a/bitvector.h +++ b/bitvector.h @@ -21,6 +21,8 @@ #include "vec.h" +namespace LA { + //compressed storage of large bit vectors //any reasonable compiler changes the dividions and modulos to shift/and instructions @@ -75,7 +77,8 @@ public: }; -extern ostream & operator<<(ostream &s, const bitvector &x); -extern istream & operator>>(istream &s, bitvector &x); +extern std::ostream & operator<<(std::ostream &s, const bitvector &x); +extern std::istream & operator>>(std::istream &s, bitvector &x); +}//namespace #endif diff --git a/conjgrad.h b/conjgrad.h index 4264384..56b27a6 100644 --- a/conjgrad.h +++ b/conjgrad.h @@ -15,6 +15,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#ifndef _CONJGRAD_H_ +#define _CONJGRAD_H_ #include "vec.h" #include "smat.h" #include "mat.h" @@ -22,6 +24,8 @@ #include "nonclass.h" #include +namespace LA { + //conjugate gradient solution of a linear system //matrix can be any class which has nrows(), ncols(), diagonalof() and gemv() available @@ -63,10 +67,10 @@ for(int iter=0; iter<= itmax; iter++) double err=p.norm(); if(verbose) { - cout << "conjgrad: iter= "<::normtype test=abs(smallV(krylovsize,nroot)); +typename LA_traits::normtype test=std::abs(smallV(krylovsize,nroot)); if(testeps) nroot=min(nroot,iroot); - if(verbose && iroot<=max(oldnroot,nroot)) + test = std::abs(smallV(krylovsize,iroot)); + if(test>eps) nroot=std::min(nroot,iroot); + if(verbose && iroot<=std::max(oldnroot,nroot)) { - cout <<"Davidson: iter="<=nroots) goto converged; if (it==maxit-1) break; //not converged @@ -195,7 +197,7 @@ eival_n = r[nroot]; for(i=0; i::elementtype> *ev; if(eivecsfile) ev = new AuxStorage::elementtype>(eivecsfile); -if(verbose) {cout << "Davidson converged in "< fields // actually it can be anything what has operator=(const T&), clear(), dot() , axpy(), norm() and copyonwrite(), and LA_traits::normtype and elementtype @@ -150,7 +152,7 @@ rhs= (Ue)0; rhs[0]= (Ue)-1; NRSMat amat=bmat; linear_solve(amat,rhs,NULL,aktdim+1); } -if(verbose) cout <<"DIIS coefficients: "< #include #include -#include "la.h" #include "laerror.h" +#include "vec.h" +#include "smat.h" +#include "mat.h" +#include "nonclass.h" +namespace LA { static unsigned int hcd0(unsigned int big,unsigned int small) { @@ -591,7 +595,7 @@ return n; } template -ostream& operator<<(ostream &s, const fourindex_ext &x) +std::ostream& operator<<(std::ostream &s, const fourindex_ext &x) { int n; n=x.size(); @@ -609,7 +613,7 @@ ostream& operator<<(ostream &s, const fourindex_ext &x) template -ostream& operator<<(ostream &s, const fourindex &x) +std::ostream& operator<<(std::ostream &s, const fourindex &x) { int n; n=x.size(); @@ -625,7 +629,7 @@ ostream& operator<<(ostream &s, const fourindex &x) } template -istream& operator>>(istream &s, fourindex &x) +std::istream& operator>>(std::istream &s, fourindex &x) { typename LA_traits_io::IOtype i,j,k,l; typename LA_traits_io::IOtype elem; @@ -680,7 +684,7 @@ public: const T& operator() (unsigned int i, unsigned int j, unsigned int k, unsigned int l) const; void resize(const int n) {(*this).NRSMat::resize(n*(n+1)/2);}; void putext(int f, T thr=1e-15); - int nbas() const {return (int)sqrt(2*(*this).nrows());}; + int nbas() const {return (int)std::sqrt(2*(*this).nrows());}; }; @@ -795,10 +799,10 @@ if (!NRMat::v) laerror("access to unallocated fourindex_dense"); return (*this).NRMat::operator() ((j-1)*noca+i-1,(b-1)*nvra+a-1); } - void print(ostream &out) const + void print(std::ostream &out) const { unsigned int i,j,a,b; - for(i=1; i<=noca; ++i) for(j=1; j<=nocb; ++j) for(a=1; a<=nvra; ++a) for(b=1; b<=nvrb; ++b) out << i<<" "<::resize(n*(n-1)/2);}; - void print(ostream &out) const + void print(std::ostream &out) const { unsigned int i,j,k,l; for(i=1; i<=nbas; ++i) for(k=1;k *>(&rhs)->pbegin(); p.notend(); ++p) } - +}//namespace #endif /*_fourindex_included*/ diff --git a/gmres.h b/gmres.h index e6eb1fb..91dbf0f 100644 --- a/gmres.h +++ b/gmres.h @@ -16,6 +16,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#ifndef _GMRES_H +#define _GMRES_H #include "vec.h" #include "smat.h" #include "mat.h" @@ -24,6 +26,8 @@ #include #include "auxstorage.h" +namespace LA { + //GMRES solution of a linear system //matrix can be any class which has nrows(), ncols(), diagonalof() and gemv() available @@ -135,7 +139,7 @@ for (int l=0;l #include #include #include + + +//using namespace std; +#define complex std::complex + #include "laerror.h" #ifdef NONCBLAS @@ -53,6 +56,9 @@ extern "C" { } #endif +namespace LA { + +extern bool _LA_count_check; //forward declarations template class NRVec; @@ -61,6 +67,7 @@ template class NRMat_from1; template class NRSMat; template class NRSMat_from1; template class SparseMat; +template class SparseSMat; typedef class {} Dummy_type; @@ -95,9 +102,13 @@ SPECIALIZE_COMPLEX(complex) SPECIALIZE_COMPLEX(char) SPECIALIZE_COMPLEX(unsigned char) SPECIALIZE_COMPLEX(short) +SPECIALIZE_COMPLEX(unsigned short) SPECIALIZE_COMPLEX(int) SPECIALIZE_COMPLEX(unsigned int) +SPECIALIZE_COMPLEX(long) SPECIALIZE_COMPLEX(unsigned long) +SPECIALIZE_COMPLEX(long long) +SPECIALIZE_COMPLEX(unsigned long long) //for general sortable classes @@ -194,10 +205,11 @@ struct LA_traits_aux, scalar_true> { typedef complex elementtype; typedef complex producttype; typedef C normtype; +static inline C sqrabs(const complex x) { return x.real()*x.real()+x.imag()*x.imag();} static inline bool gencmp(const complex *x, const complex *y, int n) {return memcmp(x,y,n*sizeof(complex));} static bool bigger(const complex &x, const complex &y) {laerror("complex comparison undefined"); return false;} static bool smaller(const complex &x, const complex &y) {laerror("complex comparison undefined"); return false;} -static inline normtype norm (const complex &x) {return abs(x);} +static inline normtype norm (const complex &x) {return std::abs(x);} static inline void axpy (complex &s, const complex &x, const complex &c) {s+=x*c;} static inline void get(int fd, complex &x, bool dimensions=0, bool transp=0) {if(sizeof(complex)!=read(fd,&x,sizeof(complex))) laerror("read error");} 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");} @@ -206,6 +218,7 @@ static void multiput(unsigned int n, int fd, const complex *x, bool dimension static void copy(complex *dest, complex *src, unsigned int n) {memcpy(dest,src,n*sizeof(complex));} static void clear(complex *dest, unsigned int n) {memset(dest,0,n*sizeof(complex));} static void copyonwrite(complex &x) {}; +static void clearme(complex &x) {x=0;}; }; //non-complex scalars @@ -214,10 +227,11 @@ struct LA_traits_aux { typedef C elementtype; typedef C producttype; typedef C normtype; +static inline C sqrabs(const C x) { return x*x;} static inline bool gencmp(const C *x, const C *y, int n) {return memcmp(x,y,n*sizeof(C));} static inline bool bigger(const C &x, const C &y) {return x>y;} static inline bool smaller(const C &x, const C &y) {return x &x) {x=0;}; }; @@ -252,6 +267,7 @@ static void multiget(unsigned int n,int fd, C *x, bool dimensions=1) {for(unsign static void copy(C *dest, C *src, unsigned int n) {for(unsigned int i=0; i &x) {x.copyonwrite();}\ +static void clearme(X &x) {x.clear();}\ }; @@ -260,6 +276,7 @@ generate_traits(NRMat) generate_traits(NRMat_from1) generate_traits(NRVec) generate_traits(SparseMat) +generate_traits(SparseSMat) //product leading to non-symmetric result not implemented #undef generate_traits @@ -282,6 +299,7 @@ static void multiget(unsigned int n,int fd, C *x, bool dimensions=1) {for(unsign static void copy(C *dest, C *src, unsigned int n) {for(unsigned int i=0; i &x) {x.copyonwrite();} \ +static void clearme(X &x) {x.clear();} \ }; generate_traits_smat(NRSMat) @@ -292,4 +310,6 @@ generate_traits_smat(NRSMat_from1) template struct LA_traits : LA_traits_aux::scalar_type> {}; +}//namespace + #endif diff --git a/laerror.cc b/laerror.cc index ba130c1..219ecba 100644 --- a/laerror.cc +++ b/laerror.cc @@ -30,6 +30,8 @@ #include "traceback.h" #endif +namespace LA { + bool _LA_count_check=true; extern "C" void _findme(void) {}; //for autoconf test we need a function with C linkage @@ -86,3 +88,5 @@ int cblas_errprn(int ierr, int info, char *form, ...) laerror(msg0); return 0; } + +}//namespace diff --git a/laerror.h b/laerror.h index 208f2c1..1dbefea 100644 --- a/laerror.h +++ b/laerror.h @@ -17,9 +17,10 @@ */ #ifndef _LAERROR_H_ #define _LAERROR_H_ - #include +namespace LA { + //exception class for laerror class LAerror { @@ -36,5 +37,6 @@ s << x.msg; return s; } +}//namespace #endif diff --git a/mat.cc b/mat.cc index 013f89c..9375348 100644 --- a/mat.cc +++ b/mat.cc @@ -31,6 +31,7 @@ extern ssize_t write(int, const void *, size_t); // TODO : // +namespace LA { /* * Templates first, specializations for BLAS next @@ -439,9 +440,9 @@ NRSMat > r(mm,mm); int i,j; for(i=0; i > r(nn,nn); int i,j; for(i=0; i > & NRMat< complex >::operator*=(const complex &a) { copyonwrite(); - cblas_zscal(nn*mm, &a, (void *)(*this)[0], 1); + cblas_zscal(nn*mm, &a, (*this)[0], 1); return *this; } @@ -591,7 +592,7 @@ NRMat< complex >::operator+=(const NRMat< complex > &rhs) laerror("Mat += Mat of incompatible matrices"); #endif copyonwrite(); - cblas_zaxpy(nn*mm, &CONE, (void *)rhs[0], 1, (void *)(*this)[0], 1); + cblas_zaxpy(nn*mm, &CONE, rhs[0], 1, (*this)[0], 1); return *this; } @@ -639,7 +640,7 @@ NRMat< complex >::operator-=(const NRMat< complex > &rhs) laerror("Mat -= Mat of incompatible matrices"); #endif copyonwrite(); - cblas_zaxpy(nn*mm, &CMONE, (void *)rhs[0], 1, (void *)(*this)[0], 1); + cblas_zaxpy(nn*mm, &CMONE, rhs[0], 1, (*this)[0], 1); return *this; } @@ -696,12 +697,12 @@ NRMat< complex >::operator+=(const NRSMat< complex > &rhs) const complex *p = rhs; copyonwrite(); for (int i=0; i & NRMat::operator+=(const NRSMat &rhs) } p = rhs; p++; for (int i=1; i >::operator-=(const NRSMat< complex > &rhs) const complex *p = rhs; copyonwrite(); for (int i=0; i & NRMat::operator-=(const NRSMat &rhs) } p = rhs; p++; for (int i=1; i >::dot(const NRMat< complex > &rhs) const if(nn!=rhs.nn || mm!= rhs.mm) laerror("Mat.Mat incompatible matrices"); #endif complex dot; - cblas_zdotc_sub(nn*mm, (void *)(*this)[0], 1, (void *)rhs[0], 1, - (void *)(&dot)); + cblas_zdotc_sub(nn*mm, (*this)[0], 1, rhs[0], 1, + &dot); return dot; } @@ -851,8 +852,8 @@ NRMat< complex >::operator*(const NRMat< complex > &rhs) const #endif NRMat< complex > result(nn, rhs.mm); cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nn, rhs.mm, mm, - (const void *)(&CONE),(const void *)(*this)[0], mm, (const void *)rhs[0], - rhs.mm, (const void *)(&CZERO), (void *)result[0], rhs.mm); + &CONE,(*this)[0], mm, rhs[0], + rhs.mm, &CZERO, result[0], rhs.mm); return result; } @@ -936,8 +937,8 @@ NRMat< complex >::operator*(const NRSMat< complex > &rhs) const #endif NRMat< complex > result(nn, rhs.ncols()); for (int i=0; i >::transpose(bool conj) const { NRMat< complex > result(mm,nn); for (int i=0; i::norm(const double scalar) const if (i==j) tmp -= scalar; sum += tmp*tmp; } - return sqrt(sum); + return std::sqrt(sum); } @@ -1060,7 +1061,7 @@ const double NRMat< complex >::norm(const complex scalar) const if (i==j) tmp -= scalar; sum += tmp.real()*tmp.real()+tmp.imag()*tmp.imag(); } - return sqrt(sum); + return std::sqrt(sum); } @@ -1087,7 +1088,7 @@ void NRMat< complex >::axpy(const complex alpha, if (nn!=mat.nn || mm!=mat.mm) laerror("zaxpy of incompatible matrices"); #endif copyonwrite(); - cblas_zaxpy(nn*mm, (void *)&alpha, mat, 1, (void *)(*this)[0], 1); + cblas_zaxpy(nn*mm, &alpha, mat, 1, (*this)[0], 1); } @@ -1186,7 +1187,7 @@ if(rowcol) //vectors are rows NRVec tmp = *metric * (*this).row(j); double norm = cblas_ddot(mm,(*this)[j],1,tmp,1); if(norm<=0.) laerror("zero vector in orthonormalize or nonpositive metric"); - cblas_dscal(mm,1./sqrt(norm),(*this)[j],1); + cblas_dscal(mm,1./std::sqrt(norm),(*this)[j],1); } } else //vectors are columns @@ -1203,7 +1204,7 @@ else //vectors are columns NRVec tmp = *metric * (*this).column(j); double norm = cblas_ddot(nn,&(*this)[0][j],mm,tmp,1); if(norm<=0.) laerror("zero vector in orthonormalize or nonpositive metric"); - cblas_dscal(nn,1./sqrt(norm),&(*this)[0][j],mm); + cblas_dscal(nn,1./std::sqrt(norm),&(*this)[0][j],mm); } } } @@ -1261,3 +1262,4 @@ template class NRMat; template class NRMat; template class NRMat; +}//namespace diff --git a/mat.h b/mat.h index a1ce209..9ed2abd 100644 --- a/mat.h +++ b/mat.h @@ -19,9 +19,9 @@ */ #ifndef _LA_MAT_H_ #define _LA_MAT_H_ - #include "la_traits.h" +namespace LA { template class NRMat { protected: @@ -91,6 +91,7 @@ public: 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 + void orthonormalize(const bool rowcol, const NRSMat *metric=NULL);//orthonormalize (true - vectors are rows) const NRVec row(const int i, int l= -1) const; //row of, efficient const NRVec column(const int j, int l= -1) const {if(l<0) l=nn; NRVec r(l); for(int i=0; i &, const bool divide=0, bool cache=false) const; //get diagonal @@ -140,11 +141,13 @@ public: #endif }; +}//namespace //due to mutual includes this has to be after full class declaration #include "vec.h" #include "smat.h" #include "sparsemat.h" +namespace LA { // ctors template NRMat::NRMat(const int n, const int m) : nn(n), mm(m), count(new int) @@ -374,9 +377,9 @@ template<> inline const complex NRMat< complex >::amax() const { #ifdef MATPTR - return v[0][cblas_izamax(nn*mm, (void *)v[0], 1)]; + return v[0][cblas_izamax(nn*mm, v[0], 1)]; #else - return v[cblas_izamax(nn*mm, (void *)v, 1)]; + return v[cblas_izamax(nn*mm, v, 1)]; #endif } @@ -576,7 +579,7 @@ return r; // I/O template -ostream& operator<<(ostream &s, const NRMat &x) +std::ostream& operator<<(std::ostream &s, const NRMat &x) { int i,j,n,m; n=x.nrows(); @@ -590,7 +593,7 @@ ostream& operator<<(ostream &s, const NRMat &x) } template -istream& operator>>(istream &s, NRMat &x) +std::istream& operator>>(std::istream &s, NRMat &x) { int i,j,n,m; s >> n >> m; @@ -655,4 +658,5 @@ NRVECMAT_OPER(Mat,*) NRVECMAT_OPER2(Mat,+) NRVECMAT_OPER2(Mat,-) +}//namespace #endif /* _LA_MAT_H_ */ diff --git a/matexp.h b/matexp.h index d7d3c51..9910cb5 100644 --- a/matexp.h +++ b/matexp.h @@ -21,10 +21,11 @@ //of matrix-matrix multiplications on cost of additions and memory // the polynom and exp routines will work on any type, for which traits class // is defined containing definition of an element type, norm and axpy operation - #include "la_traits.h" #include "laerror.h" +#include +namespace LA { template const T polynom0(const T &x, const NRVec &c) @@ -40,6 +41,7 @@ else z=x*c[order]; for(i=order-1; i>=0; i--) { + //std::cerr<<"TEST polynom0 "< NRVec exp_aux(const T &x, int &power, int maxpower, int maxtaylor, S prescale) { -double mnorm= x.norm() * abs(prescale); +double mnorm= x.norm() * std::abs(prescale); power=nextpow2(mnorm); if(maxpower>=0 && power>maxpower) power=maxpower; -double scale=exp(-log(2.)*power); +double scale=std::exp(-std::log(2.)*power); //find how long taylor expansion will be necessary @@ -236,8 +238,8 @@ for(i=0,t=1.;i<=n;i++) taylor2[i]=exptaylor[i]*t; t*=scale; } -//cout <<"TEST power, scale "< void sincos_aux(NRVec &si, NRVec &co, const T &x, int &power,int maxpower, int maxtaylor, const S prescale) { -double mnorm= x.norm() * abs(prescale); +double mnorm= x.norm() * std::abs(prescale); power=nextpow2(mnorm); if(maxpower>=0 && power>maxpower) power=maxpower; -double scale=exp(-log(2.)*power); +double scale=std::exp(-std::log(2.)*power); //find how long taylor expansion will be necessary const double precision=1e-14; //further decreasing brings nothing @@ -275,8 +277,8 @@ for(i=0,t=1.;i<=n;i++) else co[i>>1] = exptaylor[i]* (i&2?-t:t); t*=scale; } -//cout <<"TEST sin "<::normtype> taylor2=exp_aux::normtype,double>(x,power,maxpower,maxtaylor,1.); +//std::cerr <<"TEST power "<::normtype> taylors,taylorc; sincos_aux::normtype>(taylors,taylorc,x,power,maxpower,maxtaylor,1.); + //could we save something by computing both polynoms simultaneously? { T x2 = x*x; @@ -446,16 +450,14 @@ NRVec::normtype> taylors,taylorc; sincos_aux::normtype>(taylors,taylorc,mat,power,maxpower,maxtaylor,scale); if(taylors.size()!=taylorc.size()) laerror("internal error - same size of sin and cos expansions assumed"); //the actual computation and resursive "squaring" -cout <<"TEST power "<) INSTANTIZE(int) INSTANTIZE(short) INSTANTIZE(char) +INSTANTIZE(long) +INSTANTIZE(long long) INSTANTIZE(unsigned char) -INSTANTIZE(unsigned long) +INSTANTIZE(unsigned short) INSTANTIZE(unsigned int) +INSTANTIZE(unsigned long) +INSTANTIZE(unsigned long long) #define EPSDET 1e-300 @@ -146,7 +151,7 @@ static void linear_solve_do(NRMat &A, double *B, const int nrhs, const i if (det && r==0) { *det = 1.; //take into account some numerical instabilities in dgesv for singular matrices - for (int i=0; i &A, double *B, const int nrhs, const i } if(det && r>0) *det = 0; /* - cout <<"ipiv = "; - for (int i=0; i0 && B) laerror("singular matrix in lapack_gesv"); @@ -202,7 +207,7 @@ static void linear_solve_do(NRSMat &a, double *b, const int nrhs, const } if (det && r == 0) { *det = 1.; - for (int i=1; i0) *det = 0; @@ -452,6 +457,9 @@ void singular_decomposition(NRMat &a, NRMat *u, NRVec &s if (r > 0) laerror("convergence problem in gesvd() of ingular_decomposition()"); } +//QR decomposition +//extern "C" void FORNAME(dgeqrf)(const int *M, const int *N, double *A, const int *LDA, double *TAU, double *WORK, int *LWORK, int *INFO); + extern "C" void FORNAME(dgeev)(const char *JOBVL, const char *JOBVR, const int *N, double *A, const int *LDA, double *WR, double *WI, double *VL, const int *LDVL, @@ -555,7 +563,7 @@ void gdiagonalize(NRMat &a, NRVec &wr, NRVec &wi, &ldvr, vl?vl[0]:(double *)0, &ldvl, work, &lwork, &r); delete[] work; -//cout <<"TEST dgeev\n"< 0) laerror("convergence problem in ggev/geev in gdiagonalize()"); @@ -589,9 +597,9 @@ void gdiagonalize(NRMat &a, NRVec &wr, NRVec &wi, x=.5*t*s11; y=.5*t*s12; double alp,bet; - t=.5*sqrt(t); - alp=sqrt(.5*(t+x)); - bet=sqrt(.5*(t-x)); + t=.5*std::sqrt(t); + alp=std::sqrt(.5*(t+x)); + bet=std::sqrt(.5*(t-x)); if(y<0.) bet= -bet; //rotate left ev @@ -722,6 +730,16 @@ const NRMat< complex > imagmatrix (const NRMat &a) return result; } +const NRMat< complex > complexmatrix (const NRMat &re, const NRMat &im) +{ + if(re.nrows()!=im.nrows() || re.ncols() != im.ncols()) laerror("incompatible sizes of real and imaginary parts"); + NRMat< complex > result(re.nrows(), re.ncols()); + cblas_dcopy(re.nrows()*re.ncols(), re, 1, (double *)result[0], 2); + cblas_dcopy(re.nrows()*re.ncols(), im, 1, (double *)result[0]+1, 2); + return result; +} + + NRMat matrixfunction(NRMat a, complex (*f)(const complex &), const bool adjust) @@ -735,13 +753,13 @@ NRMat > a0=complexify(a); gdiagonalize(a, w, &u, &v);//a gets destroyed, eigenvectors are rows NRVec< complex > z = diagofproduct(u, v, 1, 1); /* -cout <<"TEST matrixfunction\n"< > wz(n); for (int i=0; i 1e-10) { - cout << "norm = " << inorm << endl; + std::cout << "norm = " << inorm << std::endl; laerror("nonzero norm of imaginary part of real matrixfunction"); } return realpart(r); @@ -817,18 +835,18 @@ complex myclog (const complex &x) complex mycexp (const complex &x) { - return exp(x); + return std::exp(x); } complex sqrtinv (const complex &x) { - return 1./sqrt(x); + return 1./std::sqrt(x); } double sqrtinv (const double x) { - return 1./sqrt(x); + return 1./std::sqrt(x); } @@ -959,7 +977,7 @@ for(j=i; j @@ -120,11 +120,11 @@ 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 sqrt(const NRSMat &a) { return matrixfunction(a,&std::sqrt); } inline NRMat sqrtinv(const NRSMat &a) { return matrixfunction(a,&sqrtinv); } -inline NRMat realsqrt(const NRMat &a) { return realmatrixfunction(a,&sqrt); } +inline NRMat realsqrt(const NRMat &a) { return realmatrixfunction(a,&std::sqrt); } inline NRMat realsqrtinv(const NRMat &a) { return realmatrixfunction(a,&sqrtinv); } -inline NRMat log(const NRSMat &a) { return matrixfunction(a,&log); } +inline NRMat log(const NRSMat &a) { return matrixfunction(a,&std::log); } extern NRMat log(const NRMat &a); extern NRMat exp0(const NRMat &a); @@ -133,6 +133,7 @@ extern const NRMat realpart(const NRMat< complex >&); extern const NRMat imagpart(const NRMat< complex >&); extern const NRMat< complex > realmatrix (const NRMat&); extern const NRMat< complex > imagmatrix (const NRMat&); +extern const NRMat< complex > complexmatrix (const NRMat&, const NRMat&); //inverse by means of linear solve, preserving rhs intact template @@ -186,7 +187,7 @@ if(ignoresign) { for(int i=0; i &v); -template -T abssqr(const complex &x) -{ -return x.real()*x.real()+x.imag()*x.imag(); -} //declaration of template interface to cblas routines with full options available //just to facilitate easy change between float, double, complex in a user code @@ -272,6 +268,5 @@ return r; } - - +}//namespace #endif diff --git a/permutation.h b/permutation.h index 9f86375..189ad94 100644 --- a/permutation.h +++ b/permutation.h @@ -15,6 +15,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#ifndef _PERMUTATION_H +#define _PERMUTATION_H +namespace LA { template const NRVec inversepermutation(const NRVec &p, const T offset=0) { @@ -24,3 +27,5 @@ if(!offset) for(int i=0; i int genqsort(INDEX l, INDEX r,COMPAR (*cmp)(const INDEX, const INDEX), void (*swap)(const INDEX,const INDEX)) @@ -181,4 +183,5 @@ else return parity; } +}//namespace #endif diff --git a/smat.cc b/smat.cc index bdc6788..75ddccd 100644 --- a/smat.cc +++ b/smat.cc @@ -31,7 +31,7 @@ extern ssize_t write(int, const void *, size_t); // TODO // specialize unary minus - +namespace LA { /* @@ -298,7 +298,7 @@ NRSMat< complex >::dot(const NRSMat< complex > &rhs) const if (nn != rhs.nn) laerror("dot of incompatible SMat's"); #endif complex dot; - cblas_zdotc_sub(NN2, (void *)v, 1, (void *)rhs.v, 1, (void *)(&dot)); + cblas_zdotc_sub(NN2, v, 1, rhs.v, 1, &dot); return dot; } @@ -322,7 +322,7 @@ NRSMat< complex >::dot(const NRVec< complex > &rhs) const 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)); + cblas_zdotc_sub(NN2, v, 1, rhs.v, 1, &dot); return dot; } @@ -341,7 +341,7 @@ const double NRSMat::norm(const double scalar) const if (i == j) tmp -= scalar; sum += tmp*tmp; } - return sqrt(sum); + return std::sqrt(sum); } @@ -350,7 +350,7 @@ template<> const double NRSMat< complex >::norm(const complex scalar) const { if (!(scalar.real()) && !(scalar.imag())) - return cblas_dznrm2(NN2, (void *)v, 1); + return cblas_dznrm2(NN2, v, 1); double sum = 0; complex tmp; int k = 0; @@ -360,7 +360,7 @@ const double NRSMat< complex >::norm(const complex scalar) const if (i == j) tmp -= scalar; sum += tmp.real()*tmp.real() + tmp.imag()*tmp.imag(); } - return sqrt(sum); + return std::sqrt(sum); } @@ -388,7 +388,7 @@ void NRSMat< complex >::axpy(const complex alpha, if (nn != x.nn) laerror("axpy of incompatible SMats"); #endif copyonwrite(); - cblas_zaxpy(nn, (void *)(&alpha), (void *)x.v, 1, (void *)v, 1); + cblas_zaxpy(nn, &alpha, x.v, 1, v, 1); } //complex from real @@ -407,9 +407,16 @@ cblas_dcopy(nn*(nn+1)/2,&rhs(0,0),1,((double *)v) + (imagpart?1:0),2); ////// forced instantization in the corresponding object file template class NRSMat; template class NRSMat< complex >; + +template class NRSMat; +template class NRSMat; template class NRSMat; template class NRSMat; template class NRSMat; +template class NRSMat; +template class NRSMat; template class NRSMat; template class NRSMat; +template class NRSMat; +}//namespace diff --git a/smat.h b/smat.h index 4520303..1b9b93e 100644 --- a/smat.h +++ b/smat.h @@ -19,9 +19,9 @@ */ #ifndef _LA_SMAT_H_ #define _LA_SMAT_H_ - #include "la_traits.h" +namespace LA { #define NN2 (nn*(nn+1)/2) template class NRSMat { // symmetric or complex hermitean matrix in packed form @@ -94,15 +94,17 @@ public: void fscanf(FILE *f, const char *format); //members concerning sparse matrix explicit NRSMat(const SparseMat &rhs); // dense from sparse + explicit NRSMat(const SparseSMat &rhs); // dense from sparse inline void simplify() {}; //just for compatibility with sparse ones bool issymmetric() const {return 1;} }; +}//namespace //due to mutual includes this has to be after full class declaration #include "vec.h" #include "mat.h" -#include "sparsemat.h" +namespace LA { // ctors template @@ -162,7 +164,7 @@ inline NRSMat< complex > & NRSMat< complex >::operator*=(const complex & a) { copyonwrite(); - cblas_zscal(NN2, (void *)(&a), (void *)v, 1); + cblas_zscal(NN2, &a, v, 1); return *this; } template @@ -214,7 +216,7 @@ NRSMat< complex >::operator+=(const NRSMat< complex > & rhs) if (nn != rhs.nn) laerror("incompatible SMats in SMat::operator+="); #endif copyonwrite(); - cblas_zaxpy(NN2, (void *)(&CONE), (void *)(&rhs.v), 1, (void *)(&v), 1); + cblas_zaxpy(NN2, &CONE, rhs.v, 1, v, 1); return *this; } @@ -251,7 +253,7 @@ NRSMat< complex >::operator-=(const NRSMat< complex > & rhs) if (nn != rhs.nn) laerror("incompatible SMats in SMat::operator-="); #endif copyonwrite(); - cblas_zaxpy(NN2, (void *)(&CMONE), (void *)(&rhs.v), 1, (void *)(&v), 1); + cblas_zaxpy(NN2, &CMONE, rhs.v, 1, v, 1); return *this; } @@ -406,7 +408,7 @@ inline const double NRSMat::amax() const template<> inline const complex NRSMat< complex >::amax() const { - return v[cblas_izamax(NN2, (void *)v, 1)]; + return v[cblas_izamax(NN2, v, 1)]; } // reference pointer to Smat @@ -554,7 +556,7 @@ return r; // I/O template -ostream& operator<<(ostream &s, const NRSMat &x) +std::ostream& operator<<(std::ostream &s, const NRSMat &x) { int i,j,n; n=x.nrows(); @@ -568,7 +570,7 @@ ostream& operator<<(ostream &s, const NRSMat &x) template -istream& operator>>(istream &s, NRSMat &x) +std::istream& operator>>(std::istream &s, NRSMat &x) { int i,j,n,m; s >> n >> m; @@ -618,5 +620,5 @@ public: } }; - +}//namespace #endif /* _LA_SMAT_H_ */ diff --git a/sparsemat.cc b/sparsemat.cc index 57c1ae2..c103f13 100644 --- a/sparsemat.cc +++ b/sparsemat.cc @@ -25,6 +25,8 @@ #include #include "sparsemat.h" +namespace LA { + template static inline const T MAX(const T &a, const T &b) {return b > a ? (b) : (a);} @@ -333,11 +335,7 @@ for(i=1; ielem)elem -#endif + std::abs(rowsorted[i]->elem)<=SPARSEEPSILON ) {delete rowsorted[i]; rowsorted[i]=NULL;} //restore connectivity @@ -397,11 +395,7 @@ void SparseMat::addsafe(const SPMatindex n, const SPMatindex m, const T elem) #ifdef debug if(n<0||n>=nn||m<0||m>=mm) laerror("SparseMat out of range"); #endif -#ifdef SPARSEEPSILON -if(abs(elem) *l=rhs.list; while(l) { if(rhs.symmetric || lower && l->row <=l->col || !lower && l->row >=l->col) -#ifdef SPARSEEPSILON - if(abs(l->elem)>SPARSEEPSILON) -#endif + if(std::abs(l->elem)>SPARSEEPSILON) add( l->row,l->col,sign=='+'?l->elem:- l->elem); l=l->next; } @@ -473,21 +465,18 @@ register matel *l=rhs.list; if(symmetrize) while(l) { -#ifdef SPARSEEPSILON - if(abs(l->elem)>SPARSEEPSILON) -#endif + if(std::abs(l->elem)>SPARSEEPSILON) {add( l->row,l->col,l->elem); if( l->row!=l->col) add( l->col,l->row,l->elem);} l=l->next; } else while(l) { -#ifdef SPARSEEPSILON - if(abs(l->elem)>SPARSEEPSILON) -#endif + if(std::abs(l->elem)>SPARSEEPSILON) add( l->row,l->col,l->elem); l=l->next; } +simplify(); //maybe leave up to the user return *this; } @@ -503,21 +492,18 @@ register matel *l=rhs.list; if(symmetrize) while(l) { -#ifdef SPARSEEPSILON - if(abs(l->elem)>SPARSEEPSILON) -#endif + if(std::abs(l->elem)>SPARSEEPSILON) {add( l->row,l->col,- l->elem); if( l->row!=l->col) add( l->col,l->row,- l->elem);} l=l->next; } else while(l) { -#ifdef SPARSEEPSILON - if(abs(l->elem)>SPARSEEPSILON) -#endif + if(std::abs(l->elem)>SPARSEEPSILON) add( l->row,l->col,- l->elem); l=l->next; } +simplify(); //maybe leave up to the user return *this; } @@ -537,11 +523,7 @@ SPMatindex i,j; for(i=0;iSPARSEEPSILON) -#else - if(t) -#endif + if( std::abs(t)>SPARSEEPSILON) add(i,j,t); } } @@ -660,40 +642,38 @@ else while(l) //assignment of a scalar matrix template -SparseMat & SparseMat::operator=(const T a) +SparseMat & SparseMat::operator=(const T &a) { if(!count ||nn<=0||mm<=0) laerror("assignment of scalar to undefined sparse matrix"); if(nn!=mm) laerror("assignment of scalar to non-square sparse matrix"); resize(nn,mm);//clear -#ifdef SPARSEEPSILON -if(abs(a) -SparseMat & SparseMat::operator+=(const T a) +SparseMat & SparseMat::operator+=(const T &a) { if(!count ||nn<=0||mm<=0) laerror("assignment of scalar to undefined sparse matrix"); if(nn!=mm) laerror("assignment of scalar to non-square sparse matrix"); if(a==(T)0) return *this; SPMatindex i; for(i=0;i -SparseMat & SparseMat::operator-=(const T a) +SparseMat & SparseMat::operator-=(const T &a) { if(!count ||nn<=0||mm<=0) laerror("assignment of scalar to undefined sparse matrix"); if(nn!=mm) laerror("assignment of scalar to non-square sparse matrix"); if(a==(T)0) return *this; SPMatindex i; for(i=0;iSPARSEEPSILON -#else - t=rhs(i,j) -#endif + std::abs(t=rhs(i,j))>SPARSEEPSILON ) add(i,j,t); } } @@ -751,9 +727,7 @@ matel *l=list; while(l) //include the mirror picture of elements into the list { if( -#ifdef SPARSEEPSILON - abs(l->elem)>SPARSEEPSILON && -#endif + std::abs(l->elem)>SPARSEEPSILON && l->row!=l->col) add(l->col,l->row,l->elem); //not OK for complex-hermitean l=l->next; } @@ -761,12 +735,12 @@ while(l) //include the mirror picture of elements into the list template -SparseMat & SparseMat::operator*=(const T a) +SparseMat & SparseMat::operator*=(const T &a) { if(!count) laerror("operator*= on undefined lhs"); if(!list||a==(T)1) return *this; -if(a==(T)0) resize(nn,mm); -else copyonwrite(); +if(a==(T)0) {clear(); return *this;} +copyonwrite(); register matel *l=list; while(l) @@ -936,15 +910,14 @@ return sum; } -//not OK for complex hermitean template -const T SparseMat::norm(const T scalar) const +const typename LA_traits::normtype SparseMat::norm(const T scalar) const { -if(!list) return T(0); +if(!list) return typename LA_traits::normtype(0); const_cast *>(this)->simplify(); matel *l=list; -T sum(0); +typename LA_traits::normtype sum(0); if(scalar!=(T)0) { if(symmetric) @@ -953,7 +926,7 @@ if(scalar!=(T)0) T hlp=l->elem; bool b=l->row==l->col; if(b) hlp-=scalar; - T tmp=hlp*hlp; + typename LA_traits::normtype tmp=LA_traits::sqrabs(hlp); sum+= tmp; if(!b) sum+=tmp; l=l->next; @@ -963,7 +936,7 @@ if(scalar!=(T)0) { T hlp=l->elem; if(l->row==l->col) hlp-=scalar; - sum+= hlp*hlp; + sum+= LA_traits::sqrabs(hlp); l=l->next; } } @@ -972,7 +945,7 @@ else if(symmetric) while(l) { - T tmp=l->elem*l->elem; + typename LA_traits::normtype tmp=LA_traits::sqrabs(l->elem); sum+= tmp; if(l->row!=l->col) sum+=tmp; l=l->next; @@ -980,11 +953,11 @@ else else while(l) { - sum+= l->elem*l->elem; + sum+= LA_traits::sqrabs(l->elem); l=l->next; } } -return sqrt(sum); //not OK for int, would need traits technique +return (typename LA_traits::normtype) std::sqrt(sum); //not OK for int, would need traits technique } @@ -1009,9 +982,7 @@ if(transp) while(l) { register T t=alpha*l->elem; -#ifdef SPARSEEPSILON - if(abs(t)>SPARSEEPSILON) -#endif + if(std::abs(t)>SPARSEEPSILON) add( l->col,l->row,t); l=l->next; } @@ -1019,9 +990,7 @@ else while(l) { register T t=alpha*l->elem; -#ifdef SPARSEEPSILON - if(abs(t)>SPARSEEPSILON) -#endif + if(std::abs(t)>SPARSEEPSILON) add( l->row,l->col,t); l=l->next; } @@ -1227,11 +1196,7 @@ incsize(rhs.nrows(), rhs.ncols()); T tmp; for(SPMatindex i=0; i<(SPMatindex)rhs.nrows(); ++i) for(SPMatindex j=0; j<(SPMatindex)rhs.ncols(); ++j) -#ifdef SPARSEEPSILON - if(abs(tmp=rhs(i,j))>SPARSEEPSILON) add(n0+i,m0+j,tmp); -#else - if((tmp=rhs(i,j))!=(T)0) add(n0+i,m0+j,tmp); -#endif + if(std::abs(tmp=rhs(i,j))>SPARSEEPSILON) add(n0+i,m0+j,tmp); return *this; } @@ -1247,11 +1212,7 @@ T tmp; incsize(rhs.nrows(), rhs.ncols()); for(SPMatindex i=0; i<(SPMatindex)rhs.nrows(); ++i) for(SPMatindex j=0; j<(SPMatindex)rhs.ncols(); ++j) -#ifdef SPARSEEPSILON - if(abs(tmp=rhs(i,j))>SPARSEEPSILON) add(n0+i,m0+j,tmp); -#else - if((tmp=rhs(i,j))!=(T)0) add(n0+i,m0+j,tmp); -#endif + if(std::abs(tmp=rhs(i,j))>SPARSEEPSILON) add(n0+i,m0+j,tmp); return *this; } @@ -1270,9 +1231,7 @@ incsize(rhs.nrows(), rhs.ncols()); register matel *l=rhs.list; while(l) { -#ifdef SPARSEEPSILON - if(abs(l->elem)>SPARSEEPSILON) -#endif + if(std::abs(l->elem)>SPARSEEPSILON) add(n0+l->row,m0+l->col,l->elem); l=l->next; } @@ -1303,18 +1262,18 @@ template SparseMat::SparseMat(const NRMat &rhs); \ template SparseMat::SparseMat(const NRSMat &rhs); \ template void SparseMat::transposeme(); \ template const T* SparseMat::diagonalof(NRVec &r, const bool divide, bool cache) const; \ -template SparseMat & SparseMat::operator*=(const T a); \ +template SparseMat & SparseMat::operator*=(const T &a); \ template void SparseMat::setunsymmetric(); \ -template SparseMat & SparseMat::operator=(const T a); \ -template SparseMat & SparseMat::operator+=(const T a); \ -template SparseMat & SparseMat::operator-=(const T a); \ +template SparseMat & SparseMat::operator=(const T &a); \ +template SparseMat & SparseMat::operator+=(const T &a); \ +template SparseMat & SparseMat::operator-=(const T &a); \ template NRMat::NRMat(const SparseMat &rhs); \ template NRSMat::NRSMat(const SparseMat &rhs); \ template NRVec::NRVec(const SparseMat &rhs); \ template const NRVec NRVec::operator*(const SparseMat &mat) const; \ template SparseMat & SparseMat::join(SparseMat &rhs); \ template const T SparseMat::trace() const; \ -template const T SparseMat::norm(const T scalar) const; \ +template const LA_traits::normtype SparseMat::norm(const T scalar) const; \ template void SparseMat::axpy(const T alpha, const SparseMat &x, const bool transp); \ template const SparseMat SparseMat::operator*(const SparseMat &rhs) const; \ template const T SparseMat::dot(const SparseMat &rhs) const; \ @@ -1336,3 +1295,4 @@ INSTANTIZE(complex) //some functions are not OK for hermitean matrices, template class SparseMat; template class SparseMat >; +}//namespace diff --git a/sparsemat.h b/sparsemat.h index 6633827..ece4a04 100644 --- a/sparsemat.h +++ b/sparsemat.h @@ -17,13 +17,13 @@ */ #ifndef _SPARSEMAT_H_ #define _SPARSEMAT_H_ - #include "la_traits.h" +namespace LA { //threshold for neglecting elements, if not defined, no tests are done except exact zero test in simplify - might be even faster //seems to perform better with a threshold, in spite of abs() tests -#define SPARSEEPSILON 1e-13 +const double SPARSEEPSILON=1e-35; typedef unsigned int SPMatindex; typedef int SPMatindexdiff; //more clear would be to use traits @@ -81,10 +81,10 @@ public: explicit SparseMat(const NRMat &rhs); //construct from a dense one explicit SparseMat(const NRSMat &rhs); //construct from a dense symmetric one SparseMat & operator=(const SparseMat &rhs); - SparseMat & operator=(const T a); //assign a to diagonal - SparseMat & operator+=(const T a); //assign a to diagonal - SparseMat & operator-=(const T a); //assign a to diagonal - SparseMat & operator*=(const T a); //multiply by a scalar + SparseMat & operator=(const T &a); //assign a to diagonal + SparseMat & operator+=(const T &a); //assign a to diagonal + SparseMat & operator-=(const T &a); //assign a to diagonal + SparseMat & operator*=(const T &a); //multiply by a scalar SparseMat & operator+=(const SparseMat &rhs); SparseMat & addtriangle(const SparseMat &rhs, const bool lower, const char sign); SparseMat & join(SparseMat &rhs); //more efficient +=, rhs will be emptied @@ -135,17 +135,21 @@ public: void clear() {copyonwrite();unsort();deletelist();} void simplify(); const T trace() const; - const T norm(const T scalar=(T)0) const; //is const only mathematically, not in internal implementation - we have to simplify first + const typename LA_traits::normtype norm(const T scalar=(T)0) const; //is const only mathematically, not in internal implementation - we have to simplify first unsigned int sort(int type) const; inline void add(const SPMatindex n, const SPMatindex m, const T elem) {matel *ltmp= new matel; ltmp->next=list; list=ltmp; list->row=n; list->col=m; list->elem=elem;} void addsafe(const SPMatindex n, const SPMatindex m, const T elem); }; +}//namespace + //due to mutual includes this has to be after full class declaration #include "vec.h" #include "smat.h" #include "mat.h" +namespace LA { + template inline const NRVec SparseMat::operator*(const NRVec &rhs) const {NRVec result(nn); result.gemv((T)0,*this,'n',(T)1,rhs); return result;}; @@ -155,7 +159,7 @@ inline const NRMat SparseMat::operator*(const NRMat &rhs) const {NRMat result(nn,rhs.ncols()); result.gemm((T)0,*this,'n',rhs,'n',(T)1); return result;}; template -ostream& operator<<(ostream &s, const SparseMat &x) +std::ostream& operator<<(std::ostream &s, const SparseMat &x) { SPMatindex n,m; n=x.nrows(); @@ -172,7 +176,7 @@ ostream& operator<<(ostream &s, const SparseMat &x) } template -istream& operator>>(istream &s, SparseMat &x) +std::istream& operator>>(std::istream &s, SparseMat &x) { int i,j; int n,m; @@ -298,4 +302,5 @@ while(l) return *this; } +}//namespace #endif diff --git a/sparsesmat.cc b/sparsesmat.cc index 248bc9e..0ecaa39 100644 --- a/sparsesmat.cc +++ b/sparsesmat.cc @@ -25,10 +25,11 @@ #include #include "sparsesmat.h" +namespace LA { + template void SparseSMat::gemm(const T beta, const SparseSMat &a, const char transa, const SparseSMat &b, const char transb, const T alpha) { -std::cerr << "enter gemm\n"; (*this) *= beta; if(alpha==(T)0) return; if(a.nn!=b.nn || a.nn!=nn) laerror("incompatible sizes in SparseSMat::gemm"); @@ -64,11 +65,7 @@ for(SPMatindex k=0; k::sqrabs(scalar); //missing diagonal element -return sqrt(sum); +return std::sqrt(sum); } @@ -208,4 +205,4 @@ INSTANTIZE(complex) template class SparseSMat; template class SparseSMat >; - +}//namespace diff --git a/sparsesmat.h b/sparsesmat.h index 298b8b3..58bd828 100644 --- a/sparsesmat.h +++ b/sparsesmat.h @@ -19,7 +19,6 @@ #ifndef _SPARSESMAT_H_ #define _SPARSESMAT_H_ - #include #include #include @@ -36,6 +35,7 @@ #include #include +namespace LA { //symmetric sparse matrix class with a representation for efficient exponentiatiation //in particular we need a unitary symmetric complex matrix as exp(iH) with H real symmetric @@ -360,5 +360,5 @@ std::istream& operator>>(std::istream &s, SparseSMat &x) } - +}//namespace #endif //_SPARSESMAT_H_ diff --git a/strassen.cc b/strassen.cc index fa55468..9a350ea 100644 --- a/strassen.cc +++ b/strassen.cc @@ -20,6 +20,7 @@ #include "mat.h" #ifndef NO_STRASSEN +namespace LA { /*Strassen algorithm*/ // called routine is fortran-compatible extern "C" void fmm(const char c_transa,const char c_transb,const int m,const int n,const int k,const double alpha, @@ -45,4 +46,5 @@ copyonwrite(); //swap transpositions and order of matrices fmm(transb,transa,mm,nn,k,alpha,b,b.mm, a, a.mm, beta,*this, mm,NULL,0); } +}//namespace #endif diff --git a/t.cc b/t.cc index 1cb8363..183f900 100644 --- a/t.cc +++ b/t.cc @@ -20,18 +20,9 @@ #include #include "la.h" -#include "sparsemat.h" -#include "matexp.h" -#include "fourindex.h" -#include "davidson.h" -#include "gmres.h" -#include "conjgrad.h" -#include "diis.h" -#include "bitvector.h" -#ifdef USE_TRACEBACK -#include "traceback.h" -#endif +using namespace std; +using namespace LA; extern void test(const NRVec &x); @@ -1335,7 +1326,7 @@ cout << "Unitary\n"< > r4 = cov2 + siv2*complex(0,1); cout <<"sincostimes error 2 = "<<(r1-r4).norm()< > h; +cin >> h; +h *= complex(0,1); +h.simplify(); +cout <<"length of hamiltonian "< > hexp = exp(h); +cout <<"sparse exp time "< > he(hexp); +NRMat > hec(he); +NRMat > het(he); +hec.conjugateme(); +het.transposeme(); +//cout < hd(100); +hd.randomize(1); +SparseSMat h(hd); +NRMat rd = hd*hd; +SparseSMat r = h*h; +NRSMatrx(r); +NRMat r2(rx); +cout <<"Error = "<<(r2-rd).norm()< > h; +cin>>h; +h *= complex(0,1); +double t=clock()/((double) (CLOCKS_PER_SEC)); +SparseSMat > r = exp(h); +cout <<"SparseSMat time "< > h3(h); +NRMat > h2(h3); +NRMat >r2 = exp(h2); +cout <<"error = "<<(r2-NRMat >(NRSMat >(r))).norm()< &x) { NRMat aa(0.,2,2); NRMat cc(aa); cc.copyonwrite(); cc[0][0]=1.; -cout << aa << cc <<"\n"; -cout <<"test x= "<. */ + #include -#include "vec.h" #include #include #include #include #include +#include "vec.h" #include "qsort.h" extern "C" { extern ssize_t read(int, void *, size_t); extern ssize_t write(int, const void *, size_t); } +namespace LA { + ////////////////////////////////////////////////////////////////////////////// //// forced instantization in the corespoding object file @@ -42,13 +45,16 @@ template void NRVec::get(int fd, bool dim, bool transp); \ INSTANTIZE(double) INSTANTIZE(complex) -INSTANTIZE(int) -INSTANTIZE(short) -INSTANTIZE(unsigned short) INSTANTIZE(char) +INSTANTIZE(short) +INSTANTIZE(int) +INSTANTIZE(long) +INSTANTIZE(long long) INSTANTIZE(unsigned char) +INSTANTIZE(unsigned short) INSTANTIZE(unsigned int) INSTANTIZE(unsigned long) +INSTANTIZE(unsigned long long) @@ -206,7 +212,7 @@ void NRVec< complex >::axpy(const complex alpha, if (nn != x.nn) laerror("axpy of incompatible vectors"); #endif copyonwrite(); - cblas_zaxpy(nn, (void *)(&alpha), (void *)(x.v), 1, (void *)v, 1); + cblas_zaxpy(nn, &alpha, x.v, 1, v, 1); } // axpy call for T = double (strided) @@ -223,7 +229,7 @@ void NRVec< complex >::axpy(const complex alpha, const complex *x, const int stride) { copyonwrite(); - cblas_zaxpy(nn, (void *)(&alpha), (void *)x, stride, v, 1); + cblas_zaxpy(nn, &alpha, x, stride, v, 1); } // unary minus @@ -242,7 +248,7 @@ NRVec< complex >::operator-() const { NRVec< complex > result(*this); result.copyonwrite(); - cblas_zdscal(nn, -1.0, (void *)(result.v), 1); + cblas_zdscal(nn, -1.0, result.v, 1); return result; } @@ -279,37 +285,26 @@ template<> NRVec< complex > & NRVec< complex >::normalize() { complex tmp; - tmp = cblas_dznrm2(nn, (void *)v, 1); + tmp = cblas_dznrm2(nn, v, 1); #ifdef DEBUG if(!(tmp.real()) && !(tmp.imag())) laerror("normalization of zero vector"); #endif copyonwrite(); tmp = 1.0/tmp; - cblas_zscal(nn, (void *)(&tmp), (void *)v, 1); + cblas_zscal(nn, &tmp, v, 1); return *this; } //stubs for linkage -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<> -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;} - #define INSTANTIZE_DUMMY(T) \ template<> void NRVec::gemv(const T beta, const NRMat &a, const char trans, const T alpha, const NRVec &x) { laerror("gemv on unsupported types"); } \ template<> void NRVec::gemv(const T beta, const NRSMat &a, const char trans, const T alpha, const NRVec &x) { laerror("gemv on unsupported types"); } \ template<> void NRVec::gemv(const T beta, const SparseMat &a, const char trans, const T alpha, const NRVec &x, bool s) { laerror("gemv on unsupported types"); } \ template<> void NRVec::gemv(const LA_traits_complex::Component_type beta, const LA_traits_complex::NRMat_Noncomplex_type &a, const char trans, const LA_traits_complex::Component_type alpha, const NRVec &x) { laerror("gemv on unsupported types"); } \ -template<> void NRVec::gemv(const LA_traits_complex::Component_type beta, const LA_traits_complex::NRSMat_Noncomplex_type &a, const char trans, const LA_traits_complex::Component_type alpha, const NRVec &x) { laerror("gemv on unsupported types"); } +template<> void NRVec::gemv(const LA_traits_complex::Component_type beta, const LA_traits_complex::NRSMat_Noncomplex_type &a, const char trans, const LA_traits_complex::Component_type alpha, const NRVec &x) { laerror("gemv on unsupported types"); } \ +template<> NRVec & NRVec::normalize() {laerror("normalize() impossible for integer types"); return *this;} \ +template<> const NRMat NRVec::otimes(const NRVec &b,const bool conj, const T &scale) const {laerror("otimes presently implemented only for double and complex double"); return NRMat ();} @@ -401,20 +396,22 @@ void NRVec< complex >::gemv(const complex beta, -// Direc product Mat = Vec | Vec +// Direct product Mat = Vec | Vec template<> -const NRMat NRVec::operator|(const NRVec &b) const +const NRMat NRVec::otimes(const NRVec &b,const bool conj, const double &scale) const { NRMat result(0.,nn,b.nn); - cblas_dger(CblasRowMajor, nn, b.nn, 1., v, 1, b.v, 1, result, b.nn); + cblas_dger(CblasRowMajor, nn, b.nn, scale, v, 1, b.v, 1, result, b.nn); return result; } + template<> const NRMat< complex > -NRVec< complex >::operator|(const NRVec< complex > &b) const +NRVec >::otimes(const NRVec< complex > &b, const bool conj, const complex &scale) const { NRMat< complex > result(0.,nn,b.nn); - cblas_zgerc(CblasRowMajor, nn, b.nn, &CONE, v, 1, b.v, 1, result, b.nn); + if(conj) cblas_zgerc(CblasRowMajor, nn, b.nn, &scale, v, 1, b.v, 1, result, b.nn); + else cblas_zgeru(CblasRowMajor, nn, b.nn, &scale, v, 1, b.v, 1, result, b.nn); return result; } @@ -436,24 +433,39 @@ else return memqsort<0,NRVec,int,int>(*this,perm,from,to); template class NRVec; template class NRVec >; template class NRVec; -template class NRVec; template class NRVec; template class NRVec; +template class NRVec; +template class NRVec; +template class NRVec; +template class NRVec; template class NRVec; template class NRVec; +template class NRVec; INSTANTIZE_DUMMY(char) -INSTANTIZE_DUMMY(unsigned char) INSTANTIZE_DUMMY(short) INSTANTIZE_DUMMY(int) +INSTANTIZE_DUMMY(long) +INSTANTIZE_DUMMY(long long) +INSTANTIZE_DUMMY(unsigned char) +INSTANTIZE_DUMMY(unsigned short) INSTANTIZE_DUMMY(unsigned int) INSTANTIZE_DUMMY(unsigned long) +INSTANTIZE_DUMMY(unsigned long long) INSTANTIZE_DUMMY(complex) -INSTANTIZE_DUMMY(complex) INSTANTIZE_DUMMY(complex) INSTANTIZE_DUMMY(complex) +INSTANTIZE_DUMMY(complex) +INSTANTIZE_DUMMY(complex) +INSTANTIZE_DUMMY(complex) +INSTANTIZE_DUMMY(complex) INSTANTIZE_DUMMY(complex) +INSTANTIZE_DUMMY(complex) +INSTANTIZE_DUMMY(complex) + INSTANTIZE_DUMMY(complex >) INSTANTIZE_DUMMY(complex >) -INSTANTIZE_DUMMY(complex) + +}//namespace diff --git a/vec.h b/vec.h index 6ce250a..75d5b7b 100644 --- a/vec.h +++ b/vec.h @@ -21,6 +21,8 @@ #include "la_traits.h" +namespace LA { + ////////////////////////////////////////////////////////////////////////////// // Forward declarations template void lawritemat(FILE *file,const T *a,int r,int c, @@ -104,7 +106,8 @@ public: 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;}; - const NRMat operator|(const NRVec &rhs) const; + const NRMat otimes(const NRVec &rhs, const bool conjugate=false, const T &scale=1) const; //outer product + inline const NRMat operator|(const NRVec &rhs) const {return otimes(rhs,true);}; inline const T sum() const {T sum=0; for(int i=0; i -ostream & operator<<(ostream &s, const NRVec &x) +std::ostream & operator<<(std::ostream &s, const NRVec &x) { int i, n; n = x.size(); - s << n << endl; + s << n << std::endl; for(i=0; i::IOtype)x[i] << (i == n-1 ? '\n' : ' '); return s; } template -istream & operator>>(istream &s, NRVec &x) +std::istream & operator>>(std::istream &s, NRVec &x) { int i,n; @@ -238,7 +243,7 @@ inline NRVec< complex > & NRVec< complex >::operator+=(const complex &a) { copyonwrite(); - cblas_zaxpy(nn, (void *)(&CONE), (void *)(&a), 0, (void *)v, 1); + cblas_zaxpy(nn, &CONE, &a, 0, v, 1); return *this; } @@ -267,7 +272,7 @@ inline NRVec< complex > & NRVec< complex >::operator-=(const complex &a) { copyonwrite(); - cblas_zaxpy(nn, (void *)(&CMONE), (void *)(&a), 0, (void *)v, 1); + cblas_zaxpy(nn, &CMONE, &a, 0, v, 1); return *this; } @@ -302,7 +307,7 @@ NRVec< complex >::operator+=(const NRVec< complex > &rhs) if (nn != rhs.nn) laerror("daxpy of incompatible vectors"); #endif copyonwrite(); - cblas_zaxpy(nn, (void *)(&CONE), rhs.v, 1, v, 1); + cblas_zaxpy(nn, &CONE, rhs.v, 1, v, 1); return *this; } @@ -366,7 +371,7 @@ NRVec< complex >::operator-=(const NRVec< complex > &rhs) if (nn != rhs.nn) laerror("daxpy of incompatible vectors"); #endif copyonwrite(); - cblas_zaxpy(nn, (void *)(&CMONE), (void *)rhs.v, 1, (void *)v, 1); + cblas_zaxpy(nn, &CMONE, rhs.v, 1, v, 1); return *this; } @@ -398,7 +403,7 @@ inline NRVec< complex > & NRVec< complex >::operator*=(const complex &a) { copyonwrite(); - cblas_zscal(nn, (void *)(&a), (void *)v, 1); + cblas_zscal(nn, &a, v, 1); return *this; } @@ -432,7 +437,7 @@ NRVec< complex >::operator*(const NRVec< complex > &rhs) const if (nn != rhs.nn) laerror("dot of incompatible vectors"); #endif complex dot; - cblas_zdotc_sub(nn, (void *)v, 1, (void *)rhs.v, 1, (void *)(&dot)); + cblas_zdotc_sub(nn, v, 1, rhs.v, 1, &dot); return dot; } @@ -468,7 +473,7 @@ inline const complex NRVec< complex >::dot(const complex *y, const int stride) const { complex dot; - cblas_zdotc_sub(nn, y, stride, v, 1, (void *)(&dot)); + cblas_zdotc_sub(nn, y, stride, v, 1, &dot); return dot; } @@ -527,7 +532,7 @@ inline const double NRVec::norm() const template<> inline const double NRVec< complex >::norm() const { - return cblas_dznrm2(nn, (void *)v, 1); + return cblas_dznrm2(nn, v, 1); } // Max element of the array @@ -539,7 +544,7 @@ inline const double NRVec::amax() const template<> inline const complex NRVec< complex >::amax() const { - return v[cblas_izamax(nn, (void *)v, 1)]; + return v[cblas_izamax(nn, v, 1)]; } @@ -687,6 +692,6 @@ for(int i=0; i