
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*                                                                           */
/*                                                                           */
/*                   MV++ Numerical Matrix/Vector C++ Library                */
/*                             MV++ Version 1.5                              */
/*                                                                           */
/*                                  R. Pozo                                  */
/*               National Institute of Standards and Technology              */
/*                                                                           */
/*                                  NOTICE                                   */
/*                                                                           */
/* Permission to use, copy, modify, and distribute this software and         */
/* its documentation for any purpose and without fee is hereby granted       */
/* provided that this permission notice appear in all copies and             */
/* supporting documentation.                                                 */
/*                                                                           */
/* Neither the Institution (National Institute of Standards and Technology)  */
/* nor the author makes any representations about the suitability of this    */
/* software for any purpose.  This software is provided ``as is''without     */
/* expressed or implied warranty.                                            */
/*                                                                           */
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

//
//      mvmtp.h  : basic templated numerical matrix class, storage
//                  by columns (Fortran oriented.)
//
//
//

#ifndef _MV_MATRIX_double_H_
#define _MV_MATRIX_double_H_

#include "mvvd.h"
#include "mvmrf.h"

#include <sstream>

#ifdef MV_MATRIX_BOUNDS_CHECK
#include <assert.h>
#endif

class MV_ColMat_double
{
private:
  MV_Vector_double v_;
  int              dim0_; // perferred to using dim_[2]. some compilers
  int              dim1_; // refuse to initalize these in the constructor.
  int              lda_;
  int              ref_; // true if this is declared as a reference vector,
                         // i.e. it does not own the memory space, but
                         // rather it is a view to another vector or array.
public:

  /*::::::::::::::::::::::::::*/
  /* Constructors/Destructors */
  /*::::::::::::::::::::::::::*/

  MV_ColMat_double();
  MV_ColMat_double( int,  int);

  // some compilers have difficulty with inlined 'for' statements.
  MV_ColMat_double( int,  int, const double &);

  // usual copy by value
  // (can't use default parameter lda=m, because m is not a constant...)
  //
  MV_ColMat_double(double *,  int m,  int n);
  MV_ColMat_double(double *,  int m,  int n,  int lda);

  // the "reference" versions
  //
  //
  MV_ColMat_double(MV_ColMat_double & A, MV_Matrix_::ref_type i);
  MV_ColMat_double(double *,  int m,  int n, MV_Matrix_::ref_type i);
  MV_ColMat_double(double *,  int m,  int n,  int lda, MV_Matrix_::ref_type i);

  MV_ColMat_double(const MV_ColMat_double &);
  ~MV_ColMat_double();

  /*::::::::::::::::::::::::::::::::*/
  /*  Indices and access operations */
  /*::::::::::::::::::::::::::::::::*/

  inline double &       operator()( int,  int);

  inline const double & operator()( int,  int) const;

  MV_ColMat_double operator()(const MV_VecIndex & I, const MV_VecIndex & J);

  const MV_ColMat_double operator()(const MV_VecIndex & I, const MV_VecIndex & J) const;

  int            dim(int i) const;

  int            lda(void) const
  {
    return lda_;
  }

  int            size(int i) const
  {
    return dim(i);
  }

  MV_ColMat_double &        newsize( int,  int);

  int ref() const
  {
    return ref_;
  }

  /*::::::::::::::*/
  /*  Assignment  */
  /*::::::::::::::*/

  MV_ColMat_double & operator=(const MV_ColMat_double &);

  MV_ColMat_double & operator=(const double &);

  friend std::ostream & operator<<(std::ostream & s, const MV_ColMat_double & A);

};

inline double & MV_ColMat_double::operator()( int i,  int j)
{
#ifdef MV_MATRIX_BOUNDS_CHECK
  assert(0 <= i && i < dim(0) );
  assert(0 <= j && j < dim(1) );
#endif
  return v_(j * lda_ + i);      // could use indirect addressing
                                // instead...
}

inline const double & MV_ColMat_double::operator()
  ( int i,  int j) const
{
#ifdef MV_MATRIX_BOUNDS_CHECK
  assert(0 <= i && i < dim(0) );
  assert(0 <= j && j < dim(1) );
#endif
  return v_(j * lda_ + i);
}

inline MV_ColMat_double::MV_ColMat_double(double* d,  int m, int n, MV_Matrix_::ref_type i ) :
  v_(d, m * n, MV_Vector_::ref), dim0_(m), dim1_(n), lda_(m), ref_(i)
{
}

inline MV_ColMat_double::MV_ColMat_double( MV_ColMat_double & A, MV_Matrix_::ref_type i ) :
  v_(&A(0, 0), A.dim(0) * A.dim(1), MV_Vector_::ref),
  dim0_(A.dim(0) ), dim1_(A.dim(1) ), lda_(A.lda() ), ref_(i)
{
}

inline MV_ColMat_double::MV_ColMat_double(double* d,  int m,  int n, int _lda, MV_Matrix_::ref_type i) :
  v_(d, _lda * n, MV_Vector_::ref), dim0_(m), dim1_(n), lda_(_lda),
  ref_(i)
{
}

#endif
