--- a/src/matrix.h Fri Nov 08 19:05:07 2019 +0200 +++ b/src/matrix.h Fri Dec 13 15:55:56 2019 +0200 @@ -1,10 +1,30 @@ #pragma once #include <QGenericMatrix> +#include <type_traits> + +template<int Rows, int Columns, typename T = double> +struct MatrixIterator; + +template<int Rows, int Columns> +struct MatrixIndex +{ + int row; + int column; +}; template<int Rows, int Columns, typename T = double> struct Matrix { + using Iterator = MatrixIterator<Rows, Columns, T>; T values[Rows][Columns]; + Iterator begin() + { + return {*this, {0, 0}}; + } + Iterator end() + { + return {*this, {Rows, 0}}; + } T& operator()(int row, int column) { return this->values[row][column]; @@ -13,9 +33,78 @@ { return this->values[row][column]; } + T& operator[](const MatrixIndex<Rows, Columns>& index) + { + return (*this)(index.row, index.column); + } + T operator[](const MatrixIndex<Rows, Columns>& index) const + { + return (*this)(index.row, index.column); + } }; template<int Rows, int Columns, typename T> +struct MatrixIterator +{ + struct Value + { + const MatrixIndex<Rows, Columns> index; + decltype(std::declval<Matrix<Rows, Columns, T>>()(0, 0)) value; + }; + Matrix<Rows, Columns, T>& matrix; + MatrixIndex<Rows, Columns> index; +}; + +template<int Rows, int Columns> +auto& operator++(MatrixIndex<Rows, Columns>& index) +{ + index.column += 1; + if (index.column >= Columns) + { + index.row += 1; + index.column -= Columns; + } + return index; +} + +template<int Rows, int Columns> +bool operator==( + const MatrixIndex<Rows, Columns>& one, + const MatrixIndex<Rows, Columns>& other) +{ + return one.row == other.row and one.column == other.column; +} +template<int Rows, int Columns, typename T> +auto& operator++(MatrixIterator<Rows, Columns, T>& iterator) +{ + ++iterator.index; + return iterator; +} + +template<int Rows, int Columns, typename T> +bool operator==( + const MatrixIterator<Rows, Columns, T>& one, + const MatrixIterator<Rows, Columns, T>& other) +{ + return &one.matrix == &other.matrix and one.index == other.index; +} + +template<int Rows, int Columns, typename T> +bool operator!=( + const MatrixIterator<Rows, Columns, T>& one, + const MatrixIterator<Rows, Columns, T>& other) +{ + return not (one == other); +} + +template<int Rows, int Columns, typename T> +auto operator*(MatrixIterator<Rows, Columns, T>& iterator) + -> typename MatrixIterator<Rows, Columns, T>::Value +{ + return {iterator.index, iterator.matrix[iterator.index]}; +} + +template<int Rows, int Columns, typename T> QGenericMatrix<Rows, Columns, T> matrixToQGenericMatrix(const Matrix<Rows, Columns, T>& matrix) { return {matrix.values}; @@ -25,12 +114,9 @@ Matrix<Rows, Columns, T> matrixFromQGenericMatrix(const QGenericMatrix<Rows, Columns, T&> matrix) { Matrix<Rows, Columns, T> result; - for (int row = 0; row < Rows; row += 1) + for (auto& cell : result) { - for (int column = 0; column < Columns; column += 1) - { - result(row, column) = matrix(row, column); - } + matrix(cell.index.row, cell.index.column) = result[cell.index]; } return result; } @@ -43,14 +129,22 @@ template<int Rows, int Columns, typename T> QDataStream& operator<<(QDataStream& stream, const Matrix<Rows, Columns, T>& matrix) { - return stream << matrixToQGenericMatrix(matrix); + for (auto& cell : matrix) + { + stream << cell.value; + } + return stream; } template<int Rows, int Columns, typename T> QDataStream& operator>>(QDataStream& stream, Matrix<Rows, Columns, T>& matrix) { - QGenericMatrix<Rows, Columns, T> qmatrix; - stream >> qmatrix; - matrix = matrixFromQGenericMatrix(matrix); + for (auto& cell : matrix) + { + stream >> cell.value; + } return stream; } + +static constexpr Matrix3x3 identity3x3 {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}}; +static constexpr Matrix4x4 identity4x4 {{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}};