src/matrix.h

Sat, 14 Dec 2019 23:00:01 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Sat, 14 Dec 2019 23:00:01 +0200
changeset 20
cef43609a374
parent 17
a5111f4e6412
child 21
0133e565e072
permissions
-rw-r--r--

fixed build

#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];
	}
	T operator()(int row, int column) const
	{
		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};
}

template<int Rows, int Columns, typename T>
Matrix<Rows, Columns, T> matrixFromQGenericMatrix(const QGenericMatrix<Rows, Columns, T&> matrix)
{
	Matrix<Rows, Columns, T> result;
	for (auto& cell : result)
	{
		matrix(cell.index.row, cell.index.column) = result[cell.index];
	}
	return result;
}

using Matrix3x3 = Matrix<3, 3>;
Q_DECLARE_METATYPE(Matrix3x3);
using Matrix4x4 = Matrix<4, 4>;
Q_DECLARE_METATYPE(Matrix4x4);

template<int Rows, int Columns, typename T>
QDataStream& operator<<(QDataStream& stream, const Matrix<Rows, Columns, T>& 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)
{
	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}}};

mercurial