//$$ newmatrc.hxx            definition file for row/column classes

// Copyright (C) 1991: R B Davies and DSIR

#ifndef MATRIXRC_LIB
#define MATRIXRC_LIB 0

#include "controlw.hxx"



/************** classes MatrixRowCol, MatrixRow, MatrixCol *****************/

// Used for accessing the rows and columns of matrices
// All matrix classes must provide routines for calculating matrix rows and
// columns. Assume rows can be found very efficiently.

enum { LoadOnEntry=1,StoreOnExit=2,IsACopy=4,DirectPart=8,StoreHere=16 };

class MatrixRowCol
// the row or column of a matrix
{
public:                                        // these are public to avoid
                                               // numerous friend statements
   int length;                                 // row or column length
   int skip;                                   // initial number of zeros
   int storage;                                // number of stored elements
   int rowcol;                                 // row or column number
   GeneralMatrix* gm;                          // pointer to parent matrix
   real* store;                                // pointer to local storage
                                               //    less skip
   ControlWord cw;                             // Load? Store? Is a Copy?
   void IncrMat() { rowcol++; store += storage; }
                                               // used by NextRow
   void IncrDiag() { rowcol++; skip++; }
   void IncrUT() { rowcol++; storage--; store += storage; skip++; }
   void IncrLT() { rowcol++; store += storage; storage++; }

public:
   void Add(const MatrixRowCol&);              // add a row/col
   void AddScaled(const MatrixRowCol&, real);  // add a multiple of a row/col
   void Add(const MatrixRowCol&, const MatrixRowCol&);
                                               // add two rows/cols
   void Add(const MatrixRowCol&, real);        // add a row/col
   void Sub(const MatrixRowCol&);              // subtract a row/col
   void Sub(const MatrixRowCol&, const MatrixRowCol&);
                                               // sub a row/col from another
   void RevSub(const MatrixRowCol&);           // subtract from a row/col
   void Copy(const MatrixRowCol&);             // copy a row/col
   void Copy(const real*&);                    // copy from an array
   void Copy(real);                            // copy from constant
   real SumAbsoluteValue();                    // sum of absolute values
   void Inject(const MatrixRowCol&);           // copy stored els of a row/col
   void Negate(const MatrixRowCol&);           // change sign of a row/col
   void Multiply(const MatrixRowCol&, real);   // scale a row/col
   friend real DotProd(const MatrixRowCol&, const MatrixRowCol&);
                                               // sum of pairwise product
   real* operator()() { return store+skip; }   // pointer to first element
   real* Store() { return store; }
   int Skip() { return skip; }                 // number of elements skipped
   int Storage() { return storage; }           // number of elements stored
   void Skip(int i) { skip=i; }
   void Storage(int i) { storage=i; }
   void SubRowCol(MatrixRowCol&, int, int) const;
                                               // get part of a row or column
   MatrixRowCol() {}                           // to stop warning messages
   virtual ~MatrixRowCol();
};

class MatrixRow : public MatrixRowCol
{
public:
   // bodies for these are inline at the end of this hxx file
   MatrixRow(GeneralMatrix*, ControlWord, int=0);
                                               // extract a row
   ~MatrixRow();
   void Next();                                // get next row
};

class MatrixCol : public MatrixRowCol
{
public:
   // bodies for these are inline at the end of this hxx file
   MatrixCol(GeneralMatrix*, ControlWord, int=0);
                                               // extract a col
   MatrixCol(GeneralMatrix*, real*, ControlWord, int=0);
                                               // store/retrieve a col
   ~MatrixCol();
   void Next();                                // get next row
};


/**************************** inline bodies ****************************/

inline MatrixRow::MatrixRow(GeneralMatrix* gmx, ControlWord cwx, int row)
{ gm=gmx; cw=cwx; rowcol=row; gm->GetRow(*this); } 

inline void MatrixRow::Next() { gm->NextRow(*this); }

inline MatrixCol::MatrixCol(GeneralMatrix* gmx, ControlWord cwx, int col)
{ gm=gmx; cw=cwx; rowcol=col; gm->GetCol(*this); } 

inline MatrixCol::MatrixCol(GeneralMatrix* gmx, real* r,
   ControlWord cwx, int col)
{ gm=gmx; store=r; cw=cwx+StoreHere; rowcol=col; gm->GetCol(*this); } 

inline void MatrixCol::Next() { gm->NextCol(*this); }

#endif
