Use int for sizes in matrix type

feature/simd
Andrew Cassidy 2 years ago
parent f77ea3be0f
commit db24af730e

@ -30,9 +30,9 @@
namespace quicktex { namespace quicktex {
template <typename T, size_t M, size_t N> class Matrix; template <typename T, int M, int N> class Matrix;
template <typename T, size_t M> using Vec = Matrix<T, M, 1>; template <typename T, int M> using Vec = Matrix<T, M, 1>;
// region helper concepts // region helper concepts
template <typename L, typename R, typename Op> template <typename L, typename R, typename Op>
@ -47,32 +47,32 @@ concept is_matrix = requires(V &v) {
std::remove_cvref_t < V >> ; std::remove_cvref_t < V >> ;
template <typename V> struct vector_stats { template <typename V> struct vector_stats {
static constexpr size_t width = 1; static constexpr int width = 1;
static constexpr size_t height = 1; static constexpr int height = 1;
static constexpr size_t dims = 0; static constexpr int dims = 0;
}; };
template <typename V> template <typename V>
requires is_matrix<V> requires is_matrix<V>
struct vector_stats<V> { struct vector_stats<V> {
static constexpr size_t width = V::width; static constexpr int width = V::width;
static constexpr size_t height = V::height; static constexpr int height = V::height;
static constexpr size_t dims = V::dims; static constexpr int dims = V::dims;
}; };
template <typename V> constexpr size_t vector_width = vector_stats<V>::width; template <typename V> constexpr int vector_width = vector_stats<V>::width;
template <typename V> constexpr size_t vector_height = vector_stats<V>::height; template <typename V> constexpr int vector_height = vector_stats<V>::height;
template <typename V> constexpr size_t vector_dims = vector_stats<V>::dims; template <typename V> constexpr int vector_dims = vector_stats<V>::dims;
// endregion // endregion
template <typename R, typename T, size_t N> class VecBase { template <typename R, typename T, int N> class VecBase {
public: public:
constexpr VecBase(T scalar = T()) : _c{} { _c.fill(scalar); } constexpr VecBase(T scalar = T()) : _c{} { _c.fill(scalar); }
protected: protected:
const R &_at(size_t index) const { return _c.at(index); } const R &_at(int index) const { return _c.at(index); }
R &_at(size_t index) { return _c.at(index); } R &_at(int index) { return _c.at(index); }
constexpr auto _begin() const { return _c.data(); } constexpr auto _begin() const { return _c.data(); }
constexpr auto _begin() { return _c.data(); } constexpr auto _begin() { return _c.data(); }
@ -83,8 +83,8 @@ template <typename R, typename T, size_t N> class VecBase {
std::array<R, N> _c; std::array<R, N> _c;
}; };
template <typename T, size_t N, size_t M> using matrix_row_type = std::conditional_t<N <= 1, T, Vec<T, N>>; template <typename T, int N, int M> using matrix_row_type = std::conditional_t<N <= 1, T, Vec<T, N>>;
template <typename T, size_t N, size_t M> using matrix_column_type = std::conditional_t<M <= 1, T, Vec<T, M>>; template <typename T, int N, int M> using matrix_column_type = std::conditional_t<M <= 1, T, Vec<T, M>>;
/** /**
* A matrix of values that can be operated on * A matrix of values that can be operated on
@ -92,7 +92,7 @@ template <typename T, size_t N, size_t M> using matrix_column_type = std::condit
* @tparam N Width of the matrix * @tparam N Width of the matrix
* @tparam M Height of the matrix * @tparam M Height of the matrix
*/ */
template <typename T, size_t M, size_t N> template <typename T, int M, int N>
class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T, M> { class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T, M> {
public: public:
using base = VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T, M>; using base = VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T, M>;
@ -150,29 +150,29 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T
requires(N == M) requires(N == M)
static constexpr Matrix identity() { static constexpr Matrix identity() {
Matrix result = Matrix(0); Matrix result = Matrix(0);
for (unsigned i = 0; i < N; i++) { result.element(i, i) = 1; } for (int i = 0; i < N; i++) { result.element(i, i) = 1; }
return result; return result;
} }
// endregion // endregion
// region iterators and accessors // region iterators and accessors
static constexpr size_t size() { return M; } static constexpr int size() { return M; }
static constexpr size_t width = N; static constexpr int width = N;
static constexpr size_t height = M; static constexpr int height = M;
static constexpr size_t elements = N * M; static constexpr int elements = N * M;
static constexpr size_t dims = ((width > 1) ? 1 : 0) + ((height > 1) ? 1 : 0); static constexpr int dims = ((width > 1) ? 1 : 0) + ((height > 1) ? 1 : 0);
const row_type &at(size_t index) const { const row_type &at(int index) const {
assert(index < M); assert(index >= 0 && index < M);
return static_cast<const row_type &>(base::_at(index)); return static_cast<const row_type &>(base::_at(index));
} }
row_type &at(size_t index) { row_type &at(int index) {
assert(index < M); assert(index >= 0 && index < M);
return static_cast<row_type &>(base::_at(index)); return static_cast<row_type &>(base::_at(index));
} }
const row_type &operator[](size_t index) const { return at(index); } const row_type &operator[](int index) const { return at(index); }
row_type &operator[](size_t index) { return at(index); } row_type &operator[](int index) { return at(index); }
const row_type *begin() const { return static_cast<const row_type *>(base::_begin()); } const row_type *begin() const { return static_cast<const row_type *>(base::_begin()); }
row_type *begin() { return static_cast<row_type *>(base::_begin()); } row_type *begin() { return static_cast<row_type *>(base::_begin()); }
@ -189,36 +189,29 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T
auto all_end() const { return linear_iterator<const Matrix>(this, N * M); } auto all_end() const { return linear_iterator<const Matrix>(this, N * M); }
auto all_end() { return linear_iterator<Matrix>(this, N * M); } auto all_end() { return linear_iterator<Matrix>(this, N * M); }
const row_type &get_row(size_t m) const { const row_type &get_row(int m) const { return static_cast<const row_type &>(this->at(m)); }
assert(m < M); template <typename R> void set_row(int m, const R &value) { this->at(m) = value; }
return static_cast<const row_type &>(this->at(m));
}
template <typename R> void set_row(size_t m, const R &value) {
assert(m < M);
this->at(m) = value;
}
template <typename S = T> column_type get_column(size_t n) const { template <typename S = T> column_type get_column(int n) const {
if constexpr (M == 1) { if constexpr (M == 1) {
return element(0, n); return element(0, n);
} else { } else {
column_type ret; column_type ret;
for (unsigned m = 0; m < M; m++) { ret[m] = element(m, n); } for (int m = 0; m < M; m++) { ret[m] = element(m, n); }
return ret; return ret;
} }
} }
void set_column(size_t n, const column_type &value) { void set_column(int n, const column_type &value) {
if constexpr (M == 1) { if constexpr (M == 1) {
element(0, n) = value; element(0, n) = value;
} else { } else {
for (unsigned m = 0; m < M; m++) { element(m, n) = value[m]; } for (int m = 0; m < M; m++) { element(m, n) = value[m]; }
} }
} }
// n/m accessors // n/m accessors
const T &element(size_t m, size_t n) const { const T &element(int m, int n) const {
if constexpr (N == 1) { if constexpr (N == 1) {
return this->at(m); return this->at(m);
} else { } else {
@ -226,11 +219,11 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T
} }
} }
T &element(size_t n, size_t m) { return const_cast<T &>(static_cast<const Matrix &>(*this).element(n, m)); } T &element(int n, int m) { return const_cast<T &>(static_cast<const Matrix &>(*this).element(n, m)); }
// linear accessors // linear accessors
const T &element(size_t i) const { return element(i / N, i % N); } const T &element(int i) const { return element(i / N, i % N); }
T &element(size_t i) { return element(i / N, i % N); } T &element(int i) { return element(i / N, i % N); }
// RGBA accessors // RGBA accessors
const T &r() const { return (*this)[0]; } const T &r() const { return (*this)[0]; }
@ -277,12 +270,12 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T
template <typename R> template <typename R>
requires operable<R, T, std::minus<>> requires operable<R, T, std::minus<>>
Matrix operator-(const Matrix<R, M, N> &rhs) const { Matrix operator-(const Matrix<R, M, N> &rhs) const {
// we can't just add the negation because that's invalid for unsigned types // we can't just add the negation because that's invalid for int types
return map(std::minus(), *this, rhs); return map(std::minus(), *this, rhs);
}; };
// multiply matrix with a matrix or column vector // multiply matrix with a matrix or column vector
template <typename R, size_t P> template <typename R, int P>
requires(P == 1 || P == N) && operable<R, T, std::multiplies<>> requires(P == 1 || P == N) && operable<R, T, std::multiplies<>>
Matrix operator*(const Matrix<R, M, P> &rhs) const { Matrix operator*(const Matrix<R, M, P> &rhs) const {
return map(std::multiplies(), *this, rhs); return map(std::multiplies(), *this, rhs);
@ -296,7 +289,7 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T
}; };
// divides a matrix by a matrix or column vector // divides a matrix by a matrix or column vector
template <typename R, size_t NN> template <typename R, int NN>
requires(NN == 1 || NN == N) && operable<R, T, std::divides<>> requires(NN == 1 || NN == N) && operable<R, T, std::divides<>>
Matrix operator/(const Matrix<R, M, NN> &rhs) const { Matrix operator/(const Matrix<R, M, NN> &rhs) const {
return map(std::divides(), *this, rhs); return map(std::divides(), *this, rhs);
@ -353,7 +346,7 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T
column_type hsum() const { column_type hsum() const {
if constexpr (N == 1) { return *this; } if constexpr (N == 1) { return *this; }
if constexpr (M == 1) { return sum(); } if constexpr (M == 1) { return sum(); }
for (unsigned i = 0; i < M; i++) {} for (int i = 0; i < M; i++) {}
return _map<column_type>([](auto row) { return quicktex::sum(row); }, *this); return _map<column_type>([](auto row) { return quicktex::sum(row); }, *this);
} }
@ -370,15 +363,15 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T
return std::accumulate(all_begin(), all_end(), T(0)); return std::accumulate(all_begin(), all_end(), T(0));
} }
template <typename R, size_t P> template <typename R, int P>
requires operable<R, T, std::multiplies<>> requires operable<R, T, std::multiplies<>>
Matrix<T, M, P> mult(const Matrix<R, N, P> &rhs) const { Matrix<T, M, P> mult(const Matrix<R, N, P> &rhs) const {
Matrix<T, M, P> res(0); Matrix<T, M, P> res(0);
for (unsigned p = 0; p < P; p++) { for (int p = 0; p < P; p++) {
// for each column of the RHS/Result // for each column of the RHS/Result
for (unsigned m = 0; m < M; m++) { for (int m = 0; m < M; m++) {
// for each row of the LHS/Result // for each row of the LHS/Result
for (unsigned n = 0; n < N; n++) { res.element(m, p) += element(m, n) * rhs.element(n, p); } for (int n = 0; n < N; n++) { res.element(m, p) += element(m, n) * rhs.element(n, p); }
} }
} }
return res; return res;
@ -386,7 +379,7 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T
Matrix<T, N, M> transpose() const { Matrix<T, N, M> transpose() const {
Matrix<T, N, M> res; Matrix<T, N, M> res;
for (unsigned m = 0; m < M; m++) { res.set_column(m, get_row(m)); } for (int m = 0; m < M; m++) { res.set_column(m, get_row(m)); }
return res; return res;
} }
@ -394,8 +387,8 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T
requires(N == M) requires(N == M)
Matrix mirror() const { Matrix mirror() const {
Matrix result = *this; Matrix result = *this;
for (unsigned n = 0; n < N - 1; n++) { for (int n = 0; n < N - 1; n++) {
for (unsigned m = (n + 1); m < M; m++) { result.element(m, n) = result.element(n, m); } for (int m = (n + 1); m < M; m++) { result.element(m, n) = result.element(n, m); }
} }
return result; return result;
} }
@ -429,7 +422,7 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T
using value_type = column_type; using value_type = column_type;
using base = index_iterator_base<column_iterator>; using base = index_iterator_base<column_iterator>;
column_iterator(const Matrix *matrix = nullptr, size_t index = 0) : base(index), _matrix(matrix){}; column_iterator(const Matrix *matrix = nullptr, int index = 0) : base(index), _matrix(matrix){};
column_type operator*() const { return _matrix->get_column(this->_index); } column_type operator*() const { return _matrix->get_column(this->_index); }
const column_type *operator->() const { &(_matrix->get_column(this->_index)); } const column_type *operator->() const { &(_matrix->get_column(this->_index)); }
@ -447,7 +440,7 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, T, N>>, T
using value_type = column_type; using value_type = column_type;
using base = index_iterator_base<linear_iterator<V>>; using base = index_iterator_base<linear_iterator<V>>;
linear_iterator(V *matrix = nullptr, size_t index = 0) : base(index), _matrix(matrix){}; linear_iterator(V *matrix = nullptr, int index = 0) : base(index), _matrix(matrix){};
auto &operator*() { return _matrix->element(this->_index); } auto &operator*() { return _matrix->element(this->_index); }
auto *operator->() const { return &(_matrix->element(this->_index)); } auto *operator->() const { return &(_matrix->element(this->_index)); }

@ -60,6 +60,7 @@ function(set_project_warnings project_name)
-Wdouble-promotion # warn if float is implicit promoted to double -Wdouble-promotion # warn if float is implicit promoted to double
-Wformat=2 # warn on security issues around functions that format output -Wformat=2 # warn on security issues around functions that format output
# (ie printf) # (ie printf)
-Wsign-compare
) )
if (${PROJECT_NAME}_WARNINGS_AS_ERRORS) if (${PROJECT_NAME}_WARNINGS_AS_ERRORS)

Loading…
Cancel
Save