More vector unit tests

This commit is contained in:
Andrew Cassidy 2022-06-19 18:33:54 -07:00
parent 232fb6cb41
commit 1c06cccd5c
2 changed files with 61 additions and 28 deletions

View File

@ -107,7 +107,6 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, N>>, M> {
using base::end;
using base::operator[];
public:
// region constructors
/**
* Create a vector from an intializer list
@ -122,7 +121,7 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, N>>, M> {
* Create a vector from a scalar value
* @param scalar value to populate with
*/
Matrix(const T &scalar) { std::fill(this->begin(), this->end(), scalar); }
Matrix(const T &scalar) { std::fill(this->all_begin(), this->all_end(), scalar); }
/**
* Create a vector from an iterator
@ -164,6 +163,12 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, N>>, M> {
auto column_begin() const { return column_iterator(this, 0); }
auto column_end() const { return column_iterator(this, N); }
auto all_begin() const { return linear_iterator<const Matrix>(this, 0); }
auto all_begin() { return linear_iterator<Matrix>(this, 0); }
auto all_end() const { return linear_iterator<const Matrix>(this, N * M); }
auto all_end() { return linear_iterator<Matrix>(this, N * M); }
const row_type &get_row(size_t y) const { return this->at(y); }
template <typename R> void set_row(size_t y, const R &value) { this->at(y) = value; }
@ -180,6 +185,7 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, N>>, M> {
return ret;
}
// n/m accessors
const T &element(size_t m, size_t n) const {
assert(n < N);
assert(m < M);
@ -193,8 +199,8 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, N>>, M> {
T &element(size_t n, size_t m) { return const_cast<T &>(static_cast<const Matrix &>(*this).element(n, m)); }
// linear accessors
const T &element(size_t i) const { return element(i / N, i % N); }
T &element(size_t i) { return element(i / N, i % N); }
// RGBA accessors
@ -320,6 +326,9 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, N>>, M> {
// sum up all rows
row_type vsum() const { return std::accumulate(row_begin(), row_end(), row_type{}); }
// sum up all values
T sum() const { return std::accumulate(all_begin(), all_end(), T{}); }
template <typename R, size_t P>
requires operable<R, T, std::multiplies<>>
Matrix<T, P, M> mult(const Matrix<R, P, N> &rhs) {
@ -414,22 +423,22 @@ class Matrix : public VecBase<std::conditional_t<N == 1, T, VecBase<T, N>>, M> {
const Matrix *_matrix;
};
class linear_iterator : public index_iterator_base<column_iterator> {
template <typename V> class linear_iterator : public index_iterator_base<linear_iterator<V>> {
public:
using value_type = column_type;
using base = index_iterator_base<column_iterator>;
using base = index_iterator_base<linear_iterator<V>>;
linear_iterator(const Matrix *matrix = nullptr, size_t index = 0) : base(index), _matrix(matrix){};
linear_iterator(V *matrix = nullptr, size_t index = 0) : base(index), _matrix(matrix){};
T &operator*() const { return _matrix->element(this->_index); }
T *operator->() const { &(_matrix->element(this->_index)); }
auto operator*() const { return _matrix->element(this->_index); }
auto *operator->() const { &(_matrix->element(this->_index)); }
friend bool operator==(const column_iterator &lhs, const column_iterator &rhs) {
friend bool operator==(const linear_iterator &lhs, const linear_iterator &rhs) {
return (lhs._matrix == rhs._matrix) && (lhs._index == rhs._index);
}
private:
const Matrix *_matrix;
V *_matrix;
};
};

View File

@ -26,8 +26,12 @@
namespace quicktex::tests {
template <typename V> inline void expect_vec_eq(V value, V expected) {
EXPECT_FLOAT_EQ((value - expected).sqr_mag(), 0);
template <typename V> inline void expect_matrix_eq(V value, V expected) {
if constexpr (std::is_floating_point_v<typename V::value_type>) {
EXPECT_FLOAT_EQ((value - expected).sum(), 0);
} else {
EXPECT_EQ(value, expected);
}
}
// region Vec_float unit tests
@ -35,34 +39,35 @@ TEST(Vec_float, add) {
auto a = Vec<float, 3>{1.0f, 1.5f, 2.0f};
auto b = Vec<float, 3>{2.0f, -2.5f, 3.0f};
expect_vec_eq(a + b, {3.0f, -1.0f, 5.0f});
expect_matrix_eq(a + b, {3.0f, -1.0f, 5.0f});
}
TEST(Vec_float, sub) {
auto a = Vec<float, 3>{1.0f, 1.5f, 2.0f};
auto b = Vec<float, 3>{3.0f, 1.5f, 1.0f};
expect_vec_eq(a - b, {-2.0f, 0.0f, 1.0f});
expect_matrix_eq(a - b, {-2.0f, 0.0f, 1.0f});
}
TEST(Vec_float, mul) {
auto a = Vec<float, 3>{1.0f, 1.5f, 2.0f};
auto b = Vec<float, 3>{3.0f, 1.5f, 0.0f};
expect_vec_eq(a * b, {3.0f, 2.25f, 0.0f});
expect_matrix_eq(a * b, {3.0f, 2.25f, 0.0f});
}
TEST(Vec_float, div) {
auto a = Vec<float, 3>{1.0f, 1.5f, 2.0f};
auto b = Vec<float, 3>{2.0f, 1.5f, 1.0f};
expect_vec_eq(a / b, {0.5f, 1.0f, 2.0f});
expect_matrix_eq(a / b, {0.5f, 1.0f, 2.0f});
}
TEST(Vec_float, vsum) {
auto a = Vec<float, 5>{1.0f, 2.0f, 3.5f, 4.0f, -4.0f};
EXPECT_FLOAT_EQ(a.vsum(), 6.5f);
EXPECT_FLOAT_EQ(a.sum(), 6.5f); // sum == vsum for a column vector
}
TEST(Vec_float, dot) {
@ -76,28 +81,36 @@ TEST(Vec_float, abs) {
auto a = Vec<float, 3>{1.0f, -5.0f, -1.0f};
auto expected = Vec<float, 3>{1.0f, 5.0f, 1.0f};
expect_vec_eq(a.abs(), expected);
expect_matrix_eq(a.abs(), expected);
}
TEST(Vec_float, clamp) {
auto a = Vec<float, 6>{-1, -1, -1, 1, 1, 1};
auto low1 = Vec<float, 6>{-2, -0.5, -2, 0, 2, 0.5};
auto high1 = Vec<float, 6>{-1.5, 0, 0, 0.5, 3, 2};
auto result1 = a.clamp(low1, high1);
auto expected1 = Vec<float, 6>{-1.5, -0.5, -1, 0.5, 2, 1};
expect_vec_eq(result1, expected1);
expect_matrix_eq(a.clamp(low1, high1), {-1.5, -0.5, -1, 0.5, 2, 1});
auto b = Vec<float, 6>{-1, -0.5, 0, 0.2, 0.5, 1};
auto result2 = b.clamp(-0.8, 0.3);
auto expected2 = Vec<float, 6>{-0.8, -0.5, 0, 0.2, 0.3, 0.3};
expect_vec_eq(result2, expected2);
expect_matrix_eq(b.clamp(-0.8, 0.3), {-0.8, -0.5, 0, 0.2, 0.3, 0.3});
}
// endregion
// region Vec_int unit tests
TEST(Vec_int, constructor) {
// scalar constructor
expect_matrix_eq(Vec<int, 4>(1), {1, 1, 1, 1});
// initializer list construtor
expect_matrix_eq(Vec<int, 4>{2, 3, 4, 5}, {2, 3, 4, 5});
// range constructor
std::array<int, 4> arr = {6, 7, 8, 9};
expect_matrix_eq(Vec<int, 4>(arr), {6, 7, 8, 9});
// iterator constructor
expect_matrix_eq(Vec<int, 4>(arr.begin()), {6, 7, 8, 9});
}
TEST(Vec_int, subscript) {
auto a = Vec<int, 4>{1, 3, 1, 2};
@ -110,12 +123,23 @@ TEST(Vec_int, subscript) {
EXPECT_EQ(a[2], 4);
}
TEST(Vec_int, getters) {
auto a = Vec<int, 4>{4, 20, 6, 9};
for (unsigned i = 0; i < a.size(); i++) {
EXPECT_EQ(a.get_row(i), a[i]); // the ith row of a column vector is a scalar
EXPECT_EQ(a.element(i, 0), a[i]);
EXPECT_EQ(a.element(i), a[i]);
}
EXPECT_EQ(a.get_column(0), a); // the 0th column of a column-vector is itself
}
TEST(Vec_int, copy) {
std::array<int, 4> arr{1, 3, 1, 2};
Vec<int, 4> a(arr);
Vec<int, 4> expected{1, 3, 1, 2};
EXPECT_EQ(a, expected);
expect_matrix_eq(a, {1, 3, 1, 2});
std::array<int, 4> out{-1, -3, -1, -2};
std::copy(a.begin(), a.end(), out.begin());