matrix_helper_test.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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 "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) {
  28. EXPECT_THAT(iden.at(i, i), 1.0);
  29. }
  30. MATRIX_FOR_EACH_RANGE(i, 4, j, 4) {
  31. EXPECT_TRUE(i == j || iden.at(i, j) == 0);
  32. }
  33. }
  34. TEST(MatrixHelper, DiagonalWillFillWithAllZeros) {
  35. vec<4> const vector({1.5, 0.5, -1.0, 2.2});
  36. auto diag = math::matrix::diagonal(vector);
  37. VECTOR_FOR_EACH_RANGE(i, 4) {
  38. EXPECT_THAT(diag.at(i, i), vector.at(i));
  39. }
  40. MATRIX_FOR_EACH_RANGE(i, 4, j, 4) {
  41. EXPECT_TRUE(i == j || diag.at(i, j) == 0);
  42. }
  43. }
  44. TEST(MatrixHelper, ScalarMatrixPiecewiseStretchesVector) {
  45. vec<3> const vector({1.5, 0.5, -1.0});
  46. vec<3> const x({2.0, 3.8, 11.0});
  47. auto const A = math::matrix::scalar(vector);
  48. EXPECT_THAT(A*x, vector * x);
  49. }
  50. TEST(MatrixHelper, TranslationMatrixAddsToEachElement) {
  51. vec<3> const vector({1.5, 0.5, -1.0});
  52. vec<3> const x({2.0, 3.8, 11.0});
  53. auto const A = math::matrix::translation(vector);
  54. EXPECT_THAT(A*x, vector + x);
  55. }
  56. using matr3 = math::matrix::matrix<double, 3, 3>;
  57. using math::matrix::rotation;
  58. using math::matrix::rotation_t;
  59. namespace rotate = math::matrix::rotate;
  60. class RotationTest : public ::testing::TestWithParam<std::tuple<rotation_t<3>, matr3>> {
  61. };
  62. TEST(MatrixHelper, RotateByHalfPi) {
  63. auto const theta = M_PI/2;
  64. auto const iden = math::matrix::identity<double, 2>();
  65. auto const expected = math::matrix::matrix<double, 2, 2>({{{0, -1},{1, 0}}});
  66. auto result = iden * rotation(theta, rotate::ROT_2D);
  67. MATRIX_FOR_EACH_RANGE(i, 2, j, 2) {
  68. EXPECT_THAT(result(i, j),
  69. ::testing::DoubleNear(expected(i, j), std::numeric_limits<double>::epsilon()));
  70. }
  71. }
  72. TEST_P(RotationTest, RotateByHalfPi) {
  73. auto const theta = M_PI/2;
  74. auto const iden = math::matrix::identity<double, 3>();
  75. auto const expected = std::get<1>(GetParam());
  76. auto result = iden * rotation(theta, std::get<0>(GetParam()));
  77. MATRIX_FOR_EACH_RANGE(i, 3, j, 3) {
  78. EXPECT_THAT(result(i, j),
  79. ::testing::DoubleNear(expected(i, j), std::numeric_limits<double>::epsilon()));
  80. }
  81. }
  82. TEST(MatrixHelper, RotateIntoLargerMatrixArea) {
  83. auto const theta = M_PI/2;
  84. auto const iden = math::matrix::identity<double, 4>();
  85. auto const expected = math::matrix::matrix<double, 4, 4>({{
  86. {0,-1,0,0},
  87. {1, 0,0,0},
  88. {0, 0,1,0},
  89. {0, 0,0,1}
  90. }});
  91. auto result = iden * rotation<4>(theta, rotate::Z_AXIS);
  92. MATRIX_FOR_EACH_RANGE(i, 4, j, 4) {
  93. EXPECT_THAT(result(i, j),
  94. ::testing::DoubleNear(expected(i, j), std::numeric_limits<double>::epsilon()));
  95. }
  96. }
  97. std::vector<std::tuple<rotation_t<3>, matr3>> values{
  98. {rotate::X_AXIS, matr3({{{1, 0,0},{0,0,-1},{ 0,1,0}}})},
  99. {rotate::Y_AXIS, matr3({{{0, 0,1},{0,1, 0},{-1,0,0}}})},
  100. {rotate::Z_AXIS, matr3({{{0,-1,0},{1,0, 0},{ 0,0,1}}})}
  101. };
  102. INSTANTIATE_TEST_CASE_P(MatrixHelper, RotationTest, ::testing::ValuesIn(values));