#include <lemon/time_measure.h>
#include <vector>

template<class T>
class Matrix 
{
public:
  int m,n;
  std::vector<T> values;
  
  Matrix(int _m, int _n) : m(_m), n(_n), values(n*m) {}
  typename std::vector<T>::reference operator()(int i, int j)
  { return values[i*n+j];}

  class Row 
  {
  public:
    Matrix<T> &mat;
    int row;
    
    Row(Matrix<T> &_mat,int _row) : mat(_mat), row(_row) {}
    typename std::vector<T>::reference operator()(int j)
    { return mat.values[row*mat.n+j];}
  };
  class Column 
  {
  public:
    Matrix<T> &mat;
    int col;
    
    Column(Matrix<T> &_mat,int _col) : mat(_mat), col(_col) {}
    typename std::vector<T>::reference operator[](int i)
    { return mat.values[i*mat.n+col];}
  };
  
  Row operator[](int i) { return Row(*this,i); }
  Column operator()(int j) { return Column(*this,j); }
};

main() 
{
  const int COUNT=1000000;
  const int SIZE=100;
  
  Matrix<int> A(SIZE,SIZE);
  
  for(int i=0;i<SIZE;i++) for(int j=0;j<SIZE;j++) A(i,j)=i+j;

  int s=0;
  lemon::Timer T;
  for(int c=0;c<COUNT;c++) {
    for(int i=0;i<SIZE;i++) for(int j=0;j<SIZE;j++) s+=A[i](j);
  }
  std::cout << "A[i](j): " << T << ' ' << s <<'\n';
  s=0;
  T.reset();
  for(int c=0;c<COUNT;c++) {
    for(int i=0;i<SIZE;i++) for(int j=0;j<SIZE;j++) s+=A(i,j);
  }
  std::cout << "A(i,j): " << T << ' ' << s << '\n';
  s=0;
  T.reset();
  for(int c=0;c<COUNT;c++) {
    for(int i=0;i<SIZE;i++) for(int j=0;j<SIZE;j++) s+=A(j)[i];
  }
  std::cout << "A(j)[i]: " << T << ' ' << s << '\n';
  s=0;
  T.reset();
  for(int c=0;c<COUNT;c++) {
    for(int i=0;i<SIZE;i++) for(int j=0;j<SIZE;j++) s+=A(i,j);
  }
  std::cout << "A(j,i): " << T << ' ' << s << "\n\n";

  return 0;
}
