/*
 * ICOM 4035 - Data Structures
 * Dr. Manuel Rodriguez-Martinez
 * Department of Electrical and Computer Engineering
 * University of Puerto Rico, Mayaguez
 * 
 * This file name: Matrix.h
 *
 * This file declares the interface of the matrix class.
 *
 */

#ifndef _MATRIX_H
#define _MATRIX_H

#include <iostream>
#include <cassert>
#include <cstdio>
#include "Object.h"

using namespace std;
using namespace uprm_icom4035;

namespace uprm_icom4035 {
  class Matrix {
  public:
    // Various constants related to matrix size
    static const int MAX_ROWS = 100;
    static const int MAX_COLUMNS = 100;
    
    // Define size type for matrix
    typedef std::size_t size_type;
    // Define value type for matrix
    typedef Object value_type;
    
    // Public methods for the matrix class
    
    // Constructor
    Matrix (size_type rows = 1, size_type cols = 2);
    
    // Accessor methods
    
    // Returns the element [i,j]
    value_type get_value(size_type i, size_type j) const;
    // Set the element [i,j]
    void set_value(size_type i, size_type j, value_type val);
    // Return current number of rows in the matrix
    size_type get_rows() const;
    // Set current number of rows
    void set_rows(size_type new_r);
    // Return the current number of columns
    size_type get_cols() const;
    // Set current number of columns
    void set_cols(size_type new_c);

    // Matrix operations
    
    // Matrix equality
    bool operator==(const Matrix& M) const;
    
    // Matrix self-addition
    const Matrix& operator+=(const Matrix& M);
    // Matrix self-substraction
    const Matrix& operator-=(const Matrix& M);
    // Matrix self-multiplication
    const Matrix& operator*=(const Matrix& M);
    // Scalar self-multiplication
    const Matrix& operator*=(int r);
    
    // Matrix transpose 
    Matrix transpose() const;

    // Input operator (Friend function)
    friend istream& operator>>(istream &in, Matrix& M);
    // Output operator (Friend function)
    friend ostream& operator<<(ostream &out, const Matrix& M);
    
  private:
    // Elements in the matrix
    value_type elements[MAX_ROWS][MAX_COLUMNS];
    // Current number of rows in the matrix
    size_type curr_rows;
    // Current number of columns in the matrix
    size_type curr_cols;
  };
  
  // Non-member matrix algebra operations
  
  // Matrix addition
  Matrix operator+(const Matrix& M1, const Matrix& M2);
  // Matrix substraction
  Matrix operator-(const Matrix& M1, const Matrix& M2);
  // Matrix multiplication
  Matrix operator*(const Matrix& M1, const Matrix& M2);
}

#endif 

