22 #ifndef __PLUMED_tools_Matrix_h
23 #define __PLUMED_tools_Matrix_h
32 #if defined(F77_NO_UNDERSCORE)
34 #define F77_FUNC(name,NAME) name
37 #define F77_FUNC(name,NAME) name ## _
43 double *
a,
int *
lda,
double *
vl,
double *
vu,
int *
54 template <
typename T> T
dotProduct(
const std::vector<T>& A,
const std::vector<T>& B ){
55 plumed_assert( A.size()==B.size() );
56 T val;
for(
unsigned i=0;i<A.size();++i){ val+=A[i]*B[i]; }
61 template <
typename T> T
norm(
const std::vector<T>& A ){
62 T val;
for(
unsigned i=0;i<A.size();++i){ val+=A[i]*A[i]; }
74 template <
typename U>
friend void mult(
const Matrix<U>&,
const std::vector<U>& , std::vector<U>& );
76 template <
typename U>
friend void mult(
const std::vector<U>&,
const Matrix<U>&, std::vector<U>& );
80 template <
typename U>
friend Log& operator<<(Log&, const Matrix<U>& );
92 template <
typename U>
friend void chol_elsolve(
const Matrix<U>& ,
const std::vector<U>& , std::vector<U>& );
103 Matrix(
const unsigned nr=0,
const unsigned nc=0 ) : sz(nr*nc), rw(nr), cl(nc), data(nr*nc) {}
106 void resize(
const unsigned nr,
const unsigned nc ){ rw=nr; cl=nc; sz=nr*nc; data.resize(sz); }
112 inline T
operator () (
const unsigned& i,
const unsigned& j)
const {
return data[j+i*
cl]; }
114 inline T&
operator () (
const unsigned& i,
const unsigned& j) {
return data[j+i*
cl]; }
117 for(
unsigned i=0;i<
sz;++i){ data[i]=v; }
130 plumed_dbg_assert( v.size()==
sz );
131 for(
unsigned i=0;i<
sz;++i){ data[i]=v[i]; }
136 for(
unsigned i=0;i<
sz;++i){ data[i]+=v; }
141 plumed_dbg_assert( m.
rw==rw && m.
cl==cl );
147 for(
unsigned i=0;i<
sz;++i){ data-=v; }
152 plumed_dbg_assert( m.
rw==rw && m.
cl==cl );
158 if (rw!=cl){
return 0; }
160 for(
unsigned i=1;i<
rw;++i)
for(
unsigned j=0;j<i;++j)
if( std::fabs(data[i+j*cl]-data[j+i*cl])>1.e-10 ){ sym=0;
break; }
166 plumed_assert(A.
cl==B.
rw);
168 for(
unsigned i=0;i<A.
rw;++i)
for(
unsigned j=0;j<B.
cl;++j)
for (
unsigned k=0; k<A.
cl; ++k) C(i,j)+=A(i,k)*B(k,j);
171 template <
typename T>
void mult(
const Matrix<T>& A,
const std::vector<T>& B, std::vector<T>& C){
172 plumed_assert( A.
cl==B.size() );
173 if( C.size()!=A.
rw ){ C.resize(A.
rw); }
174 for(
unsigned i=0;i<A.
rw;++i){ C[i]=
static_cast<T
>( 0 ); }
175 for(
unsigned i=0;i<A.
rw;++i)
for(
unsigned k=0;k<A.
cl;++k) C[i]+=A(i,k)*B[k] ;
178 template <
typename T>
void mult(
const std::vector<T>& A,
const Matrix<T>& B, std::vector<T>& C){
179 plumed_assert( B.
rw==A.size() );
180 if( C.size()!=B.
cl ){C.resize( B.
cl );}
181 for(
unsigned i=0;i<B.
cl;++i){ C[i]=
static_cast<T
>( 0 ); }
182 for(
unsigned i=0;i<B.
cl;++i)
for(
unsigned k=0;k<B.
rw;++k) C[i]+=A[k]*B(k,i);
187 for(
unsigned i=0;i<A.
cl;++i)
for(
unsigned j=0;j<A.
rw;++j) AT(i,j)=A(j,i);
190 template <
typename T>
Log& operator<<(Log& ostr, const Matrix<T>& mat){
191 for(
unsigned i=0;i<mat.sz;++i) ostr<<mat.data[i]<<
" ";
196 for(
unsigned i=0;i<mat.
rw;++i){
197 for(
unsigned j=0;j<mat.
cl;++j){ ostr<<mat(i,j)<<
" "; }
207 double *
da=
new double[A.
sz];
unsigned k=0;
double *evals=
new double[ A.
cl ];
209 for (
unsigned i=0; i<A.
cl; ++i)
for (
unsigned j=0; j<A.
rw; ++j) da[k++]=static_cast<double>( A(j,i) );
214 int* isup=
new int[2*A.
cl];
double *evecs=
new double[A.
sz];
216 F77_FUNC(dsyevr,DSYEVR)(
"V",
"I",
"U", &
n,
da, &
n, &
vl, &
vu, &one, &
n ,
219 if (info!=0)
return info;
222 liwork=iwork[0];
delete []
iwork; iwork=
new int[
liwork];
223 lwork=
static_cast<int>( work[0] );
delete []
work; work=
new double[
lwork];
225 F77_FUNC(dsyevr,DSYEVR)(
"V",
"I",
"U", &
n,
da, &
n, &
vl, &
vu, &one, &
n ,
228 if (info!=0)
return info;
230 if( eigenvals.size()!=A.
cl ){ eigenvals.resize( A.
cl ); }
233 for(
unsigned i=0;i<A.
cl;++i){
234 eigenvals[i]=evals[i];
238 for(
unsigned j=0;j<A.
rw;++j){ eigenvecs(i,j)=evecs[k++]; }
242 delete[]
da;
delete []
work;
delete [] evals;
delete[] evecs;
delete []
iwork;
delete [] isup;
253 int err; err=
diagMat( A, eval, evec );
254 if(err!=0)
return err;
255 for (
unsigned i=0; i<A.
rw; ++i)
for (
unsigned j=0; j<A.
cl; ++j) tevec(i,j)=evec(j,i)/eval[j];
256 mult(tevec,evec,inverse);
258 double *
da=
new double[A.
sz];
int *
ipiv=
new int[A.
cl];
259 unsigned k=0;
int n=A.
rw,
info;
260 for(
unsigned i=0;i<A.
cl;++i)
for(
unsigned j=0;j<A.
rw;++j) da[k++]=static_cast<double>( A(j,i) );
269 lwork=
static_cast<int>( work[0] );
delete []
work; work=
new double[
lwork];
274 k=0;
for(
unsigned i=0;i<A.
rw;++i)
for(
unsigned j=0;j<A.
cl;++j)
inverse(j,i)=da[k++];
286 std::vector<T> D(A.
rw,0.);
287 for(
unsigned i=0; i<A.
rw; ++i){
288 L(i,i)=
static_cast<T
>( 1 );
289 for (
unsigned j=0; j<i; ++j){
291 for (
unsigned k=0; k<j; ++k) L(i,j)-=L(i,k)*L(j,k)*D[k];
292 if (D[j]!=0.) L(i,j)/=D[j];
else L(i,j)=
static_cast<T
>( 0 );
295 for (
unsigned k=0; k<i; ++k) D[i]-=L(i,k)*L(i,k)*D[k];
298 for(
unsigned i=0; i<A.
rw; ++i) D[i]=(D[i]>0.?sqrt(D[i]):0.);
300 B=0.;
for(
unsigned i=0; i<A.
rw; ++i)
for(
unsigned j=0; j<=i; ++j) B(i,j)+=L(i,j)*D[j];
305 plumed_assert( M.
rw==M.
cl && M(0,1)==0.0 && b.size()==M.
rw );
306 if( y.size()!=M.
rw ){ y.resize( M.
rw ); }
307 for(
unsigned i=0;i<M.
rw;++i){
309 for(
unsigned j=0;j<i;++j) y[i]-=M(i,j)*y[j];
318 double *
da=
new double[M.
sz];
unsigned k=0;
double *evals=
new double[M.
cl];
320 for (
unsigned i=0; i<M.
rw; ++i)
for (
unsigned j=0; j<M.
cl; ++j) da[k++]=static_cast<double>( M(j,i) );
325 int* isup=
new int[2*M.
rw];
double *evecs=
new double[M.
sz];
326 F77_FUNC(dsyevr,DSYEVR)(
"N",
"I",
"U", &
n,
da, &
n, &
vl, &
vu, &one, &
n ,
332 lwork=
static_cast<int>( work[0] );
delete []
work; work=
new double[
lwork];
333 liwork=iwork[0];
delete []
iwork; iwork=
new int[
liwork];
335 F77_FUNC(dsyevr,DSYEVR)(
"N",
"I",
"U", &
n,
da, &
n, &
vl, &
vu, &one, &
n ,
341 ldet=0;
for(
unsigned i=0;i<M.
cl;i++){ ldet+=log(evals[i]); }
344 delete[]
da;
delete []
work;
delete [] evals;
delete[] evecs;
delete []
iwork;
delete [] isup;
Matrix< T > & operator+=(const Matrix< T > &m)
Matrix addition.
Matrix< T > & operator=(const std::vector< T > &v)
Set the Matrix equal to the value of a standard vector - used for readin.
Matrix< T > operator-=(const T &v)
Subtract v from all elements of the Matrix.
TensorGeneric< 3, 3 > inverse(const TensorGeneric< 3, 3 > &t)
int Invert(const Matrix< T > &A, Matrix< double > &inverse)
Matrix< T > & operator=(const Matrix< T > &m)
Set the Matrix equal to another Matrix.
void cholesky(const Matrix< T > &A, Matrix< T > &B)
unsigned ncols() const
Return the number of columns.
Utility class to add [][] access.
unsigned rw
Number of rows in matrix.
Class containing the log stream.
void transpose(const Matrix< T > &A, Matrix< T > &AT)
Matrix< T > & operator-=(const Matrix< T > &m)
Matrix subtraction.
Matrix(const unsigned nr=0, const unsigned nc=0)
friend void chol_elsolve(const Matrix< U > &, const std::vector< U > &, std::vector< U > &)
Solve a system of equations using the cholesky decomposition.
void mult(const Matrix< T > &A, const Matrix< T > &B, Matrix< T > &C)
std::vector< T > data
The data in the matrix.
friend void transpose(const Matrix< U > &, Matrix< U > &)
Matrix transpose.
unsigned cl
Number of columns in matrix.
unsigned nrows() const
Return the number of rows.
friend int diagMat(const Matrix< U > &, std::vector< double > &, Matrix< double > &)
Diagonalize a symmetric matrix - returns zero if diagonalization worked.
T dotProduct(const std::vector< T > &A, const std::vector< T > &B)
Calculate the dot product between two vectors.
friend void cholesky(const Matrix< U > &, Matrix< U > &)
Do a cholesky decomposition of a matrix.
int logdet(const Matrix< T > &M, double &ldet)
int diagMat(const Matrix< T > &A, std::vector< double > &eigenvals, Matrix< double > &eigenvecs)
T operator()(const unsigned &i, const unsigned &j) const
Return element i,j of the matrix.
Matrix(const Matrix< T > &t)
unsigned isSymmetric() const
Test if the matrix is symmetric or not.
void chol_elsolve(const Matrix< T > &M, const std::vector< T > &b, std::vector< T > &y)
friend int Invert(const Matrix< U > &, Matrix< double > &)
Invert a matrix (works for both symmetric and assymetric matrices) - returns zero if sucesfull...
friend void mult(const Matrix< U > &, const Matrix< U > &, Matrix< U > &)
Matrix matrix multiply.
void resize(const unsigned nr, const unsigned nc)
Resize the matrix.
unsigned sz
Number of elements in matrix (nrows*ncols)
Matrix< T > & operator=(const T &v)
Set all elements of the matrix equal to the value of v.
Matrix< T > operator+=(const T &v)
Add v to all elements of the Matrix.
void matrixOut(Log &ostr, const Matrix< T > &mat)
This class stores a full matrix and allows one to do some simple matrix operations.
friend int logdet(const Matrix< U > &, double &)
Calculate the logarithm of the determinant of a symmetric matrix - returns zero if succesfull...
friend void matrixOut(Log &, const Matrix< U > &)
Output the Matrix in matrix form.
T norm(const std::vector< T > &A)
Calculate the dot product between a vector and itself.