// ----------------------------------------------------------------------------
//
// Copyright (C) Columbia University, 1994. All Rights Reserved.
// Sameer A. Nene, Shree K. Nayar, Hiroshi Murase
//
// See file LICENSE for details of software license agreement.
//
// ----------------------------------------------------------------------------
//
// matrix.h
//
// Author:               Sameer Nene
// Date:                 05/23/94
// Version:              1.0
// Modification History:
//   10/27/94: (Post Release). Made Matrix::getMaxEigenVectors more efficient.
//
// Bugs:
//
// ToDo:
//   Add a global macro defining the type(float or double or anything else) of
//   the floating point data used to store elements in a Matrix. Unfortunately
//   this adds complexity in reading/writing of matrices from/to disk if
//   compatibility with older files is required, so the plan is shelved for the
//   moment! Using Templates does not solve the problem either.
//
//   Implement a VectAryIter style interface (MatrixIter). Implement
//   Matrix::row() and Matrix::col() to return a row or a column as a vector
//   respectively.
//
// Classes:
//   Matrix
//   MatrixUtil
//
// Notes:
//   This header includes declarations for class Matrix and MatrixUtil. Matrix
//   and MatrixUtil are Persistents.
//
//   Matrix is used to efficiently store m x n floating point elements in
//   tabular format.
//
//   MatrixUtil provides a scoped mechanism for implementation of various
//   matrix processing algorithms. Currently, only the eigen vector computation
//   algorithm is implemented.
//   
// ----------------------------------------------------------------------------

#ifndef MATRIX_INCLUDED
#define MATRIX_INCLUDED

#ifndef PERSISTENT_INCLUDED
#include "persistent.h"
#endif

#ifndef REGISTRY_INCLUDED
#include "registry.h"
#endif

#include <stdio.h>

class ostream;
class Vector;
class VectAry;
class MatrixUtil;

class Matrix : public Persistent {

  // Private Members

  static void* d_protocol;
  static char *d_name_p;
  static Registrar d_registrar;
  
  int d_rsize, d_csize;
  float *d_data_p;

  static Persistent* createFunc();
  // returns a pointer to a newly created Matrix

  // Friends

friend MatrixUtil;
friend Matrix operator*(double, const Matrix &);
friend ostream& operator<<(ostream&, const Matrix&);

  // Protected Members

protected:
  
  int hasProtocol(void* protocol) const;
  // returns 1 if this object is of type(protocol) protocol OR is derived
  // from an object of type(protocol) protocol
  
  // Public Functions

public:

  // Construct & Destroy

  Matrix();
  Matrix(int row, int col); // Matrix of size row x col
  Matrix(const Matrix&);
  ~Matrix();

  // Manipulators

  Matrix& operator=(const Matrix&);
  void element(int row, int col, double v); // Sets value of element i to v
  Matrix& operator+=(const Matrix&);
  Matrix& operator-=(const Matrix&);
  Matrix& operator*=(const Matrix&);
  Matrix& operator*=(double);

  Error get(FILE*);
  // gets Matrix from file
  
  // Accessors

  static Matrix* safeCast(Persistent*);
  // Converts Persistent to a Matrix if the object pointed to by
  // Persistent is in fact a Matrix

  double element(int row, int col) const;
  int numRows() const;
  int numCols() const;

  Error put(FILE*) const;
  // puts Matrix in file

  const char* name() const;
  // returns the name of the class

  // Operations

  Matrix operator+(const Matrix&) const;
  Matrix operator-(const Matrix&) const;
  Matrix operator*(const Matrix&) const;
  Matrix operator*(double) const;
  Vector operator*(const Vector&) const;

};

Matrix operator*(double, const Matrix&);
ostream& operator<<(ostream&, const Matrix&);

class MatrixUtil : public ErrorScope {

  // Public members

public:

  static void getMaxEigenVectors(Matrix*, VectAry*, Vector*);
  // Gets Eigen vectors for the supplied Matrix with maximum dimension
  // in VectAry. The size of VectAry should be set to the number of eigen
  // vectors desired. Eigenvalues are returned in the vector. The length of the
  // vector should be set to the number of eigenvalues to be returned. The
  // matrix is overwritten at the end of the call; if the user wishes to
  // preserve the matrix, s/he make a copy before calling this method.

};

#endif		     
