441 lines
10 KiB
C++
441 lines
10 KiB
C++
/**********************************************************
|
|
|
|
This software is part of J.-S. Caux's ABACUS library.
|
|
|
|
Copyright (c).
|
|
|
|
-----------------------------------------------------------
|
|
|
|
File: JSC_Matrix.h
|
|
|
|
Purpose: Declares square matrix class.
|
|
|
|
***********************************************************/
|
|
|
|
#ifndef _MATRIX_
|
|
#define _MATRIX_
|
|
|
|
namespace JSC {
|
|
|
|
|
|
// CLASS DEFINITIONS
|
|
|
|
template <class T>
|
|
class SQMat {
|
|
|
|
private:
|
|
int dim;
|
|
T** M;
|
|
|
|
public:
|
|
SQMat (int N); // initializes all elements of this n by n matrix to zero
|
|
SQMat (const SQMat& rhs); // copy constructor
|
|
SQMat (const T& a, int N); // initialize to diagonal matrix with value a (NOT like in NR !!!)
|
|
SQMat (const SQMat& a, const SQMat& b); // initialize to tensor product of a and b
|
|
SQMat (const SQMat& a, int row_id, int col_id); // init by cutting row row_id and col col_id
|
|
void Print ();
|
|
SQMat& operator= (const SQMat& rhs); // assignment
|
|
SQMat& operator= (const T& a); // assign 1 to diagonal elements (NOT like in NR !!!)
|
|
inline T* operator[] (const int i); // subscripting: pointer to row i
|
|
inline const T* operator[] (const int i) const;
|
|
SQMat& operator+= (const T& a);
|
|
SQMat& operator+= (const SQMat& a);
|
|
SQMat& operator-= (const T& a);
|
|
SQMat& operator-= (const SQMat& a);
|
|
SQMat& operator*= (const T& a);
|
|
SQMat& operator*= (const SQMat& a);
|
|
inline int size() const;
|
|
~SQMat();
|
|
|
|
};
|
|
|
|
template <class T>
|
|
SQMat<T>::SQMat (int N) : dim(N) , M(new T*[N])
|
|
{
|
|
M[0] = new T[N*N];
|
|
for (int i = 1; i < N; i++) M[i] = M[i-1] + N;
|
|
}
|
|
|
|
template <class T>
|
|
SQMat<T>::SQMat (const SQMat& rhs) : dim(rhs.dim) , M(new T*[dim])
|
|
{
|
|
int i,j;
|
|
M[0] = new T[dim*dim];
|
|
for (i = 1; i < dim; i++) M[i] = M[i-1] + dim;
|
|
for (i = 0; i < dim; i++)
|
|
for (j = 0; j < dim; j++) M[i][j] = rhs[i][j];
|
|
}
|
|
|
|
template <class T>
|
|
SQMat<T>::SQMat (const T& a, int N) : dim(N) , M(new T*[dim])
|
|
{
|
|
int i, j;
|
|
M[0] = new T[dim*dim];
|
|
for (i = 1; i < dim; i++) M[i] = M[i-1] + dim;
|
|
for (i = 0; i < dim; i++) {
|
|
for (j = 0; j < dim; j++) M[i][j] = T(0);
|
|
M[i][i] = a;
|
|
}
|
|
}
|
|
|
|
template <class T>
|
|
SQMat<T>::SQMat (const SQMat& a, const SQMat& b) : dim (a.dim * b.dim) , M(new T*[a.dim * b.dim])
|
|
{
|
|
M[0] = new T[a.dim * b.dim * a.dim * b.dim];
|
|
|
|
for (int i = 1; i < a.dim * b.dim; ++i) M[i] = M[i-1] + a.dim * b.dim;
|
|
|
|
for (int i1 = 0; i1 < a.dim; ++i1) {
|
|
|
|
for (int i2 = 0; i2 < a.dim; ++i2) {
|
|
|
|
for (int j1 = 0; j1 < b.dim; ++j1) {
|
|
|
|
for (int j2 = 0; j2 < b.dim; ++j2) {
|
|
|
|
M[i1 * (b.dim) + j1][i2 * (b.dim) + j2] = a[i1][i2] * b[j1][j2];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class T>
|
|
SQMat<T>::SQMat (const SQMat&a, int row_id, int col_id) : dim (a.dim - 1) , M(new T*[dim])
|
|
{
|
|
if (dim == 0) {
|
|
JSCerror("Error: chopping a row and col from size one matrix.");
|
|
exit(1);
|
|
}
|
|
|
|
M[0] = new T[dim * dim];
|
|
|
|
for (int i = 1; i < dim; ++i) M[i] = M[i-1] + dim;
|
|
|
|
for (int i = 0; i < row_id; ++i)
|
|
for (int j = 0; j < col_id; ++j) M[i][j] = a[i][j];
|
|
for (int i = row_id; i < dim; ++i)
|
|
for (int j = 0; j < col_id; ++j) M[i][j] = a[i+1][j];
|
|
for (int i = 0; i < row_id; ++i)
|
|
for (int j = col_id; j < dim; ++j) M[i][j] = a[i][j+1];
|
|
for (int i = row_id; i < dim; ++i)
|
|
for (int j = col_id; j < dim; ++j) M[i][j] = a[i+1][j+1];
|
|
|
|
}
|
|
|
|
// operators
|
|
template <class T>
|
|
void SQMat<T>::Print ()
|
|
{
|
|
cout << endl;
|
|
for (int i = 0; i < dim; ++i) {
|
|
for (int j = 0; j < dim; ++j) cout << M[i][j] << " ";
|
|
cout << endl;
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
template <class T>
|
|
SQMat<T>& SQMat<T>::operator= (const SQMat<T>& rhs)
|
|
{
|
|
if (this != &rhs) {
|
|
if (dim != rhs.dim) {
|
|
JSCerror("Assignment between matrices of different dimensions. Bailing out.");
|
|
exit(1);
|
|
}
|
|
|
|
for (int i = 0; i < dim; ++i)
|
|
for (int j = 0; j < dim; ++j) M[i][j] = rhs[i][j];
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <class T>
|
|
SQMat<T>& SQMat<T>::operator= (const T& a)
|
|
{
|
|
for (int i = 0; i < dim; ++i) {
|
|
for (int j = 0; j < dim; ++j)
|
|
M[i][j] = T(0);
|
|
M[i][i] = a;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <class T>
|
|
inline T* SQMat<T>::operator[] (const int i)
|
|
{
|
|
return M[i];
|
|
}
|
|
|
|
template <class T>
|
|
inline const T* SQMat<T>::operator[] (const int i) const
|
|
{
|
|
return M[i];
|
|
}
|
|
|
|
template <class T>
|
|
SQMat<T>& SQMat<T>::operator+= (const T& a)
|
|
{
|
|
|
|
for (int i = 0; i < dim; ++i) M[i][i] += a;
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <class T>
|
|
SQMat<T>& SQMat<T>::operator+= (const SQMat<T>& a)
|
|
{
|
|
if (dim != a.dim) {
|
|
JSCerror("Incompatible matrix sizes in matrix operator +.");
|
|
exit(1);
|
|
}
|
|
for (int i = 0; i < dim; ++i) {
|
|
for (int j = 0; j < dim; ++j) {
|
|
M[i][j] += a[i][j];
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <class T>
|
|
SQMat<T>& SQMat<T>::operator-= (const T& a)
|
|
{
|
|
|
|
for (int i = 0; i < dim; ++i) M[i][i] -= a;
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <class T>
|
|
SQMat<T>& SQMat<T>::operator-= (const SQMat<T>& a)
|
|
{
|
|
if (dim != a.dim) {
|
|
JSCerror("Incompatible matrix sizes in matrix operator +.");
|
|
exit(1);
|
|
}
|
|
for (int i = 0; i < dim; ++i) {
|
|
for (int j = 0; j < dim; ++j) {
|
|
M[i][j] -= a[i][j];
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <class T>
|
|
SQMat<T>& SQMat<T>::operator*= (const T& a)
|
|
{
|
|
|
|
for (int i = 0; i < dim; ++i) for (int j = 0; j < dim; ++j) M[i][j] *= a;
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <class T>
|
|
SQMat<T>& SQMat<T>::operator*= (const SQMat<T>& a)
|
|
{
|
|
|
|
if (dim != a.dim) {
|
|
JSCerror("Incompatible matrix sizes in matrix operator *.");
|
|
exit(1);
|
|
}
|
|
|
|
SQMat<T> leftarg(*this); // use copy constructor.
|
|
|
|
for (int i = 0; i < dim; ++i) {
|
|
|
|
for (int j = 0; j < dim; ++j) {
|
|
|
|
M[i][j] = 0.0;
|
|
|
|
for (int k = 0; k < dim; ++k) {
|
|
|
|
M[i][j] += leftarg[i][k] * a[k][j];
|
|
}
|
|
}
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <class T>
|
|
inline int SQMat<T>::size() const
|
|
{
|
|
return dim;
|
|
}
|
|
|
|
template <class T>
|
|
SQMat<T>::~SQMat()
|
|
{
|
|
if (M != 0) {
|
|
delete[] (M[0]);
|
|
delete[] (M);
|
|
}
|
|
}
|
|
|
|
|
|
//*****************************
|
|
|
|
template <class T>
|
|
class RecMat {
|
|
|
|
private:
|
|
int nrows;
|
|
int ncols;
|
|
T** M;
|
|
|
|
public:
|
|
RecMat (int Nrows, int Ncols); // initializes all elements of this n by n matrix to zero
|
|
RecMat (const T& a, int Nrows, int Ncols);
|
|
RecMat (const RecMat& rhs); // copy constructor
|
|
void Print ();
|
|
RecMat& operator= (const RecMat& rhs); // assignment
|
|
inline T* operator[] (const int i); // subscripting: pointer to row i
|
|
inline const T* operator[] (const int i) const;
|
|
inline int nr_rows() const;
|
|
inline int nr_cols() const;
|
|
~RecMat();
|
|
|
|
};
|
|
|
|
template <class T>
|
|
RecMat<T>::RecMat (int Nrows, int Ncols) : nrows(Nrows), ncols(Ncols), M(new T*[Nrows])
|
|
{
|
|
M[0] = new T[Nrows*Ncols];
|
|
for (int i = 1; i < Nrows; i++) M[i] = M[i-1] + Ncols;
|
|
|
|
for (int i = 0; i < Nrows; i++) for (int j = 0; j < Ncols; j++) M[i][j] = T(0);
|
|
}
|
|
|
|
template <class T>
|
|
RecMat<T>::RecMat (const T& a, int Nrows, int Ncols) : nrows(Nrows), ncols(Ncols), M(new T*[Nrows])
|
|
{
|
|
M[0] = new T[Nrows*Ncols];
|
|
for (int i = 1; i < Nrows; i++) M[i] = M[i-1] + Ncols;
|
|
|
|
for (int i = 0; i < Nrows; i++) for (int j = 0; j < Ncols; j++) {
|
|
if (i == j) M[i][i] = a;
|
|
else M[i][j] = T(0);
|
|
}
|
|
}
|
|
|
|
template <class T>
|
|
RecMat<T>::RecMat (const RecMat& rhs) : nrows(rhs.nrows), ncols(rhs.ncols), M(new T*[nrows])
|
|
{
|
|
int i,j;
|
|
M[0] = new T[nrows*ncols];
|
|
for (i = 1; i < nrows; i++) M[i] = M[i-1] + ncols;
|
|
for (i = 0; i < nrows; i++)
|
|
for (j = 0; j < ncols; j++) M[i][j] = rhs[i][j];
|
|
}
|
|
|
|
// operators
|
|
template <class T>
|
|
void RecMat<T>::Print ()
|
|
{
|
|
cout << endl;
|
|
for (int i = 0; i < nrows; ++i) {
|
|
for (int j = 0; j < ncols; ++j) cout << M[i][j] << " ";
|
|
cout << endl;
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
template <class T>
|
|
RecMat<T>& RecMat<T>::operator= (const RecMat<T>& rhs)
|
|
{
|
|
if (this != &rhs) {
|
|
if (nrows != rhs.nrows || ncols != rhs.ncols) {
|
|
if (M != 0) {
|
|
delete[] (M[0]);
|
|
delete[] (M);
|
|
}
|
|
nrows = rhs.nrows;
|
|
ncols = rhs.ncols;
|
|
M = new T*[nrows];
|
|
M[0] = new T[nrows * ncols];
|
|
}
|
|
|
|
for (int i = 0; i < nrows; ++i)
|
|
for (int j = 0; j < ncols; ++j) M[i][j] = rhs[i][j];
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <class T>
|
|
inline T* RecMat<T>::operator[] (const int i)
|
|
{
|
|
return M[i];
|
|
}
|
|
|
|
template <class T>
|
|
inline const T* RecMat<T>::operator[] (const int i) const
|
|
{
|
|
return M[i];
|
|
}
|
|
|
|
template <class T>
|
|
inline int RecMat<T>::nr_rows() const
|
|
{
|
|
return nrows;
|
|
}
|
|
|
|
template <class T>
|
|
inline int RecMat<T>::nr_cols() const
|
|
{
|
|
return ncols;
|
|
}
|
|
|
|
template <class T>
|
|
inline std::ostream& operator<< (std::ostream& s, const RecMat<T>& matrix)
|
|
{
|
|
for (int i = 0; i < matrix.nr_rows(); ++i) {
|
|
for (int j = 0; j < matrix.nr_cols(); ++j) s << matrix[i][j] << " ";
|
|
s << endl;
|
|
}
|
|
|
|
return (s);
|
|
}
|
|
|
|
template <class T>
|
|
RecMat<T>::~RecMat()
|
|
{
|
|
if (M != 0) {
|
|
delete[] (M[0]);
|
|
delete[] (M);
|
|
}
|
|
}
|
|
|
|
// TYPEDEFS:
|
|
|
|
typedef JSC::SQMat<DP> SQMat_DP;
|
|
typedef JSC::SQMat<complex<double> > SQMat_CX;
|
|
|
|
|
|
// FUNCTION DEFINITIONS
|
|
|
|
// Functions in src/MATRIX directory
|
|
|
|
DP det_LU (SQMat_DP a);
|
|
DP lndet_LU (SQMat_DP a);
|
|
complex<DP> lndet_LU_dstry (SQMat_DP& a);
|
|
complex<DP> det_LU_CX (SQMat_CX a);
|
|
complex<DP> lndet_LU_CX (SQMat_CX a);
|
|
complex<DP> lndet_LU_CX_dstry (SQMat_CX& a);
|
|
void eigsrt (Vect_DP& d, SQMat_DP& v);
|
|
void balanc (SQMat_DP& a);
|
|
void elmhes (SQMat_DP& a);
|
|
void gaussj (SQMat_DP& a, SQMat_DP& b);
|
|
void hqr (SQMat_DP& a, Vect_CX& wri);
|
|
void jacobi (SQMat_DP& a, Vect_DP& d, SQMat_DP& v, int& nrot);
|
|
void lubksb (SQMat_DP& a, Vect_INT& indx, Vect_DP& b);
|
|
void lubksb_CX (SQMat_CX& a, Vect_INT& indx, Vect_CX& b);
|
|
void ludcmp (SQMat_DP& a, Vect_INT& indx, DP& d);
|
|
void ludcmp_CX (SQMat_CX& a, Vect_INT& indx, DP& d);
|
|
DP pythag(DP a, DP b);
|
|
void tqli(Vect_DP& d, Vect_DP& e, SQMat_DP& z);
|
|
void tred2 (SQMat_DP& a, Vect_DP& d, Vect_DP& e);
|
|
|
|
} // namespace JSC
|
|
|
|
#endif
|