diff --git a/sparsesmat.h b/sparsesmat.h new file mode 100644 index 0000000..4c24028 --- /dev/null +++ b/sparsesmat.h @@ -0,0 +1,192 @@ +/* + LA: linear algebra C++ interface library + Copyright (C) 2008 Jiri Pittner or + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _SPARSESMAT_H_ +#define _SPARSESMAT_H_ + + +#include +#include +#include +#include +#include +#include +#include +#include "sparsemat.h" +#include "vec.h" +#include "mat.h" + +#include +#include + + +//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 +//indices are counted from zero + + +template +class SparseSMat +{ +protected: + SPMatindex nn; + std::map **v; + int *count; +public: + SparseSMat() : nn(0), v(NULL), count(NULL) {}; + SparseSMat(const SPMatindex n); + SparseSMat(const SparseSMat &rhs); + SparseSMat(const SparseMat &rhs); + SparseSMat & operator=(const SparseSMat &rhs); + void copyonwrite(); + void clear(); + void simplify(); + ~SparseSMat() {clear();}; + // + SparseSMat & operator=(const T a); //assign a to diagonal + SparseSMat & operator+=(const T a); //assign a to diagonal + SparseSMat & operator-=(const T a); //assign a to diagonal + SparseSMat & operator*=(const T a); //multiply by a scalar + SparseSMat & operator+=(const SparseSMat &rhs); + SparseSMat & operator-=(const SparseSMat &rhs); + void gemv(const T beta, NRVec &r, const char trans, const T alpha, const NRVec &x) const; + void gemm(const T beta, const SparseSMat &a, const char transa, const SparseSMat &b, const char transb, const T alpha); + const SparseSMat operator*(const SparseSMat &rhs) const; + const typename LA_traits::normtype norm(const T scalar=(T)0) const; + void add(const SPMatindex n, const SPMatindex m, const T elem); + unsigned int length() const; +}; + +template +SparseSMat::SparseSMat(const SPMatindex n) +:nn(n), +count(new int(1)) +{ +v= new std::map * [n]; +memset(v,0,nn*sizeof(std::map *)); +} + +template +SparseSMat::SparseSMat(const SparseSMat &rhs) +{ +v = rhs.v; +nn = rhs.nn; +count = rhs.count; +if(count) (*count)++; +} + + +template +void SparseSMat::clear() +{ + if(!count) return; + if(--(*count) <= 0) { + if(v) + { + for(SPMatindex i=0; i +SparseSMat & SparseSMat::operator=(const SparseSMat &rhs) +{ + if (this != &rhs) + { + if(count) + if(--(*count) == 0) + { + if(v) + { + for(SPMatindex i=0; i +void SparseSMat::copyonwrite() +{ + if(!count) laerror("SparseSmat::copyonwrite() of an undefined object"); + if(*count > 1) + { + (*count)--; + count = new int; + *count = 1; + std::map *newv= new std::map * [nn]; + for(SPMatindex i=0; i(*(v[i])); //deep copy of each map + else + newv[i]=NULL; + v = newv; + } +} + + +template +void SparseSMat::add(const SPMatindex n, const SPMatindex m, const T elem) +{ +#ifdef DEBUG +if(n>=nn || m>=nn) laerror("illegal index in SparseSMat::add()"); +#endif +if(!v[n]) v[n] = new std::map; +if(!v[m]) v[m] = new std::map; + +typename std::map::iterator p; + +p= v[n]->find(m); +if(p!=v[n]->end()) p->second+=elem; else (*v[n])[m] = elem; +if(n!=m) + { + p= v[m]->find(n); + if(p!=v[m]->end()) p->second+=elem; else (*v[m])[n] = elem; + } +//addition can lead to zero, but do not treat it now, make a simplify +} + + +template +void SparseSMat::simplify() +{ +for(SPMatindex i=0; i l; + typename std::map::iterator p; + for(p=v[i]->begin(); p!=v[i]->end(); ++p) + if(std::abs(p->second) < SPARSEEPSILON) l.push_front(p->first); + typename std::list::iterator q; + for(q=l.begin(); q!=l.end(); ++q) v[i]->erase(*q); + if(v[i]->size() == 0) delete v[i]; + } +} + + +#endif //_SPARSESMAT_H_