#include "smat.h" // TODO // specialize unary minus ////////////////////////////////////////////////////////////////////////////// ////// forced instantization in the corresponding object file template NRSMat; template NRSMat< complex >; /* * * Templates first, specializations for BLAS next * */ // conversion ctor, symmetrize general Mat into SMat template NRSMat::NRSMat(const NRMat &rhs) { #ifdef DEBUG if (nn != rhs.ncols()) laerror("attempt to convert non-square Mat to SMat"); #endif count = new int; *count = 1; v = new T[NN2]; int i, j, k=0; for (i=0; i NRSMat::~NRSMat() { if (!count) return; if (--(*count) <= 0) { if (v) delete[] (v); delete count; } } // assignment with a physical copy template NRSMat & NRSMat::operator|=(const NRSMat &rhs) { if (this != &rhs) { if(!rhs.v) laerror("unallocated rhs in NRSMat operator |="); if(count) if(*count > 1) { // detach from the other --(*count); nn = 0; count = 0; v = 0; } if (nn != rhs.nn) { if(v) delete [] (v); nn = rhs.nn; } if (!v) v = new T[NN2]; if (!count) count = new int; *count = 1; memcpy(v, rhs.v, NN2*sizeof(T)); } return *this; } // assignment template NRSMat & NRSMat::operator=(const NRSMat & rhs) { if (this == & rhs) return *this; if (count) if(--(*count) == 0) { delete [] v; delete count; } v = rhs.v; nn = rhs.nn; count = rhs.count; if (count) (*count)++; return *this; } // assing to diagonal template NRSMat & NRSMat::operator=(const T &a) { copyonwrite(); for (int i=0; i const NRSMat NRSMat::operator-() const { NRSMat result(nn); for(int i=0; i const T NRSMat::trace() const { T tmp = 0; for (int i=0; i void NRSMat::copyonwrite() { #ifdef DEBUG if (!count) laerror("probably an assignment to undefined Smat"); #endif if (*count > 1) { (*count)--; count = new int; *count = 1; T *newv = new T[NN2]; memcpy(newv, v, NN2*sizeof(T)); v = newv; } } // resize Smat template void NRSMat::resize(const int n) { #ifdef DEBUG if (n <= 0) laerror("illegal matrix dimension in resize of Smat"); #endif if (count) if(*count > 1) { //detach from previous (*count)--; count = 0; v = 0; nn = 0; } if (!count) { //new uninitialized vector or just detached count = new int; *count = 1; nn = n; v = new T[NN2]; return; } if (n != nn) { nn = n; delete[] v; v = new T[NN2]; } } // write matrix to the file with specific format template void NRSMat::fprintf(FILE *file, const char *format, const int modulo) const { lawritemat(file, (const T *)(*this) ,nn, nn, format, 2, modulo, 1); } // read matrix from the file with specific format template void NRSMat::fscanf(FILE *f, const char *format) { int n, m; if (std::fscanf(f,"%d %d",&n,&m) != 2) laerror("cannot read matrix dimensions in SMat::fscanf"); if (n != m) laerror("different dimensions of SMat"); resize(n); for (int i=0; i */ // SMat * Mat const NRMat NRSMat::operator*(const NRMat &rhs) const { #ifdef DEBUG if (nn != rhs.nrows()) laerror("incompatible dimensions in SMat*Mat"); #endif NRMat result(nn, rhs.ncols()); for (int k=0; k > NRSMat< complex >::operator*(const NRMat< complex > &rhs) const { #ifdef DEBUG if (nn != rhs.nrows()) laerror("incompatible dimensions in SMat*Mat"); #endif NRMat< complex > result(nn, rhs.ncols()); for (int k=0; k NRSMat::operator*(const NRSMat &rhs) const { #ifdef DEBUG if (nn != rhs.nn) laerror("incompatible dimensions in SMat*SMat"); #endif NRMat result(0.0, nn, nn); double *p, *q; p = v; for (int i=0; i > NRSMat< complex >::operator*(const NRSMat< complex > &rhs) const { #ifdef DEBUG if (nn != rhs.nn) laerror("incompatible dimensions in SMat*SMat"); #endif NRMat< complex > result(0.0, nn, nn); NRMat< complex > rhsmat(rhs); result = *this * rhsmat; return result; // laerror("complex SMat*Smat not implemented"); } // S dot S const double NRSMat::dot(const NRSMat &rhs) const { #ifdef DEBUG if (nn != rhs.nn) laerror("dot of incompatible SMat's"); #endif return cblas_ddot(NN2, v, 1, rhs.v, 1); } const complex NRSMat< complex >::dot(const NRSMat< complex > &rhs) const { #ifdef DEBUG if (nn != rhs.nn) laerror("dot of incompatible SMat's"); #endif complex dot; cblas_zdotc_sub(nn, (void *)v, 1, (void *)rhs.v, 1, (void *)(&dot)); return dot; } // x = S * x const NRVec NRSMat::operator*(const NRVec &rhs) const { #ifdef DEBUG if (nn!=rhs.size()) laerror("incompatible dimension in Smat*Vec"); #endif NRVec result(nn); cblas_dspmv(CblasRowMajor, CblasLower, nn, 1.0, v, rhs, 1, 0.0, result, 1); return result; } const NRVec< complex > NRSMat< complex >::operator*(const NRVec< complex > &rhs) const { #ifdef DEBUG if (nn!=rhs.size()) laerror("incompatible dimension in Smat*Vec"); #endif NRVec< complex > result(nn); cblas_zhpmv(CblasRowMajor, CblasLower, nn, (void *)(&CONE), (void *)v, (const void *)rhs, 1, (void *)(&CZERO), (void *)result, 1); return result; } // norm of the matrix const double NRSMat::norm(const double scalar) const { if (!scalar) return cblas_dnrm2(NN2, v, 1); double sum = 0; int k = 0; for (int i=0; i >::norm(const complex scalar) const { if (!(scalar.real()) && !(scalar.imag())) return cblas_dznrm2(NN2, (void *)v, 1); double sum = 0; complex tmp; int k = 0; for (int i=0; i::axpy(const double alpha, const NRSMat & x) { #ifdef DEBUG if (nn != x.nn) laerror("axpy of incompatible SMats"); #endif copyonwrite(); cblas_daxpy(NN2, alpha, x.v, 1, v, 1); } void NRSMat< complex >::axpy(const complex alpha, const NRSMat< complex > & x) { #ifdef DEBUG if (nn != x.nn) laerror("axpy of incompatible SMats"); #endif copyonwrite(); cblas_zaxpy(nn, (void *)(&alpha), (void *)x.v, 1, (void *)v, 1); } export template ostream& operator<<(ostream &s, const NRSMat &x) { int i,j,n; n=x.nrows(); s << n << ' ' << n << '\n'; for(i=0;i istream& operator>>(istream &s, NRSMat &x) { int i,j,n,m; s >> n >> m; if(n!=m) laerror("input symmetric matrix not square"); x.resize(n); for(i=0;i>x(i,j); return s; } ////////////////////////////////////////////////////////////////////////////// //// forced instantization in the corespoding object file #define INSTANTIZE(T) \ template ostream & operator<<(ostream &s, const NRSMat< T > &x); \ template istream & operator>>(istream &s, NRSMat< T > &x); \ INSTANTIZE(double) INSTANTIZE(complex)