// NOTE: The current revision of this file was left untouched when the DUNE source files were reindented!
// NOTE: It contained invalid syntax that could not be processed by uncrustify.

/****************************************************************************/
/*																			*/
/* File:      famg_onlyugalgebra.h											*/
/*																			*/
/* Purpose:   famg algera classes fixed for ug data structure				*/
/*																			*/
/* Author:    Christian Wrobel												*/
/*			  Institut fuer Computeranwendungen  III						*/
/*			  Universitaet Stuttgart										*/
/*			  Pfaffenwaldring 27											*/
/*			  70569 Stuttgart												*/
/*			  internet: ug@ica3.uni-stuttgart.de							*/
/*																			*/
/*																			*/
/* History:   February 99 begin (Christian Wrobel)							*/
/*																			*/
/* Remarks:	  don't include this file into your own files!					*/
/*			  only for use within famg_algebra.h							*/
/*																			*/
/****************************************************************************/

#ifndef __FAMG_ONLYUGALGEBRA__
#define __FAMG_ONLYUGALGEBRA__

/* RCS_ID
$Header$
*/

extern "C"
{
#include "gm.h"
#include "udm.h"

#ifdef ModelP
#include "np.h"
#endif
}

#include "famg_sparse.h"

//
// vector stuff
//
class FAMGVectorEntry; // forward declaration
typedef FAMGVectorEntry FAMGVectorEntryRef;		// synonym; for compatibility only

class FAMGVectorEntry
{			
	public:
		FAMGVectorEntry() : vp(NULL) {}
		FAMGVectorEntry( const FAMGVectorEntry& ve ) : vp(ve.vp) {}
		FAMGVectorEntry( VECTOR *vptr ) : vp(vptr) {}
		// weg FAMGVectorEntry( FAMGVectorEntryRef* vep ) : vp(vep) {}
		~FAMGVectorEntry() {}
		
		FAMGVectorEntry& operator=( const FAMGVectorEntry& ve ) { vp=ve.vp; return *this;}
		FAMGVectorEntry& operator++() {vp=SUCCVC(vp); return *this;}	// prefix
		void operator++(int) {vp=SUCCVC(vp);}							// postfix
		FAMGVectorEntry& operator--() {vp=PREDVC(vp); return *this;}	// prefix
		void operator--(int) {vp=PREDVC(vp);}							// postfix
		int operator==( const FAMGVectorEntry& ve ) const {return (vp==ve.vp);}
		int operator!=( const FAMGVectorEntry& ve ) const {return (vp!=ve.vp);}

		VECTOR *myvector() const {return vp;}
		FAMGVectorEntryRef* GetPointer() const {return (FAMGVectorEntryRef*)this;}
		int GetIndex() const {return VINDEX(vp);}
		
	private:
		VECTOR *vp;
};

class FAMGGridVector
{
	public:
		FAMGGridVector( GRID* grid) : mygrid(grid) {}
		~FAMGGridVector() {};	// nothing to do
		
		int is_valid( const FAMGVectorEntry& ve ) const {return ve.myvector()!=NULL;}
		int is_end( const FAMGVectorEntry& ve ) const {return ve.myvector()==NULL;}
		int is_beforefirst( const FAMGVectorEntry& ve ) const {return ve.myvector()==NULL;}
		FAMGVectorEntry firstEntry() const {return (FAMGVectorEntry)PFIRSTVECTOR(mygrid);}
		FAMGVectorEntry lastEntry() const {return (FAMGVectorEntry)LASTVECTOR(mygrid);}
		FAMGVectorEntry endEntry() const {return (FAMGVectorEntry)NULL;}
		
		int IsCG( const FAMGVectorEntry& ve ) const {return VCCOARSE(ve.myvector());}
		int IsFG( const FAMGVectorEntry& ve ) const {return !IsCG(ve);}
		void SetCG( const FAMGVectorEntry& ve ) const {SETVCCOARSE(ve.myvector(),1);}
		void SetFG( const FAMGVectorEntry& ve ) const {SETVCCOARSE(ve.myvector(),0);}

		GRID *GetGrid() const {return mygrid;}
		
	private:
		GRID *mygrid;
};

#ifdef FAMG_SPARSE_BLOCK
// todo: remove comp
class FAMGVector
{
	friend class FAMGVectorIter;
	friend class FAMGVectorRevIter;
		
	public:
		typedef class FAMGVectorEntry VectorEntry; 
		typedef class FAMGVectorIter Iterator;
		typedef class FAMGVectorRevIter RevIterator;
		
		FAMGVector(const FAMGGridVector& gridvec) : mygridvector(gridvec) {}
		~FAMGVector();
		FAMGVector( const FAMGGridVector& gridvec, VECDATA_DESC *vec_desc ) : mygridvector(gridvec), mydesc(vec_desc) , sv(VD_NCMPS_IN_TYPE(vec_desc,0),VD_CMPPTR_OF_TYPE(vec_desc,0)) {allocatedVD=0;  comp =  VD_CMP_OF_TYPE(vec_desc,0,0);}
		FAMGVector( const FAMGGridVector& gridvec, VECDATA_DESC *vec_desc, short *cmpmap, short ncmp ) : mygridvector(gridvec), mydesc(vec_desc), sv(VD_CMPPTR_OF_TYPE(vec_desc,0),cmpmap,ncmp) {allocatedVD=0;  comp =  VD_CMP_OF_TYPE(vec_desc,0,0);}
		FAMGVector( const FAMGGridVector& gridvec, const FAMGVector &pattern_vec) : mygridvector(gridvec), comp(pattern_vec.comp), mydesc(pattern_vec.mydesc), sv(pattern_vec.sv) {}
		FAMGVector* create_new() const;		// create copy of my; incl. memory for data but without copying the data
		const FAMGGridVector& GetGridVector() const {return mygridvector;}
				
        const FAMGSparseVector *GetSparseVectorPtr() const {return &sv;}
        double *GetValuePtr(const FAMGVectorEntry& ve) const {return &(VVALUE(ve.myvector(),0));}

		double& operator[]( const FAMGVectorEntry& ve ) {return VVALUE(ve.myvector(),GetComp());}
		double operator[]( const FAMGVectorEntry& ve ) const {return VVALUE(ve.myvector(),GetComp());}
		FAMGVector& operator=( const FAMGVector &v ) {CopyValue(*this,v); return *this;}
		FAMGVector& operator+=( const FAMGVector &v ) {AddValue(*this,v); return *this;}
		FAMGVector& operator-=( const FAMGVector &v ) {SubtractValue(*this,v); return *this;}
		double operator=(double val) {SetValue(*this,val); return val;}
		double operator*(const FAMGVector &v) {return ScalProd(*this,v);}	// scalar product
		FAMGVector& operator*=(double scale) {Scale(*this,scale); return *this;}
		
		int is_valid( const FAMGVectorEntry& ve ) const {return ve.myvector()!=NULL;}
		int is_end( const FAMGVectorEntry& ve ) const {return ve.myvector()==NULL;}
		int is_beforefirst( const FAMGVectorEntry& ve ) {return ve.myvector()==NULL;}
		FAMGVectorEntry firstEntry(const FAMGVectorEntry& ve) const {return GetGridVector().firstEntry();}
		FAMGVectorEntry lastEntry() const {return GetGridVector().lastEntry();}
		FAMGVectorEntry endEntry() const {return (FAMGVectorEntry)NULL;}

		int IsCG( const FAMGVectorEntry& ve ) const {return VCCOARSE(ve.myvector());}
		int IsFG( const FAMGVectorEntry& ve ) const {return !IsCG(ve);}
		void SetCG( const FAMGVectorEntry& ve ) const {SETVCCOARSE(ve.myvector(),1);}
		void SetFG( const FAMGVectorEntry& ve ) const {SETVCCOARSE(ve.myvector(),0);}
		
		double norm() const {return ::norm(*this);}
		double sum() const {return ::sum(*this);}
		void AddScaledVec( double scale, const FAMGVector &source ) {::AddScaledValue( *this, scale, source);}
		void VecMinusMatVec( const FAMGVector &rhs, const FAMGMatrixAlg &mat, const FAMGVector &sol ) {::VecMinusMatVec( *this, rhs, mat, sol);}
		void MatVec( const FAMGMatrixAlg &mat, const FAMGVector &source ) {::MatVec( *this, mat, source);}

		void JacobiSmoother( const FAMGMatrixAlg &mat, const FAMGVector &def ) {::JacobiSmoother( *this, mat, def );}
		void dampedJacobiSmoother( const FAMGMatrixAlg &mat, const FAMGVector &def ) {::dampedJacobiSmoother( *this, mat, def );}
		void FGSSmoother( const FAMGMatrixAlg &mat, FAMGVector &def ) {::FGSSmoother( *this, mat, def );}
		void BGSSmoother( const FAMGMatrixAlg &mat, FAMGVector &def ) {::BGSSmoother( *this, mat, def );}
		void SGSSmoother( const FAMGMatrixAlg &mat, FAMGVector &def ) {::SGSSmoother( *this, mat, def );}
		void JacobiSmoothFG( const FAMGMatrixAlg &mat, const FAMGVector &def ) {::JacobiSmoothFG( *this, mat, def );}

		VECDATA_DESC *GetUgVecDesc () const {return mydesc;}
	protected:
		const FAMGGridVector &mygridvector;
	
	private:
		int GetComp() const {return comp;}
		VECDATA_DESC *mydesc;
		int comp;
		int allocatedVD;	// 1 if a new VECDATA_DESC was allocated for this vector
        FAMGSparseVector sv;
};
#else
class FAMGVector
{
	friend class FAMGVectorIter;
	friend class FAMGVectorRevIter;
		
	public:
		typedef class FAMGVectorEntry VectorEntry;
		typedef class FAMGVectorIter Iterator;
		typedef class FAMGVectorRevIter RevIterator;
		
		FAMGVector(const FAMGGridVector& gridvec) : mygridvector(gridvec) {}
		~FAMGVector();
		FAMGVector( const FAMGGridVector& gridvec, VECDATA_DESC *vec_desc ) : mygridvector(gridvec), mydesc(vec_desc) {allocatedVD=0; assert(VD_IS_SCALAR(vec_desc)); comp = VD_SCALCMP(vec_desc);}
		FAMGVector( const FAMGGridVector& gridvec, const FAMGVector &pattern_vec) : mygridvector(gridvec), mydesc(pattern_vec.mydesc), comp(pattern_vec.comp) {}
		FAMGVector* create_new() const;		// create copy of my; incl. memory for data but without copying the data
		const FAMGGridVector& GetGridVector() const {return mygridvector;}
				
		double& operator[]( const FAMGVectorEntry& ve ) {return VVALUE(ve.myvector(),GetComp());}
		double operator[]( const FAMGVectorEntry& ve ) const {return VVALUE(ve.myvector(),GetComp());}
		FAMGVector& operator=( const FAMGVector &v ) {CopyValue(*this,v); return *this;}
		FAMGVector& operator+=( const FAMGVector &v ) {AddValue(*this,v); return *this;}
		FAMGVector& operator-=( const FAMGVector &v ) {SubtractValue(*this,v); return *this;}
		double operator=(double val) {SetValue(*this,val); return val;}
		double operator*(const FAMGVector &v) {return ScalProd(*this,v);}	// scalar product
		FAMGVector& operator*=(double scale) {Scale(*this,scale); return *this;}
		
		int is_valid( const FAMGVectorEntry& ve ) const {return ve.myvector()!=NULL;}
		int is_end( const FAMGVectorEntry& ve ) const {return ve.myvector()==NULL;}
		int is_beforefirst( const FAMGVectorEntry& ve ) {return ve.myvector()==NULL;}
		FAMGVectorEntry firstEntry(const FAMGVectorEntry& ve) const {return GetGridVector().firstEntry();}
		FAMGVectorEntry lastEntry() const {return GetGridVector().lastEntry();}
		FAMGVectorEntry endEntry() const {return (FAMGVectorEntry)NULL;}

		int IsCG( const FAMGVectorEntry& ve ) const {return VCCOARSE(ve.myvector());}
		int IsFG( const FAMGVectorEntry& ve ) const {return !IsCG(ve);}
		void SetCG( const FAMGVectorEntry& ve ) const {SETVCCOARSE(ve.myvector(),1);}
		void SetFG( const FAMGVectorEntry& ve ) const {SETVCCOARSE(ve.myvector(),0);}
		
		double norm() const {return ::norm(*this);}
		double sum() const {return ::sum(*this);}
		void AddScaledVec( double scale, const FAMGVector &source ) {::AddScaledValue( *this, scale, source);}
		void VecMinusMatVec( const FAMGVector &rhs, const FAMGMatrixAlg &mat, const FAMGVector &sol ) {::VecMinusMatVec( *this, rhs, mat, sol);}
		void MatVec( const FAMGMatrixAlg &mat, const FAMGVector &source ) {::MatVec( *this, mat, source);}

		void JacobiSmoother( const FAMGMatrixAlg &mat, const FAMGVector &def ) {::JacobiSmoother( *this, mat, def );}
		void dampedJacobiSmoother( const FAMGMatrixAlg &mat, const FAMGVector &def ) {::dampedJacobiSmoother( *this, mat, def );}
		void FGSSmoother( const FAMGMatrixAlg &mat, FAMGVector &def ) {::FGSSmoother( *this, mat, def );}
		void BGSSmoother( const FAMGMatrixAlg &mat, FAMGVector &def ) {::BGSSmoother( *this, mat, def );}
		void SGSSmoother( const FAMGMatrixAlg &mat, FAMGVector &def ) {::SGSSmoother( *this, mat, def );}
		void JacobiSmoothFG( const FAMGMatrixAlg &mat, const FAMGVector &def ) {::JacobiSmoothFG( *this, mat, def );}

		VECDATA_DESC *GetUgVecDesc () const {return mydesc;}
	protected:
		const FAMGGridVector &mygridvector;
	
	private:
		int GetComp() const {return comp;}
		VECDATA_DESC *mydesc;
		int comp;
		int allocatedVD;	// 1 if a new VECDATA_DESC was allocated for this vector
};
#endif
class FAMGVectorIter
{
	public:
		FAMGVectorIter( const FAMGGridVector& gv ) : mygridvector(gv), current_ve(gv.firstEntry()) {}
		FAMGVectorIter( const FAMGVector& v ) : mygridvector(v.GetGridVector()), current_ve(v.GetGridVector().firstEntry()) {}

		int operator()( FAMGVectorEntry& ve ) {int res = !mygridvector.is_end(ve=current_ve); if(res) ++current_ve; return res;}
		void reset() {current_ve = mygridvector.firstEntry();}
	private:
		const FAMGGridVector& mygridvector;
		FAMGVectorEntry current_ve;
};

class FAMGVectorRevIter
{
	public:
		FAMGVectorRevIter( const FAMGGridVector& gv ) : mygridvector(gv), current_ve(gv.lastEntry()) {}
		FAMGVectorRevIter( const FAMGVector& v ) : mygridvector(v.mygridvector), current_ve(v.GetGridVector().lastEntry()) {}

		int operator()( FAMGVectorEntry& ve ) {int res = !mygridvector.is_beforefirst(ve=current_ve); if(res) --current_ve; return res;}
		void reset() {current_ve = mygridvector.lastEntry();}
	private:
		const FAMGGridVector &mygridvector;
		FAMGVectorEntry current_ve;
};

//
// matrix stuff
//

class FAMGMatrixEntry
{
	friend class FAMGMatrixAlg;
	friend class FAMGMatrixIter;
		
	public:
		FAMGMatrixEntry() : matp(NULL) {}
		FAMGMatrixEntry( const FAMGMatrixEntry& me ) : matp(me.GetMyMatrix()) {}
		~FAMGMatrixEntry() {}	// nothing to do
		
		FAMGMatrixEntry& operator=( const FAMGMatrixEntry& me ) { matp=me.GetMyMatrix(); return *this;}
		FAMGMatrixEntry& operator++() {matp = MNEXT(matp); return *this;}				// prefix
		FAMGMatrixEntry& operator++(int) {FAMGMatrixEntry& tmp = *this; ++*this; return tmp;}	// postfix
		
		FAMGVectorEntry dest() const {return (FAMGVectorEntry)MDEST(GetMyMatrix());}

		int is_strong() const {return MUSED(GetMyMatrix());}
		void set_strong(const int n) {SETMUSED(GetMyMatrix(),n);}
		
	private:
		FAMGMatrixEntry( MATRIX *mat) : matp(mat) {}
		MATRIX* GetMyMatrix() const {return matp;}
		MATRIX*& myMatrix() {return matp;}
		MATRIX *matp;
};

#ifdef FAMG_SPARSE_BLOCK
// todo: remove comp, compD
class FAMGMatrixAlg 
{
	public:
		typedef class FAMGVector Vector;
		typedef class FAMGGridVector GridVector;
		typedef class FAMGMatrixEntry MatrixEntry;
		typedef class FAMGMatrixIter Iterator;

		FAMGMatrixAlg( int nr_vecs, int nr_links ) : n(nr_vecs), nlinks(nr_links) {}
    FAMGMatrixAlg( GRID *grid, MATDATA_DESC *md, int nrVec, int nrLink ) : n(nrVec), nlinks(nrLink), mygrid(grid), matdesc(md), sb(md->sm[MTP(0,0)]), sbd(md->sm[DMTP(0)]) {sbT.Transposed(&sb);}
    FAMGMatrixAlg( GRID *grid, MATDATA_DESC *md, int nrVec) : n(nrVec), nlinks(nrVec), mygrid(grid), matdesc(md)), sb(md->sm[MTP(0,0)]), sbd(md->sm[DMTP(0)]){sbT.Transposed(&sb);}
		FAMGMatrixAlg( GRID *grid, MATDATA_DESC *md ) : n(0), nlinks(0), mygrid(grid), matdesc(md), sb(md->sm[MTP(0,0)]), sbd(md->sm[DMTP(0)] ) {sbT.Transposed(&sb);} // CAUTION: set N and NLinks explicitly
		FAMGMatrixAlg( GRID *grid, const FAMGMatrixAlg &pattern_mat) :  n(0), nlinks(0), mygrid(grid), sb(pattern_mat.sb), sbT(pattern_mat.sbT), sbd(pattern_mat.sbd) { matdesc = NULL; if(pattern_mat.GetMatDesc()->locked) matdesc = pattern_mat.GetMatDesc(); else AllocMDFromMD(MYMG(grid), GLEVEL(grid), GLEVEL(grid), pattern_mat.GetMatDesc(), &matdesc); assert(matdesc!=NULL);}
		~FAMGMatrixAlg() {if (FreeMD(MYMG(GetMyGrid()),GLEVEL(GetMyGrid()),GLEVEL(GetMyGrid()),GetMatDesc())) assert(0);}

		double operator[]( const FAMGMatrixEntry& me ) const {if(MDIAG(me.GetMyMatrix())) return MVALUE(me.GetMyMatrix(),GetCompD());else return MVALUE(me.GetMyMatrix(),GetComp());}
		double& operator[]( const FAMGMatrixEntry& me ) {if(MDIAG(me.GetMyMatrix())) return MVALUE(me.GetMyMatrix(),GetCompD());else return MVALUE(me.GetMyMatrix(),GetComp());}
    
    double *GetValuePtr(const FAMGMatrixEntry& me ) const {return &(MVALUE(me.GetMyMatrix(),0));}
    double *GetDiagValuePtr(const FAMGVectorEntry& ve) const {return &(MVALUE(VSTART(ve.myvector()),0));}
    double *GetAdjValuePtr( const FAMGMatrixEntry& me ) const {return &(MVALUE(MADJ(me.GetMyMatrix()),0));}
    FAMGSparseBlock GetSparseBlock() const {return sb;}
    FAMGSparseBlock GetSparseBlockAdj() const {return sbT;}
    FAMGSparseBlock GetDiagSparseBlock() const {return sbd;}
    const FAMGSparseBlock *GetSparseBlockPtr() const {return &sb;}
    const FAMGSparseBlock *GetSparseBlockAdjPtr() const {return &sbT;}
    const FAMGSparseBlock *GetDiagSparseBlockPtr() const {return &(sbd);}

		int is_valid( const FAMGVectorEntry& row_ve, const FAMGMatrixEntry& me ) const {return me.GetMyMatrix()!=NULL;}
		int is_end( const FAMGVectorEntry& row_ve, const FAMGMatrixEntry& me ) const {return me.GetMyMatrix()==NULL;}
		FAMGMatrixEntry firstEntry( const FAMGVectorEntry& row_ve ) const {return (FAMGMatrixEntry)VSTART(row_ve.myvector());}
		FAMGMatrixEntry endEntry( const FAMGVectorEntry& row_ve ) const {return (FAMGMatrixEntry)NULL;}
		double DiagValue( const FAMGVectorEntry& row_ve ) const {return MVALUE(VSTART(row_ve.myvector()),GetCompD());}
		double GetAdjData( const FAMGMatrixEntry& me ) const {return MVALUE(MADJ(me.GetMyMatrix()),GetComp());}
		void AddEntry(double mval, const FAMGVectorEntry &row, const FAMGVectorEntry &col);	
        void AddEntry(const FAMGSparseBlock *sbm, const double *mval, const FAMGVectorEntry &row, const FAMGVectorEntry &col);
        void AddEntry(const FAMGSparseBlock *sbm, const double *mval, const FAMGVectorEntry &row, const FAMGVectorEntry &col, double factor);
		int ConstructGalerkinMatrix( const FAMGGrid &fg ) {return ::ConstructGalerkinMatrix(*this, fg);}
		void MarkStrongLinks( const FAMGGrid &grid ) const {::MarkStrongLinks(*this, grid);}
		
		int &GetN() {return n;}
		int &GetNLinks() {return nlinks;}
		MATDATA_DESC *GetMatDesc() const {return matdesc;}
		
	private:
		int n;		// number of vectors
		int nlinks;	// number of links (==entries) in the matrix
		GRID *GetMyGrid() {return mygrid;}
		int GetComp() const {return comp;}
		int GetCompD() const {return compD;}
		int comp;
		int compD;
		GRID *mygrid;
		MATDATA_DESC *matdesc;
        FAMGSparseBlock sb;
        FAMGSparseBlock sbT;
        FAMGSparseBlock sbd;
};
#else
class FAMGMatrixAlg
{
	public:
		typedef class FAMGVector Vector;
		typedef class FAMGGridVector GridVector;
		typedef class FAMGMatrixEntry MatrixEntry;
		typedef class FAMGMatrixIter Iterator;

		FAMGMatrixAlg( int nr_vecs, int nr_links ) : n(nr_vecs), nlinks(nr_links) {}
		FAMGMatrixAlg( GRID *grid, MATDATA_DESC *md, int nrVec, int nrLink ) : n(nrVec), nlinks(nrLink), comp(MD_SCALCMP(md)), mygrid(grid), matdesc(md) {assert(MD_IS_SCALAR(md));}
		FAMGMatrixAlg( GRID *grid, MATDATA_DESC *md ) : n(0), nlinks(0), comp(MD_SCALCMP(md)), mygrid(grid), matdesc(md) {assert(MD_IS_SCALAR(md));} // CAUTION: set N and NLinks explicitly
		FAMGMatrixAlg( GRID *grid, const FAMGMatrixAlg &pattern_mat) :  n(0), nlinks(0), mygrid(grid) { matdesc = NULL; if(pattern_mat.GetMatDesc()->locked) matdesc = pattern_mat.GetMatDesc(); else AllocMDFromMD(MYMG(grid), GLEVEL(grid), GLEVEL(grid), pattern_mat.GetMatDesc(), &matdesc); assert(matdesc!=NULL); assert(MD_IS_SCALAR(matdesc)); comp = MD_SCALCMP(matdesc);}
		~FAMGMatrixAlg() {if (FreeMD(MYMG(GetMyGrid()),GLEVEL(GetMyGrid()),GLEVEL(GetMyGrid()),GetMatDesc())) assert(0);}
		double operator[]( const FAMGMatrixEntry& me ) const {return MVALUE(me.GetMyMatrix(),GetComp());}
		double& operator[]( const FAMGMatrixEntry& me ) {return MVALUE(me.GetMyMatrix(),GetComp());}
		int is_valid( const FAMGVectorEntry& row_ve, const FAMGMatrixEntry& me ) const {return me.GetMyMatrix()!=NULL;}
		int is_end( const FAMGVectorEntry& row_ve, const FAMGMatrixEntry& me ) const {return me.GetMyMatrix()==NULL;}
		FAMGMatrixEntry firstEntry( const FAMGVectorEntry& row_ve ) const {return (FAMGMatrixEntry)VSTART(row_ve.myvector());}
		FAMGMatrixEntry endEntry( const FAMGVectorEntry& row_ve ) const {return (FAMGMatrixEntry)NULL;}
		double DiagValue( const FAMGVectorEntry& row_ve ) const {return MVALUE(VSTART(row_ve.myvector()),GetComp());}
		double GetAdjData( const FAMGMatrixEntry& me ) const {return MVALUE(MADJ(me.GetMyMatrix()),GetComp());}
		void AddEntry(double mval, const FAMGVectorEntry &row, const FAMGVectorEntry &col);	
		int ConstructGalerkinMatrix( const FAMGGrid &fg ) {return ::ConstructGalerkinMatrix(*this, fg);}
		void MarkStrongLinks( const FAMGGrid &grid ) const {::MarkStrongLinks(*this, grid);}
		
		int &GetN() {return n;}
		int &GetNLinks() {return nlinks;}
		MATDATA_DESC *GetMatDesc() const {return matdesc;}
		
	private:
		int n;		// number of vectors
		int nlinks;	// number of links (==entries) in the matrix
		GRID *GetMyGrid() {return mygrid;}
		int GetComp() const {return comp;}
		int comp;
		GRID *mygrid;
		MATDATA_DESC *matdesc;
};
#endif

class FAMGMatrixIter
{
	public:
		FAMGMatrixIter( const FAMGMatrixAlg& m, const FAMGVectorEntry& row_ve) : myMatrix(m), myrow_ve(row_ve), current_me(m.firstEntry(row_ve)) {}
		
		int operator()( FAMGMatrixEntry& me ) {me=current_me; int res = (current_me.GetMyMatrix()!=NULL); if(res) ++current_me; return res;}
		void reset() {current_me = myMatrix.firstEntry(myrow_ve);}

	private:
		const FAMGMatrixAlg& myMatrix;
		const FAMGVectorEntry& myrow_ve;
		FAMGMatrixEntry current_me;
};

#ifdef __KCC
typedef FAMGVectorEntryRef FAMGugVectorEntryRef;
typedef class FAMGVectorEntry FAMGugVectorEntry;
typedef class FAMGGridVector FAMGugGridVector;
typedef class FAMGVector FAMGugVector;
typedef class FAMGMatrixEntry FAMGugMatrixEntry;
typedef class FAMGMatrixAlg FAMGugMatrix;
typedef class FAMGMatrixIter FAMGugMatrixIter;
#endif

#ifdef __SGI10__
typedef FAMGVectorEntryRef FAMGugVectorEntryRef;
typedef class FAMGVectorEntry FAMGugVectorEntry;
typedef class FAMGGridVector FAMGugGridVector;
typedef class FAMGVector FAMGugVector;
typedef class FAMGMatrixEntry FAMGugMatrixEntry;
typedef class FAMGMatrixAlg FAMGugMatrix;
typedef class FAMGMatrixIter FAMGugMatrixIter;
#endif

#endif

