#include "smat.h" #include #include #include #include extern "C" { extern ssize_t read(int, void *, size_t); extern ssize_t write(int, const void *, size_t); } // TODO // specialize unary minus ////////////////////////////////////////////////////////////////////////////// ////// forced instantization in the corresponding object file template NRSMat; template NRSMat< complex >; template NRSMat; template NRSMat; /* * * Templates first, specializations for BLAS next * */ //raw I/O template void NRSMat::put(int fd, bool dim) const { errno=0; if(dim) { if(sizeof(int) != write(fd,&nn,sizeof(int))) laerror("cannot write"); if(sizeof(int) != write(fd,&nn,sizeof(int))) laerror("cannot write"); } LA_traits::multiput(NN2,fd,v,dim); } template void NRSMat::get(int fd, bool dim) { int nn0[2]; //align at least 8-byte errno=0; if(dim) { if(2*sizeof(int) != read(fd,&nn0,2*sizeof(int))) laerror("cannot read"); resize(nn0[0]); } else copyonwrite(); LA_traits::multiget(NN2,fd,v,dim); } // 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::operator=(const T &a) { copyonwrite(); for (int i=0; i void NRSMat::diagonalof(NRVec &r, const bool divide) const { #ifdef DEBUG if(r.size()!=nn) laerror("incompatible vector in diagonalof()"); #endif r.copyonwrite(); if (divide) 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::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; } //not implemented yet const NRVec NRSMat::operator*(NRVec const&rhs) const { laerror("NRSMat::operator*(NRVec const&) not implemented yet"); return rhs; } const NRVec NRSMat::operator*(NRVec const&rhs) const { laerror("NRSMat::operator*(NRVec const&) not implemented yet"); return rhs; } ////////////////////////////////////////////////////////////////////////////// //// 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) INSTANTIZE(int) INSTANTIZE(char)