#pragma once

#include <valarray>

template<class T> class matrix {
  private:
    std::valarray<T> v;
    std::size_t m, n;

  public:
    matrix(std::valarray<T>&&, std::size_t, std::size_t);
    matrix(std::size_t m_ = 0, std::size_t n_ = 0, T val_ = T());

    size_t rows() const; size_t columns() const;

    class matrix_slice : public std::slice {
      friend class matrix;
      private:
        std::valarray<T>& v;

        matrix_slice(std::valarray<T>& v_, std::size_t start, std::size_t size, std::size_t stride);

      public:
        T& operator[](std::size_t i);
        T operator[](std::size_t i) const;
        operator std::valarray<T>() const;
    };

    matrix_slice operator[](std::size_t i);
    matrix_slice row(std::size_t i);
    matrix_slice column(std::size_t j);

    operator std::valarray<T>() const;

    T* begin();
    T* end();
};
