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/>.
2010-09-08 18:27:58 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
# ifndef _LA_VEC_H_
# define _LA_VEC_H_
2005-02-14 01:10:07 +01:00
# include "la_traits.h"
2023-11-18 15:15:32 +01:00
# include "vecmat3.h"
2022-02-18 19:03:19 +01:00
# include <list>
2005-02-14 01:10:07 +01:00
2023-11-18 15:15:32 +01:00
using namespace LA_Vecmat3 ;
2009-11-12 22:01:19 +01:00
namespace LA {
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* forward declarations
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template < typename T > void lawritemat ( FILE * file , const T * a , int r , int c ,
const char * form0 , int nodim , int modulo , int issym ) ;
2004-03-17 04:07:21 +01:00
2021-05-13 16:45:10 +02:00
template < typename T > class NRPerm ;
2021-05-14 17:39:22 +02:00
template < typename T > class CyclePerm ;
2021-05-13 16:45:10 +02:00
2021-06-30 14:54:35 +02:00
/***************************************************************************/ /**
* auxiliary macro to avoid compilation errors for some types
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template < typename T >
2021-10-07 13:57:19 +02:00
inline typename LA_traits < T > : : normtype MYABS ( const T & x ) { return std : : abs ( x ) ; }
2021-06-30 14:54:35 +02:00
template < > inline unsigned char MYABS ( const unsigned char & x ) { return x ; }
template < > inline unsigned short MYABS ( const unsigned short & x ) { return x ; }
template < > inline unsigned int MYABS ( const unsigned int & x ) { return x ; }
template < > inline unsigned long MYABS ( const unsigned long & x ) { return x ; }
template < > inline unsigned long long MYABS ( const unsigned long long & x ) { return x ; }
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* static constants used in several cblas - routines
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2021-04-21 15:04:37 +02:00
const static std : : complex < double > CONE = 1.0 , CMONE = - 1.0 , CZERO = 0.0 ;
2010-06-25 17:28:19 +02:00
# ifdef CUDALA
const static cuDoubleComplex CUONE = { 1. , 0. } , CUMONE = { - 1. , 0. } , CUZERO = { 0. , 0. } ;
# endif
2004-03-17 04:07:21 +01:00
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* macros to construct binary operators + , - , * , from + = , - = , * =
* for 3 cases : X + a , a + X , X + Y
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
# define NRVECMAT_OPER(E,X) \
template < class T > \
inline const NR # # E < T > NR # # E < T > : : operator X ( const T & a ) const \
{ return NR # # E ( * this ) X # # = a ; } \
\
template < class T > \
inline const NR # # E < T > operator X ( const T & a , const NR # # E < T > & rhs ) \
{ return NR # # E < T > ( rhs ) X # # = a ; }
# define NRVECMAT_OPER2(E,X) \
template < class T > \
2010-06-25 17:28:19 +02:00
inline const NR # # E < T > NR # # E < T > : : operator X ( const NR # # E < T > & a ) const \
2004-03-17 04:07:21 +01:00
{ return NR # # E ( * this ) X # # = a ; }
2004-03-17 17:39:07 +01:00
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* \ brief NRVec < T > class template implementing the vector interface
* @ see NRMat < T > , NRSMat < T >
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
template < typename T >
class NRVec {
protected :
2010-09-08 18:27:58 +02:00
int nn ; //!< size of the vector
T * v ; //!< 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 ; //!< determines the memory address space of this object (CPU/GPU)
2010-06-25 17:28:19 +02:00
# endif
2004-03-17 04:07:21 +01:00
public :
friend class NRSMat < T > ;
friend class NRMat < T > ;
2021-04-21 15:04:37 +02:00
template < typename U > friend NRVec < std : : complex < U > > complexify ( const NRVec < U > & ) ;
2004-03-17 04:07:21 +01:00
2010-09-08 18:27:58 +02:00
typedef T ROWTYPE ;
//! standard destructor
~ NRVec ( ) ;
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* inlined constructor creating zero vector of general type < code > T < / code >
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
inline NRVec ( ) : nn ( 0 ) , v ( 0 ) , count ( 0 ) {
# ifdef CUDALA
location = DEFAULT_LOC ;
# endif
} ;
/***************************************************************************/ /**
* Explicit inlined constructor creating vector of given size and location .
* Because of performance reasons , no incialization is done .
* @ param [ in ] n vector size ( count of elements )
* @ param [ in ] loc location of the underlying data ( CPU / GPU )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
explicit inline NRVec ( const int n , const GPUID loc = undefined ) : nn ( n ) , count ( new int ( 1 ) ) {
# ifdef CUDALA
location = ( loc = = undefined ) ? DEFAULT_LOC : loc ;
if ( location = = cpu ) {
# endif
v = new T [ n ] ;
# ifdef CUDALA
} else {
v = ( T * ) gpualloc ( n * sizeof ( T ) ) ;
}
# endif
} ;
//! inlined constructor creating vector of given size filled with prescribed value
2004-03-17 04:07:21 +01:00
inline NRVec ( const T & a , const int n ) ;
2021-10-27 23:24:41 +02:00
//! inlined constructor creating vector froman array
template < int SIZE > inline NRVec ( const T ( & a ) [ SIZE ] ) ;
2010-09-08 18:27:58 +02:00
//! inlined constructor creating vector of given size filled with data located at given memory location
2006-09-12 01:07:22 +02:00
inline NRVec ( const T * a , const int n ) ;
2023-11-18 15:15:32 +01:00
inline NRVec ( const Vec3 < T > & rhs ) : NRVec ( & rhs [ 0 ] , 3 ) { } ;
2010-09-08 18:27:58 +02:00
//! inlined constructor creating vector of given size filled with data located at given memory location
2006-09-12 01:07:22 +02:00
inline NRVec ( T * a , const int n , bool skeleton ) ;
2010-09-08 18:27:58 +02:00
//! inlined copy constructor
2004-03-17 04:07:21 +01:00
inline NRVec ( const NRVec & rhs ) ;
2010-09-08 18:27:58 +02:00
2022-02-18 19:03:19 +01:00
//! constructor from std::list
2022-06-09 20:51:09 +02:00
explicit NRVec ( const std : : list < T > l ) ;
2022-02-18 19:03:19 +01:00
2010-09-08 18:27:58 +02:00
//! complexifying constructor
NRVec ( const typename LA_traits_complex < T > : : NRVec_Noncomplex_type & rhs , bool imagpart = false ) ; //construct complex from real
//! explicit inlined constructor converting symmetric matrix into a vector
2004-03-17 04:07:21 +01:00
inline explicit NRVec ( const NRSMat < T > & S ) ;
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef MATPTR
explicit NRVec ( const NRMat < T > & rhs ) : NRVec ( & rhs [ 0 ] [ 0 ] , rhs . nrows ( ) * rhs . ncols ( ) ) { } ;
# else
explicit NRVec ( const NRMat < T > & rhs ) ;
# endif
/***************************************************************************/ /**
* routines for CUDA related stuff
* \ li < code > getlocation ( ) < / code > gets the protected data member location
* \ li < code > moveto ( const GPUID ) < / code > moves underlying data between CPU / GPU memory
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# 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
//! create separate copy of the data corresponding to this vector
2013-11-04 15:56:39 +01:00
void copyonwrite ( bool detachonly = false ) ;
2010-09-08 18:27:58 +02:00
//! purge this vector
2021-05-24 18:45:58 +02:00
void clear ( ) { copyonwrite ( LA_traits < T > : : is_plaindata ( ) ) ; LA_traits < T > : : clear ( v , nn ) ; } ;
2010-09-08 18:27:58 +02:00
//! assignment operator assigns given vector
NRVec & operator = ( const NRVec & rhs ) ;
//! assigment operator assigns given scalar to each element of this vector
NRVec & operator = ( const T & a ) ;
//! fills in this vector with pseudo-random numbers generated using 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
//! perform deep-copy of given vector
NRVec & operator | = ( const NRVec & rhs ) ;
2022-06-23 19:34:17 +02:00
//! extract specified subvector
const NRVec subvector ( const int from , const int to ) const ;
2023-07-26 21:18:57 +02:00
const NRVec subvector ( const NRVec < int > & selection ) const ;
2022-06-23 19:34:17 +02:00
//! store given vector at given position into the current vector
void storesubvector ( const int from , const NRVec & rhs ) ;
2023-07-26 21:18:57 +02:00
void storesubvector ( const NRVec < int > & selection , const NRVec & rhs ) ;
2022-06-23 19:34:17 +02:00
2010-09-08 18:27:58 +02:00
//! relational operators
2021-06-24 17:08:55 +02:00
const bool operator ! = ( const NRVec & rhs ) const
{
if ( nn ! = rhs . nn ) return 1 ;
if ( LA_traits < T > : : is_plaindata ( ) ) return LA_traits < T > : : gencmp ( v , rhs . v , nn ) ;
else
{
for ( int i = 0 ; i < nn ; + + i ) if ( v [ i ] ! = rhs . v [ i ] ) return 1 ;
return 0 ;
}
}
2005-02-14 01:10:07 +01:00
const bool operator = = ( const NRVec & rhs ) const { return ! ( * this ! = rhs ) ; } ;
2005-09-06 17:55:07 +02:00
const bool operator > ( const NRVec & rhs ) const ;
const bool operator < ( const NRVec & rhs ) const ;
const bool operator > = ( const NRVec & rhs ) const { return ! ( * this < rhs ) ; } ;
const bool operator < = ( const NRVec & rhs ) const { return ! ( * this > rhs ) ; } ;
2010-09-08 18:27:58 +02:00
//! unary minus
2004-03-17 04:07:21 +01:00
const NRVec operator - ( ) const ;
2010-09-08 18:27:58 +02:00
//! bunch of vector-vector arithmetic operators defined element-wise
inline NRVec & operator + = ( const NRVec & rhs ) ;
inline NRVec & operator - = ( const NRVec & rhs ) ;
inline NRVec & operator * = ( const NRVec & rhs ) ;
inline NRVec & operator / = ( const NRVec & rhs ) ;
2004-03-17 04:07:21 +01:00
inline const NRVec operator + ( const NRVec & rhs ) const ;
inline const NRVec operator - ( const NRVec & rhs ) const ;
2010-09-08 18:27:58 +02:00
//! bunch of scalar-vector arithmetic operators defined element-wise
inline NRVec & operator + = ( const T & a ) ;
inline NRVec & operator - = ( const T & a ) ;
inline NRVec & operator * = ( const T & a ) ;
2021-06-10 17:44:54 +02:00
inline NRVec & operator / = ( const T & a ) ;
2010-09-08 18:27:58 +02:00
2004-03-17 04:07:21 +01:00
inline const NRVec operator + ( const T & a ) const ;
inline const NRVec operator - ( const T & a ) const ;
inline const NRVec operator * ( const T & a ) const ;
2021-06-10 17:44:54 +02:00
inline const NRVec operator / ( const T & a ) const ;
2021-10-22 13:28:13 +02:00
//!concatenate vectors
NRVec concat ( const NRVec & rhs ) const
{
if ( nn = = 0 ) return rhs ;
if ( rhs . nn = = 0 ) return * this ;
NRVec r ( nn + rhs . nn ) ;
for ( int i = 0 ; i < nn ; + + i ) r [ i ] = ( * this ) [ i ] ;
for ( int i = 0 ; i < rhs . nn ; + + i ) r [ nn + i ] = rhs [ i ] ;
return r ;
}
2010-09-08 18:27:58 +02:00
2024-01-16 22:03:46 +01:00
NRVec concatscaled ( const NRVec & rhs , const T alpha = 1 ) const
{
if ( nn = = 0 ) return rhs ;
if ( rhs . nn = = 0 ) return * this ;
NRVec r ( nn + rhs . nn ) ;
for ( int i = 0 ; i < nn ; + + i ) r [ i ] = ( * this ) [ i ] ;
for ( int i = 0 ; i < rhs . nn ; + + i ) r [ nn + i ] = rhs [ i ] * alpha ;
return r ;
}
2022-06-09 13:56:42 +02:00
//!concatenate vector into *this
void concatme ( const NRVec & rhs )
{
2022-06-21 17:33:16 +02:00
NOT_GPU ( * this ) ;
2022-06-09 13:56:42 +02:00
if ( rhs . nn = = 0 ) return ;
2022-06-21 17:33:16 +02:00
int nnold = nn ;
2022-06-09 13:56:42 +02:00
resize ( nn + rhs . nn , true ) ;
2022-06-21 17:33:16 +02:00
for ( int i = 0 ; i < rhs . nn ; + + i ) v [ nnold + i ] = rhs [ i ] ;
2022-06-09 13:56:42 +02:00
}
2022-08-10 16:25:17 +02:00
void concatmescaled ( const NRVec & rhs , const T alpha = 1 )
{
NOT_GPU ( * this ) ;
if ( rhs . nn = = 0 ) return ;
int nnold = nn ;
resize ( nn + rhs . nn , true ) ;
for ( int i = 0 ; i < rhs . nn ; + + i ) v [ nnold + i ] = rhs [ i ] * alpha ;
}
2022-06-09 13:56:42 +02:00
void append ( const T & a ) //not efficient if done repeatedly
{
2022-06-21 17:33:16 +02:00
NOT_GPU ( * this ) ;
int nnold = nn ;
2022-06-09 13:56:42 +02:00
resize ( nn + 1 , true ) ;
2022-06-21 17:33:16 +02:00
v [ nnold ] = a ;
2022-06-09 13:56:42 +02:00
}
2023-03-17 16:04:41 +01:00
void prepend ( const T & a ) //not efficient if done repeatedly
{
NOT_GPU ( * this ) ;
int nnold = nn ;
resize ( nn + 1 , true , true ) ;
v [ 0 ] = a ;
}
2010-09-08 18:27:58 +02:00
//! determine the actual value of the reference counter
inline int getcount ( ) const { return count ? * count : 0 ; }
//! compute the Euclidean inner product (with conjugation in complex case)
inline const T operator * ( const NRVec & rhs ) const ;
inline const T dot ( const NRVec & rhs ) const { return * this * rhs ; } ;
//! compute the Euclidean inner product (with conjugation in complex case) with a stride-vector
inline const T dot ( const T * a , const int stride = 1 ) const ;
2005-02-18 23:08:15 +01:00
void gemv ( const T beta , const NRMat < T > & a , const char trans , const T alpha , const NRVec & x ) ;
2010-09-08 18:27:58 +02:00
void gemv ( const T beta , const NRSMat < T > & a , const char trans /**< just for compatibility reasons */ , const T alpha , const NRVec & x ) ;
void gemv ( const T beta , const SparseMat < T > & a , const char trans , const T alpha , const NRVec & x , const bool treat_as_symmetric = false ) ;
void gemv ( const typename LA_traits_complex < T > : : Component_type beta ,
const typename LA_traits_complex < T > : : NRMat_Noncomplex_type & a ,
const char trans ,
const typename LA_traits_complex < T > : : Component_type alpha ,
const NRVec & x ) ;
void gemv ( const typename LA_traits_complex < T > : : Component_type beta ,
const typename LA_traits_complex < T > : : NRSMat_Noncomplex_type & a ,
const char trans ,
const typename LA_traits_complex < T > : : Component_type alpha , const NRVec & x ) ;
//! multiply given matrix with this vector from left
const NRVec operator * ( const NRMat < T > & mat ) const {
SAME_LOC ( * this , mat ) ;
NRVec < T > result ( mat . ncols ( ) , mat . getlocation ( ) ) ;
result . gemv ( ( T ) 0 , mat , ' t ' , ( T ) 1 , * this ) ;
return result ;
} ;
//! multiply given symmetric matrix in packed form with this vector from left
const NRVec operator * ( const NRSMat < T > & mat ) const {
SAME_LOC ( * this , mat ) ;
NRVec < T > result ( mat . ncols ( ) , mat . getlocation ( ) ) ;
result . gemv ( ( T ) 0 , mat , ' t ' , ( T ) 1 , * this ) ;
return result ;
} ;
//! multiply given sparse matrix with this vector from left
const NRVec operator * ( const SparseMat < T > & mat ) const {
NOT_GPU ( * this ) ;
NRVec < T > result ( mat . ncols ( ) ) ;
result . gemv ( ( T ) 0 , mat , ' t ' , ( T ) 1 , * this ) ;
return result ;
} ;
//! compute the outer product of two vectors
const NRMat < T > otimes ( const NRVec < T > & rhs , const bool conjugate = false , const T & scale = 1 ) const ;
//! opeartor for outer product computation
inline const NRMat < T > operator | ( const NRVec < T > & rhs ) const { return otimes ( rhs , true ) ; } ;
//! compute the sum of the vector elements
inline const T sum ( ) const {
2021-05-14 17:39:22 +02:00
T sum ( v [ 0 ] ) ;
for ( register int i = 1 ; i < nn ; i + + ) { sum + = v [ i ] ; }
2010-09-08 18:27:58 +02:00
return sum ;
} ;
2024-01-18 14:31:00 +01:00
//! compute the sum of squares the vector elements
inline const T sumsqr ( ) const {
T sum ( v [ 0 ] ) ;
for ( register int i = 1 ; i < nn ; i + + ) { sum + = v [ i ] * v [ i ] ; }
return sum ;
} ;
2021-05-14 17:39:22 +02:00
//! compute the product of the vector elements
inline const T prod ( ) const {
T prod ( v [ 0 ] ) ;
for ( register int i = 1 ; i < nn ; i + + ) { prod * = v [ i ] ; }
return prod ;
} ;
2021-05-13 16:45:10 +02:00
//! permute vector elements
2021-05-19 22:29:47 +02:00
const NRVec permuted ( const NRPerm < int > & p , const bool inverse = false ) const ;
void permuteme ( const CyclePerm < int > & p ) ; //in place
2023-07-30 15:26:38 +02:00
void permuteme ( const NRPerm < int > & p , const bool inverse = false )
{
NRVec < T > tmp = permuted ( p , inverse ) ;
copyonwrite ( ) ;
for ( int i = 0 ; i < size ( ) ; + + i ) v [ i ] = tmp . v [ i ] ;
}
2021-05-13 16:45:10 +02:00
2010-09-08 18:27:58 +02:00
//! compute the sum of the absolute values of the elements of this vector
inline const typename LA_traits < T > : : normtype asum ( ) const ;
//! indexing operator - index running from zero
2004-03-17 04:07:21 +01:00
inline T & operator [ ] ( const int i ) ;
inline const T & operator [ ] ( const int i ) const ;
2010-09-08 18:27:58 +02:00
//! dummy routine
inline void setcoldim ( int i ) { } ;
//! get the pointer to the underlying data structure
inline operator T * ( ) ;
2021-04-21 15:04:37 +02:00
2010-09-08 18:27:58 +02:00
//! get the constant pointer to the underlying data structure
inline operator const T * ( ) const ;
//! add up a scalar multiple of a given vector
void axpy ( const T alpha , const NRVec & x ) ;
//! add up a scalar multiple of a given vector with given stride
void axpy ( const T alpha , const T * x , const int stride = 1 ) ;
//! determine the number of elements
2004-03-17 04:07:21 +01:00
inline int size ( ) const ;
2010-09-08 18:27:58 +02:00
2021-06-09 15:33:24 +02:00
//! resize the current vector, optionally preserving data
2023-03-17 16:04:41 +01:00
void resize ( const int n , const bool preserve = false , const bool preserve_at_end = false ) ;
2010-09-08 18:27:58 +02:00
2011-01-18 15:37:05 +01:00
//!deallocate the current vector
void dealloc ( void ) { resize ( 0 ) ; }
2010-09-08 18:27:58 +02:00
//! determine the norm of this vector
2022-06-15 14:42:19 +02:00
inline const typename LA_traits < T > : : normtype norm ( int length = - 1 , int offset = 0 , int stride = 1 ) const ;
2010-09-08 18:27:58 +02:00
//! normalize this vector and optionally save the norm
NRVec & normalize ( typename LA_traits < T > : : normtype * norm = 0 ) ;
//! get normalized copy of this vector
2004-03-17 04:07:21 +01:00
inline const NRVec unitvector ( ) const ;
2010-09-08 18:27:58 +02:00
2021-10-28 20:17:32 +02:00
//! find an element by value with threshold, first from left
const int find ( const T & val ) const ;
const int findthr ( const T & val , const typename LA_traits < T > : : normtype & thr = 0 ) const ;
2010-09-08 18:27:58 +02:00
//! determine the maximal element (in the absolute value) of this vector
inline const T amax ( ) const ;
//! determine the minimal element (in the absolute value) of this vector
inline const T amin ( ) const ;
2021-05-19 22:29:47 +02:00
//! determine the maximal element of this vector
const T max ( ) const ;
//! determine the minimal element of this vector
const T min ( ) const ;
2010-09-08 18:27:58 +02:00
//! routine for formatted output
2004-03-17 04:07:21 +01:00
void fprintf ( FILE * f , const char * format , const int modulo ) const ;
2010-09-08 18:27:58 +02:00
//! routine for unformatted output
void put ( int fd , bool dimensions = 1 , bool transp = 0 ) const ;
//! routine for formatted input
2004-03-17 04:07:21 +01:00
void fscanf ( FILE * f , const char * format ) ;
2010-09-08 18:27:58 +02:00
//! routine for unformatted input
void get ( int fd , bool dimensions = 1 , bool transp = 0 ) ;
//! constructor creating vector from sparse matrix
explicit NRVec ( const SparseMat < T > & rhs ) ;
//! routine for compatibility with sparse types
inline void simplify ( ) { } ;
//! determine whether the i<sup>th</sup> element is bigger than the j<sup>th</sup> element
bool bigger ( int i , int j ) const {
NOT_GPU ( * this ) ;
return LA_traits < T > : : bigger ( v [ i ] , v [ j ] ) ;
} ;
//! determine whether the i<sup>th</sup> element is bigger than the j<sup>th</sup> element
bool smaller ( int i , int j ) const {
NOT_GPU ( * this ) ;
return LA_traits < T > : : smaller ( v [ i ] , v [ j ] ) ;
} ;
//! swap the i<sup>th</sup> and j<sup>th</sup> element
void swap ( int i , int j ) {
const T tmp ( v [ i ] ) ;
v [ i ] = v [ j ] ;
v [ j ] = tmp ;
} ;
//! sort by default in ascending order and return the parity of corresponding permutation resulting to this order
2023-07-30 11:00:41 +02:00
int sort ( int direction = 0 , int from = 0 , int to = - 1 , int * perm = NULL , bool stable = false ) ;
int sort ( int direction , NRPerm < int > & perm , bool stable = false ) ;
2010-09-08 18:27:58 +02:00
//! apply given function to each element
NRVec & call_on_me ( T ( * _F ) ( const T & ) ) {
NOT_GPU ( * this ) ;
copyonwrite ( ) ;
for ( int i = 0 ; i < nn ; + + i ) v [ i ] = _F ( v [ i ] ) ;
return * this ;
} ;
2021-06-29 14:39:04 +02:00
void swap ( NRVec & rhs ) //more efficient swap than via tmp and constructors and operator=
{
int tmpnn = nn ; nn = rhs . nn ; rhs . nn = tmpnn ;
T * tmpv = v ; v = rhs . v ; rhs . v = tmpv ;
int * tmpcount = count ; count = rhs . count ; rhs . count = tmpcount ;
# ifdef CUDALA
GPUID tmplocation = location ; location = rhs . location ; rhs . location = tmplocation ;
# endif
}
2021-06-30 14:54:35 +02:00
2021-11-13 19:00:46 +01:00
NRVec < typename LA_traits < T > : : normtype > diffabs ( const NRVec & rhs ) const ; //difference of absolute values
NRVec < typename LA_traits < T > : : normtype > abs ( ) const ; //element-wise absolute values
2004-03-17 04:07:21 +01:00
} ;
2005-02-18 23:08:15 +01:00
2010-06-25 17:28:19 +02:00
2021-05-13 14:16:05 +02:00
/***************************************************************************/ /**
* implements \ c NRVec < T > functionality with indexing from 1
* all possible constructors have to be given explicitly , other stuff is inherited
* with exception of the operator ( ) which differs
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template < typename T >
class NRVec_from1 : public NRVec < T > {
public :
NRVec_from1 ( ) : NRVec < T > ( ) { } ;
2021-10-28 20:44:05 +02:00
template < int SIZE > NRVec_from1 ( const T ( & a ) [ SIZE ] ) : NRVec < T > ( a ) { } ;
2021-05-13 14:16:05 +02:00
explicit NRVec_from1 ( const int n ) : NRVec < T > ( n ) { } ;
NRVec_from1 ( const NRVec < T > & rhs ) : NRVec < T > ( rhs ) { } ; //!< be able to convert the parent class transparently to this
NRVec_from1 ( const T & a , const int n ) : NRVec < T > ( a , n ) { } ;
NRVec_from1 ( const T * a , const int n ) : NRVec < T > ( a , n ) { } ;
inline const T & operator [ ] ( const int i ) const ;
inline T & operator [ ] ( const int i ) ;
} ;
2021-06-04 15:21:35 +02:00
2021-05-13 16:45:10 +02:00
} //namespace
2021-06-04 15:21:35 +02:00
//due to mutual includes this has to be after full class declaration
# include "mat.h"
# include "smat.h"
# include "sparsemat.h"
# include "sparsesmat.h"
2022-06-09 21:36:42 +02:00
# include "qsort.h"
2021-06-04 15:21:35 +02:00
2021-05-13 16:45:10 +02:00
//needs NRVec_from1
# include "permutation.h"
namespace LA {
2022-06-09 21:36:42 +02:00
template < typename T >
2023-07-30 11:00:41 +02:00
int NRVec < T > : : sort ( int direction , int from , int to , int * perm , bool stable ) {
2022-06-09 21:36:42 +02:00
NOT_GPU ( * this ) ;
copyonwrite ( ) ;
if ( to = = - 1 ) to = nn - 1 ;
2023-07-30 11:00:41 +02:00
if ( stable )
{
if ( direction ) return memqsortstable < 1 , NRVec < T > , int , int > ( * this , perm , from , to ) ;
else return memqsortstable < 0 , NRVec < T > , int , int > ( * this , perm , from , to ) ;
}
else
{
if ( direction ) return memqsort < 1 , NRVec < T > , int , int > ( * this , perm , from , to ) ;
else return memqsort < 0 , NRVec < T > , int , int > ( * this , perm , from , to ) ;
}
2022-06-09 21:36:42 +02:00
}
template < typename T >
2023-07-30 11:00:41 +02:00
int NRVec < T > : : sort ( int direction , NRPerm < int > & perm , bool stable )
2022-06-09 21:36:42 +02:00
{
if ( nn ! = perm . size ( ) ) laerror ( " incompatible vector and permutation " ) ;
perm . identity ( ) ;
2023-07-30 11:00:41 +02:00
int r = sort ( direction , 0 , nn - 1 , & perm [ 1 ] , stable ) ;
2022-06-09 21:36:42 +02:00
return r ;
}
2021-05-13 14:16:05 +02:00
/***************************************************************************/ /**
* indexing operator giving the element at given position with range checking in
* the DEBUG mode
* @ param [ in ] i position of the required vector element ( starting from 0 )
* @ return reference to the requested element
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template < typename T >
inline T & NRVec_from1 < T > : : operator [ ] ( const int i ) {
# ifdef DEBUG
if ( _LA_count_check & & * NRVec < T > : : count ! = 1 ) laerror ( " possible use of NRVec[] with count>1 as l-value " ) ;
if ( i < 1 | | i > NRVec < T > : : nn ) laerror ( " out of range " ) ;
if ( ! NRVec < T > : : v ) laerror ( " unallocated NRVec " ) ;
# endif
NOT_GPU ( * this ) ;
return NRVec < T > : : v [ i - 1 ] ;
}
/***************************************************************************/ /**
* indexing operator giving the element at given position with range checking in
* the DEBUG mode
* @ param [ in ] i position of the required vector element ( starting from 0 )
* @ return constant reference to the requested element
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template < typename T >
inline const T & NRVec_from1 < T > : : operator [ ] ( const int i ) const {
# ifdef DEBUG
if ( i < 1 | | i > NRVec < T > : : nn ) laerror ( " out of range " ) ;
if ( ! NRVec < T > : : v ) laerror ( " unallocated NRVec " ) ;
# endif
NOT_GPU ( * this ) ;
return NRVec < T > : : v [ i - 1 ] ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* output operator
* @ param [ in , out ] s output stream
* @ param [ in ] x vector of general type intended for output
* @ 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 NRVec < 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
const int n = x . size ( ) ;
s < < n < < std : : endl ;
for ( register int i = 0 ; i < n ; i + + ) {
s < < ( typename LA_traits_io < T > : : IOtype ) x [ i ] < < ( i = = n - 1 ? ' \n ' : ' ' ) ;
}
return s ;
2010-06-25 17:28:19 +02:00
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
} else {
NRVec < T > tmp ( x ) ;
tmp . moveto ( cpu ) ;
return s < < tmp ;
}
2010-06-25 17:28:19 +02:00
# endif
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 vector of general type intended for 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 , NRVec < 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 , n ;
s > > n ;
x . resize ( n ) ;
typename LA_traits_io < T > : : IOtype tmp ;
for ( i = 0 ; i < n ; i + + ) {
s > > tmp ;
x [ i ] = tmp ;
}
return s ;
2010-06-25 17:28:19 +02:00
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
} else {
NRVec < T > tmp ;
tmp . moveto ( cpu ) ;
s > > tmp ;
tmp . moveto ( x . getlocation ( ) ) ;
x = tmp ;
return s ;
}
2010-06-25 17:28:19 +02:00
# endif
2006-10-21 17:32:53 +02:00
}
2004-03-17 04:07:21 +01:00
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* inline constructor creating vector of given size filled with prescribed value
* @ param [ in ] a value to be assigned to all vector elements
* @ param [ in ] n required vector size
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline NRVec < T > : : NRVec ( const T & a , const int n ) : nn ( n ) , count ( new int ) {
2004-03-17 04:07:21 +01:00
* count = 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 [ n ] ;
2021-10-28 20:17:32 +02:00
if ( ! LA_traits < T > : : is_plaindata ( ) | | a ! = ( T ) 0 ) {
for ( register int i = 0 ; i < n ; i + + ) v [ i ] = a ;
} else {
memset ( v , 0 , nn * sizeof ( T ) ) ;
}
2010-06-25 17:28:19 +02:00
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
} else {
v = ( T * ) gpualloc ( n * sizeof ( T ) ) ;
2021-10-28 20:17:32 +02:00
if ( ! LA_traits < T > : : is_plaindata ( ) ) laerror ( " only implemented for plain data " ) ;
2010-09-08 18:27:58 +02:00
smart_gpu_set ( n , a , v ) ;
2010-06-25 17:28:19 +02:00
}
# endif
2004-03-17 04:07:21 +01:00
}
2021-10-27 23:24:41 +02:00
/***************************************************************************/ /**
* inline constructor creating vector from an array
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template < typename T > template < int SIZE >
inline NRVec < T > : : NRVec ( const T ( & a ) [ SIZE ] ) : count ( new int ) {
nn = SIZE ;
* count = 1 ;
# ifdef CUDALA
location = DEFAULT_LOC ;
if ( location = = cpu ) {
# endif
v = new T [ nn ] ;
if ( LA_traits < T > : : is_plaindata ( ) ) memcpy ( v , a , nn * sizeof ( T ) ) ;
else for ( int i = 0 ; i < nn ; i + + ) v [ i ] = a [ i ] ;
# ifdef CUDALA
} else {
v = ( T * ) gpualloc ( nn * sizeof ( T ) ) ;
2021-10-28 20:17:32 +02:00
if ( ! LA_traits < T > : : is_plaindata ( ) ) laerror ( " only implemented for plain data " ) ;
2021-10-27 23:24:41 +02:00
cublasSetVector ( nn , sizeof ( T ) , a , 1 , v , 1 ) ;
TEST_CUBLAS ( " cublasSetVector " ) ;
}
# endif
}
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* inline constructor creating vector of given size filled with given data
* @ param [ in ] a pointer to the data
* @ param [ in ] n required vector size
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline NRVec < T > : : NRVec ( const T * a , const int n ) : nn ( n ) , count ( new int ) {
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 [ n ] ;
* count = 1 ;
2021-10-28 20:17:32 +02:00
if ( LA_traits < T > : : is_plaindata ( ) ) memcpy ( v , a , n * sizeof ( T ) ) ;
else for ( int i = 0 ; i < n ; i + + ) v [ i ] = a [ i ] ;
2010-06-25 17:28:19 +02:00
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
} else {
v = ( T * ) gpualloc ( n * sizeof ( T ) ) ;
2021-10-28 20:17:32 +02:00
if ( ! LA_traits < T > : : is_plaindata ( ) ) laerror ( " only implemented for plain data " ) ;
2010-09-08 18:27:58 +02:00
cublasSetVector ( n , sizeof ( T ) , a , 1 , v , 1 ) ;
TEST_CUBLAS ( " cublasSetVector " ) ;
}
2010-06-25 17:28:19 +02:00
# endif
2006-09-12 01:07:22 +02:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* inline constructor creating vector of given size filled with given data
* @ param [ in ] a pointer to the data
* @ param [ in ] n required vector size
* @ param [ in ] skeleton if equal to true , only the internal data pointer is modified
* and reference counter is set to two , i . e . no data deallocation occurs in destructor
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-09-12 01:07:22 +02:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline NRVec < T > : : NRVec ( T * a , const int n , bool skeleton ) : nn ( n ) , count ( new int ) {
if ( ! skeleton ) {
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 [ n ] ;
* count = 1 ;
2021-10-28 20:17:32 +02:00
if ( LA_traits < T > : : is_plaindata ( ) ) memcpy ( v , a , n * sizeof ( T ) ) ;
else for ( int i = 0 ; i < n ; i + + ) v [ i ] = a [ i ] ;
2010-06-25 17:28:19 +02:00
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
} else {
v = ( T * ) gpualloc ( n * sizeof ( T ) ) ;
2021-10-28 20:17:32 +02:00
if ( ! LA_traits < T > : : is_plaindata ( ) ) laerror ( " only implemented for plain data " ) ;
2010-09-08 18:27:58 +02:00
cublasSetVector ( n , sizeof ( T ) , a , 1 , v , 1 ) ;
TEST_CUBLAS ( " cublasSetVector " ) ;
2006-09-12 01:07:22 +02:00
}
2010-09-08 18:27:58 +02:00
# endif
} else {
2010-06-25 17:28:19 +02:00
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
if ( location ! = cpu ) laerror ( " NRVec() with skeleton option cannot be on GPU " ) ;
2010-06-25 17:28:19 +02:00
# endif
2006-09-12 01:07:22 +02:00
* count = 2 ;
2010-09-08 18:27:58 +02:00
v = a ;
}
2004-03-17 04:07:21 +01:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* inline copy constructor
* @ param [ in ] rhs reference vector being copied
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline NRVec < T > : : NRVec ( const NRVec < 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 ;
if ( count ) ( * count ) + + ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* inline constructor interpreting symmetric matrix of order \ f $ n \ f $ stored in packed form
* as a linear vector consisting of \ f $ n ( n + 1 ) / 2 \ f $ elements
* @ param [ in ] rhs symmetric matrix of type < code > NRSMat < T > < / code >
* @ see NRSMat < T >
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline NRVec < T > : : NRVec ( 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
nn = rhs . nn ;
2010-09-08 18:27:58 +02:00
//! using macro NN2 defined in smat.h
2004-03-17 04:07:21 +01:00
nn = NN2 ;
v = rhs . v ;
count = rhs . count ;
( * count ) + + ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* adds given scalar value of type T to all vector elements
* @ param [ in ] a scalar value being added
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 06:34:59 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline NRVec < T > & NRVec < T > : : operator + = ( const T & a ) {
2010-06-25 17:28:19 +02:00
NOT_GPU ( * this ) ;
2010-09-08 18:27:58 +02:00
2004-03-17 06:34:59 +01:00
copyonwrite ( ) ;
2010-09-08 18:27:58 +02:00
if ( a ! = ( T ) 0 ) { for ( register int i = 0 ; i < nn ; + + i ) v [ i ] + = a ; }
2004-03-17 06:34:59 +01:00
return * this ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* subtracts given scalar value of type T from all vector elements
* @ param [ in ] a scalar value being subtracted
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 06:34:59 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline NRVec < T > & NRVec < T > : : operator - = ( const T & a ) {
2010-06-25 17:28:19 +02:00
NOT_GPU ( * this ) ;
2004-03-17 06:34:59 +01:00
2010-09-08 18:27:58 +02:00
copyonwrite ( ) ;
if ( a ! = ( T ) 0 ) { for ( register int i = 0 ; i < nn ; + + i ) v [ i ] - = a ; }
return * this ;
}
2004-03-17 06:34:59 +01:00
2004-03-17 04:07:21 +01:00
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* adds a vector \ f $ \ vec { y } \ f $ of general type < code > T < / code > to this vector \ f $ \ vec { x } \ f $
* \ f [ \ vec { x } \ leftarrow \ vec { x } + \ vec { y } \ f ]
* @ param [ in ] rhs vector \ f $ \ vec { y } \ f $ of type < code > T < / code >
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 06:34:59 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline NRVec < T > & NRVec < T > : : operator + = ( const NRVec < 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 dimensions " ) ;
2004-03-17 06:34:59 +01:00
# endif
2010-09-08 18:27:58 +02:00
NOT_GPU ( * this ) ;
NOT_GPU ( rhs ) ;
copyonwrite ( ) ;
for ( register int i = 0 ; i < nn ; + + i ) v [ i ] + = rhs . v [ i ] ;
return * this ;
2004-03-17 06:34:59 +01:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* multiplies this vector \ f $ \ vec { y } \ f $ componentwise by general vector \ f $ \ vec { x } \ f $
* \ f [ \ vec { x } _i = \ vec { x } _i \ times \ vec { y } _i \ f ]
* @ param [ in ] rhs general vector \ f $ \ vec { y } \ f $
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-04-06 23:45:51 +02:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline NRVec < T > & NRVec < T > : : operator * = ( const NRVec < T > & rhs ) {
2006-04-06 23:45:51 +02:00
# ifdef DEBUG
2010-09-08 18:27:58 +02:00
if ( nn ! = rhs . nn ) laerror ( " incompatible dimensions " ) ;
2006-04-06 23:45:51 +02:00
# endif
2010-09-08 18:27:58 +02:00
NOT_GPU ( * this ) ;
NOT_GPU ( rhs ) ;
copyonwrite ( ) ;
for ( register int i = 0 ; i < nn ; + + i ) v [ i ] * = rhs . v [ i ] ;
2006-04-06 23:45:51 +02:00
return * this ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* divides this vector \ f $ \ vec { y } \ f $ componentwise by general vector \ f $ \ vec { x } \ f $
* \ f [ \ vec { x } _i = \ vec { x } _i \ slash \ vec { y } _i \ f ]
* @ param [ in ] rhs general vector \ f $ \ vec { y } \ f $
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-04-06 23:45:51 +02:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline NRVec < T > & NRVec < T > : : operator / = ( const NRVec < T > & rhs ) {
2006-04-06 23:45:51 +02:00
# ifdef DEBUG
2010-09-08 18:27:58 +02:00
if ( nn ! = rhs . nn ) laerror ( " incompatible dimensions " ) ;
2006-04-06 23:45:51 +02:00
# endif
2010-09-08 18:27:58 +02:00
NOT_GPU ( * this ) ;
NOT_GPU ( rhs ) ;
2006-04-06 23:45:51 +02:00
copyonwrite ( ) ;
2010-09-08 18:27:58 +02:00
for ( register int i = 0 ; i < nn ; + + i ) v [ i ] / = rhs . v [ i ] ;
2006-04-06 23:45:51 +02:00
return * this ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* subtracts given vector \ f $ \ vec { y } \ f $ from this vector \ f $ \ vec { x } \ f $
* \ f [ \ vec { x } _i = \ vec { x } _i - \ vec { y } _i \ f ]
* @ param [ in ] rhs vector \ f $ \ vec { y } \ f $
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 06:34:59 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline NRVec < T > & NRVec < T > : : operator - = ( const NRVec < 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 dimensions " ) ;
2004-03-17 06:34:59 +01:00
# endif
2010-09-08 18:27:58 +02:00
NOT_GPU ( * this ) ;
NOT_GPU ( rhs ) ;
copyonwrite ( ) ;
for ( register int i = 0 ; i < nn ; + + i ) v [ i ] - = rhs . v [ i ] ;
2004-03-17 06:34:59 +01:00
return * this ;
}
2021-06-30 14:54:35 +02:00
/***************************************************************************/ /**
* difference of elements of two vectors in absolute values
* \ f [ \ vec { z } _i = \ vec { x } _i - \ vec { y } _i \ f ]
* @ param [ in ] rhs vector \ f $ \ vec { y } \ f $
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template < typename T >
2021-11-13 19:00:46 +01:00
NRVec < typename LA_traits < T > : : normtype > NRVec < T > : : diffabs ( const NRVec < T > & rhs ) const {
2021-06-30 14:54:35 +02:00
# ifdef DEBUG
if ( nn ! = rhs . nn ) laerror ( " incompatible dimensions " ) ;
# endif
NOT_GPU ( * this ) ;
NOT_GPU ( rhs ) ;
2021-11-13 19:00:46 +01:00
NRVec < typename LA_traits < T > : : normtype > r ( nn ) ;
2021-06-30 14:54:35 +02:00
for ( int i = 0 ; i < nn ; + + i ) r [ i ] = MYABS ( v [ i ] ) - MYABS ( rhs . v [ i ] ) ;
return r ;
}
2021-11-13 19:00:46 +01:00
template < typename T >
NRVec < typename LA_traits < T > : : normtype > NRVec < T > : : abs ( ) const {
NOT_GPU ( * this ) ;
NRVec < typename LA_traits < T > : : normtype > r ( nn ) ;
for ( int i = 0 ; i < nn ; + + i ) r [ i ] = MYABS ( v [ i ] ) ;
return r ;
}
2004-03-17 06:34:59 +01:00
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* multiply this general vector \ f $ \ vec { x } \ f $ by scalar value \ f $ \ lambda \ f $
* \ f [ \ vec { x } _i \ leftarrow \ lambda \ vec { x } _i \ f ]
* @ param [ in ] a scalar value \ f $ \ lambda \ f $
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 06:34:59 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline NRVec < T > & NRVec < T > : : operator * = ( const T & a ) {
NOT_GPU ( * this ) ;
copyonwrite ( ) ;
2004-03-17 06:34:59 +01:00
2010-09-08 18:27:58 +02:00
for ( register int i = 0 ; i < nn ; + + i ) v [ i ] * = a ;
return * this ;
}
2004-03-17 06:34:59 +01:00
2021-06-10 17:44:54 +02:00
template < typename T >
inline NRVec < T > & NRVec < T > : : operator / = ( const T & a ) {
NOT_GPU ( * this ) ;
copyonwrite ( ) ;
for ( register int i = 0 ; i < nn ; + + i ) v [ i ] / = a ;
return * this ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* compute scalar product \ f $ d \ f $ of this vector \ f $ \ vec { x } \ f $ of general type < code > T < / code >
* with given vector \ f $ \ vec { y } \ f $ of type < code > T < / code > and order \ f $ N \ f $
* \ f [ d = \ sum_ { i = 1 } ^ N \ vec { x } _i \ cdot \ vec { y } _i \ f ]
* @ param [ in ] rhs general vector \ f $ \ vec { y } \ f $
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-18 23:08:15 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline const T NRVec < T > : : operator * ( const NRVec < T > & rhs ) const {
2005-02-18 23:08:15 +01:00
# ifdef DEBUG
2010-09-08 18:27:58 +02:00
if ( nn ! = rhs . nn ) laerror ( " incompatible dimensions " ) ;
2005-02-18 23:08:15 +01:00
# endif
2010-09-08 18:27:58 +02:00
NOT_GPU ( * this ) ;
NOT_GPU ( rhs ) ;
T dot ( 0 ) ;
for ( register int i = 0 ; i < nn ; + + i ) dot + = v [ i ] * rhs . v [ i ] ;
2005-02-18 23:08:15 +01:00
return dot ;
2004-03-17 04:07:21 +01:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* indexing operator giving the element at given position with range checking in
* the DEBUG mode
* @ param [ in ] i position of the required vector element ( starting from 0 )
* @ return reference to the requested element
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline T & NRVec < T > : : operator [ ] ( const int i ) {
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 ( " possible use of NRVec[] with count>1 as l-value " ) ;
if ( i < 0 | | i > = nn ) laerror ( " out of range " ) ;
if ( ! v ) laerror ( " unallocated NRVec " ) ;
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 [ i ] ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* indexing operator giving the element at given position with range checking in
* the DEBUG mode
* @ param [ in ] i position of the required vector element ( starting from 0 )
* @ return constant reference to the requested element
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline const T & NRVec < T > : : operator [ ] ( const int i ) const {
2004-03-17 04:07:21 +01:00
# ifdef DEBUG
2010-09-08 18:27:58 +02:00
if ( i < 0 | | i > = nn ) laerror ( " out of range " ) ;
if ( ! v ) laerror ( " unallocated NRVec " ) ;
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 [ i ] ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* determine the number of elements of this vector
* @ return length of this vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline int NRVec < T > : : size ( ) const {
2004-03-17 04:07:21 +01:00
return nn ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* get the pointer to the underlying data of this vector
* @ return pointer to the first vector element
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline NRVec < 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 NRVec " ) ;
2004-03-17 04:07:21 +01:00
# endif
return v ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* get the constant pointer to the underlying data of this vector
* @ return constant pointer to the first vector element
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline NRVec < 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 NRVec " ) ;
2004-03-17 04:07:21 +01:00
# endif
return v ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* create normalized copy of this vector
* @ return copy of this vector after normalization
* @ see NRVec < T > : : normalize ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
inline const NRVec < T > NRVec < T > : : unitvector ( ) const {
2004-03-17 04:07:21 +01:00
return NRVec < T > ( * this ) . normalize ( ) ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* generate operators involving vector and scalar
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
NRVECMAT_OPER ( Vec , + )
NRVECMAT_OPER ( Vec , - )
NRVECMAT_OPER ( Vec , * )
2021-06-10 17:44:54 +02:00
NRVECMAT_OPER ( Vec , / )
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* generate operators involving vector and vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 04:07:21 +01:00
NRVECMAT_OPER2 ( Vec , + )
NRVECMAT_OPER2 ( Vec , - )
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* destructor for general vector decreases the reference count and performs
* deallocation if neccessary
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 17:39:07 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
NRVec < T > : : ~ NRVec ( ) {
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
}
2004-03-17 17:39:07 +01:00
delete count ;
}
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* make own copy of the underlying data connected with this vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 17:39:07 +01:00
template < typename T >
2013-11-04 15:56:39 +01:00
void NRVec < T > : : copyonwrite ( bool detachonly ) {
2021-11-04 14:21:13 +01:00
if ( ! count )
{
if ( nn ) laerror ( " nonempty vector without reference count encountered " ) ;
if ( _LA_warn_empty_copyonwrite ) std : : cout < < " Warning: copyonwrite of empty vector \n " ;
return ;
}
2010-09-08 18:27:58 +02:00
if ( * count > 1 ) {
( * count ) - - ;
count = new int ;
* count = 1 ;
T * newv ;
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
newv = new T [ nn ] ;
2021-05-23 10:28:10 +02:00
if ( ! detachonly )
{
if ( LA_traits < T > : : is_plaindata ( ) ) memcpy ( newv , v , nn * sizeof ( T ) ) ;
else
{
for ( int i = 0 ; i < nn ; + + i ) { newv [ i ] = v [ i ] ; LA_traits < T > : : copyonwrite ( newv [ i ] ) ; }
}
}
2010-09-08 18:27:58 +02:00
# ifdef CUDALA
} else {
2021-05-23 10:28:10 +02:00
if ( ! LA_traits < T > : : is_plaindata ( ) ) laerror ( " nested types not supported on gpu memory " ) ;
2010-09-08 18:27:58 +02:00
newv = ( T * ) gpualloc ( nn * sizeof ( T ) ) ;
if ( sizeof ( T ) % sizeof ( float ) ! = 0 ) laerror ( " memory alignment problem in NRVec<T>::copyonwrite() " ) ;
2013-11-04 15:56:39 +01:00
if ( ! detachonly ) cublasScopy ( nn * sizeof ( T ) / sizeof ( float ) , ( const float * ) v , 1 , ( float * ) newv , 1 ) ;
2010-09-08 18:27:58 +02:00
TEST_CUBLAS ( " cublasScopy " ) ; //"NRVec<T>::copyonwrite()"
}
# endif
v = newv ;
}
2004-03-17 17:39:07 +01:00
}
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* assigns general vector \ f $ \ vec { y } \ f $ to this vector \ f $ \ vec { x } \ f $
* \ li checks for self - assignment
* \ li decreases the reference count and performs deallocation if neccesary
* \ li links the internal data structures with corresponding properties of vector \ f $ \ vec { y } \ f $
* \ li updates the reference count properly
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 17:39:07 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
NRVec < T > & NRVec < T > : : operator = ( const NRVec < T > & rhs ) {
//check for self-assignment
if ( this ! = & rhs ) {
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 ) + + ; }
}
return * this ;
2004-03-17 17:39:07 +01:00
}
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* resizes this vector
* @ param [ in ] n requested size
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 17:39:07 +01:00
template < typename T >
2023-03-17 16:04:41 +01:00
void NRVec < T > : : resize ( const int n , const bool preserve , const bool preserve_at_end )
2021-06-09 15:33:24 +02:00
{
2004-03-17 17:39:07 +01:00
# ifdef DEBUG
2021-06-09 15:33:24 +02:00
if ( n < 0 ) laerror ( " illegal dimension in NRVec::resize " ) ;
2004-03-17 17:39:07 +01:00
# endif
2021-06-09 15:33:24 +02:00
T * vold = 0 ;
int nnold = 0 ;
bool preserved = false ;
bool do_delete = false ;
if ( count ) //we are allocated
{
if ( n = = 0 ) //just deallocate
{
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
2021-06-09 15:33:24 +02:00
}
2010-09-08 18:27:58 +02:00
delete count ;
2021-06-09 15:33:24 +02:00
}
2010-09-08 18:27:58 +02:00
count = 0 ;
nn = 0 ;
v = 0 ;
return ;
2021-06-09 15:33:24 +02:00
}
if ( * count > 1 ) //detach from shared data
{
2010-09-08 18:27:58 +02:00
( * count ) - - ;
count = 0 ;
2021-06-09 15:33:24 +02:00
vold = v ;
2010-09-08 18:27:58 +02:00
v = 0 ;
2021-06-09 15:33:24 +02:00
nnold = nn ;
2010-09-08 18:27:58 +02:00
nn = 0 ;
2021-06-09 15:33:24 +02:00
preserved = true ;
}
2010-09-08 18:27:58 +02:00
}
2021-06-09 15:33:24 +02:00
if ( ! count ) //we were not allocated or we just detached
{
2010-09-08 18:27:58 +02:00
count = new int ;
* count = 1 ;
nn = n ;
# ifdef CUDALA
if ( location = = cpu )
# endif
v = new T [ nn ] ;
2010-06-25 17:28:19 +02:00
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
else
v = ( T * ) gpualloc ( nn * sizeof ( T ) ) ;
# endif
2021-06-09 15:33:24 +02:00
if ( preserved & & preserve ) goto do_preserve ;
2010-09-08 18:27:58 +02:00
return ;
2021-06-09 15:33:24 +02:00
}
// *count == 1 in this branch
if ( n = = nn ) return ; //nothing to do
nnold = nn ;
nn = n ;
2010-09-08 18:27:58 +02:00
# ifdef CUDALA
2021-06-09 15:33:24 +02:00
if ( location = = cpu )
{
2010-09-08 18:27:58 +02:00
# endif
2021-06-10 17:44:54 +02:00
if ( preserve ) { vold = v ; preserved = do_delete = true ; } else delete [ ] v ;
2010-09-08 18:27:58 +02:00
v = new T [ nn ] ;
# ifdef CUDALA
2021-06-09 15:33:24 +02:00
}
else
{
2021-06-10 17:44:54 +02:00
if ( preserve ) { vold = v ; d preserved = o_delete = true ; } else gpufree ( v ) ;
2010-09-08 18:27:58 +02:00
v = ( T * ) gpualloc ( nn * sizeof ( T ) ) ;
2021-06-09 15:33:24 +02:00
}
2010-06-25 17:28:19 +02:00
# endif
2021-06-09 15:33:24 +02:00
if ( ! preserve ) return ;
//copy data from old location and zero excess allocated memory
do_preserve :
if ( ! preserve | | ! preserved ) laerror ( " assertion failed in NRVec::resize " ) ;
// omit this check since we would need to have traits for presently unknown user defined classes
// if(!LA_traits<T>::is_plaindata()) laerror("do not know how to preserve non-plain data");
2021-06-09 22:59:19 +02:00
int nnmin = nnold ;
if ( nn < nnmin ) nnmin = nn ;
2021-06-09 15:33:24 +02:00
# ifdef CUDALA
if ( location = = cpu )
{
# endif
2023-03-17 16:04:41 +01:00
if ( preserve_at_end )
{
for ( int i = 0 ; i < nnmin ; + + i ) v [ nn - i - 1 ] = vold [ nnold - i - 1 ] ; //preserve even non-plain data classes
if ( nn > nnold ) memset ( v , 0 , ( nn - nnold ) * sizeof ( T ) ) ; //just zero the new memory
}
else
{
for ( int i = 0 ; i < nnmin ; + + i ) v [ i ] = vold [ i ] ; //preserve even non-plain data classes
if ( nn > nnold ) memset ( v + nnold , 0 , ( nn - nnold ) * sizeof ( T ) ) ; //just zero the new memory
}
2021-06-09 15:33:24 +02:00
if ( do_delete ) delete [ ] vold ;
# ifdef CUDALA
}
else
{
//!!!works only with plain data
2023-03-17 16:04:41 +01:00
if ( preserve_at_end )
{
cublasSetVector ( nnmin , sizeof ( T ) , vold + nnold - nnmin , 1 , v + nn - nnmin , 1 ) ;
TEST_CUBLAS ( " cublasSetVector " ) ;
T a ( 0 ) ;
if ( nn > nnold ) smart_gpu_set ( nn - nnold , a , v ) ;
}
else
{
cublasSetVector ( nnmin , sizeof ( T ) , vold , 1 , v , 1 ) ;
TEST_CUBLAS ( " cublasSetVector " ) ;
T a ( 0 ) ;
if ( nn > nnold ) smart_gpu_set ( nn - nnold , a , v + nnold ) ;
}
2021-06-09 15:33:24 +02:00
if ( do_delete ) gpufree ( vold ) ;
}
# endif
return ;
2004-03-17 17:39:07 +01:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* perfrom deep copy
* @ param [ in ] rhs vector being copied
* @ see NRVec < T > : : copyonwrite ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-17 17:39:07 +01:00
template < typename T >
2010-09-08 18:27:58 +02:00
NRVec < T > & NRVec < T > : : operator | = ( const NRVec < T > & rhs ) {
2004-03-17 17:39:07 +01:00
# ifdef DEBUG
2010-09-08 18:27:58 +02:00
if ( ! rhs . v ) laerror ( " unallocated vector " ) ;
2004-03-17 17:39:07 +01:00
# endif
2010-09-08 18:27:58 +02:00
if ( this = = & rhs ) return * this ;
2010-06-25 17:28:19 +02:00
* this = rhs ;
this - > copyonwrite ( ) ;
return * this ;
2004-03-17 17:39:07 +01:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* complexify given vector of general type < code > T < / code > , i . e . convert its
* elements to type < code > complex < T > < / code >
* @ param [ in ] rhs vector being complexified
* @ see NRVec < T > : : copyonwrite ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-04-01 06:48:01 +02:00
template < typename T >
2021-04-21 15:04:37 +02:00
NRVec < std : : complex < T > > complexify ( const NRVec < T > & rhs ) {
2010-09-08 18:27:58 +02:00
NOT_GPU ( rhs ) ;
2006-04-01 06:48:01 +02:00
2021-04-21 15:04:37 +02:00
NRVec < std : : complex < T > > r ( rhs . size ( ) , rhs . getlocation ( ) ) ;
2010-09-08 18:27:58 +02:00
for ( register int i = 0 ; i < rhs . size ( ) ; + + i ) r [ i ] = rhs [ i ] ;
return r ;
}
2021-04-21 15:04:37 +02:00
template < > NRVec < std : : complex < double > > complexify < double > ( const NRVec < double > & rhs ) ;
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* routine for moving vector data between CPU and GPU memory
* @ param [ in ] dest required location
* @ see NRVec < T > : : location , NRVec < T > : : getlocation ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
# ifdef CUDALA
template < typename T >
2010-09-08 18:27:58 +02:00
void NRVec < T > : : moveto ( const GPUID dest ) {
if ( location = = dest ) return ;
CPU_GPU ( location , dest ) ;
location = dest ;
if ( v & & ! count ) laerror ( " internal " ) ;
if ( ! count ) return ;
if ( v & & * count = = 0 ) laerror ( " internal " ) ;
if ( ! v ) return ;
T * vold = v ;
if ( dest = = cpu ) { // moving from GPU to CPU
v = new T [ nn ] ;
gpuget ( nn , sizeof ( T ) , vold , v ) ;
if ( * count = = 1 ) gpufree ( vold ) ;
else { - - ( * count ) ; count = new int ( 1 ) ; }
} else { // moving from CPU to GPU
v = ( T * ) gpualloc ( nn * sizeof ( T ) ) ;
gpuput ( nn , sizeof ( T ) , vold , v ) ;
if ( * count = = 1 ) delete [ ] vold ;
else { - - ( * count ) ; count = new int ( 1 ) ; }
}
2010-06-25 17:28:19 +02:00
}
# endif
2021-05-19 22:29:47 +02:00
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* adds a real scalar value \ f $ \ alpha \ f $ to all elements of this real vector \ f $ \ vec { x } \ f $
* \ f [ \ vec { x } _i \ leftarrow \ vec { x } _i + \ alpha \ f ]
* @ param [ in ] a real scalar value \ f $ \ alpha \ f $ being added
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2010-09-08 18:27:58 +02:00
inline NRVec < double > & NRVec < double > : : operator + = ( const double & a ) {
2010-06-25 17:28:19 +02:00
copyonwrite ( ) ;
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
if ( location = = cpu ) {
2010-06-25 17:28:19 +02:00
# endif
cblas_daxpy ( nn , 1.0 , & a , 0 , v , 1 ) ;
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
} else {
double * d = gpuputdouble ( a ) ;
2010-06-25 17:28:19 +02:00
cublasDaxpy ( nn , 1.0 , d , 0 , v , 1 ) ;
2010-09-08 18:27:58 +02:00
TEST_CUBLAS ( " cublasDaxpy " ) ;
2010-06-25 17:28:19 +02:00
gpufree ( d ) ;
2010-09-08 18:27:58 +02:00
}
2010-06-25 17:28:19 +02:00
# endif
return * this ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* adds a complex scalar value \ f $ \ alpha \ f $ to all elements of this complex vector \ f $ \ vec { x } \ f $
* \ f [ \ vec { x } _i \ leftarrow \ vec { x } _i + \ alpha \ f ]
* @ param [ in ] a complex scalar value \ f $ \ alpha \ f $ being added
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2021-04-21 15:04:37 +02:00
inline NRVec < std : : complex < double > > & NRVec < std : : complex < double > > : : operator + = ( const std : : complex < double > & a ) {
2010-06-25 17:28:19 +02:00
copyonwrite ( ) ;
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
if ( location = = cpu ) {
2010-06-25 17:28:19 +02:00
# endif
cblas_zaxpy ( nn , & CONE , & a , 0 , v , 1 ) ;
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
} else {
2021-04-21 15:04:37 +02:00
std : : complex < double > * d = gpuputcomplex ( a ) ;
2010-06-25 17:28:19 +02:00
cublasZaxpy ( nn , CUONE , ( cuDoubleComplex * ) d , 0 , ( cuDoubleComplex * ) v , 1 ) ;
2010-09-08 18:27:58 +02:00
TEST_CUBLAS ( " cublasZaxpy " ) ;
2010-06-25 17:28:19 +02:00
gpufree ( d ) ;
2010-09-08 18:27:58 +02:00
}
2010-06-25 17:28:19 +02:00
# endif
return * this ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* subtracts a real scalar value \ f $ \ alpha \ f $ from all elements of this real vector \ f $ \ vec { x } \ f $
* \ f [ \ vec { x } _i \ leftarrow \ vec { x } _i - \ alpha \ f ]
* @ param [ in ] a real scalar value \ f $ \ alpha \ f $ being subtracted
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2010-09-08 18:27:58 +02:00
inline NRVec < double > & NRVec < double > : : operator - = ( const double & a ) {
2010-06-25 17:28:19 +02:00
copyonwrite ( ) ;
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
if ( location = = cpu ) {
2010-06-25 17:28:19 +02:00
# endif
cblas_daxpy ( nn , - 1.0 , & a , 0 , v , 1 ) ;
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
} else {
double * d = gpuputdouble ( a ) ;
2010-06-25 17:28:19 +02:00
cublasDaxpy ( nn , - 1.0 , d , 0 , v , 1 ) ;
2010-09-08 18:27:58 +02:00
TEST_CUBLAS ( " cublasDaxpy " ) ;
2010-06-25 17:28:19 +02:00
gpufree ( d ) ;
2010-09-08 18:27:58 +02:00
}
2010-06-25 17:28:19 +02:00
# endif
return * this ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* subtracts a complex scalar value \ f $ \ alpha \ f $ from all elements of this complex vector \ f $ \ vec { x } \ f $
* \ f [ \ vec { x } _i \ leftarrow \ vec { x } _i - \ alpha \ f ]
* @ param [ in ] a complex scalar value \ f $ \ alpha \ f $ being subtracted
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2021-04-21 15:04:37 +02:00
inline NRVec < std : : complex < double > > & NRVec < std : : complex < double > > : : operator - = ( const std : : complex < double > & a ) {
2010-06-25 17:28:19 +02:00
copyonwrite ( ) ;
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
if ( location = = cpu ) {
2010-06-25 17:28:19 +02:00
# endif
cblas_zaxpy ( nn , & CMONE , & a , 0 , v , 1 ) ;
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
} else {
2021-04-21 15:04:37 +02:00
std : : complex < double > * d = gpuputcomplex ( a ) ;
2010-09-08 18:27:58 +02:00
cublasZaxpy ( nn , CUMONE , ( cuDoubleComplex * ) d , 0 , ( cuDoubleComplex * ) v , 1 ) ;
TEST_CUBLAS ( " cublasZaxpy " ) ;
gpufree ( d ) ;
}
2010-06-25 17:28:19 +02:00
# endif
return * this ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* adds a real vector \ f $ \ vec { y } \ f $ to this real vector \ f $ \ vec { x } \ f $
* \ f [ \ vec { x } \ leftarrow \ vec { x } + \ vec { y } \ f ]
* @ param [ in ] rhs real vector \ f $ \ vec { y } \ f $
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2010-09-08 18:27:58 +02:00
inline NRVec < double > & NRVec < double > : : operator + = ( const NRVec < double > & rhs ) {
2010-06-25 17:28:19 +02:00
# ifdef DEBUG
2010-09-08 18:27:58 +02:00
if ( nn ! = rhs . nn ) laerror ( " incompatible dimensions " ) ;
2010-06-25 17:28:19 +02:00
# endif
2010-09-08 18:27:58 +02:00
SAME_LOC ( * this , rhs ) ;
2010-06-25 17:28:19 +02:00
copyonwrite ( ) ;
2010-09-08 18:27:58 +02:00
# ifdef CUDALA
if ( location = = cpu ) {
# endif
cblas_daxpy ( nn , 1.0 , rhs . v , 1 , v , 1 ) ;
# ifdef CUDALA
} else {
cublasDaxpy ( nn , 1.0 , rhs . v , 1 , v , 1 ) ;
TEST_CUBLAS ( " cubasDaxpy " ) ;
}
# endif
2010-06-25 17:28:19 +02:00
return * this ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* adds a complex vector \ f $ \ vec { y } \ f $ to this complex vector \ f $ \ vec { x } \ f $
* \ f [ \ vec { x } \ leftarrow \ vec { x } + \ vec { y } \ f ]
* @ param [ in ] rhs complex vector \ f $ \ vec { y } \ f $
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2021-04-21 15:04:37 +02:00
inline NRVec < std : : complex < double > > & NRVec < std : : complex < double > > : : operator + = ( const NRVec < std : : complex < double > > & rhs ) {
2010-06-25 17:28:19 +02:00
# ifdef DEBUG
2010-09-08 18:27:58 +02:00
if ( nn ! = rhs . nn ) laerror ( " incompatible dimensions " ) ;
2010-06-25 17:28:19 +02:00
# endif
2010-09-08 18:27:58 +02:00
SAME_LOC ( * this , rhs ) ;
2010-06-25 17:28:19 +02:00
copyonwrite ( ) ;
2010-09-08 18:27:58 +02:00
# ifdef CUDALA
if ( location = = cpu ) {
# endif
cblas_zaxpy ( nn , & CONE , rhs . v , 1 , v , 1 ) ;
# ifdef CUDALA
} else {
cublasZaxpy ( nn , CUONE , ( cuDoubleComplex * ) rhs . v , 1 , ( cuDoubleComplex * ) v , 1 ) ;
TEST_CUBLAS ( " cublasZaxpy " ) ;
}
# endif
return * this ;
2010-06-25 17:28:19 +02:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* subtracts a real vector \ f $ \ vec { y } \ f $ from this real vector \ f $ \ vec { x } \ f $
* \ f [ \ vec { x } \ leftarrow \ vec { x } - \ vec { y } \ f ]
* @ param [ in ] rhs real vector \ f $ \ vec { y } \ f $
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2010-09-08 18:27:58 +02:00
inline NRVec < double > & NRVec < double > : : operator - = ( const NRVec < double > & rhs ) {
2010-06-25 17:28:19 +02:00
# ifdef DEBUG
2010-09-08 18:27:58 +02:00
if ( nn ! = rhs . nn ) laerror ( " incompatible dimensions " ) ;
2010-06-25 17:28:19 +02:00
# endif
2010-09-08 18:27:58 +02:00
SAME_LOC ( * this , rhs ) ;
copyonwrite ( ) ;
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
cblas_daxpy ( nn , - 1.0 , rhs . v , 1 , v , 1 ) ;
2010-06-25 17:28:19 +02:00
# ifdef CUDALA
2010-09-08 18:27:58 +02:00
} else {
2010-06-25 17:28:19 +02:00
cublasDaxpy ( nn , - 1.0 , rhs . v , 1 , v , 1 ) ;
2010-09-08 18:27:58 +02:00
TEST_CUBLAS ( " cubasDaxpy " ) ;
}
2010-06-25 17:28:19 +02:00
# endif
return * this ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* subtracts a complex vector \ f $ \ vec { y } \ f $ from this complex vector \ f $ \ vec { x } \ f $
* \ f [ \ vec { x } \ leftarrow \ vec { x } - \ vec { y } \ f ]
* @ param [ in ] rhs double - precision complex vector \ f $ \ vec { y } \ f $
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2021-04-21 15:04:37 +02:00
inline NRVec < std : : complex < double > > & NRVec < std : : complex < double > > : : operator - = ( const NRVec < std : : complex < double > > & rhs ) {
2010-06-25 17:28:19 +02:00
# ifdef DEBUG
2010-09-08 18:27:58 +02:00
if ( nn ! = rhs . nn ) laerror ( " incompatible dimensions " ) ;
# endif
SAME_LOC ( * this , rhs ) ;
copyonwrite ( ) ;
# ifdef CUDALA
if ( location = = cpu ) {
# endif
cblas_zaxpy ( nn , & CMONE , rhs . v , 1 , v , 1 ) ;
# ifdef CUDALA
} else {
cublasZaxpy ( nn , CUMONE , ( cuDoubleComplex * ) rhs . v , 1 , ( cuDoubleComplex * ) v , 1 ) ;
TEST_CUBLAS ( " cublasZaxpy " ) ;
}
2010-06-25 17:28:19 +02:00
# endif
return * this ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* multiplies this real vector \ f $ \ vec { x } \ f $ by a real scalar value \ f $ \ alpha \ f $
* \ f [ \ vec { x } _i \ leftarrow \ alpha \ vec { x } _i \ f ]
* @ param [ in ] a real scalar value \ f $ \ alpha \ f $
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2010-09-08 18:27:58 +02:00
inline NRVec < double > & NRVec < double > : : operator * = ( const double & a ) {
2010-06-25 17:28:19 +02:00
copyonwrite ( ) ;
2010-09-08 18:27:58 +02:00
# ifdef CUDALA
if ( location = = cpu ) {
# endif
cblas_dscal ( nn , a , v , 1 ) ;
# ifdef CUDALA
} else {
cublasDscal ( nn , a , v , 1 ) ;
TEST_CUBLAS ( " cublasDscal " ) ;
}
# endif
2010-06-25 17:28:19 +02:00
return * this ;
}
2021-06-10 17:44:54 +02:00
template < >
inline NRVec < double > & NRVec < double > : : operator / = ( const double & a ) { return * this * = ( 1. / a ) ; }
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* multiplies this complex vector \ f $ \ vec { x } \ f $ by a complex scalar value \ f $ \ alpha \ f $
* \ f [ \ vec { x } _i \ leftarrow \ alpha \ vec { x } _i \ f ]
* @ param [ in ] a complex scalar value \ f $ \ alpha \ f $
* @ return reference to the modified vector
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2021-04-21 15:04:37 +02:00
inline NRVec < std : : complex < double > > & NRVec < std : : complex < double > > : : operator * = ( const std : : complex < double > & a ) {
2010-06-25 17:28:19 +02:00
copyonwrite ( ) ;
2010-09-08 18:27:58 +02:00
# ifdef CUDALA
if ( location = = cpu ) {
# endif
cblas_zscal ( nn , & a , v , 1 ) ;
# ifdef CUDALA
} else {
const cuDoubleComplex alpha = make_cuDoubleComplex ( a . real ( ) , a . imag ( ) ) ;
cublasZscal ( nn , alpha , ( cuDoubleComplex * ) v , 1 ) ;
TEST_CUBLAS ( " cublasZscal " ) ;
}
# endif
2010-06-25 17:28:19 +02:00
return * this ;
}
2021-06-10 17:44:54 +02:00
template < >
inline NRVec < std : : complex < double > > & NRVec < std : : complex < double > > : : operator / = ( const std : : complex < double > & a ) { return * this * = ( 1. / a ) ; }
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* computes the inner product of this real vector \ f $ \ vec { x } \ f $ with given real vector \ f $ \ vec { y ] \ f $
* @ param [ in ] rhs real vector \ f $ \ vec { y } \ f $
* @ return \ f $ \ sum_ { i = 1 } ^ N \ vec { x } _i \ cdot \ vec { y } _i \ f $
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2010-09-08 18:27:58 +02:00
inline const double NRVec < double > : : operator * ( const NRVec < double > & rhs ) const {
double ret ( 0.0 ) ;
2010-06-25 17:28:19 +02:00
# ifdef DEBUG
2010-09-08 18:27:58 +02:00
if ( nn ! = rhs . nn ) laerror ( " incompatible dimensions " ) ;
2010-06-25 17:28:19 +02:00
# endif
2010-09-08 18:27:58 +02:00
SAME_LOC ( * this , rhs ) ;
# ifdef CUDALA
if ( location = = cpu ) {
# endif
ret = cblas_ddot ( nn , v , 1 , rhs . v , 1 ) ;
# ifdef CUDALA
} else {
ret = cublasDdot ( nn , v , 1 , rhs . v , 1 ) ;
TEST_CUBLAS ( " cublasDdot " ) ;
}
# endif
return ret ;
2010-06-25 17:28:19 +02:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* computes the inner product of this complex vector \ f $ \ vec { x } \ f $ with given complex vector \ f $ \ vec { y } \ f $
* taking conjugation of vector \ f $ \ vec { x } \ f $ into account
* @ param [ in ] rhs complex vector \ f $ \ vec { y } \ f $
* @ return \ f $ \ sum_ { i = 1 } ^ N \ overbar { \ vec { x } _i } \ cdot \ vec { y } _i \ f $
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2021-04-21 15:04:37 +02:00
inline const std : : complex < double > NRVec < std : : complex < double > > : : operator * ( const NRVec < std : : complex < double > > & rhs ) const {
2010-06-25 17:28:19 +02:00
# ifdef DEBUG
2010-09-08 18:27:58 +02:00
if ( nn ! = rhs . nn ) laerror ( " incompatible dimensions " ) ;
2010-06-25 17:28:19 +02:00
# endif
2021-04-21 15:04:37 +02:00
std : : complex < double > dot ;
2010-09-08 18:27:58 +02:00
SAME_LOC ( * this , rhs ) ;
# ifdef CUDALA
if ( location = = cpu ) {
# endif
cblas_zdotc_sub ( nn , v , 1 , rhs . v , 1 , & dot ) ;
# ifdef CUDALA
} else {
const cuDoubleComplex val = cublasZdotc ( nn , ( cuDoubleComplex * ) v , 1 , ( cuDoubleComplex * ) rhs . v , 1 ) ;
TEST_CUBLAS ( " cublasZdotc " ) ;
2021-04-21 15:04:37 +02:00
dot = std : : complex < double > ( cuCreal ( val ) , cuCimag ( val ) ) ;
2010-09-08 18:27:58 +02:00
}
# endif
2010-06-25 17:28:19 +02:00
return dot ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* computes the inner product of this real vector \ f $ \ vec { x } \ f $ with given real data
* @ param [ in ] y pointer to the double - precision real array ( sufficient length assumed )
* @ param [ in ] stride specifies the stride regarding the data pointe to by < tt > y < / tt >
* @ return \ f $ \ sum_ { i = 1 } ^ N \ vec { x } _ { i } \ cdot y_ { \ mathrm { stride } \ cdot ( i - 1 ) + 1 } \ f $
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2010-09-08 18:27:58 +02:00
inline const double NRVec < double > : : dot ( const double * y , const int stride ) const {
NOT_GPU ( * this ) ;
return cblas_ddot ( nn , y , stride , v , 1 ) ;
2010-06-25 17:28:19 +02:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* computes the inner product of this complex vector \ f $ \ vec { x } \ f $ with given complex data
* @ param [ in ] y pointer to the double - precision complex array ( sufficient length assumed )
* @ param [ in ] stride specifies the stride regarding the data pointe to by < tt > y < / tt >
* @ return \ f $ \ sum_ { i = 1 } ^ N \ vec { x } _ { i } \ cdot \ overbar { y_ { \ mathrm { stride } \ cdot ( i - 1 ) + 1 } } \ f $
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2021-04-21 15:04:37 +02:00
inline const std : : complex < double > NRVec < std : : complex < double > > : : dot ( const std : : complex < double > * y , const int stride ) const {
std : : complex < double > dot ;
2010-09-08 18:27:58 +02:00
NOT_GPU ( * this ) ;
2010-06-25 17:28:19 +02:00
cblas_zdotc_sub ( nn , y , stride , v , 1 , & dot ) ;
return dot ;
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* computes the sum of the absolute values of the elements of this real vector \ f $ \ vec { x } \ f $
* @ return \ f $ \ sum_ { i = 1 } ^ N \ left | \ vec { x } _i \ right | \ f $
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2010-09-08 18:27:58 +02:00
inline const double NRVec < double > : : asum ( ) const {
double ret ( 0.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
ret = cblas_dasum ( nn , v , 1 ) ;
# ifdef CUDALA
} else {
ret = cublasDasum ( nn , v , 1 ) ;
TEST_CUBLAS ( " cublasDasum " ) ;
}
# endif
return ret ;
2010-06-25 17:28:19 +02:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* for this complex vector \ f $ \ vec { x } \ f $ compute the expression
* \ f [ \ sum_ { i = 1 } ^ N \ left | \ Re { } \ vec { x } _i \ right | + \ left | \ Im { } \ vec { x } _i \ right | \ f ]
* @ return the value of this sum
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2021-04-21 15:04:37 +02:00
inline const double NRVec < std : : complex < double > > : : asum ( ) const {
2010-09-08 18:27:58 +02:00
double ret ( 0.0 ) ;
# ifdef CUDALA
if ( location = = cpu ) {
# endif
ret = cblas_dzasum ( nn , v , 1 ) ;
# ifdef CUDALA
} else {
ret = cublasDzasum ( nn , ( cuDoubleComplex * ) v , 1 ) ;
TEST_CUBLAS ( " cublasDzasum " ) ;
}
# endif
return ret ;
}
/***************************************************************************/ /**
* for this real vector \ f $ \ vec { x } \ f $ ( of \ f $ N \ f $ elements ) determine the Frobenius norm
* @ return \ f $ \ sum_ { i = 1 } ^ N \ left | \ vec { x } _i \ right | ^ 2 \ f $
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template < >
2022-06-15 14:42:19 +02:00
inline const double NRVec < double > : : norm ( int length , int offset , int stride ) const {
2010-09-08 18:27:58 +02:00
double ret ( 0. ) ;
# ifdef CUDALA
if ( location = = cpu ) {
# endif
2022-06-15 14:42:19 +02:00
ret = cblas_dnrm2 ( ( length > = 0 ? length : nn ) , v + offset , stride ) ;
2010-09-08 18:27:58 +02:00
# ifdef CUDALA
} else {
2022-06-15 14:42:19 +02:00
ret = cublasDnrm2 ( ( length > = 0 ? length : nn ) , v + offset , stride ) ;
2010-09-08 18:27:58 +02:00
TEST_CUBLAS ( " cublasDnrm2 " ) ;
}
# endif
return ret ;
2010-06-25 17:28:19 +02:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* for this complex vector \ f $ \ vec { x } \ f $ ( of \ f $ N \ f $ elements ) determine the Frobenius norm
* @ return \ f $ \ sum_ { i = 1 } ^ N \ left | \ vec { x } _i \ right | ^ 2 \ f $
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2022-06-15 14:42:19 +02:00
inline const double NRVec < std : : complex < double > > : : norm ( int length , int offset , int stride ) const {
2010-09-08 18:27:58 +02:00
double ret ( 0. ) ;
# ifdef CUDALA
if ( location = = cpu ) {
# endif
2022-06-15 14:42:19 +02:00
ret = cblas_dznrm2 ( ( length > = 0 ? length : nn ) , v + offset , stride ) ;
2010-09-08 18:27:58 +02:00
# ifdef CUDALA
} else {
2022-06-15 14:42:19 +02:00
ret = cublasDznrm2 ( ( length > = 0 ? length : nn ) , ( ( cuDoubleComplex * ) v ) + offset , stride ) ;
2010-09-08 18:27:58 +02:00
TEST_CUBLAS ( " cublasDzrm2 " ) ;
}
# endif
return ret ;
2010-06-25 17:28:19 +02:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* for this real vector \ f $ \ vec { x } \ f $ determine the element with largest absolute value
* @ return \ f $ \ vec { x } _i \ f $ where \ f $ \ left | \ vec { x ] _i \ right | = \ mathrm { max } _ { j } \ left | \ vec { x } _ { j } \ right | \ f $
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-25 17:28:19 +02:00
template < >
2010-09-08 18:27:58 +02:00
inline const double NRVec < double > : : amax ( ) const {
double ret ( 0.0 ) ;
# ifdef CUDALA
if ( location = = cpu ) {
# endif
ret = v [ cblas_idamax ( nn , v , 1 ) - 1 ] ;
# ifdef CUDALA
} else {
const int pozice = cublasIdamax ( nn , v , 1 ) - 1 ;
TEST_CUBLAS ( " cublasIdamax " ) ;
gpuget ( 1 , sizeof ( double ) , v + pozice , & ret ) ;
}
# endif
return ret ;
2010-06-25 17:28:19 +02:00
}
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* for this real vector \ f $ \ vec { x } \ f $ determine the element with smallest absolute value
* @ return \ f $ \ vec { x } _i \ f $ where \ f $ \ left | \ vec { x ] _i \ right | = \ mathrm { min } _ { j } \ left | \ vec { x } _ { j } \ right | \ f $
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template < >
inline const double NRVec < double > : : amin ( ) const {
double ret ( std : : numeric_limits < double > : : max ( ) ) ;
# ifdef CUDALA
if ( location = = cpu ) {
# endif
//BLAS routine idamin seems no to be supported
double val ( 0.0 ) ;
int index ( - 1 ) ;
for ( register int i = 0 ; i < nn ; 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 " ) ;
gpuget ( 1 , sizeof ( double ) , v + pozice , & ret ) ;
}
# endif
return ret ;
}
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* for a given complex vector \ f $ \ vec { v } \ f $ , determine the smallest index of the maximum
* magnitude element , i . e . maximal element in the 1 - norm
* @ return \ f $ \ vec { v } _ { j } \ f $ which maximizes \ f $ \ left \ { \ left | \ Re { } \ vec { v } _ { i } \ right | + \ left | \ Im { } \ vec { v } _ { i } \ right | \ right } \ f $
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template < >
2021-04-21 15:04:37 +02:00
inline const std : : complex < double > NRVec < std : : complex < double > > : : amax ( ) const {
std : : complex < double > ret ( 0. , 0. ) ;
2010-09-08 18:27:58 +02:00
# ifdef CUDALA
if ( location = = cpu ) {
# endif
ret = v [ cblas_izamax ( nn , v , 1 ) - 1 ] ;
# ifdef CUDALA
} else {
const int pozice = cublasIzamax ( nn , ( cuDoubleComplex * ) v , 1 ) - 1 ;
TEST_CUBLAS ( " cublasIzamax " ) ;
2021-04-21 15:04:37 +02:00
gpuget ( 1 , sizeof ( std : : complex < double > ) , v + pozice , & ret ) ;
2010-09-08 18:27:58 +02:00
}
# endif
return ret ;
}
2010-06-25 17:28:19 +02:00
2010-09-08 18:27:58 +02:00
/***************************************************************************/ /**
* for a given complex vector \ f $ \ vec { v } \ f $ , determine the smallest index of the minimum
* magnitude element , i . e . minimal element in the 1 - norm
* @ return \ f $ \ vec { v } _ { j } \ f $ which minimizes \ f $ \ left \ { \ left | \ Re { } \ vec { v } _ { i } \ right | + \ left | \ Im { } \ vec { v } _ { i } \ right | \ right } \ f $
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template < >
2021-04-21 15:04:37 +02:00
inline const std : : complex < double > NRVec < std : : complex < double > > : : amin ( ) const {
std : : complex < double > ret ( 0. , 0. ) ;
2010-09-08 18:27:58 +02:00
# ifdef CUDALA
if ( location = = cpu ) {
# endif
// izamin seems not to be supported
int index ( 0 ) ;
double val ( 0.0 ) , min_val ( std : : numeric_limits < double > : : max ( ) ) ;
2021-04-21 15:04:37 +02:00
std : : complex < double > z_val ( 0.0 , 0.0 ) ;
2010-09-08 18:27:58 +02:00
for ( register int i = 0 ; i < nn ; 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 " ) ;
2021-04-21 15:04:37 +02:00
gpuget ( 1 , sizeof ( std : : complex < double > ) , v + pozice , & ret ) ;
2010-09-08 18:27:58 +02:00
}
# endif
return ret ;
}
2023-03-10 16:39:07 +01:00
/***************************************************************************/ /**
* routine for raw output
* @ param [ in ] fd file descriptor for output
* @ param [ in ] dim number of elements intended for output
* @ param [ in ] transp reserved
* @ see NRMat < T > : : put ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template < typename T >
void NRVec < T > : : put ( int fd , bool dim , bool transp ) const {
# ifdef CUDALA
if ( location ! = cpu ) {
NRVec < T > tmp = * this ;
tmp . moveto ( cpu ) ;
tmp . put ( fd , dim , transp ) ;
return ;
}
# endif
errno = 0 ;
int pad ( 1 ) ; //align at least 8-byte
if ( dim ) {
if ( sizeof ( int ) ! = write ( fd , & nn , sizeof ( int ) ) ) laerror ( " write failed " ) ;
if ( sizeof ( int ) ! = write ( fd , & pad , sizeof ( int ) ) ) laerror ( " write failed " ) ;
}
LA_traits < T > : : multiput ( nn , fd , v , dim ) ;
}
/***************************************************************************/ /**
* routine for raw input
* @ param [ in ] fd file descriptor for input
* @ param [ in ] dim number of elements intended for input , for dim = 0 perform copyonwrite
* @ param [ in ] transp reserved
* @ see NRMat < T > : : get ( ) , copyonwrite ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template < typename T >
void NRVec < T > : : get ( int fd , bool dim , bool transp ) {
# ifdef CUDALA
if ( location ! = cpu ) {
NRVec < T > tmp ;
tmp . moveto ( cpu ) ;
tmp . get ( fd , dim , transp ) ;
tmp . moveto ( location ) ;
* this = tmp ;
return ;
}
# endif
int nn0 [ 2 ] ; //align at least 8-byte
errno = 0 ;
if ( dim ) {
if ( 2 * sizeof ( int ) ! = read ( fd , & nn0 , 2 * sizeof ( int ) ) ) laerror ( " read failed " ) ;
resize ( nn0 [ 0 ] ) ;
} else {
copyonwrite ( ) ;
}
LA_traits < T > : : multiget ( nn , fd , v , dim ) ;
}
2023-04-08 17:31:06 +02:00
//constructor from a list
template < typename T >
NRVec < T > : : NRVec ( const std : : list < T > l ) : NRVec < T > ( l . size ( ) )
{
int ii = 0 ;
for ( typename std : : list < T > : : const_iterator i = l . begin ( ) ; i ! = l . end ( ) ; + + i ) ( * this ) [ ii + + ] = * i ;
}
2024-01-17 17:59:19 +01:00
//general simplification template for a NRVec of a class consisting from a coefficient and an element
//the class T must have traits for sorting, normtype, elementtype, coefficienttype, coefficient, abscoefficient, and operator== which ignores the coefficient and uses just the element
//it is not a member function to avoid the need of extra traits when this is not needed
template < typename T >
void NRVec_simplify ( NRVec < T > & x , const typename LA_traits < T > : : normtype thr = 0 , bool alwayskeepfirst = false )
{
if ( x . size ( ) = = 0 ) return ;
x . copyonwrite ( ) ;
//first sort to identify identical terms
x . sort ( ) ;
//the following operations conserve the sorting, so no need to reset the issorted flag
int newsize = 1 ;
//add factors of identical elements
for ( int next = 1 ; next < x . size ( ) ; + + next )
{
if ( x [ next ] = = x [ newsize - 1 ] )
{
LA_traits < T > : : coefficient ( x [ newsize - 1 ] ) + = LA_traits < T > : : coefficient ( x [ next ] ) ;
}
else
{
if ( next ! = newsize ) x [ newsize ] = x [ next ] ;
+ + newsize ;
}
}
//now skip terms with zero coefficients
int newsize2 = 0 ;
for ( int next = 0 ; next < newsize ; + + next )
{
if ( next = = 0 & & alwayskeepfirst | | ! ( LA_traits < T > : : coefficient ( x [ next ] ) = = 0 | | LA_traits < T > : : abscoefficient ( x [ next ] ) < thr ) )
{
if ( next ! = newsize2 ) x [ newsize2 ] = x [ next ] ;
+ + newsize2 ;
}
}
x . resize ( newsize2 , true ) ;
}
2024-01-18 15:50:11 +01:00
//convert whole vector between types
template < typename T , typename S >
void NRVec_convert ( NRVec < T > & a , const NRVec < S > & b )
{
a . resize ( b . size ( ) ) ;
for ( int i = 0 ; i < b . size ( ) ; + + i )
a [ i ] = ( T ) b [ i ] ;
}
2023-04-08 17:31:06 +02:00
2009-11-12 22:01:19 +01:00
} //namespace
2004-03-17 04:07:21 +01:00
# endif /* _LA_VEC_H_ */