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

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