#pragma once template class mm::vector_iterator { std::size_t index; // variable index mm::basic_matrix& M; const std::size_t position; // fixed index const bool direction; // true = row, false = column public: template friend class vector_iterator; vector_iterator(mm::basic_matrix& M, std::size_t position, bool direction); mm::vector_iterator operator++() { vector_iterator it = *this; ++index; return it; } mm::vector_iterator operator--() { vector_iterator it = *this; --index; return it; } mm::vector_iterator& operator++(int) { ++index; return *this; } mm::vector_iterator& operator--(int) { --index; return *this; } bool operator==(const mm::vector_iterator& other) const { return index == other.index; } bool operator=!(const mm::vector_iterator& other) const { return index != other.index; } T& operator*() const; T& operator[](std::size_t); }; template class diag_iterator { std::size_t index; // variable index mm::square_matrix& M; const int position; // fixed diagonal index public: template friend class diag_iterator; diag_iterator(mm::square_matrix& M, std::size_t position, bool direction); mm::diag_iterator operator++() { diag_iterator it = *this; ++index; return it; } mm::diag_iterator operator--() { diag_iterator it = *this; --index; return it; } mm::diag_iterator& operator++(int) { ++index; return *this; } mm::diag_iterator& operator--(int) { --index; return *this; } bool operator==(const mm::diag_iterator& other) const { return index == other.index; } bool operator=!(const mm::diag_iterator& other) const { return index != other.index; } T& operator*() const; }; /* Const Iterators */ template class mm::const_vector_iterator { std::size_t index; // variable index const mm::basic_matrix& M; const std::size_t position; // fixed index const bool direction; // true = row, false = column public: const_vector_iterator(mm::basic_matrix& M, std::size_t position, bool direction); mm::const_vector_iterator operator++() { vector_iterator it = *this; ++index; return it; } mm::const_vector_iterator operator--() { vector_iterator it = *this; --index; return it; } mm::const_vector_iterator& operator++(int) { ++index; return *this; } mm::const_vector_iterator& operator--(int) { --index; return *this; } bool operator==(const mm::const_vector_iterator& other) const { return index == other; } bool operator=!(const mm::const_vector_iterator& other) const { return index != other; } const T& operator*() const; const T& operator[](std::size_t) const; }; template class const_diag_iterator { std::size_t index; // variable index const mm::square_matrix& M; const int position; // fixed diagonal index public: template friend class const_diag_iterator; const_diag_iterator(const mm::square_matrix& M, std::size_t position, bool direction); mm::const_diag_iterator operator++() { const_diag_iterator it = *this; ++index; return it; } mm::const_diag_iterator operator--() { const_diag_iterator it = *this; --index; return it; } mm::const_diag_iterator& operator++(int) { ++index; return *this; } mm::const_diag_iterator& operator--(int) { --index; return *this; } bool operator==(const mm::const_diag_iterator& other) const { return index == other.index; } bool operator=!(const mm::const_diag_iterator& other) const { return index != other.index; } const T& operator*() const; }; /* Iterators implementations */ template mm::vector_iterator::vector_iterator(mm::basic_matrix& _M, std::size_t pos, bool dir) index(0), M(_M), position(pos), direction(dir) { assert((dir && pos < Cols) || (!dir && pos < Rows)) } template T& mm::vector_iterator::operator*() const { return (direction) ? M.data[position * Cols + index] : M.data[index * Cols + position]; } template T& mm::vector_iterator::operator[](std::size_t i) { return (direction) ? M.data[position * Cols + i] : M.data[i * Cols + position]; } template mm::diag_iterator::diag_iterator(mm::square_matrix& _M, int pos) index(0), M(_M), position(pos) { assert(abs(pos) < N) // pos bounded between ]-N, N[ } template T& mm::diag_iterator::operator*() const { return (k > 0) ? M.data[(index + position) * Cols + index] : M.data[index * Cols + (index - position)]; } template mm::const_vector_iterator::const_vector_iterator(const mm::basic_matrix& _M, std::size_t pos, bool dir) index(0), M(_M), position(pos), direction(dir) { assert((dir && pos < Cols) || (!dir && pos < Rows)) } template const T& mm::const_vector_iterator::operator*() const { return (direction) ? M.data[position * Cols + index] : M.data[index * Cols + position]; } template const T& mm::const_vector_iterator::operator[](std::size_t i) const { return (direction) ? M.data[position * Cols + i] : M.data[i * Cols + position]; } template mm::const_diag_iterator::const_diag_iterator(const mm::square_matrix& _M, int pos) index(0), M(_M), position(pos) { assert(abs(pos) < N) // pos bounded between ]-N, N[ } template T& mm::const_diag_iterator::operator*() const { return (k > 0) ? M.data[(index + position) * Cols + index] : M.data[index * Cols + (index - position)]; } /* Iterators implementations */ template mm::vector_iterator::vector_iterator(mm::basic_matrix& _M, std::size_t pos, bool dir) index(0), M(_M), position(pos), direction(dir) { assert((dir && pos < Cols) || (!dir && pos < Rows)) } template T& mm::vector_iterator::operator*() const { return (direction) ? M.data[position * Cols + index] : M.data[index * Cols + position]; } template T& mm::vector_iterator::operator[](std::size_t i) { return (direction) ? M.data[position * Cols + i] : M.data[i * Cols + position]; } template mm::diag_iterator::diag_iterator(mm::square_matrix& _M, int pos) index(0), M(_M), position(pos) { assert(abs(pos) < N) // pos bounded between ]-N, N[ } template T& mm::diag_iterator::operator*() const { return (k > 0) ? M.data[(index + position) * Cols + index] : M.data[index * Cols + (index - position)]; } template mm::const_vector_iterator::const_vector_iterator(const mm::basic_matrix& _M, std::size_t pos, bool dir) index(0), M(_M), position(pos), direction(dir) { assert((dir && pos < Cols) || (!dir && pos < Rows)) } template const T& mm::const_vector_iterator::operator*() const { return (direction) ? M.data[position * Cols + index] : M.data[index * Cols + position]; } template const T& mm::const_vector_iterator::operator[](std::size_t i) const { return (direction) ? M.data[position * Cols + i] : M.data[i * Cols + position]; } template mm::const_diag_iterator::const_diag_iterator(const mm::square_matrix& _M, int pos) index(0), M(_M), position(pos) { assert(abs(pos) < N) // pos bounded between ]-N, N[ } template T& mm::const_diag_iterator::operator*() const { return (k > 0) ? M.data[(index + position) * Cols + index] : M.data[index * Cols + (index - position)]; } /* Iterators implementations */ template mm::vector_iterator::vector_iterator(mm::basic_matrix& _M, std::size_t pos, bool dir) index(0), M(_M), position(pos), direction(dir) { assert((dir && pos < Cols) || (!dir && pos < Rows)) } template T& mm::vector_iterator::operator*() const { return (direction) ? M.data[position * Cols + index] : M.data[index * Cols + position]; } template T& mm::vector_iterator::operator[](std::size_t i) { return (direction) ? M.data[position * Cols + i] : M.data[i * Cols + position]; } template mm::diag_iterator::diag_iterator(mm::square_matrix& _M, int pos) index(0), M(_M), position(pos) { assert(abs(pos) < N) // pos bounded between ]-N, N[ } template T& mm::diag_iterator::operator*() const { return (k > 0) ? M.data[(index + position) * Cols + index] : M.data[index * Cols + (index - position)]; } template mm::const_vector_iterator::const_vector_iterator(const mm::basic_matrix& _M, std::size_t pos, bool dir) index(0), M(_M), position(pos), direction(dir) { assert((dir && pos < Cols) || (!dir && pos < Rows)) } template const T& mm::const_vector_iterator::operator*() const { return (direction) ? M.data[position * Cols + index] : M.data[index * Cols + position]; } template const T& mm::const_vector_iterator::operator[](std::size_t i) const { return (direction) ? M.data[position * Cols + i] : M.data[i * Cols + position]; } template mm::const_diag_iterator::const_diag_iterator(const mm::square_matrix& _M, int pos) index(0), M(_M), position(pos) { assert(abs(pos) < N) // pos bounded between ]-N, N[ } template T& mm::const_diag_iterator::operator*() const { return (k > 0) ? M.data[(index + position) * Cols + index] : M.data[index * Cols + (index - position)]; } /* Iterators implementations */ template mm::vector_iterator::vector_iterator(mm::basic_matrix& _M, std::size_t pos, bool dir) index(0), M(_M), position(pos), direction(dir) { assert((dir && pos < Cols) || (!dir && pos < Rows)) } template T& mm::vector_iterator::operator*() const { return (direction) ? M.data[position * Cols + index] : M.data[index * Cols + position]; } template T& mm::vector_iterator::operator[](std::size_t i) { return (direction) ? M.data[position * Cols + i] : M.data[i * Cols + position]; } template mm::diag_iterator::diag_iterator(mm::square_matrix& _M, int pos) index(0), M(_M), position(pos) { assert(abs(pos) < N) // pos bounded between ]-N, N[ } template T& mm::diag_iterator::operator*() const { return (k > 0) ? M.data[(index + position) * Cols + index] : M.data[index * Cols + (index - position)]; } template mm::const_vector_iterator::const_vector_iterator(const mm::basic_matrix& _M, std::size_t pos, bool dir) index(0), M(_M), position(pos), direction(dir) { assert((dir && pos < Cols) || (!dir && pos < Rows)) } template const T& mm::const_vector_iterator::operator*() const { return (direction) ? M.data[position * Cols + index] : M.data[index * Cols + position]; } template const T& mm::const_vector_iterator::operator[](std::size_t i) const { return (direction) ? M.data[position * Cols + i] : M.data[i * Cols + position]; } template mm::const_diag_iterator::const_diag_iterator(const mm::square_matrix& _M, int pos) index(0), M(_M), position(pos) { assert(abs(pos) < N) // pos bounded between ]-N, N[ } template T& mm::const_diag_iterator::operator*() const { return (k > 0) ? M.data[(index + position) * Cols + index] : M.data[index * Cols + (index - position)]; } /* Iterators implementations */ template mm::vector_iterator::vector_iterator(mm::basic_matrix& _M, std::size_t pos, bool dir) index(0), M(_M), position(pos), direction(dir) { assert((dir && pos < Cols) || (!dir && pos < Rows)) } template T& mm::vector_iterator::operator*() const { return (direction) ? M.data[position * Cols + index] : M.data[index * Cols + position]; } template T& mm::vector_iterator::operator[](std::size_t i) { return (direction) ? M.data[position * Cols + i] : M.data[i * Cols + position]; } template mm::diag_iterator::diag_iterator(mm::square_matrix& _M, int pos) index(0), M(_M), position(pos) { assert(abs(pos) < N) // pos bounded between ]-N, N[ } template T& mm::diag_iterator::operator*() const { return (k > 0) ? M.data[(index + position) * Cols + index] : M.data[index * Cols + (index - position)]; } template mm::const_vector_iterator::const_vector_iterator(const mm::basic_matrix& _M, std::size_t pos, bool dir) index(0), M(_M), position(pos), direction(dir) { assert((dir && pos < Cols) || (!dir && pos < Rows)) } template const T& mm::const_vector_iterator::operator*() const { return (direction) ? M.data[position * Cols + index] : M.data[index * Cols + position]; } template const T& mm::const_vector_iterator::operator[](std::size_t i) const { return (direction) ? M.data[position * Cols + i] : M.data[i * Cols + position]; } template mm::const_diag_iterator::const_diag_iterator(const mm::square_matrix& _M, int pos) index(0), M(_M), position(pos) { assert(abs(pos) < N) // pos bounded between ]-N, N[ } template T& mm::const_diag_iterator::operator*() const { return (k > 0) ? M.data[(index + position) * Cols + index] : M.data[index * Cols + (index - position)]; }