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

959 lines
22 KiB

  1. /*
  2. * Copyright (C) 2021 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef ANTKEEPER_MATH_QUATERNION_HPP
  20. #define ANTKEEPER_MATH_QUATERNION_HPP
  21. #include "math/constants.hpp"
  22. #include "math/matrix.hpp"
  23. #include "math/vector.hpp"
  24. #include <cmath>
  25. #include <istream>
  26. #include <ostream>
  27. namespace math {
  28. /**
  29. * A quaternion type is a tuple made of a scalar (real) part and vector (imaginary) part.
  30. *
  31. * @tparam T Scalar type.
  32. */
  33. template <class T>
  34. struct quaternion
  35. {
  36. /// Scalar type.
  37. typedef T scalar_type;
  38. /// Vector type.
  39. typedef vector<T, 3> vector_type;
  40. /// Rotation matrix type.
  41. typedef matrix<T, 3, 3> matrix_type;
  42. /// Quaternion real part.
  43. scalar_type r;
  44. /// Quaternion imaginary part.
  45. vector_type i;
  46. /// Returns a reference to the quaternion real part.
  47. /// @{
  48. constexpr inline scalar_type& w() noexcept
  49. {
  50. return r;
  51. }
  52. constexpr inline const scalar_type& w() const noexcept
  53. {
  54. return r;
  55. }
  56. /// @}
  57. /// Returns a reference to the first element of the quaternion imaginary part.
  58. /// @{
  59. constexpr inline scalar_type& x() noexcept
  60. {
  61. return i.x();
  62. }
  63. constexpr inline const scalar_type& x() const noexcept
  64. {
  65. return i.x();
  66. }
  67. /// @}
  68. /// Returns a reference to the second element of the quaternion imaginary part.
  69. /// @{
  70. constexpr inline scalar_type& y() noexcept
  71. {
  72. return i.y();
  73. }
  74. constexpr inline const scalar_type& y() const noexcept
  75. {
  76. return i.y();
  77. }
  78. /// @}
  79. /// Returns a reference to the third element of the quaternion imaginary part.
  80. /// @{
  81. constexpr inline scalar_type& z() noexcept
  82. {
  83. return i.z();
  84. }
  85. constexpr inline const scalar_type& z() const noexcept
  86. {
  87. return i.z();
  88. }
  89. /// @}
  90. /**
  91. * Returns a quaternion representing a rotation about the x-axis.
  92. *
  93. * @param angle Angle of rotation, in radians.
  94. *
  95. * @return Quaternion representing an x-axis rotation.
  96. */
  97. static quaternion rotate_x(scalar_type angle)
  98. {
  99. return {std::cos(angle * T(0.5)), std::sin(angle * T(0.5)), T(0), T(0)};
  100. }
  101. /**
  102. * Returns a quaternion representing a rotation about the y-axis.
  103. *
  104. * @param angle Angle of rotation, in radians.
  105. *
  106. * @return Quaternion representing an y-axis rotation.
  107. */
  108. static quaternion rotate_y(scalar_type angle)
  109. {
  110. return {std::cos(angle * T(0.5)), T(0), std::sin(angle * T(0.5)), T(0)};
  111. }
  112. /**
  113. * Returns a quaternion representing a rotation about the z-axis.
  114. *
  115. * @param angle Angle of rotation, in radians.
  116. * @return Quaternion representing an z-axis rotation.
  117. */
  118. static quaternion rotate_z(scalar_type angle)
  119. {
  120. return {std::cos(angle * T(0.5)), T(0), T(0), std::sin(angle * T(0.5))};
  121. }
  122. /**
  123. * Type-casts the quaternion scalars using `static_cast`.
  124. *
  125. * @tparam U Target scalar type.
  126. *
  127. * @return Type-casted quaternion.
  128. */
  129. template <class U>
  130. constexpr inline explicit operator quaternion<U>() const noexcept
  131. {
  132. return {static_cast<U>(r), vector<U, 3>(i)};
  133. }
  134. /**
  135. * Casts the quaternion to a 4-element vector, with the real part as the first element and the imaginary part as the following three elements.
  136. *
  137. * @return Vector containing the real and imaginary parts of the quaternion.
  138. */
  139. constexpr inline explicit operator vector<T, 4>() const noexcept
  140. {
  141. return {r, i[0], i[1], i[2]};
  142. }
  143. /// Returns a zero quaternion, where every scalar is equal to zero.
  144. static constexpr quaternion zero() noexcept
  145. {
  146. return {};
  147. }
  148. /// Returns a rotation identity quaternion.
  149. static constexpr quaternion identity() noexcept
  150. {
  151. return {T{1}, vector_type::zero()};
  152. }
  153. };
  154. /**
  155. * Adds two quaternions.
  156. *
  157. * @param a First quaternion.
  158. * @param b Second quaternion.
  159. *
  160. * @return Sum of the two quaternions.
  161. */
  162. template <class T>
  163. constexpr quaternion<T> add(const quaternion<T>& a, const quaternion<T>& b) noexcept;
  164. /**
  165. * Adds a quaternion and a scalar.
  166. *
  167. * @param a First value.
  168. * @param b Second second value.
  169. *
  170. * @return Sum of the quaternion and scalar.
  171. */
  172. template <class T>
  173. constexpr quaternion<T> add(const quaternion<T>& a, T b) noexcept;
  174. /**
  175. * Calculates the conjugate of a quaternion.
  176. *
  177. * @param q Quaternion from which the conjugate will be calculated.
  178. *
  179. * @return Conjugate of the quaternion.
  180. */
  181. template <class T>
  182. constexpr quaternion<T> conjugate(const quaternion<T>& q) noexcept;
  183. /**
  184. * Calculates the dot product of two quaternions.
  185. *
  186. * @param a First quaternion.
  187. * @param b Second quaternion.
  188. *
  189. * @return Dot product of the two quaternions.
  190. */
  191. template <class T>
  192. constexpr T dot(const quaternion<T>& a, const quaternion<T>& b) noexcept;
  193. /**
  194. * Divides a quaternion by another quaternion.
  195. *
  196. * @param a First value.
  197. * @param b Second value.
  198. *
  199. * @return Result of the division.
  200. */
  201. template <class T>
  202. constexpr quaternion<T> div(const quaternion<T>& a, const quaternion<T>& b) noexcept;
  203. /**
  204. * Divides a quaternion by a scalar.
  205. *
  206. * @param a Quaternion.
  207. * @param b Scalar.
  208. *
  209. * @return Result of the division.
  210. */
  211. template <class T>
  212. constexpr quaternion<T> div(const quaternion<T>& a, T b) noexcept;
  213. /**
  214. * Divides a scalar by a quaternion.
  215. *
  216. * @param a Scalar.
  217. * @param b Quaternion.
  218. *
  219. * @return Result of the division.
  220. */
  221. template <class T>
  222. constexpr quaternion<T> div(T a, const quaternion<T>& b) noexcept;
  223. /**
  224. * Calculates the length of a quaternion.
  225. *
  226. * @param q Quaternion to calculate the length of.
  227. *
  228. * @return Length of the quaternion.
  229. */
  230. template <class T>
  231. T length(const quaternion<T>& q);
  232. /**
  233. * Calculates the squared length of a quaternion. The squared length can be calculated faster than the length because a call to `std::sqrt` is saved.
  234. *
  235. * @param q Quaternion to calculate the squared length of.
  236. *
  237. * @return Squared length of the quaternion.
  238. */
  239. template <class T>
  240. constexpr T length_squared(const quaternion<T>& q) noexcept;
  241. /**
  242. * Performs linear interpolation between two quaternions.
  243. *
  244. * @param a First quaternion.
  245. * @param b Second quaternion.
  246. * @param t Interpolation factor.
  247. *
  248. * @return Interpolated quaternion.
  249. */
  250. template <class T>
  251. constexpr quaternion<T> lerp(const quaternion<T>& a, const quaternion<T>& b, T t) noexcept;
  252. /**
  253. * Creates a unit quaternion rotation using forward and up vectors.
  254. *
  255. * @param forward Unit forward vector.
  256. * @param up Unit up vector.
  257. *
  258. * @return Unit rotation quaternion.
  259. */
  260. template <class T>
  261. quaternion<T> look_rotation(const vector<T, 3>& forward, vector<T, 3> up);
  262. /**
  263. * Converts a quaternion to a rotation matrix.
  264. *
  265. * @param q Unit quaternion.
  266. *
  267. * @return Matrix representing the rotation described by `q`.
  268. */
  269. template <class T>
  270. constexpr matrix<T, 3, 3> matrix_cast(const quaternion<T>& q) noexcept;
  271. /**
  272. * Multiplies two quaternions.
  273. *
  274. * @param a First quaternion.
  275. * @param b Second quaternion.
  276. *
  277. * @return Product of the two quaternions.
  278. */
  279. template <class T>
  280. constexpr quaternion<T> mul(const quaternion<T>& a, const quaternion<T>& b) noexcept;
  281. /**
  282. * Multiplies a quaternion by a scalar.
  283. *
  284. * @param a First value.
  285. * @param b Second value.
  286. *
  287. * @return Product of the quaternion and scalar.
  288. */
  289. template <class T>
  290. constexpr quaternion<T> mul(const quaternion<T>& a, T b) noexcept;
  291. /**
  292. * Calculates the product of a quaternion and a vector.
  293. *
  294. * @param a First value.
  295. * @param b second value.
  296. *
  297. * @return Product of the quaternion and vector.
  298. */
  299. /// @{
  300. template <class T>
  301. constexpr vector<T, 3> mul(const quaternion<T>& a, const vector<T, 3>& b) noexcept;
  302. template <class T>
  303. constexpr vector<T, 3> mul(const vector<T, 3>& a, const quaternion<T>& b) noexcept;
  304. /// @}
  305. /**
  306. * Negates a quaternion.
  307. *
  308. * @param q Quaternion to negate.
  309. *
  310. * @return Negated quaternion.
  311. */
  312. template <class T>
  313. constexpr quaternion<T> negate(const quaternion<T>& q) noexcept;
  314. /**
  315. * Performs normalized linear interpolation between two quaternions.
  316. *
  317. * @param a First quaternion.
  318. * @param b Second quaternion.
  319. * @param t Interpolation factor.
  320. *
  321. * @return Interpolated quaternion.
  322. */
  323. template <class T>
  324. quaternion<T> nlerp(const quaternion<T>& a, const quaternion<T>& b, T t);
  325. /**
  326. * Normalizes a quaternion.
  327. *
  328. * @param q Quaternion to normalize.
  329. *
  330. * @return Normalized quaternion.
  331. */
  332. template <class T>
  333. quaternion<T> normalize(const quaternion<T>& q);
  334. /**
  335. * Creates a rotation from an angle and axis.
  336. *
  337. * @param angle Angle of rotation (in radians).
  338. * @param axis Axis of rotation
  339. *
  340. * @return Quaternion representing the rotation.
  341. */
  342. template <class T>
  343. quaternion<T> angle_axis(T angle, const vector<T, 3>& axis);
  344. /**
  345. * Calculates the minimum rotation between two normalized direction vectors.
  346. *
  347. * @param source Normalized source direction.
  348. * @param destination Normalized destination direction.
  349. *
  350. * @return Quaternion representing the minimum rotation between the source and destination vectors.
  351. */
  352. template <class T>
  353. quaternion<T> rotation(const vector<T, 3>& source, const vector<T, 3>& destination);
  354. /**
  355. * Performs spherical linear interpolation between two quaternions.
  356. *
  357. * @param a First quaternion.
  358. * @param b Second quaternion.
  359. * @param t Interpolation factor.
  360. *
  361. * @return Interpolated quaternion.
  362. */
  363. template <class T>
  364. quaternion<T> slerp(const quaternion<T>& a, const quaternion<T>& b, T t, T error = T{1e-6});
  365. /**
  366. * Subtracts a quaternion from another quaternion.
  367. *
  368. * @param a First quaternion.
  369. * @param b Second quaternion.
  370. *
  371. * @return Difference between the quaternions.
  372. */
  373. template <class T>
  374. constexpr quaternion<T> sub(const quaternion<T>& a, const quaternion<T>& b) noexcept;
  375. /**
  376. * Subtracts a quaternion and a scalar.
  377. *
  378. * @param a First value.
  379. * @param b Second second.
  380. *
  381. * @return Difference between the quaternion and scalar.
  382. */
  383. /// @{
  384. template <class T>
  385. constexpr quaternion<T> sub(const quaternion<T>& a, T b) noexcept;
  386. template <class T>
  387. constexpr quaternion<T> sub(T a, const quaternion<T>& b) noexcept;
  388. /// @}
  389. /**
  390. * Decomposes a quaternion into swing and twist rotation components.
  391. *
  392. * @param[in] q Quaternion to decompose.
  393. * @param[in] a Axis of twist rotation.
  394. * @param[out] swing Swing rotation component.
  395. * @param[out] twist Twist rotation component.
  396. * @param[in] error Threshold at which a number is considered zero.
  397. *
  398. * @see https://www.euclideanspace.com/maths/geometry/rotations/for/decomposition/
  399. */
  400. template <class T>
  401. void swing_twist(const quaternion<T>& q, const vector<T, 3>& a, quaternion<T>& qs, quaternion<T>& qt, T error = T{1e-6});
  402. /**
  403. * Converts a 3x3 rotation matrix to a quaternion.
  404. *
  405. * @param m Rotation matrix.
  406. *
  407. * @return Unit quaternion representing the rotation described by @p m.
  408. */
  409. template <class T>
  410. quaternion<T> quaternion_cast(const matrix<T, 3, 3>& m);
  411. template <class T>
  412. constexpr inline quaternion<T> add(const quaternion<T>& a, const quaternion<T>& b) noexcept
  413. {
  414. return {a.r + b.r, a.i + b.i};
  415. }
  416. template <class T>
  417. constexpr inline quaternion<T> add(const quaternion<T>& a, T b) noexcept
  418. {
  419. return {a.r + b, a.i + b};
  420. }
  421. template <class T>
  422. constexpr inline quaternion<T> conjugate(const quaternion<T>& q) noexcept
  423. {
  424. return {q.r, -q.i};
  425. }
  426. template <class T>
  427. constexpr inline T dot(const quaternion<T>& a, const quaternion<T>& b) noexcept
  428. {
  429. return a.r * b.r + dot(a.i, b.i);
  430. }
  431. template <class T>
  432. constexpr inline quaternion<T> div(const quaternion<T>& a, const quaternion<T>& b) noexcept
  433. {
  434. return {a.r / b.r, a.i / b.i};
  435. }
  436. template <class T>
  437. constexpr inline quaternion<T> div(const quaternion<T>& a, T b) noexcept
  438. {
  439. return {a.r / b, a.i / b};
  440. }
  441. template <class T>
  442. constexpr inline quaternion<T> div(T a, const quaternion<T>& b) noexcept
  443. {
  444. return {a / b.r, a / b.i};
  445. }
  446. template <class T>
  447. inline T length(const quaternion<T>& q)
  448. {
  449. return std::sqrt(length_squared(q));
  450. }
  451. template <class T>
  452. constexpr inline T length_squared(const quaternion<T>& q) noexcept
  453. {
  454. return q.r * q.r + length_squared(q.i);
  455. }
  456. template <class T>
  457. constexpr inline quaternion<T> lerp(const quaternion<T>& a, const quaternion<T>& b, T t) noexcept
  458. {
  459. return
  460. {
  461. (b.r - a.r) * t + a.r,
  462. (b.i - a.i) * t + a.i
  463. };
  464. }
  465. template <class T>
  466. quaternion<T> look_rotation(const vector<T, 3>& forward, vector<T, 3> up)
  467. {
  468. vector<T, 3> right = normalize(cross(forward, up));
  469. up = cross(right, forward);
  470. matrix<T, 3, 3> m =
  471. {
  472. right,
  473. up,
  474. -forward
  475. };
  476. // Convert to quaternion
  477. return normalize(quaternion_cast(m));
  478. }
  479. template <class T>
  480. constexpr matrix<T, 3, 3> matrix_cast(const quaternion<T>& q) noexcept
  481. {
  482. const T xx = q.x() * q.x();
  483. const T xy = q.x() * q.y();
  484. const T xz = q.x() * q.z();
  485. const T xw = q.x() * q.w();
  486. const T yy = q.y() * q.y();
  487. const T yz = q.y() * q.z();
  488. const T yw = q.y() * q.w();
  489. const T zz = q.z() * q.z();
  490. const T zw = q.z() * q.w();
  491. return
  492. {
  493. T(1) - (yy + zz) * T(2), (xy + zw) * T(2), (xz - yw) * T(2),
  494. (xy - zw) * T(2), T(1) - (xx + zz) * T(2), (yz + xw) * T(2),
  495. (xz + yw) * T(2), (yz - xw) * T(2), T(1) - (xx + yy) * T(2)
  496. };
  497. }
  498. template <class T>
  499. constexpr quaternion<T> mul(const quaternion<T>& a, const quaternion<T>& b) noexcept
  500. {
  501. return
  502. {
  503. -a.x() * b.x() - a.y() * b.y() - a.z() * b.z() + a.w() * b.w(),
  504. a.x() * b.w() + a.y() * b.z() - a.z() * b.y() + a.w() * b.x(),
  505. -a.x() * b.z() + a.y() * b.w() + a.z() * b.x() + a.w() * b.y(),
  506. a.x() * b.y() - a.y() * b.x() + a.z() * b.w() + a.w() * b.z()
  507. };
  508. }
  509. template <class T>
  510. constexpr inline quaternion<T> mul(const quaternion<T>& a, T b) noexcept
  511. {
  512. return {a.r * b, a.i * b};
  513. }
  514. template <class T>
  515. constexpr vector<T, 3> mul(const quaternion<T>& a, const vector<T, 3>& b) noexcept
  516. {
  517. return a.i * dot(a.i, b) * T(2) + b * (a.r * a.r - length_squared(a.i)) + cross(a.i, b) * a.r * T(2);
  518. }
  519. template <class T>
  520. constexpr inline vector<T, 3> mul(const vector<T, 3>& a, const quaternion<T>& b) noexcept
  521. {
  522. return mul(conjugate(b), a);
  523. }
  524. template <class T>
  525. constexpr inline quaternion<T> negate(const quaternion<T>& q) noexcept
  526. {
  527. return {-q.r, -q.i};
  528. }
  529. template <class T>
  530. quaternion<T> nlerp(const quaternion<T>& a, const quaternion<T>& b, T t)
  531. {
  532. return normalize(add(mul(a, T(1) - t), mul(b, t * std::copysign(T(1), dot(a, b)))));
  533. }
  534. template <class T>
  535. inline quaternion<T> normalize(const quaternion<T>& q)
  536. {
  537. return mul(q, T(1) / length(q));
  538. }
  539. template <class T>
  540. quaternion<T> angle_axis(T angle, const vector<T, 3>& axis)
  541. {
  542. angle *= T{0.5};
  543. return {std::cos(angle), axis * std::sin(angle)};
  544. }
  545. template <class T>
  546. quaternion<T> rotation(const vector<T, 3>& source, const vector<T, 3>& destination)
  547. {
  548. quaternion<T> q = {dot(source, destination), cross(source, destination)};
  549. q.w() += length(q);
  550. return normalize(q);
  551. }
  552. template <class T>
  553. quaternion<T> slerp(const quaternion<T>& a, const quaternion<T>& b, T t, T error)
  554. {
  555. T cos_theta = dot(a, b);
  556. if (cos_theta > T(1) - error)
  557. return normalize(lerp(a, b, t));
  558. cos_theta = std::max<T>(T(-1), std::min<T>(T(1), cos_theta));
  559. const T theta = std::acos(cos_theta) * t;
  560. quaternion<T> c = normalize(sub(b, mul(a, cos_theta)));
  561. return add(mul(a, std::cos(theta)), mul(c, std::sin(theta)));
  562. }
  563. template <class T>
  564. constexpr inline quaternion<T> sub(const quaternion<T>& a, const quaternion<T>& b) noexcept
  565. {
  566. return {a.r - b.r, a.i - b.i};
  567. }
  568. template <class T>
  569. constexpr inline quaternion<T> sub(const quaternion<T>& a, T b) noexcept
  570. {
  571. return {a.r - b, a.i - b};
  572. }
  573. template <class T>
  574. constexpr inline quaternion<T> sub(T a, const quaternion<T>& b) noexcept
  575. {
  576. return {a - b.r, a - b.i};
  577. }
  578. template <class T>
  579. void swing_twist(const quaternion<T>& q, const vector<T, 3>& a, quaternion<T>& qs, quaternion<T>& qt, T error)
  580. {
  581. if (length_squared(q.i) > error)
  582. {
  583. qt = normalize(quaternion<T>{q.w(), a * dot(a, q.i)});
  584. qs = mul(q, conjugate(qt));
  585. }
  586. else
  587. {
  588. qt = angle_axis(pi<T>, a);
  589. const vector<T, 3> qa = mul(q, a);
  590. const vector<T, 3> sa = cross(a, qa);
  591. if (length_squared(sa) > error)
  592. qs = angle_axis(std::acos(dot(a, qa)), sa);
  593. else
  594. qs = quaternion<T>::identity();
  595. }
  596. }
  597. template <class T>
  598. quaternion<T> quaternion_cast(const matrix<T, 3, 3>& m)
  599. {
  600. const T t = trace(m);
  601. if (t > T(0))
  602. {
  603. T s = T(0.5) / std::sqrt(t + T(1));
  604. return
  605. {
  606. T(0.25) / s,
  607. (m[1][2] - m[2][1]) * s,
  608. (m[2][0] - m[0][2]) * s,
  609. (m[0][1] - m[1][0]) * s
  610. };
  611. }
  612. else
  613. {
  614. if (m[0][0] > m[1][1] && m[0][0] > m[2][2])
  615. {
  616. T s = T(2) * std::sqrt(T(1) + m[0][0] - m[1][1] - m[2][2]);
  617. return
  618. {
  619. (m[1][2] - m[2][1]) / s,
  620. T(0.25) * s,
  621. (m[1][0] + m[0][1]) / s,
  622. (m[2][0] + m[0][2]) / s
  623. };
  624. }
  625. else if (m[1][1] > m[2][2])
  626. {
  627. T s = T(2) * std::sqrt(T(1) + m[1][1] - m[0][0] - m[2][2]);
  628. return
  629. {
  630. (m[2][0] - m[0][2]) / s,
  631. (m[1][0] + m[0][1]) / s,
  632. T(0.25) * s,
  633. (m[2][1] + m[1][2]) / s
  634. };
  635. }
  636. else
  637. {
  638. T s = T(2) * std::sqrt(T(1) + m[2][2] - m[0][0] - m[1][1]);
  639. return
  640. {
  641. (m[0][1] - m[1][0]) / s,
  642. (m[2][0] + m[0][2]) / s,
  643. (m[2][1] + m[1][2]) / s,
  644. T(0.25) * s
  645. };
  646. }
  647. }
  648. }
  649. namespace operators {
  650. /// @copydoc add(const quaternion<T>&, const quaternion<T>&)
  651. template <class T>
  652. constexpr inline quaternion<T> operator+(const quaternion<T>& a, const quaternion<T>& b) noexcept
  653. {
  654. return add(a, b);
  655. }
  656. /// @copydoc add(const quaternion<T>&, T)
  657. /// @{
  658. template <class T>
  659. constexpr inline quaternion<T> operator+(const quaternion<T>& a, T b) noexcept
  660. {
  661. return add(a, b);
  662. }
  663. template <class T>
  664. constexpr inline quaternion<T> operator+(T a, const quaternion<T>& b) noexcept
  665. {
  666. return add(b, a);
  667. }
  668. /// @}
  669. /// @copydoc div(const quaternion<T>&, const quaternion<T>&)
  670. template <class T>
  671. constexpr inline quaternion<T> operator/(const quaternion<T>& a, const quaternion<T>& b) noexcept
  672. {
  673. return div(a, b);
  674. }
  675. /// @copydoc div(const quaternion<T>&, T)
  676. template <class T>
  677. constexpr inline quaternion<T> operator/(const quaternion<T>& a, T b) noexcept
  678. {
  679. return div(a, b);
  680. }
  681. /// @copydoc div(T, const quaternion<T>&)
  682. template <class T>
  683. constexpr inline quaternion<T> operator/(T a, const quaternion<T>& b) noexcept
  684. {
  685. return div(a, b);
  686. }
  687. /// @copydoc mul(const quaternion<T>&, const quaternion<T>&)
  688. template <class T>
  689. constexpr inline quaternion<T> operator*(const quaternion<T>& a, const quaternion<T>& b) noexcept
  690. {
  691. return mul(a, b);
  692. }
  693. /// @copydoc mul(const quaternion<T>&, T)
  694. /// @{
  695. template <class T>
  696. constexpr inline quaternion<T> operator*(const quaternion<T>& a, T b) noexcept
  697. {
  698. return mul(a, b);
  699. }
  700. template <class T>
  701. constexpr inline quaternion<T> operator*(T a, const quaternion<T>& b) noexcept
  702. {
  703. return mul(b, a);
  704. }
  705. /// @}
  706. /// @copydoc mul(const quaternion<T>&, const vector<T, 3>&)
  707. template <class T>
  708. constexpr inline vector<T, 3> operator*(const quaternion<T>& a, const vector<T, 3>& b) noexcept
  709. {
  710. return mul(a, b);
  711. }
  712. /// @copydoc mul(const vector<T, 3>&, const quaternion<T>&)
  713. template <class T>
  714. constexpr inline vector<T, 3> operator*(const vector<T, 3>& a, const quaternion<T>& b) noexcept
  715. {
  716. return mul(a, b);
  717. }
  718. /// @copydoc sub(const quaternion<T>&, const quaternion<T>&)
  719. template <class T>
  720. constexpr inline quaternion<T> operator-(const quaternion<T>& a, const quaternion<T>& b) noexcept
  721. {
  722. return sub(a, b);
  723. }
  724. /// @copydoc sub(const quaternion<T>&, T)
  725. /// @{
  726. template <class T>
  727. constexpr inline quaternion<T> operator-(const quaternion<T>& a, T b) noexcept
  728. {
  729. return sub(a, b);
  730. }
  731. template <class T>
  732. constexpr inline quaternion<T> operator-(T a, const quaternion<T>& b) noexcept
  733. {
  734. return sub(a, b);
  735. }
  736. /// @}
  737. /// @copydoc negate(const quaternion<T>&)
  738. template <class T>
  739. constexpr inline quaternion<T> operator-(const quaternion<T>& q) noexcept
  740. {
  741. return negate(q);
  742. }
  743. /**
  744. * Adds two values and stores the result in the first value.
  745. *
  746. * @param a First value.
  747. * @param b Second value.
  748. *
  749. * @return Reference to the first value.
  750. */
  751. /// @{
  752. template <class T>
  753. constexpr inline quaternion<T>& operator+=(quaternion<T>& a, const quaternion<T>& b) noexcept
  754. {
  755. return (a = a + b);
  756. }
  757. template <class T>
  758. constexpr inline quaternion<T>& operator+=(quaternion<T>& a, T b) noexcept
  759. {
  760. return (a = a + b);
  761. }
  762. /// @}
  763. /**
  764. * Subtracts the first value by the second value and stores the result in the first value.
  765. *
  766. * @param a First value.
  767. * @param b Second value.
  768. *
  769. * @return Reference to the first value.
  770. */
  771. /// @{
  772. template <class T>
  773. constexpr inline quaternion<T>& operator-=(quaternion<T>& a, const quaternion<T>& b) noexcept
  774. {
  775. return (a = a - b);
  776. }
  777. template <class T>
  778. constexpr inline quaternion<T>& operator-=(quaternion<T>& a, T b) noexcept
  779. {
  780. return (a = a - b);
  781. }
  782. /// @}
  783. /**
  784. * Multiplies two values and stores the result in the first value.
  785. *
  786. * @param a First value.
  787. * @param b Second value.
  788. *
  789. * @return Reference to the first value.
  790. */
  791. /// @{
  792. template <class T>
  793. constexpr inline quaternion<T>& operator*=(quaternion<T>& a, const quaternion<T>& b) noexcept
  794. {
  795. return (a = a * b);
  796. }
  797. template <class T>
  798. constexpr inline quaternion<T>& operator*=(quaternion<T>& a, T b) noexcept
  799. {
  800. return (a = a * b);
  801. }
  802. /// @}
  803. /**
  804. * Divides the first value by the second value and stores the result in the first value.
  805. *
  806. * @param a First value.
  807. * @param b Second value.
  808. *
  809. * @return Reference to the first value.
  810. */
  811. /// @{
  812. template <class T>
  813. constexpr inline quaternion<T>& operator/=(quaternion<T>& a, const quaternion<T>& b) noexcept
  814. {
  815. return (a = a / b);
  816. }
  817. template <class T>
  818. constexpr inline quaternion<T>& operator/=(quaternion<T>& a, T b) noexcept
  819. {
  820. return (a = a / b);
  821. }
  822. /// @}
  823. /**
  824. * Writes the real and imaginary parts of a quaternion to an output stream, with each number delimeted by a space.
  825. *
  826. * @param os Output stream.
  827. * @param q Quaternion.
  828. *
  829. * @return Output stream.
  830. */
  831. template <class T>
  832. std::ostream& operator<<(std::ostream& os, const math::quaternion<T>& q)
  833. {
  834. os << q.r << ' ' << q.i;
  835. return os;
  836. }
  837. /**
  838. * Reads the real and imaginary parts of a quaternion from an input stream, with each number delimeted by a space.
  839. *
  840. * @param is Input stream.
  841. * @param q Quaternion.
  842. *
  843. * @return Input stream.
  844. */
  845. template <class T>
  846. std::istream& operator>>(std::istream& is, const math::quaternion<T>& q)
  847. {
  848. is >> q.r;
  849. is >> q.i;
  850. return is;
  851. }
  852. } // namespace operators
  853. } // namespace math
  854. using namespace math::operators;
  855. #endif // ANTKEEPER_MATH_QUATERNION_HPP