matrix.cpp

#include <iostream>
//#include <iomanip>
#include "matrix.h"


namespace SW {

  /*
  // Example
  #include "matrix.h"
  #include <iostream>

  int main(int argc, char **argv)
  {
  Matrix<double> mat1(10, 10, 1.0);
  Matrix<double> mat2(10, 10, 2.0);

  Matrix<double> mat3 = mat1 + mat2;

  for (int i = 0; i<mat3.get_rows(); i++)
  {
  for (int j = 0; j<mat3.get_cols(); j++)
  {
  std::cout << mat3(i, j) << ", ";
  }
  std::cout << std::endl;
  }

  return 0;
  }
  */




  // Basic Constructor.
  template<typename T>
  Matrix<T>::Matrix()
  {
    rows = 0;
    cols = 0;
  }
  /**/

  // Parameter Constructor.
  template<typename T>
  Matrix<T>::Matrix(unsigned _rows, unsigned _cols)
  {
    mat.resize(_rows);
    for (unsigned i = 0; i<mat.size(); i++)
    {
      mat[i].resize(_cols, 0);
    }

    rows = _rows;
    cols = _cols;
  }


  // Parameter Constructor.
  template<typename T>
  Matrix<T>::Matrix(unsigned _rows, unsigned _cols, const T& _initial)
  {
    mat.resize(_rows);
    for (unsigned i = 0; i<mat.size(); i++)
    {
      mat[i].resize(_cols, _initial);
    }

    rows = _rows;
    cols = _cols;
  }
  /**/

  // Copy Constructor.
  template<typename T>
  Matrix<T>::Matrix(const Matrix<T>& rhs)
  {
    mat = rhs.mat;
    rows = rhs.get_rows();
    cols = rhs.get_cols();
  }


  // (Virtual) Destructor.
  template<typename T>
  Matrix<T>::~Matrix()
  {

  }
  /**/

  // Comparison Operator ==.
  template<typename T>
  bool Matrix<T>::operator==(const Matrix<T>& rhs) const
  {
    unsigned rows = rhs.get_rows();
    unsigned cols = rhs.get_cols();

    if (get_rows() != rows)
      return false;

    if (get_cols() != cols)
      return false;

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        if (this->mat[i][j] != rhs(i, j))
          return false;
      }
    }

    return true;
  }


  // Comparison Operator !=.
  template<typename T>
  bool Matrix<T>::operator!=(const Matrix<T>& rhs) const
  {
    unsigned rows = rhs.get_rows();
    unsigned cols = rhs.get_cols();

    if (get_rows() != rows)
      return true;

    if (get_cols() != cols)
      return true;

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        if (this->mat[i][j] == rhs(i, j))
          return false;
      }
    }

    return false;
  }


  // Comparison Operator <.
  template<typename T>
  bool Matrix<T>::operator<(const Matrix<T>& rhs) const
  {
    unsigned rows = rhs.get_rows();
    unsigned cols = rhs.get_cols();

    if (get_rows() != rows)
      return false;

    if (get_cols() != cols)
      return false;

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        if (this->mat[i][j] >= rhs(i, j))
          return false;
      }
    }

    return true;
  }


  // Comparison Operator <=.
  template<typename T>
  bool Matrix<T>::operator<=(const Matrix<T>& rhs) const
  {
    unsigned rows = rhs.get_rows();
    unsigned cols = rhs.get_cols();

    if (get_rows() != rows)
      return false;

    if (get_cols() != cols)
      return false;

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        if (this->mat[i][j] > rhs(i, j))
          return false;
      }
    }

    return true;
  }



  // Comparison Operator <.
  template<typename T>
  bool Matrix<T>::operator>(const Matrix<T>& rhs) const
  {
    unsigned rows = rhs.get_rows();
    unsigned cols = rhs.get_cols();

    if (get_rows() != rows)
      return false;

    if (get_cols() != cols)
      return false;

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        if (this->mat[i][j] <= rhs(i, j))
          return false;
      }
    }

    return true;
  }


  // Comparison Operator >=.
  template<typename T>
  bool Matrix<T>::operator>=(const Matrix<T>& rhs) const
  {
    unsigned rows = rhs.get_rows();
    unsigned cols = rhs.get_cols();

    if (get_rows() != rows)
      return false;

    if (get_cols() != cols)
      return false;

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        if (this->mat[i][j] < rhs(i, j))
          return false;
      }
    }

    return true;
  }


  // Assignment Operator.
  template<typename T>
  Matrix<T>& Matrix<T>::operator=(const Matrix<T>& rhs)
  {
    if (&rhs == this)
      return *this;

    unsigned new_rows = rhs.get_rows();
    unsigned new_cols = rhs.get_cols();

    mat.resize(new_rows);
    for (unsigned i = 0; i<mat.size(); i++)
    {
      mat[i].resize(new_cols);
    }

    for (unsigned i = 0; i<new_rows; i++)
    {
      for (unsigned j = 0; j<new_cols; j++)
      {
        mat[i][j] = rhs(i, j);
      }
    }

    rows = new_rows;
    cols = new_cols;

    return *this;
  }





  // Unary - operator
  template<typename T>
  Matrix<T> Matrix<T>::operator -() const
  {
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result(i, j) = -this->mat[i][j];
      }
    }

    return result;
  }


  // Prefix increment operator
  template<typename T>
  Matrix<T> Matrix<T>::operator ++ ()
  {
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result(i, j) = this->mat[i][j] + 1;
      }
    }

    return *this = result;
  }


  // Postfix increment operator
  template<typename T>
  Matrix<T> Matrix<T>::operator ++ (int)
  {
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result(i, j) = this->mat[i][j] + 1;
      }
    }

    return result;
  }


  // Prefix decrement operator
  template<typename T>
  Matrix<T> Matrix<T>::operator -- ()
  {
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result(i, j) = this->mat[i][j] - 1;
      }
    }

    return *this = result;
  }


  // Postfix decrement operator
  template<typename T>
  Matrix<T> Matrix<T>::operator -- (int)
  {
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result(i, j) = this->mat[i][j] - 1;
      }
    }

    return result;
  }



  // Addition of two matrices.
  template<typename T>
  Matrix<T> Matrix<T>::operator+(const Matrix<T>& rhs)
  {
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result(i, j) = this->mat[i][j] + rhs(i, j);
      }
    }

    return result;
  }


  // Cumulative addition of this matrix and another.
  template<typename T>
  Matrix<T>& Matrix<T>::operator+=(const Matrix<T>& rhs)
  {
    unsigned rows = rhs.get_rows();
    unsigned cols = rhs.get_cols();

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        this->mat[i][j] += rhs(i, j);
      }
    }

    return *this;
  }


  // Subtraction of this matrix and another.
  template<typename T>
  Matrix<T> Matrix<T>::operator-(const Matrix<T>& rhs)
  {
    unsigned rows = rhs.get_rows();
    unsigned cols = rhs.get_cols();
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result(i, j) = this->mat[i][j] - rhs(i, j);
      }
    }

    return result;
  }


  // Cumulative subtraction of this matrix and another.
  template<typename T>
  Matrix<T>& Matrix<T>::operator-=(const Matrix<T>& rhs)
  {
    unsigned rows = rhs.get_rows();
    unsigned cols = rhs.get_cols();

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        this->mat[i][j] -= rhs(i, j);
      }
    }

    return *this;
  }


  // Left multiplication of this matrix and another.
  template<typename T>
  Matrix<T> Matrix<T>::operator*(const Matrix<T>& rhs)
  {
    unsigned rows = rhs.get_rows();
    unsigned cols = rhs.get_cols();
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        for (unsigned k = 0; k<rows; k++)
        {
          result(i, j) += this->mat[i][k] * rhs(k, j);
        }
      }
    }

    return result;
  }


  // Cumulative left multiplication of this matrix and another.
  template<typename T>
  Matrix<T>& Matrix<T>::operator*=(const Matrix<T>& rhs)
  {
    Matrix result = (*this) * rhs;
    (*this) = result;
    return *this;
  }




  // Left mod of this matrix and another.
  template<typename T>
  Matrix<T> Matrix<T>::operator%(const Matrix<T>& rhs)
  {
    unsigned rows = rhs.get_rows();
    unsigned cols = rhs.get_cols();
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        for (unsigned k = 0; k<rows; k++)
        {
          result(i, j) += this->mat[i][k] % rhs(k, j);
        }
      }
    }

    return result;
  }


  // Cumulative left mod of this matrix and another.
  template<typename T>
  Matrix<T>& Matrix<T>::operator%=(const Matrix<T>& rhs)
  {
    Matrix result = (*this) % rhs;
    (*this) = result;
    return *this;
  }



  // Left raise of this matrix and another.
  template<typename T>
  Matrix<T> Matrix<T>::operator^(const Matrix<T>& rhs)
  {
    //	unsigned rows = rhs.get_rows();
    //	unsigned cols = rhs.get_cols();
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        for (unsigned k = 0; k<rows; k++)
        {
          result(i, j) += this->mat[i][k] ^ rhs(k, j);
        }
      }
    }

    return result;
  }


  // Cumulative left raise of this matrix and another.
  template<typename T>
  Matrix<T>& Matrix<T>::operator^=(const Matrix<T>& rhs)
  {
    Matrix result = (*this) % rhs;
    (*this) = result;
    return *this;
  }



  /*
  template<typename T>
  //Matrix<T> Matrix<T>::operator^(const Matrix<T>& rhs, const int power)
  Matrix<T> Matrix<T>::operator^(const int power)
  {
  std::cout << "Z" << std::endl;
  //unsigned rows = rhs.get_rows();
  //unsigned cols = rhs.get_cols();
  Matrix result(rows, cols, 0.0);
  //result = rhs;

  for (unsigned i = 0; i<rows; i++)
  {
  for (unsigned j = 0; j<cols; j++)
  {
  T temp = this->mat[i][j];
  std::cout << "T=" << std::endl;
  //T temp = 2;
  //T temp = rhs[i][j];

  //   not <= below \/ because first time counts as 2
  for (int k = 2; k<=power; k++)
  //result(i, j) += this->mat[i][j] * this->mat[i][j];
  result(i, j) = result(i, j) * temp;
  }
  }

  return result;
  }
  */


  // Left raise of this matrix and another.
  template<typename T>
  Matrix<T>& Matrix<T>::operator^=(const int power)
  {
    Matrix result = (*this);
    unsigned rows = result.get_rows();
    unsigned cols = result.get_cols();

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        T temp = this->mat[i][j];

        //   not <= below \/ because first time counts as 2
        for (int k = 2; k <= power; k++)
          result(i, j) = result(i, j) * temp;
      }
    }

    //(*this) = result;
    *this = result;
    return *this;
  }



  // Concerts all values to their absolute value within the matrix.
  template<typename T>
  Matrix<T> Matrix<T>::abs()
  {
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result(i, j) = std::math::abs(this->mat[j][i]);
      }
    }

    return result;
  }


  // Concerts all values to their square roots within the matrix.
  template<typename T>
  Matrix<T> Matrix<T>::sqrt()
  {
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result(i, j) = std::math::sqrt(this->mat[j][i]);
      }
    }

    return result;
  }


  // Calculate a transpose of this matrix.
  template<typename T>
  Matrix<T> Matrix<T>::transpose()
  {
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result(i, j) = this->mat[j][i];
      }
    }

    return result;
  }


  // Matrix/scalar addition.
  template<typename T>
  Matrix<T> Matrix<T>::operator+(const T& rhs)
  {
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result(i, j) = this->mat[i][j] + rhs;
      }
    }

    return result;
  }


  // Matrix/scalar subtraction.
  template<typename T>
  Matrix<T> Matrix<T>::operator-(const T& rhs)
  {
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result(i, j) = this->mat[i][j] - rhs;
      }
    }

    return result;
  }


  // Matrix/scalar multiplication.
  template<typename T>
  Matrix<T> Matrix<T>::operator*(const T& rhs)
  {
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result(i, j) = this->mat[i][j] * rhs;
      }
    }

    return result;
  }


  // Matrix/scalar division.
  template<typename T>
  Matrix<T> Matrix<T>::operator/(const T& rhs)
  {
    Matrix result(rows, cols, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result(i, j) = this->mat[i][j] / rhs;
      }
    }

    return result;
  }


  // Multiply a matrix with a vector.
  template<typename T>
  std::vector<T> Matrix<T>::operator*(const std::vector<T>& rhs)
  {
    std::vector<T> result(rhs.size(), 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        result[i] = this->mat[i][j] * rhs[j];
      }
    }

    return result;
  }


  // Obtain a vector of the diagonal elements.
  template<typename T>
  std::vector<T> Matrix<T>::diag_vec()
  {
    std::vector<T> result(rows, 0.0);

    for (unsigned i = 0; i<rows; i++)
    {
      result[i] = this->mat[i][i];
    }

    return result;
  }


  // Access the individual elements.
  template<typename T>
  T& Matrix<T>::operator()(const unsigned& row, const unsigned& col)
  {
    return this->mat[row][col];
  }


  // Access the individual elements (const).
  template<typename T>
  const T& Matrix<T>::operator()(const unsigned& row, const unsigned& col) const
  {
    return this->mat[row][col];
  }


  // Get the number of rows of the matrix.
  template<typename T>
  unsigned Matrix<T>::get_rows() const
  {
    return this->rows;
  }


  // Get the number of columns of the matrix.
  template<typename T>
  unsigned Matrix<T>::get_cols() const
  {
    return this->cols;
  }


  template<typename T>
  std::ostream & operator << (std::ostream &s, const Matrix<T>& m)
  {
    unsigned rows = m.get_rows();
    unsigned cols = m.get_cols();

    for (unsigned i = 0; i<rows; i++)
    {
      for (unsigned j = 0; j<cols; j++)
      {
        s << m(i, j);

        if ((i*j) < (((rows - 1)*(cols - 1)) - 1))
          s << ", ";
      }
      s << std::endl;
    }

    return s;
  }



  template<typename T>
  std::istream & operator >> (std::istream &s, Matrix<T>& m)
  {
    /*
    std::string temp(10000, ' ');

    s >> temp;
    v = Verylong(temp);
    */
    return s;
  }



} // end namespace SW