*** empty log message ***

This commit is contained in:
jiri 2010-01-11 10:12:28 +00:00
parent 12c88e6872
commit 8ec7c11a6e
6 changed files with 92 additions and 42 deletions

View File

@ -219,8 +219,9 @@ static void copy(complex<C> *dest, complex<C> *src, unsigned int n) {memcpy(dest
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;};
static inline complex<C> conjugate(complex<C> &x) {return complex<C>(x.real(),-x.imag());};
static inline C realpart(complex<C> &x) {return x.real();}
static inline complex<C> conjugate(const complex<C> &x) {return complex<C>(x.real(),-x.imag());};
static inline C realpart(const complex<C> &x) {return x.real();}
static inline C imagpart(const complex<C> &x) {return x.imag();}
};
//non-complex scalars
@ -243,8 +244,9 @@ 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;};
static inline C conjugate(C&x) {return x;};
static inline C realpart(C &x) {return x;}
static inline C conjugate(const C &x) {return x;};
static inline C realpart(const C &x) {return x;}
static inline C imagpart(const C &x) {return 0;}
};

2
mat.h
View File

@ -128,7 +128,7 @@ public:
const T trace() const;
//members concerning sparse matrix
SparseSMat<T> & operator*(const SparseSMat<T> &rhs) const;
SparseSMat<T> operator*(const SparseSMat<T> &rhs) const;
explicit NRMat(const SparseMat<T> &rhs); // dense from sparse
explicit NRMat(const SparseSMat<T> &rhs); // dense from sparse
NRMat & operator+=(const SparseMat<T> &rhs);

View File

@ -30,11 +30,11 @@ namespace LA {
//dense times sparse (not necessarily symmetric)
template <typename T>
SparseSMat<T> & NRMat<T>::operator*(const SparseSMat<T> &rhs) const
SparseSMat<T> NRMat<T>::operator*(const SparseSMat<T> &rhs) const
{
SparseSMat<T> r(nn,rhs.ncols());
if(mm!=rhs.nrows()) laerror("incompatible sizes in NRMat*SparseSMat");
for(SPMatindex k=0; k<nn; ++k) //summation loop
for(SPMatindex k=0; k<mm; ++k) //summation loop
{
std::map<SPMatindex,T> * kl = rhs.line(k);
if(kl)
@ -71,6 +71,7 @@ void SparseSMat<T>::gemm(const T beta, const SparseSMat &a, const char transa, c
{
(*this) *= beta;
if(alpha==(T)0) return;
if(a.nn!=a.mm || b.nn!=b.mm || nn!=mm) laerror("SparseSMat::gemm implemented only for square symmetric matrices");
if(a.nn!=b.nn || a.nn!=nn) laerror("incompatible sizes in SparseSMat::gemm");
copyonwrite();
@ -89,13 +90,10 @@ for(SPMatindex k=0; k<nn; ++k) //summation loop
for(p=a.v[k]->begin(), i=0; p!=a.v[k]->end(); ++p,++i) { ai[i] = p->first; av[i] = LA_traits<T>::conjugate(p->second); }
else
for(p=a.v[k]->begin(), i=0; p!=a.v[k]->end(); ++p,++i) { ai[i] = p->first; av[i] = p->second; }
if(tolower(transb)=='c')
for(p=b.v[k]->begin(), i=0; p!=b.v[k]->end(); ++p,++i) { bi[i] = p->first; bv[i] = LA_traits<T>::conjugate(p->second); }
else
for(p=b.v[k]->begin(), i=0; p!=b.v[k]->end(); ++p,++i) { bi[i] = p->first; bv[i] = p->second; }
for(p=b.v[k]->begin(), i=0; p!=b.v[k]->end(); ++p,++i) { bi[i] = p->first; bv[i] = p->second; }
//make multiply via blas
NRMat<T> prod=av.otimes(bv,false,alpha);
NRMat<T> prod=av.otimes(bv,tolower(transb)=='c',alpha);
//scatter the results -- probably the computational bottleneck
for(i=0; i<prod.nrows(); ++i) for(j=0; j<prod.ncols(); ++j)
@ -127,7 +125,7 @@ return *this;
template <class T>
void SparseSMat<T>::axpy(const T alpha, const SparseSMat &x, const bool transp)
{
if(nn!=x.nn) laerror("incompatible matrix dimensions in SparseSMat::axpy");
if(nn!=x.nn || mm!=x.mm) laerror("incompatible matrix dimensions in SparseSMat::axpy");
if(alpha==(T)0) return;
copyonwrite();
for(SPMatindex i=0; i<nn; ++i) if(x.v[i])
@ -148,7 +146,8 @@ simplify();
template <class T>
void SparseSMat<T>::gemv(const T beta, NRVec<T> &r, const char trans, const T alpha, const NRVec<T> &x) const
{
if(nn!=r.size() || nn!= x.size()) laerror("incompatible matrix vector dimensions in SparseSMat::gemv");
if(nn!=r.size() || mm!= x.size()) laerror("incompatible matrix vector dimensions in SparseSMat::gemv");
if(trans) laerror("transposition not implemented yet in SparseSMat::gemv");
r *= beta;
if(alpha == (T)0) return;
r.copyonwrite();
@ -236,6 +235,7 @@ return std::sqrt(sum);
template <class T>
const T* SparseSMat<T>::diagonalof(NRVec<T> &r, const bool divide, bool cache) const
{
if(nn!=mm) laerror("non-square matrix in SparseSMat::diagonalof");
if(nn!=r.size()) laerror("incompatible vector size in diagonalof()");
NRVec<T> *rr;
@ -266,8 +266,7 @@ void SparseSMat<T>::get(int fd, bool dimen, bool transp) {
if(dimen) {
if(2*sizeof(SPMatindex)!=read(fd,&dim,2*sizeof(SPMatindex))) laerror("read() error in SparseSMat::get ");
if(dim[0]!=dim[1]) laerror("SparseSMat must be square (nonsquare read in ::get)");
resize(dim[0]);
resize(dim[0],dim[1]);
}
else copyonwrite();
@ -288,7 +287,7 @@ void SparseSMat<T>::put(int fd, bool dimen, bool transp) const {
errno=0;
if(dimen) {
if(sizeof(SPMatindex)!=write(fd,&nn,sizeof(SPMatindex))) laerror("cannot write() 1 in SparseSMat::put");
if(sizeof(SPMatindex)!=write(fd,&nn,sizeof(SPMatindex))) laerror("cannot write() 2 in SparseSMat::put");
if(sizeof(SPMatindex)!=write(fd,&mm,sizeof(SPMatindex))) laerror("cannot write() 2 in SparseSMat::put");
}
typename SparseSMat<T>::iterator p(*this);

View File

@ -50,20 +50,25 @@ class SparseSMat
{
protected:
SPMatindex nn;
SPMatindex mm;
std::map<SPMatindex,T> **v;
int *count;
public:
SparseSMat() : nn(0), v(NULL), count(NULL) {};
explicit SparseSMat(const SPMatindex n); //prevent double -> int -> SparseSMat
SparseSMat() : nn(0), mm(0), v(NULL), count(NULL) {};
explicit SparseSMat(const SPMatindex n, const SPMatindex m); //prevent double -> int -> SparseSMat
explicit SparseSMat(const SPMatindex n);
SparseSMat(const SparseSMat &rhs);
explicit SparseSMat(const SparseMat<T> &rhs);
explicit SparseSMat(const NRSMat<T> &rhs);
explicit SparseSMat(const NRMat<T> &rhs);
SparseSMat & operator=(const SparseSMat &rhs);
void copyonwrite();
void resize(const SPMatindex n);
std::map<SPMatindex,T> *line(SPMatindex n) const {return v[n];};
void clear() {resize(nn);}
void resize(const SPMatindex nn, const SPMatindex mm);
inline void setcoldim(int i) {mm=(SPMatindex)i;};
//std::map<SPMatindex,T> *line(SPMatindex n) const {return v[n];};
typedef std::map<SPMatindex,T> *ROWTYPE;
inline typename SparseSMat<T>::ROWTYPE & operator[](const SPMatindex i) {return v[i];};
void clear() {resize(nn,mm);}
unsigned long long simplify();
~SparseSMat();
inline int getcount() const {return count?*count:0;}
@ -83,7 +88,7 @@ public:
void gemv(const T beta, NRVec<T> &r, const char trans, const T alpha, const NRVec<T> &x) const;
inline const NRVec<T> operator*(const NRVec<T> &rhs) const {NRVec<T> result(nn); this->gemv((T)0,result,'n',(T)1,rhs); return result;};
typename LA_traits<T>::normtype norm(const T scalar=(T)0) const;
inline const SparseSMat operator*(const SparseSMat &rhs) const {SparseSMat<T> r(nn); r.gemm(0,*this,'n',rhs,'n',1); return r;}; //!!!NOT A GENERAL ROUTINE, JUST FOR THE CASES WHEN THE RESULT STAYS SYMMETRIC
inline const SparseSMat operator*(const SparseSMat &rhs) const {SparseSMat<T> r(nn,mm); r.gemm(0,*this,'n',rhs,'n',1); return r;}; //!!!NOT A GENERAL ROUTINE, JUST FOR THE CASES WHEN THE RESULT STAYS SYMMETRIC
void gemm(const T beta, const SparseSMat &a, const char transa, const SparseSMat &b, const char transb, const T alpha); //this := alpha*op( A )*op( B ) + beta*this !!!NOT A GENERAL ROUTINE, JUST FOR THE CASES WHEN THE RESULT STAYS SYMMETRIC
inline void add(const SPMatindex n, const SPMatindex m, const T elem, const bool both=true);
inline unsigned long long length() {return simplify();};
@ -92,7 +97,7 @@ public:
void get(int fd, bool dimen, bool transp);
void put(int fd, bool dimen, bool transp) const;
int nrows() const {return nn;}
int ncols() const {return nn;}
int ncols() const {return mm;}
SparseSMat<T> cholesky(void) const;
class iterator {//not efficient, just for output to ostreams
@ -103,14 +108,15 @@ public:
typename std::map<SPMatindex,T>::iterator *col;
typename std::map<SPMatindex,T>::iterator mycol;
SPMatindex mynn;
SPMatindex mymm;
std::map<SPMatindex,T> **myv;
public:
//compiler-generated iterator & operator=(const iterator &rhs);
//compiler-generated iterator(const iterator &rhs);
iterator(): p(NULL),row(0),col(NULL),mynn(0),myv(NULL) {};
iterator(const SparseSMat &rhs) : mynn(rhs.nn), myv(rhs.v), col(NULL) {row=0; p= &my; operator++();}
iterator(): p(NULL),row(0),col(NULL),mynn(0),mymm(0),myv(NULL) {};
iterator(const SparseSMat &rhs) : mynn(rhs.nn), mymm(rhs.mm), myv(rhs.v), col(NULL) {row=0; p= &my; operator++();}
iterator operator++() {
if(col) //finish column list
{
@ -156,10 +162,19 @@ public:
iterator end() const {return iterator(NULL);}
};
template <typename T>
SparseSMat<T>::SparseSMat(const SPMatindex n)
:nn(n),
:nn(n), mm(n),
count(new int(1))
{
v= new std::map<SPMatindex,T> * [n];
memset(v,0,nn*sizeof(std::map<SPMatindex,T> *));
}
template <typename T>
SparseSMat<T>::SparseSMat(const SPMatindex n, const SPMatindex m)
:nn(n), mm(m),
count(new int(1))
{
v= new std::map<SPMatindex,T> * [n];
@ -168,7 +183,7 @@ memset(v,0,nn*sizeof(std::map<SPMatindex,T> *));
template <typename T>
SparseSMat<T>::SparseSMat(const NRSMat<T> &rhs)
:nn(rhs.nrows()),
:nn(rhs.nrows()), mm(rhs.ncols()),
count(new int(1))
{
v= new std::map<SPMatindex,T> * [nn];
@ -179,14 +194,14 @@ for(i=0; i<nn; ++i) for(j=0; j<=i; ++j) if(std::abs(rhs(i,j))>SPARSEEPSILON) (*t
template <typename T>
SparseSMat<T>::SparseSMat(const NRMat<T> &rhs)
:nn(rhs.nrows()),
:nn(rhs.nrows()), mm(rhs.ncols()),
count(new int(1))
{
if(rhs.nrows()!=rhs.ncols()) laerror("non-square matrix in SparseSMat constructor from NRMat");
v= new std::map<SPMatindex,T> * [nn];
memset(v,0,nn*sizeof(std::map<SPMatindex,T> *));
int i,j;
for(i=0; i<nn; ++i) for(j=0; j<nn; ++j) if(std::abs(rhs(i,j))>SPARSEEPSILON) (*this).add(i,j,rhs(i,j),false);
for(i=0; i<nn; ++i) for(j=0; j<mm; ++j) if(std::abs(rhs(i,j))>SPARSEEPSILON) (*this).add(i,j,rhs(i,j),false);
}
@ -195,6 +210,7 @@ SparseSMat<T>::SparseSMat(const SparseSMat &rhs)
{
v = rhs.v;
nn = rhs.nn;
mm = rhs.mm;
count = rhs.count;
if(count) (*count)++;
}
@ -205,6 +221,7 @@ template <typename T>
NRSMat<T>::NRSMat(const SparseSMat<T> &rhs)
: nn(rhs.nrows())
{
if(rhs.nrows()!=rhs.ncols()) laerror("cannot transform rectangular matrix to NRSMat");
count = new int(1);
v=new T[nn2];
memset(v,0,nn2*sizeof(T));
@ -251,13 +268,14 @@ SparseSMat<T>::~SparseSMat()
template <typename T>
void SparseSMat<T>::resize(const SPMatindex n)
void SparseSMat<T>::resize(const SPMatindex n, const SPMatindex m)
{
if(!count)
{
if(n==0) return;
count = new int(1);
nn=n;
mm=m;
v= new std::map<SPMatindex,T> * [nn];
for(SPMatindex i=0; i<nn; ++i) v[i]=NULL;
return;
@ -270,13 +288,15 @@ if(*count > 1) //it was shared
{
count = new int(1);
nn=n;
mm=m;
v= new std::map<SPMatindex,T> * [nn];
for(SPMatindex i=0; i<nn; ++i) v[i]=NULL;
}
else {v=NULL; nn=0; count=NULL;}
else {v=NULL; nn=0; mm=0; count=NULL;}
}
else //it was not shared
{
mm=m;
//delete all trees
for(SPMatindex i=0; i<nn; ++i) if(v[i]) {delete v[i]; v[i]=NULL;}
if(n!=nn)
@ -305,6 +325,7 @@ SparseSMat<T> & SparseSMat<T>::operator=(const SparseSMat &rhs)
}
v = rhs.v;
nn = rhs.nn;
mm = rhs.mm;
count = rhs.count;
if(count) (*count)++;
}
@ -335,7 +356,7 @@ template <typename T>
void SparseSMat<T>::add(const SPMatindex n, const SPMatindex m, const T elem, const bool both)
{
#ifdef DEBUG
if(n>=nn || m>=nn) laerror("illegal index in SparseSMat::add()");
if(n>=nn || m>=mm) laerror("illegal index in SparseSMat::add()");
#endif
if(!v[n]) v[n] = new std::map<SPMatindex,T>;
@ -377,8 +398,7 @@ std::ostream & operator<<(std::ostream &s, const SparseSMat<T> &x)
{
SPMatindex n;
n = x.nrows();
s << n << " "<< n<< std::endl;
s << x.nrows() << " "<< x.ncols()<< std::endl;
typename SparseSMat<T>::iterator p(x);
for(; p.notend(); ++p) s << (int)p->row << ' ' << (int)p->col << ' ' << (typename LA_traits_io<T>::IOtype) p->elem << '\n';
@ -393,28 +413,31 @@ std::istream& operator>>(std::istream &s, SparseSMat<T> &x)
long i,j;
s >> n >> m;
if(n!=m) laerror("SparseSMat must be square");
x.resize(n);
x.resize(n,m);
s >> i >> j;
typename LA_traits_io<T>::IOtype tmp;
while(i>=0 && j>=0)
{
s>>tmp;
if(i>=n||j>=m) laerror("bad index in SparseSMat::operator>>");
x.add(i,j,tmp,false);
s >> i >> j;
}
return s;
}
template <typename T>
SparseSMat<T> SparseSMat<T>::transpose(bool conj) const
{
SparseSMat<T> r(nn);
SparseSMat<T> r(mm,nn);
typename SparseSMat<T>::iterator p(*this);
for(; p.notend(); ++p) r.add(p->col, p->row, (conj?LA_traits<T>::conjugate(p->elem):p->elem), false);
return r;
}
//Cholesky decomposition, pivoted, positive semidefinite, not in place
//it is NOT checked that the input matrix is symmetric/hermitean
//result.transpose(true)*result reproduces the original matrix
@ -423,7 +446,7 @@ return r;
template <typename T>
SparseSMat<T> SparseSMat<T>::cholesky(void) const
{
if(nn!=mm) laerror("Cholesky defined only for square matrices");
//we need real values for sorting, if T is already real it makes just an unnecessary copy of one vector
NRVec<typename LA_traits<T>::normtype> diagreal(nn);
{
@ -451,6 +474,7 @@ for(int i=0; i<nn; ++i) invpivot[pivot[i]]=i;
//copy-permute upper triangle
SparseSMat<T> r;
r.nn=nn;
r.mm=nn;
r.count = new int(1);
r.v = new std::map<SPMatindex,T> * [nn];
for(SPMatindex i=0; i<nn; ++i)
@ -545,5 +569,27 @@ return r;
}
//outer product expected to be sparse
template<typename T>
SparseSMat<T> otimes_sparse(const NRVec<T> &lhs, const NRVec<T> &rhs, const bool conjugate=false, const T &scale=1)
{
SparseSMat<T> r(lhs.size(),rhs.size());
for(SPMatindex i=0; i<lhs.size(); ++i)
if(lhs[i])
{
for(SPMatindex j=0; j<rhs.size(); ++j)
if(rhs[j])
{
T x=lhs[i]*(conjugate?LA_traits<T>::conjugate(rhs[j]):rhs[j])*scale;
if(std::abs(x)>SPARSEEPSILON) r.add(i,j,x);
}
}
return r;
}
}//namespace
#endif //_SPARSESMAT_H_

6
t.cc
View File

@ -1555,17 +1555,17 @@ if(1)
{
int n;
cin >>n;
SparseSMat<double> bh(n);
SparseSMat<double> bh(n,n);
for(int i=0; i<=n/400; ++i) for(int j=i; j<n; ++j) {if((double)random()/RAND_MAX>0.995 || i==j)
{bh.add(i,j,(double)random()/RAND_MAX*(i==j?10.:(random()>RAND_MAX/2?1:-1)),false);}}
if(n<1000) cout <<"Random matrix\n"<<bh;
SparseSMat<double> bb(n);
SparseSMat<double> bb(n,n);
bb.gemm(0.,bh,'c',bh,'n',1.);
if(n<1000) cout <<"Input matrix\n"<<bb;
cout <<"Original filling = "<<bb.simplify()<<endl;
SparseSMat<double> b = bb.cholesky();
if(n<1000) cout <<"Cholesky result\n"<<b;
SparseSMat<double> br(n);
SparseSMat<double> br(n,n);
br.gemm(0.,b,'c',b,'n',1.);
if(n<1000) cout <<"Result of reconstruction\n"<<br;
if(n<1000) cout <<"Difference\n"<<br-bb;

3
vec.h
View File

@ -113,6 +113,8 @@ public:
inline const T dot(const T *a, const int stride=1) const; // ddot with a stride-vector
inline T & operator[](const int i);
inline const T & operator[](const int i) const;
typedef T ROWTYPE;
inline void setcoldim(int i) {}; //dummy
inline int size() const;
inline operator T*(); //get a pointer to the data
inline operator const T*() const; //get a pointer to the data
@ -145,6 +147,7 @@ public:
#include "mat.h"
#include "smat.h"
#include "sparsemat.h"
#include "sparsesmat.h"
namespace LA {
// formatted I/O