From 5266767a4c71ece7245a6fc80b2c47e45d5c81d2 Mon Sep 17 00:00:00 2001 From: Jiri Pittner Date: Thu, 5 Nov 2026 15:42:29 +0100 Subject: [PATCH] float support for smat --- smat.cc | 451 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- smat.h | 231 ++++++++++++++++++++++++++--- 2 files changed, 657 insertions(+), 25 deletions(-) diff --git a/smat.cc b/smat.cc index a948a50..af17b97 100644 --- a/smat.cc +++ b/smat.cc @@ -167,7 +167,7 @@ const T* NRSMat::diagonalof(NRVec &r, const bool divide, bool cache) const if(divide){ for(register int i=0; i NRSMat::operator-() const { return result; } +template <> +const NRSMat NRSMat::operator-() const { + NRSMat result(nn, getlocation()); +#ifdef CUDALA + if(location == cpu){ +#endif + memcpy(result.v, v, NN2*sizeof(float)); + cblas_sscal(NN2, -1., result.v, 1); +#ifdef CUDALA + }else{ + cublasScopy(NN2, v, 1, result.v, 1); + TEST_CUBLAS("cublasScopy"); + + cublasSscal(NN2, -1., result.v, 1); + TEST_CUBLAS("cublasSscal"); + } +#endif + return result; +} + /***************************************************************************//** * implements unary minus operator for this hermitian matrix * @return modified copy of this matrix @@ -240,6 +260,27 @@ const NRSMat > NRSMat >::operator-() c return result; } +template <> +const NRSMat > NRSMat >::operator-() const { + NRSMat > result(nn, getlocation()); +#ifdef CUDALA + if(location == cpu) { +#endif + memcpy(result.v, v, NN2*sizeof(std::complex)); + cblas_cscal(NN2, &CMONEF, result.v, 1); + +#ifdef CUDALA + }else{ + cublasCcopy(NN2, (cuComplex*)v, 1, (cuComplex*)result.v, 1); + TEST_CUBLAS("cublasCcopy"); + + cublasCscal(NN2, CUMONE, (cuComplex*)result.v, 1); + TEST_CUBLAS("cublasCscal"); + } +#endif + return result; +} + /***************************************************************************//** * @return the sum of the diagonal elements ******************************************************************************/ @@ -266,6 +307,16 @@ void NRSMat::randomize(const double &x) { } } +template<> +void NRSMat::randomize(const float &x) { + NOT_GPU(*this); + copyonwrite(); + + for(size_t i=0; i >::randomize(const double &x) { } } +template<> +void NRSMat >::randomize(const float &x) { + copyonwrite(); + for(register size_t i=0; iFILE structure representing the output file @@ -390,6 +453,30 @@ const NRMat NRSMat::operator*(const NRMat &rhs) const { return result; } +template<> +const NRMat NRSMat::operator*(const NRMat &rhs) const { +#ifdef DEBUG + if(nn != rhs.nrows()) laerror("incompatible dimensions in NRMat NRSMat::operator*(const NRMat &)"); +#endif + SAME_LOC(*this, rhs); + NRMat result(nn, rhs.ncols(), getlocation()); +#ifdef CUDALA + if(location == cpu){ +#endif + for(register int k = 0; k >::operator*(const NRMat > &rhs return result; } +template<> +const NRMat > +NRSMat >::operator*(const NRMat > &rhs) const { +#ifdef DEBUG + if (nn != rhs.nrows()) laerror("incompatible dimensions in NRSMat >::operator*(const NRMat > &)"); +#endif + SAME_LOC(*this, rhs); + NRMat > result(nn, rhs.ncols(), getlocation()); +#ifdef CUDALA + if(location == cpu){ +#endif + for(register int k=0; k NRSMat::operator*(const NRSMat &rhs) const { return result; } +template<> +const NRMat NRSMat::operator*(const NRSMat &rhs) const { +#ifdef DEBUG + if (nn != rhs.nn) laerror("incompatible dimensions in NRMat NRSMat::operator*(const NRSMat &)"); +#endif + NRMat result(0.0, nn, nn); + float *p, *q; + + p = v; + for (int i=0; i >::operator*(const NRSMat > &rh return result; } +template<> +const NRMat > +NRSMat >::operator*(const NRSMat > &rhs) const { +#ifdef DEBUG + if (nn != rhs.nn) laerror("incompatible dimensions in NRSMat >::operator*(const NRSMat > &)"); +#endif + SAME_LOC(*this, rhs); + NRMat > result(nn, nn, getlocation()); + NRMat > rhsmat(rhs); + result = *this * rhsmat; + return result; +} + /***************************************************************************//** * compute inner product of this real symmetric matrix \f$A\f$ with given real symmetric matrix \f$B\f$ @@ -524,6 +700,25 @@ const double NRSMat::dot(const NRSMat &rhs) const { return ret; } +template<> +const float NRSMat::dot(const NRSMat &rhs) const { + float ret(0.); +#ifdef DEBUG + if (nn != rhs.nn) laerror("incompatible dimensions in float NRSMat::dot(const NRSMat &)"); +#endif + SAME_LOC(*this, rhs); +#ifdef CUDALA + if(location == cpu){ +#endif + ret = cblas_sdot(NN2, v, 1, rhs.v, 1); +#ifdef CUDALA + }else{ + ret = cublasSdot(NN2, v, 1, rhs.v, 1); + } +#endif + return ret; +} + /***************************************************************************//** * compute inner product of this complex symmetric matrix \f$A\f$ with given complex symmetric matrix \f$B\f$ @@ -554,6 +749,28 @@ const std::complex NRSMat >::dot(const NRSMat +const std::complex NRSMat >::dot(const NRSMat > &rhs) const { +#ifdef DEBUG + if (nn != rhs.nn) laerror("incompatible dimensions in std::complex NRSMat >::dot(const NRSMat > &)"); +#endif + std::complex dot(0., 0.); + SAME_LOC(*this, rhs); + +#ifdef CUDALA + if(location == cpu){ +#endif + cblas_cdotc_sub(NN2, v, 1, rhs.v, 1, &dot); +#ifdef CUDALA + }else{ + const cuComplex _dot = cublasCdotc(NN2, (cuComplex*)v, 1, (cuComplex*)(rhs.v), 1); + dot = std::complex(cuCreal(_dot), cuCimag(_dot)); + TEST_CUBLAS("cublasCdotc"); + } +#endif + return dot; +} + /***************************************************************************//** * compute inner product of this real double-precision symmetric matrix \f$S\f$ of order \f$n\f$ @@ -581,6 +798,26 @@ const double NRSMat::dot(const NRVec &rhs) const { return ret; } +template<> +const float NRSMat::dot(const NRVec &rhs) const { + float ret(0.0); +#ifdef DEBUG + if(NN2 != rhs.nn) laerror("incompatible dimensions in float NRSMat::dot(const NRVec &)"); +#endif + SAME_LOC(*this, rhs); +#ifdef CUDALA + if(location == cpu){ +#endif + ret = cblas_sdot(NN2, v, 1, rhs.v, 1); +#ifdef CUDALA + }else{ + ret = cublasSdot(NN2, v, 1, rhs.v, 1); + TEST_CUBLAS("cublasSdot"); + } +#endif +return ret; +} + /***************************************************************************//** * compute inner product of this complex double-precision hermitian matrix \f$H\f$ of order \f$n\f$ @@ -610,6 +847,28 @@ NRSMat >::dot(const NRVec > &rhs) cons return dot; } +template<> +const std::complex +NRSMat >::dot(const NRVec > &rhs) const { +#ifdef DEBUG + if(NN2 != rhs.nn) laerror("incompatible dimensions in std::complex NRSMat >::dot(const NRVec > &)"); +#endif + std::complex dot(0., 0.); + SAME_LOC(*this, rhs); +#ifdef CUDALA + if(location == cpu){ +#endif + cblas_cdotc_sub(NN2, v, 1, rhs.v, 1, &dot); +#ifdef CUDALA + }else{ + const cuComplex _dot = cublasCdotc(NN2, (cuComplex*)v, 1, (cuComplex*)rhs.v, 1); + TEST_CUBLAS("cublasCdotc"); + dot = std::complex(cuCreal(_dot), cuCimag(_dot)); + } +#endif + return dot; +} + /***************************************************************************//** * compute the Frobenius norm of this real double-precision symmetric matrix * @param[in] scalar subtract this scalar value from the diagonal elements before the norm computation @@ -645,6 +904,37 @@ const double NRSMat::norm(const double scalar) const { return std::sqrt(sum); } +template<> +const float NRSMat::norm(const float scalar) const { + if(!scalar){ + float ret(0.); +#ifdef CUDALA + if(location == cpu){ +#endif + ret = cblas_snrm2(NN2, v, 1); +#ifdef CUDALA + }else{ + ret = cublasSnrm2(NN2, v, 1); + TEST_CUBLAS("cublasSnrm2"); + } +#endif + return ret; + } + + NOT_GPU(*this); + + float sum(0.); + int k(0); + for(register int i=0; i >::norm(const std::complex sca return std::sqrt(sum); } +template<> +const float NRSMat< std::complex >::norm(const std::complex scalar) const { + if(!(scalar.real()) && !(scalar.imag())){ + float ret(0.); +#ifdef CUDALA + if(location == cpu){ +#endif + ret = cblas_scnrm2(NN2, v, 1); +#ifdef CUDALA + }else{ + ret = cublasScnrm2(NN2, (cuComplex*)v, 1); + TEST_CUBLAS("cublasScnrm2"); + } +#endif + return ret; + } + + int k(0); + float sum(0.); + std::complex tmp; + + for(register int i=0; i::rank2update(const double alpha, const NRVec &x, con cblas_dspr2(CblasRowMajor, CblasLower, nn, alpha, x, 1, y, 1, v); } +template<> +void NRSMat::rank2update(const float alpha, const NRVec &x, const NRVec &y) { +#ifdef DEBUG + if(nn != x.size() || nn != y.size()) laerror("incompatible dimensions in NRSMat::rank2update"); +#endif + NOT_GPU(*this); NOT_GPU(x); NOT_GPU(y); + copyonwrite(); + cblas_sspr2(CblasRowMajor, CblasLower, nn, alpha, x, 1, y, 1, v); +} + template<> void NRSMat >::rank2update(const std::complex alpha, const NRVec > &x, const NRVec > &y) { #ifdef DEBUG @@ -719,6 +1050,16 @@ void NRSMat >::rank2update(const std::complex alpha cblas_zhpr2(CblasRowMajor, CblasLower, nn, &alpha, x, 1, y, 1, v); } +template<> +void NRSMat >::rank2update(const std::complex alpha, const NRVec > &x, const NRVec > &y) { +#ifdef DEBUG + if(nn != x.size() || nn != y.size()) laerror("incompatible dimensions in NRSMat >::rank2update"); +#endif + NOT_GPU(*this); NOT_GPU(x); NOT_GPU(y); + copyonwrite(); + cblas_chpr2(CblasRowMajor, CblasLower, nn, &alpha, x, 1, y, 1, v); +} + /***************************************************************************//** * for this real double-precision symmetric matrix \f$S\f$ stored in packed form, @@ -744,6 +1085,25 @@ void NRSMat::axpy(const double alpha, const NRSMat &x) { #endif } +template<> +void NRSMat::axpy(const float alpha, const NRSMat &x) { +#ifdef DEBUG + if(nn != x.nn) laerror("incompatible dimensions in void NRSMat::axpy(const float, const NRSMat&)"); +#endif + SAME_LOC(*this, x); + copyonwrite(); +#ifdef CUDALA + if(location == cpu){ +#endif + cblas_saxpy(NN2, alpha, x.v, 1, v, 1); +#ifdef CUDALA + }else{ + cublasSaxpy(NN2, alpha, x.v, 1, v, 1); + TEST_CUBLAS("cublasSaxpy"); + } +#endif +} + /***************************************************************************//** * for this complex double-precision hermitian matrix \f$H\f$ stored in packed form, @@ -771,6 +1131,27 @@ void NRSMat >::axpy(const std::complex alpha, const } +template<> +void NRSMat >::axpy(const std::complex alpha, const NRSMat > & x) { +#ifdef DEBUG + if(nn != x.nn) laerror("incompatible dimensions in void NRSMat >::axpy(const std::complex , const NRSMat >&)"); +#endif + SAME_LOC(*this, x); + copyonwrite(); +#ifdef CUDALA + if(location == cpu){ +#endif + cblas_caxpy(NN2, &alpha, x.v, 1, v, 1); +#ifdef CUDALA + }else{ + const cuComplex _alpha = make_cuComplex(alpha.real(), alpha.imag()); + cublasCaxpy(NN2, _alpha, (cuComplex*)x.v, 1, (cuComplex*)v, 1); + TEST_CUBLAS("cublasCaxpy"); + } +#endif + +} + /***************************************************************************//** * create hermitian matrix \f$H\f$ from given real double-precision symmetric * matrix \f$S\f$ @@ -803,6 +1184,32 @@ NRSMat >::NRSMat(const NRSMat &rhs, bool imagpart): #endif } +template<> +NRSMat >::NRSMat(const NRSMat &rhs, bool imagpart): nn(rhs.nrows()), count(new int(1)) { + //inconsistent in general case? + const int nnp1 = nn*(nn + 1)/2; +#ifdef CUDALA + location = rhs.getlocation(); + if(location == cpu){ +#endif + v = new std::complex[nnp1]; + memset(v, 0, nnp1*sizeof(std::complex)); + cblas_scopy(nnp1, &rhs(0, 0), 1, ((float *)v) + (imagpart?1:0), 2); +#ifdef CUDALA + }else{ + v = (std::complex*) gpualloc(nnp1*sizeof(std::complex)); + + std::complex *_val = gpuputcomplex(CZEROF); + cublasCcopy(nnp1, (cuComplex*)_val, 0, (cuComplex*)v, 1); + TEST_CUBLAS("cublasCcopy"); + gpufree(_val); + + cublasScopy(nnp1, (float*)(&rhs(0,0)), 1, ((float*)v) + (imagpart?1:0), 2); + TEST_CUBLAS("cublasScopy"); + } +#endif +} + /***************************************************************************//** @@ -978,13 +1385,51 @@ NRSMat >& NRSMat >::conjugateme() { +/***************************************************************************//** + * complexify a given real matrix \f$A\f$ (double and float, by BLAS; the complex default constructor zeroes the imaginary parts) + * @param[in] rhs matrix \f$A\f$ intended for this operation + * @return matrix \f$B\f$ where \f$\Re B=A\f$ and \f$\Im B = 0\f$ + ******************************************************************************/ +template<> +NRSMat > complexify(const NRSMat &rhs) { + NRSMat > r(rhs.nrows(), rhs.getlocation()); +#ifdef CUDALA + if(rhs.getlocation() == cpu){ +#endif + cblas_dcopy(rhs.size(), &(rhs[0]), 1, (double*)(&(r[0])), 2); +#ifdef CUDALA + }else{ + cublasDcopy(rhs.size(), &(rhs[0]), 1, (double*)(&(r[0])), 2); + TEST_CUBLAS("cublasDcopy");//"NRSMat > complexify(const NRSMat &)" + } +#endif + return r; +} + +template<> +NRSMat > complexify(const NRSMat &rhs) { + NRSMat > r(rhs.nrows(), rhs.getlocation()); +#ifdef CUDALA + if(rhs.getlocation() == cpu){ +#endif + cblas_scopy(rhs.size(), &(rhs[0]), 1, (float*)(&(r[0])), 2); +#ifdef CUDALA + }else{ + cublasScopy(rhs.size(), &(rhs[0]), 1, (float*)(&(r[0])), 2); + TEST_CUBLAS("cublasScopy");//"NRSMat > complexify(const NRSMat &)" + } +#endif + return r; +} + + /***************************************************************************//** * forced instantization in the corresponding object file ******************************************************************************/ template class NRSMat; template class NRSMat >; -//template class NRSMat; -//template class NRSMat >; +template class NRSMat; +template class NRSMat >; template class NRSMat; template class NRSMat; template class NRSMat; diff --git a/smat.h b/smat.h index 6be29fd..3de96e6 100644 --- a/smat.h +++ b/smat.h @@ -387,6 +387,22 @@ inline NRSMat & NRSMat::operator*=(const double &a) { return *this; } +template<> +inline NRSMat & NRSMat::operator*=(const float &a) { + copyonwrite(); +#ifdef CUDALA + if(location == cpu){ +#endif + cblas_sscal(NN2, a, v, 1); +#ifdef CUDALA + }else{ + cublasSscal(NN2, a, v, 1); + TEST_CUBLAS("cublasSscal");//"NRSMat& NRSMat::operator*=(const float &)" + } +#endif + return *this; +} + /***************************************************************************//** * multiply this complex symmetric matrix with complex scalar value * @param[in] a complex multiplicative factor @@ -410,6 +426,24 @@ NRSMat >::operator*=(const std::complex &a) { return *this; } +template<> +inline NRSMat > & +NRSMat >::operator*=(const std::complex &a) { + copyonwrite(); +#ifdef CUDALA + if(location == cpu){ +#endif + cblas_cscal(NN2, &a, v, 1); +#ifdef CUDALA + }else{ + const cuComplex _a = make_cuComplex(a.real(), a.imag()); + cublasCscal(NN2, _a, (cuComplex*)v, 1); + TEST_CUBLAS("cublasCscal");//"NRSMat >& NRSMat >::operator*=(const std::complex &)" + } +#endif + return *this; +} + /***************************************************************************//** * multiply this symmetric matrix of general type T stored in packed form @@ -508,6 +542,27 @@ inline NRSMat& NRSMat::operator+=(const NRSMat & rhs) { return *this; } +template<> +inline NRSMat& NRSMat::operator+=(const NRSMat & rhs) { +#ifdef DEBUG + if(nn != rhs.nn) laerror("incompatible dimensions in NRSMat& NRSMat::operator+=(const NRSMat &)"); +#endif + SAME_LOC(*this, rhs); + copyonwrite(); + +#ifdef CUDALA + if(location == cpu){ +#endif + cblas_saxpy(NN2, 1.0, rhs.v, 1, v, 1); +#ifdef CUDALA + }else{ + cublasSaxpy(NN2, 1.0, rhs.v, 1, v, 1); + TEST_CUBLAS("cublasSaxpy");//" NRSMat& NRSMat::operator+=(const NRSMat &)" + } +#endif + return *this; +} + /***************************************************************************//** * add up this complex symmetric matrix with given symmetric matrix * @param[in] rhs complex symmetric matrix to be added @@ -534,6 +589,27 @@ inline NRSMat >& NRSMat >::operator+=( return *this; } +template<> +inline NRSMat >& NRSMat >::operator+=(const NRSMat > & rhs) { +#ifdef DEBUG + if(nn != rhs.nn) laerror("incompatible dimensions in NRSMat >& NRSMat >::operator+=(const NRSMat > &)"); +#endif + SAME_LOC(*this, rhs); + copyonwrite(); + +#ifdef CUDALA + if(location == cpu){ +#endif + cblas_caxpy(NN2, &CONEF, rhs.v, 1, v, 1); +#ifdef CUDALA + }else{ + cublasCaxpy(NN2, CUONE, (cuComplex*)(rhs.v), 1, (cuComplex*)v, 1); + TEST_CUBLAS("cublasCaxpy");//"NRSMat >& NRSMat >::operator+=(const NRSMat > &)" + } +#endif + return *this; +} + /***************************************************************************//** * add up this symmetric matrix of general type T with given symmetric matrix * @param[in] rhs complex matrix of general type T to be added @@ -578,6 +654,27 @@ inline NRSMat& NRSMat::operator-=(const NRSMat& rhs) { return *this; } +template<> +inline NRSMat& NRSMat::operator-=(const NRSMat& rhs) { +#ifdef DEBUG + if(nn != rhs.nn) laerror("incompatible dimensions in NRSMat& NRSMat::operator-=(const NRSMat &)"); +#endif + SAME_LOC(*this, rhs); + copyonwrite(); + +#ifdef CUDALA + if(location == cpu){ +#endif + cblas_saxpy(NN2, -1.0, rhs.v, 1, v, 1); +#ifdef CUDALA + }else{ + cublasSaxpy(NN2, -1.0, rhs.v, 1, v, 1); + TEST_CUBLAS("cublasSaxpy");//" NRSMat& NRSMat::operator-=(const NRSMat &)" + } +#endif + return *this; +} + /***************************************************************************//** * subtracts given complex symmetric matrix from this complex symmetric matrix * @param[in] rhs complex symmetric matrix to be subtracted @@ -604,6 +701,27 @@ inline NRSMat >& NRSMat >::operator-=( return *this; } +template<> +inline NRSMat >& NRSMat >::operator-=(const NRSMat >& rhs) { +#ifdef DEBUG + if(nn != rhs.nn) laerror("incompatible dimensions in NRSMat >& NRSMat >::operator-=(const NRSMat > &)"); +#endif + SAME_LOC(*this, rhs); + copyonwrite(); + +#ifdef CUDALA + if(location == cpu){ +#endif + cblas_caxpy(NN2, &CMONEF, rhs.v, 1, v, 1); +#ifdef CUDALA + }else{ + cublasCaxpy(NN2, CUMONE, (cuComplex*)(rhs.v), 1, (cuComplex*)v, 1); + TEST_CUBLAS("cublasCaxpy");//"NRSMat >& NRSMat >::operator-=(const NRSMat > &)" + } +#endif + return *this; +} + /***************************************************************************//** * subtracts given symmetric matrix of general type T from this symmetric matrix of type T * @param[in] rhs symmetric matrix of general type T to be subtracted @@ -871,6 +989,24 @@ inline const double NRSMat::amax() const { return ret; } +template<> +inline const float NRSMat::amax() const { + float ret(0.0); +#ifdef CUDALA + if(location == cpu){ +#endif + ret = v[cblas_isamax(NN2, v, 1)]; +#ifdef CUDALA + }else{ + const int pozice = cublasIsamax(NN2, v, 1) ; + TEST_CUBLAS("cublasIsamax");//"float NRSMat::amax()" + + gpuget(1, sizeof(float), v + pozice, &ret); + } +#endif + return ret; +} + /***************************************************************************//** * for this real symmetric matrix \f$A\f$, determine the * first element with smallest absolute value @@ -901,6 +1037,31 @@ inline const double NRSMat::amin() const { return ret; } +template<> +inline const float NRSMat::amin() const { + float ret(0.0); +#ifdef CUDALA + if(location == cpu){ +#endif + // idamin seems not to be supported + float val(0.0); + int index(-1); + ret = std::numeric_limits::max(); + for(register size_t i = 0; i < NN2; i++){ + val = std::abs(v[i]); + if(val < ret){ index = i; ret = val; } + } + ret = v[index]; +#ifdef CUDALA + }else{ + const int pozice = cublasIsamin(nn, v, 1); + TEST_CUBLAS("cublasIsamin");//"float NRSMat::amin()" + gpuget(1, sizeof(float), v + pozice, &ret); + } +#endif + return ret; +} + /***************************************************************************//** * for this complex symmetric matrix \f$A\f$, determine the * first element with largest "absolute value" @@ -923,6 +1084,23 @@ inline const std::complex NRSMat< std::complex >::amax() const{ return ret; } +template<> +inline const std::complex NRSMat< std::complex >::amax() const{ + std::complex ret(0., 0.); +#ifdef CUDALA + if(location == cpu){ +#endif + ret = v[cblas_icamax(NN2, v, 1)]; +#ifdef CUDALA + }else{ + const int pozice = cublasIcamax(NN2, (cuComplex*)v, 1); + TEST_CUBLAS("cublasIcamax");//"std::complex NRSMat >::amax()" + gpuget(1, sizeof(std::complex), v + pozice, &ret); + } +#endif + return ret; +} + /***************************************************************************//** * for this complex symmetric matrix \f$A\f$, determine the * first element with smallest "absolute value" @@ -956,6 +1134,34 @@ inline const std::complex NRSMat >::amin() const{ return ret; } +template<> +inline const std::complex NRSMat >::amin() const{ + std::complex ret(0., 0.); +#ifdef CUDALA + if(location == cpu){ +#endif + // izamin seems not to be supported + int index(0); + float val(0.0), min_val(0.0); + std::complex z_val(0.0, 0.0); + + min_val = std::numeric_limits::max(); + for(register size_t i = 0; i < NN2; i++){ + z_val = v[i]; + val = std::abs(z_val.real()) + std::abs(z_val.imag()); + if(val < min_val){ index = i; min_val = val; } + } + ret = v[index]; +#ifdef CUDALA + }else{ + const int pozice = cublasIcamin(nn, (cuComplex*)v, 1); + TEST_CUBLAS("cublasIcamin");//"std::complex NRSMat >::amin()" + gpuget(1, sizeof(std::complex), v + pozice, &ret); + } +#endif + return ret; +} + /***************************************************************************//** * @return pointer of general type T to the underlying data structure ******************************************************************************/ @@ -1215,28 +1421,9 @@ NRSMat > complexify(const NRSMat &rhs) { } -/***************************************************************************//** - * complexify a given double-precision real matrix \f$A\f$ - * @param[in] rhs matrix \f$A\f$ intended for this operation - * @return matrix \f$B\f$ where \f$\Re B=A\f$ and \f$\Im B = 0\f$ - ******************************************************************************/ -/* -template<> -NRSMat > complexify(const NRSMat &rhs) { - NRSMat > r(rhs.nrows(), rhs.getlocation()); -#ifdef CUDALA - if(rhs.getlocation() == cpu){ -#endif - cblas_dcopy(rhs.size(), &(rhs[0]), 1, (double*)(&(r[0])), 2); -#ifdef CUDALA - }else{ - cublasDcopy(rhs.size(), &(rhs[0]), 1, (double*)(&(r[0])), 2); - TEST_CUBLAS("cublasDcopy");//"NRSMat > complexify(const NRSMat &)" - } -#endif - return r; -} -*/ +//BLAS versions for double and float are in smat.cc (a full specialization defined in the header would be multiply defined) +template<> NRSMat > complexify(const NRSMat &rhs); +template<> NRSMat > complexify(const NRSMat &rhs); /***************************************************************************//** * output operator * @param[in,out] s output stream