dynare/dynare++/sylv/cc/QuasiTriangular.h

340 lines
10 KiB
C++

/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/QuasiTriangular.h,v 1.1.1.1 2004/06/04 13:00:44 kamenik Exp $ */
/* Tag $Name: $ */
#ifndef QUASI_TRIANGULAR_H
#define QUASI_TRIANGULAR_H
#include "Vector.h"
#include "KronVector.h"
#include "SylvMatrix.h"
#include <list>
using namespace std;
class DiagonalBlock;
class Diagonal;
class DiagPair {
private:
double* a1;
double* a2;
public:
DiagPair() {}
DiagPair(double* aa1, double* aa2) {a1 = aa1; a2 = aa2;}
DiagPair(const DiagPair& p) {a1 = p.a1; a2 = p.a2;}
const DiagPair& operator=(const DiagPair& p) {a1 = p.a1; a2 = p.a2; return *this;}
const DiagPair& operator=(double v) {*a1 = v; *a2 = v; return *this;}
const double& operator*() const {return *a1;}
/** here we must not define double& operator*(), since it wouldn't
rewrite both values, we use operator= for this */
friend class Diagonal;
friend class DiagonalBlock;
};
class DiagonalBlock {
private:
int jbar;
bool real;
DiagPair alpha;
double* beta1;
double* beta2;
void copy(const DiagonalBlock& b) {
jbar = b.jbar;
real = b.real;
alpha = b.alpha;
beta1 = b.beta1;
beta2 = b.beta2;
}
public:
DiagonalBlock() {}
DiagonalBlock(int jb, bool r, double* a1, double* a2,
double* b1, double* b2)
: alpha(a1, a2)
{
jbar = jb;
real = r;
beta1 = b1;
beta2 = b2;
}
// construct complex block
DiagonalBlock(int jb, double* a1, double* a2)
: alpha(a1, a2)
{
jbar = jb;
real = false;
beta1 = a2 - 1;
beta2 = a1 + 1;
}
// construct real block
DiagonalBlock(int jb, double* a1)
: alpha(a1, a1)
{
jbar = jb;
real = true;
beta1 = 0;
beta2 = 0;
}
DiagonalBlock(const DiagonalBlock& b)
{copy(b);}
const DiagonalBlock& operator=(const DiagonalBlock& b)
{copy(b); return *this;}
int getIndex() const
{return jbar;}
bool isReal() const
{return real;}
const DiagPair& getAlpha() const
{return alpha;}
DiagPair& getAlpha()
{return alpha;}
double& getBeta1() const
{return *beta1;}
double& getBeta2() const
{return *beta2;}
double getDeterminant() const;
double getSBeta() const;
double getSize() const;
void setReal();
// for debugging
void checkBlock(const double* d, int d_size);
friend class Diagonal;
};
template <class _Tdiag, class _Tblock, class _Titer>
struct _diag_iter {
typedef _diag_iter<_Tdiag, _Tblock, _Titer> _Self;
_Tdiag diag;
_Titer it;
public:
_diag_iter(_Tdiag d, _Titer iter) : diag(d), it(iter) {}
_Tblock operator*() const {return *it;}
_Self& operator++() {++it; return *this;}
_Self& operator--() {--it; return *this;}
bool operator==(const _Self& x) const {return x.it == it;}
bool operator!=(const _Self& x) const {return x.it != it;}
const _Self& operator=(const _Self& x) {it = x.it; return *this;}
_Titer iter() const {return it;}
};
class Diagonal {
public:
typedef _diag_iter<const Diagonal&, const DiagonalBlock&, list<DiagonalBlock>::const_iterator> const_diag_iter;
typedef _diag_iter<Diagonal&, DiagonalBlock&, list<DiagonalBlock>::iterator> diag_iter;
private:
int num_all;
list<DiagonalBlock> blocks;
int num_real;
void copy(const Diagonal&);
public:
Diagonal() : num_all(0), num_real(0) {}
Diagonal(double* data, int d_size);
Diagonal(double* data, const Diagonal& d);
Diagonal(const Diagonal& d) {copy(d);}
const Diagonal& operator =(const Diagonal& d) {copy(d); return *this;}
virtual ~Diagonal() {}
int getNumComplex() const {return num_all - num_real;}
int getNumReal() const {return num_real;}
int getSize() const {return getNumReal() + 2*getNumComplex();}
int getNumBlocks() const {return num_all;}
void getEigenValues(Vector& eig) const;
void swapLogically(diag_iter it);
void checkConsistency(diag_iter it);
double getAverageSize(diag_iter start, diag_iter end);
diag_iter findClosestBlock(diag_iter start, diag_iter end, double a);
diag_iter findNextLargerBlock(diag_iter start, diag_iter end, double a);
void print() const;
diag_iter begin()
{return diag_iter(*this, blocks.begin());}
const_diag_iter begin() const
{return const_diag_iter(*this, blocks.begin());}
diag_iter end()
{return diag_iter(*this, blocks.end());}
const_diag_iter end() const
{return const_diag_iter(*this, blocks.end());}
/* redefine pointers as data start at p */
void changeBase(double* p);
private:
static double EPS;
static int getNumComplex(const double* data, int d_size);
static bool isZero(double p);
};
template <class _TRef, class _TPtr>
struct _matrix_iter {
typedef _matrix_iter<_TRef, _TPtr> _Self;
int d_size;
bool real;
_TPtr ptr;
public:
_matrix_iter(_TPtr base, int ds, bool r)
{ptr = base; d_size = ds; real = r;}
virtual ~_matrix_iter() {}
const _Self& operator=(const _Self& it)
{ptr = it.ptr; d_size = it.d_size; real = it.real; return *this;}
bool operator==(const _Self& it) const
{return ptr == it.ptr;}
bool operator!=(const _Self& it) const
{return ptr != it.ptr;}
_TRef operator*() const
{return *ptr;}
_TRef a() const
{return *ptr;}
virtual _Self& operator++() =0;
};
template <class _TRef, class _TPtr>
class _column_iter : public _matrix_iter<_TRef, _TPtr> {
typedef _matrix_iter<_TRef, _TPtr> _Tparent;
typedef _column_iter<_TRef, _TPtr> _Self;
int row;
public:
_column_iter(_TPtr base, int ds, bool r, int rw)
: _matrix_iter<_TRef, _TPtr>(base, ds, r), row(rw) {};
_Self& operator++()
{_Tparent::ptr++; row++; return *this;}
_TRef b() const
{
if (_Tparent::real) {
return *(_Tparent::ptr);
} else {
return *(_Tparent::ptr+_Tparent::d_size);
}
}
int getRow() const {return row;}
};
template <class _TRef, class _TPtr>
class _row_iter : public _matrix_iter<_TRef, _TPtr> {
typedef _matrix_iter<_TRef, _TPtr> _Tparent;
typedef _row_iter<_TRef, _TPtr> _Self;
int col;
public:
_row_iter(_TPtr base, int ds, bool r, int cl)
: _matrix_iter<_TRef, _TPtr>(base, ds, r), col(cl) {};
_Self& operator++()
{_Tparent::ptr += _Tparent::d_size; col++; return *this;}
virtual _TRef b() const
{
if (_Tparent::real) {
return *(_Tparent::ptr);
}else {
return *(_Tparent::ptr+1);
}
}
int getCol() const {return col;}
};
class SchurDecomp;
class SchurDecompZero;
class QuasiTriangular : public SqSylvMatrix {
public:
typedef _column_iter<const double&, const double*> const_col_iter;
typedef _column_iter<double&, double*> col_iter;
typedef _row_iter<const double&, const double*> const_row_iter;
typedef _row_iter<double&, double*> row_iter;
typedef Diagonal::const_diag_iter const_diag_iter;
typedef Diagonal::diag_iter diag_iter;
protected:
Diagonal diagonal;
public:
QuasiTriangular(const double* d, int d_size);
QuasiTriangular(double r, const QuasiTriangular& t);
QuasiTriangular(double r, const QuasiTriangular& t,
double rr, const QuasiTriangular& tt);
QuasiTriangular(int p, const QuasiTriangular& t);
QuasiTriangular(const SchurDecomp& decomp);
QuasiTriangular(const SchurDecompZero& decomp);
QuasiTriangular(const QuasiTriangular& t);
virtual ~QuasiTriangular();
const Diagonal& getDiagonal() const {return diagonal;}
int getNumOffdiagonal() const;
void swapDiagLogically(diag_iter it);
void checkDiagConsistency(diag_iter it);
double getAverageDiagSize(diag_iter start, diag_iter end);
diag_iter findClosestDiagBlock(diag_iter start, diag_iter end, double a);
diag_iter findNextLargerBlock(diag_iter start, diag_iter end, double a);
/* (I+T)y = x, y-->x */
virtual void solvePre(Vector& x, double& eig_min);
/* (I+T')y = x, y-->x */
virtual void solvePreTrans(Vector& x, double& eig_min);
/* (I+T)x = b */
virtual void solve(Vector& x, const ConstVector& b, double& eig_min);
/* (I+T')x = b */
virtual void solveTrans(Vector& x, const ConstVector& b, double& eig_min);
/* x = Tb */
virtual void multVec(Vector& x, const ConstVector& b) const;
/* x = T'b */
virtual void multVecTrans(Vector& x, const ConstVector& b) const;
/* x = x + Tb */
virtual void multaVec(Vector& x, const ConstVector& b) const;
/* x = x + T'b */
virtual void multaVecTrans(Vector& x, const ConstVector& b) const;
/* x = (T\otimes I)x */
virtual void multKron(KronVector& x) const;
/* x = (T'\otimes I)x */
virtual void multKronTrans(KronVector& x) const;
/* A = T*A */
virtual void multLeftOther(GeneralMatrix& a) const;
/* A = T'*A */
virtual void multLeftOtherTrans(GeneralMatrix& a) const;
const_diag_iter diag_begin() const
{return diagonal.begin();}
diag_iter diag_begin()
{return diagonal.begin();}
const_diag_iter diag_end() const
{return diagonal.end();}
diag_iter diag_end()
{return diagonal.end();}
/* iterators for off diagonal elements */
virtual const_col_iter col_begin(const DiagonalBlock& b) const;
virtual col_iter col_begin(const DiagonalBlock& b);
virtual const_row_iter row_begin(const DiagonalBlock& b) const;
virtual row_iter row_begin(const DiagonalBlock& b);
virtual const_col_iter col_end(const DiagonalBlock& b) const;
virtual col_iter col_end(const DiagonalBlock& b);
virtual const_row_iter row_end(const DiagonalBlock& b) const;
virtual row_iter row_end(const DiagonalBlock& b);
/* clone */
virtual QuasiTriangular* clone() const
{return new QuasiTriangular(*this);}
virtual QuasiTriangular* clone(int p, const QuasiTriangular& t) const
{return new QuasiTriangular(p, t);}
virtual QuasiTriangular* clone(double r) const
{return new QuasiTriangular(r, *this);}
virtual QuasiTriangular* clone(double r, double rr, const QuasiTriangular& tt) const
{return new QuasiTriangular(r, *this, rr, tt);}
protected:
void setMatrix(double r, const QuasiTriangular& t);
void addMatrix(double r, const QuasiTriangular& t);
private:
void addUnit();
/* x = x + (T\otimes I)b */
void multaKron(KronVector& x, const ConstKronVector& b) const;
/* x = x + (T'\otimes I)b */
void multaKronTrans(KronVector& x, const ConstKronVector& b) const;
/* implementation via iterators, useful for large matrices */
void setMatrixViaIter(double r, const QuasiTriangular& t);
void addMatrixViaIter(double r, const QuasiTriangular& t);
/* hide noneffective implementations of parents */
void multsVec(Vector& x, const ConstVector& d) const;
void multsVecTrans(Vector& x, const ConstVector& d) const;
};
#endif /* QUASI_TRIANGULAR_H */
// Local Variables:
// mode:C++
// End: