Matrix.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Types.h>
  8. #include <initializer_list>
  9. namespace Gfx {
  10. template<size_t N, typename T>
  11. class Matrix {
  12. public:
  13. static constexpr size_t Size = N;
  14. constexpr Matrix() = default;
  15. constexpr Matrix(std::initializer_list<T> elements)
  16. {
  17. VERIFY(elements.size() == N * N);
  18. size_t i = 0;
  19. for (auto& element : elements) {
  20. m_elements[i / N][i % N] = element;
  21. ++i;
  22. }
  23. }
  24. template<typename... Args>
  25. constexpr Matrix(Args... args)
  26. : Matrix({ (T)args... })
  27. {
  28. }
  29. Matrix(const Matrix& other)
  30. {
  31. __builtin_memcpy(m_elements, other.elements(), sizeof(T) * N * N);
  32. }
  33. Matrix& operator=(const Matrix& other)
  34. {
  35. __builtin_memcpy(m_elements, other.elements(), sizeof(T) * N * N);
  36. return *this;
  37. }
  38. constexpr auto elements() const { return m_elements; }
  39. constexpr auto elements() { return m_elements; }
  40. constexpr Matrix operator*(const Matrix& other) const
  41. {
  42. Matrix product;
  43. for (size_t i = 0; i < N; ++i) {
  44. for (size_t j = 0; j < N; ++j) {
  45. auto& element = product.m_elements[i][j];
  46. if constexpr (N == 4) {
  47. element = m_elements[i][0] * other.m_elements[0][j]
  48. + m_elements[i][1] * other.m_elements[1][j]
  49. + m_elements[i][2] * other.m_elements[2][j]
  50. + m_elements[i][3] * other.m_elements[3][j];
  51. } else if constexpr (N == 3) {
  52. element = m_elements[i][0] * other.m_elements[0][j]
  53. + m_elements[i][1] * other.m_elements[1][j]
  54. + m_elements[i][2] * other.m_elements[2][j];
  55. } else if constexpr (N == 2) {
  56. element = m_elements[i][0] * other.m_elements[0][j]
  57. + m_elements[i][1] * other.m_elements[1][j];
  58. } else if constexpr (N == 1) {
  59. element = m_elements[i][0] * other.m_elements[0][j];
  60. } else {
  61. T value {};
  62. for (size_t k = 0; k < N; ++k)
  63. value += m_elements[i][k] * other.m_elements[k][j];
  64. element = value;
  65. }
  66. }
  67. }
  68. return product;
  69. }
  70. constexpr Matrix operator/(T divisor) const
  71. {
  72. Matrix division;
  73. for (size_t i = 0; i < N; ++i) {
  74. for (size_t j = 0; j < N; ++j) {
  75. division.m_elements[i][j] = m_elements[i][j] / divisor;
  76. }
  77. }
  78. return division;
  79. }
  80. [[nodiscard]] constexpr Matrix adjugate() const
  81. {
  82. if constexpr (N == 1)
  83. return Matrix(1);
  84. Matrix adjugate;
  85. for (size_t i = 0; i < N; ++i) {
  86. for (size_t j = 0; j < N; ++j) {
  87. int sign = (i + j) % 2 == 0 ? 1 : -1;
  88. adjugate.m_elements[j][i] = sign * first_minor(i, j);
  89. }
  90. }
  91. return adjugate;
  92. }
  93. [[nodiscard]] constexpr T determinant() const
  94. {
  95. if constexpr (N == 1) {
  96. return m_elements[0][0];
  97. } else {
  98. T result = {};
  99. int sign = 1;
  100. for (size_t j = 0; j < N; ++j) {
  101. result += sign * m_elements[0][j] * first_minor(0, j);
  102. sign *= -1;
  103. }
  104. return result;
  105. }
  106. }
  107. [[nodiscard]] constexpr T first_minor(size_t skip_row, size_t skip_column) const
  108. {
  109. static_assert(N > 1);
  110. VERIFY(skip_row < N);
  111. VERIFY(skip_column < N);
  112. Matrix<N - 1, T> first_minor;
  113. constexpr auto new_size = N - 1;
  114. size_t k = 0;
  115. for (size_t i = 0; i < N; ++i) {
  116. for (size_t j = 0; j < N; ++j) {
  117. if (i == skip_row || j == skip_column)
  118. continue;
  119. first_minor.elements()[k / new_size][k % new_size] = m_elements[i][j];
  120. ++k;
  121. }
  122. }
  123. return first_minor.determinant();
  124. }
  125. [[nodiscard]] constexpr static Matrix identity()
  126. {
  127. Matrix result;
  128. for (size_t i = 0; i < N; ++i) {
  129. for (size_t j = 0; j < N; ++j) {
  130. if (i == j)
  131. result.m_elements[i][j] = 1;
  132. else
  133. result.m_elements[i][j] = 0;
  134. }
  135. }
  136. return result;
  137. }
  138. [[nodiscard]] constexpr Matrix inverse() const
  139. {
  140. auto det = determinant();
  141. VERIFY(det != 0);
  142. return adjugate() / det;
  143. }
  144. [[nodiscard]] constexpr Matrix transpose() const
  145. {
  146. Matrix result;
  147. for (size_t i = 0; i < N; ++i) {
  148. for (size_t j = 0; j < N; ++j) {
  149. result.m_elements[i][j] = m_elements[j][i];
  150. }
  151. }
  152. return result;
  153. }
  154. private:
  155. T m_elements[N][N];
  156. };
  157. }
  158. using Gfx::Matrix;