💿🐜 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.

1381 lines
40 KiB

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