LA_library/nonclass.h
2005-09-06 15:55:07 +00:00

171 lines
5.8 KiB
C++

#ifndef _LA_NONCLASS_H_
#define _LA_NONCLASS_H_
#include "vec.h"
#include "smat.h"
#include "mat.h"
#include "la_traits.h"
//MISC
export template <class T>
const NRMat<T> diagonalmatrix(const NRVec<T> &x)
{
int n=x.size();
NRMat<T> result((T)0,n,n);
T *p = result[0];
for(int j=0; j<n; j++) {*p = x[j]; p+=(n+1);}
return result;
}
//more efficient commutator for a special case of full matrices
template<class T>
inline const NRMat<T> commutator ( const NRMat<T> &x, const NRMat<T> &y, const bool trx=0, const bool tryy=0)
{
NRMat<T> r(trx?x.ncols():x.nrows(), tryy?y.nrows():y.ncols());
r.gemm((T)0,x,trx?'t':'n',y,tryy?'t':'n',(T)1);
r.gemm((T)1,y,tryy?'t':'n',x,trx?'t':'n',(T)-1);
return r;
}
//more efficient commutator for a special case of full matrices
template<class T>
inline const NRMat<T> anticommutator ( const NRMat<T> &x, const NRMat<T> &y, const bool trx=0, const bool tryy=0)
{
NRMat<T> r(trx?x.ncols():x.nrows(), tryy?y.nrows():y.ncols());
r.gemm((T)0,x,trx?'t':'n',y,tryy?'t':'n',(T)1);
r.gemm((T)1,y,tryy?'t':'n',x,trx?'t':'n',(T)1);
return r;
}
//////////////////////
// LAPACK interface //
//////////////////////
#define declare_la(T) \
extern const NRVec<T> diagofproduct(const NRMat<T> &a, const NRMat<T> &b,\
bool trb=0, bool conjb=0); \
extern T trace2(const NRMat<T> &a, const NRMat<T> &b, bool trb=0); \
extern T trace2(const NRSMat<T> &a, const NRSMat<T> &b, const bool diagscaled=0);\
extern void linear_solve(NRMat<T> &a, NRMat<T> *b, double *det=0,int n=0); \
extern void linear_solve(NRSMat<T> &a, NRMat<T> *b, double *det=0, int n=0); \
extern void linear_solve(NRMat<T> &a, NRVec<T> &b, double *det=0, int n=0); \
extern void linear_solve(NRSMat<T> &a, NRVec<T> &b, double *det=0, int n=0); \
extern void diagonalize(NRMat<T> &a, NRVec<T> &w, const bool eivec=1, const bool corder=1, int n=0, NRMat<T> *b=NULL, const int itype=1); \
extern void diagonalize(NRSMat<T> &a, NRVec<T> &w, NRMat<T> *v, const bool corder=1, int n=0, NRSMat<T> *b=NULL, const int itype=1);\
extern void singular_decomposition(NRMat<T> &a, NRMat<T> *u, NRVec<T> &s,\
NRMat<T> *v, const bool corder=1, int m=0, int n=0);
declare_la(double)
declare_la(complex<double>)
// Separate declarations
//general nonsymmetric matrix and generalized diagonalization
extern void gdiagonalize(NRMat<double> &a, NRVec<double> &wr, NRVec<double> &wi,
NRMat<double> *vl, NRMat<double> *vr, const bool corder=1, int n=0, const int sorttype=0, const bool biorthonormalize=0,
NRMat<double> *b=NULL, NRVec<double> *beta=NULL);
extern void gdiagonalize(NRMat<double> &a, NRVec< complex<double> > &w,
NRMat< complex<double> >*vl, NRMat< complex<double> > *vr,
const bool corder=1, int n=0, const int sorttype=0, const bool biorthonormalize=0,
NRMat<double> *b=NULL, NRVec<double> *beta=NULL);
extern NRMat<double> matrixfunction(NRSMat<double> a, double (*f) (double));
extern NRMat<double> matrixfunction(NRMat<double> a, complex<double> (*f)(const complex<double> &),const bool adjust=0);
//functions on matrices
inline NRMat<double> sqrt(const NRSMat<double> &a) { return matrixfunction(a,&sqrt); }
inline NRMat<double> log(const NRSMat<double> &a) { return matrixfunction(a,&log); }
extern NRMat<double> log(const NRMat<double> &a);
extern const NRMat<double> realpart(const NRMat< complex<double> >&);
extern const NRMat<double> imagpart(const NRMat< complex<double> >&);
extern const NRMat< complex<double> > realmatrix (const NRMat<double>&);
extern const NRMat< complex<double> > imagmatrix (const NRMat<double>&);
//inverse by means of linear solve, preserving rhs intact
template<typename T>
const NRMat<T> inverse(NRMat<T> a, T *det=0)
{
#ifdef DEBUG
if(a.nrows()!=a.ncols()) laerror("inverse() for non-square matrix");
#endif
NRMat<T> result(a.nrows(),a.nrows());
result = (T)1.;
linear_solve(a, &result, det);
return result;
}
//general determinant
template<class MAT>
const typename LA_traits<MAT>::elementtype determinant(MAT a)//passed by value
{
typename LA_traits<MAT>::elementtype det;
if(a.nrows()!=a.ncols()) laerror("determinant of non-square matrix");
linear_solve(a,NULL,&det);
return det;
}
//general determinant destructive on input
template<class MAT>
const typename LA_traits<MAT>::elementtype determinant_destroy(MAT &a) //passed by reference
{
typename LA_traits<MAT>::elementtype det;
if(a.nrows()!=a.ncols()) laerror("determinant of non-square matrix");
linear_solve(a,NULL,&det);
return det;
}
//general submatrix, INDEX will typically be NRVec<int> or even int*
//NOTE: in order to check consistency between nrows and rows in rows is a NRVec
//some advanced metaprogramming would be necessary
//application: e.g. ignoresign=true, equalsigns=true, indexshift= -1 ... elements of Slater overlaps for RHF
template<class MAT, class INDEX>
const NRMat<typename LA_traits<MAT>::elementtype> submatrix(const MAT a, const int nrows, const INDEX rows, const int ncols, const INDEX cols, int indexshift=0, bool ignoresign=false, bool equalsigns=false)
{
NRMat<typename LA_traits<MAT>::elementtype> r(nrows,ncols);
if(equalsigns) //make the element zero if signs of both indices are opposite
{
if(ignoresign)
{
for(int i=0; i<nrows; ++i)
for(int j=0; j<ncols; ++j)
r(i,j) = rows[i]*cols[j]<0?0.:a(abs(rows[i])+indexshift,abs(cols[j])+indexshift);
}
else
{
for(int i=0; i<nrows; ++i)
for(int j=0; j<ncols; ++j)
r(i,j) = rows[i]*cols[j]<0?0.:a(rows[i]+indexshift,cols[j]+indexshift);
}
}
else
{
if(ignoresign)
{
for(int i=0; i<nrows; ++i)
for(int j=0; j<ncols; ++j)
r(i,j) = a(abs(rows[i])+indexshift,abs(cols[j])+indexshift);
}
else
{
for(int i=0; i<nrows; ++i)
for(int j=0; j<ncols; ++j)
r(i,j) = a(rows[i]+indexshift,cols[j]+indexshift);
}
}
return r;
}
//auxiliary routine to adjust eigenvectors to guarantee real logarithm
extern void adjustphases(NRMat<double> &v);
#endif