continueing on permutations
This commit is contained in:
parent
83b9463334
commit
78c94f1e17
245
mat.cc
245
mat.cc
@ -27,6 +27,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
namespace LA {
|
namespace LA {
|
||||||
@ -2754,6 +2755,7 @@ NRMat<T>& NRMat<T>::swap_rows(){
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************//**
|
/***************************************************************************//**
|
||||||
* interchange the order of the columns of the current (real) matrix
|
* interchange the order of the columns of the current (real) matrix
|
||||||
* @return reference to the modified matrix
|
* @return reference to the modified matrix
|
||||||
@ -2925,6 +2927,61 @@ NRMat<T>& NRMat<T>::swap_rows(const int a, const int b){
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*rotate rows or columns of a matrix - general implementation, more efficient version could be done with BLAS scal and axpy operations
|
||||||
|
* but it would require allocation of temporary storage
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NRMat<T>& NRMat<T>::rotate_rows(const int a, const int b, const T phi){
|
||||||
|
T tmp1,tmp2;
|
||||||
|
copyonwrite();
|
||||||
|
T c=cos(phi);
|
||||||
|
T s=sin(phi);
|
||||||
|
#ifdef CUDALA
|
||||||
|
if(location == cpu){
|
||||||
|
#endif
|
||||||
|
for(register int j=0;j<mm;j++){
|
||||||
|
tmp1 = (*this)(a,j);
|
||||||
|
tmp2 = (*this)(b,j);
|
||||||
|
(*this)(a,j) = c*tmp1 + s*tmp2;
|
||||||
|
(*this)(b,j) = c*tmp2 - s*tmp1;
|
||||||
|
}
|
||||||
|
#ifdef CUDALA
|
||||||
|
}else{
|
||||||
|
laerror("rotate_rows not implemented on gpu");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NRMat<T>& NRMat<T>::rotate_cols(const int a, const int b, const T phi){
|
||||||
|
T tmp1,tmp2;
|
||||||
|
copyonwrite();
|
||||||
|
T c=cos(phi);
|
||||||
|
T s=sin(phi);
|
||||||
|
#ifdef CUDALA
|
||||||
|
if(location == cpu){
|
||||||
|
#endif
|
||||||
|
for(register int j=0;j<nn;j++){
|
||||||
|
tmp1 = (*this)(j,a);
|
||||||
|
tmp2 = (*this)(j,b);
|
||||||
|
(*this)(j,a) = c*tmp1 + s*tmp2;
|
||||||
|
(*this)(j,b) = c*tmp2 - s*tmp1;
|
||||||
|
}
|
||||||
|
#ifdef CUDALA
|
||||||
|
}else{
|
||||||
|
laerror("rotate_rows not implemented on gpu");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************//**
|
/***************************************************************************//**
|
||||||
* interchange the order of the rows and columns of the current
|
* interchange the order of the rows and columns of the current
|
||||||
* real matrix \f$A\f$ of type T, i.e. perform the operation
|
* real matrix \f$A\f$ of type T, i.e. perform the operation
|
||||||
@ -3075,9 +3132,23 @@ NRMat<T>& NRMat<T>::swap_rows_cols(){
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//permutation matrix
|
||||||
|
template<typename T>
|
||||||
|
NRMat<T>::NRMat(const NRPerm<int> &p, const bool direction)
|
||||||
|
{
|
||||||
|
int n=p.size();
|
||||||
|
resize(n,n);
|
||||||
|
clear();
|
||||||
|
for(int i=0; i<n; ++i)
|
||||||
|
{
|
||||||
|
if(direction) (*this)(i,p[i+1]-1)=1;
|
||||||
|
else (*this)(p[i+1]-1,i)=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//apply permutations
|
//apply permutations
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const NRMat<T> NRMat<T>::permute_rows(const NRPerm<int> &p) const
|
const NRMat<T> NRMat<T>::permuted_rows(const NRPerm<int> &p, const bool inverse) const
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(!p.is_valid()) laerror("invalid permutation of matrix");
|
if(!p.is_valid()) laerror("invalid permutation of matrix");
|
||||||
@ -3088,12 +3159,13 @@ if(n!=nn) laerror("incompatible permutation and matrix");
|
|||||||
if(this->getlocation() != cpu || p.getlocation() != cpu ) laerror("permutations can be done only in CPU memory");
|
if(this->getlocation() != cpu || p.getlocation() != cpu ) laerror("permutations can be done only in CPU memory");
|
||||||
#endif
|
#endif
|
||||||
NRMat<T> r(nn,mm);
|
NRMat<T> r(nn,mm);
|
||||||
for(int i=1; i<=n; ++i) {int pi=p[i]-1; for(int j=0; j<mm; ++j) r(i-1,j) = (*this)(pi,j);}
|
if(inverse) for(int i=1; i<=n; ++i) {int pi=p[i]-1; for(int j=0; j<mm; ++j) r(i-1,j) = (*this)(pi,j);}
|
||||||
|
else for(int i=1; i<=n; ++i) {int pi=p[i]-1; for(int j=0; j<mm; ++j) r(pi,j) = (*this)(i-1,j);}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const NRMat<T> NRMat<T>::permute_cols(const NRPerm<int> &p) const
|
const NRMat<T> NRMat<T>::permuted_cols(const NRPerm<int> &p, const bool inverse) const
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(!p.is_valid()) laerror("invalid permutation of matrix");
|
if(!p.is_valid()) laerror("invalid permutation of matrix");
|
||||||
@ -3104,12 +3176,13 @@ if(n!=mm) laerror("incompatible permutation and matrix");
|
|||||||
if(this->getlocation() != cpu || p.getlocation() != cpu ) laerror("permutations can be done only in CPU memory");
|
if(this->getlocation() != cpu || p.getlocation() != cpu ) laerror("permutations can be done only in CPU memory");
|
||||||
#endif
|
#endif
|
||||||
NRMat<T> r(nn,mm);
|
NRMat<T> r(nn,mm);
|
||||||
for(int i=1; i<=n; ++i) {int pi=p[i]-1; for(int j=0; j<nn; ++j) r(j,i-1) = (*this)(j,pi);}
|
if(inverse) for(int i=1; i<=n; ++i) {int pi=p[i]-1; for(int j=0; j<nn; ++j) r(j,i-1) = (*this)(j,pi);}
|
||||||
|
else for(int i=1; i<=n; ++i) {int pi=p[i]-1; for(int j=0; j<nn; ++j) r(j,pi) = (*this)(j,i-1);}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const NRMat<T> NRMat<T>::permute_both(const NRPerm<int> &p, const NRPerm<int> &q) const
|
const NRMat<T> NRMat<T>::permuted_both(const NRPerm<int> &p, const NRPerm<int> &q, const bool inverse) const
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(!p.is_valid() || !q.is_valid() ) laerror("invalid permutation of matrix");
|
if(!p.is_valid() || !q.is_valid() ) laerror("invalid permutation of matrix");
|
||||||
@ -3121,11 +3194,171 @@ if(n!=nn ||m!=mm) laerror("incompatible permutation and matrix");
|
|||||||
if(this->getlocation() != cpu || p.getlocation() != cpu ) laerror("permutations can be done only in CPU memory");
|
if(this->getlocation() != cpu || p.getlocation() != cpu ) laerror("permutations can be done only in CPU memory");
|
||||||
#endif
|
#endif
|
||||||
NRMat<T> r(nn,mm);
|
NRMat<T> r(nn,mm);
|
||||||
for(int i=1; i<=n; ++i) {int pi=p[i]-1; for(int j=1; j<=m; ++j) r(i-1,j-1) = (*this)(pi,q[j]-1);}
|
if(inverse) for(int i=1; i<=n; ++i) {int pi=p[i]-1; for(int j=1; j<=m; ++j) r(i-1,j-1) = (*this)(pi,q[j]-1);}
|
||||||
|
else for(int i=1; i<=n; ++i) {int pi=p[i]-1; for(int j=1; j<=m; ++j) r(pi,q[j]-1) = (*this)(i-1,j-1);}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void NRMat<T>::permuteme_rows(const CyclePerm<int> &p)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(!p.is_valid()) laerror("invalid permutation of matrix");
|
||||||
|
#endif
|
||||||
|
if(p.max()>nn) laerror("incompatible permutation and matrix");
|
||||||
|
#ifdef CUDALA
|
||||||
|
if(this->getlocation() != cpu || p.getlocation() != cpu ) laerror("permutations can be done only in CPU memory");
|
||||||
|
#endif
|
||||||
|
copyonwrite();
|
||||||
|
T *tmp = new T[mm];
|
||||||
|
for(int cycle=1; cycle<=p.size(); ++cycle)
|
||||||
|
{
|
||||||
|
int length= p[cycle].size();
|
||||||
|
if(length<=1) continue; //trivial cycle
|
||||||
|
for(int j=0; j<mm; ++j) tmp[j] = (*this)(p[cycle][length]-1,j);
|
||||||
|
for(int i=length; i>1; --i)
|
||||||
|
for(int j=0; j<mm; ++j) (*this)(p[cycle][i]-1,j)=(*this)(p[cycle][i-1]-1,j);
|
||||||
|
for(int j=0; j<mm; ++j) (*this)(p[cycle][1]-1,j)=tmp[j];
|
||||||
|
}
|
||||||
|
delete[] tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void NRMat<T>::permuteme_cols(const CyclePerm<int> &p)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(!p.is_valid()) laerror("invalid permutation of matrix");
|
||||||
|
#endif
|
||||||
|
if(p.max()>mm) laerror("incompatible permutation and matrix");
|
||||||
|
#ifdef CUDALA
|
||||||
|
if(this->getlocation() != cpu || p.getlocation() != cpu ) laerror("permutations can be done only in CPU memory");
|
||||||
|
#endif
|
||||||
|
copyonwrite();
|
||||||
|
T *tmp = new T[nn];
|
||||||
|
for(int cycle=1; cycle<=p.size(); ++cycle)
|
||||||
|
{
|
||||||
|
int length= p[cycle].size();
|
||||||
|
if(length<=1) continue; //trivial cycle
|
||||||
|
for(int j=0; j<nn; ++j) tmp[j] = (*this)(j,p[cycle][length]-1);
|
||||||
|
for(int i=length; i>1; --i)
|
||||||
|
for(int j=0; j<nn; ++j) (*this)(j,p[cycle][i]-1)=(*this)(j,p[cycle][i-1]-1);
|
||||||
|
for(int j=0; j<nn; ++j) (*this)(j,p[cycle][1]-1)=tmp[j];
|
||||||
|
}
|
||||||
|
delete[] tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//double and complex specialization
|
||||||
|
template<>
|
||||||
|
void NRMat<double>::scale_row(const int i, const double f)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(i<0||i>=nn) laerror("index out of range in scale_row");
|
||||||
|
#endif
|
||||||
|
copyonwrite();
|
||||||
|
#ifdef CUDALA
|
||||||
|
if(location == cpu) {
|
||||||
|
#endif
|
||||||
|
cblas_dscal(mm, f, &(*this)(i,0), 1);
|
||||||
|
#ifdef CUDALA
|
||||||
|
}else{
|
||||||
|
cublasDscal(mm, f, v+i*mm, 1);
|
||||||
|
TEST_CUBLAS("cublasDscal");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void NRMat<double>::scale_col(const int i, const double f)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(i<0||i>=mm) laerror("index out of range in scale_col");
|
||||||
|
#endif
|
||||||
|
copyonwrite();
|
||||||
|
#ifdef CUDALA
|
||||||
|
if(location == cpu) {
|
||||||
|
#endif
|
||||||
|
cblas_dscal(nn, f, &(*this)(0,i), mm);
|
||||||
|
#ifdef CUDALA
|
||||||
|
}else{
|
||||||
|
cublasDscal(nn, f, v+i, mm);
|
||||||
|
TEST_CUBLAS("cublasDscal");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void NRMat<std::complex<double> >::scale_row(const int i, const std::complex<double> f)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(i<0||i>=nn) laerror("index out of range in scale_row");
|
||||||
|
#endif
|
||||||
|
copyonwrite();
|
||||||
|
#ifdef CUDALA
|
||||||
|
if(location == cpu) {
|
||||||
|
#endif
|
||||||
|
cblas_zscal(mm, &f, &(*this)(i,0), 1);
|
||||||
|
#ifdef CUDALA
|
||||||
|
}else{
|
||||||
|
const cuDoubleComplex fac = *(reinterpret_cast<const cuDoubleComplex*> (&f));
|
||||||
|
cublasZscal(mm, &fac, v+i*mm, 1);
|
||||||
|
TEST_CUBLAS("cublasDscal");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void NRMat<std::complex<double> >::scale_col(const int i, const std::complex<double> f)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(i<0||i>=mm) laerror("index out of range in scale_col");
|
||||||
|
#endif
|
||||||
|
copyonwrite();
|
||||||
|
#ifdef CUDALA
|
||||||
|
if(location == cpu) {
|
||||||
|
#endif
|
||||||
|
cblas_zscal(nn, &f, &(*this)(0,i), mm);
|
||||||
|
#ifdef CUDALA
|
||||||
|
}else{
|
||||||
|
const cuDoubleComplex fac = *(reinterpret_cast<const cuDoubleComplex*> (&f));
|
||||||
|
cublasZscal(nn, &fac, v+i, mm);
|
||||||
|
TEST_CUBLAS("cublasDscal");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//general version
|
||||||
|
template<typename T>
|
||||||
|
void NRMat<T>::scale_row(const int i, const T f)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(i<0||i>=nn) laerror("index out of range in scale_row");
|
||||||
|
#endif
|
||||||
|
copyonwrite();
|
||||||
|
for(int j=0; j<mm; ++j) (*this)(i,j) *= f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void NRMat<T>::scale_col(const int i, const T f)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(i<0||i>=mm) laerror("index out of range in scale_col");
|
||||||
|
#endif
|
||||||
|
copyonwrite();
|
||||||
|
for(int j=0; j<nn; ++j) (*this)(j,i) *= f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************//**
|
/***************************************************************************//**
|
||||||
|
16
mat.h
16
mat.h
@ -117,9 +117,14 @@ public:
|
|||||||
void copyonwrite(bool detachonly=false);
|
void copyonwrite(bool detachonly=false);
|
||||||
|
|
||||||
//! permute matrix elements
|
//! permute matrix elements
|
||||||
const NRMat permute_rows(const NRPerm<int> &p) const;
|
const NRMat permuted_rows(const NRPerm<int> &p, const bool inverse=false) const;
|
||||||
const NRMat permute_cols(const NRPerm<int> &p) const;
|
const NRMat permuted_cols(const NRPerm<int> &p, const bool inverse=false) const;
|
||||||
const NRMat permute_both(const NRPerm<int> &p, const NRPerm<int> &q) const;
|
const NRMat permuted_both(const NRPerm<int> &p, const NRPerm<int> &q, const bool inverse=false) const;
|
||||||
|
void permuteme_rows(const CyclePerm<int> &p); //in place
|
||||||
|
void permuteme_cols(const CyclePerm<int> &p); //in place
|
||||||
|
void scale_row(const int i, const T f); //in place
|
||||||
|
void scale_col(const int i, const T f); //in place
|
||||||
|
explicit NRMat(const NRPerm<int> &p, const bool direction); //permutation matrix
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************//**
|
/***************************************************************************//**
|
||||||
@ -349,6 +354,11 @@ public:
|
|||||||
// LV - swapping of rows i and j
|
// LV - swapping of rows i and j
|
||||||
NRMat & swap_rows(const int i, const int j);
|
NRMat & swap_rows(const int i, const int j);
|
||||||
|
|
||||||
|
//rotate rows or columns through an angle
|
||||||
|
NRMat & rotate_cols(const int i, const int j, const T phi);
|
||||||
|
NRMat & rotate_rows(const int i, const int j, const T phi);
|
||||||
|
|
||||||
|
|
||||||
//! multiply by sparse matrix
|
//! multiply by sparse matrix
|
||||||
SparseSMat<T> operator*(const SparseSMat<T> &rhs) const;
|
SparseSMat<T> operator*(const SparseSMat<T> &rhs) const;
|
||||||
|
|
||||||
|
153
permutation.cc
153
permutation.cc
@ -17,6 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "permutation.h"
|
#include "permutation.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
namespace LA {
|
namespace LA {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -27,6 +31,7 @@ T n=this->size();
|
|||||||
if(n<0) laerror("invalid permutation size");
|
if(n<0) laerror("invalid permutation size");
|
||||||
#endif
|
#endif
|
||||||
if(n==0) return;
|
if(n==0) return;
|
||||||
|
this->copyonwrite();
|
||||||
for(T i=1; i<=n; ++i) (*this)[i]=i;
|
for(T i=1; i<=n; ++i) (*this)[i]=i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,12 +123,14 @@ return (count&1)? -1:1;
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
NRPerm<T>::NRPerm(const CyclePerm<T> &rhs, int n)
|
NRPerm<T>::NRPerm(const CyclePerm<T> &rhs, const int n)
|
||||||
: NRVec_from1<T>(n)
|
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(!rhs.is_valid()) laerror("invalid cycle permutation");
|
if(!rhs.is_valid()) laerror("invalid cycle permutation");
|
||||||
#endif
|
#endif
|
||||||
|
int m;
|
||||||
|
if(n) m=n; else m=rhs.max();
|
||||||
|
this->resize(m);
|
||||||
|
|
||||||
identity();
|
identity();
|
||||||
T ncycles=rhs.size();
|
T ncycles=rhs.size();
|
||||||
@ -137,6 +144,22 @@ if(!is_valid()) laerror("internal error in NRPerm constructor from CyclePerm");
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void NRPerm<T>::randomize(void)
|
||||||
|
{
|
||||||
|
int n=this->size();
|
||||||
|
if(n<=0) laerror("cannot randomize empty permutation");
|
||||||
|
this->copyonwrite();
|
||||||
|
this->identity();
|
||||||
|
for(int i=n-1; i>=1; --i)
|
||||||
|
{
|
||||||
|
int j= random()%(i+1);
|
||||||
|
T tmp = (*this)[i+1];
|
||||||
|
(*this)[i+1]=(*this)[j+1];
|
||||||
|
(*this)[j+1]=tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -150,7 +173,7 @@ T n=p.size();
|
|||||||
NRVec_from1<T> used(0,n),tmp(n);
|
NRVec_from1<T> used(0,n),tmp(n);
|
||||||
T firstunused=1;
|
T firstunused=1;
|
||||||
T currentcycle=0;
|
T currentcycle=0;
|
||||||
std::list<NRVec<T> > cyclelist={};
|
std::list<NRVec_from1<T> > cyclelist={};
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
//find a cycle starting with first unused element
|
//find a cycle starting with first unused element
|
||||||
@ -196,7 +219,7 @@ for(T i=1; i<=this->size(); ++i)
|
|||||||
for(T ii=i; ii<=this->size(); ++ii)
|
for(T ii=i; ii<=this->size(); ++ii)
|
||||||
{
|
{
|
||||||
T nn=(*this)[ii].size();
|
T nn=(*this)[ii].size();
|
||||||
for(T jj=1; jj<=nn; ++jj)
|
for(T jj=(ii==i?j+1:1); jj<=nn; ++jj)
|
||||||
{
|
{
|
||||||
T xx=(*this)[ii][jj];
|
T xx=(*this)[ii][jj];
|
||||||
if(x==xx) return false;
|
if(x==xx) return false;
|
||||||
@ -233,11 +256,24 @@ for(T i=1; i<=ncycles; ++i)
|
|||||||
{
|
{
|
||||||
T length=(*this)[i].size();
|
T length=(*this)[i].size();
|
||||||
r[i].resize(length);
|
r[i].resize(length);
|
||||||
|
//reverse order in cycles (does not matter in cycle lengths 1 and 2 anyway)
|
||||||
for(T j=1; j<=length; ++j) r[i][j] = (*this)[i][length-j+1];
|
for(T j=1; j<=length; ++j) r[i][j] = (*this)[i][length-j+1];
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//multiplication via NRPerm - could there be a more efficient direct algorithm?
|
||||||
|
template <typename T>
|
||||||
|
CyclePerm<T> CyclePerm<T>::operator*(const CyclePerm q) const
|
||||||
|
{
|
||||||
|
int m=this->max();
|
||||||
|
int mm=q.max();
|
||||||
|
if(mm>m) mm=m;
|
||||||
|
NRPerm<T> qq(q,m);
|
||||||
|
NRPerm<T> pp(*this,m);
|
||||||
|
NRPerm<T> rr=pp*qq;
|
||||||
|
return CyclePerm<T>(rr);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int CyclePerm<T>::parity() const
|
int CyclePerm<T>::parity() const
|
||||||
@ -271,12 +307,105 @@ for(T i=1; i<=ncycles; ++i)
|
|||||||
r[length]++;
|
r[length]++;
|
||||||
}
|
}
|
||||||
//fill in trivial cycles of length one
|
//fill in trivial cycles of length one
|
||||||
r[1] = n - r.sum();
|
r[1] += n - r.sum();
|
||||||
if(r[1]<0) laerror("inconsistent cycle lengths in CyclePerm::cycles");
|
if(r[1]<0) laerror("inconsistent cycle lengths in CyclePerm::cycles");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//auxiliary function for input of a permutation in cycle format
|
||||||
|
//returns pointer after closing bracket or NULL if no cycle found
|
||||||
|
//or input error
|
||||||
|
template <typename T>
|
||||||
|
const char *read1cycle(NRVec_from1<T> &c, const char *p)
|
||||||
|
{
|
||||||
|
if(*p==0) return NULL;
|
||||||
|
const char *openbracket = strchr(p,'(');
|
||||||
|
if(!openbracket) return NULL;
|
||||||
|
const char *closebracket = strchr(openbracket+1,')');
|
||||||
|
if(!closebracket) return NULL;
|
||||||
|
const char *s = openbracket+1;
|
||||||
|
int r;
|
||||||
|
int length=0;
|
||||||
|
std::list<T> cycle;
|
||||||
|
do {
|
||||||
|
long int tmp;
|
||||||
|
int nchar;
|
||||||
|
if(*s==',') ++s;
|
||||||
|
r = sscanf(s,"%ld%n",&tmp,&nchar);
|
||||||
|
if(r==1)
|
||||||
|
{
|
||||||
|
++length;
|
||||||
|
s += nchar;
|
||||||
|
cycle.push_back((T)tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(r==1 && s<closebracket);
|
||||||
|
|
||||||
|
//make vector from list
|
||||||
|
c.resize(length);
|
||||||
|
int i=0;
|
||||||
|
for(auto l=cycle.begin(); l!=cycle.end(); ++l) c[++i] = *l;
|
||||||
|
|
||||||
|
return closebracket+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void CyclePerm<T>::readfrom(const std::string &line)
|
||||||
|
{
|
||||||
|
const char *p=line.c_str();
|
||||||
|
std::list<NRVec<T> > cyclelist={};
|
||||||
|
int ncycles=0;
|
||||||
|
int count=0;
|
||||||
|
NRVec_from1<T> c;
|
||||||
|
while(p=read1cycle(c,p))
|
||||||
|
{
|
||||||
|
//printf("cycle %d of length %d read\n",count,c.size());
|
||||||
|
if(c.size()!=0) //store a nonempty cycle
|
||||||
|
{
|
||||||
|
++count;
|
||||||
|
cyclelist.push_back(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//convert list to vector
|
||||||
|
this->resize(count);
|
||||||
|
T i=0;
|
||||||
|
for(auto l=cyclelist.begin(); l!=cyclelist.end(); ++l) (*this)[++i] = *l;
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(!this->is_valid()) laerror("readfrom received input of invalid CyclePerm");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::istream & operator>>(std::istream &s, CyclePerm<T> &x)
|
||||||
|
{
|
||||||
|
std::string l;
|
||||||
|
getline(s,l);
|
||||||
|
x.readfrom(l);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::ostream & operator<<(std::ostream &s, const CyclePerm<T> &x)
|
||||||
|
{
|
||||||
|
for(int i=1; i<=x.size(); ++i)
|
||||||
|
{
|
||||||
|
s<<"(";
|
||||||
|
for(int j=1; j<=x[i].size(); ++j)
|
||||||
|
{
|
||||||
|
s<<x[i][j];
|
||||||
|
if(j<x[i].size()) s<<" ";
|
||||||
|
}
|
||||||
|
s<<")";
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
@ -286,4 +415,16 @@ return r;
|
|||||||
template class NRPerm<int>;
|
template class NRPerm<int>;
|
||||||
template class CyclePerm<int>;
|
template class CyclePerm<int>;
|
||||||
template class Partition<int>;
|
template class Partition<int>;
|
||||||
}
|
|
||||||
|
#define INSTANTIZE(T) \
|
||||||
|
template std::istream & operator>>(std::istream &s, CyclePerm<T> &x); \
|
||||||
|
template std::ostream & operator<<(std::ostream &s, const CyclePerm<T> &x); \
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
INSTANTIZE(int)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}//namespace
|
||||||
|
@ -41,7 +41,7 @@ public:
|
|||||||
NRPerm(const NRVec_from1<T> &rhs): NRVec_from1<T>(rhs) {};
|
NRPerm(const NRVec_from1<T> &rhs): NRVec_from1<T>(rhs) {};
|
||||||
NRPerm(const T &a, const int n): NRVec_from1<T>(a, n) {};
|
NRPerm(const T &a, const int n): NRVec_from1<T>(a, n) {};
|
||||||
NRPerm(const T *a, const int n): NRVec_from1<T>(a, n) {};
|
NRPerm(const T *a, const int n): NRVec_from1<T>(a, n) {};
|
||||||
NRPerm(const CyclePerm<T> &rhs, int n);
|
explicit NRPerm(const CyclePerm<T> &rhs, const int n=0);
|
||||||
|
|
||||||
//specific operations
|
//specific operations
|
||||||
void identity();
|
void identity();
|
||||||
@ -51,10 +51,10 @@ public:
|
|||||||
NRPerm operator*(const NRPerm q) const; //q is rhs and applied first, this applied second
|
NRPerm operator*(const NRPerm q) const; //q is rhs and applied first, this applied second
|
||||||
NRPerm conjugate_by(const NRPerm q) const; //q^-1 p q
|
NRPerm conjugate_by(const NRPerm q) const; //q^-1 p q
|
||||||
int parity() const;
|
int parity() const;
|
||||||
|
void randomize(void); //uniformly random by Fisher-Yates shuffle
|
||||||
|
|
||||||
|
|
||||||
//TODO:
|
//TODO:
|
||||||
//@@@permutation matrix
|
|
||||||
//@@@permgener
|
//@@@permgener
|
||||||
//@@@next permutation
|
//@@@next permutation
|
||||||
//@@@lex rank
|
//@@@lex rank
|
||||||
@ -67,19 +67,27 @@ template <typename T>
|
|||||||
class CyclePerm : public NRVec_from1<NRVec_from1<T> > {
|
class CyclePerm : public NRVec_from1<NRVec_from1<T> > {
|
||||||
public:
|
public:
|
||||||
CyclePerm() : NRVec_from1<NRVec_from1<T> >() {};
|
CyclePerm() : NRVec_from1<NRVec_from1<T> >() {};
|
||||||
CyclePerm(const NRPerm<T> &rhs);
|
explicit CyclePerm(const NRPerm<T> &rhs);
|
||||||
|
|
||||||
bool is_valid() const; //is it really a permutation
|
bool is_valid() const; //is it really a permutation
|
||||||
bool is_identity() const; //no cycles of length > 1
|
bool is_identity() const; //no cycles of length > 1
|
||||||
CyclePerm inverse() const; //reverse all cycles
|
CyclePerm inverse() const; //reverse all cycles
|
||||||
int parity() const; //negative if having odd number of even-length cycles
|
int parity() const; //negative if having odd number of even-length cycles
|
||||||
|
T max() const {T m=0; for(int i=1; i<=this->size(); ++i) {T mm= (*this)[i].max(); if(mm>m) m=mm;} return m;}
|
||||||
Partition<T> cycles(const T n) const;
|
Partition<T> cycles(const T n) const;
|
||||||
//@@@efficient algorithm for multiplication?
|
void readfrom(const std::string &line);
|
||||||
//@@@operator >> and <<
|
CyclePerm operator*(const CyclePerm q) const; //q is rhs and applied first, this applied second
|
||||||
//@@@operation in place on matrix and vector
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::istream & operator>>(std::istream &s, CyclePerm<T> &x);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::ostream & operator<<(std::ostream &s, const CyclePerm<T> &x);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//partitions stored as #of 1s, #of 2s, etc.
|
//partitions stored as #of 1s, #of 2s, etc.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Partition : public NRVec_from1<T> {
|
class Partition : public NRVec_from1<T> {
|
||||||
@ -94,8 +102,8 @@ public:
|
|||||||
//@@@generate all partitions,
|
//@@@generate all partitions,
|
||||||
//@@@enumerator of partitions of n to r parts and total
|
//@@@enumerator of partitions of n to r parts and total
|
||||||
//@@@adjoint partition,
|
//@@@adjoint partition,
|
||||||
//@@@ output as in the group character table
|
//@@@output formatted as in the group character table
|
||||||
//@@@Sn character table
|
//@@@Sn character table computation
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
5
smat.cc
5
smat.cc
@ -305,7 +305,7 @@ void NRSMat<T>::fscanf(FILE *f, const char *format) {
|
|||||||
|
|
||||||
//apply permutation
|
//apply permutation
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const NRSMat<T> NRSMat<T>::permute(const NRPerm<int> &p) const
|
const NRSMat<T> NRSMat<T>::permuted(const NRPerm<int> &p, const bool inverse) const
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(!p.is_valid()) laerror("invalid permutation of smatrix");
|
if(!p.is_valid()) laerror("invalid permutation of smatrix");
|
||||||
@ -316,7 +316,8 @@ if(n!=(*this).size()) laerror("incompatible permutation and smatrix");
|
|||||||
if(this->getlocation() != cpu || p.getlocation() != cpu ) laerror("permutations can be done only in CPU memory");
|
if(this->getlocation() != cpu || p.getlocation() != cpu ) laerror("permutations can be done only in CPU memory");
|
||||||
#endif
|
#endif
|
||||||
NRSMat<T> r(n);
|
NRSMat<T> r(n);
|
||||||
for(int i=1; i<=n; ++i) {int pi = p[i]-1; r(i-1,i-1) = (*this)(pi,pi);}
|
if(inverse) for(int i=1; i<=n; ++i) {int pi = p[i]-1; r(i-1,i-1) = (*this)(pi,pi);}
|
||||||
|
else for(int i=1; i<=n; ++i) {int pi = p[i]-1; r(pi,pi) = (*this)(i-1,i-1);}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
smat.h
2
smat.h
@ -93,7 +93,7 @@ public:
|
|||||||
NRSMat & operator=(const T &a);
|
NRSMat & operator=(const T &a);
|
||||||
|
|
||||||
//! permute matrix elements
|
//! permute matrix elements
|
||||||
const NRSMat permute(const NRPerm<int> &p) const;
|
const NRSMat permuted(const NRPerm<int> &p, const bool inverse=false) const;
|
||||||
|
|
||||||
inline int getcount() const {return count?*count:0;}
|
inline int getcount() const {return count?*count:0;}
|
||||||
|
|
||||||
|
63
t.cc
63
t.cc
@ -1989,7 +1989,7 @@ c=a+b;
|
|||||||
cout<<c;
|
cout<<c;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(1)
|
if(0)
|
||||||
{
|
{
|
||||||
NRPerm<int> p;
|
NRPerm<int> p;
|
||||||
cin >>p;
|
cin >>p;
|
||||||
@ -1997,8 +1997,67 @@ int n=p.size();
|
|||||||
NRVec_from1<double> v(n);
|
NRVec_from1<double> v(n);
|
||||||
int i;
|
int i;
|
||||||
for(i=1; i<=n; ++i) v[i]=10.*i;
|
for(i=1; i<=n; ++i) v[i]=10.*i;
|
||||||
cout <<v.permute(p);
|
cout <<v.permuted(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(0)
|
||||||
|
{
|
||||||
|
CyclePerm<int> c;
|
||||||
|
cin>>c;
|
||||||
|
cout<<c<<endl;
|
||||||
|
NRPerm<int> p(c);
|
||||||
|
cout <<p;
|
||||||
|
CyclePerm<int> cc(p);
|
||||||
|
cout <<cc<<endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(0)
|
||||||
|
{
|
||||||
|
int seed;
|
||||||
|
int f=open("/dev/random",O_RDONLY);
|
||||||
|
if(sizeof(int)!=read(f,&seed,sizeof(int))) laerror("cannot read /dev/random");
|
||||||
|
close(f);
|
||||||
|
srand(seed);
|
||||||
|
int n;
|
||||||
|
cin >>n;
|
||||||
|
NRPerm<int> p(n);
|
||||||
|
p.randomize();
|
||||||
|
cout <<p;
|
||||||
|
CyclePerm<int> cc(p);
|
||||||
|
cout <<cc<<endl;
|
||||||
|
NRPerm<int> pp(cc,n);
|
||||||
|
cout <<pp;
|
||||||
|
if(pp!=p) laerror("inconsistency");
|
||||||
|
NRVec<double> v(n);
|
||||||
|
for(int i=0; i<n; ++i) v[i]=10.*(i+1);
|
||||||
|
NRVec<double> vv(v);
|
||||||
|
v.permuteme(cc);
|
||||||
|
cout <<v;
|
||||||
|
NRVec<double> vvv= vv.permuted(pp);
|
||||||
|
cout<<vvv;
|
||||||
|
cout<<"error "<<(v-vvv).norm()<<endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(1)
|
||||||
|
{
|
||||||
|
int seed;
|
||||||
|
int f=open("/dev/random",O_RDONLY);
|
||||||
|
if(sizeof(int)!=read(f,&seed,sizeof(int))) laerror("cannot read /dev/random");
|
||||||
|
close(f);
|
||||||
|
srand(seed);
|
||||||
|
int n;
|
||||||
|
cin >>n;
|
||||||
|
NRVec<double> v(n);
|
||||||
|
v.randomize(1.);
|
||||||
|
NRVec<double> vv(v);
|
||||||
|
NRPerm<int> p(n);
|
||||||
|
vv.sort(0,p);
|
||||||
|
NRVec<double> vvv=v.permuted(p,true);
|
||||||
|
NRVec<double> v4=vv.permuted(p,false);
|
||||||
|
cout<<v<<vv;
|
||||||
|
cout<<vvv<<v4<<p;
|
||||||
|
cout <<"error "<<(vv-vvv).norm() <<" "<<(v-v4).norm()<<endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
69
vec.cc
69
vec.cc
@ -815,6 +815,15 @@ int NRVec<T>::sort(int direction, int from, int to, int *perm) {
|
|||||||
else return memqsort<0, NRVec<T>, int, int>(*this, perm, from, to);
|
else return memqsort<0, NRVec<T>, int, int>(*this, perm, from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
int NRVec<T>::sort(int direction, NRPerm<int> &perm)
|
||||||
|
{
|
||||||
|
if(nn!=perm.size()) laerror("incompatible vector and permutation");
|
||||||
|
perm.identity();
|
||||||
|
int r=sort(direction,0,nn-1,&perm[1]);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
NRVec<std::complex<double> > complexify(const NRVec<double> &rhs) {
|
NRVec<std::complex<double> > complexify(const NRVec<double> &rhs) {
|
||||||
NRVec<std::complex<double> > r(rhs.size(), rhs.getlocation());
|
NRVec<std::complex<double> > r(rhs.size(), rhs.getlocation());
|
||||||
@ -834,7 +843,7 @@ NRVec<std::complex<double> > complexify(const NRVec<double> &rhs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const NRVec<T> NRVec<T>::permute(const NRPerm<int> &p) const
|
const NRVec<T> NRVec<T>::permuted(const NRPerm<int> &p, const bool inverse) const
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(!p.is_valid()) laerror("invalid permutation of vector");
|
if(!p.is_valid()) laerror("invalid permutation of vector");
|
||||||
@ -845,10 +854,34 @@ if(n!=(*this).size()) laerror("incompatible permutation and vector");
|
|||||||
if(this->getlocation() != cpu || p.getlocation() != cpu ) laerror("permutations can be done only in CPU memory");
|
if(this->getlocation() != cpu || p.getlocation() != cpu ) laerror("permutations can be done only in CPU memory");
|
||||||
#endif
|
#endif
|
||||||
NRVec<T> r(n);
|
NRVec<T> r(n);
|
||||||
for(int i=1; i<=n; ++i) r[i-1] = v[p[i]-1];
|
if(inverse) for(int i=1; i<=n; ++i) r[i-1] = v[p[i]-1];
|
||||||
|
else for(int i=1; i<=n; ++i) r[p[i]-1] = v[i-1];
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void NRVec<T>::permuteme(const CyclePerm<int> &p)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(!p.is_valid()) laerror("invalid permutation of vector");
|
||||||
|
#endif
|
||||||
|
if(p.max()>nn) laerror("incompatible permutation and vector");
|
||||||
|
#ifdef CUDALA
|
||||||
|
if(this->getlocation() != cpu || p.getlocation() != cpu ) laerror("permutations can be done only in CPU memory");
|
||||||
|
#endif
|
||||||
|
copyonwrite();
|
||||||
|
for(int cycle=1; cycle<=p.size(); ++cycle)
|
||||||
|
{
|
||||||
|
int length= p[cycle].size();
|
||||||
|
if(length<=1) continue; //trivial cycle
|
||||||
|
T tmp = v[p[cycle][length]-1];
|
||||||
|
for(int i=length; i>1; --i) v[p[cycle][i]-1] = v[p[cycle][i-1]-1];
|
||||||
|
v[p[cycle][1]-1] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************//**
|
/***************************************************************************//**
|
||||||
* forced instantization in the corespoding object file
|
* forced instantization in the corespoding object file
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@ -911,6 +944,38 @@ INSTANTIZE_DUMMY(std::complex<unsigned long long>)
|
|||||||
INSTANTIZE_DUMMY(std::complex<std::complex<double> >)
|
INSTANTIZE_DUMMY(std::complex<std::complex<double> >)
|
||||||
INSTANTIZE_DUMMY(std::complex<std::complex<float> >)
|
INSTANTIZE_DUMMY(std::complex<std::complex<float> >)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//also not supported on gpu
|
||||||
|
#define INSTANTIZE_NONCOMPLEX(T) \
|
||||||
|
template<>\
|
||||||
|
const T NRVec<T>::max() const\
|
||||||
|
{\
|
||||||
|
if(nn==0) return 0;\
|
||||||
|
T m=v[0];\
|
||||||
|
for(int i=1; i<nn; ++i) if(v[i]>m) m=v[i];\
|
||||||
|
return m;\
|
||||||
|
}\
|
||||||
|
\
|
||||||
|
template<>\
|
||||||
|
const T NRVec<T>::min() const\
|
||||||
|
{\
|
||||||
|
if(nn==0) return 0;\
|
||||||
|
T m=v[0];\
|
||||||
|
for(int i=1; i<nn; ++i) if(v[i]<m) m=v[i];\
|
||||||
|
return m;\
|
||||||
|
}\
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
INSTANTIZE_NONCOMPLEX(char)
|
||||||
|
INSTANTIZE_NONCOMPLEX(short)
|
||||||
|
INSTANTIZE_NONCOMPLEX(int)
|
||||||
|
INSTANTIZE_NONCOMPLEX(long)
|
||||||
|
INSTANTIZE_NONCOMPLEX(long long)
|
||||||
|
INSTANTIZE_NONCOMPLEX(float)
|
||||||
|
INSTANTIZE_NONCOMPLEX(double)
|
||||||
|
|
||||||
template class NRVec<double>;
|
template class NRVec<double>;
|
||||||
template class NRVec<std::complex<double> >;
|
template class NRVec<std::complex<double> >;
|
||||||
template class NRVec<char>;
|
template class NRVec<char>;
|
||||||
|
12
vec.h
12
vec.h
@ -271,7 +271,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
//! permute vector elements
|
//! permute vector elements
|
||||||
const NRVec permute(const NRPerm<int> &p) const;
|
const NRVec permuted(const NRPerm<int> &p, const bool inverse=false) const;
|
||||||
|
void permuteme(const CyclePerm<int> &p); //in place
|
||||||
|
|
||||||
//! compute the sum of the absolute values of the elements of this vector
|
//! compute the sum of the absolute values of the elements of this vector
|
||||||
inline const typename LA_traits<T>::normtype asum() const;
|
inline const typename LA_traits<T>::normtype asum() const;
|
||||||
@ -318,6 +319,12 @@ public:
|
|||||||
//! determine the minimal element (in the absolute value) of this vector
|
//! determine the minimal element (in the absolute value) of this vector
|
||||||
inline const T amin() const;
|
inline const T amin() const;
|
||||||
|
|
||||||
|
//! determine the maximal element of this vector
|
||||||
|
const T max() const;
|
||||||
|
//! determine the minimal element of this vector
|
||||||
|
const T min() const;
|
||||||
|
|
||||||
|
|
||||||
//! routine for formatted output
|
//! routine for formatted output
|
||||||
void fprintf(FILE *f, const char *format, const int modulo) const;
|
void fprintf(FILE *f, const char *format, const int modulo) const;
|
||||||
//! routine for unformatted output
|
//! routine for unformatted output
|
||||||
@ -355,6 +362,7 @@ public:
|
|||||||
|
|
||||||
//! sort by default in ascending order and return the parity of corresponding permutation resulting to this order
|
//! sort by default in ascending order and return the parity of corresponding permutation resulting to this order
|
||||||
int sort(int direction = 0, int from = 0, int to = -1, int *perm = NULL);
|
int sort(int direction = 0, int from = 0, int to = -1, int *perm = NULL);
|
||||||
|
int sort(int direction, NRPerm<int> &perm);
|
||||||
|
|
||||||
//! apply given function to each element
|
//! apply given function to each element
|
||||||
NRVec& call_on_me(T (*_F)(const T &) ){
|
NRVec& call_on_me(T (*_F)(const T &) ){
|
||||||
@ -1082,6 +1090,8 @@ void NRVec<T>::moveto(const GPUID dest) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************//**
|
/***************************************************************************//**
|
||||||
* adds a real scalar value \f$\alpha\f$ to all elements of this real vector \f$\vec{x}\f$
|
* 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]
|
* \f[\vec{x}_i\leftarrow\vec{x}_i+\alpha\f]
|
||||||
|
Loading…
Reference in New Issue
Block a user