Skip to content

Commit

Permalink
matrix: Slice templated on const and non-const matrix cases
Browse files Browse the repository at this point in the history
to avoid casting const to non-const with
`const_cast<Matrix<Type, M, N>*>(data)`
  • Loading branch information
MaEtUgR authored and dagar committed Jan 30, 2024
1 parent 88102d8 commit 3e183fe
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 68 deletions.
18 changes: 15 additions & 3 deletions src/lib/matrix/matrix/Matrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ class Matrix
}
}

template<size_t P, size_t Q>
Matrix(const ConstSlice<Type, M, N, P, Q> &in_slice)
{
Matrix<Type, M, N> &self = *this;

for (size_t i = 0; i < M; i++) {
for (size_t j = 0; j < N; j++) {
self(i, j) = in_slice(i, j);
}
}
}

/**
* Accessors/ Assignment etc.
*/
Expand Down Expand Up @@ -438,7 +450,7 @@ class Matrix
}

template<size_t P, size_t Q>
const Slice<Type, P, Q, M, N> slice(size_t x0, size_t y0) const
ConstSlice<Type, P, Q, M, N> slice(size_t x0, size_t y0) const
{
return {x0, y0, this};
}
Expand All @@ -449,7 +461,7 @@ class Matrix
return {x0, y0, this};
}

const Slice<Type, 1, N, M, N> row(size_t i) const
ConstSlice<Type, 1, N, M, N> row(size_t i) const
{
return slice<1, N>(i, 0);
}
Expand All @@ -459,7 +471,7 @@ class Matrix
return slice<1, N>(i, 0);
}

const Slice<Type, M, 1, M, N> col(size_t j) const
ConstSlice<Type, M, 1, M, N> col(size_t j) const
{
return slice<M, 1>(0, j);
}
Expand Down
103 changes: 62 additions & 41 deletions src/lib/matrix/matrix/Slice.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,24 @@ class Matrix;
template<typename Type, size_t M>
class Vector;

template <typename Type, size_t P, size_t Q, size_t M, size_t N>
class Slice
template <typename MatrixT, typename Type, size_t P, size_t Q, size_t M, size_t N>
class SliceT
{
public:
Slice(size_t x0, size_t y0, const Matrix<Type, M, N> *data) :
using Self = SliceT<MatrixT, Type, P, Q, M, N>;

SliceT(size_t x0, size_t y0, MatrixT *data) :
_x0(x0),
_y0(y0),
_data(const_cast<Matrix<Type, M, N>*>(data))
_data(data)
{
static_assert(P <= M, "Slice rows bigger than backing matrix");
static_assert(Q <= N, "Slice cols bigger than backing matrix");
assert(x0 + P <= M);
assert(y0 + Q <= N);
}

Slice(const Slice<Type, P, Q, M, N> &other) = default;
SliceT(const Self &other) = default;

const Type &operator()(size_t i, size_t j) const
{
Expand All @@ -47,7 +49,6 @@ class Slice
}

Type &operator()(size_t i, size_t j)

{
assert(i < P);
assert(j < Q);
Expand All @@ -56,15 +57,15 @@ class Slice
}

// Separate function needed otherwise the default copy constructor matches before the deep copy implementation
Slice<Type, P, Q, M, N> &operator=(const Slice<Type, P, Q, M, N> &other)
Self &operator=(const Self &other)
{
return this->operator=<M, N>(other);
}

template<size_t MM, size_t NN>
Slice<Type, P, Q, M, N> &operator=(const Slice<Type, P, Q, MM, NN> &other)
Self &operator=(const SliceT<Matrix<Type, MM, NN>, Type, P, Q, MM, NN> &other)
{
Slice<Type, P, Q, M, N> &self = *this;
Self &self = *this;

for (size_t i = 0; i < P; i++) {
for (size_t j = 0; j < Q; j++) {
Expand All @@ -75,9 +76,10 @@ class Slice
return self;
}

Slice<Type, P, Q, M, N> &operator=(const Matrix<Type, P, Q> &other)
template<size_t MM, size_t NN>
SliceT<MatrixT, Type, P, Q, M, N> &operator=(const SliceT<const Matrix<Type, MM, NN>, Type, P, Q, MM, NN> &other)
{
Slice<Type, P, Q, M, N> &self = *this;
SliceT<MatrixT, Type, P, Q, M, N> &self = *this;

for (size_t i = 0; i < P; i++) {
for (size_t j = 0; j < Q; j++) {
Expand All @@ -88,9 +90,22 @@ class Slice
return self;
}

Slice<Type, P, Q, M, N> &operator=(const Type &other)
SliceT<MatrixT, Type, P, Q, M, N> &operator=(const Matrix<Type, P, Q> &other)
{
Slice<Type, P, Q, M, N> &self = *this;
SliceT<MatrixT, Type, P, Q, M, N> &self = *this;

for (size_t i = 0; i < P; i++) {
for (size_t j = 0; j < Q; j++) {
self(i, j) = other(i, j);
}
}

return self;
}

SliceT<MatrixT, Type, P, Q, M, N> &operator=(const Type &other)
{
SliceT<MatrixT, Type, P, Q, M, N> &self = *this;

for (size_t i = 0; i < P; i++) {
for (size_t j = 0; j < Q; j++) {
Expand All @@ -103,9 +118,9 @@ class Slice

// allow assigning vectors to a slice that are in the axis
template <size_t DUMMY = 1> // make this a template function since it only exists for some instantiations
Slice<Type, 1, Q, M, N> &operator=(const Vector<Type, Q> &other)
SliceT<MatrixT, Type, 1, Q, M, N> &operator=(const Vector<Type, Q> &other)
{
Slice<Type, 1, Q, M, N> &self = *this;
SliceT<MatrixT, Type, 1, Q, M, N> &self = *this;

for (size_t j = 0; j < Q; j++) {
self(0, j) = other(j);
Expand All @@ -115,9 +130,9 @@ class Slice
}

template<size_t MM, size_t NN>
Slice<Type, P, Q, M, N> &operator+=(const Slice<Type, P, Q, MM, NN> &other)
SliceT<MatrixT, Type, P, Q, M, N> &operator+=(const SliceT<MatrixT, Type, P, Q, MM, NN> &other)
{
Slice<Type, P, Q, M, N> &self = *this;
SliceT<MatrixT, Type, P, Q, M, N> &self = *this;

for (size_t i = 0; i < P; i++) {
for (size_t j = 0; j < Q; j++) {
Expand All @@ -128,9 +143,9 @@ class Slice
return self;
}

Slice<Type, P, Q, M, N> &operator+=(const Matrix<Type, P, Q> &other)
SliceT<MatrixT, Type, P, Q, M, N> &operator+=(const Matrix<Type, P, Q> &other)
{
Slice<Type, P, Q, M, N> &self = *this;
SliceT<MatrixT, Type, P, Q, M, N> &self = *this;

for (size_t i = 0; i < P; i++) {
for (size_t j = 0; j < Q; j++) {
Expand All @@ -141,9 +156,9 @@ class Slice
return self;
}

Slice<Type, P, Q, M, N> &operator+=(const Type &other)
SliceT<MatrixT, Type, P, Q, M, N> &operator+=(const Type &other)
{
Slice<Type, P, Q, M, N> &self = *this;
SliceT<MatrixT, Type, P, Q, M, N> &self = *this;

for (size_t i = 0; i < P; i++) {
for (size_t j = 0; j < Q; j++) {
Expand All @@ -155,9 +170,9 @@ class Slice
}

template<size_t MM, size_t NN>
Slice<Type, P, Q, M, N> &operator-=(const Slice<Type, P, Q, MM, NN> &other)
SliceT<MatrixT, Type, P, Q, M, N> &operator-=(const SliceT<MatrixT, Type, P, Q, MM, NN> &other)
{
Slice<Type, P, Q, M, N> &self = *this;
SliceT<MatrixT, Type, P, Q, M, N> &self = *this;

for (size_t i = 0; i < P; i++) {
for (size_t j = 0; j < Q; j++) {
Expand All @@ -168,9 +183,9 @@ class Slice
return self;
}

Slice<Type, P, Q, M, N> &operator-=(const Matrix<Type, P, Q> &other)
SliceT<MatrixT, Type, P, Q, M, N> &operator-=(const Matrix<Type, P, Q> &other)
{
Slice<Type, P, Q, M, N> &self = *this;
SliceT<MatrixT, Type, P, Q, M, N> &self = *this;

for (size_t i = 0; i < P; i++) {
for (size_t j = 0; j < Q; j++) {
Expand All @@ -181,9 +196,9 @@ class Slice
return self;
}

Slice<Type, P, Q, M, N> &operator-=(const Type &other)
SliceT<MatrixT, Type, P, Q, M, N> &operator-=(const Type &other)
{
Slice<Type, P, Q, M, N> &self = *this;
SliceT<MatrixT, Type, P, Q, M, N> &self = *this;

for (size_t i = 0; i < P; i++) {
for (size_t j = 0; j < Q; j++) {
Expand All @@ -194,9 +209,9 @@ class Slice
return self;
}

Slice<Type, P, Q, M, N> &operator*=(const Type &other)
SliceT<MatrixT, Type, P, Q, M, N> &operator*=(const Type &other)
{
Slice<Type, P, Q, M, N> &self = *this;
SliceT<MatrixT, Type, P, Q, M, N> &self = *this;

for (size_t i = 0; i < P; i++) {
for (size_t j = 0; j < Q; j++) {
Expand All @@ -207,14 +222,14 @@ class Slice
return self;
}

Slice<Type, P, Q, M, N> &operator/=(const Type &other)
SliceT<MatrixT, Type, P, Q, M, N> &operator/=(const Type &other)
{
return operator*=(Type(1) / other);
}

Matrix<Type, P, Q> operator*(const Type &other) const
{
const Slice<Type, P, Q, M, N> &self = *this;
const SliceT<MatrixT, Type, P, Q, M, N> &self = *this;
Matrix<Type, P, Q> res;

for (size_t i = 0; i < P; i++) {
Expand All @@ -228,25 +243,25 @@ class Slice

Matrix<Type, P, Q> operator/(const Type &other) const
{
const Slice<Type, P, Q, M, N> &self = *this;
const SliceT<MatrixT, Type, P, Q, M, N> &self = *this;
return self * (Type(1) / other);
}

template<size_t R, size_t S>
const Slice<Type, R, S, M, N> slice(size_t x0, size_t y0) const
const SliceT<MatrixT, Type, R, S, M, N> slice(size_t x0, size_t y0) const
{
return Slice<Type, R, S, M, N>(x0 + _x0, y0 + _y0, _data);
return SliceT<MatrixT, Type, R, S, M, N>(x0 + _x0, y0 + _y0, _data);
}

template<size_t R, size_t S>
Slice<Type, R, S, M, N> slice(size_t x0, size_t y0)
SliceT<MatrixT, Type, R, S, M, N> slice(size_t x0, size_t y0)
{
return Slice<Type, R, S, M, N>(x0 + _x0, y0 + _y0, _data);
return SliceT<MatrixT, Type, R, S, M, N>(x0 + _x0, y0 + _y0, _data);
}

void copyTo(Type dst[P * Q]) const
{
const Slice<Type, P, Q, M, N> &self = *this;
const SliceT<MatrixT, Type, P, Q, M, N> &self = *this;

for (size_t i = 0; i < P; i++) {
for (size_t j = 0; j < Q; j++) {
Expand All @@ -257,7 +272,7 @@ class Slice

void copyToColumnMajor(Type dst[P * Q]) const
{
const Slice<Type, P, Q, M, N> &self = *this;
const SliceT<MatrixT, Type, P, Q, M, N> &self = *this;

for (size_t i = 0; i < P; i++) {
for (size_t j = 0; j < Q; j++) {
Expand All @@ -268,7 +283,7 @@ class Slice

Vector < Type, P < Q ? P : Q > diag() const
{
const Slice<Type, P, Q, M, N> &self = *this;
const SliceT<MatrixT, Type, P, Q, M, N> &self = *this;
Vector < Type, P < Q ? P : Q > res;

for (size_t j = 0; j < (P < Q ? P : Q); j++) {
Expand All @@ -280,7 +295,7 @@ class Slice

Type norm_squared() const
{
const Slice<Type, P, Q, M, N> &self = *this;
const SliceT<MatrixT, Type, P, Q, M, N> &self = *this;
Type accum(0);

for (size_t i = 0; i < P; i++) {
Expand Down Expand Up @@ -338,7 +353,13 @@ class Slice

private:
size_t _x0, _y0;
Matrix<Type, M, N> *_data;
MatrixT *_data;
};

template <typename Type, size_t P, size_t Q, size_t M, size_t N>
using Slice = SliceT<Matrix<Type, M, N>, Type, P, Q, M, N>;

template <typename Type, size_t P, size_t Q, size_t M, size_t N>
using ConstSlice = SliceT<const Matrix<Type, M, N>, Type, P, Q, M, N>;

}
8 changes: 3 additions & 5 deletions src/lib/matrix/matrix/SquareMatrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,8 @@ class SquareMatrix : public Matrix<Type, M, M>
{
}

template<size_t P, size_t Q>
SquareMatrix(const Slice<Type, M, M, P, Q> &in_slice) : Matrix<Type, M, M>(in_slice)
{
}
using base = Matrix<Type, M, M>;
using base::base;

SquareMatrix<Type, M> &operator=(const Matrix<Type, M, M> &other)
{
Expand All @@ -55,7 +53,7 @@ class SquareMatrix : public Matrix<Type, M, M>
}

template<size_t P, size_t Q>
const Slice<Type, P, Q, M, M> slice(size_t x0, size_t y0) const
ConstSlice<Type, P, Q, M, M> slice(size_t x0, size_t y0) const
{
return {x0, y0, this};
}
Expand Down
16 changes: 16 additions & 0 deletions src/lib/matrix/matrix/Vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ class Vector : public Matrix<Type, M, 1>
}
}

template<size_t P, size_t Q>
Vector(const ConstSlice<Type, M, 1, P, Q> &slice_in) :
Matrix<Type, M, 1>(slice_in)
{
}

template<size_t P, size_t Q, size_t DUMMY = 1>
Vector(const ConstSlice<Type, 1, M, P, Q> &slice_in)
{
Vector &self(*this);

for (size_t i = 0; i < M; i++) {
self(i) = slice_in(0, i);
}
}

inline const Type &operator()(size_t i) const
{
assert(i < M);
Expand Down
11 changes: 2 additions & 9 deletions src/lib/matrix/matrix/Vector2.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,8 @@ class Vector2 : public Vector<Type, 2>
v(1) = y;
}

template<size_t P, size_t Q>
Vector2(const Slice<Type, 2, 1, P, Q> &slice_in) : Vector<Type, 2>(slice_in)
{
}

template<size_t P, size_t Q>
Vector2(const Slice<Type, 1, 2, P, Q> &slice_in) : Vector<Type, 2>(slice_in)
{
}
using base = Vector<Type, 2>;
using base::base;

explicit Vector2(const Vector3 &other)
{
Expand Down
Loading

0 comments on commit 3e183fe

Please sign in to comment.