Antkeeper  0.0.1
math/matrix.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Christopher J. Howard
3  *
4  * This file is part of Antkeeper source code.
5  *
6  * Antkeeper source code is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Antkeeper source code is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef ANTKEEPER_MATH_MATRIX_HPP
21 #define ANTKEEPER_MATH_MATRIX_HPP
22 
23 #include <engine/math/vector.hpp>
24 #include <cstddef>
25 #include <format>
26 #include <iterator>
27 #include <tuple>
28 #include <type_traits>
29 #include <utility>
30 
31 namespace math {
32 
42 template <class T, std::size_t N, std::size_t M>
43 struct matrix
44 {
46  using element_type = T;
47 
49  static constexpr std::size_t column_count = N;
50 
52  static constexpr std::size_t row_count = M;
53 
55  static constexpr std::size_t element_count = column_count * row_count;
56 
59 
62 
65 
68 
70  template <class U, std::size_t... I>
71  [[nodiscard]] inline constexpr matrix<U, N, M> type_cast(std::index_sequence<I...>) const noexcept
72  {
73  return {vector<U, M>(columns[I])...};
74  }
75 
83  template <class U>
84  [[nodiscard]] inline constexpr explicit operator matrix<U, N, M>() const noexcept
85  {
86  return type_cast<U>(std::make_index_sequence<N>{});
87  }
88 
90  template <std::size_t P, std::size_t O, std::size_t... I>
91  [[nodiscard]] inline constexpr matrix<T, P, O> size_cast(std::index_sequence<I...>) const noexcept
92  {
93  if constexpr (O == M)
94  {
96  }
97  else
98  {
99  return {((I < N) ? vector<T, O>(columns[I]) : matrix<T, P, O>::identity()[I]) ...};
100  }
101  }
102 
111  template <std::size_t P, std::size_t O>
112  [[nodiscard]] inline constexpr explicit operator matrix<T, P, O>() const noexcept
113  {
114  return size_cast<P, O>(std::make_index_sequence<P>{});
115  }
116 
118 
121 
130  [[nodiscard]] inline constexpr column_vector_type& operator[](std::size_t i) noexcept
131  {
132  return columns[i];
133  }
134  [[nodiscard]] inline constexpr const column_vector_type& operator[](std::size_t i) const noexcept
135  {
136  return columns[i];
137  }
138  [[nodiscard]] inline constexpr column_vector_type& column(std::size_t i) noexcept
139  {
140  return columns[i];
141  }
142  [[nodiscard]] inline constexpr const column_vector_type& column(std::size_t i) const noexcept
143  {
144  return columns[i];
145  }
147 
152  [[nodiscard]] inline constexpr column_vector_type& front() noexcept
153  {
154  return columns[0];
155  }
156  [[nodiscard]] inline constexpr const column_vector_type& front() const noexcept
157  {
158  return columns[0];
159  }
161 
166  [[nodiscard]] inline constexpr column_vector_type& back() noexcept
167  {
168  return columns[column_count - 1];
169  }
170  [[nodiscard]] inline constexpr const column_vector_type& back() const noexcept
171  {
172  return columns[column_count - 1];
173  }
175 
177 
180 
189  [[nodiscard]] inline constexpr T& element(std::size_t i) noexcept
190  {
191  return columns[i / row_count][i % row_count];
192  }
193  [[nodiscard]] inline constexpr const T& element(std::size_t i) const noexcept
194  {
195  return columns[i / row_count][i % row_count];
196  }
198 
205  [[nodiscard]] inline constexpr element_type* data() noexcept
206  {
207  return &columns[0][0];
208  };
209  [[nodiscard]] inline constexpr const element_type* data() const noexcept
210  {
211  return &columns[0][0];
212  };
214 
216 
219 
224  [[nodiscard]] inline constexpr column_vector_type* begin() noexcept
225  {
226  return columns;
227  }
228  [[nodiscard]] inline constexpr const column_vector_type* begin() const noexcept
229  {
230  return columns;
231  }
232  [[nodiscard]] inline constexpr const column_vector_type* cbegin() const noexcept
233  {
234  return columns;
235  }
237 
242  [[nodiscard]] inline constexpr column_vector_type* end() noexcept
243  {
244  return columns + column_count;
245  }
246  [[nodiscard]] inline constexpr const column_vector_type* end() const noexcept
247  {
248  return columns + column_count;
249  }
250  [[nodiscard]] inline constexpr const column_vector_type* cend() const noexcept
251  {
252  return columns + column_count;
253  }
255 
260  [[nodiscard]] inline constexpr std::reverse_iterator<column_vector_type*> rbegin() noexcept
261  {
262  return std::reverse_iterator<column_vector_type*>(columns + column_count);
263  }
264  [[nodiscard]] inline constexpr std::reverse_iterator<const column_vector_type*> rbegin() const noexcept
265  {
266  return std::reverse_iterator<const column_vector_type*>(columns + column_count);
267  }
268  [[nodiscard]] inline constexpr std::reverse_iterator<const column_vector_type*> crbegin() const noexcept
269  {
270  return std::reverse_iterator<const column_vector_type*>(columns + column_count);
271  }
273 
278  [[nodiscard]] inline constexpr std::reverse_iterator<column_vector_type*> rend() noexcept
279  {
280  return std::reverse_iterator<column_vector_type*>(columns);
281  }
282  [[nodiscard]] inline constexpr std::reverse_iterator<const column_vector_type*> rend() const noexcept
283  {
284  return std::reverse_iterator<const column_vector_type*>(columns);
285  }
286  [[nodiscard]] inline constexpr std::reverse_iterator<const column_vector_type*> crend() const noexcept
287  {
288  return std::reverse_iterator<const column_vector_type*>(columns);
289  }
291 
293 
296 
300  [[nodiscard]] inline constexpr std::size_t size() const noexcept
301  {
302  return element_count;
303  };
304 
306 
309 
313  [[nodiscard]] static constexpr matrix zero() noexcept
314  {
315  return {};
316  }
317 
319  template <std::size_t... I>
320  [[nodiscard]] static inline constexpr matrix one(std::index_sequence<I...>) noexcept
321  {
322  //return {column_vector_type::one() ...};
323 
324  // MSVC bug workaround (I must be referenced for parameter pack expansion)
325  return {(I ? column_vector_type::one() : column_vector_type::one()) ...};
326  }
327 
331  [[nodiscard]] static constexpr matrix one() noexcept
332  {
333  return one(std::make_index_sequence<column_count>{});
334  }
335 
337  template <std::size_t... I>
338  [[nodiscard]] static inline constexpr column_vector_type identity_column(std::size_t i, std::index_sequence<I...>) noexcept
339  {
340  return {(I == i ? T{1} : T{0}) ...};
341  }
342 
344  template <std::size_t... I>
345  [[nodiscard]] static inline constexpr matrix identity(std::index_sequence<I...>) noexcept
346  {
347  return {identity_column(I, std::make_index_sequence<row_count>{}) ...};
348  }
349 
353  [[nodiscard]] static constexpr matrix identity() noexcept
354  {
355  return identity(std::make_index_sequence<column_count>{});
356  }
357 
359 };
360 
362 namespace matrix_types {
363 
370 template <class T>
372 template <class T>
374 template <class T>
376 template <class T>
378 template <class T>
380 template <class T>
382 template <class T>
384 template <class T>
386 template <class T>
389 
396 template <class T>
397 using mat2 = mat2x2<T>;
398 template <class T>
399 using mat3 = mat3x3<T>;
400 template <class T>
401 using mat4 = mat4x4<T>;
403 
411 template <std::size_t N, std::size_t M>
423 
426 using fmat2 = fmat2x2;
427 using fmat3 = fmat3x3;
428 using fmat4 = fmat4x4;
430 
438 template <std::size_t N, std::size_t M>
450 
453 using dmat2 = dmat2x2;
454 using dmat3 = dmat3x3;
455 using dmat4 = dmat4x4;
457 
458 } // namespace matrix_types
459 
460 // Bring matrix types into math namespace
461 using namespace matrix_types;
462 
463 // Bring matrix types into math::types namespace
464 namespace types { using namespace matrix_types; }
465 
474 template <class T, std::size_t N, std::size_t M>
475 [[nodiscard]] constexpr matrix<T, N, M> add(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept;
476 
485 template <class T, std::size_t N, std::size_t M>
486 [[nodiscard]] constexpr matrix<T, N, M> add(const matrix<T, N, M>& a, T b) noexcept;
487 
497 template <class T, std::size_t N>
498 [[nodiscard]] constexpr T determinant(const matrix<T, N, N>& m) noexcept;
499 
508 template <class T, std::size_t N, std::size_t M>
509 [[nodiscard]] constexpr matrix<T, N, M> componentwise_mul(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept;
510 
519 template <class T, std::size_t N, std::size_t M>
520 [[nodiscard]] constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept;
521 
530 template <class T, std::size_t N, std::size_t M>
531 [[nodiscard]] constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, T b) noexcept;
532 
541 template <class T, std::size_t N, std::size_t M>
542 [[nodiscard]] constexpr matrix<T, N, M> div(T a, const matrix<T, N, M>& b) noexcept;
543 
557 template<std::size_t I, class T, std::size_t N, std::size_t M>
558 [[nodiscard]] constexpr typename matrix<T, N, M>::column_vector_type& get(matrix<T, N, M>& m) noexcept;
559 template<std::size_t I, class T, std::size_t N, std::size_t M>
560 [[nodiscard]] constexpr typename matrix<T, N, M>::column_vector_type&& get(matrix<T, N, M>&& m) noexcept;
561 template<std::size_t I, class T, std::size_t N, std::size_t M>
562 [[nodiscard]] constexpr const typename matrix<T, N, M>::column_vector_type& get(const matrix<T, N, M>& m) noexcept;
563 template<std::size_t I, class T, std::size_t N, std::size_t M>
564 [[nodiscard]] constexpr const typename matrix<T, N, M>::column_vector_type&& get(const matrix<T, N, M>&& m) noexcept;
566 
576 template <class T, std::size_t N>
577 [[nodiscard]] constexpr matrix<T, N, N> inverse(const matrix<T, N, N>& m) noexcept;
578 
588 template <class T>
589 [[nodiscard]] constexpr mat4<T> look_at_rh(const vec3<T>& position, const vec3<T>& target, const vec3<T>& up);
590 
602 template <class T>
603 [[nodiscard]] constexpr std::tuple<mat4<T>, mat4<T>> look_at_rh_inv(const vec3<T>& position, const vec3<T>& target, const vec3<T>& up);
604 
618 template <class T, std::size_t N, std::size_t M, std::size_t P>
619 [[nodiscard]] constexpr matrix<T, P, M> mul(const matrix<T, N, M>& a, const matrix<T, P, N>& b) noexcept;
620 
629 template <class T, std::size_t N, std::size_t M>
630 [[nodiscard]] constexpr matrix<T, N, M> mul(const matrix<T, N, M>& a, T b) noexcept;
631 
640 template <class T, std::size_t N, std::size_t M>
641 [[nodiscard]] constexpr typename matrix<T, N, M>::column_vector_type mul(const matrix<T, N, M>& a, const typename matrix<T, N, M>::row_vector_type& b) noexcept;
642 
651 template <class T, std::size_t N, std::size_t M>
652 [[nodiscard]] constexpr typename matrix<T, N, M>::row_vector_type mul(const typename matrix<T, N, M>::column_vector_type& a, const matrix<T, N, M>& b) noexcept;
653 
662 template <class T>
663 [[nodiscard]] mat3<T> rotate(T angle, const vector<T, 3>& axis);
664 
672 template <class T>
673 [[nodiscard]] mat3<T> rotate_x(T angle);
674 
682 template <class T>
683 [[nodiscard]] mat3<T> rotate_y(T angle);
684 
692 template <class T>
693 [[nodiscard]] mat3<T> rotate_z(T angle);
694 
702 template <class T>
703 [[nodiscard]] constexpr mat4<T> scale(const vec3<T>& v);
704 
713 template <class T, std::size_t N, std::size_t M>
714 [[nodiscard]] constexpr matrix<T, N, M> sub(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept;
715 
724 template <class T, std::size_t N, std::size_t M>
725 [[nodiscard]] constexpr matrix<T, N, M> sub(const matrix<T, N, M>& a, T b) noexcept;
726 
735 template <class T, std::size_t N, std::size_t M>
736 [[nodiscard]] constexpr matrix<T, N, M> sub(T a, const matrix<T, N, M>& b) noexcept;
737 
745 template <class T, std::size_t N>
746 [[nodiscard]] constexpr T trace(const matrix<T, N, N>& m) noexcept;
747 
755 template <class T>
756 [[nodiscard]] constexpr mat4<T> translate(const vec3<T>& v);
757 
765 template <class T, std::size_t N, std::size_t M>
766 [[nodiscard]] constexpr matrix<T, M, N> transpose(const matrix<T, N, M>& m) noexcept;
767 
769 template <class T, std::size_t N, std::size_t M, std::size_t... I>
770 inline constexpr matrix<T, N, M> add(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
771 {
772  return {(a[I] + b[I]) ...};
773 }
774 
775 template <class T, std::size_t N, std::size_t M>
776 constexpr matrix<T, N, M> add(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
777 {
778  return add(a, b, std::make_index_sequence<N>{});
779 }
780 
782 template <class T, std::size_t N, std::size_t M, std::size_t... I>
783 inline constexpr matrix<T, N, M> add(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
784 {
785  return {(a[I] + b) ...};
786 }
787 
788 template <class T, std::size_t N, std::size_t M>
789 constexpr matrix<T, N, M> add(const matrix<T, N, M>& a, T b) noexcept
790 {
791  return add(a, b, std::make_index_sequence<N>{});
792 }
793 
795 template <class T>
796 constexpr T determinant(const matrix<T, 2, 2>& m) noexcept
797 {
798  return
799  m[0][0] * m[1][1] -
800  m[0][1] * m[1][0];
801 }
802 
804 template <class T>
805 constexpr T determinant(const mat3<T>& m) noexcept
806 {
807  return
808  m[0][0] * m[1][1] * m[2][2] +
809  m[0][1] * m[1][2] * m[2][0] +
810  m[0][2] * m[1][0] * m[2][1] -
811  m[0][0] * m[1][2] * m[2][1] -
812  m[0][1] * m[1][0] * m[2][2] -
813  m[0][2] * m[1][1] * m[2][0];
814 }
815 
817 template <class T>
818 constexpr T determinant(const matrix<T, 4, 4>& m) noexcept
819 {
820  return
821  m[0][3] * m[1][2] * m[2][1] * m[3][0] - m[0][2] * m[1][3] * m[2][1] * m[3][0] -
822  m[0][3] * m[1][1] * m[2][2] * m[3][0] + m[0][1] * m[1][3] * m[2][2] * m[3][0] +
823  m[0][2] * m[1][1] * m[2][3] * m[3][0] - m[0][1] * m[1][2] * m[2][3] * m[3][0] -
824  m[0][3] * m[1][2] * m[2][0] * m[3][1] + m[0][2] * m[1][3] * m[2][0] * m[3][1] +
825  m[0][3] * m[1][0] * m[2][2] * m[3][1] - m[0][0] * m[1][3] * m[2][2] * m[3][1] -
826  m[0][2] * m[1][0] * m[2][3] * m[3][1] + m[0][0] * m[1][2] * m[2][3] * m[3][1] +
827  m[0][3] * m[1][1] * m[2][0] * m[3][2] - m[0][1] * m[1][3] * m[2][0] * m[3][2] -
828  m[0][3] * m[1][0] * m[2][1] * m[3][2] + m[0][0] * m[1][3] * m[2][1] * m[3][2] +
829  m[0][1] * m[1][0] * m[2][3] * m[3][2] - m[0][0] * m[1][1] * m[2][3] * m[3][2] -
830  m[0][2] * m[1][1] * m[2][0] * m[3][3] + m[0][1] * m[1][2] * m[2][0] * m[3][3] +
831  m[0][2] * m[1][0] * m[2][1] * m[3][3] - m[0][0] * m[1][2] * m[2][1] * m[3][3] -
832  m[0][1] * m[1][0] * m[2][2] * m[3][3] + m[0][0] * m[1][1] * m[2][2] * m[3][3];
833 }
834 
836 template <class T, std::size_t N, std::size_t M, std::size_t... I>
837 inline constexpr matrix<T, N, M> componentwise_mul(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
838 {
839  return {(a[I] * b[I]) ...};
840 }
841 
842 template <class T, std::size_t N, std::size_t M>
843 constexpr matrix<T, N, M> componentwise_mul(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
844 {
845  return componentwise_mul(a, b, std::make_index_sequence<N>{});
846 }
847 
849 template <class T, std::size_t N, std::size_t M, std::size_t... I>
850 inline constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
851 {
852  return {(a[I] / b[I]) ...};
853 }
854 
855 template <class T, std::size_t N, std::size_t M>
856 constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
857 {
858  return div(a, b, std::make_index_sequence<N>{});
859 }
860 
862 template <class T, std::size_t N, std::size_t M, std::size_t... I>
863 inline constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
864 {
865  return {(a[I] / b) ...};
866 }
867 
868 template <class T, std::size_t N, std::size_t M>
869 constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, T b) noexcept
870 {
871  return div(a, b, std::make_index_sequence<N>{});
872 }
873 
875 template <class T, std::size_t N, std::size_t M, std::size_t... I>
876 inline constexpr matrix<T, N, M> div(T a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
877 {
878  return {(a / b[I]) ...};
879 }
880 
881 template <class T, std::size_t N, std::size_t M>
882 constexpr matrix<T, N, M> div(T a, const matrix<T, N, M>& b) noexcept
883 {
884  return div(a, b, std::make_index_sequence<N>{});
885 }
886 
887 template<std::size_t I, class T, std::size_t N, std::size_t M>
888 inline constexpr typename matrix<T, N, M>::column_vector_type& get(matrix<T, N, M>& m) noexcept
889 {
890  static_assert(I < N);
891  return m.columns[I];
892 }
893 
894 template<std::size_t I, class T, std::size_t N, std::size_t M>
895 inline constexpr typename matrix<T, N, M>::column_vector_type&& get(matrix<T, N, M>&& m) noexcept
896 {
897  static_assert(I < N);
898  return std::move(m.columns[I]);
899 }
900 
901 template<std::size_t I, class T, std::size_t N, std::size_t M>
902 inline constexpr const typename matrix<T, N, M>::column_vector_type& get(const matrix<T, N, M>& m) noexcept
903 {
904  static_assert(I < N);
905  return m.columns[I];
906 }
907 
908 template<std::size_t I, class T, std::size_t N, std::size_t M>
909 inline constexpr const typename matrix<T, N, M>::column_vector_type&& get(const matrix<T, N, M>&& m) noexcept
910 {
911  static_assert(I < N);
912  return std::move(m.columns[I]);
913 }
914 
916 template <class T>
917 constexpr matrix<T, 2, 2> inverse(const matrix<T, 2, 2>& m) noexcept
918 {
919  const T inv_det = T{1} / determinant(m);
920 
921  return
922  {
923  m[1][1] * inv_det,
924  -m[0][1] * inv_det,
925  -m[1][0] * inv_det,
926  m[0][0] * inv_det
927  };
928 }
929 
931 template <class T>
932 constexpr mat3<T> inverse(const mat3<T>& m) noexcept
933 {
934  const T inv_det = T{1} / determinant(m);
935 
936  return
937  {
938  (m[1][1] * m[2][2] - m[1][2] * m[2][1]) * inv_det,
939  (m[0][2] * m[2][1] - m[0][1] * m[2][2]) * inv_det,
940  (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * inv_det,
941 
942  (m[1][2] * m[2][0] - m[1][0] * m[2][2]) * inv_det,
943  (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * inv_det,
944  (m[0][2] * m[1][0] - m[0][0] * m[1][2]) * inv_det,
945 
946  (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * inv_det,
947  (m[0][1] * m[2][0] - m[0][0] * m[2][1]) * inv_det,
948  (m[0][0] * m[1][1] - m[0][1] * m[1][0]) * inv_det
949  };
950 }
951 
953 template <class T>
954 constexpr matrix<T, 4, 4> inverse(const matrix<T, 4, 4>& m) noexcept
955 {
956  const T inv_det = T{1} / determinant(m);
957 
958  return
959  {
960  (m[1][2] * m[2][3] * m[3][1] - m[1][3] * m[2][2] * m[3][1] + m[1][3] * m[2][1] * m[3][2] - m[1][1] * m[2][3] * m[3][2] - m[1][2] * m[2][1] * m[3][3] + m[1][1] * m[2][2] * m[3][3]) * inv_det,
961  (m[0][3] * m[2][2] * m[3][1] - m[0][2] * m[2][3] * m[3][1] - m[0][3] * m[2][1] * m[3][2] + m[0][1] * m[2][3] * m[3][2] + m[0][2] * m[2][1] * m[3][3] - m[0][1] * m[2][2] * m[3][3]) * inv_det,
962  (m[0][2] * m[1][3] * m[3][1] - m[0][3] * m[1][2] * m[3][1] + m[0][3] * m[1][1] * m[3][2] - m[0][1] * m[1][3] * m[3][2] - m[0][2] * m[1][1] * m[3][3] + m[0][1] * m[1][2] * m[3][3]) * inv_det,
963  (m[0][3] * m[1][2] * m[2][1] - m[0][2] * m[1][3] * m[2][1] - m[0][3] * m[1][1] * m[2][2] + m[0][1] * m[1][3] * m[2][2] + m[0][2] * m[1][1] * m[2][3] - m[0][1] * m[1][2] * m[2][3]) * inv_det,
964 
965  (m[1][3] * m[2][2] * m[3][0] - m[1][2] * m[2][3] * m[3][0] - m[1][3] * m[2][0] * m[3][2] + m[1][0] * m[2][3] * m[3][2] + m[1][2] * m[2][0] * m[3][3] - m[1][0] * m[2][2] * m[3][3]) * inv_det,
966  (m[0][2] * m[2][3] * m[3][0] - m[0][3] * m[2][2] * m[3][0] + m[0][3] * m[2][0] * m[3][2] - m[0][0] * m[2][3] * m[3][2] - m[0][2] * m[2][0] * m[3][3] + m[0][0] * m[2][2] * m[3][3]) * inv_det,
967  (m[0][3] * m[1][2] * m[3][0] - m[0][2] * m[1][3] * m[3][0] - m[0][3] * m[1][0] * m[3][2] + m[0][0] * m[1][3] * m[3][2] + m[0][2] * m[1][0] * m[3][3] - m[0][0] * m[1][2] * m[3][3]) * inv_det,
968  (m[0][2] * m[1][3] * m[2][0] - m[0][3] * m[1][2] * m[2][0] + m[0][3] * m[1][0] * m[2][2] - m[0][0] * m[1][3] * m[2][2] - m[0][2] * m[1][0] * m[2][3] + m[0][0] * m[1][2] * m[2][3]) * inv_det,
969 
970  (m[1][1] * m[2][3] * m[3][0] - m[1][3] * m[2][1] * m[3][0] + m[1][3] * m[2][0] * m[3][1] - m[1][0] * m[2][3] * m[3][1] - m[1][1] * m[2][0] * m[3][3] + m[1][0] * m[2][1] * m[3][3]) * inv_det,
971  (m[0][3] * m[2][1] * m[3][0] - m[0][1] * m[2][3] * m[3][0] - m[0][3] * m[2][0] * m[3][1] + m[0][0] * m[2][3] * m[3][1] + m[0][1] * m[2][0] * m[3][3] - m[0][0] * m[2][1] * m[3][3]) * inv_det,
972  (m[0][1] * m[1][3] * m[3][0] - m[0][3] * m[1][1] * m[3][0] + m[0][3] * m[1][0] * m[3][1] - m[0][0] * m[1][3] * m[3][1] - m[0][1] * m[1][0] * m[3][3] + m[0][0] * m[1][1] * m[3][3]) * inv_det,
973  (m[0][3] * m[1][1] * m[2][0] - m[0][1] * m[1][3] * m[2][0] - m[0][3] * m[1][0] * m[2][1] + m[0][0] * m[1][3] * m[2][1] + m[0][1] * m[1][0] * m[2][3] - m[0][0] * m[1][1] * m[2][3]) * inv_det,
974 
975  (m[1][2] * m[2][1] * m[3][0] - m[1][1] * m[2][2] * m[3][0] - m[1][2] * m[2][0] * m[3][1] + m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2] - m[1][0] * m[2][1] * m[3][2]) * inv_det,
976  (m[0][1] * m[2][2] * m[3][0] - m[0][2] * m[2][1] * m[3][0] + m[0][2] * m[2][0] * m[3][1] - m[0][0] * m[2][2] * m[3][1] - m[0][1] * m[2][0] * m[3][2] + m[0][0] * m[2][1] * m[3][2]) * inv_det,
977  (m[0][2] * m[1][1] * m[3][0] - m[0][1] * m[1][2] * m[3][0] - m[0][2] * m[1][0] * m[3][1] + m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2] - m[0][0] * m[1][1] * m[3][2]) * inv_det,
978  (m[0][1] * m[1][2] * m[2][0] - m[0][2] * m[1][1] * m[2][0] + m[0][2] * m[1][0] * m[2][1] - m[0][0] * m[1][2] * m[2][1] - m[0][1] * m[1][0] * m[2][2] + m[0][0] * m[1][1] * m[2][2]) * inv_det
979  };
980 }
981 
982 template <class T>
983 constexpr mat4<T> look_at_rh(const vec3<T>& position, const vec3<T>& target, const vec3<T>& up)
984 {
985  const auto f = normalize(sub(target, position));
986  const auto r = normalize(cross(f, up));
987  const auto u = cross(r, f);
988  const auto t = vec3<T>{dot(position, r), dot(position, u), dot(position, f)};
989 
990  return
991  {{
992  { r.x(), u.x(), -f.x(), T{0}},
993  { r.y(), u.y(), -f.y(), T{0}},
994  { r.z(), u.z(), -f.z(), T{0}},
995  {-t.x(), -t.y(), t.z(), T{1}}
996  }};
997 }
998 
999 template <class T>
1000 constexpr std::tuple<mat4<T>, mat4<T>> look_at_rh_inv(const vec3<T>& position, const vec3<T>& target, const vec3<T>& up)
1001 {
1002  const auto f = normalize(sub(target, position));
1003  const auto r = normalize(cross(f, up));
1004  const auto u = cross(r, f);
1005 
1006  return
1007  {
1008  mat4<T>
1009  {{
1010  { r.x(), u.x(), -f.x(), T{0}},
1011  { r.y(), u.y(), -f.y(), T{0}},
1012  { r.z(), u.z(), -f.z(), T{0}},
1013  {-dot(position, r), -dot(position, u), dot(position, f), T{1}}
1014  }},
1015 
1016  mat4<T>
1017  {{
1018  { r.x(), r.y(), r.z(), T{0}},
1019  { u.x(), u.y(), u.z(), T{0}},
1020  {-f.x(), -f.y(), -f.z(), T{0}},
1021  {position.x(), position.y(), position.z(), T{1}}
1022  }}
1023  };
1024 }
1025 
1026 template <class T, std::size_t N, std::size_t M, std::size_t P>
1027 constexpr matrix<T, P, M> mul(const matrix<T, N, M>& a, const matrix<T, P, N>& b) noexcept
1028 {
1030 
1031  for (std::size_t i = 0; i < P; ++i)
1032  {
1033  for (std::size_t j = 0; j < M; ++j)
1034  {
1035  for (std::size_t k = 0; k < N; ++k)
1036  {
1037  c[i][j] += a[k][j] * b[i][k];
1038  }
1039  }
1040  }
1041 
1042  return c;
1043 }
1044 
1046 template <class T, std::size_t N, std::size_t M, std::size_t... I>
1047 inline constexpr matrix<T, N, M> mul(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
1048 {
1049  return {(a[I] * b) ...};
1050 }
1051 
1052 template <class T, std::size_t N, std::size_t M>
1053 constexpr matrix<T, N, M> mul(const matrix<T, N, M>& a, T b) noexcept
1054 {
1055  return mul(a, b, std::make_index_sequence<N>{});
1056 }
1057 
1059 template <class T, std::size_t N, std::size_t M, std::size_t... I>
1060 inline constexpr typename matrix<T, N, M>::column_vector_type mul(const matrix<T, N, M>& a, const typename matrix<T, N, M>::row_vector_type& b, std::index_sequence<I...>) noexcept
1061 {
1062  return ((a[I] * b[I]) + ...);
1063 }
1064 
1065 template <class T, std::size_t N, std::size_t M>
1066 constexpr typename matrix<T, N, M>::column_vector_type mul(const matrix<T, N, M>& a, const typename matrix<T, N, M>::row_vector_type& b) noexcept
1067 {
1068  return mul(a, b, std::make_index_sequence<N>{});
1069 }
1070 
1072 template <class T, std::size_t N, std::size_t M, std::size_t... I>
1073 inline constexpr typename matrix<T, N, M>::row_vector_type mul(const typename matrix<T, N, M>::column_vector_type& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
1074 {
1075  return {dot(a, b[I]) ...};
1076 }
1077 
1078 template <class T, std::size_t N, std::size_t M>
1079 constexpr typename matrix<T, N, M>::row_vector_type mul(const typename matrix<T, N, M>::column_vector_type& a, const matrix<T, N, M>& b) noexcept
1080 {
1081  return mul(a, b, std::make_index_sequence<N>{});
1082 }
1083 
1084 template <class T>
1086 {
1087  const T c = std::cos(angle);
1088  const T s = std::sin(angle);
1089  const vector<T, 3> temp = mul(axis, T{1} - c);
1090 
1091  mat3<T> rotation;
1092  rotation[0][0] = axis[0] * temp[0] + c;
1093  rotation[0][1] = axis[1] * temp[0] + axis[2] * s;
1094  rotation[0][2] = axis[2] * temp[0] - axis[1] * s;
1095  rotation[1][0] = axis[0] * temp[1] - axis[2] * s;
1096  rotation[1][1] = axis[1] * temp[1] + c;
1097  rotation[1][2] = axis[2] * temp[1] + axis[0] * s;
1098  rotation[2][0] = axis[0] * temp[2] + axis[1] * s;
1099  rotation[2][1] = axis[1] * temp[2] - axis[0] * s;
1100  rotation[2][2] = axis[2] * temp[2] + c;
1101 
1102  return rotation;
1103 }
1104 
1105 template <class T>
1107 {
1108  const T c = std::cos(angle);
1109  const T s = std::sin(angle);
1110 
1111  return mat3<T>
1112  {
1113  T{1}, T{0}, T{0},
1114  T{0}, c, s,
1115  T{0}, -s, c
1116  };
1117 }
1118 
1119 template <class T>
1121 {
1122  const T c = std::cos(angle);
1123  const T s = std::sin(angle);
1124 
1125  return mat3<T>
1126  {
1127  c, T{0}, -s,
1128  T{0}, T{1}, T{0},
1129  s, T{0}, c
1130  };
1131 }
1132 
1133 template <class T>
1135 {
1136  const T c = std::cos(angle);
1137  const T s = std::sin(angle);
1138 
1139  return mat3<T>
1140  {
1141  c, s, T{0},
1142  -s, c, T{0},
1143  T{0}, T{0}, T{1}
1144  };
1145 }
1146 
1147 template <class T>
1148 constexpr mat4<T> scale(const vec3<T>& v)
1149 {
1150  return
1151  {{
1152  {v[0], T{0}, T{0}, T{0}},
1153  {T{0}, v[1], T{0}, T{0}},
1154  {T{0}, T{0}, v[2], T{0}},
1155  {T{0}, T{0}, T{0}, T{1}}
1156  }};
1157 }
1158 
1160 template <class T, std::size_t N, std::size_t M, std::size_t... I>
1161 inline constexpr matrix<T, N, M> sub(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
1162 {
1163  return {(a[I] - b[I]) ...};
1164 }
1165 
1166 template <class T, std::size_t N, std::size_t M>
1167 constexpr matrix<T, N, M> sub(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
1168 {
1169  return sub(a, b, std::make_index_sequence<N>{});
1170 }
1171 
1173 template <class T, std::size_t N, std::size_t M, std::size_t... I>
1174 inline constexpr matrix<T, N, M> sub(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
1175 {
1176  return {(a[I] - b) ...};
1177 }
1178 
1179 template <class T, std::size_t N, std::size_t M>
1180 constexpr matrix<T, N, M> sub(const matrix<T, N, M>& a, T b) noexcept
1181 {
1182  return sub(a, b, std::make_index_sequence<N>{});
1183 }
1184 
1186 template <class T, std::size_t N, std::size_t M, std::size_t... I>
1187 inline constexpr matrix<T, N, M> sub(T a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
1188 {
1189  return {(a - b[I]) ...};
1190 }
1191 
1192 template <class T, std::size_t N, std::size_t M>
1193 constexpr matrix<T, N, M> sub(T a, const matrix<T, N, M>& b) noexcept
1194 {
1195  return sub(a, b, std::make_index_sequence<N>{});
1196 }
1197 
1199 template <class T, std::size_t N, std::size_t... I>
1200 inline constexpr T trace(const matrix<T, N, N>& m, std::index_sequence<I...>) noexcept
1201 {
1202  return ((m[I][I]) + ...);
1203 }
1204 
1205 template <class T, std::size_t N>
1206 constexpr T trace(const matrix<T, N, N>& m) noexcept
1207 {
1208  return trace(m, std::make_index_sequence<N>{});
1209 }
1210 
1211 template <class T>
1212 constexpr mat4<T> translate(const vec3<T>& v)
1213 {
1214  return
1215  {{
1216  {T{1}, T{0}, T{0}, T{0}},
1217  {T{0}, T{1}, T{0}, T{0}},
1218  {T{0}, T{0}, T{1}, T{0}},
1219  {v[0], v[1], v[2], T{1}}
1220  }};
1221 }
1222 
1224 template <class T, std::size_t N, std::size_t M, std::size_t... I>
1225 inline constexpr typename matrix<T, M, N>::column_vector_type transpose_column(const matrix<T, N, M>& m, std::size_t i, std::index_sequence<I...>) noexcept
1226 {
1227  return {m[I][i] ...};
1228 }
1229 
1231 template <class T, std::size_t N, std::size_t M, std::size_t... I>
1232 inline constexpr matrix<T, M, N> transpose(const matrix<T, N, M>& m, std::index_sequence<I...>) noexcept
1233 {
1234  return {transpose_column(m, I, std::make_index_sequence<N>{}) ...};
1235 }
1236 
1237 template <class T, std::size_t N, std::size_t M>
1238 constexpr matrix<T, M, N> transpose(const matrix<T, N, M>& m) noexcept
1239 {
1240  return transpose(m, std::make_index_sequence<M>{});
1241 }
1242 
1243 namespace operators {
1244 
1246 template <class T, std::size_t N, std::size_t M>
1247 inline constexpr matrix<T, N, M> operator+(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
1248 {
1249  return add(a, b);
1250 }
1251 
1254 template <class T, std::size_t N, std::size_t M>
1255 inline constexpr matrix<T, N, M> operator+(const matrix<T, N, M>& a, T b) noexcept
1256 {
1257  return add(a, b);
1258 }
1259 template <class T, std::size_t N, std::size_t M>
1260 inline constexpr matrix<T, N, M> operator+(T a, const matrix<T, N, M>& b) noexcept
1261 {
1262  return add(b, a);
1263 }
1265 
1267 template <class T, std::size_t N, std::size_t M>
1268 inline constexpr matrix<T, N, M> operator/(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
1269 {
1270  return div(a, b);
1271 }
1272 
1274 template <class T, std::size_t N, std::size_t M>
1275 inline constexpr matrix<T, N, M> operator/(const matrix<T, N, M>& a, T b) noexcept
1276 {
1277  return div(a, b);
1278 }
1279 
1281 template <class T, std::size_t N, std::size_t M>
1282 inline constexpr matrix<T, N, M> operator/(T a, const matrix<T, N, M>& b) noexcept
1283 {
1284  return div(a, b);
1285 }
1286 
1288 template <class T, std::size_t N, std::size_t M, std::size_t P>
1289 inline constexpr matrix<T, P, M> operator*(const matrix<T, N, M>& a, const matrix<T, P, N>& b) noexcept
1290 {
1291  return mul(a, b);
1292 }
1293 
1296 template <class T, std::size_t N, std::size_t M>
1297 inline constexpr matrix<T, N, M> operator*(const matrix<T, N, M>& a, T b) noexcept
1298 {
1299  return mul(a, b);
1300 }
1301 template <class T, std::size_t N, std::size_t M>
1302 inline constexpr matrix<T, N, M> operator*(T a, const matrix<T, N, M>& b) noexcept
1303 {
1304  return mul(b, a);
1305 }
1307 
1309 template <class T, std::size_t N, std::size_t M>
1310 inline constexpr typename matrix<T, N, M>::column_vector_type operator*(const matrix<T, N, M>& a, const typename matrix<T, N, M>::row_vector_type& b) noexcept
1311 {
1312  return mul(a, b);
1313 }
1314 
1316 template <class T, std::size_t N, std::size_t M>
1317 inline constexpr typename matrix<T, N, M>::row_vector_type operator*(const typename matrix<T, N, M>::column_vector_type& a, const matrix<T, N, M>& b) noexcept
1318 {
1319  return mul(a, b);
1320 }
1321 
1323 template <class T, std::size_t N, std::size_t M>
1324 inline constexpr matrix<T, N, M> operator-(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
1325 {
1326  return sub(a, b);
1327 }
1328 
1330 template <class T, std::size_t N, std::size_t M>
1331 inline constexpr matrix<T, N, M> operator-(const matrix<T, N, M>& a, T b) noexcept
1332 {
1333  return sub(a, b);
1334 }
1335 
1337 template <class T, std::size_t N, std::size_t M>
1338 inline constexpr matrix<T, N, M> operator-(T a, const matrix<T, N, M>& b) noexcept
1339 {
1340  return sub(a, b);
1341 }
1342 
1352 template <class T, std::size_t N, std::size_t M>
1353 inline constexpr matrix<T, N, M>& operator+=(matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
1354 {
1355  return (a = a + b);
1356 }
1357 template <class T, std::size_t N, std::size_t M>
1358 inline constexpr matrix<T, N, M>& operator+=(matrix<T, N, M>& a, T b) noexcept
1359 {
1360  return (a = a + b);
1361 }
1363 
1373 template <class T, std::size_t N, std::size_t M>
1374 inline constexpr matrix<T, N, M>& operator-=(matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
1375 {
1376  return (a = a - b);
1377 }
1378 template <class T, std::size_t N, std::size_t M>
1379 inline constexpr matrix<T, N, M>& operator-=(matrix<T, N, M>& a, T b) noexcept
1380 {
1381  return (a = a - b);
1382 }
1384 
1394 template <class T, std::size_t N>
1395 inline constexpr matrix<T, N, N>& operator*=(matrix<T, N, N>& a, const matrix<T, N, N>& b) noexcept
1396 {
1397  return (a = a * b);
1398 }
1399 template <class T, std::size_t N, std::size_t M>
1400 inline constexpr matrix<T, N, M>& operator*=(matrix<T, N, M>& a, T b) noexcept
1401 {
1402  return (a = a * b);
1403 }
1405 
1415 template <class T, std::size_t N, std::size_t M>
1416 inline constexpr matrix<T, N, M>& operator/=(matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
1417 {
1418  return (a = a / b);
1419 }
1420 template <class T, std::size_t N, std::size_t M>
1421 inline constexpr matrix<T, N, M>& operator/=(matrix<T, N, M>& a, T b) noexcept
1422 {
1423  return (a = a / b);
1424 }
1426 
1427 } // namespace operators
1428 
1429 } // namespace math
1430 
1431 // Bring matrix operators into global namespace
1432 using namespace math::operators;
1433 
1434 namespace std
1435 {
1443  template<class T, std::size_t N, std::size_t M>
1444  struct tuple_size<math::matrix<T, N, M>>
1445  {
1447  static constexpr std::size_t value = math::matrix<T, N, M>::column_count;
1448  };
1449 
1458  template<std::size_t I, class T, std::size_t N, std::size_t M>
1459  struct tuple_element<I, math::matrix<T, N, M>>
1460  {
1463  };
1464 
1472  template <class T, std::size_t N, std::size_t M>
1473  struct formatter<math::matrix<T, N, M>>: formatter<math::vector<T, M>>
1474  {
1475  auto format(const math::matrix<T, N, M>& t, format_context& fc) const
1476  {
1477  auto&& out = fc.out();
1478  format_to(out, "{{");
1479 
1480  for (std::size_t i = 0; i < N; ++i)
1481  {
1482  formatter<math::vector<T, M>>::format(t[i], fc);
1483  if (i < N - 1)
1484  {
1485  format_to(out, ", ");
1486  }
1487  }
1488 
1489  return format_to(out, "}}");
1490  }
1491  };
1492 }
1493 
1494 // Ensure matrices are POD types
1495 static_assert(std::is_standard_layout_v<math::fmat3>);
1496 static_assert(std::is_trivial_v<math::fmat3>);
1497 
1498 #endif // ANTKEEPER_MATH_MATRIX_HPP
T identity(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2)
Returns the percent identity between two proteins.
Definition: protein.hpp:63
@ a
Vertex A region.
@ b
Vertex B region.
format
Image and vertex formats.
Definition: format.hpp:29
dmat< 3, 3 > dmat3x3
n by m matrix of double-precision floating-point numbers.
dmat< 4, 4 > dmat4x4
n by m matrix of double-precision floating-point numbers.
fmat< 3, 3 > fmat3x3
n by m matrix of single-precision floating-point numbers.
dmat< 2, 2 > dmat2x2
n by m matrix of double-precision floating-point numbers.
fmat< 2, 2 > fmat2x2
n by m matrix of single-precision floating-point numbers.
fmat< 4, 4 > fmat4x4
n by m matrix of single-precision floating-point numbers.
Mathematical operators.
constexpr matrix< T, N, M > & operator/=(matrix< T, N, M > &a, T b) noexcept
Divides the first value by the second value and stores the result in the first value.
constexpr matrix< T, N, M > operator/(T a, const matrix< T, N, M > &b) noexcept
Divides a scalar by a matrix.
constexpr matrix< T, N, M > & operator-=(matrix< T, N, M > &a, T b) noexcept
Subtracts the first value by the second value and stores the result in the first value.
constexpr matrix< T, N, M > & operator*=(matrix< T, N, M > &a, T b) noexcept
Multiplies two values and stores the result in the first value.
constexpr matrix< T, N, M > operator+(T a, const matrix< T, N, M > &b) noexcept
constexpr matrix< T, N, M > operator-(T a, const matrix< T, N, M > &b) noexcept
Subtracts a matrix from a scalar.
constexpr matrix< T, N, M > & operator+=(matrix< T, N, M > &a, T b) noexcept
Adds two values and stores the result in the first value.
constexpr matrix< T, N, M >::row_vector_type operator*(const typename matrix< T, N, M >::column_vector_type &a, const matrix< T, N, M > &b) noexcept
Calculates the product of a column vector and a matrix.
Mathematical functions and data types.
Definition: angles.hpp:26
constexpr mat4< T > look_at_rh(const vec3< T > &position, const vec3< T > &target, const vec3< T > &up)
Constructs a right-handed viewing transformation matrix.
constexpr mat4< T > translate(const vec3< T > &v)
Constructs a translation matrix.
constexpr matrix< T, P, M > mul(const matrix< T, N, M > &a, const matrix< T, P, N > &b) noexcept
Multiplies two matrices.
T angle(const vector< T, N > &from, const vector< T, N > &to)
Calculates the angle between two direction vectors.
Definition: vector.hpp:1030
constexpr T trace(const matrix< T, N, N > &m) noexcept
Calculates the trace of a square matrix.
quaternion< T > normalize(const quaternion< T > &q)
Normalizes a quaternion.
Definition: quaternion.hpp:679
constexpr matrix< T, N, M > div(const matrix< T, N, M > &a, const matrix< T, N, M > &b) noexcept
Divides a matrix by a matrix.
constexpr std::tuple< mat4< T >, mat4< T > > look_at_rh_inv(const vec3< T > &position, const vec3< T > &target, const vec3< T > &up)
Constructs a right-handed viewing transformation matrix and its inverse.
constexpr matrix< T, N, M > add(const matrix< T, N, M > &a, const matrix< T, N, M > &b) noexcept
Adds two matrices.
quaternion< T > rotation(const vec3< T > &from, const vec3< T > &to, T tolerance=T{1e-6})
Constructs a quaternion representing the minimum rotation from one direction to another direction.
Definition: quaternion.hpp:691
constexpr mat4< T > scale(const vec3< T > &v)
Constructs a scale matrix.
mat3< T > rotate_y(T angle)
Produces a matrix which rotates Cartesian coordinates about the y-axis by a given angle.
constexpr T determinant(const matrix< T, N, N > &m) noexcept
Calculates the determinant of a square matrix.
mat3< T > rotate_z(T angle)
Produces a matrix which rotates Cartesian coordinates about the z-axis by a given angle.
constexpr matrix< T, N, M > sub(const matrix< T, N, M > &a, const matrix< T, N, M > &b) noexcept
Subtracts a matrix from another matrix.
mat3< T > rotate_x(T angle)
Produces a matrix which rotates Cartesian coordinates about the x-axis by a given angle.
constexpr matrix< T, N, M >::column_vector_type & get(matrix< T, N, M > &m) noexcept
Extracts the Ith column from a matrix.
constexpr vector< T, 3 > cross(const vector< T, 3 > &x, const vector< T, 3 > &y) noexcept
Calculates the cross product of two vectors.
Definition: vector.hpp:1095
constexpr matrix< T, M, N > transpose(const matrix< T, N, M > &m) noexcept
Calculates the transpose of a matrix.
mat3< T > rotate(T angle, const vector< T, 3 > &axis)
Constructs a rotation matrix.
constexpr matrix< T, N, M > componentwise_mul(const matrix< T, N, M > &a, const matrix< T, N, M > &b) noexcept
Performs a component-wise multiplication of two matrices.
constexpr T dot(const quaternion< T > &a, const quaternion< T > &b) noexcept
Calculates the dot product of two quaternions.
Definition: quaternion.hpp:572
constexpr matrix< T, N, N > inverse(const matrix< T, N, N > &m) noexcept
Calculates the inverse of a square matrix.
Text and typography.
Definition: bitmap-font.cpp:24
n by m column-major matrix.
Definition: math/matrix.hpp:44
static constexpr matrix identity() noexcept
Returns an identity matrix, with ones on the main diagonal and zeros elsewhere.
constexpr column_vector_type * begin() noexcept
Returns an iterator to the first column vector.
constexpr std::reverse_iterator< const column_vector_type * > crend() const noexcept
Returns a reverse iterator to the column vector following the last column vector of the reversed matr...
vector< element_type, column_count > row_vector_type
Matrix row vector data type.
Definition: math/matrix.hpp:61
constexpr const column_vector_type * begin() const noexcept
Returns an iterator to the first column vector.
constexpr const element_type * data() const noexcept
Returns a pointer to the first element.
constexpr const column_vector_type & back() const noexcept
Returns a reference to the last column vector.
static constexpr std::size_t row_count
Number of rows.
Definition: math/matrix.hpp:52
constexpr const column_vector_type * cbegin() const noexcept
Returns an iterator to the first column vector.
constexpr const column_vector_type * end() const noexcept
Returns an iterator to the column vector following the last column vector.
static constexpr std::size_t column_count
Number of columns.
Definition: math/matrix.hpp:49
constexpr T & element(std::size_t i) noexcept
Returns a reference to the element at a given column-major index.
static constexpr std::size_t element_count
Number of elements.
Definition: math/matrix.hpp:55
constexpr element_type * data() noexcept
Returns a pointer to the first element.
constexpr std::reverse_iterator< const column_vector_type * > crbegin() const noexcept
Returns a reverse iterator to the first column vector of the reversed matrix.
constexpr const column_vector_type & front() const noexcept
Returns a reference to the first column vector.
constexpr const T & element(std::size_t i) const noexcept
Returns a reference to the element at a given column-major index.
constexpr const column_vector_type * cend() const noexcept
Returns an iterator to the column vector following the last column vector.
column_vector_type columns[column_count]
Array of matrix column vectors.
Definition: math/matrix.hpp:64
constexpr std::reverse_iterator< const column_vector_type * > rend() const noexcept
Returns a reverse iterator to the column vector following the last column vector of the reversed matr...
constexpr column_vector_type & operator[](std::size_t i) noexcept
Returns a reference to the column vector at a given index.
static constexpr matrix zero() noexcept
Returns a zero matrix, where every element is equal to zero.
constexpr column_vector_type * end() noexcept
Returns an iterator to the column vector following the last column vector.
constexpr const column_vector_type & column(std::size_t i) const noexcept
Returns a reference to the column vector at a given index.
constexpr std::reverse_iterator< const column_vector_type * > rbegin() const noexcept
Returns a reverse iterator to the first column vector of the reversed matrix.
constexpr std::reverse_iterator< column_vector_type * > rend() noexcept
Returns a reverse iterator to the column vector following the last column vector of the reversed matr...
static constexpr matrix one() noexcept
Returns a matrix of ones, where every element is equal to one.
vector< element_type, row_count > column_vector_type
Matrix column vector data type.
Definition: math/matrix.hpp:58
T element_type
Element type.
Definition: math/matrix.hpp:46
constexpr column_vector_type & front() noexcept
Returns a reference to the first column vector.
constexpr const column_vector_type & operator[](std::size_t i) const noexcept
Returns a reference to the column vector at a given index.
constexpr column_vector_type & column(std::size_t i) noexcept
Returns a reference to the column vector at a given index.
constexpr std::reverse_iterator< column_vector_type * > rbegin() noexcept
Returns a reverse iterator to the first column vector of the reversed matrix.
constexpr std::size_t size() const noexcept
Returns the number of elements in the matrix.
constexpr column_vector_type & back() noexcept
Returns a reference to the last column vector.
static constexpr vector one() noexcept
Returns a vector of ones, where every element is equal to one.
Definition: vector.hpp:324
auto format(const math::matrix< T, N, M > &t, format_context &fc) const