/* 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_