/* LA: linear algebra C++ interface library Copyright (C) 2008 Jiri Pittner or complex versions written by Roman Curik 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 "vec.h" #include #include #include #include #include #include "qsort.h" extern "C" { extern ssize_t read(int, void *, size_t); extern ssize_t write(int, const void *, size_t); } ////////////////////////////////////////////////////////////////////////////// //// forced instantization in the corespoding object file #define INSTANTIZE(T) \ template void NRVec::put(int fd, bool dim, bool transp) const; \ template void NRVec::get(int fd, bool dim, bool transp); \ INSTANTIZE(double) INSTANTIZE(complex) INSTANTIZE(int) INSTANTIZE(short) INSTANTIZE(unsigned short) INSTANTIZE(char) INSTANTIZE(unsigned char) INSTANTIZE(unsigned int) INSTANTIZE(unsigned long) /* * Templates first, specializations for BLAS next */ // conversion ctor #ifndef MATPTR template NRVec::NRVec(const NRMat &rhs) { nn = rhs.nn*rhs.mm; v = rhs.v; count = rhs.count; (*count)++; } #endif //raw I/O template void NRVec::put(int fd, bool dim, bool transp) const { errno=0; int pad=1; //align at least 8-byte if(dim) { if(sizeof(int) != write(fd,&nn,sizeof(int))) laerror("cannot write"); if(sizeof(int) != write(fd,&pad,sizeof(int))) laerror("cannot write"); } LA_traits::multiput(nn,fd,v,dim); } template void NRVec::get(int fd, bool dim, bool transp) { 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(nn,fd,v,dim); } // formatted print for NRVec template void NRVec::fprintf(FILE *file, const char *format, const int modulo) const { lawritemat(file, v, 1, nn, format, 1, modulo, 0); } // formatted scan for NRVec template void NRVec::fscanf(FILE *f, const char *format) { int n; if(std::fscanf(f, "%d", &n) != 1) laerror("cannot read vector dimension"); resize(n); for (int i=0; i const NRVec NRVec::operator-() const { NRVec result(nn); for (int i=0; i const bool NRVec::operator>(const NRVec &rhs) const { int n=nn; if(rhs.nn::bigger(v[i],rhs.v[i])) return true; if(LA_traits::smaller(v[i],rhs.v[i])) return false; } return nn>rhs.nn; } template const bool NRVec::operator<(const NRVec &rhs) const { int n=nn; if(rhs.nn::smaller(v[i],rhs.v[i])) return true; if(LA_traits::bigger(v[i],rhs.v[i])) return false; } return nn void NRVec::axpy(const double alpha, const NRVec &x) { #ifdef DEBUG if (nn != x.nn) laerror("axpy of incompatible vectors"); #endif copyonwrite(); cblas_daxpy(nn, alpha, x.v, 1, v, 1); } // axpy call for T = complex (not strided) template<> void NRVec< complex >::axpy(const complex alpha, const NRVec< complex > &x) { #ifdef DEBUG if (nn != x.nn) laerror("axpy of incompatible vectors"); #endif copyonwrite(); cblas_zaxpy(nn, (void *)(&alpha), (void *)(x.v), 1, (void *)v, 1); } // axpy call for T = double (strided) template<> void NRVec::axpy(const double alpha, const double *x, const int stride) { copyonwrite(); cblas_daxpy(nn, alpha, x, stride, v, 1); } // axpy call for T = complex (strided) template<> void NRVec< complex >::axpy(const complex alpha, const complex *x, const int stride) { copyonwrite(); cblas_zaxpy(nn, (void *)(&alpha), (void *)x, stride, v, 1); } // unary minus template<> const NRVec NRVec::operator-() const { NRVec result(*this); result.copyonwrite(); cblas_dscal(nn, -1.0, result.v, 1); return result; } template<> const NRVec< complex > NRVec< complex >::operator-() const { NRVec< complex > result(*this); result.copyonwrite(); cblas_zdscal(nn, -1.0, (void *)(result.v), 1); return result; } // assignment of scalar to every element template NRVec & NRVec::operator=(const T &a) { copyonwrite(); if(a != (T)0) for (int i=0; i template<> NRVec & NRVec::normalize() { double tmp; tmp = cblas_dnrm2(nn, v, 1); #ifdef DEBUG if(!tmp) laerror("normalization of zero vector"); #endif copyonwrite(); tmp = 1.0/tmp; cblas_dscal(nn, tmp, v, 1); return *this; } // Normalization of NRVec< complex > template<> NRVec< complex > & NRVec< complex >::normalize() { complex tmp; tmp = cblas_dznrm2(nn, (void *)v, 1); #ifdef DEBUG if(!(tmp.real()) && !(tmp.imag())) laerror("normalization of zero vector"); #endif copyonwrite(); tmp = 1.0/tmp; cblas_zscal(nn, (void *)(&tmp), (void *)v, 1); return *this; } //stubs for linkage template<> NRVec & NRVec::normalize() {laerror("normalize() impossible for integer types"); return *this;} template<> NRVec & NRVec::normalize() {laerror("normalize() impossible for integer types"); return *this;} template<> NRVec & NRVec::normalize() {laerror("normalize() impossible for integer types"); return *this;} template<> NRVec & NRVec::normalize() {laerror("normalize() impossible for integer types"); return *this;} template<> NRVec & NRVec::normalize() {laerror("normalize() impossible for integer types"); return *this;} template<> NRVec & NRVec::normalize() {laerror("normalize() impossible for integer types"); return *this;} template<> void NRVec::gemv(const int beta, const NRSMat &A, const char trans, const int alpha, const NRVec &x) { laerror("not yet implemented"); } template<> void NRVec::gemv(const short beta, const NRSMat &A, const char trans, const short alpha, const NRVec &x) { laerror("not yet implemented"); } template<> void NRVec::gemv(const unsigned long beta, const NRSMat &A, const char trans, const unsigned long alpha, const NRVec &x) { laerror("not yet implemented"); } template<> void NRVec::gemv(const unsigned int beta, const NRSMat &A, const char trans, const unsigned int alpha, const NRVec &x) { laerror("not yet implemented"); } template<> void NRVec::gemv(const unsigned char beta, const NRSMat &A, const char trans, const unsigned char alpha, const NRVec &x) { laerror("not yet implemented"); } template<> void NRVec::gemv(const char beta, const NRSMat &A, const char trans, const char alpha, const NRVec &x) { laerror("not yet implemented"); } template<> void NRVec::gemv(const int beta, const NRMat &A, const char trans, const int alpha, const NRVec &x) { laerror("not yet implemented"); } template<> void NRVec::gemv(const short beta, const NRMat &A, const char trans, const short alpha, const NRVec &x) { laerror("not yet implemented"); } template<> void NRVec::gemv(const unsigned long beta, const NRMat &A, const char trans, const unsigned long alpha, const NRVec &x) { laerror("not yet implemented"); } template<> void NRVec::gemv(const unsigned int beta, const NRMat &A, const char trans, const unsigned int alpha, const NRVec &x) { laerror("not yet implemented"); } template<> void NRVec::gemv(const unsigned char beta, const NRMat &A, const char trans, const unsigned char alpha, const NRVec &x) { laerror("not yet implemented"); } template<> void NRVec::gemv(const char beta, const NRMat &A, const char trans, const char alpha, const NRVec &x) { laerror("not yet implemented"); } template<> void NRVec::gemv(const int beta, const SparseMat &A, const char trans, const int alpha, const NRVec &x, bool s) { laerror("not yet implemented"); } template<> void NRVec::gemv(const short beta, const SparseMat &A, const char trans, const short alpha, const NRVec &x, bool s) { laerror("not yet implemented"); } template<> void NRVec::gemv(const char beta, const SparseMat &A, const char trans, const char alpha, const NRVec &x, bool s) { laerror("not yet implemented"); } template<> void NRVec::gemv(const unsigned long beta, const SparseMat &A, const char trans, const unsigned long alpha, const NRVec &x, bool s) { laerror("not yet implemented"); } template<> void NRVec::gemv(const unsigned int beta, const SparseMat &A, const char trans, const unsigned int alpha, const NRVec &x, bool s) { laerror("not yet implemented"); } template<> void NRVec::gemv(const unsigned char beta, const SparseMat &A, const char trans, const unsigned char alpha, const NRVec &x, bool s) { laerror("not yet implemented"); } // gemv calls template<> void NRVec::gemv(const double beta, const NRMat &A, const char trans, const double alpha, const NRVec &x) { #ifdef DEBUG if ((trans == 'n'?A.ncols():A.nrows()) != x.size()) laerror("incompatible sizes in gemv A*x"); #endif copyonwrite(); cblas_dgemv(CblasRowMajor, (trans=='n' ? CblasNoTrans:CblasTrans), A.nrows(), A.ncols(), alpha, A, A.ncols(), x.v, 1, beta, v, 1); } template<> void NRVec< complex >::gemv(const complex beta, const NRMat< complex > &A, const char trans, const complex alpha, const NRVec &x) { #ifdef DEBUG if ((trans == 'n'?A.ncols():A.nrows()) != x.size()) laerror("incompatible sizes in gemv A*x"); #endif copyonwrite(); cblas_zgemv(CblasRowMajor, (trans=='n' ? CblasNoTrans:CblasTrans), A.nrows(), A.ncols(), &alpha, A, A.ncols(), x.v, 1, &beta, v, 1); } template<> void NRVec::gemv(const double beta, const NRSMat &A, const char trans, const double alpha, const NRVec &x) { #ifdef DEBUG if (A.ncols()!=x.size()) laerror("incompatible dimension in gemv A*x"); #endif copyonwrite(); cblas_dspmv(CblasRowMajor, CblasLower, A.ncols(), alpha, A, x.v, 1, beta, v, 1); } template<> void NRVec< complex >::gemv(const complex beta, const NRSMat< complex > &A, const char trans, const complex alpha, const NRVec &x) { #ifdef DEBUG if (A.ncols()!=x.size()) laerror("incompatible dimension in gemv"); #endif copyonwrite(); cblas_zhpmv(CblasRowMajor, CblasLower, A.ncols(), &alpha, A, x.v, 1, &beta, v, 1); } // Direc product Mat = Vec | Vec template<> const NRMat NRVec::operator|(const NRVec &b) const { NRMat result(0.,nn,b.nn); cblas_dger(CblasRowMajor, nn, b.nn, 1., v, 1, b.v, 1, result, b.nn); return result; } template<> const NRMat< complex > NRVec< complex >::operator|(const NRVec< complex > &b) const { NRMat< complex > result(0.,nn,b.nn); cblas_zgerc(CblasRowMajor, nn, b.nn, &CONE, v, 1, b.v, 1, result, b.nn); return result; } template int NRVec::sort(int direction, int from, int to, int *perm) { copyonwrite(); if(to == -1) to=nn-1; if(direction) return memqsort<1,NRVec,int,int>(*this,perm,from,to); else return memqsort<0,NRVec,int,int>(*this,perm,from,to); } ////////////////////////////////////////////////////////////////////////////// //// forced instantization in the corespoding object file template class NRVec; template class NRVec >; template class NRVec; template class NRVec; template class NRVec; template class NRVec; template class NRVec; template class NRVec;