text: /// \ingroup newmat
  ///@{
  
  /// \file newmatrc.h
  /// Header file for row/column classes
  
  // Copyright (C) 1991,2,3,4,7: R B Davies
  
  #ifndef NEWMATRC_LIB
  #define NEWMATRC_LIB 0
  
  #ifdef use_namespace
  namespace NEWMAT
  {
  #endif
  
  #include "controlw.h"
  
  /************** 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 LSF
  {
    LoadOnEntry = 1,
    StoreOnExit = 2,
    DirectPart = 4,
    StoreHere = 8,
    HaveStore = 16
  };
  
  /// Option for accessing row or column.
  /// \internal
  class LoadAndStoreFlag : public ControlWord
  {
  public:
    LoadAndStoreFlag()
    {
    }
    LoadAndStoreFlag(int i) : ControlWord(i)
    {
    }
    LoadAndStoreFlag(LSF lsf) : ControlWord(lsf)
    {
    }
    LoadAndStoreFlag(const ControlWord& cwx) : ControlWord(cwx)
    {
    }
  };
  
  /// Access a row or column of a matrix.
  /// \internal
  class MatrixRowCol
  {
  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* data;           // pointer to local storage
    LoadAndStoreFlag cw;  // Load? Store? Is a Copy?
    void IncrMat()
    {
      rowcol++;
      data += storage;
    }  // used by NextRow
    void IncrDiag()
    {
      rowcol++;
      skip++;
      data++;
    }
    void IncrId()
    {
      rowcol++;
      skip++;
    }
    void IncrUT()
    {
      rowcol++;
      data += storage;
      storage--;
      skip++;
    }
    void IncrLT()
    {
      rowcol++;
      data += storage;
      storage++;
    }
  
  public:
    void Zero();                                // set elements to zero
    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 NegAdd(const MatrixRowCol&, Real);  // Real - 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 ConCat(const MatrixRowCol&, const MatrixRowCol&);
    // concatenate two row/cols
    void Multiply(const MatrixRowCol&);  // multiply a row/col
    void Multiply(const MatrixRowCol&, const MatrixRowCol&);
    // multiply two row/cols
    void KP(const MatrixRowCol&, const MatrixRowCol&);
    // Kronecker Product two row/cols
    void Copy(const MatrixRowCol&);              // copy a row/col
    void CopyCheck(const MatrixRowCol&);         // ... check for data loss
    void Check(const MatrixRowCol&);             // just check for data loss
    void Check();                                // check full row/col present
    void Copy(const double*&);                   // copy from an array
    void Copy(const float*&);                    // copy from an array
    void Copy(const int*&);                      // copy from an array
    void Copy(Real);                             // copy from constant
    void Add(Real);                              // add a constant
    void Multiply(Real);                         // multiply by constant
    Real SumAbsoluteValue();                     // sum of absolute values
    Real MaximumAbsoluteValue1(Real r, int& i);  // maximum of absolute values
    Real MinimumAbsoluteValue1(Real r, int& i);  // minimum of absolute values
    Real Maximum1(Real r, int& i);               // maximum
    Real Minimum1(Real r, int& i);               // minimum
    Real Sum();                                  // sum of 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* Data()
    {
      return data;
    }
    int Skip()
    {
      return skip;
    }  // number of elements skipped
    int Storage()
    {
      return storage;
    }  // number of elements stored
    int Length()
    {
      return length;
    }  // length of row or column
    void Skip(int i)
    {
      skip = i;
    }
    void Storage(int i)
    {
      storage = i;
    }
    void Length(int i)
    {
      length = i;
    }
    void SubRowCol(MatrixRowCol&, int, int) const;
    // get part of a row or column
    MatrixRowCol()
    {
    }  // to stop warning messages
    ~MatrixRowCol();
    FREE_CHECK(MatrixRowCol)
  };
  
  /// Access a row of a matrix.
  /// \internal
  class MatrixRow : public MatrixRowCol
  {
  public:
    // bodies for these are inline at the end of this .h file
    MatrixRow(GeneralMatrix*, LoadAndStoreFlag, int = 0);
    // extract a row
    ~MatrixRow();
    void Next();  // get next row
    FREE_CHECK(MatrixRow)
  };
  
  /// Access a column of a matrix.
  /// \internal
  class MatrixCol : public MatrixRowCol
  {
  public:
    // bodies for these are inline at the end of this .h file
    MatrixCol(GeneralMatrix*, LoadAndStoreFlag, int = 0);
    // extract a col
    MatrixCol(GeneralMatrix*, Real*, LoadAndStoreFlag, int = 0);
    // store/retrieve a col
    ~MatrixCol();
    void Next();  // get next column
    FREE_CHECK(MatrixCol)
  };
  
  /// Alternative to MatrixCol where the complete column is stored externally.
  /// \internal
  class MatrixColX : public MatrixRowCol
  {
  public:
    // bodies for these are inline at the end of this .h file
    MatrixColX(GeneralMatrix*, Real*, LoadAndStoreFlag, int = 0);
    // store/retrieve a col
    ~MatrixColX();
    void Next();  // get next row
    Real* store;  // pointer to local storage
                  //    less skip
    FREE_CHECK(MatrixColX)
  };
  
  /**************************** inline bodies ****************************/
  
  inline MatrixRow::MatrixRow(GeneralMatrix* gmx, LoadAndStoreFlag cwx, int row)
  {
    gm = gmx;
    cw = cwx;
    rowcol = row;
    gm->GetRow(*this);
  }
  
  inline void MatrixRow::Next()
  {
    gm->NextRow(*this);
  }
  
  inline MatrixCol::MatrixCol(GeneralMatrix* gmx, LoadAndStoreFlag cwx, int col)
  {
    gm = gmx;
    cw = cwx;
    rowcol = col;
    gm->GetCol(*this);
  }
  
  inline MatrixCol::MatrixCol(GeneralMatrix* gmx, Real* r, LoadAndStoreFlag cwx, int col)
  {
    gm = gmx;
    data = r;
    cw = cwx + StoreHere;
    rowcol = col;
    gm->GetCol(*this);
  }
  
  inline MatrixColX::MatrixColX(GeneralMatrix* gmx, Real* r, LoadAndStoreFlag cwx, int col)
  {
    gm = gmx;
    store = data = r;
    cw = cwx + StoreHere;
    rowcol = col;
    gm->GetCol(*this);
  }
  
  inline void MatrixCol::Next()
  {
    gm->NextCol(*this);
  }
  
  inline void MatrixColX::Next()
  {
    gm->NextCol(*this);
  }
  
  #ifdef use_namespace
  }
  #endif
  
  #endif
  
  ///@}
  