
#ifndef COMPARISON_BENCHMARKS_BASE_MATRIX_H
#define COMPARISON_BENCHMARKS_BASE_MATRIX_H

#include <algorithm>
#include <iostream>

namespace comparison_benchmarks {
namespace base {
namespace matrix {

const int MATRIX_SIZE = 128;

const int NUM_ITERATIONS = 5000;
const int WARMUP_ITERATIONS = 1000;

template<typename T, int SIZE>
class matrix {
 public:
  T data[SIZE][SIZE];

  explicit matrix() {
    for (int i = 0; i < MATRIX_SIZE; i++) {
      for (int j = 0; j < MATRIX_SIZE; j++) {
        data[i][j] = i;
      }
    }
  }

  virtual void multiply(const matrix<T, SIZE> &a, const matrix<T, SIZE> &b) {
    for (int i = 0; i < SIZE; i++) {
      multiply_column(i, a, b);
    }
  }

 protected:
  void multiply_column(int i, const matrix<T, SIZE> &a, const matrix<T, SIZE> &b) {
    for (int j = 0; j < SIZE; ++j) {
      data[i][j] = 0;
    }
    for (int k = 0; k < SIZE; ++k) {
      for (int j = 0; j < SIZE; ++j) {
        data[i][j] += a.data[i][k] * b.data[k][j];
      }
    }
  }
};

template<typename T, int SIZE>
std::ostream &operator<<(std::ostream &strm, const matrix<T, SIZE> &matrix) {
  for (int i = 0; i < SIZE; i++) {
    for (int j = 0; j < SIZE; j++) {
      strm << matrix.data[i][j] << "\t";
    }
    strm << std::endl;
  }

  return strm;
}

}
}
}

#endif //COMPARISON_BENCHMARKS_BASE_MATRIX_H
