💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1241 lines
36 KiB

  1. /*
  2. * Copyright (C) 2021 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. #ifndef ANTKEEPER_MATH_MATRIX_HPP
  20. #define ANTKEEPER_MATH_MATRIX_HPP
  21. #include "math/vector.hpp"
  22. #include <cstddef>
  23. #include <istream>
  24. #include <iterator>
  25. #include <ostream>
  26. #include <type_traits>
  27. #include <utility>
  28. namespace math {
  29. /**
  30. * *n* by *m* column-major matrix.
  31. *
  32. * @tparam T Matrix element data type.
  33. * @tparam N Number of columns.
  34. * @tparam M Number of rows.
  35. *
  36. * @see https://en.wikipedia.org/wiki/Row-_and_column-major_order
  37. */
  38. template <typename T, std::size_t N, std::size_t M>
  39. struct matrix
  40. {
  41. /// Matrix element data type.
  42. typedef T element_type;
  43. /// Number of matrix columns.
  44. static constexpr std::size_t column_count = N;
  45. /// Number of matrix rows.
  46. static constexpr std::size_t row_count = M;
  47. /// Number of matrix elements.
  48. static constexpr std::size_t element_count = column_count * row_count;
  49. /// Matrix column vector data type.
  50. typedef vector<element_type, row_count> column_vector_type;
  51. /// Matrix row vector data type.
  52. typedef vector<element_type, column_count> row_vector_type;
  53. /// Array of matrix column vectors.
  54. column_vector_type columns[column_count];
  55. /**
  56. * Returns a reference to the column vector at a given index.
  57. *
  58. * @param i Index of a column vector.
  59. *
  60. * @return Reference to the column vector at index @p i.
  61. */
  62. /// @{
  63. constexpr inline column_vector_type& operator[](std::size_t i) noexcept
  64. {
  65. return columns[i];
  66. }
  67. constexpr inline const column_vector_type& operator[](std::size_t i) const noexcept
  68. {
  69. return columns[i];
  70. }
  71. constexpr inline column_vector_type& column(std::size_t i) noexcept
  72. {
  73. return columns[i];
  74. }
  75. constexpr inline const column_vector_type& column(std::size_t i) const noexcept
  76. {
  77. return columns[i];
  78. }
  79. /// @}
  80. /**
  81. * Returns a reference to the element at a given column-major index.
  82. *
  83. * @param i Column-major index of a matrix element.
  84. *
  85. * @return Reference to the element at column-major index @p i.
  86. */
  87. /// @{
  88. constexpr inline T& element(std::size_t i) noexcept
  89. {
  90. return columns[i / row_count][i % row_count];
  91. }
  92. constexpr inline const T& element(std::size_t i) const noexcept
  93. {
  94. return columns[i / row_count][i % row_count];
  95. }
  96. /// @}
  97. /// Returns a reference to the first column vector.
  98. /// @{
  99. constexpr inline column_vector_type& front() noexcept
  100. {
  101. return columns[0];
  102. }
  103. constexpr inline const column_vector_type& front() const noexcept
  104. {
  105. return columns[0];
  106. }
  107. /// @}
  108. /// Returns a reference to the last column vector.
  109. /// @{
  110. constexpr inline column_vector_type& back() noexcept
  111. {
  112. return elements[column_count - 1];
  113. }
  114. constexpr inline const column_vector_type& back() const noexcept
  115. {
  116. return elements[column_count - 1];
  117. }
  118. /// @}
  119. /**
  120. * Returns a pointer to the first element.
  121. *
  122. * @warning If matrix::element_type is not a POD type, elements may not be stored contiguously.
  123. */
  124. /// @{
  125. constexpr inline element_type* data() noexcept
  126. {
  127. return &columns[0][0];
  128. };
  129. constexpr inline const element_type* data() const noexcept
  130. {
  131. return &columns[0][0];
  132. };
  133. /// @}
  134. /// Returns an iterator to the first column vector.
  135. /// @{
  136. constexpr inline column_vector_type* begin() noexcept
  137. {
  138. return columns;
  139. }
  140. constexpr inline const column_vector_type* begin() const noexcept
  141. {
  142. return columns;
  143. }
  144. constexpr inline const column_vector_type* cbegin() const noexcept
  145. {
  146. return columns;
  147. }
  148. /// @}
  149. /// Returns an iterator to the column vector following the last column vector.
  150. /// @{
  151. constexpr inline column_vector_type* end() noexcept
  152. {
  153. return columns + column_count;
  154. }
  155. constexpr inline const column_vector_type* end() const noexcept
  156. {
  157. return columns + column_count;
  158. }
  159. constexpr inline const column_vector_type* cend() const noexcept
  160. {
  161. return columns + column_count;
  162. }
  163. /// @}
  164. /// Returns a reverse iterator to the first column vector of the reversed matrix.
  165. /// @{
  166. constexpr inline std::reverse_iterator<column_vector_type*> rbegin() noexcept
  167. {
  168. return std::reverse_iterator<column_vector_type*>(columns + column_count);
  169. }
  170. constexpr inline std::reverse_iterator<const column_vector_type*> rbegin() const noexcept
  171. {
  172. return std::reverse_iterator<const column_vector_type*>(columns + column_count);
  173. }
  174. constexpr inline std::reverse_iterator<const column_vector_type*> crbegin() const noexcept
  175. {
  176. return std::reverse_iterator<const column_vector_type*>(columns + column_count);
  177. }
  178. /// @}
  179. /// Returns a reverse iterator to the column vector following the last column vector of the reversed matrix.
  180. /// @{
  181. constexpr inline std::reverse_iterator<column_vector_type*> rend() noexcept
  182. {
  183. return std::reverse_iterator<column_vector_type*>(columns);
  184. }
  185. constexpr inline std::reverse_iterator<const column_vector_type*> rend() const noexcept
  186. {
  187. return std::reverse_iterator<const column_vector_type*>(columns);
  188. }
  189. constexpr inline std::reverse_iterator<const column_vector_type*> crend() const noexcept
  190. {
  191. return std::reverse_iterator<const column_vector_type*>(columns);
  192. }
  193. /// @}
  194. /// Returns the number of elements in the matrix.
  195. constexpr inline std::size_t size() const noexcept
  196. {
  197. return element_count;
  198. };
  199. /// @private
  200. template <class U, std::size_t... I>
  201. constexpr inline matrix<U, N, M> type_cast(std::index_sequence<I...>) const noexcept
  202. {
  203. return {vector<U, M>(columns[I])...};
  204. }
  205. /**
  206. * Type-casts the elements of this matrix using `static_cast`.
  207. *
  208. * @tparam U Target element type.
  209. *
  210. * @return Matrix containing the type-casted elements.
  211. */
  212. template <class U>
  213. constexpr inline explicit operator matrix<U, N, M>() const noexcept
  214. {
  215. return type_cast<U>(std::make_index_sequence<N>{});
  216. }
  217. /// @private
  218. template <std::size_t P, std::size_t O, std::size_t... I>
  219. constexpr inline matrix<T, P, O> size_cast(std::index_sequence<I...>) const noexcept
  220. {
  221. if constexpr (O == M)
  222. return {((I < N) ? columns[I] : matrix<T, P, O>::identity()[I]) ...};
  223. else
  224. return {((I < N) ? vector<T, O>(columns[I]) : matrix<T, P, O>::identity()[I]) ...};
  225. }
  226. /**
  227. * Size-casts this matrix to a matrix with different dimensions. Casting to greater dimensions causes new elements to be set to identity matrix elements.
  228. *
  229. * @tparam P Target number of columns.
  230. * @tparam O Target number of rows.
  231. *
  232. * @return *p* by *o* matrix.
  233. */
  234. template <std::size_t P, std::size_t O>
  235. constexpr inline explicit operator matrix<T, P, O>() const noexcept
  236. {
  237. return size_cast<P, O>(std::make_index_sequence<P>{});
  238. }
  239. /// Returns a zero matrix, where every element is equal to zero.
  240. static constexpr matrix zero() noexcept
  241. {
  242. return {};
  243. }
  244. /// @private
  245. template <std::size_t... I>
  246. static constexpr inline matrix one(std::index_sequence<I...>) noexcept
  247. {
  248. //return {column_vector_type::one() ...};
  249. // MSVC bug workaround (I must be referenced for parameter pack expansion)
  250. return {(I ? column_vector_type::one() : column_vector_type::one()) ...};
  251. }
  252. /// Returns a matrix of ones, where every element is equal to one.
  253. static constexpr matrix one() noexcept
  254. {
  255. return one(std::make_index_sequence<column_count>{});
  256. }
  257. /// @private
  258. template <std::size_t... I>
  259. static constexpr inline column_vector_type identity_column(std::size_t i, std::index_sequence<I...>) noexcept
  260. {
  261. return {(I == i ? T{1} : T{0}) ...};
  262. }
  263. /// @private
  264. template <std::size_t... I>
  265. static constexpr inline matrix identity(std::index_sequence<I...>) noexcept
  266. {
  267. return {identity_column(I, std::make_index_sequence<row_count>{}) ...};
  268. }
  269. /// Returns an identity matrix, with ones on the main diagonal and zeros elsewhere.
  270. static constexpr matrix identity() noexcept
  271. {
  272. return identity(std::make_index_sequence<column_count>{});
  273. }
  274. };
  275. /// 2x2 matrix.
  276. template <typename T>
  277. using matrix2 = matrix<T, 2, 2>;
  278. /// 2x2 matrix.
  279. template <typename T>
  280. using matrix2x2 = matrix<T, 2, 2>;
  281. /// 3x3 matrix.
  282. template <typename T>
  283. using matrix3 = matrix<T, 3, 3>;
  284. /// 3x3 matrix.
  285. template <typename T>
  286. using matrix3x3 = matrix<T, 3, 3>;
  287. /// 4x4 matrix.
  288. template <typename T>
  289. using matrix4 = matrix<T, 4, 4>;
  290. /// 4x4 matrix.
  291. template <typename T>
  292. using matrix4x4 = matrix<T, 4, 4>;
  293. /**
  294. * Adds two matrices.
  295. *
  296. * @param a First matrix.
  297. * @param b Second matrix.
  298. *
  299. * @return Sum of the two matrices.
  300. */
  301. template <class T, std::size_t N, std::size_t M>
  302. constexpr matrix<T, N, M> add(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept;
  303. /**
  304. * Adds a matrix and a scalar.
  305. *
  306. * @param a Matrix.
  307. * @param b scalar.
  308. *
  309. * @return Sum of the matrix and scalar.
  310. */
  311. template <class T, std::size_t N, std::size_t M>
  312. constexpr matrix<T, N, M> add(const matrix<T, N, M>& a, T b) noexcept;
  313. /**
  314. * Calculates the determinant of a square matrix.
  315. *
  316. * @param m Matrix of which to take the determinant.
  317. *
  318. * @return Determinant of @p m.
  319. *
  320. * @warning Currently only implemented for 2x2, 3x3, and 4x4 matrices.
  321. */
  322. template <class T, std::size_t N>
  323. constexpr T determinant(const matrix<T, N, N>& m) noexcept;
  324. /**
  325. * Calculates the inverse of a square matrix.
  326. *
  327. * @param m Square matrix.
  328. *
  329. * @return Inverse of matrix @p m.
  330. *
  331. * @warning Currently only implemented for 2x2, 3x3, and 4x4 matrices.
  332. */
  333. template <class T, std::size_t N>
  334. constexpr matrix<T, N, N> inverse(const matrix<T, N, N>& m) noexcept;
  335. /**
  336. * Performs a component-wise multiplication of two matrices.
  337. *
  338. * @param x First matrix multiplicand.
  339. * @param y Second matrix multiplicand.
  340. *
  341. * @return Product of the component-wise multiplcation.
  342. */
  343. template <class T, std::size_t N, std::size_t M>
  344. constexpr matrix<T, N, M> componentwise_mul(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept;
  345. /**
  346. * Divides a matrix by a matrix.
  347. *
  348. * @param a First matrix.
  349. * @param b Second matrix.
  350. *
  351. * @return Result of the division.
  352. */
  353. template <class T, std::size_t N, std::size_t M>
  354. constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept;
  355. /**
  356. * Divides a matrix by a scalar.
  357. *
  358. * @param a Matrix.
  359. * @param b Scalar.
  360. *
  361. * @return Result of the division.
  362. */
  363. template <class T, std::size_t N, std::size_t M>
  364. constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, T b) noexcept;
  365. /**
  366. * Divides a scalar by a matrix.
  367. *
  368. * @param a Scalar.
  369. * @param b Matrix.
  370. *
  371. * @return Result of the division.
  372. */
  373. template <class T, std::size_t N, std::size_t M>
  374. constexpr matrix<T, N, M> div(T a, const matrix<T, N, M>& b) noexcept;
  375. /**
  376. * Creates a viewing transformation matrix.
  377. *
  378. * @param position Position of the view point.
  379. * @param target Position of the target.
  380. * @param up Normalized direction of the up vector.
  381. *
  382. * @return Viewing transformation matrix.
  383. */
  384. template <class T>
  385. constexpr matrix<T, 4, 4> look_at(const vector<T, 3>& position, const vector<T, 3>& target, vector<T, 3> up);
  386. /**
  387. * Multiplies two matrices
  388. *
  389. * @tparam T Matrix element type.
  390. * @tparam N Number of columns in matrix @p a, and rows in matrix @p b.
  391. * @tparam M Number of rows in matrix @p a.
  392. * @tparam P Number of columns in matrix @p b.
  393. *
  394. * @param a First matrix.
  395. * @param b Second matrix.
  396. *
  397. * @return Product of `a * b`.
  398. */
  399. template <typename T, std::size_t N, std::size_t M, std::size_t P>
  400. constexpr matrix<T, P, M> mul(const matrix<T, N, M>& a, const matrix<T, P, N>& b) noexcept;
  401. /**
  402. * Multiplies a matrix by a scalar.
  403. *
  404. * @param a Matrix.
  405. * @param b Scalar.
  406. *
  407. * @return Product of the matrix and the scalar.
  408. */
  409. template <class T, std::size_t N, std::size_t M>
  410. constexpr matrix<T, N, M> mul(const matrix<T, N, M>& a, T b) noexcept;
  411. /**
  412. * Calculates the product of a matrix and a row vector.
  413. *
  414. * @param a Matrix.
  415. * @param b Row vector
  416. *
  417. * @return Product of the matrix and the row vector.
  418. */
  419. template <typename T, std::size_t N, std::size_t M>
  420. 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;
  421. /**
  422. * Calculates the product of a column vector and a matrix.
  423. *
  424. * @param a Column vector.
  425. * @param b Matrix.
  426. *
  427. * @return Product of the column vector and the matrix.
  428. */
  429. template <typename T, std::size_t N, std::size_t M>
  430. 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;
  431. /**
  432. * Constructs a rotation matrix.
  433. *
  434. * @param angle Angle of rotation, in radians.
  435. * @param axis Axis of rotation.
  436. *
  437. * @return Rotation matrix.
  438. */
  439. template <class T>
  440. matrix<T, 3, 3> rotate(T angle, const vector<T, 3>& axis);
  441. /**
  442. * Produces a matrix which rotates Cartesian coordinates about the x-axis by a given angle.
  443. *
  444. * @param angle Angle of rotation, in radians.
  445. *
  446. * @return Rotation matrix.
  447. */
  448. template <class T>
  449. matrix3<T> rotate_x(T angle);
  450. /**
  451. * Produces a matrix which rotates Cartesian coordinates about the y-axis by a given angle.
  452. *
  453. * @param angle Angle of rotation, in radians.
  454. *
  455. * @return Rotation matrix.
  456. */
  457. template <class T>
  458. matrix3<T> rotate_y(T angle);
  459. /**
  460. * Produces a matrix which rotates Cartesian coordinates about the z-axis by a given angle.
  461. *
  462. * @param angle Angle of rotation, in radians.
  463. *
  464. * @return Rotation matrix.
  465. */
  466. template <class T>
  467. matrix3<T> rotate_z(T angle);
  468. /**
  469. * Scales a matrix.
  470. *
  471. * @param m Matrix to scale.
  472. * @param v Scale vector.
  473. *
  474. * @return Scaled matrix.
  475. */
  476. template <class T>
  477. constexpr matrix<T, 4, 4> scale(const matrix<T, 4, 4>& m, const vector<T, 3>& v);
  478. /**
  479. * Subtracts a matrix from another matrix.
  480. *
  481. * @param a First matrix.
  482. * @param b Second matrix.
  483. *
  484. * @return Difference between the two matrices.
  485. */
  486. template <class T, std::size_t N, std::size_t M>
  487. constexpr matrix<T, N, M> sub(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept;
  488. /**
  489. * Subtracts a scalar from matrix.
  490. *
  491. * @param a Matrix.
  492. * @param b Scalar.
  493. *
  494. * @return Difference between the matrix and scalar.
  495. */
  496. template <class T, std::size_t N, std::size_t M>
  497. constexpr matrix<T, N, M> sub(const matrix<T, N, M>& a, T b) noexcept;
  498. /**
  499. * Subtracts a matrix from a scalar.
  500. *
  501. * @param a Scalar.
  502. * @param b Matrix.
  503. *
  504. * @return Difference between the scalar and matrix.
  505. */
  506. template <class T, std::size_t N, std::size_t M>
  507. constexpr matrix<T, N, M> sub(T a, const matrix<T, N, M>& b) noexcept;
  508. /**
  509. * Calculates the trace of a square matrix.
  510. *
  511. * @param m Square matrix.
  512. *
  513. * @return Sum of elements on the main diagonal.
  514. */
  515. template <class T, std::size_t N>
  516. constexpr T trace(const matrix<T, N, N>& m) noexcept;
  517. /**
  518. * Translates a matrix.
  519. *
  520. * @param m Matrix to translate.
  521. * @param v Translation vector.
  522. *
  523. * @return Translated matrix.
  524. */
  525. template <class T>
  526. constexpr matrix<T, 4, 4> translate(const matrix<T, 4, 4>& m, const vector<T, 3>& v);
  527. /**
  528. * Calculates the transpose of a matrix.
  529. *
  530. * @param m Matrix to transpose.
  531. *
  532. * @return Transposed matrix.
  533. */
  534. template <typename T, std::size_t N, std::size_t M>
  535. constexpr matrix<T, M, N> transpose(const matrix<T, N, M>& m) noexcept;
  536. /// @private
  537. template <class T, std::size_t N, std::size_t M, std::size_t... I>
  538. constexpr inline matrix<T, N, M> add(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
  539. {
  540. return {(a[I] + b[I]) ...};
  541. }
  542. template <class T, std::size_t N, std::size_t M>
  543. constexpr matrix<T, N, M> add(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
  544. {
  545. return add(a, b, std::make_index_sequence<N>{});
  546. }
  547. /// @private
  548. template <class T, std::size_t N, std::size_t M, std::size_t... I>
  549. constexpr inline matrix<T, N, M> add(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
  550. {
  551. return {(a[I] + b) ...};
  552. }
  553. template <class T, std::size_t N, std::size_t M>
  554. constexpr matrix<T, N, M> add(const matrix<T, N, M>& a, T b) noexcept
  555. {
  556. return add(a, b, std::make_index_sequence<N>{});
  557. }
  558. template <class T>
  559. constexpr T determinant(const matrix<T, 2, 2>& m) noexcept
  560. {
  561. return
  562. m[0][0] * m[1][1] -
  563. m[0][1] * m[1][0];
  564. }
  565. template <class T>
  566. constexpr T determinant(const matrix<T, 3, 3>& m) noexcept
  567. {
  568. return
  569. m[0][0] * m[1][1] * m[2][2] +
  570. m[0][1] * m[1][2] * m[2][0] +
  571. m[0][2] * m[1][0] * m[2][1] -
  572. m[0][0] * m[1][2] * m[2][1] -
  573. m[0][1] * m[1][0] * m[2][2] -
  574. m[0][2] * m[1][1] * m[2][0];
  575. }
  576. template <class T>
  577. constexpr T determinant(const matrix<T, 4, 4>& m) noexcept
  578. {
  579. return
  580. m[0][3] * m[1][2] * m[2][1] * m[3][0] - m[0][2] * m[1][3] * m[2][1] * m[3][0] -
  581. m[0][3] * m[1][1] * m[2][2] * m[3][0] + m[0][1] * m[1][3] * m[2][2] * m[3][0] +
  582. m[0][2] * m[1][1] * m[2][3] * m[3][0] - m[0][1] * m[1][2] * m[2][3] * m[3][0] -
  583. m[0][3] * m[1][2] * m[2][0] * m[3][1] + m[0][2] * m[1][3] * m[2][0] * m[3][1] +
  584. m[0][3] * m[1][0] * m[2][2] * m[3][1] - m[0][0] * m[1][3] * m[2][2] * m[3][1] -
  585. m[0][2] * m[1][0] * m[2][3] * m[3][1] + m[0][0] * m[1][2] * m[2][3] * m[3][1] +
  586. m[0][3] * m[1][1] * m[2][0] * m[3][2] - m[0][1] * m[1][3] * m[2][0] * m[3][2] -
  587. m[0][3] * m[1][0] * m[2][1] * m[3][2] + m[0][0] * m[1][3] * m[2][1] * m[3][2] +
  588. m[0][1] * m[1][0] * m[2][3] * m[3][2] - m[0][0] * m[1][1] * m[2][3] * m[3][2] -
  589. m[0][2] * m[1][1] * m[2][0] * m[3][3] + m[0][1] * m[1][2] * m[2][0] * m[3][3] +
  590. m[0][2] * m[1][0] * m[2][1] * m[3][3] - m[0][0] * m[1][2] * m[2][1] * m[3][3] -
  591. m[0][1] * m[1][0] * m[2][2] * m[3][3] + m[0][0] * m[1][1] * m[2][2] * m[3][3];
  592. }
  593. template <class T>
  594. constexpr matrix<T, 2, 2> inverse(const matrix<T, 2, 2>& m) noexcept
  595. {
  596. const T inv_det = T{1} / determinant(m);
  597. return
  598. {
  599. m[1][1] * inv_det,
  600. -m[0][1] * inv_det,
  601. -m[1][0] * inv_det,
  602. m[0][0] * inv_det
  603. };
  604. }
  605. template <class T>
  606. constexpr matrix<T, 3, 3> inverse(const matrix<T, 3, 3>& m) noexcept
  607. {
  608. const T inv_det = T{1} / determinant(m);
  609. return
  610. {
  611. (m[1][1] * m[2][2] - m[1][2] * m[2][1]) * inv_det,
  612. (m[0][2] * m[2][1] - m[0][1] * m[2][2]) * inv_det,
  613. (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * inv_det,
  614. (m[1][2] * m[2][0] - m[1][0] * m[2][2]) * inv_det,
  615. (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * inv_det,
  616. (m[0][2] * m[1][0] - m[0][0] * m[1][2]) * inv_det,
  617. (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * inv_det,
  618. (m[0][1] * m[2][0] - m[0][0] * m[2][1]) * inv_det,
  619. (m[0][0] * m[1][1] - m[0][1] * m[1][0]) * inv_det
  620. };
  621. }
  622. template <class T>
  623. constexpr matrix<T, 4, 4> inverse(const matrix<T, 4, 4>& m) noexcept
  624. {
  625. const T inv_det = T{1} / determinant(m);
  626. return
  627. {
  628. (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,
  629. (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,
  630. (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,
  631. (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,
  632. (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,
  633. (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,
  634. (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,
  635. (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,
  636. (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,
  637. (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,
  638. (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,
  639. (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,
  640. (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,
  641. (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,
  642. (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,
  643. (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
  644. };
  645. }
  646. /// @private
  647. template <class T, std::size_t N, std::size_t M, std::size_t... I>
  648. constexpr inline matrix<T, N, M> componentwise_mul(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
  649. {
  650. return {(a[I] * b[I]) ...};
  651. }
  652. template <class T, std::size_t N, std::size_t M>
  653. constexpr matrix<T, N, M> componentwise_mul(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
  654. {
  655. return componentwise_mul(a, b, std::make_index_sequence<N>{});
  656. }
  657. /// @private
  658. template <class T, std::size_t N, std::size_t M, std::size_t... I>
  659. constexpr inline matrix<T, N, M> div(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
  660. {
  661. return {(a[I] / b[I]) ...};
  662. }
  663. template <class T, std::size_t N, std::size_t M>
  664. constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
  665. {
  666. return div(a, b, std::make_index_sequence<N>{});
  667. }
  668. /// @private
  669. template <class T, std::size_t N, std::size_t M, std::size_t... I>
  670. constexpr inline matrix<T, N, M> div(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
  671. {
  672. return {(a[I] / b) ...};
  673. }
  674. template <class T, std::size_t N, std::size_t M>
  675. constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, T b) noexcept
  676. {
  677. return div(a, b, std::make_index_sequence<N>{});
  678. }
  679. /// @private
  680. template <class T, std::size_t N, std::size_t M, std::size_t... I>
  681. constexpr inline matrix<T, N, M> div(T a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
  682. {
  683. return {(a / b[I]) ...};
  684. }
  685. template <class T, std::size_t N, std::size_t M>
  686. constexpr matrix<T, N, M> div(T a, const matrix<T, N, M>& b) noexcept
  687. {
  688. return div(a, b, std::make_index_sequence<N>{});
  689. }
  690. template <class T>
  691. constexpr matrix<T, 4, 4> look_at(const vector<T, 3>& position, const vector<T, 3>& target, vector<T, 3> up)
  692. {
  693. vector<T, 3> forward = normalize(sub(target, position));
  694. vector<T, 3> right = normalize(cross(forward, up));
  695. up = cross(right, forward);
  696. matrix<T, 4, 4> m =
  697. {{
  698. {right[0], up[0], -forward[0], T(0)},
  699. {right[1], up[1], -forward[1], T(0)},
  700. {right[2], up[2], -forward[2], T(0)},
  701. {T(0), T(0), T(0), T(1)}
  702. }};
  703. return translate(m, negate(position));
  704. }
  705. template <typename T, std::size_t N, std::size_t M, std::size_t P>
  706. constexpr matrix<T, P, M> mul(const matrix<T, N, M>& a, const matrix<T, P, N>& b) noexcept
  707. {
  708. matrix<T, P, M> c = matrix<T, P, M>::zero();
  709. for (std::size_t i = 0; i < P; ++i)
  710. {
  711. for (std::size_t j = 0; j < M; ++j)
  712. {
  713. for (std::size_t k = 0; k < N; ++k)
  714. {
  715. c[i][j] += a[k][j] * b[i][k];
  716. }
  717. }
  718. }
  719. return c;
  720. }
  721. /// @private
  722. template <class T, std::size_t N, std::size_t M, std::size_t... I>
  723. constexpr inline matrix<T, N, M> mul(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
  724. {
  725. return {(a[I] * b) ...};
  726. }
  727. template <class T, std::size_t N, std::size_t M>
  728. constexpr matrix<T, N, M> mul(const matrix<T, N, M>& a, T b) noexcept
  729. {
  730. return mul(a, b, std::make_index_sequence<N>{});
  731. }
  732. /// @private
  733. template <typename T, std::size_t N, std::size_t M, std::size_t... I>
  734. constexpr inline 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
  735. {
  736. return ((a[I] * b[I]) + ...);
  737. }
  738. template <typename T, std::size_t N, std::size_t M>
  739. 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
  740. {
  741. return mul(a, b, std::make_index_sequence<N>{});
  742. }
  743. /// @private
  744. template <typename T, std::size_t N, std::size_t M, std::size_t... I>
  745. constexpr inline 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
  746. {
  747. return {dot(a, b[I]) ...};
  748. }
  749. template <typename T, std::size_t N, std::size_t M>
  750. 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
  751. {
  752. return mul(a, b, std::make_index_sequence<N>{});
  753. }
  754. template <class T>
  755. matrix<T, 3, 3> rotate(T angle, const vector<T, 3>& axis)
  756. {
  757. const T c = std::cos(angle);
  758. const T s = std::sin(angle);
  759. const vector<T, 3> temp = mul(axis, T(1) - c);
  760. matrix<T, 3, 3> rotation;
  761. rotation[0][0] = axis[0] * temp[0] + c;
  762. rotation[0][1] = axis[1] * temp[0] + axis[2] * s;
  763. rotation[0][2] = axis[2] * temp[0] - axis[1] * s;
  764. rotation[1][0] = axis[0] * temp[1] - axis[2] * s;
  765. rotation[1][1] = axis[1] * temp[1] + c;
  766. rotation[1][2] = axis[2] * temp[1] + axis[0] * s;
  767. rotation[2][0] = axis[0] * temp[2] + axis[1] * s;
  768. rotation[2][1] = axis[1] * temp[2] - axis[0] * s;
  769. rotation[2][2] = axis[2] * temp[2] + c;
  770. return rotation;
  771. }
  772. template <class T>
  773. matrix3<T> rotate_x(T angle)
  774. {
  775. const T c = std::cos(angle);
  776. const T s = std::sin(angle);
  777. return matrix3<T>
  778. {
  779. T(1), T(0), T(0),
  780. T(0), c, s,
  781. T(0), -s, c
  782. };
  783. }
  784. template <class T>
  785. matrix3<T> rotate_y(T angle)
  786. {
  787. const T c = std::cos(angle);
  788. const T s = std::sin(angle);
  789. return matrix3<T>
  790. {
  791. c, T(0), -s,
  792. T(0), T(1), T(0),
  793. s, T(0), c
  794. };
  795. }
  796. template <class T>
  797. matrix3<T> rotate_z(T angle)
  798. {
  799. const T c = std::cos(angle);
  800. const T s = std::sin(angle);
  801. return matrix3<T>
  802. {
  803. c, s, T(0),
  804. -s, c, T(0),
  805. T(0), T(0), T(1)
  806. };
  807. }
  808. template <class T>
  809. constexpr matrix<T, 4, 4> scale(const matrix<T, 4, 4>& m, const vector<T, 3>& v)
  810. {
  811. return mul(m, matrix<T, 4, 4>
  812. {{
  813. {v[0], T(0), T(0), T(0)},
  814. {T(0), v[1], T(0), T(0)},
  815. {T(0), T(0), v[2], T(0)},
  816. {T(0), T(0), T(0), T(1)}
  817. }});
  818. }
  819. /// @private
  820. template <class T, std::size_t N, std::size_t M, std::size_t... I>
  821. constexpr inline matrix<T, N, M> sub(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
  822. {
  823. return {(a[I] - b[I]) ...};
  824. }
  825. template <class T, std::size_t N, std::size_t M>
  826. constexpr matrix<T, N, M> sub(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
  827. {
  828. return sub(a, b, std::make_index_sequence<N>{});
  829. }
  830. /// @private
  831. template <class T, std::size_t N, std::size_t M, std::size_t... I>
  832. constexpr inline matrix<T, N, M> sub(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
  833. {
  834. return {(a[I] - b) ...};
  835. }
  836. template <class T, std::size_t N, std::size_t M>
  837. constexpr matrix<T, N, M> sub(const matrix<T, N, M>& a, T b) noexcept
  838. {
  839. return sub(a, b, std::make_index_sequence<N>{});
  840. }
  841. /// @private
  842. template <class T, std::size_t N, std::size_t M, std::size_t... I>
  843. constexpr inline matrix<T, N, M> sub(T a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
  844. {
  845. return {(a - b[I]) ...};
  846. }
  847. template <class T, std::size_t N, std::size_t M>
  848. constexpr matrix<T, N, M> sub(T a, const matrix<T, N, M>& b) noexcept
  849. {
  850. return sub(a, b, std::make_index_sequence<N>{});
  851. }
  852. /// @private
  853. template <class T, std::size_t N, std::size_t... I>
  854. constexpr inline T trace(const matrix<T, N, N>& m, std::index_sequence<I...>) noexcept
  855. {
  856. return ((m[I][I]) + ...);
  857. }
  858. template <class T, std::size_t N>
  859. constexpr T trace(const matrix<T, N, N>& m) noexcept
  860. {
  861. return trace(m, std::make_index_sequence<N>{});
  862. }
  863. template <class T>
  864. constexpr matrix<T, 4, 4> translate(const matrix<T, 4, 4>& m, const vector<T, 3>& v)
  865. {
  866. return mul(m, matrix<T, 4, 4>
  867. {{
  868. {T(1), T(0), T(0), T(0)},
  869. {T(0), T(1), T(0), T(0)},
  870. {T(0), T(0), T(1), T(0)},
  871. {v[0], v[1], v[2], T(1)}
  872. }});
  873. }
  874. /// @private
  875. template <typename T, std::size_t N, std::size_t M, std::size_t... I>
  876. constexpr inline 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
  877. {
  878. return {m[I][i] ...};
  879. }
  880. /// @private
  881. template <typename T, std::size_t N, std::size_t M, std::size_t... I>
  882. constexpr inline matrix<T, M, N> transpose(const matrix<T, N, M>& m, std::index_sequence<I...>) noexcept
  883. {
  884. return {transpose_column(m, I, std::make_index_sequence<N>{}) ...};
  885. }
  886. template <typename T, std::size_t N, std::size_t M>
  887. constexpr matrix<T, M, N> transpose(const matrix<T, N, M>& m) noexcept
  888. {
  889. return transpose(m, std::make_index_sequence<M>{});
  890. }
  891. namespace operators {
  892. /// @copydoc add(const matrix<T, N, M>&, const matrix<T, N, M>&)
  893. template <class T, std::size_t N, std::size_t M>
  894. constexpr inline matrix<T, N, M> operator+(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
  895. {
  896. return add(a, b);
  897. }
  898. /// @copydoc add(const matrix<T, N, M>&, T)
  899. /// @{
  900. template <class T, std::size_t N, std::size_t M>
  901. constexpr inline matrix<T, N, M> operator+(const matrix<T, N, M>& a, T b) noexcept
  902. {
  903. return add(a, b);
  904. }
  905. template <class T, std::size_t N, std::size_t M>
  906. constexpr inline matrix<T, N, M> operator+(T a, const matrix<T, N, M>& b) noexcept
  907. {
  908. return add(b, a);
  909. }
  910. /// @}
  911. /// @copydoc div(const matrix<T, N, M>&, const matrix<T, N, M>&)
  912. template <class T, std::size_t N, std::size_t M>
  913. constexpr inline matrix<T, N, M> operator/(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
  914. {
  915. return div(a, b);
  916. }
  917. /// @copydoc div(const matrix<T, N, M>&, T)
  918. template <class T, std::size_t N, std::size_t M>
  919. constexpr inline matrix<T, N, M> operator/(const matrix<T, N, M>& a, T b) noexcept
  920. {
  921. return div(a, b);
  922. }
  923. /// @copydoc div(T, const matrix<T, N, M>&)
  924. template <class T, std::size_t N, std::size_t M>
  925. constexpr inline matrix<T, N, M> operator/(T a, const matrix<T, N, M>& b) noexcept
  926. {
  927. return div(a, b);
  928. }
  929. /// @copydoc mul(const matrix<T, N, M>&, const matrix<T, P, N>&)
  930. template <typename T, std::size_t N, std::size_t M, std::size_t P>
  931. constexpr inline matrix<T, P, M> operator*(const matrix<T, N, M>& a, const matrix<T, P, N>& b) noexcept
  932. {
  933. return mul(a, b);
  934. }
  935. /// @copydoc mul(const matrix<T, N, M>&, T)
  936. /// @{
  937. template <class T, std::size_t N, std::size_t M>
  938. constexpr inline matrix<T, N, M> operator*(const matrix<T, N, M>& a, T b) noexcept
  939. {
  940. return mul(a, b);
  941. }
  942. template <class T, std::size_t N, std::size_t M>
  943. constexpr inline matrix<T, N, M> operator*(T a, const matrix<T, N, M>& b) noexcept
  944. {
  945. return mul(b, a);
  946. }
  947. /// @}
  948. /// @copydoc mul(const matrix<T, N, M>&, const typename matrix<T, N, M>::row_vector_type&)
  949. template <typename T, std::size_t N, std::size_t M>
  950. constexpr inline 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
  951. {
  952. return mul(a, b);
  953. }
  954. /// @copydoc mul(const typename matrix<T, N, M>::column_vector_type&, const matrix<T, N, M>&)
  955. template <typename T, std::size_t N, std::size_t M>
  956. constexpr inline 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
  957. {
  958. return mul(a, b);
  959. }
  960. /// @copydoc sub(const matrix<T, N, M>&, const matrix<T, N, M>&)
  961. template <class T, std::size_t N, std::size_t M>
  962. constexpr inline matrix<T, N, M> operator-(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
  963. {
  964. return sub(a, b);
  965. }
  966. /// @copydoc sub(const matrix<T, N, M>&, T)
  967. template <class T, std::size_t N, std::size_t M>
  968. constexpr inline matrix<T, N, M> operator-(const matrix<T, N, M>& a, T b) noexcept
  969. {
  970. return sub(a, b);
  971. }
  972. /// @copydoc sub(T, const matrix<T, N, M>&)
  973. template <class T, std::size_t N, std::size_t M>
  974. constexpr inline matrix<T, N, M> operator-(T a, const matrix<T, N, M>& b) noexcept
  975. {
  976. return sub(a, b);
  977. }
  978. /**
  979. * Adds two values and stores the result in the first value.
  980. *
  981. * @param a First value.
  982. * @param b Second value.
  983. *
  984. * @return Reference to the first value.
  985. */
  986. /// @{
  987. template <class T, std::size_t N, std::size_t M>
  988. constexpr inline matrix<T, N, M>& operator+=(matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
  989. {
  990. return (a = a + b);
  991. }
  992. template <class T, std::size_t N, std::size_t M>
  993. constexpr inline matrix<T, N, M>& operator+=(matrix<T, N, M>& a, T b) noexcept
  994. {
  995. return (a = a + b);
  996. }
  997. /// @}
  998. /**
  999. * Subtracts the first value by the second value and stores the result in the first value.
  1000. *
  1001. * @param a First value.
  1002. * @param b Second value.
  1003. *
  1004. * @return Reference to the first value.
  1005. */
  1006. /// @{
  1007. template <class T, std::size_t N, std::size_t M>
  1008. constexpr inline matrix<T, N, M>& operator-=(matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
  1009. {
  1010. return (a = a - b);
  1011. }
  1012. template <class T, std::size_t N, std::size_t M>
  1013. constexpr inline matrix<T, N, M>& operator-=(matrix<T, N, M>& a, T b) noexcept
  1014. {
  1015. return (a = a - b);
  1016. }
  1017. /// @}
  1018. /**
  1019. * Multiplies two values and stores the result in the first value.
  1020. *
  1021. * @param a First value.
  1022. * @param b Second value.
  1023. *
  1024. * @return Reference to the first value.
  1025. */
  1026. /// @{
  1027. template <class T, std::size_t N>
  1028. constexpr inline matrix<T, N, N>& operator*=(matrix<T, N, N>& a, const matrix<T, N, N>& b) noexcept
  1029. {
  1030. return (a = a * b);
  1031. }
  1032. template <class T, std::size_t N, std::size_t M>
  1033. constexpr inline matrix<T, N, M>& operator*=(matrix<T, N, M>& a, T b) noexcept
  1034. {
  1035. return (a = a * b);
  1036. }
  1037. /// @}
  1038. /**
  1039. * Divides the first value by the second value and stores the result in the first value.
  1040. *
  1041. * @param a First value.
  1042. * @param b Second value.
  1043. *
  1044. * @return Reference to the first value.
  1045. */
  1046. /// @{
  1047. template <class T, std::size_t N, std::size_t M>
  1048. constexpr inline matrix<T, N, M>& operator/=(matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
  1049. {
  1050. return (a = a / b);
  1051. }
  1052. template <class T, std::size_t N, std::size_t M>
  1053. constexpr inline matrix<T, N, M>& operator/=(matrix<T, N, M>& a, T b) noexcept
  1054. {
  1055. return (a = a / b);
  1056. }
  1057. /// @}
  1058. /**
  1059. * Writes the elements of a matrix to an output stream, with each element delimeted by a space.
  1060. *
  1061. * @param os Output stream.
  1062. * @param m Matrix.
  1063. *
  1064. * @return Output stream.
  1065. */
  1066. template <class T, std::size_t N, std::size_t M>
  1067. std::ostream& operator<<(std::ostream& os, const matrix<T, N, M>& m)
  1068. {
  1069. for (std::size_t i = 0; i < m.size(); ++i)
  1070. {
  1071. if (i)
  1072. os << ' ';
  1073. os << m.element(i);
  1074. }
  1075. return os;
  1076. }
  1077. /**
  1078. * Reads the elements of a matrix from an input stream, with each element delimeted by a space.
  1079. *
  1080. * @param is Input stream.
  1081. * @param m Matrix.
  1082. *
  1083. * @return Input stream.
  1084. */
  1085. template <class T, std::size_t N, std::size_t M>
  1086. std::istream& operator>>(std::istream& is, matrix<T, N, M>& m)
  1087. {
  1088. for (std::size_t i = 0; i < m.size(); ++i)
  1089. is >> m.element(i);
  1090. return is;
  1091. }
  1092. } // namespace operators
  1093. } // namespace math
  1094. using namespace math::operators;
  1095. #endif // ANTKEEPER_MATH_MATRIX_HPP