matrix_helper_test.cxx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. //
  2. // matrix_helper_test.cpp
  3. // matrix
  4. //
  5. // Created by Sam Jaffe on 6/3/18.
  6. //
  7. #include <gmock/gmock.h>
  8. #include "math/matrix/matrix_helpers.hpp"
  9. template <std::size_t N> using vec = math::vector::vector<double, N>;
  10. namespace math { namespace matrix {
  11. template <typename T, std::size_t R, std::size_t C>
  12. void PrintTo(matrix<T, R, C> const & matr, std::ostream * out) {
  13. (*out) << "[\n";
  14. VECTOR_FOR_EACH_RANGE(i, R) {
  15. (*out) << " [ ";
  16. VECTOR_FOR_EACH_RANGE(j, C) {
  17. if (j != 0) (*out) << ", ";
  18. (*out) << matr(i, j);
  19. }
  20. (*out) << " ]\n";
  21. }
  22. (*out) << "]";
  23. }
  24. }}
  25. TEST(MatrixHelper, IdentityFunctionProducesOnes) {
  26. auto iden = math::matrix::identity<double, 4>();
  27. VECTOR_FOR_EACH_RANGE(i, 4) { EXPECT_THAT(iden.at(i, i), 1.0); }
  28. MATRIX_FOR_EACH_RANGE(i, 4, j, 4) {
  29. EXPECT_TRUE(i == j || iden.at(i, j) == 0);
  30. }
  31. }
  32. TEST(MatrixHelper, DiagonalWillFillWithAllZeros) {
  33. vec<4> const vector({1.5, 0.5, -1.0, 2.2});
  34. auto diag = math::matrix::diagonal(vector);
  35. VECTOR_FOR_EACH_RANGE(i, 4) { EXPECT_THAT(diag.at(i, i), vector.at(i)); }
  36. MATRIX_FOR_EACH_RANGE(i, 4, j, 4) {
  37. EXPECT_TRUE(i == j || diag.at(i, j) == 0);
  38. }
  39. }
  40. TEST(MatrixHelper, ScalarMatrixPiecewiseStretchesVector) {
  41. vec<3> const vector({1.5, 0.5, -1.0});
  42. vec<3> const x({2.0, 3.8, 11.0});
  43. auto const A = math::matrix::scalar(vector);
  44. EXPECT_THAT(A * x, vector * x);
  45. }
  46. TEST(MatrixHelper, TranslationMatrixAddsToEachElement) {
  47. vec<3> const vector({1.5, 0.5, -1.0});
  48. vec<3> const x({2.0, 3.8, 11.0});
  49. auto const A = math::matrix::translation(vector);
  50. EXPECT_THAT(A * x, vector + x);
  51. }
  52. using matr3 = math::matrix::matrix<double, 3, 3>;
  53. using math::matrix::rotation;
  54. using math::matrix::rotation_t;
  55. namespace rotate = math::matrix::rotate;
  56. class RotationTest
  57. : public ::testing::TestWithParam<std::tuple<rotation_t<3>, matr3>> {};
  58. TEST(MatrixHelper, RotateByHalfPi) {
  59. auto const theta = M_PI / 2;
  60. auto const iden = math::matrix::identity<double, 2>();
  61. auto const expected = math::matrix::matrix<double, 2, 2>({{{0, -1}, {1, 0}}});
  62. auto result = iden * rotation(theta, rotate::ROT_2D);
  63. MATRIX_FOR_EACH_RANGE(i, 2, j, 2) {
  64. EXPECT_THAT(result(i, j),
  65. ::testing::DoubleNear(expected(i, j),
  66. std::numeric_limits<double>::epsilon()));
  67. }
  68. }
  69. TEST_P(RotationTest, RotateByHalfPi) {
  70. auto const theta = M_PI / 2;
  71. auto const iden = math::matrix::identity<double, 3>();
  72. auto const expected = std::get<1>(GetParam());
  73. auto result = iden * rotation(theta, std::get<0>(GetParam()));
  74. MATRIX_FOR_EACH_RANGE(i, 3, j, 3) {
  75. EXPECT_THAT(result(i, j),
  76. ::testing::DoubleNear(expected(i, j),
  77. std::numeric_limits<double>::epsilon()));
  78. }
  79. }
  80. TEST(MatrixHelper, RotateIntoLargerMatrixArea) {
  81. auto const theta = M_PI / 2;
  82. auto const iden = math::matrix::identity<double, 4>();
  83. auto const expected = math::matrix::matrix<double, 4, 4>(
  84. {{{0, -1, 0, 0}, {1, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}});
  85. auto result = iden * rotation<4>(theta, rotate::Z_AXIS);
  86. MATRIX_FOR_EACH_RANGE(i, 4, j, 4) {
  87. EXPECT_THAT(result(i, j),
  88. ::testing::DoubleNear(expected(i, j),
  89. std::numeric_limits<double>::epsilon()));
  90. }
  91. }
  92. std::vector<std::tuple<rotation_t<3>, matr3>> values{
  93. {rotate::X_AXIS, matr3({{{1, 0, 0}, {0, 0, -1}, {0, 1, 0}}})},
  94. {rotate::Y_AXIS, matr3({{{0, 0, 1}, {0, 1, 0}, {-1, 0, 0}}})},
  95. {rotate::Z_AXIS, matr3({{{0, -1, 0}, {1, 0, 0}, {0, 0, 1}}})}};
  96. INSTANTIATE_TEST_CASE_P(MatrixHelper, RotationTest,
  97. ::testing::ValuesIn(values));