/* 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 . */ #include #include #include #include #include #include #include #include "sparsesmat.h" namespace LA { template void SparseSMat::gemm(const T beta, const SparseSMat &a, const char transa, const SparseSMat &b, const char transb, const T alpha) { (*this) *= beta; if(alpha==(T)0) return; if(a.nn!=b.nn || a.nn!=nn) laerror("incompatible sizes in SparseSMat::gemm"); copyonwrite(); for(SPMatindex k=0; k av(a.v[k]->size()); NRVec bv(b.v[k]->size()); NRVec ai(a.v[k]->size()); NRVec bi(b.v[k]->size()); //gather the data typename std::map::iterator p; int i,j; for(p=a.v[k]->begin(), i=0; p!=a.v[k]->end(); ++p,++i) { ai[i] = p->first; av[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 prod=av.otimes(bv,false,alpha); //scatter the results -- probably the computational bottleneck for(i=0; i SparseSMat & SparseSMat::operator*=(const T &a) { if(!count) laerror("operator*= on undefined lhs"); if(a==(T)1) return *this; if(a==(T)0) {clear(); return *this;} copyonwrite(); for(SPMatindex i=0; i::iterator p; for(p=v[i]->begin(); p!=v[i]->end(); ++p) p->second *= a; } return *this; } template void SparseSMat::axpy(const T alpha, const SparseSMat &x, const bool transp) { if(nn!=x.nn) laerror("incompatible matrix dimensions in SparseSMat::axpy"); if(alpha==(T)0) return; copyonwrite(); for(SPMatindex i=0; i; typename std::map::iterator p; for(p=x.v[i]->begin(); p!=x.v[i]->end(); ++p) (*v[i])[p->first] = p->second * alpha; } simplify(); } template void SparseSMat::gemv(const T beta, NRVec &r, const char trans, const T alpha, const NRVec &x) const { if(nn!=r.size() || nn!= x.size()) laerror("incompatible matrix vector dimensions in SparseSMat::gemv"); r *= beta; if(alpha == (T)0) return; r.copyonwrite(); for(SPMatindex i=0; i::iterator p; for(p=v[i]->begin(); p!=v[i]->end(); ++p) r[i] += x[p->first] * p->second * alpha ; } } template SparseSMat & SparseSMat::operator=(const T &a) { clear(); for(SPMatindex i=0; i; (*v[i])[i] = a; } return *this; } template SparseSMat & SparseSMat::operator+=(const T &a) { copyonwrite(); for(SPMatindex i=0; i::iterator p; p= v[i]->find(i); if(p!=v[i]->end()) p->second+=a; else (*v[i])[i] = a; } else {v[i] = new std::map; (*v[i])[i] = a;} } return *this; } template SparseSMat & SparseSMat::operator-=(const T &a) { copyonwrite(); for(SPMatindex i=0; i::iterator p; p= v[i]->find(i); if(p!=v[i]->end()) p->second-=a; else (*v[i])[i] = -a; } else {v[i] = new std::map; (*v[i])[i] = -a;} } return *this; } template typename LA_traits::normtype SparseSMat::norm(const T scalar) const { typename LA_traits::normtype sum=0; for(SPMatindex i=0; i::iterator p; p= v[i]->find(i); if(p!=v[i]->end()) sum += LA_traits::sqrabs(p->second - scalar); else sum += LA_traits::sqrabs(scalar); } else sum += LA_traits::sqrabs(scalar); //missing diagonal element return std::sqrt(sum); } #define INSTANTIZE(T) \ template void SparseSMat::gemm(const T beta, const SparseSMat &a, const char transa, const SparseSMat &b, const char transb, const T alpha); \ template SparseSMat & SparseSMat::operator*=(const T &a); \ template void SparseSMat::gemv(const T beta, NRVec &r, const char trans, const T alpha, const NRVec &x) const; \ template void SparseSMat::axpy(const T alpha, const SparseSMat &x, const bool transp); \ template SparseSMat & SparseSMat::operator=(const T &a); \ template SparseSMat & SparseSMat::operator+=(const T &a); \ template SparseSMat & SparseSMat::operator-=(const T &a); \ template LA_traits::normtype SparseSMat::norm(const T scalar) const; \ INSTANTIZE(double) INSTANTIZE(complex) //// forced instantization of functions in the header in the corresponding object file template class SparseSMat; template class SparseSMat >; }//namespace