matrix.h

#ifndef __SW_MATRIX_H__
#define __SW_MATRIX_H__

/*
#include <iostream>
//#include <iomanip>
#include <vector>
*/

// uncomment to disable assert()
// #define NDEBUG
#include <cassert>


namespace SW {



template <typename T> class Matrix
{
private:
  std::vector<std::vector<T> > data;
  mutable unsigned rows;
  mutable unsigned cols;

public:
  Matrix();
  Matrix(unsigned _rows, unsigned _cols);
  Matrix(unsigned _rows, unsigned _cols, const T& _initial);

  //Matrix(T&&... elements);

  /*
  template<typename ...E>
  //Matrix(T element, E&&... elements);
  Matrix(E&&... elements);
  //Matrix(unsigned _rows, unsigned _cols, T element, E&&... elements);
    */

  /**
  * Constructs a Matrix whose elements are initialized with the provided values
  *
  * @param element the first value
  *
  * @param elements all subsequent values
  *
  * <pre>Matrix<int, 3, 3> matrix(1, 2, 3, 1, 2, 3, 1, 2 ,3);</pre>
  *
  */
  //template<typename ...E>
  //Matrix(unsigned _rows, unsigned _cols, T element, E&&... elements);



  Matrix(const Matrix<T>& rhs);
  virtual ~Matrix();
  //~Matrix();

  /*
  template<typename T, std::size_t X, std::size_t Y>
  bool operator==(const Matrix<T, X, Y>& lhs, const Matrix<T, X, Y>& rhs) noexcept;

  template<typename T, std::size_t X, std::size_t Y>
  bool operator!=(const Matrix<T, X, Y>& lhs, const Matrix<T, X, Y>& rhs) noexcept;

  template<typename T, std::size_t X, std::size_t Y>
  std::ostream& operator<<(std::ostream& stream, const Matrix<T, X, Y>& matrix);

  template<typename T, std::size_t X, std::size_t Y>
  std::istream& operator>>(std::istream& stream, Matrix<T, X, Y>& matrix);
  */

  /// Privileged free-functions
 /*
  friend std::ostream& operator<<<>(std::ostream&, const Matrix<T, Rows, Columns>&);
  friend std::istream& operator>><>(std::istream&, const Matrix<T, Rows, Columns>&);
  friend bool operator!=<>(const Matrix<T>& lhs, const Matrix<T>&);
  friend bool operator==<>(const Matrix<T>& lhs, const Matrix<T>& rhs);
  */

  //Matrix<T>& operator==<>(const Matrix<T>& lhs, const Matrix<T>& rhs);
  //bool operator==(const Matrix<T>& lhs, const Matrix<T>& rhs);

  //Matrix<T>& operator==(Matrix<T>& rhs);
  //bool operator==(Matrix<T>& rhs);

  // Operator overloading, for "standard" mathematical matrix operations.
  Matrix<T>& operator=(const Matrix<T>& rhs);

  // Operator overloading, for comparitive operations.
  bool operator==(const Matrix<T>& rhs) const;
  bool operator!=(const Matrix<T>& rhs) const;
  bool operator<(const Matrix<T>& rhs) const;
  bool operator<=(const Matrix<T>& rhs) const;
  bool operator>(const Matrix<T>& rhs) const;
  bool operator>=(const Matrix<T>& rhs) const;

  // Arithmetic operators.
  Matrix<T> operator - () const;     // negate  operator
  Matrix<T> operator ++ ();          // prefix  increment operator
  Matrix<T> operator ++ (int);       // postfix increment operator
  Matrix<T> operator -- ();          // prefix  decrement operator
  Matrix<T> operator -- (int);       // postfix decrement operator

  // Matrix mathematical operations.
  Matrix<T> operator+(const Matrix<T>& rhs);
  Matrix<T>& operator+=(const Matrix<T>& rhs);
  Matrix<T> operator-(const Matrix<T>& rhs);
  Matrix<T>& operator-=(const Matrix<T>& rhs);
  Matrix<T> operator*(const Matrix<T>& rhs);
  Matrix<T>& operator*=(const Matrix<T>& rhs);

  Matrix<T> operator%(const Matrix<T>& rhs);
  Matrix<T>& operator%=(const Matrix<T>& rhs);
  Matrix<T> operator^(const Matrix<T>& rhs);
  Matrix<T>& operator^=(const Matrix<T>& rhs);

  //Matrix operator ^ (const Matrix<T>& rhs, const int power);
  //Matrix<T> operator^(const int power);
  Matrix<T>& operator^=(const int power);

  Matrix<T> abs();
  void print();
  Matrix<T> sqrt();
  //sequence_generator
  Matrix<T> transpose();

  // Matrix/scalar operations.
  Matrix<T> operator+(const T& rhs);
  Matrix<T> operator-(const T& rhs);
  Matrix<T> operator*(const T& rhs);
  Matrix<T> operator/(const T& rhs);

  // Matrix/vector operations.
  std::vector<T> operator*(const std::vector<T>& rhs);
  std::vector<T> diag_vec();

  // Access the individual elements.
  T& operator()(const unsigned& row, const unsigned& col);
  const T& operator()(const unsigned& row, const unsigned& col) const;

  // Access the row and column sizes.
  unsigned get_rows() const;
  unsigned get_cols() const;

  // vector operations
  Matrix<T> get_row(unsigned r) const;
  Matrix<T> get_col(unsigned c) const;
  Matrix<T>& set_col(unsigned c, const Matrix<T>& C);
  Matrix<T>& set_row(unsigned r, const Matrix<T>& R);
  Matrix<T> delete_row(unsigned r) const;
  Matrix<T> delete_col(unsigned c) const;

  bool swap_rows(unsigned i, unsigned j);

  /**/
  // I/O stream functions.
  template<typename T>
  friend std::ostream & operator<<(std::ostream &, const Matrix<T>&);

  template<typename T>
  friend std::istream& operator>>(std::istream&, const Matrix<T>&);

};

/*
template<class T>
ostream& operator<<(ostream& o, const Matrix<T>& M)
{
  o << endl;
  for (int i = 0; i<M.rows; i++) {
    o << "[ ";
    for (int j = 0; j<M.cols; j++)
      o << M(i, j) << " ";
    o << "]" << endl;
  }
  o << endl;
  return o;
}
*/

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


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

  rows = _rows;
  cols = _cols;
}


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

  rows = _rows;
  cols = _cols;
}


//template<typename T, unsigned _rows, unsigned cols>
//template<typename ...E>
//Matrix<T, Rows, Columns>::Matrix(T first, E&&... elements) noexcept : values{ { first, std::forward<T>(static_cast<T>(elements))... } }

/*
template<typename T>
template<typename ...E>
//Matrix<T>::Matrix(T first, E&&... elements) noexcept : values{ { first, std::forward<T>(static_cast<T>(elements))... } }
//Matrix<T>::Matrix(T first, E&&... elements) : data{ { first, std::forward<T>(static_cast<T>(elements))... } } 
Matrix<T>::Matrix(E&&... elements) : data{ { std::forward<T>(static_cast<T>(elements))... } }
{
  data.push_back()
}
*/




/*
template<typename T>
template<typename ...E>
//Matrix<T>::Matrix(unsigned _rows, unsigned _cols, T first, E&&... elements) : mat{ { first, std::forward<T>(static_cast<T>(elements))... } }
//Matrix<T>::Matrix(unsigned _rows, unsigned _cols, T first, E&&... elements) : mat{ { first, std::forward<T>(static_cast<T>(elements))... } }
Matrix<T>::Matrix(unsigned _rows, unsigned _cols, T first, E&&... elements) : mat{ { first, std::forward<T>(static_cast<T>(elements))... } }
{
  data.resize(_rows);
  for (unsigned i = 0; i<data.size(); i++)
  {
    data[i].resize(_cols, 0);
  }

  rows = _rows;
  cols = _cols;
}
*/
/*
Matrix<T>::Matrix(T&&... elements)
{
  std::forward<T>(static_cast<T>(elements))...;
}
*/

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


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


// 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();

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

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

  rows = new_rows;
  cols = new_cols;

  return *this;
}



// 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->data[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->data[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->data[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->data[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->data[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->data[i][j] < rhs(i, j))
        return false;
    }
  }

  return true;
}






// 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->data[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->data[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->data[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->data[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->data[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->data[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->data[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->data[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->data[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->data[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->data[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->data[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->data[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->data[i][j] * this->data[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->data[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;
}


//*********************************************************************************************


// Converts 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->data[i][j]);
    }
  }

  return result;
}



template<typename T>
void Matrix<T>::print()
{
  for (unsigned int i = 0; i < rows; i++)
  {
    for (unsigned int j = 0; j<cols; j++)
    {
      std::cout << data[i][j] << ", ";
    }
    std::cout << std::endl;
  }

  std::cout << std::endl;
}


// 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->data[j][i]);
    }
  }

  return result;
}


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

  for (unsigned i = 0; i<rows; i++)
  {
    for (unsigned j = 0; j<cols; j++)
    {
      result(i, j) = this->data[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->data[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->data[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->data[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->data[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->data[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->data[i][i];
  }

  return result;
}


// Access the individual elements.
template<typename T>
T& Matrix<T>::operator()(const unsigned& row, const unsigned& col)
{
  assert(row >= 0);
  assert(col >= 0);
  assert(row < rows);
  assert(col < cols);

  return this->data[row][col];
}


// Access the individual elements (const).
template<typename T>
const T& Matrix<T>::operator()(const unsigned& row, const unsigned& col) const
{
  assert(row >= 0);
  assert(col >= 0);
  assert(row < rows);
  assert(col < cols);

  return this->data[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;
}




// Returns a row.
template<typename T>
Matrix<T> Matrix<T>::get_row(unsigned r) const
{
  Matrix<T> result(1, cols, 0.0);

  for (unsigned i = 0; i<cols; i++)
  {
    result[i] = this->data[r][i];
  }

  return result;
}


template<typename T>
Matrix<T> Matrix<T>::get_col(unsigned c) const
{
  Matrix<T> result(rows, 1, 0.0);

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

  return result;
}


template<typename T>
Matrix<T>& Matrix<T>::set_col(unsigned c, const Matrix<T>& C)
{

}


template<typename T>
Matrix<T>& Matrix<T>::set_row(unsigned r, const Matrix<T>& R)
{

}

template<typename T>
Matrix<T> Matrix<T>::delete_row(unsigned r) const
{

}


template<typename T>
Matrix<T> Matrix<T>::delete_col(unsigned c) const
{

}


// swap_rows() uses a row's worth of memory for better run-time performance
// if you want pairwise swap, just write it yourself
template<typename T>
bool Matrix<T>::swap_rows(unsigned i, unsigned j)
{
  if (i == j) return;
  /*
  Matrix<T,1> temp = (*this)[i];
  (*this)[i] = (*this)[j];
  (*this)[j] = temp;
  */
  unsigned max = (*this)[i].size();
  for (unsigned ii = 0; ii<max; ++ii) 
    std::swap((*this)(i, ii), (*this)(j, ii));

  return true;
}


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.

#endif