// Copyright (C) 1996 DIMACS Center, Rutgers, The State University of New Jersey
// Author(s): ??

// This software is copyrighted by the DIMACS Center at Rutgers, The State
// University of New Jersey.  IT IS PROVIDED AS IS, AND THE AUTHORS, DIMACS, AND
// RUTGERS, THE STATE UNIVERSITY OF NEW JERSEY  DISCLAIM
// ALL LIABILITY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
// DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

// THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
// IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
// NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
// MODIFICATIONS.

// The authors hereby grant permission to use, copy, modify, distribute,
// and license this software and its documentation for any purpose, provided
// that existing copyright notices are retained in all copies and that this
// notice is included verbatim in any distributions. No written agreement,
// license, or royalty fee is required for any of the authorized uses.
// Modifications to this software may be copyrighted by their authors
// and need not follow the licensing terms described here, provided that
// the new terms are clearly indicated on the first page of each file where
// they apply.

// Last File Update: 31-Jul-1996
// 

#ifndef IntMATRIX_H
#define IntMATRIX_H

/*
 *  WARNING!  This is the origial Matrix.h restricted to integer elements.
 *            (maybe a declining/unsupported piece of software)
 *
 *  Matrix -> IntMatrix
 *  SymMatrix -> SymIntMatrix 	(Still the only symmetric matrix class.)
 *  AsymMatrix -> AsymIntMatrix
 */

#include <iostream.h>
#include <LINK/basic/general.h>

ostream& operator<<(ostream&, const class IntMatrix&);

// 
// abstract super class for matrices
//
class IntMatrix {
protected:
    int		 numrows;   // number of rows
    int		 numcols;   // number of cols

   //checks the dimensions of a matrix
   //virtual void check_dimensions(int i,j); 

public:
    IntMatrix(int rows=0, int cols=0) : numrows(rows), numcols(cols) {}

    virtual ~IntMatrix() {};
    
    virtual void save(char* filename) = 0;
    virtual void load(char* filename) = 0;

    // returns element i,j.  Can also be used to set element i,j
    virtual 	int& operator() (int i,int j) = 0;   

    int get(int i, int j) const 
    { 
      return ((IntMatrix&) *this)(i,j); // read-only copy of element
    }

    void display()  { cout << *this; }  // calls op() virtual method
    
    // return number of rows and number of columns
    int 	numRows() const    { return numrows;}
    int		numCols() const    { return numcols;}
};


// forward declartion
class SymIntMatrix;

//
// asymmetric matrices
//
class AsymIntMatrix : public IntMatrix { 
        
friend class SymIntMatrix; 

public:
    AsymIntMatrix(int=0, int=0);
    AsymIntMatrix(const AsymIntMatrix& A);
    ~AsymIntMatrix();

    void	 save(char* filename);
    void 	 load(char* filename);

    // returns or sets element: row,col
    int&	 operator() (int row, int col);
    //
    int	 	 at(int row, int col) const
                 { return ((AsymIntMatrix&)*this)(row,col); }

    // assigns one AsymIntMatrix the values of another AsymIntMatrix        
    AsymIntMatrix&	 operator=(const AsymIntMatrix& A);

    // overloaded operators
    AsymIntMatrix	 operator*(const AsymIntMatrix& A); //asym * asym
    AsymIntMatrix	 operator*(const SymIntMatrix&  S); //asym * sym
    AsymIntMatrix	 operator*(const int scalar);       //asym * element

    AsymIntMatrix	 operator+(const AsymIntMatrix& A); //asym + asym
    AsymIntMatrix	 operator+(const SymIntMatrix&  S); //asym + sym

    AsymIntMatrix	 operator-(const AsymIntMatrix& A); //asym - asym
    AsymIntMatrix	 operator-(const SymIntMatrix&  S); //asym - sym
        
    Bool	 operator==(const AsymIntMatrix& A);       //asym == asym
    Bool	 operator==(const SymIntMatrix& S);        //asym == sym

    Bool	 operator!=(const AsymIntMatrix& A);       //asym != asym
    Bool	 operator!=(const SymIntMatrix& S);        //asym != sym

    AsymIntMatrix	 transpose();

private:
    // points to the elements of the asymmetric matrix
    int**	 Elements;                               
       
    // returns element row,col.  Used only for const asymmetric matrices
    // Does not check if element row,col is legal, therefore this is 
    // only used when we know we are within the matrix's bounds
    int	 operator()(int row, int col) const;
};


class SymIntMatrix : public IntMatrix {

friend class AsymIntMatrix;

public:
    SymIntMatrix(int dim=0,...); // allow two arguments but use only the first
				 // to be compatible with (#rows,#cols)
    SymIntMatrix(const SymIntMatrix& S);
    ~SymIntMatrix();

    void	 save(char * filename);
    void	 load(char * filename);

    int 	 dimension() const    { return numrows;}

    // returns or sets element row,col 
    int&	 operator() (int row, int col) ; 

    // assigns one SymIntMatrix the values of another SymIntMatrix 
    SymIntMatrix&	 operator=(const SymIntMatrix& S);

    // overloaded operators
    AsymIntMatrix	 operator*(const AsymIntMatrix& A);      //sym * asym
    AsymIntMatrix	 operator*(const SymIntMatrix&  S);      //sym * sym
    SymIntMatrix 	 operator*(const int scalar);       	 //sym * element

    SymIntMatrix 	 operator+(const SymIntMatrix&  S);      //sym + sym
    AsymIntMatrix	 operator+(const AsymIntMatrix& A);      //sym + asym

    SymIntMatrix 	 operator-(const SymIntMatrix&  S);      //sym - sym
    AsymIntMatrix	 operator-(const AsymIntMatrix& A);      //sym - asym

    Bool	 operator==(const SymIntMatrix& S);        //sym == sym
    Bool	 operator==(const AsymIntMatrix& A);       //sym == asym

    Bool	 operator!=(const SymIntMatrix& S);        //sym != sym
    Bool	 operator!=(const AsymIntMatrix& A);       //sym != asym

    SymIntMatrix	 transpose();

private:
    //points to the elements of the SymIntMatrix stored in lower triangual form
    int*	 LowTriangMat;

    // contains the number of elements in the SymIntMatrix
    int		 size;
  
    // returns element row,col.  Used only for const symmetric matrices
    // Does not check if element row,col is legal, therefore is only used
    // when we know element row,col is within the matrix's bounds  
    int	 	operator()(int row, int col) const;
};


#endif

