LA_library/smat.h

1197 lines
41 KiB
C
Raw Normal View History

2010-09-08 18:27:58 +02:00
//------------------------------------------------------------------------------
/* vim: set ts=8 sw=8 sts=8 noexpandtab cindent: */
//------------------------------------------------------------------------------
2008-02-26 14:55:23 +01:00
/*
LA: linear algebra C++ interface library
Copyright (C) 2008 Jiri Pittner <jiri.pittner@jh-inst.cas.cz> or <jiri@pittnerovi.com>
complex versions written by Roman Curik <roman.curik@jh-inst.cas.cz>
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 <http://www.gnu.org/licenses/>.
*/
2004-03-17 04:07:21 +01:00
#ifndef _LA_SMAT_H_
#define _LA_SMAT_H_
2005-02-14 01:10:07 +01:00
#include "la_traits.h"
2004-03-17 04:07:21 +01:00
2009-11-12 22:01:19 +01:00
namespace LA {
2004-03-17 04:07:21 +01:00
#define NN2 (nn*(nn+1)/2)
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* This class implements a general symmetric or hermitian matrix the elements
* of which are stored in packed form. Particularly the lower triangular part
* of a symmetric or hermitian matrix of order \f$N\f$ is interpreted as a
* vector of length \f$N(N+1)/2\f$ in row-major storage scheme.
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <class T>
2010-09-08 18:27:58 +02:00
class NRSMat{
2004-03-17 04:07:21 +01:00
protected:
2010-09-08 18:27:58 +02:00
int nn;//!< number of rows/columns of this symmetric matrix
T *v;//!< internal pointer to the underlying data structure
int *count;//!< pointer to the reference counter
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
GPUID location;//!< specification of memory (GPU/CPU) location where this objects resides
2010-06-25 17:28:19 +02:00
#endif
2004-03-17 04:07:21 +01:00
public:
friend class NRVec<T>;
friend class NRMat<T>;
2010-09-08 18:27:58 +02:00
~NRSMat();
//! default constructor of null-matrix
inline NRSMat() : nn(0),v(0),count(0) {
#ifdef CUDALA
location = DEFAULT_LOC;
#endif
};
//! default constructor
inline explicit NRSMat(const int n, const GPUID loc = undefined);
//! constructor initializing the matrix being created by given scalar value
inline NRSMat(const T &a, const int n);
//! constructor initializing the matrix being created by data located at given memory position
inline NRSMat(const T *a, const int n);
//! copy constructor
inline NRSMat(const NRSMat &rhs);
//! constructor converting real matrix to its complex counterpart
NRSMat(const typename LA_traits_complex<T>::NRSMat_Noncomplex_type &rhs, bool imagpart = false);
//! constructor creating symmetric part of a general matrix
explicit NRSMat(const NRMat<T> &rhs);
//! construct symmetric matrix by filling the lower triangle with data stored in a vector
explicit NRSMat(const NRVec<T> &rhs, const int n);
//! assignment operator performing shallow copy
NRSMat & operator=(const NRSMat &rhs);
//! assignment operator performing deep copy
NRSMat & operator|=(const NRSMat &rhs);
//! fill the matrix with pseudorandom numbers (uniform distribution)
2009-09-04 10:09:32 +02:00
void randomize(const typename LA_traits<T>::normtype &x);
2010-09-08 18:27:58 +02:00
//! assign scalar value to diagonal elements
NRSMat & operator=(const T &a);
inline int getcount() const {return count?*count:0;}
#ifdef CUDALA
inline GPUID getlocation() const {return location;}
void moveto(const GPUID dest);
#else
inline GPUID getlocation() const {return cpu;}
void moveto(const GPUID dest) {};
#endif
//! relational operator for testing nonequality
const bool operator!=(const NRSMat &rhs) const {if(nn!=rhs.nn) return 1; return LA_traits<T>::gencmp(v,rhs.v,NN2);};
//! relational operator for testing equality
2005-02-14 01:10:07 +01:00
const bool operator==(const NRSMat &rhs) const {return !(*this != rhs);};
2010-09-08 18:27:58 +02:00
2004-03-17 04:07:21 +01:00
inline NRSMat & operator*=(const T &a);
2010-09-08 18:27:58 +02:00
inline NRSMat & operator+=(const T &a);
inline NRSMat & operator-=(const T &a);
inline NRSMat & operator+=(const NRSMat &rhs);
inline NRSMat & operator-=(const NRSMat &rhs);
const NRSMat operator-() const;
2004-03-17 04:07:21 +01:00
inline const NRSMat operator*(const T &a) const;
inline const NRSMat operator+(const T &a) const;
inline const NRSMat operator-(const T &a) const;
2010-09-08 18:27:58 +02:00
inline const NRSMat operator+(const NRSMat &rhs) const;
2004-03-17 04:07:21 +01:00
inline const NRSMat operator-(const NRSMat &rhs) const;
2010-09-08 18:27:58 +02:00
inline const NRMat<T> operator+(const NRMat<T> &rhs) const;
inline const NRMat<T> operator-(const NRMat<T> &rhs) const;
const NRMat<T> operator*(const NRSMat &rhs) const;
const NRMat<T> operator*(const NRMat<T> &rhs) const;
const T dot(const NRSMat &rhs) const;
const T dot(const NRVec<T> &rhs) const;
const NRVec<T> operator*(const NRVec<T> &rhs) const {NRVec<T> result(nn,rhs.getlocation()); result.gemv((T)0,*this,'n',(T)1,rhs); return result;};
const NRVec<complex<T> > operator*(const NRVec<complex<T> > &rhs) const {NRVec<complex<T> > result(nn,rhs.getlocation()); result.gemv((T)0,*this,'n',(T)1,rhs); return result;};
const T* diagonalof(NRVec<T> &, const bool divide = 0, bool cache = false) const;
2006-04-06 23:45:51 +02:00
void gemv(const T beta, NRVec<T> &r, const char trans, const T alpha, const NRVec<T> &x) const {r.gemv(beta,*this,trans,alpha,x);};
2009-09-04 10:09:32 +02:00
void gemv(const T beta, NRVec<complex<T> > &r, const char trans, const T alpha, const NRVec<complex<T> > &x) const {r.gemv(beta,*this,trans,alpha,x);};
2010-09-08 18:27:58 +02:00
2004-03-17 04:07:21 +01:00
inline const T& operator[](const int ij) const;
inline T& operator[](const int ij);
2010-09-08 18:27:58 +02:00
2004-03-17 04:07:21 +01:00
inline const T& operator()(const int i, const int j) const;
inline T& operator()(const int i, const int j);
2010-09-08 18:27:58 +02:00
2004-03-17 04:07:21 +01:00
inline int nrows() const;
inline int ncols() const;
2005-02-18 23:08:15 +01:00
inline int size() const;
2010-09-08 18:27:58 +02:00
2006-04-06 23:45:51 +02:00
inline bool transp(const int i, const int j) const {return i>j;} //this can be used for compact storage of matrices, which are actually not symmetric, but one triangle of them is redundant
2010-09-08 18:27:58 +02:00
const typename LA_traits<T>::normtype norm(const T scalar = (T)0) const;
2004-03-17 04:07:21 +01:00
void axpy(const T alpha, const NRSMat &x); // this+= a*x
2010-09-08 18:27:58 +02:00
2004-03-17 04:07:21 +01:00
inline const T amax() const;
2010-09-08 18:27:58 +02:00
inline const T amin() const;
2004-03-17 04:07:21 +01:00
const T trace() const;
2010-09-08 18:27:58 +02:00
void get(int fd, bool dimensions = 1, bool transp = 0);
void put(int fd, bool dimensions = 1, bool transp = 0) const;
2004-03-17 04:07:21 +01:00
void copyonwrite();
2010-09-08 18:27:58 +02:00
2009-09-04 10:09:32 +02:00
void clear() {copyonwrite(); LA_traits<T>::clear(v,NN2);}; //zero out
2004-03-17 04:07:21 +01:00
void resize(const int n);
2011-01-18 15:37:05 +01:00
void dealloc(void) {resize(0);}
2010-09-08 18:27:58 +02:00
inline operator T*();
inline operator const T*() const;
2004-03-17 04:07:21 +01:00
void fprintf(FILE *f, const char *format, const int modulo) const;
void fscanf(FILE *f, const char *format);
//members concerning sparse matrix
explicit NRSMat(const SparseMat<T> &rhs); // dense from sparse
2009-11-12 22:01:19 +01:00
explicit NRSMat(const SparseSMat<T> &rhs); // dense from sparse
2004-03-17 04:07:21 +01:00
inline void simplify() {}; //just for compatibility with sparse ones
2005-02-18 23:08:15 +01:00
bool issymmetric() const {return 1;}
2004-03-17 04:07:21 +01:00
};
2009-11-12 22:01:19 +01:00
}//namespace
2005-02-18 23:08:15 +01:00
//due to mutual includes this has to be after full class declaration
#include "vec.h"
#include "mat.h"
2009-11-12 22:01:19 +01:00
namespace LA {
2005-02-18 23:08:15 +01:00
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* constructor of a symmetric matrix stored in packed form
* @param[in] n number of rows of the matrix being created
* @param[in] loc location for storing the matrix
* @see count, v, location
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline NRSMat<T>::NRSMat(const int n, const GPUID loc): nn(n), count(new int(1)) {
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
location = (loc == undefined?DEFAULT_LOC:loc);
if(location == cpu){
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
v = new T[NN2];
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
}else{
v = (T*) gpualloc(NN2*sizeof(T));
}
2010-06-25 17:28:19 +02:00
#endif
}
2004-03-17 04:07:21 +01:00
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* constructor of a symmetric matrix stored in packed form (default location in used)
* @param[in] a set all matrix elements equal to this value
* @param[in] n number of rows of the matrix being created
* @see count, v, location, NRSMat<T>::NRSMat(const int, const GPUID)
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline NRSMat<T>::NRSMat(const T& a, const int n) : nn(n), count(new int(1)) {
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
location = DEFAULT_LOC;
if(location == cpu){
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
v = new T[NN2];
if(a != (T)0) for(register int i = 0; i<NN2; i++) v[i] = a;
else memset(v, 0, NN2*sizeof(T));
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
}else{
v = (T*) gpualloc(NN2*sizeof(T));
cublasSetVector(NN2, sizeof(T), &a, 0, v, 1);
2010-06-25 17:28:19 +02:00
}
#endif
2004-03-17 04:07:21 +01:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* constructor of a symmetric matrix stored in packed form (default location in used)
* @param[in] a pointer to data of type T used for matrix inicialization
* @param[in] n number of rows of the matrix being created
* @see count, v, location, NRSMat<T>::NRSMat(const int, const GPUID), NRSMat<T>::NRSMat(const T&, const int)
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline NRSMat<T>::NRSMat(const T *a, const int n) : nn(n), count(new int(1)) {
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
location = DEFAULT_LOC;
if(location == cpu){
2010-06-25 17:28:19 +02:00
#endif
memcpy(v, a, NN2*sizeof(T));
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
}else{
v = (T*) gpualloc(NN2*sizeof(T));
cublasSetVector(NN2, sizeof(T), a, 1, v, 1);
}
2010-06-25 17:28:19 +02:00
#endif
2004-03-17 04:07:21 +01:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* copy constructor implementing shallow copy
* @param[in] rhs reference matrix being copied
* @see count, v, location
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline NRSMat<T>::NRSMat(const NRSMat<T> &rhs) {
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
location = rhs.location;
2010-06-25 17:28:19 +02:00
#endif
2004-03-17 04:07:21 +01:00
v = rhs.v;
nn = rhs.nn;
count = rhs.count;
2010-09-08 18:27:58 +02:00
if(count) (*count)++;
2004-03-17 04:07:21 +01:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* constructor interpreting a vector of \f$n(n+1)/2\f$ elements as a symmetric
* matrix stored in packed form having \f$n\f$ rows
* @param[in] rhs reference matrix being copied
* @param[in] n count of rows of the matrix being created
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
NRSMat<T>::NRSMat(const NRVec<T> &rhs, const int n) {
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
location = rhs.location;
2010-06-25 17:28:19 +02:00
#endif
2004-03-17 04:07:21 +01:00
nn = n;
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(NN2 != rhs.size()){ laerror("incompatible dimensions in NRSMat<T>::NRSMat(const NRVec<T>&, const int)"); }
2004-03-17 04:07:21 +01:00
#endif
count = rhs.count;
v = rhs.v;
(*count)++;
}
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* multiply this real symmetric matrix with real scalar value
* @param[in] a real multiplicative factor
* @return reference to the modified matrix
******************************************************************************/
2005-11-20 14:46:00 +01:00
template<>
2010-09-08 18:27:58 +02:00
inline NRSMat<double> & NRSMat<double>::operator*=(const double &a) {
2004-03-17 04:07:21 +01:00
copyonwrite();
2010-09-08 18:27:58 +02:00
#ifdef CUDALA
if(location == cpu){
#endif
cblas_dscal(NN2, a, v, 1);
#ifdef CUDALA
}else{
cublasDscal(NN2, a, v, 1);
TEST_CUBLAS("cublasDscal");//"NRSMat<double>& NRSMat<double>::operator*=(const double &)"
}
#endif
2004-03-17 04:07:21 +01:00
return *this;
}
2005-11-20 14:46:00 +01:00
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* multiply this complex symmetric matrix with complex scalar value
* @param[in] a complex multiplicative factor
* @return reference to the modified matrix
******************************************************************************/
2005-11-20 14:46:00 +01:00
template<>
2010-09-08 18:27:58 +02:00
inline NRSMat<complex<double> > &
NRSMat<complex<double> >::operator*=(const complex<double> &a) {
2004-03-17 04:07:21 +01:00
copyonwrite();
2010-09-08 18:27:58 +02:00
#ifdef CUDALA
if(location == cpu){
#endif
cblas_zscal(NN2, &a, v, 1);
#ifdef CUDALA
}else{
const cuDoubleComplex _a = make_cuDoubleComplex(a.real(), a.imag());
cublasZscal(NN2, _a, (cuDoubleComplex*)v, 1);
TEST_CUBLAS("cublasZscal");//"NRSMat<complex<double> >& NRSMat<complex<double> >::operator*=(const complex<double> &)"
}
#endif
2004-03-17 04:07:21 +01:00
return *this;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* multiply this symmetric matrix of general type <code>T</code> stored in packed form
* with scalar value of type <code>T</code>
* @param[in] a multiplicative factor of type <code>T</code>
* @return reference to the modified matrix
******************************************************************************/
2004-03-17 06:34:59 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline NRSMat<T> & NRSMat<T>::operator*=(const T &a) {
NOT_GPU(*this);
copyonwrite();
for(register int i = 0; i<NN2; ++i) v[i] *= a;
2004-03-17 06:34:59 +01:00
return *this;
}
2004-03-17 04:07:21 +01:00
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* add a scalar value \f$\alpha\f$ of general type <code>T</code> to the diagonal elements of this symmetric matrix of type <code>T</code>
* @param[in] a scalar value \f$\alpha\f$
* @return reference to the modified matrix
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline NRSMat<T> & NRSMat<T>::operator+=(const T &a) {
NOT_GPU(*this);
2004-03-17 04:07:21 +01:00
copyonwrite();
2010-09-08 18:27:58 +02:00
for(register int i = 0; i<nn; i++) v[i*(i+1)/2 + i] += a;
2004-03-17 04:07:21 +01:00
return *this;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* subtract a scalar value \f$\alpha\f$ of general type <code>T</code> from the
* diagonal elements of this symmetric matrix of type <code>T</code>
* @param[in] a scalar value \f$\alpha\f$
* @return reference to the modified matrix
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline NRSMat<T> & NRSMat<T>::operator-=(const T &a) {
NOT_GPU(*this);
2004-03-17 04:07:21 +01:00
copyonwrite();
2010-09-08 18:27:58 +02:00
for(register int i = 0; i<nn; i++) v[i*(i+1)/2+i] -= a;
2004-03-17 04:07:21 +01:00
return *this;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* add up this real symmetric matrix with given symmetric matrix
* @param[in] rhs real symmetric matrix to be added
* @return reference to the modified matrix
******************************************************************************/
2005-11-20 14:46:00 +01:00
template<>
2010-09-08 18:27:58 +02:00
inline NRSMat<double>& NRSMat<double>::operator+=(const NRSMat<double> & rhs) {
2004-03-17 04:07:21 +01:00
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(nn != rhs.nn) laerror("incompatible dimensions in NRSMat<double>& NRSMat<double>::operator+=(const NRSMat<double> &)");
2004-03-17 04:07:21 +01:00
#endif
2010-09-08 18:27:58 +02:00
SAME_LOC(*this, rhs);
2004-03-17 04:07:21 +01:00
copyonwrite();
2010-09-08 18:27:58 +02:00
#ifdef CUDALA
if(location == cpu){
#endif
cblas_daxpy(NN2, 1.0, rhs.v, 1, v, 1);
#ifdef CUDALA
}else{
cublasDaxpy(NN2, 1.0, rhs.v, 1, v, 1);
TEST_CUBLAS("cublasDaxpy");//" NRSMat<double>& NRSMat<double>::operator+=(const NRSMat<double> &)"
}
#endif
2004-03-17 04:07:21 +01:00
return *this;
}
2005-11-20 14:46:00 +01:00
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* add up this complex symmetric matrix with given symmetric matrix
* @param[in] rhs complex symmetric matrix to be added
* @return reference to the modified matrix
******************************************************************************/
2005-11-20 14:46:00 +01:00
template<>
2010-09-08 18:27:58 +02:00
inline NRSMat<complex<double> >& NRSMat<complex<double> >::operator+=(const NRSMat<complex<double> > & rhs) {
2004-03-17 04:07:21 +01:00
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(nn != rhs.nn) laerror("incompatible dimensions in NRSMat<complex<double> >& NRSMat<complex<double> >::operator+=(const NRSMat<complex<double> > &)");
2004-03-17 04:07:21 +01:00
#endif
2010-09-08 18:27:58 +02:00
SAME_LOC(*this, rhs);
2004-03-17 04:07:21 +01:00
copyonwrite();
2010-09-08 18:27:58 +02:00
#ifdef CUDALA
if(location == cpu){
#endif
cblas_zaxpy(NN2, &CONE, rhs.v, 1, v, 1);
#ifdef CUDALA
}else{
cublasZaxpy(NN2, CUONE, (cuDoubleComplex*)(rhs.v), 1, (cuDoubleComplex*)v, 1);
TEST_CUBLAS("cublasZaxpy");//"NRSMat<complex<double> >& NRSMat<complex<double> >::operator+=(const NRSMat<complex<double> > &)"
}
#endif
2004-03-17 04:07:21 +01:00
return *this;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* add up this symmetric matrix of general type <code>T</code> with given symmetric matrix
* @param[in] rhs complex matrix of general type <code>T</code> to be added
* @return reference to the modified matrix
******************************************************************************/
2004-03-17 06:34:59 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline NRSMat<T>& NRSMat<T>::operator+=(const NRSMat<T>& rhs) {
2004-03-17 06:34:59 +01:00
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(nn != rhs.nn) laerror("incompatible NRSMat<T>& NRSMat<T>::operator+=(const NRSMat<T> &)");
2004-03-17 06:34:59 +01:00
#endif
2010-09-08 18:27:58 +02:00
NOT_GPU(*this);
SAME_LOC(*this, rhs);
2004-03-17 06:34:59 +01:00
copyonwrite();
2010-09-08 18:27:58 +02:00
for(register int i = 0; i<NN2; ++i) v[i] += rhs.v[i];
2004-03-17 06:34:59 +01:00
return *this;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* subtracts given real symmetric matrix from this real symmetric matrix
* @param[in] rhs real symmetric matrix to be subtracted
* @return reference to the modified matrix
******************************************************************************/
2005-11-20 14:46:00 +01:00
template<>
2010-09-08 18:27:58 +02:00
inline NRSMat<double>& NRSMat<double>::operator-=(const NRSMat<double>& rhs) {
2004-03-17 04:07:21 +01:00
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(nn != rhs.nn) laerror("incompatible dimensions in NRSMat<double>& NRSMat<double>::operator-=(const NRSMat<double> &)");
2004-03-17 04:07:21 +01:00
#endif
2010-09-08 18:27:58 +02:00
SAME_LOC(*this, rhs);
2004-03-17 04:07:21 +01:00
copyonwrite();
2010-09-08 18:27:58 +02:00
#ifdef CUDALA
if(location == cpu){
#endif
cblas_daxpy(NN2, -1.0, rhs.v, 1, v, 1);
#ifdef CUDALA
}else{
cublasDaxpy(NN2, -1.0, rhs.v, 1, v, 1);
TEST_CUBLAS("cublasDaxpy");//" NRSMat<double>& NRSMat<double>::operator-=(const NRSMat<double> &)"
}
#endif
2004-03-17 04:07:21 +01:00
return *this;
}
2005-11-20 14:46:00 +01:00
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* subtracts given complex symmetric matrix from this complex symmetric matrix
* @param[in] rhs complex symmetric matrix to be subtracted
* @return reference to the modified matrix
******************************************************************************/
2005-11-20 14:46:00 +01:00
template<>
2010-09-08 18:27:58 +02:00
inline NRSMat<complex<double> >& NRSMat<complex<double> >::operator-=(const NRSMat<complex<double> >& rhs) {
2004-03-17 04:07:21 +01:00
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(nn != rhs.nn) laerror("incompatible dimensions in NRSMat<complex<double> >& NRSMat<complex<double> >::operator-=(const NRSMat<complex<double> > &)");
2004-03-17 04:07:21 +01:00
#endif
2010-09-08 18:27:58 +02:00
SAME_LOC(*this, rhs);
2004-03-17 04:07:21 +01:00
copyonwrite();
2010-09-08 18:27:58 +02:00
#ifdef CUDALA
if(location == cpu){
#endif
cblas_zaxpy(NN2, &CMONE, rhs.v, 1, v, 1);
#ifdef CUDALA
}else{
cublasZaxpy(NN2, CUMONE, (cuDoubleComplex*)(rhs.v), 1, (cuDoubleComplex*)v, 1);
TEST_CUBLAS("cublasZaxpy");//"NRSMat<complex<double> >& NRSMat<complex<double> >::operator-=(const NRSMat<complex<double> > &)"
}
#endif
2004-03-17 04:07:21 +01:00
return *this;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* subtracts given symmetric matrix of general type <code>T</code> from this symmetric matrix of type <code>T</code>
* @param[in] rhs symmetric matrix of general type <code>T</code> to be subtracted
* @return reference to the modified matrix
******************************************************************************/
2004-03-17 06:34:59 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline NRSMat<T>& NRSMat<T>::operator-=(const NRSMat<T>& rhs) {
2004-03-17 06:34:59 +01:00
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(nn != rhs.nn) laerror("incompatible NRSMat<T>& NRSMat<T>::operator-=(const NRSMat<T> &)");
2004-03-17 06:34:59 +01:00
#endif
2010-09-08 18:27:58 +02:00
NOT_GPU(*this);
2004-03-17 06:34:59 +01:00
copyonwrite();
2010-09-08 18:27:58 +02:00
for(register int i = 0; i<NN2; ++i) v[i] -= rhs.v[i];
2004-03-17 06:34:59 +01:00
return *this;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* add up given dense matrix of general type <code>T</code> with this symmetric matrix of type <code>T</code>
* @param[in] rhs dense matrix of type <code>T</code> to be added
* @return reference to the modified matrix
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline const NRMat<T> NRSMat<T>::operator+(const NRMat<T> &rhs) const {
2004-03-17 04:07:21 +01:00
return NRMat<T>(rhs) += *this;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* subtracts given dense matrix of general type <code>T</code> from this symmetric matrix of type <code>T</code>
* @param[in] rhs dense matrix of type <code>T</code> to be added
* @return reference to the modified matrix
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline const NRMat<T> NRSMat<T>::operator-(const NRMat<T> &rhs) const {
2004-03-17 04:07:21 +01:00
return NRMat<T>(-rhs) += *this;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* determine matrix element of this symmetric matrix of general type <code>T</code>
* using cumulative index increasing in a row-major way and corresponding to the
* lower triangular part of the respective dense matrix
* @param[in] ij index of the requested element
* @return reference to the corresponding matrix element
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline T& NRSMat<T>::operator[](const int ij) {
2004-03-17 04:07:21 +01:00
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(_LA_count_check && *count != 1) laerror("T& NRSMat<T>::operator[] used for matrix with count>1");
if(ij<0 || ij>=NN2) laerror("T& NRSMat<T>::operator[] out of range");
if(!v) laerror("T& NRSMat<T>::operator[] used for unallocated NRSmat<T> object");
2004-03-17 04:07:21 +01:00
#endif
2010-09-08 18:27:58 +02:00
NOT_GPU(*this);
2004-03-17 04:07:21 +01:00
return v[ij];
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* determine matrix element of this symmetric matrix of general type <code>T</code>
* using cumulative index increasing in a row-major way and corresponding to the
* lower triangular part of the respective dense matrix, i.e. \f$A_{i,j}\f$ for
* \f$N>i\geq{}j\geq0\f$ corresponds to cumulative index \f$i(i+1)/2+j\f$
* @param[in] ij index of the requested element
* @return constant reference to the corresponding matrix element
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline const T & NRSMat<T>::operator[](const int ij) const {
2004-03-17 04:07:21 +01:00
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(ij<0 || ij>=NN2) laerror("T& NRSMat<T>::operator[] out of range");
if(!v) laerror("T& NRSMat<T>::operator[] used for unallocated NRSmat<T> object");
2004-03-17 04:07:21 +01:00
#endif
2010-09-08 18:27:58 +02:00
NOT_GPU(*this);
2004-03-17 04:07:21 +01:00
return v[ij];
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* determine the cumulative index or matrix element in row \f$i\f$ and column \f$j\f$
* where \f$0\leq{}i,j<N\f$
* @param[in] i row index
* @param[in] i column index
* @return cumulative index
******************************************************************************/
2006-04-06 23:45:51 +02:00
template<typename T>
2010-09-08 18:27:58 +02:00
inline T SMat_index(T i, T j) {
return (i>=j) ? i*(i+1)/2+j : j*(j+1)/2+i;
2006-04-06 23:45:51 +02:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* determine the cumulative index or matrix element in row \f$i\f$ and column \f$j\f$
* where \f$0\leq{}i,j<N\f$ for special case \f$i\geq{}j\f$
* @param[in] i row index
* @param[in] i column index
* @return cumulative index
******************************************************************************/
2006-04-07 07:00:44 +02:00
template<typename T>
2010-09-08 18:27:58 +02:00
inline T SMat_index_igej(T i, T j) {
return i*(i+1)/2+j;
2006-04-07 07:00:44 +02:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* determine the cumulative index or matrix element in row \f$i\f$ and column \f$j\f$
* where \f$0\leq{}i,j<N\f$ for special case \f$i\leq{}j\f$
* @param[in] i row index
* @param[in] i column index
* @return cumulative index
******************************************************************************/
2006-04-07 07:00:44 +02:00
template<typename T>
2010-09-08 18:27:58 +02:00
inline T SMat_index_ilej(T i, T j) {
return j*(j+1)/2+i;
2006-04-07 07:00:44 +02:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* determine the cumulative index or matrix element in row \f$i\f$ and column \f$j\f$
* where \f$1\leq{}i,j\leq{}N\f$
* @param[in] i row index
* @param[in] i column index
* @return cumulative index
******************************************************************************/
2006-04-06 23:45:51 +02:00
template<typename T>
2010-09-08 18:27:58 +02:00
inline T SMat_index_1(T i, T j) {
return (i>=j)? i*(i-1)/2+j-1 : j*(j-1)/2+i-1;
2006-04-06 23:45:51 +02:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* determine the cumulative index or matrix element in row \f$i\f$ and column \f$j\f$
* where \f$1\leq{}i,j\leq{}N\f$ for special case \f$i\geq{}j\f$
* @param[in] i row index
* @param[in] i column index
* @return cumulative index
******************************************************************************/
2006-04-07 07:00:44 +02:00
template<typename T>
2010-09-08 18:27:58 +02:00
inline T SMat_index_1igej(T i, T j) {
return i*(i-1)/2+j-1;
2006-04-07 07:00:44 +02:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* determine the cumulative index or matrix element in row \f$i\f$ and column \f$j\f$
* where \f$1\leq{}i,j\leq{}N\f$ for special case \f$i\leq{}j\f$
* @param[in] i row index
* @param[in] i column index
* @return cumulative index
******************************************************************************/
2006-04-07 07:00:44 +02:00
template<typename T>
2010-09-08 18:27:58 +02:00
inline T SMat_index_1ilej(T i, T j) {
return j*(j-1)/2+i-1;
2006-04-07 07:00:44 +02:00
}
2008-06-17 17:01:37 +02:00
//indexing for antisymmetric matrix (used by fourindex)
template<typename T>
inline T ASMat_index(T i, T j)
{
2010-09-08 18:27:58 +02:00
if(i == j) return -1;
2008-06-17 17:01:37 +02:00
return (i>j) ? i*(i-1)/2+j : j*(j-1)/2+i;
}
template<typename T>
inline T ASMat_index_1(T i, T j)
{
2010-09-08 18:27:58 +02:00
if(i == j) return -1;
2008-06-17 17:01:37 +02:00
return (i>j)? (i-2)*(i-1)/2+j-1 : (j-2)*(j-1)/2+i-1;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* determine matrix element of this symmetric matrix of general type <code>T</code>
* @param[in] i row index running from 0
* @param[in] j column index running from 0
* @return reference to the corresponding matrix element
* @see count, SMat_index, NRSMat<T>::operator[]
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline T & NRSMat<T>::operator()(const int i, const int j) {
2004-03-17 04:07:21 +01:00
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(_LA_count_check && *count != 1) laerror("T & NRSMat<T>::operator()(const int, const int) used for matrix with count > 1");
if(i<0 || i>=nn || j<0 || j>=nn) laerror("T & NRSMat<T>::operator()(const int, const int) out of range");
if(!v) laerror("T & NRSMat<T>::operator()(const int, const int) used for unallocated NRSmat<T> object");
2004-03-17 04:07:21 +01:00
#endif
2010-09-08 18:27:58 +02:00
NOT_GPU(*this);
2006-04-06 23:45:51 +02:00
return v[SMat_index(i,j)];
2004-03-17 04:07:21 +01:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* determine matrix element of this symmetric matrix of general type <code>T</code>
* @param[in] i row index running from 0
* @param[in] j column index running from 0
* @return constant reference to the corresponding matrix element
* @see count, SMat_index, NRSMat<T>::operator[]
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline const T & NRSMat<T>::operator()(const int i, const int j) const {
2004-03-17 04:07:21 +01:00
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(i<0 || i>=nn || j<0 || j>=nn) laerror("T & NRSMat<T>::operator()(const int, const int) out of range");
if(!v) laerror("T & NRSMat<T>::operator()(const int, const int) used for unallocated NRSmat<T> object");
2004-03-17 04:07:21 +01:00
#endif
2010-09-08 18:27:58 +02:00
NOT_GPU(*this);
2006-04-06 23:45:51 +02:00
return v[SMat_index(i,j)];
2004-03-17 04:07:21 +01:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* @return number of rows of this symmetric matrix of generalt type <code>T</code>
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline int NRSMat<T>::nrows() const {
2004-03-17 04:07:21 +01:00
return nn;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* @return number of columns of this symmetric matrix of generalt type <code>T</code>
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline int NRSMat<T>::ncols() const {
2004-03-17 04:07:21 +01:00
return nn;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* @return number of elements of this symmetric matrix of generalt type <code>T</code>
******************************************************************************/
2005-02-18 23:08:15 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline int NRSMat<T>::size() const {
2005-02-18 23:08:15 +01:00
return NN2;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* for this real symmetric matrix \f$A\f$, determine the
* first element with largest absolute value
* @return \f$A_{l,m}\f$ which maximizes \f$\left|A_{i,j}\right|\f$
******************************************************************************/
2005-11-20 14:46:00 +01:00
template<>
2010-09-08 18:27:58 +02:00
inline const double NRSMat<double>::amax() const {
double ret(0.0);
#ifdef CUDALA
if(location == cpu){
#endif
ret = v[cblas_idamax(NN2, v, 1) - 1];
#ifdef CUDALA
}else{
const int pozice = cublasIdamax(NN2, v, 1) - 1;
TEST_CUBLAS("cublasIdamax");//"double NRSMat<double>::amax()"
gpuget(1, sizeof(double), v + pozice, &ret);
}
#endif
return ret;
2004-03-17 04:07:21 +01:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* for this real symmetric matrix \f$A\f$, determine the
* first element with smallest absolute value
* @return \f$A_{l,m}\f$ which minimizes \f$\left|A_{i,j}\right|\f$
******************************************************************************/
2005-11-20 14:46:00 +01:00
template<>
2010-09-08 18:27:58 +02:00
inline const double NRSMat<double>::amin() const {
double ret(0.0);
#ifdef CUDALA
if(location == cpu){
#endif
// idamin seems not to be supported
double val(0.0);
int index(-1);
ret = std::numeric_limits<double>::max();
for(register int 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 = cublasIdamin(nn, v, 1) - 1;
TEST_CUBLAS("cublasIdamin");//"double NRSMat<double>::amin()"
gpuget(1, sizeof(double), v + pozice, &ret);
}
#endif
return ret;
2004-03-17 04:07:21 +01:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* for this complex symmetric matrix \f$A\f$, determine the
* first element with largest "absolute value"
* @return \f$A_{l,m}\f$ which maximizes \f$\left|\Re{}A_{i,j}\right| + \left|\Im{}A_{i,j}\right|\f$
******************************************************************************/
template<>
inline const complex<double> NRSMat< complex<double> >::amax() const{
complex<double> ret(0., 0.);
#ifdef CUDALA
if(location == cpu){
#endif
ret = v[cblas_izamax(NN2, v, 1) - 1];
#ifdef CUDALA
}else{
const int pozice = cublasIzamax(NN2, (cuDoubleComplex*)v, 1) - 1;
TEST_CUBLAS("cublasIzamax");//"complex<double> NRSMat<complex<double> >::amax()"
gpuget(1, sizeof(complex<double>), v + pozice, &ret);
}
#endif
return ret;
}
/***************************************************************************//**
* for this complex symmetric matrix \f$A\f$, determine the
* first element with smallest "absolute value"
* @return \f$A_{l,m}\f$ which minimizes \f$\left|\Re{}A_{i,j}\right| + \left|\Im{}A_{i,j}\right|\f$
******************************************************************************/
template<>
inline const complex<double> NRSMat<complex<double> >::amin() const{
complex<double> ret(0., 0.);
#ifdef CUDALA
if(location == cpu){
#endif
// izamin seems not to be supported
int index(0);
double val(0.0), min_val(0.0);
complex<double> z_val(0.0, 0.0);
min_val = std::numeric_limits<double>::max();
for(register int 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 = cublasIzamin(nn, (cuDoubleComplex*)v, 1) - 1;
TEST_CUBLAS("cublasIzamin");//"complex<double> NRSMat<complex<double> >::amin()"
gpuget(1, sizeof(complex<double>), v + pozice, &ret);
}
#endif
return ret;
}
/***************************************************************************//**
* @return pointer of general type T to the underlying data structure
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline NRSMat<T>::operator T*() {
2004-03-17 04:07:21 +01:00
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(!v) laerror("unallocated NRSMat object in NRSMat<T>::operator T*()");
2004-03-17 04:07:21 +01:00
#endif
return v;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* @return constant pointer of general type T to the underlying data structure
******************************************************************************/
2004-03-17 04:07:21 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
inline NRSMat<T>::operator const T*() const {
2004-03-17 04:07:21 +01:00
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(!v) laerror("unallocated NRSMat object in NRSMat<T>::operator const T*()");
2004-03-17 04:07:21 +01:00
#endif
return v;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* destructor for general type <code>T</code>
* @see NRSMat<T>::count, NRSMat<T>::v
******************************************************************************/
2004-03-17 17:39:07 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
NRSMat<T>::~NRSMat() {
if(!count) return;
if(--(*count) <= 0) {
if(v){
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
if(location == cpu){
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
delete[] v;
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
}else{ gpufree(v); }
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
}
delete count;
}
2004-03-17 17:39:07 +01:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* assigment operator implementing deep copy of the reference NRSMat<T> object
* @see NRSMat<T>::operator=, NRSMat<T>::copyonwrite()
******************************************************************************/
2004-03-17 17:39:07 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
NRSMat<T> & NRSMat<T>::operator|=(const NRSMat<T> &rhs) {
2010-06-25 17:28:19 +02:00
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(!rhs.v) laerror("unallocated NRSMat<T> object in NRSMat<T> & NRSMat<T>::operator|=(const NRSMat<T> &)");
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
if(this == &rhs) return *this;
*this = rhs;
this->copyonwrite();
return *this;
2004-03-17 17:39:07 +01:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* assignment operator implementing shallow copy of reference NRSMat<T> object
* @see NRSMat<T>::operator|=, NRSMat<T>::copyonwrite()
******************************************************************************/
2004-03-17 17:39:07 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
NRSMat<T> & NRSMat<T>::operator=(const NRSMat<T> & rhs) {
if(this == &rhs) return *this;
if(count)
if(--(*count) == 0){
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
if(location == cpu){
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
delete [] v;
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
}else{ gpufree(v); }
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
delete count;
}
v = rhs.v;
nn = rhs.nn;
count = rhs.count;
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
location = rhs.location;
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
if(count) (*count)++;
2004-03-17 17:39:07 +01:00
return *this;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* detach this NRSMat<T> object and create own physical copy of the data
* @see NRSMat<T>::operator|=, NRSMat<T>::copyonwrite()
******************************************************************************/
2004-03-17 17:39:07 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
void NRSMat<T>::copyonwrite() {
if(!count) laerror("calling NRSMat<T>::copyonwrite() for undefined NRSMat<T> object");
if(*count > 1){
(*count)--;
count = new int;
*count = 1;
2010-06-25 17:28:19 +02:00
T *newv;
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
if(location == cpu) {
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
newv = new T[NN2];
memcpy(newv, v, NN2*sizeof(T));
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
}else{
newv = (T *) gpualloc(NN2*sizeof(T));
if(sizeof(T)%sizeof(float) != 0) laerror("memory alignment problem in NRSMat<T>::copyonwrite()");
cublasScopy(NN2*sizeof(T)/sizeof(float), (const float *) v, 1, (float *)newv, 1);
TEST_CUBLAS("cublasScopy");//"NRSMat<T>::copyonwrite()"
}
2010-06-25 17:28:19 +02:00
#endif
v = newv;
2004-03-17 17:39:07 +01:00
}
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* resize this symmetric matrix of general type <code>T</code>
* @param[in] n requested number of rows (columns)
******************************************************************************/
2004-03-17 17:39:07 +01:00
template <typename T>
2010-09-08 18:27:58 +02:00
void NRSMat<T>::resize(const int n) {
2004-03-17 17:39:07 +01:00
#ifdef DEBUG
2010-09-08 18:27:58 +02:00
if(n < 0) laerror("illegal dimension in NRSMat<T>::resize(const int)");
2004-03-17 17:39:07 +01:00
#endif
2010-09-08 18:27:58 +02:00
if(count){
if(n == 0){
if(--(*count) <= 0) {
if(v) {
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
if(location == cpu){
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
delete[] (v);
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
}else{ gpufree(v); }
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
}
delete count;
2010-06-25 17:28:19 +02:00
}
2010-09-08 18:27:58 +02:00
count = 0;
nn = 0;
v = 0;
return;
}
if(*count > 1){
(*count)--;
count = 0;
v = 0;
nn = 0;
}
2005-02-14 01:10:07 +01:00
}
2010-09-08 18:27:58 +02:00
if(!count){
count = new int;
*count = 1;
nn = n;
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
if(location == cpu){
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
v = new T[NN2];
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
}else{ v = (T*) gpualloc(NN2*sizeof(T)); }
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
return;
}
if(n != nn){
nn = n;
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
if(location == cpu){
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
delete[] v;
v = new T[NN2];
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
}else{
gpufree(v);
v = (T*) gpualloc(NN2*sizeof(T));
}
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
}
2010-06-25 17:28:19 +02:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* perform memory transfers between CPU and GPU memory
* @param[in] dest memory destination
* @see NRSMat<T>::location, NRSMat<T>::getlocation()
******************************************************************************/
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
template<typename T>
2010-09-08 18:27:58 +02:00
void NRSMat<T>::moveto(const GPUID dest) {
if(location == dest) return;
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
CPU_GPU(location,dest);
location = dest;
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
if(v && !count) laerror("internal inconsistency of reference counting 1");
if(!count) return;
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
if(v && *count == 0) laerror("internal inconsistency of reference counting 2");
if(!v) return;
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
T *vold = v;
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
if(dest == cpu){ //moving from GPU to CPU
v = new T[NN2];
gpuget(NN2, sizeof(T), vold, v);
if(*count == 1) gpufree(vold);
else {--(*count); count = new int(1);}
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
}else{ //moving from CPU to GPU
2004-03-17 17:39:07 +01:00
2010-09-08 18:27:58 +02:00
v = (T *) gpualloc(NN2*sizeof(T));
gpuput(NN2, sizeof(T), vold, v);
if(*count == 1) delete[] vold;
else {--(*count); count = new int(1);}
}
}
#endif
2004-03-17 17:39:07 +01:00
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* complexify a given matrix \f$A\f$ of general type <code>T</code>
* @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$
******************************************************************************/
2006-04-01 06:48:01 +02:00
template<typename T>
2010-09-08 18:27:58 +02:00
NRSMat<complex<T> > complexify(const NRSMat<T> &rhs) {
NOT_GPU(rhs);
NRSMat<complex<T> > r(rhs.nrows());
for(register int i = 0; i<rhs.nrows(); ++i)
for(register int j = 0; j<=i; ++j) r(i,j) = rhs(i,j);
return r;
2006-04-01 06:48:01 +02:00
}
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* 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<complex<double> > complexify(const NRSMat<double> &rhs) {
NRSMat<complex<double> > 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<complex<double> > complexify(const NRSMat<double> &)"
}
#endif
return r;
}
*/
/***************************************************************************//**
* output operator
* @param[in,out] s output stream
* @param[in] x NRSMat<T> matrix to be printed out
* @return modified stream
******************************************************************************/
2006-10-21 17:32:53 +02:00
template <typename T>
2010-09-08 18:27:58 +02:00
std::ostream& operator<<(std::ostream &s, const NRSMat<T> &x) {
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
if(x.getlocation() == cpu){
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
int i,j,n;
n = x.nrows();
s << n << ' ' << n << '\n';
for(i = 0;i<n;i++){
for(j = 0; j<n;j++) s << (typename LA_traits_io<T>::IOtype)x(i,j) << (j == n-1 ? '\n' : ' ');
}
return s;
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
}else{
NRSMat<T> tmp = x;
tmp.moveto(cpu);
return s<<tmp;
}
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
}
2006-10-21 17:32:53 +02:00
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* input operator
* @param[in,out] s input stream
* @param[in] x NRSMat<T> matrix for storing the input
* @return modified stream
******************************************************************************/
2006-10-21 17:32:53 +02:00
template <typename T>
2010-09-08 18:27:58 +02:00
std::istream& operator>>(std::istream &s, NRSMat<T> &x) {
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
if(x.getlocation() == cpu){
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
int i,j,n,m;
s >> n >> m;
if(n!=m) laerror("input symmetric matrix not square");
x.resize(n);
2006-10-21 17:32:53 +02:00
typename LA_traits_io<T>::IOtype tmp;
2010-09-08 18:27:58 +02:00
for(i = 0;i<n;i++) for(j = 0; j<m;j++) {s>>tmp; x(i,j)=tmp;}
return s;
2010-06-25 17:28:19 +02:00
#ifdef CUDALA
2010-09-08 18:27:58 +02:00
}else{
NRSMat<T> tmp;
tmp.moveto(cpu);
s >> tmp;
tmp.moveto(x.getlocation());
x = tmp;
return s;
}
2010-06-25 17:28:19 +02:00
#endif
2010-09-08 18:27:58 +02:00
}
2006-10-21 17:32:53 +02:00
2004-03-17 04:07:21 +01:00
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* generate operators relating NRSMat<T> objects and scalars
* corresponding macro is defined in vec.h
******************************************************************************/
2004-03-17 04:07:21 +01:00
NRVECMAT_OPER(SMat,+)
NRVECMAT_OPER(SMat,-)
NRVECMAT_OPER(SMat,*)
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* generate operators relating in general two NRSMat<T> objects
* corresponding macro is defined in vec.h
******************************************************************************/
2004-03-17 04:07:21 +01:00
NRVECMAT_OPER2(SMat,+)
NRVECMAT_OPER2(SMat,-)
2010-09-08 18:27:58 +02:00
/***************************************************************************//**
* class implementing NRSMat<T> funcitonality with indices running from 1
* allmost all function members are inherited, only constructors are given explicitly
******************************************************************************/
2006-04-06 23:45:51 +02:00
template<typename T>
class NRSMat_from1 : public NRSMat<T> {
public:
2010-09-08 18:27:58 +02:00
NRSMat_from1(): NRSMat<T>() {};
explicit NRSMat_from1(const int n): NRSMat<T>(n) {};
2006-04-06 23:45:51 +02:00
NRSMat_from1(const NRSMat<T> &rhs): NRSMat<T>(rhs) {}; //be able to convert the parent class transparently to this
2010-09-08 18:27:58 +02:00
NRSMat_from1(const T &a, const int n): NRSMat<T>(a,n) {};
NRSMat_from1(const T *a, const int n): NRSMat<T>(a,n) {};
explicit NRSMat_from1(const NRMat<T> &rhs): NRSMat<T>(rhs) {};
explicit NRSMat_from1(const NRVec<T> &rhs, const int n): NRSMat<T>(rhs,n) {};
inline const T& operator() (const int i, const int j) const {
#ifdef DEBUG
if(i<=0||j<=0||i>NRSMat<T>::nn||j>NRSMat<T>::nn) laerror("index in const T& NRSMat<T>::operator() (const int, const int) out of range");
#endif
2006-07-29 21:46:41 +02:00
return NRSMat<T>::v[SMat_index_1(i,j)];
2010-09-08 18:27:58 +02:00
}
inline T& operator() (const int i, const int j){
#ifdef DEBUG
if(i<=0||j<=0||i>NRSMat<T>::nn||j>NRSMat<T>::nn) laerror("index in T& NRSMat<T>::operator() (const int, const int) out of range");
#endif
2006-07-29 21:46:41 +02:00
return NRSMat<T>::v[SMat_index_1(i,j)];
2010-09-08 18:27:58 +02:00
}
2006-04-06 23:45:51 +02:00
};
2009-11-12 22:01:19 +01:00
}//namespace
2004-03-17 04:07:21 +01:00
#endif /* _LA_SMAT_H_ */