*** empty log message ***
This commit is contained in:
parent
f44662bdab
commit
7f7c4aa553
@ -17,6 +17,7 @@
|
||||
*/
|
||||
#ifndef _AUXSTORAGE_H_
|
||||
#define _AUXSTORAGE_H_
|
||||
|
||||
#include "vec.h"
|
||||
#include "mat.h"
|
||||
#include "smat.h"
|
||||
@ -27,6 +28,8 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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<x.size(); ++i) s<< x[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
istream & operator>>(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
|
||||
|
@ -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
|
||||
|
14
conjgrad.h
14
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _CONJGRAD_H_
|
||||
#define _CONJGRAD_H_
|
||||
#include "vec.h"
|
||||
#include "smat.h"
|
||||
#include "mat.h"
|
||||
@ -22,6 +24,8 @@
|
||||
#include "nonclass.h"
|
||||
#include <iomanip>
|
||||
|
||||
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= "<<iter<<" err= "<<
|
||||
setiosflags(ios::scientific)<<setprecision(8) <<err<<
|
||||
resetiosflags(ios::scientific)<<setprecision(12)<<"\n";
|
||||
cout.flush();
|
||||
std::cout << "conjgrad: iter= "<<iter<<" err= "<<
|
||||
std::setiosflags(std::ios::scientific)<<std::setprecision(8) <<err<<
|
||||
std::resetiosflags(std::ios::scientific)<<std::setprecision(12)<<"\n";
|
||||
std::cout.flush();
|
||||
}
|
||||
if(err <= tol)
|
||||
{
|
||||
@ -94,3 +98,5 @@ if(!issquare) delete r;
|
||||
return false;
|
||||
}
|
||||
|
||||
}//namespace
|
||||
#endif
|
||||
|
25
davidson.h
25
davidson.h
@ -24,6 +24,8 @@
|
||||
#include "nonclass.h"
|
||||
#include "auxstorage.h"
|
||||
|
||||
namespace LA {
|
||||
|
||||
//Davidson diagonalization of real symmetric matrix (modified Lanczos)
|
||||
|
||||
//matrix can be any class which has nrows(), ncols(), diagonalof(), issymmetric(), and gemv() available
|
||||
@ -146,21 +148,21 @@ else
|
||||
|
||||
T eival_n=r[nroot];
|
||||
oldnroot=nroot;
|
||||
typename LA_traits<T>::normtype test=abs(smallV(krylovsize,nroot));
|
||||
typename LA_traits<T>::normtype test=std::abs(smallV(krylovsize,nroot));
|
||||
if(test<eps) nroot++;
|
||||
if(it==0) nroot = 0;
|
||||
for(int iroot=0; iroot<=min(krylovsize,nroots-1); ++iroot)
|
||||
for(int iroot=0; iroot<=std::min(krylovsize,nroots-1); ++iroot)
|
||||
{
|
||||
test = abs(smallV(krylovsize,iroot));
|
||||
if(test>eps) 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="<<it <<" dim="<<krylovsize<<" root="<<iroot<<" energy="<<r[iroot]<<"\n";
|
||||
cout.flush();
|
||||
std::cout <<"Davidson: iter="<<it <<" dim="<<krylovsize<<" root="<<iroot<<" energy="<<r[iroot]<<"\n";
|
||||
std::cout.flush();
|
||||
}
|
||||
}
|
||||
|
||||
if(verbose && oldnroot!=nroot) {cout <<"root no. "<<oldnroot<<" converged\n"; cout.flush();}
|
||||
if(verbose && oldnroot!=nroot) {std::cout <<"root no. "<<oldnroot<<" converged\n"; std::cout.flush();}
|
||||
if (nroot>=nroots) goto converged;
|
||||
if (it==maxit-1) break; //not converged
|
||||
|
||||
@ -195,7 +197,7 @@ eival_n = r[nroot];
|
||||
for(i=0; i<n; ++i)
|
||||
{
|
||||
T denom = diagonal[i] - eival_n;
|
||||
denom = denom<0?-max(0.1,abs(denom)):max(0.1,abs(denom));
|
||||
denom = denom<0?-std::max(0.1,std::abs(denom)):std::max(0.1,std::abs(denom));
|
||||
vec1[i] /= denom;
|
||||
}
|
||||
|
||||
@ -224,7 +226,7 @@ goto finished;
|
||||
converged:
|
||||
AuxStorage<typename LA_traits<T>::elementtype> *ev;
|
||||
if(eivecsfile) ev = new AuxStorage<typename LA_traits<T>::elementtype>(eivecsfile);
|
||||
if(verbose) {cout << "Davidson converged in "<<it<<" iterations.\n"; cout.flush();}
|
||||
if(verbose) {std::cout << "Davidson converged in "<<it<<" iterations.\n"; std::cout.flush();}
|
||||
for(nroot=0; nroot<nroots; ++nroot)
|
||||
{
|
||||
eivals[nroot]=r[nroot];
|
||||
@ -254,6 +256,5 @@ else {delete s0; delete s1;}
|
||||
if(flag) laerror("no convergence in davidson");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}//namespace
|
||||
#endif
|
||||
|
7
diis.h
7
diis.h
@ -26,8 +26,10 @@
|
||||
#include "la_traits.h"
|
||||
#include "auxstorage.h"
|
||||
|
||||
namespace LA {
|
||||
|
||||
//Pulay memorial book remarks - for numerical stabilization small addition to diagonal
|
||||
#define DIISEPS 1e-9
|
||||
const double DIISEPS=1e-9;
|
||||
|
||||
// Typically, T is some solution vector in form of NRVec, NRMat, or NRSMat over double or complex<double> fields
|
||||
// actually it can be anything what has operator=(const T&), clear(), dot() , axpy(), norm() and copyonwrite(), and LA_traits<T>::normtype and elementtype
|
||||
@ -150,7 +152,7 @@ rhs= (Ue)0; rhs[0]= (Ue)-1;
|
||||
NRSMat<Te> amat=bmat;
|
||||
linear_solve(amat,rhs,NULL,aktdim+1);
|
||||
}
|
||||
if(verbose) cout <<"DIIS coefficients: "<<rhs<<endl;
|
||||
if(verbose) std::cout <<"DIIS coefficients: "<<rhs<<std::endl;
|
||||
|
||||
//build the new linear combination
|
||||
vec.clear();
|
||||
@ -170,5 +172,6 @@ else
|
||||
return norm;
|
||||
}
|
||||
|
||||
}//namespace
|
||||
|
||||
#endif
|
||||
|
28
fourindex.h
28
fourindex.h
@ -26,9 +26,13 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#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 <class I, class T>
|
||||
ostream& operator<<(ostream &s, const fourindex_ext<I,T> &x)
|
||||
std::ostream& operator<<(std::ostream &s, const fourindex_ext<I,T> &x)
|
||||
{
|
||||
int n;
|
||||
n=x.size();
|
||||
@ -609,7 +613,7 @@ ostream& operator<<(ostream &s, const fourindex_ext<I,T> &x)
|
||||
|
||||
|
||||
template <class I, class T>
|
||||
ostream& operator<<(ostream &s, const fourindex<I,T> &x)
|
||||
std::ostream& operator<<(std::ostream &s, const fourindex<I,T> &x)
|
||||
{
|
||||
int n;
|
||||
n=x.size();
|
||||
@ -625,7 +629,7 @@ ostream& operator<<(ostream &s, const fourindex<I,T> &x)
|
||||
}
|
||||
|
||||
template <class I, class T>
|
||||
istream& operator>>(istream &s, fourindex<I,T> &x)
|
||||
std::istream& operator>>(std::istream &s, fourindex<I,T> &x)
|
||||
{
|
||||
typename LA_traits_io<I>::IOtype i,j,k,l;
|
||||
typename LA_traits_io<T>::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<T>::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<T>::v) laerror("access to unallocated fourindex_dense");
|
||||
return (*this).NRMat<T>::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<<" "<<j<<" "<<a<<" "<<b<<" "<<(*this)(i,j,a,b)<<endl;
|
||||
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<<" "<<j<<" "<<a<<" "<<b<<" "<<(*this)(i,j,a,b)<<std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
@ -854,10 +858,10 @@ if(a<b) {minus++; unsigned int t=a; a=b; b=t;}
|
||||
}
|
||||
|
||||
|
||||
void print(ostream &out) const
|
||||
void print(std::ostream &out) const
|
||||
{
|
||||
unsigned int i,j,a,b;
|
||||
for(i=1; i<=nocc; ++i) for(j=1; j<i; ++j) for(a=1; a<=nvrt; ++a) for(b=1; b<a; ++b) out << i<<" "<<j<<" "<<a<<" "<<b<<" "<<(*this)(i,j,a,b)<<endl;
|
||||
for(i=1; i<=nocc; ++i) for(j=1; j<i; ++j) for(a=1; a<=nvrt; ++a) for(b=1; b<a; ++b) out << i<<" "<<j<<" "<<a<<" "<<b<<" "<<(*this)(i,j,a,b)<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
@ -886,14 +890,14 @@ public:
|
||||
void add_unique(unsigned int i, unsigned int j, unsigned int k, unsigned int l, T elem);
|
||||
const T& operator() (unsigned int i, unsigned int j, unsigned int k, unsigned int l) const;
|
||||
void resize(const int n) {nbas=n; (*this).NRSMat<T>::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<i; ++k)
|
||||
for(j=1; j<=i; ++j)
|
||||
for(l=1; l<j && (j==i ? l<=k : 1); ++l)
|
||||
cout << i<<" "<<k<<" "<<j<<" "<<l<<" "<<(*this)(i,k,j,l)<<endl;
|
||||
std::cout << i<<" "<<k<<" "<<j<<" "<<l<<" "<<(*this)(i,k,j,l)<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
@ -992,6 +996,6 @@ for(p= const_cast<fourindex_ext<I,T> *>(&rhs)->pbegin(); p.notend(); ++p)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}//namespace
|
||||
|
||||
#endif /*_fourindex_included*/
|
||||
|
21
gmres.h
21
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _GMRES_H
|
||||
#define _GMRES_H
|
||||
#include "vec.h"
|
||||
#include "smat.h"
|
||||
#include "mat.h"
|
||||
@ -24,6 +26,8 @@
|
||||
#include <iomanip>
|
||||
#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<neustart;l++) // main loop for restarts
|
||||
H(k+1,k) = tmp= z.norm();
|
||||
if(tmp < 1.e-2*eps )
|
||||
{
|
||||
if(verbose) cerr <<("gmres restart performed\n");
|
||||
if(verbose) std::cerr <<("gmres restart performed\n");
|
||||
// Abbruchbedingung, konstruiere x_k
|
||||
for (int i=0;i<k;i++)
|
||||
{
|
||||
@ -190,12 +194,12 @@ for (int l=0;l<neustart;l++) // main loop for restarts
|
||||
//Schritt 6: Konvergenz?
|
||||
if(verbose)
|
||||
{
|
||||
cout << "gmres iter "<<l<<" "<<k<<" resid "
|
||||
<<setw(0)<<setiosflags(ios::scientific)<<setprecision(8)
|
||||
<<abs(d[k+1])<< " thr "<<eps*beta_0<< " reduction "
|
||||
<<setw(5)<<setprecision(2)<<resetiosflags(ios::scientific)
|
||||
<<(d_alt - abs(d[k+1]))/d_alt*100<< "\n" <<setprecision(12);
|
||||
cout.flush();
|
||||
std::cout << "gmres iter "<<l<<" "<<k<<" resid "
|
||||
<<std::setw(0)<<std::setiosflags(std::ios::scientific)<<std::setprecision(8)
|
||||
<<std::abs(d[k+1])<< " thr "<<eps*beta_0<< " reduction "
|
||||
<<std::setw(5)<<std::setprecision(2)<<std::resetiosflags(std::ios::scientific)
|
||||
<<(d_alt - std::abs(d[k+1]))/d_alt*100<< "\n" <<std::setprecision(12);
|
||||
std::cout.flush();
|
||||
}
|
||||
|
||||
d_alt = abs(d[k+1]);
|
||||
@ -258,3 +262,6 @@ if(!incore) delete st;
|
||||
return !flag;
|
||||
}
|
||||
|
||||
}//namespace
|
||||
|
||||
#endif
|
||||
|
25
la.h
25
la.h
@ -20,10 +20,29 @@
|
||||
|
||||
//this should be the single include file for the end user
|
||||
//
|
||||
|
||||
#include "vec.h"
|
||||
#include "smat.h"
|
||||
#ifdef USE_TRACEBACK
|
||||
#include "traceback.h"
|
||||
#endif
|
||||
#include "la_traits.h"
|
||||
#include "laerror.h"
|
||||
#include "auxstorage.h"
|
||||
#include "bisection.h"
|
||||
#include "bitvector.h"
|
||||
#include "conjgrad.h"
|
||||
#include "davidson.h"
|
||||
#include "diis.h"
|
||||
#include "fourindex.h"
|
||||
#include "gmres.h"
|
||||
#include "mat.h"
|
||||
#include "matexp.h"
|
||||
#include "noncblas.h"
|
||||
#include "nonclass.h"
|
||||
#include "permutation.h"
|
||||
#include "qsort.h"
|
||||
#include "smat.h"
|
||||
#include "sparsemat.h"
|
||||
#include "sparsesmat.h"
|
||||
#include "vec.h"
|
||||
|
||||
|
||||
#endif /* _LA_H_ */
|
||||
|
28
la_traits.h
28
la_traits.h
@ -27,14 +27,17 @@
|
||||
#define _LA_TRAITS_INCL
|
||||
|
||||
|
||||
extern bool _LA_count_check;
|
||||
|
||||
|
||||
using namespace std;
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <complex>
|
||||
|
||||
|
||||
//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<typename C> class NRVec;
|
||||
@ -61,6 +67,7 @@ template<typename C> class NRMat_from1;
|
||||
template<typename C> class NRSMat;
|
||||
template<typename C> class NRSMat_from1;
|
||||
template<typename C> class SparseMat;
|
||||
template<typename C> class SparseSMat;
|
||||
|
||||
|
||||
typedef class {} Dummy_type;
|
||||
@ -95,9 +102,13 @@ SPECIALIZE_COMPLEX(complex<float>)
|
||||
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<complex<C>, scalar_true> {
|
||||
typedef complex<C> elementtype;
|
||||
typedef complex<C> producttype;
|
||||
typedef C normtype;
|
||||
static inline C sqrabs(const complex<C> x) { return x.real()*x.real()+x.imag()*x.imag();}
|
||||
static inline bool gencmp(const complex<C> *x, const complex<C> *y, int n) {return memcmp(x,y,n*sizeof(complex<C>));}
|
||||
static bool bigger(const complex<C> &x, const complex<C> &y) {laerror("complex comparison undefined"); return false;}
|
||||
static bool smaller(const complex<C> &x, const complex<C> &y) {laerror("complex comparison undefined"); return false;}
|
||||
static inline normtype norm (const complex<C> &x) {return abs(x);}
|
||||
static inline normtype norm (const complex<C> &x) {return std::abs(x);}
|
||||
static inline void axpy (complex<C> &s, const complex<C> &x, const complex<C> &c) {s+=x*c;}
|
||||
static inline void get(int fd, complex<C> &x, bool dimensions=0, bool transp=0) {if(sizeof(complex<C>)!=read(fd,&x,sizeof(complex<C>))) laerror("read error");}
|
||||
static inline void put(int fd, const complex<C> &x, bool dimensions=0, bool transp=0) {if(sizeof(complex<C>)!=write(fd,&x,sizeof(complex<C>))) laerror("write error");}
|
||||
@ -206,6 +218,7 @@ static void multiput(unsigned int n, int fd, const complex<C> *x, bool dimension
|
||||
static void copy(complex<C> *dest, complex<C> *src, unsigned int n) {memcpy(dest,src,n*sizeof(complex<C>));}
|
||||
static void clear(complex<C> *dest, unsigned int n) {memset(dest,0,n*sizeof(complex<C>));}
|
||||
static void copyonwrite(complex<C> &x) {};
|
||||
static void clearme(complex<C> &x) {x=0;};
|
||||
};
|
||||
|
||||
//non-complex scalars
|
||||
@ -214,10 +227,11 @@ struct LA_traits_aux<C, scalar_true> {
|
||||
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<y;}
|
||||
static inline normtype norm (const C &x) {return abs(x);}
|
||||
static inline normtype norm (const C &x) {return std::abs(x);}
|
||||
static inline void axpy (C &s, const C &x, const C &c) {s+=x*c;}
|
||||
static inline void put(int fd, const C &x, bool dimensions=0, bool transp=0) {if(sizeof(C)!=write(fd,&x,sizeof(C))) laerror("write error");}
|
||||
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");}
|
||||
@ -226,6 +240,7 @@ static void multiget(unsigned int n, int fd, C *x, bool dimensions=0) {if((ssize
|
||||
static void copy(C *dest, C *src, unsigned int n) {memcpy(dest,src,n*sizeof(C));}
|
||||
static void clear(C *dest, unsigned int n) {memset(dest,0,n*sizeof(C));}
|
||||
static void copyonwrite(C &x) {};
|
||||
static void clearme(complex<C> &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<n; ++i) dest[i]=src[i];} \
|
||||
static void clear(C *dest, unsigned int n) {for(unsigned int i=0; i<n; ++i) dest[i].clear();}\
|
||||
static void copyonwrite(X<C> &x) {x.copyonwrite();}\
|
||||
static void clearme(X<C> &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<n; ++i) dest[i]=src[i];} \
|
||||
static void clear(C *dest, unsigned int n) {for(unsigned int i=0; i<n; ++i) dest[i].clear();} \
|
||||
static void copyonwrite(X<C> &x) {x.copyonwrite();} \
|
||||
static void clearme(X<C> &x) {x.clear();} \
|
||||
};
|
||||
|
||||
generate_traits_smat(NRSMat)
|
||||
@ -292,4 +310,6 @@ generate_traits_smat(NRSMat_from1)
|
||||
template<typename C>
|
||||
struct LA_traits : LA_traits_aux<C, typename isscalar<C>::scalar_type> {};
|
||||
|
||||
}//namespace
|
||||
|
||||
#endif
|
||||
|
@ -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
|
||||
|
@ -17,9 +17,10 @@
|
||||
*/
|
||||
#ifndef _LAERROR_H_
|
||||
#define _LAERROR_H_
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace LA {
|
||||
|
||||
//exception class for laerror
|
||||
class LAerror
|
||||
{
|
||||
@ -36,5 +37,6 @@ s << x.msg;
|
||||
return s;
|
||||
}
|
||||
|
||||
}//namespace
|
||||
|
||||
#endif
|
||||
|
52
mat.cc
52
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<complex<double> > r(mm,mm);
|
||||
int i,j;
|
||||
for(i=0; i<mm; ++i) for(j=0; j<=i; ++j)
|
||||
#ifdef MATPTR
|
||||
cblas_zdotc_sub(nn, v[0]+i , mm,v[0]+j, mm, (void *)(&r(i,j)));
|
||||
cblas_zdotc_sub(nn, v[0]+i , mm,v[0]+j, mm, &r(i,j));
|
||||
#else
|
||||
cblas_zdotc_sub(nn, v+i , mm,v+j, mm, (void *)(&r(i,j)));
|
||||
cblas_zdotc_sub(nn, v+i , mm,v+j, mm, &r(i,j));
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
@ -486,9 +487,9 @@ NRSMat<complex<double> > r(nn,nn);
|
||||
int i,j;
|
||||
for(i=0; i<nn; ++i) for(j=0; j<=i; ++j)
|
||||
#ifdef MATPTR
|
||||
cblas_zdotc_sub(mm, v[i] , 1,v[j], 1, (void *)(&r(i,j)));
|
||||
cblas_zdotc_sub(mm, v[i] , 1,v[j], 1, &r(i,j));
|
||||
#else
|
||||
cblas_zdotc_sub(mm, v+i*mm , 1,v+j*mm, 1, (void *)(&r(i,j)));
|
||||
cblas_zdotc_sub(mm, v+i*mm , 1,v+j*mm, 1, &r(i,j));
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
@ -548,7 +549,7 @@ NRMat< complex<double> > &
|
||||
NRMat< complex<double> >::operator*=(const complex<double> &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<double> >::operator+=(const NRMat< complex<double> > &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<double> >::operator-=(const NRMat< complex<double> > &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<double> >::operator+=(const NRSMat< complex<double> > &rhs)
|
||||
const complex<double> *p = rhs;
|
||||
copyonwrite();
|
||||
for (int i=0; i<nn; i++) {
|
||||
cblas_zaxpy(i+1, (void *)&CONE, (void *)p, 1, (void *)(*this)[i], 1);
|
||||
cblas_zaxpy(i+1, &CONE, p, 1, (*this)[i], 1);
|
||||
p += i+1;
|
||||
}
|
||||
p = rhs; p++;
|
||||
for (int i=1; i<nn; i++) {
|
||||
cblas_zaxpy(i, (void *)&CONE, (void *)p, 1, (void *)((*this)[i]+i), nn);
|
||||
cblas_zaxpy(i, &CONE, p, 1, (*this)[0]+i, nn);
|
||||
p += i+1;
|
||||
}
|
||||
return *this;
|
||||
@ -725,7 +726,7 @@ NRMat<T> & NRMat<T>::operator+=(const NRSMat<T> &rhs)
|
||||
}
|
||||
p = rhs; p++;
|
||||
for (int i=1; i<nn; i++) {
|
||||
for(int j=0; j<i; ++j) *((*this)[i]+i+nn*j) += p[j];
|
||||
for(int j=0; j<i; ++j) *((*this)[j]+i) += p[j];
|
||||
p += i+1;
|
||||
}
|
||||
return *this;
|
||||
@ -765,12 +766,12 @@ NRMat< complex<double> >::operator-=(const NRSMat< complex<double> > &rhs)
|
||||
const complex<double> *p = rhs;
|
||||
copyonwrite();
|
||||
for (int i=0; i<nn; i++) {
|
||||
cblas_zaxpy(i+1, (void *)&CMONE, (void *)p, 1, (void *)(*this)[i], 1);
|
||||
cblas_zaxpy(i+1, &CMONE, p, 1, (*this)[i], 1);
|
||||
p += i+1;
|
||||
}
|
||||
p = rhs; p++;
|
||||
for (int i=1; i<nn; i++) {
|
||||
cblas_zaxpy(i, (void *)&CMONE, (void *)p, 1, (void *)((*this)[i]+i), nn);
|
||||
cblas_zaxpy(i, &CMONE, p, 1, (*this)[0]+i, nn);
|
||||
p += i+1;
|
||||
}
|
||||
return *this;
|
||||
@ -792,7 +793,7 @@ NRMat<T> & NRMat<T>::operator-=(const NRSMat<T> &rhs)
|
||||
}
|
||||
p = rhs; p++;
|
||||
for (int i=1; i<nn; i++) {
|
||||
for(int j=0; j<i; ++j) *((*this)[i]+i+nn*j) -= p[j];
|
||||
for(int j=0; j<i; ++j) *((*this)[j]+i) -= p[j];
|
||||
p += i+1;
|
||||
}
|
||||
return *this;
|
||||
@ -821,8 +822,8 @@ NRMat< complex<double> >::dot(const NRMat< complex<double> > &rhs) const
|
||||
if(nn!=rhs.nn || mm!= rhs.mm) laerror("Mat.Mat incompatible matrices");
|
||||
#endif
|
||||
complex<double> 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<double> >::operator*(const NRMat< complex<double> > &rhs) const
|
||||
#endif
|
||||
NRMat< complex<double> > 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<double> >::operator*(const NRSMat< complex<double> > &rhs) const
|
||||
#endif
|
||||
NRMat< complex<double> > result(nn, rhs.ncols());
|
||||
for (int i=0; i<nn; i++)
|
||||
cblas_zhpmv(CblasRowMajor, CblasLower, mm, (void *)&CONE, (void *)&rhs[0],
|
||||
(void *)(*this)[i], 1, (void *)&CZERO, (void *)result[i], 1);
|
||||
cblas_zhpmv(CblasRowMajor, CblasLower, mm, &CONE, &rhs[0],
|
||||
(*this)[i], 1, &CZERO, result[i], 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -969,7 +970,7 @@ NRMat< complex<double> >::transpose(bool conj) const
|
||||
{
|
||||
NRMat< complex<double> > result(mm,nn);
|
||||
for (int i=0; i<nn; i++)
|
||||
cblas_zcopy(mm, (void *)(*this)[i], 1, (void *)(result[0]+i), nn);
|
||||
cblas_zcopy(mm, (*this)[i], 1, (result[0]+i), nn);
|
||||
if (conj) cblas_dscal(mm*nn, -1.0, (double *)(result[0])+1, 2);
|
||||
return result;
|
||||
}
|
||||
@ -1039,7 +1040,7 @@ const double NRMat<double>::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<double> >::norm(const complex<double> 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<double> >::axpy(const complex<double> 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<double> 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<double> 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<unsigned int>;
|
||||
template class NRMat<unsigned long>;
|
||||
template class NRMat<unsigned long long>;
|
||||
|
||||
}//namespace
|
||||
|
14
mat.h
14
mat.h
@ -19,9 +19,9 @@
|
||||
*/
|
||||
#ifndef _LA_MAT_H_
|
||||
#define _LA_MAT_H_
|
||||
|
||||
#include "la_traits.h"
|
||||
|
||||
namespace LA {
|
||||
template <typename T>
|
||||
class NRMat {
|
||||
protected:
|
||||
@ -91,6 +91,7 @@ public:
|
||||
const NRVec<complex<T> > operator*(const NRVec<complex<T> > &rhs) const {NRVec<complex<T> > result(nn); result.gemv((T)0,*this,'n',(T)1,rhs); return result;}; // Mat * Vec
|
||||
const NRVec<T> rsum() const; //sum of rows
|
||||
const NRVec<T> csum() const; //sum of columns
|
||||
void orthonormalize(const bool rowcol, const NRSMat<T> *metric=NULL);//orthonormalize (true - vectors are rows)
|
||||
const NRVec<T> row(const int i, int l= -1) const; //row of, efficient
|
||||
const NRVec<T> column(const int j, int l= -1) const {if(l<0) l=nn; NRVec<T> r(l); for(int i=0; i<l; ++i) r[i]= (*this)(i,j); return r;}; //column of, general but not very efficient
|
||||
const T* diagonalof(NRVec<T> &, 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 <typename T>
|
||||
NRMat<T>::NRMat(const int n, const int m) : nn(n), mm(m), count(new int)
|
||||
@ -374,9 +377,9 @@ template<>
|
||||
inline const complex<double> NRMat< complex<double> >::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 <typename T>
|
||||
ostream& operator<<(ostream &s, const NRMat<T> &x)
|
||||
std::ostream& operator<<(std::ostream &s, const NRMat<T> &x)
|
||||
{
|
||||
int i,j,n,m;
|
||||
n=x.nrows();
|
||||
@ -590,7 +593,7 @@ ostream& operator<<(ostream &s, const NRMat<T> &x)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
istream& operator>>(istream &s, NRMat<T> &x)
|
||||
std::istream& operator>>(std::istream &s, NRMat<T> &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_ */
|
||||
|
34
matexp.h
34
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 <math.h>
|
||||
|
||||
namespace LA {
|
||||
|
||||
template<class T,class R>
|
||||
const T polynom0(const T &x, const NRVec<R> &c)
|
||||
@ -40,6 +41,7 @@ else
|
||||
z=x*c[order];
|
||||
for(i=order-1; i>=0; i--)
|
||||
{
|
||||
//std::cerr<<"TEST polynom0 "<<i<<'\n';
|
||||
if(i<order-1) z=y*x;
|
||||
y=z+c[i];
|
||||
}
|
||||
@ -138,7 +140,7 @@ for(int i=1; i<=n; ++i)
|
||||
{
|
||||
factor/=i;
|
||||
z= z*t-t*z;
|
||||
if(verbose) cerr << "BCH contribution at order "<<i<<" : "<<z.norm()*factor<<endl;
|
||||
if(verbose) std::cerr << "BCH contribution at order "<<i<<" : "<<z.norm()*factor<<std::endl;
|
||||
result+= z*factor;
|
||||
}
|
||||
return result;
|
||||
@ -169,10 +171,10 @@ return y;
|
||||
|
||||
inline int nextpow2(const double n)
|
||||
{
|
||||
const double log2=log(2.);
|
||||
const double log2=std::log(2.);
|
||||
if(n<=.75) return 0; //try to keep the taylor expansion short
|
||||
if(n<=1.) return 1;
|
||||
return int(ceil(log(n)/log2-log(.75)));
|
||||
return int(std::ceil(std::log(n)/log2-std::log(.75)));
|
||||
}
|
||||
|
||||
//should better be computed by mathematica to have accurate last digits, perhaps chebyshev instead, see exp in glibc
|
||||
@ -208,10 +210,10 @@ template<class T, class C, class S>
|
||||
NRVec<C> 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 "<<power<<" "<<scale<<endl;
|
||||
//cout <<"TEST taylor2 "<<taylor2<<endl;
|
||||
//std::cout <<"TEST power, scale "<<power<<" "<<scale<<std::endl;
|
||||
//std::cout <<"TEST taylor2 "<<taylor2<<std::endl;
|
||||
return taylor2;
|
||||
}
|
||||
|
||||
@ -246,10 +248,10 @@ return taylor2;
|
||||
template<class T, class C, class S>
|
||||
void sincos_aux(NRVec<C> &si, NRVec<C> &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 "<<si<<endl;
|
||||
//cout <<"TEST cos "<<co<<endl;
|
||||
//std::cout <<"TEST sin "<<si<<std::endl;
|
||||
//std::cout <<"TEST cos "<<co<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
@ -290,6 +292,7 @@ int power;
|
||||
//prepare the polynom of and effectively scale T
|
||||
NRVec<typename LA_traits<T>::normtype> taylor2=exp_aux<T,typename LA_traits<T>::normtype,double>(x,power,maxpower,maxtaylor,1.);
|
||||
|
||||
//std::cerr <<"TEST power "<<power<<std::endl;
|
||||
|
||||
T r= horner?polynom0(x,taylor2):polynom(x,taylor2);
|
||||
//for accuracy summing from the smallest terms up would be better, but this is more efficient for matrices
|
||||
@ -309,6 +312,7 @@ int power;
|
||||
NRVec<typename LA_traits<T>::normtype> taylors,taylorc;
|
||||
sincos_aux<T,typename LA_traits<T>::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<typename LA_traits<V>::normtype> taylors,taylorc;
|
||||
sincos_aux<M,typename LA_traits<V>::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 "<<power<<endl;
|
||||
//std::cout <<"TEST power "<<power<<std::endl;
|
||||
sincostimes_aux(mat,si,co,rhs,taylors,taylorc,transpose,scale,power);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//@@@ power series matrix logarithm?
|
||||
|
||||
}//namespace
|
||||
#endif
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "laerror.h"
|
||||
#include "mat.h"
|
||||
|
||||
namespace LA {
|
||||
|
||||
#ifdef FORTRAN_
|
||||
#define FORNAME(x) x##_
|
||||
#else
|
||||
@ -255,3 +257,5 @@ return INFO;
|
||||
|
||||
#endif
|
||||
|
||||
}//namespace
|
||||
|
||||
|
63
nonclass.cc
63
nonclass.cc
@ -24,6 +24,7 @@
|
||||
#include "nonclass.h"
|
||||
#include "qsort.h"
|
||||
|
||||
namespace LA {
|
||||
|
||||
#ifdef FORTRAN_
|
||||
#define FORNAME(x) x##_
|
||||
@ -39,9 +40,13 @@ INSTANTIZE(complex<double>)
|
||||
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<double> &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<n; ++i) {double t=A[i][i]; if(!finite(t) || abs(t) < EPSDET ) {*det=0.; break;} else *det *=t;}
|
||||
for (int i=0; i<n; ++i) {double t=A[i][i]; if(!finite(t) || std::abs(t) < EPSDET ) {*det=0.; break;} else *det *=t;}
|
||||
//change sign of det by parity of ipiv permutation
|
||||
if(*det) for (int i=0; i<n; ++i) if(
|
||||
#ifdef NONCBLAS
|
||||
@ -158,9 +163,9 @@ static void linear_solve_do(NRMat<double> &A, double *B, const int nrhs, const i
|
||||
}
|
||||
if(det && r>0) *det = 0;
|
||||
/*
|
||||
cout <<"ipiv = ";
|
||||
for (int i=0; i<n; ++i) cout <<ipiv[i]<<" ";
|
||||
cout <<endl;
|
||||
std::cout <<"ipiv = ";
|
||||
for (int i=0; i<n; ++i) std::cout <<ipiv[i]<<" ";
|
||||
std::cout <<std::endl;
|
||||
*/
|
||||
delete [] ipiv;
|
||||
if (r>0 && B) laerror("singular matrix in lapack_gesv");
|
||||
@ -202,7 +207,7 @@ static void linear_solve_do(NRSMat<double> &a, double *b, const int nrhs, const
|
||||
}
|
||||
if (det && r == 0) {
|
||||
*det = 1.;
|
||||
for (int i=1; i<n; i++) {double t=a(i,i); if(!finite(t) || abs(t) < EPSDET ) {*det=0.; break;} else *det *= t;}
|
||||
for (int i=1; i<n; i++) {double t=a(i,i); if(!finite(t) || std::abs(t) < EPSDET ) {*det=0.; break;} else *det *= t;}
|
||||
//do not use ipiv, since the permutation matrix occurs twice in the decomposition and signs thus cancel (man dspsv)
|
||||
}
|
||||
if (det && r>0) *det = 0;
|
||||
@ -452,6 +457,9 @@ void singular_decomposition(NRMat<double> &a, NRMat<double> *u, NRVec<double> &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<double> &a, NRVec<double> &wr, NRVec<double> &wi,
|
||||
&ldvr, vl?vl[0]:(double *)0, &ldvl, work, &lwork, &r);
|
||||
delete[] work;
|
||||
|
||||
//cout <<"TEST dgeev\n"<<wr<<wi<<*vr<<*vl<<endl;
|
||||
//std::cout <<"TEST dgeev\n"<<wr<<wi<<*vr<<*vl<<std::endl;
|
||||
|
||||
if (r < 0) laerror("illegal argument in ggev/geev in gdiagonalize()");
|
||||
if (r > 0) laerror("convergence problem in ggev/geev in gdiagonalize()");
|
||||
@ -589,9 +597,9 @@ void gdiagonalize(NRMat<double> &a, NRVec<double> &wr, NRVec<double> &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<double> > imagmatrix (const NRMat<double> &a)
|
||||
return result;
|
||||
}
|
||||
|
||||
const NRMat< complex<double> > complexmatrix (const NRMat<double> &re, const NRMat<double> &im)
|
||||
{
|
||||
if(re.nrows()!=im.nrows() || re.ncols() != im.ncols()) laerror("incompatible sizes of real and imaginary parts");
|
||||
NRMat< complex<double> > 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<double> matrixfunction(NRMat<double> a, complex<double>
|
||||
(*f)(const complex<double> &), const bool adjust)
|
||||
@ -735,13 +753,13 @@ NRMat<complex<double> > a0=complexify(a);
|
||||
gdiagonalize(a, w, &u, &v);//a gets destroyed, eigenvectors are rows
|
||||
NRVec< complex<double> > z = diagofproduct(u, v, 1, 1);
|
||||
/*
|
||||
cout <<"TEST matrixfunction\n"<<w<<u<<v<<z;
|
||||
cout <<"TEST matrixfunction1 "<< u*a0 - diagonalmatrix(w)*u<<endl;
|
||||
cout <<"TEST matrixfunction2 "<< a0*v.transpose(1) - v.transpose(1)*diagonalmatrix(w)<<endl;
|
||||
cout <<"TEST matrixfunction3 "<< u*v.transpose(1)<<diagonalmatrix(z)<<endl;
|
||||
std::cout <<"TEST matrixfunction\n"<<w<<u<<v<<z;
|
||||
std::cout <<"TEST matrixfunction1 "<< u*a0 - diagonalmatrix(w)*u<<std::endl;
|
||||
std::cout <<"TEST matrixfunction2 "<< a0*v.transpose(1) - v.transpose(1)*diagonalmatrix(w)<<std::endl;
|
||||
std::cout <<"TEST matrixfunction3 "<< u*v.transpose(1)<<diagonalmatrix(z)<<std::endl;
|
||||
NRVec< complex<double> > wz(n);
|
||||
for (int i=0; i<a.nrows(); i++) wz[i] = w[i]/z[i];
|
||||
cout <<"TEST matrixfunction4 "<< a0<< v.transpose(true)*diagonalmatrix(wz)*u<<endl;
|
||||
std::cout <<"TEST matrixfunction4 "<< a0<< v.transpose(true)*diagonalmatrix(wz)*u<<std::endl;
|
||||
*/
|
||||
|
||||
for (int i=0; i<a.nrows(); i++) w[i] = (*f)(w[i])/z[i];
|
||||
@ -751,7 +769,7 @@ cout <<"TEST matrixfunction4 "<< a0<< v.transpose(true)*diagonalmatrix(wz)*u<<en
|
||||
r.gemm(0.0, v, 'c', u, 'n', 1.0);
|
||||
double inorm = cblas_dnrm2(n*n, (double *)r[0]+1, 2);
|
||||
if (inorm > 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<double> myclog (const complex<double> &x)
|
||||
|
||||
complex<double> mycexp (const complex<double> &x)
|
||||
{
|
||||
return exp(x);
|
||||
return std::exp(x);
|
||||
}
|
||||
|
||||
|
||||
complex<double> sqrtinv (const complex<double> &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<n; ++j)
|
||||
if(i==j)
|
||||
{
|
||||
if(x<=0) laerror("not positive definite metric in gendiagonalize");
|
||||
dl[i] = sqrt(x);
|
||||
dl[i] = std::sqrt(x);
|
||||
}
|
||||
else
|
||||
b(j,i) = x / dl[i];
|
||||
@ -1023,12 +1041,13 @@ if(nchange&1)//still adjust to get determinant=1
|
||||
{
|
||||
int imin=-1; double min=1e200;
|
||||
for(int i=0; i<n;++i)
|
||||
if(abs(v[i][i])<min)
|
||||
if(std::abs(v[i][i])<min)
|
||||
{
|
||||
imin=i;
|
||||
min=abs(v[i][i]);
|
||||
min=std::abs(v[i][i]);
|
||||
}
|
||||
cblas_dscal(n,-1.,v[imin],1);
|
||||
}
|
||||
}
|
||||
|
||||
}//namespace
|
||||
|
21
nonclass.h
21
nonclass.h
@ -17,12 +17,12 @@
|
||||
*/
|
||||
#ifndef _LA_NONCLASS_H_
|
||||
#define _LA_NONCLASS_H_
|
||||
|
||||
#include "vec.h"
|
||||
#include "smat.h"
|
||||
#include "mat.h"
|
||||
#include "la_traits.h"
|
||||
|
||||
namespace LA {
|
||||
|
||||
//MISC
|
||||
template <class T>
|
||||
@ -120,11 +120,11 @@ extern complex<double> sqrtinv(const complex<double> &);
|
||||
extern double sqrtinv(const double);
|
||||
|
||||
//functions on matrices
|
||||
inline NRMat<double> sqrt(const NRSMat<double> &a) { return matrixfunction(a,&sqrt); }
|
||||
inline NRMat<double> sqrt(const NRSMat<double> &a) { return matrixfunction(a,&std::sqrt); }
|
||||
inline NRMat<double> sqrtinv(const NRSMat<double> &a) { return matrixfunction(a,&sqrtinv); }
|
||||
inline NRMat<double> realsqrt(const NRMat<double> &a) { return realmatrixfunction(a,&sqrt); }
|
||||
inline NRMat<double> realsqrt(const NRMat<double> &a) { return realmatrixfunction(a,&std::sqrt); }
|
||||
inline NRMat<double> realsqrtinv(const NRMat<double> &a) { return realmatrixfunction(a,&sqrtinv); }
|
||||
inline NRMat<double> log(const NRSMat<double> &a) { return matrixfunction(a,&log); }
|
||||
inline NRMat<double> log(const NRSMat<double> &a) { return matrixfunction(a,&std::log); }
|
||||
extern NRMat<double> log(const NRMat<double> &a);
|
||||
extern NRMat<double> exp0(const NRMat<double> &a);
|
||||
|
||||
@ -133,6 +133,7 @@ extern const NRMat<double> realpart(const NRMat< complex<double> >&);
|
||||
extern const NRMat<double> imagpart(const NRMat< complex<double> >&);
|
||||
extern const NRMat< complex<double> > realmatrix (const NRMat<double>&);
|
||||
extern const NRMat< complex<double> > imagmatrix (const NRMat<double>&);
|
||||
extern const NRMat< complex<double> > complexmatrix (const NRMat<double>&, const NRMat<double>&);
|
||||
|
||||
//inverse by means of linear solve, preserving rhs intact
|
||||
template<typename T>
|
||||
@ -186,7 +187,7 @@ if(ignoresign)
|
||||
{
|
||||
for(int i=0; i<nrows; ++i)
|
||||
for(int j=0; j<ncols; ++j)
|
||||
r(i,j) = rows[i]*cols[j]<0?0.:a(abs(rows[i])+indexshift,abs(cols[j])+indexshift);
|
||||
r(i,j) = rows[i]*cols[j]<0?0.:a(std::abs(rows[i])+indexshift,std::abs(cols[j])+indexshift);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -201,7 +202,7 @@ if(ignoresign)
|
||||
{
|
||||
for(int i=0; i<nrows; ++i)
|
||||
for(int j=0; j<ncols; ++j)
|
||||
r(i,j) = a(abs(rows[i])+indexshift,abs(cols[j])+indexshift);
|
||||
r(i,j) = a(std::abs(rows[i])+indexshift,std::abs(cols[j])+indexshift);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -218,11 +219,6 @@ return r;
|
||||
//auxiliary routine to adjust eigenvectors to guarantee real logarithm
|
||||
extern void adjustphases(NRMat<double> &v);
|
||||
|
||||
template<class T>
|
||||
T abssqr(const complex<T> &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
|
||||
|
@ -15,6 +15,9 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _PERMUTATION_H
|
||||
#define _PERMUTATION_H
|
||||
namespace LA {
|
||||
template<typename T>
|
||||
const NRVec<T> inversepermutation(const NRVec<T> &p, const T offset=0)
|
||||
{
|
||||
@ -24,3 +27,5 @@ if(!offset) for(int i=0; i<n; ++i) q[p[i]]=i;
|
||||
else for(int i=0; i<n; ++i) q[p[i]-offset]=i+offset;
|
||||
return q;
|
||||
}
|
||||
}//namespace
|
||||
#endif
|
||||
|
3
qsort.h
3
qsort.h
@ -18,6 +18,8 @@
|
||||
#ifndef _QSORT_H
|
||||
#define _QSORT_H
|
||||
//quicksort, returns parity of the permutation
|
||||
//
|
||||
namespace LA {
|
||||
|
||||
template<typename INDEX, typename COMPAR>
|
||||
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
|
||||
|
21
smat.cc
21
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<double> >::dot(const NRSMat< complex<double> > &rhs) const
|
||||
if (nn != rhs.nn) laerror("dot of incompatible SMat's");
|
||||
#endif
|
||||
complex<double> 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<double> >::dot(const NRVec< complex<double> > &rhs) const
|
||||
if (NN2 != rhs.nn) laerror("dot of incompatible SMat's");
|
||||
#endif
|
||||
complex<double> 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<double>::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<double> >::norm(const complex<double> scalar) const
|
||||
{
|
||||
if (!(scalar.real()) && !(scalar.imag()))
|
||||
return cblas_dznrm2(NN2, (void *)v, 1);
|
||||
return cblas_dznrm2(NN2, v, 1);
|
||||
double sum = 0;
|
||||
complex<double> tmp;
|
||||
int k = 0;
|
||||
@ -360,7 +360,7 @@ const double NRSMat< complex<double> >::norm(const complex<double> 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<double> >::axpy(const complex<double> 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<double>;
|
||||
template class NRSMat< complex<double> >;
|
||||
|
||||
template class NRSMat<long long>;
|
||||
template class NRSMat<long>;
|
||||
template class NRSMat<int>;
|
||||
template class NRSMat<short>;
|
||||
template class NRSMat<char>;
|
||||
template class NRSMat<unsigned char>;
|
||||
template class NRSMat<unsigned short>;
|
||||
template class NRSMat<unsigned int>;
|
||||
template class NRSMat<unsigned long>;
|
||||
template class NRSMat<unsigned long long>;
|
||||
|
||||
}//namespace
|
||||
|
20
smat.h
20
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 T>
|
||||
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<T> &rhs); // dense from sparse
|
||||
explicit NRSMat(const SparseSMat<T> &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 <typename T>
|
||||
@ -162,7 +164,7 @@ inline NRSMat< complex<double> > &
|
||||
NRSMat< complex<double> >::operator*=(const complex<double> & a)
|
||||
{
|
||||
copyonwrite();
|
||||
cblas_zscal(NN2, (void *)(&a), (void *)v, 1);
|
||||
cblas_zscal(NN2, &a, v, 1);
|
||||
return *this;
|
||||
}
|
||||
template <typename T>
|
||||
@ -214,7 +216,7 @@ NRSMat< complex<double> >::operator+=(const NRSMat< complex<double> > & 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<double> >::operator-=(const NRSMat< complex<double> > & 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<double>::amax() const
|
||||
template<>
|
||||
inline const complex<double> NRSMat< complex<double> >::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 <typename T>
|
||||
ostream& operator<<(ostream &s, const NRSMat<T> &x)
|
||||
std::ostream& operator<<(std::ostream &s, const NRSMat<T> &x)
|
||||
{
|
||||
int i,j,n;
|
||||
n=x.nrows();
|
||||
@ -568,7 +570,7 @@ ostream& operator<<(ostream &s, const NRSMat<T> &x)
|
||||
|
||||
|
||||
template <typename T>
|
||||
istream& operator>>(istream &s, NRSMat<T> &x)
|
||||
std::istream& operator>>(std::istream &s, NRSMat<T> &x)
|
||||
{
|
||||
int i,j,n,m;
|
||||
s >> n >> m;
|
||||
@ -618,5 +620,5 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}//namespace
|
||||
#endif /* _LA_SMAT_H_ */
|
||||
|
124
sparsemat.cc
124
sparsemat.cc
@ -25,6 +25,8 @@
|
||||
#include <errno.h>
|
||||
#include "sparsemat.h"
|
||||
|
||||
namespace LA {
|
||||
|
||||
template<typename T>
|
||||
static inline const T MAX(const T &a, const T &b)
|
||||
{return b > a ? (b) : (a);}
|
||||
@ -333,11 +335,7 @@ for(i=1; i<n;i++)
|
||||
|
||||
//check if summed to zero
|
||||
for(i=0; i<n;i++) if(rowsorted[i] &&
|
||||
#ifdef SPARSEEPSILON
|
||||
abs(rowsorted[i]->elem)<SPARSEEPSILON
|
||||
#else
|
||||
! rowsorted[i]->elem
|
||||
#endif
|
||||
std::abs(rowsorted[i]->elem)<=SPARSEEPSILON
|
||||
) {delete rowsorted[i]; rowsorted[i]=NULL;}
|
||||
|
||||
//restore connectivity
|
||||
@ -397,11 +395,7 @@ void SparseMat<T>::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)<SPARSEEPSILON) return;
|
||||
#else
|
||||
if(!elem) return;
|
||||
#endif
|
||||
if(std::abs(elem)<=SPARSEEPSILON) return;
|
||||
if(!count) {count=new int; *count=1; list=NULL;} //blank new matrix
|
||||
else copyonwrite(); //makes also unsort
|
||||
add(n,m,elem);
|
||||
@ -452,9 +446,7 @@ register matel<T> *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<T> *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<T> *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;i<nn;++i)
|
||||
for(j=0; j<mm;++j)
|
||||
{register T t(rhs(i,j));
|
||||
#ifdef SPARSEEPSILON
|
||||
if( abs(t)>SPARSEEPSILON)
|
||||
#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 <class T>
|
||||
SparseMat<T> & SparseMat<T>::operator=(const T a)
|
||||
SparseMat<T> & SparseMat<T>::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)<SPARSEEPSILON) return *this;
|
||||
#else
|
||||
if(a==(T)0) return *this;
|
||||
#endif
|
||||
if(std::abs(a)<=SPARSEEPSILON) return *this;
|
||||
SPMatindex i;
|
||||
for(i=0;i<nn;++i) add(i,i,a);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SparseMat<T> & SparseMat<T>::operator+=(const T a)
|
||||
SparseMat<T> & SparseMat<T>::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<nn;++i) add(i,i,a);
|
||||
simplify(); //maybe leave up to the user
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SparseMat<T> & SparseMat<T>::operator-=(const T a)
|
||||
SparseMat<T> & SparseMat<T>::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<nn;++i) add(i,i,-a);
|
||||
simplify(); //maybe leave up to the user
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -715,11 +695,7 @@ for(i=0;i<nn;++i)
|
||||
for(j=0; j<=i;++j)
|
||||
{register T t;
|
||||
if(
|
||||
#ifdef SPARSEEPSILON
|
||||
abs(t=rhs(i,j))>SPARSEEPSILON
|
||||
#else
|
||||
t=rhs(i,j)
|
||||
#endif
|
||||
std::abs(t=rhs(i,j))>SPARSEEPSILON
|
||||
) add(i,j,t);
|
||||
}
|
||||
}
|
||||
@ -751,9 +727,7 @@ matel<T> *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 <class T>
|
||||
SparseMat<T> & SparseMat<T>::operator*=(const T a)
|
||||
SparseMat<T> & SparseMat<T>::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<T> *l=list;
|
||||
while(l)
|
||||
@ -936,15 +910,14 @@ return sum;
|
||||
}
|
||||
|
||||
|
||||
//not OK for complex hermitean
|
||||
template<class T>
|
||||
const T SparseMat<T>::norm(const T scalar) const
|
||||
const typename LA_traits<T>::normtype SparseMat<T>::norm(const T scalar) const
|
||||
{
|
||||
if(!list) return T(0);
|
||||
if(!list) return typename LA_traits<T>::normtype(0);
|
||||
const_cast<SparseMat<T> *>(this)->simplify();
|
||||
|
||||
matel<T> *l=list;
|
||||
T sum(0);
|
||||
typename LA_traits<T>::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<T>::normtype tmp=LA_traits<T>::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<T>::sqrabs(hlp);
|
||||
l=l->next;
|
||||
}
|
||||
}
|
||||
@ -972,7 +945,7 @@ else
|
||||
if(symmetric)
|
||||
while(l)
|
||||
{
|
||||
T tmp=l->elem*l->elem;
|
||||
typename LA_traits<T>::normtype tmp=LA_traits<T>::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<T>::sqrabs(l->elem);
|
||||
l=l->next;
|
||||
}
|
||||
}
|
||||
return sqrt(sum); //not OK for int, would need traits technique
|
||||
return (typename LA_traits<T>::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<T> *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<T>::SparseMat(const NRMat<T> &rhs); \
|
||||
template SparseMat<T>::SparseMat(const NRSMat<T> &rhs); \
|
||||
template void SparseMat<T>::transposeme(); \
|
||||
template const T* SparseMat<T>::diagonalof(NRVec<T> &r, const bool divide, bool cache) const; \
|
||||
template SparseMat<T> & SparseMat<T>::operator*=(const T a); \
|
||||
template SparseMat<T> & SparseMat<T>::operator*=(const T &a); \
|
||||
template void SparseMat<T>::setunsymmetric(); \
|
||||
template SparseMat<T> & SparseMat<T>::operator=(const T a); \
|
||||
template SparseMat<T> & SparseMat<T>::operator+=(const T a); \
|
||||
template SparseMat<T> & SparseMat<T>::operator-=(const T a); \
|
||||
template SparseMat<T> & SparseMat<T>::operator=(const T &a); \
|
||||
template SparseMat<T> & SparseMat<T>::operator+=(const T &a); \
|
||||
template SparseMat<T> & SparseMat<T>::operator-=(const T &a); \
|
||||
template NRMat<T>::NRMat(const SparseMat<T> &rhs); \
|
||||
template NRSMat<T>::NRSMat(const SparseMat<T> &rhs); \
|
||||
template NRVec<T>::NRVec(const SparseMat<T> &rhs); \
|
||||
template const NRVec<T> NRVec<T>::operator*(const SparseMat<T> &mat) const; \
|
||||
template SparseMat<T> & SparseMat<T>::join(SparseMat<T> &rhs); \
|
||||
template const T SparseMat<T>::trace() const; \
|
||||
template const T SparseMat<T>::norm(const T scalar) const; \
|
||||
template const LA_traits<T>::normtype SparseMat<T>::norm(const T scalar) const; \
|
||||
template void SparseMat<T>::axpy(const T alpha, const SparseMat<T> &x, const bool transp); \
|
||||
template const SparseMat<T> SparseMat<T>::operator*(const SparseMat<T> &rhs) const; \
|
||||
template const T SparseMat<T>::dot(const SparseMat<T> &rhs) const; \
|
||||
@ -1336,3 +1295,4 @@ INSTANTIZE(complex<double>) //some functions are not OK for hermitean matrices,
|
||||
template class SparseMat<double>;
|
||||
template class SparseMat<complex<double> >;
|
||||
|
||||
}//namespace
|
||||
|
23
sparsemat.h
23
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<T> &rhs); //construct from a dense one
|
||||
explicit SparseMat(const NRSMat<T> &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<T>::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<T> *ltmp= new matel<T>; 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 <typename T>
|
||||
inline const NRVec<T> SparseMat<T>::operator*(const NRVec<T> &rhs) const
|
||||
{NRVec<T> result(nn); result.gemv((T)0,*this,'n',(T)1,rhs); return result;};
|
||||
@ -155,7 +159,7 @@ inline const NRMat<T> SparseMat<T>::operator*(const NRMat<T> &rhs) const
|
||||
{NRMat<T> result(nn,rhs.ncols()); result.gemm((T)0,*this,'n',rhs,'n',(T)1); return result;};
|
||||
|
||||
template <class T>
|
||||
ostream& operator<<(ostream &s, const SparseMat<T> &x)
|
||||
std::ostream& operator<<(std::ostream &s, const SparseMat<T> &x)
|
||||
{
|
||||
SPMatindex n,m;
|
||||
n=x.nrows();
|
||||
@ -172,7 +176,7 @@ ostream& operator<<(ostream &s, const SparseMat<T> &x)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
istream& operator>>(istream &s, SparseMat<T> &x)
|
||||
std::istream& operator>>(std::istream &s, SparseMat<T> &x)
|
||||
{
|
||||
int i,j;
|
||||
int n,m;
|
||||
@ -298,4 +302,5 @@ while(l)
|
||||
return *this;
|
||||
}
|
||||
|
||||
}//namespace
|
||||
#endif
|
||||
|
@ -25,10 +25,11 @@
|
||||
#include <errno.h>
|
||||
#include "sparsesmat.h"
|
||||
|
||||
namespace LA {
|
||||
|
||||
template <typename T>
|
||||
void SparseSMat<T>::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<nn; ++k) //summation loop
|
||||
add(ai[i],bi[j],prod(i,j),false);
|
||||
|
||||
}
|
||||
std::cerr << "before simplify in gemm\n";
|
||||
std::cerr << " nterms = "<<
|
||||
simplify()
|
||||
<<std::endl; //erase elements below threshold
|
||||
std::cerr << "regular exit gemm\n";
|
||||
simplify();
|
||||
}
|
||||
|
||||
|
||||
@ -183,7 +180,7 @@ for(SPMatindex i=0; i<nn; ++i)
|
||||
}
|
||||
else sum += LA_traits<T>::sqrabs(scalar); //missing diagonal element
|
||||
|
||||
return sqrt(sum);
|
||||
return std::sqrt(sum);
|
||||
}
|
||||
|
||||
|
||||
@ -208,4 +205,4 @@ INSTANTIZE(complex<double>)
|
||||
template class SparseSMat<double>;
|
||||
template class SparseSMat<complex<double> >;
|
||||
|
||||
|
||||
}//namespace
|
||||
|
@ -19,7 +19,6 @@
|
||||
#ifndef _SPARSESMAT_H_
|
||||
#define _SPARSESMAT_H_
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <stdlib.h>
|
||||
@ -36,6 +35,7 @@
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
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<T> &x)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}//namespace
|
||||
#endif //_SPARSESMAT_H_
|
||||
|
@ -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
|
||||
|
66
t.cc
66
t.cc
@ -20,18 +20,9 @@
|
||||
|
||||
#include <time.h>
|
||||
#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<double> &x);
|
||||
|
||||
@ -1335,7 +1326,7 @@ cout << "Unitary\n"<<U;
|
||||
cout <<"Error = "<<(U*U.transpose() -1.).norm()<<endl;
|
||||
}
|
||||
|
||||
if(1)
|
||||
if(0)
|
||||
{
|
||||
double t;
|
||||
NRMat<complex<double> > ham;
|
||||
@ -1397,7 +1388,58 @@ cout <<"sparse sincostimes "<<clock()/((double) (CLOCKS_PER_SEC))-t <<"\n";
|
||||
NRVec<complex<double> > r4 = cov2 + siv2*complex<double>(0,1);
|
||||
cout <<"sincostimes error 2 = "<<(r1-r4).norm()<<endl;
|
||||
*/
|
||||
}
|
||||
|
||||
if(0)
|
||||
{
|
||||
double t;
|
||||
SparseMat<complex<double> > h;
|
||||
cin >> h;
|
||||
h *= complex<double>(0,1);
|
||||
h.simplify();
|
||||
cout <<"length of hamiltonian "<<h.length()<<endl;
|
||||
t=clock()/((double) (CLOCKS_PER_SEC));
|
||||
SparseMat<complex<double> > hexp = exp(h);
|
||||
cout <<"sparse exp time "<<clock()/((double) (CLOCKS_PER_SEC))-t <<"\n";
|
||||
cout <<"length of exp hamiltonian "<<hexp.length()<<endl;
|
||||
NRMat<complex<double> > he(hexp);
|
||||
NRMat<complex<double> > hec(he);
|
||||
NRMat<complex<double> > het(he);
|
||||
hec.conjugateme();
|
||||
het.transposeme();
|
||||
//cout <<he;
|
||||
cout <<"unitarity error "<<(hec*he).norm(1)<<endl;
|
||||
cout <<"symmetry error "<<(het-he).norm()<<endl;
|
||||
}
|
||||
|
||||
if(0)
|
||||
{
|
||||
NRSMat<double> hd(100);
|
||||
hd.randomize(1);
|
||||
SparseSMat<double> h(hd);
|
||||
NRMat<double> rd = hd*hd;
|
||||
SparseSMat<double> r = h*h;
|
||||
NRSMat<double>rx(r);
|
||||
NRMat<double> r2(rx);
|
||||
cout <<"Error = "<<(r2-rd).norm()<<endl;
|
||||
}
|
||||
|
||||
if(1)
|
||||
{
|
||||
SparseSMat<complex<double> > h;
|
||||
cin>>h;
|
||||
h *= complex<double>(0,1);
|
||||
double t=clock()/((double) (CLOCKS_PER_SEC));
|
||||
SparseSMat<complex<double> > r = exp(h);
|
||||
cout <<"SparseSMat time "<<clock()/((double) (CLOCKS_PER_SEC))-t <<"\n";
|
||||
if(h.nrows()<=1024)
|
||||
{
|
||||
NRSMat<complex<double> > h3(h);
|
||||
NRMat<complex<double> > h2(h3);
|
||||
NRMat<complex<double> >r2 = exp(h2);
|
||||
cout <<"error = "<<(r2-NRMat<complex<double> >(NRSMat<complex<double> >(r))).norm()<<endl;
|
||||
cout <<"errorx = "<<(r2-NRSMat<complex<double> >(r)).norm()<<endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
6
t2.cc
6
t2.cc
@ -28,13 +28,15 @@
|
||||
#include "traceback.h"
|
||||
#endif
|
||||
|
||||
using namespace LA;
|
||||
|
||||
void test(const NRVec<double> &x)
|
||||
{
|
||||
NRMat<double> aa(0.,2,2);
|
||||
NRMat<double> cc(aa);
|
||||
cc.copyonwrite(); cc[0][0]=1.;
|
||||
|
||||
cout << aa << cc <<"\n";
|
||||
cout <<"test x= "<<x<<"\n";
|
||||
std::cout << aa << cc <<"\n";
|
||||
std::cout <<"test x= "<<x<<"\n";
|
||||
}
|
||||
|
||||
|
2
test.cc
2
test.cc
@ -25,6 +25,8 @@
|
||||
#include "traceback.h"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
void test2(char *msg)
|
||||
{
|
||||
laerror(msg);
|
||||
|
76
vec.cc
76
vec.cc
@ -18,19 +18,22 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "vec.h"
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#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<T>::get(int fd, bool dim, bool transp); \
|
||||
|
||||
INSTANTIZE(double)
|
||||
INSTANTIZE(complex<double>)
|
||||
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<double> >::axpy(const complex<double> 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<double> >::axpy(const complex<double> alpha,
|
||||
const complex<double> *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<double> >::operator-() const
|
||||
{
|
||||
NRVec< complex<double> > 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<double> > & NRVec< complex<double> >::normalize()
|
||||
{
|
||||
complex<double> 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<unsigned char> & NRVec<unsigned char>::normalize() {laerror("normalize() impossible for integer types"); return *this;}
|
||||
template<>
|
||||
NRVec<int> & NRVec<int>::normalize() {laerror("normalize() impossible for integer types"); return *this;}
|
||||
template<>
|
||||
NRVec<short> & NRVec<short>::normalize() {laerror("normalize() impossible for integer types"); return *this;}
|
||||
template<>
|
||||
NRVec<char> & NRVec<char>::normalize() {laerror("normalize() impossible for integer types"); return *this;}
|
||||
template<>
|
||||
NRVec<unsigned long> & NRVec<unsigned long>::normalize() {laerror("normalize() impossible for integer types"); return *this;}
|
||||
template<>
|
||||
NRVec<unsigned int> & NRVec<unsigned int>::normalize() {laerror("normalize() impossible for integer types"); return *this;}
|
||||
|
||||
|
||||
#define INSTANTIZE_DUMMY(T) \
|
||||
template<> void NRVec<T>::gemv(const T beta, const NRMat<T> &a, const char trans, const T alpha, const NRVec<T> &x) { laerror("gemv on unsupported types"); } \
|
||||
template<> void NRVec<T>::gemv(const T beta, const NRSMat<T> &a, const char trans, const T alpha, const NRVec<T> &x) { laerror("gemv on unsupported types"); } \
|
||||
template<> void NRVec<T>::gemv(const T beta, const SparseMat<T> &a, const char trans, const T alpha, const NRVec<T> &x, bool s) { laerror("gemv on unsupported types"); } \
|
||||
template<> void NRVec<T>::gemv(const LA_traits_complex<T>::Component_type beta, const LA_traits_complex<T>::NRMat_Noncomplex_type &a, const char trans, const LA_traits_complex<T>::Component_type alpha, const NRVec<T> &x) { laerror("gemv on unsupported types"); } \
|
||||
template<> void NRVec<T>::gemv(const LA_traits_complex<T>::Component_type beta, const LA_traits_complex<T>::NRSMat_Noncomplex_type &a, const char trans, const LA_traits_complex<T>::Component_type alpha, const NRVec<T> &x) { laerror("gemv on unsupported types"); }
|
||||
template<> void NRVec<T>::gemv(const LA_traits_complex<T>::Component_type beta, const LA_traits_complex<T>::NRSMat_Noncomplex_type &a, const char trans, const LA_traits_complex<T>::Component_type alpha, const NRVec<T> &x) { laerror("gemv on unsupported types"); } \
|
||||
template<> NRVec<T> & NRVec<T>::normalize() {laerror("normalize() impossible for integer types"); return *this;} \
|
||||
template<> const NRMat<T> NRVec<T>::otimes(const NRVec<T> &b,const bool conj, const T &scale) const {laerror("otimes presently implemented only for double and complex double"); return NRMat<T> ();}
|
||||
|
||||
|
||||
|
||||
@ -401,20 +396,22 @@ void NRVec< complex<double> >::gemv(const complex<double> beta,
|
||||
|
||||
|
||||
|
||||
// Direc product Mat = Vec | Vec
|
||||
// Direct product Mat = Vec | Vec
|
||||
template<>
|
||||
const NRMat<double> NRVec<double>::operator|(const NRVec<double> &b) const
|
||||
const NRMat<double> NRVec<double>::otimes(const NRVec<double> &b,const bool conj, const double &scale) const
|
||||
{
|
||||
NRMat<double> 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<double> >
|
||||
NRVec< complex<double> >::operator|(const NRVec< complex<double> > &b) const
|
||||
NRVec<complex<double> >::otimes(const NRVec< complex<double> > &b, const bool conj, const complex<double> &scale) const
|
||||
{
|
||||
NRMat< complex<double> > 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<T>,int,int>(*this,perm,from,to);
|
||||
template class NRVec<double>;
|
||||
template class NRVec<complex<double> >;
|
||||
template class NRVec<char>;
|
||||
template class NRVec<unsigned char>;
|
||||
template class NRVec<short>;
|
||||
template class NRVec<int>;
|
||||
template class NRVec<long>;
|
||||
template class NRVec<long long>;
|
||||
template class NRVec<unsigned char>;
|
||||
template class NRVec<unsigned short>;
|
||||
template class NRVec<unsigned int>;
|
||||
template class NRVec<unsigned long>;
|
||||
template class NRVec<unsigned long long>;
|
||||
|
||||
|
||||
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<char>)
|
||||
INSTANTIZE_DUMMY(complex<unsigned char>)
|
||||
INSTANTIZE_DUMMY(complex<short>)
|
||||
INSTANTIZE_DUMMY(complex<int>)
|
||||
INSTANTIZE_DUMMY(complex<long>)
|
||||
INSTANTIZE_DUMMY(complex<long long>)
|
||||
INSTANTIZE_DUMMY(complex<unsigned char>)
|
||||
INSTANTIZE_DUMMY(complex<unsigned short>)
|
||||
INSTANTIZE_DUMMY(complex<unsigned int>)
|
||||
INSTANTIZE_DUMMY(complex<unsigned long>)
|
||||
INSTANTIZE_DUMMY(complex<unsigned long long>)
|
||||
|
||||
INSTANTIZE_DUMMY(complex<complex<double> >)
|
||||
INSTANTIZE_DUMMY(complex<complex<float> >)
|
||||
INSTANTIZE_DUMMY(complex<unsigned long>)
|
||||
|
||||
}//namespace
|
||||
|
33
vec.h
33
vec.h
@ -21,6 +21,8 @@
|
||||
|
||||
#include "la_traits.h"
|
||||
|
||||
namespace LA {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declarations
|
||||
template <typename T> void lawritemat(FILE *file,const T *a,int r,int c,
|
||||
@ -104,7 +106,8 @@ public:
|
||||
const NRVec operator*(const NRMat<T> &mat) const {NRVec<T> result(mat.ncols()); result.gemv((T)0,mat,'t',(T)1,*this); return result;};
|
||||
const NRVec operator*(const NRSMat<T> &mat) const {NRVec<T> result(mat.ncols()); result.gemv((T)0,mat,'t',(T)1,*this); return result;};
|
||||
const NRVec operator*(const SparseMat<T> &mat) const {NRVec<T> result(mat.ncols()); result.gemv((T)0,mat,'t',(T)1,*this); return result;};
|
||||
const NRMat<T> operator|(const NRVec<T> &rhs) const;
|
||||
const NRMat<T> otimes(const NRVec<T> &rhs, const bool conjugate=false, const T &scale=1) const; //outer product
|
||||
inline const NRMat<T> operator|(const NRVec<T> &rhs) const {return otimes(rhs,true);};
|
||||
inline const T sum() const {T sum=0; for(int i=0; i<nn; i++) sum += v[i]; return sum;}; //sum of its elements
|
||||
inline const T asum() const; //sum of its elements absolute values
|
||||
inline const T dot(const T *a, const int stride=1) const; // ddot with a stride-vector
|
||||
@ -136,26 +139,28 @@ public:
|
||||
int sort(int direction=0, int from=0, int to= -1, int *perm=NULL); //sort, ascending by default, returns parity of permutation
|
||||
};
|
||||
|
||||
}//namespace
|
||||
|
||||
//due to mutual includes this has to be after full class declaration
|
||||
#include "mat.h"
|
||||
#include "smat.h"
|
||||
#include "sparsemat.h"
|
||||
|
||||
namespace LA {
|
||||
// formatted I/O
|
||||
template <typename T>
|
||||
ostream & operator<<(ostream &s, const NRVec<T> &x)
|
||||
std::ostream & operator<<(std::ostream &s, const NRVec<T> &x)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
n = x.size();
|
||||
s << n << endl;
|
||||
s << n << std::endl;
|
||||
for(i=0; i<n; i++) s << (typename LA_traits_io<T>::IOtype)x[i] << (i == n-1 ? '\n' : ' ');
|
||||
return s;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
istream & operator>>(istream &s, NRVec<T> &x)
|
||||
std::istream & operator>>(std::istream &s, NRVec<T> &x)
|
||||
{
|
||||
int i,n;
|
||||
|
||||
@ -238,7 +243,7 @@ inline NRVec< complex<double> > &
|
||||
NRVec< complex<double> >::operator+=(const complex<double> &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<double> > &
|
||||
NRVec< complex<double> >::operator-=(const complex<double> &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<double> >::operator+=(const NRVec< complex<double> > &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<double> >::operator-=(const NRVec< complex<double> > &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<double> > &
|
||||
NRVec< complex<double> >::operator*=(const complex<double> &a)
|
||||
{
|
||||
copyonwrite();
|
||||
cblas_zscal(nn, (void *)(&a), (void *)v, 1);
|
||||
cblas_zscal(nn, &a, v, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -432,7 +437,7 @@ NRVec< complex<double> >::operator*(const NRVec< complex<double> > &rhs) const
|
||||
if (nn != rhs.nn) laerror("dot of incompatible vectors");
|
||||
#endif
|
||||
complex<double> 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<double>
|
||||
NRVec< complex<double> >::dot(const complex<double> *y, const int stride) const
|
||||
{
|
||||
complex<double> 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<double>::norm() const
|
||||
template<>
|
||||
inline const double NRVec< complex<double> >::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<double>::amax() const
|
||||
template<>
|
||||
inline const complex<double> NRVec< complex<double> >::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<rhs.size(); ++i) r[i]=rhs[i];
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
}//namespace
|
||||
|
||||
#endif /* _LA_VEC_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user