*** empty log message ***
This commit is contained in:
parent
84560cd6c7
commit
344a4f4764
192
sparsesmat.h
Normal file
192
sparsesmat.h
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
LA: linear algebra C++ interface library
|
||||
Copyright (C) 2008 Jiri Pittner <jiri.pittner@jh-inst.cas.cz> or <jiri@pittnerovi.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SPARSESMAT_H_
|
||||
#define _SPARSESMAT_H_
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "sparsemat.h"
|
||||
#include "vec.h"
|
||||
#include "mat.h"
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
|
||||
//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 <typename T>
|
||||
class SparseSMat
|
||||
{
|
||||
protected:
|
||||
SPMatindex nn;
|
||||
std::map<SPMatindex,T> **v;
|
||||
int *count;
|
||||
public:
|
||||
SparseSMat() : nn(0), v(NULL), count(NULL) {};
|
||||
SparseSMat(const SPMatindex n);
|
||||
SparseSMat(const SparseSMat &rhs);
|
||||
SparseSMat(const SparseMat<T> &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<T> &r, const char trans, const T alpha, const NRVec<T> &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<T>::normtype norm(const T scalar=(T)0) const;
|
||||
void add(const SPMatindex n, const SPMatindex m, const T elem);
|
||||
unsigned int length() const;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
SparseSMat<T>::SparseSMat(const SPMatindex n)
|
||||
:nn(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 SparseSMat &rhs)
|
||||
{
|
||||
v = rhs.v;
|
||||
nn = rhs.nn;
|
||||
count = rhs.count;
|
||||
if(count) (*count)++;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void SparseSMat<T>::clear()
|
||||
{
|
||||
if(!count) return;
|
||||
if(--(*count) <= 0) {
|
||||
if(v)
|
||||
{
|
||||
for(SPMatindex i=0; i<nn; ++i) if(v[i]) delete[] v[i];
|
||||
delete[] (v);
|
||||
}
|
||||
delete count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
SparseSMat<T> & SparseSMat<T>::operator=(const SparseSMat &rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
if(count)
|
||||
if(--(*count) == 0)
|
||||
{
|
||||
if(v)
|
||||
{
|
||||
for(SPMatindex i=0; i<nn; ++i) if(v[i]) delete[] v[i];
|
||||
delete[] (v);
|
||||
}
|
||||
delete count;
|
||||
}
|
||||
v = rhs.v;
|
||||
nn = rhs.nn;
|
||||
count = rhs.count;
|
||||
if(count) (*count)++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SparseSMat<T>::copyonwrite()
|
||||
{
|
||||
if(!count) laerror("SparseSmat::copyonwrite() of an undefined object");
|
||||
if(*count > 1)
|
||||
{
|
||||
(*count)--;
|
||||
count = new int;
|
||||
*count = 1;
|
||||
std::map<SPMatindex,T> *newv= new std::map<SPMatindex,T> * [nn];
|
||||
for(SPMatindex i=0; i<nn; ++i) if(v[i])
|
||||
newv[i]= new std::map<SPMatindex,T>(*(v[i])); //deep copy of each map
|
||||
else
|
||||
newv[i]=NULL;
|
||||
v = newv;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void SparseSMat<T>::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<SPMatindex,T>;
|
||||
if(!v[m]) v[m] = new std::map<SPMatindex,T>;
|
||||
|
||||
typename std::map<SPMatindex,T>::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 <typename T>
|
||||
void SparseSMat<T>::simplify()
|
||||
{
|
||||
for(SPMatindex i=0; i<nn; ++i) if(v[i])
|
||||
{
|
||||
//check for zero elements and erase them from the list
|
||||
//build a list since we are not sure whether erase from within the traversal loop is safe
|
||||
std::list<SPMatindex> l;
|
||||
typename std::map<SPMatindex,T>::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<SPMatindex>::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_
|
Loading…
Reference in New Issue
Block a user