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

969 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. * Quaternion composed of a real scalar part and imaginary vector 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. * Constructs a matrix representing the rotation described the quaternion.
  136. *
  137. * @return Rotation matrix.
  138. */
  139. constexpr explicit operator matrix_type() const noexcept
  140. {
  141. const T xx = x() * x();
  142. const T xy = x() * y();
  143. const T xz = x() * z();
  144. const T xw = x() * w();
  145. const T yy = y() * y();
  146. const T yz = y() * z();
  147. const T yw = y() * w();
  148. const T zz = z() * z();
  149. const T zw = z() * w();
  150. return
  151. {
  152. T(1) - (yy + zz) * T(2), (xy + zw) * T(2), (xz - yw) * T(2),
  153. (xy - zw) * T(2), T(1) - (xx + zz) * T(2), (yz + xw) * T(2),
  154. (xz + yw) * T(2), (yz - xw) * T(2), T(1) - (xx + yy) * T(2)
  155. };
  156. }
  157. /**
  158. * 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.
  159. *
  160. * @return Vector containing the real and imaginary parts of the quaternion.
  161. */
  162. constexpr inline explicit operator vector<T, 4>() const noexcept
  163. {
  164. return {r, i[0], i[1], i[2]};
  165. }
  166. /// Returns a zero quaternion, where every scalar is equal to zero.
  167. static constexpr quaternion zero() noexcept
  168. {
  169. return {};
  170. }
  171. /// Returns a rotation identity quaternion.
  172. static constexpr quaternion identity() noexcept
  173. {
  174. return {T{1}, vector_type::zero()};
  175. }
  176. };
  177. /**
  178. * Adds two quaternions.
  179. *
  180. * @param a First quaternion.
  181. * @param b Second quaternion.
  182. *
  183. * @return Sum of the two quaternions.
  184. */
  185. template <class T>
  186. constexpr quaternion<T> add(const quaternion<T>& a, const quaternion<T>& b) noexcept;
  187. /**
  188. * Adds a quaternion and a scalar.
  189. *
  190. * @param a First value.
  191. * @param b Second second value.
  192. *
  193. * @return Sum of the quaternion and scalar.
  194. */
  195. template <class T>
  196. constexpr quaternion<T> add(const quaternion<T>& a, T b) noexcept;
  197. /**
  198. * Calculates the conjugate of a quaternion.
  199. *
  200. * @param q Quaternion from which the conjugate will be calculated.
  201. *
  202. * @return Conjugate of the quaternion.
  203. */
  204. template <class T>
  205. constexpr quaternion<T> conjugate(const quaternion<T>& q) noexcept;
  206. /**
  207. * Calculates the dot product of two quaternions.
  208. *
  209. * @param a First quaternion.
  210. * @param b Second quaternion.
  211. *
  212. * @return Dot product of the two quaternions.
  213. */
  214. template <class T>
  215. constexpr T dot(const quaternion<T>& a, const quaternion<T>& b) noexcept;
  216. /**
  217. * Divides a quaternion by another quaternion.
  218. *
  219. * @param a First value.
  220. * @param b Second value.
  221. *
  222. * @return Result of the division.
  223. */
  224. template <class T>
  225. constexpr quaternion<T> div(const quaternion<T>& a, const quaternion<T>& b) noexcept;
  226. /**
  227. * Divides a quaternion by a scalar.
  228. *
  229. * @param a Quaternion.
  230. * @param b Scalar.
  231. *
  232. * @return Result of the division.
  233. */
  234. template <class T>
  235. constexpr quaternion<T> div(const quaternion<T>& a, T b) noexcept;
  236. /**
  237. * Divides a scalar by a quaternion.
  238. *
  239. * @param a Scalar.
  240. * @param b Quaternion.
  241. *
  242. * @return Result of the division.
  243. */
  244. template <class T>
  245. constexpr quaternion<T> div(T a, const quaternion<T>& b) noexcept;
  246. /**
  247. * Calculates the inverse length of a quaternion.
  248. *
  249. * @param q Quaternion to calculate the inverse length of.
  250. *
  251. * @return Inverse length of the quaternion.
  252. */
  253. template <class T>
  254. T inv_length(const quaternion<T>& q);
  255. /**
  256. * Calculates the length of a quaternion.
  257. *
  258. * @param q Quaternion to calculate the length of.
  259. *
  260. * @return Length of the quaternion.
  261. */
  262. template <class T>
  263. T length(const quaternion<T>& q);
  264. /**
  265. * Performs linear interpolation between two quaternions.
  266. *
  267. * @param a First quaternion.
  268. * @param b Second quaternion.
  269. * @param t Interpolation factor.
  270. *
  271. * @return Interpolated quaternion.
  272. */
  273. template <class T>
  274. constexpr quaternion<T> lerp(const quaternion<T>& a, const quaternion<T>& b, T t) noexcept;
  275. /**
  276. * Creates a unit quaternion rotation using forward and up vectors.
  277. *
  278. * @param forward Unit forward vector.
  279. * @param up Unit up vector.
  280. *
  281. * @return Unit rotation quaternion.
  282. */
  283. template <class T>
  284. quaternion<T> look_rotation(const vector<T, 3>& forward, vector<T, 3> up);
  285. /**
  286. * Multiplies two quaternions.
  287. *
  288. * @param a First quaternion.
  289. * @param b Second quaternion.
  290. *
  291. * @return Product of the two quaternions.
  292. */
  293. template <class T>
  294. constexpr quaternion<T> mul(const quaternion<T>& a, const quaternion<T>& b) noexcept;
  295. /**
  296. * Multiplies a quaternion by a scalar.
  297. *
  298. * @param a First value.
  299. * @param b Second value.
  300. *
  301. * @return Product of the quaternion and scalar.
  302. */
  303. template <class T>
  304. constexpr quaternion<T> mul(const quaternion<T>& a, T b) noexcept;
  305. /**
  306. * Calculates the product of a quaternion and a vector.
  307. *
  308. * @param a First value.
  309. * @param b second value.
  310. *
  311. * @return Product of the quaternion and vector.
  312. */
  313. /// @{
  314. template <class T>
  315. constexpr vector<T, 3> mul(const quaternion<T>& a, const vector<T, 3>& b) noexcept;
  316. template <class T>
  317. constexpr vector<T, 3> mul(const vector<T, 3>& a, const quaternion<T>& b) noexcept;
  318. /// @}
  319. /**
  320. * Negates a quaternion.
  321. *
  322. * @param q Quaternion to negate.
  323. *
  324. * @return Negated quaternion.
  325. */
  326. template <class T>
  327. constexpr quaternion<T> negate(const quaternion<T>& q) noexcept;
  328. /**
  329. * Performs normalized linear interpolation between two quaternions.
  330. *
  331. * @param a First quaternion.
  332. * @param b Second quaternion.
  333. * @param t Interpolation factor.
  334. *
  335. * @return Interpolated quaternion.
  336. */
  337. template <class T>
  338. quaternion<T> nlerp(const quaternion<T>& a, const quaternion<T>& b, T t);
  339. /**
  340. * Normalizes a quaternion.
  341. *
  342. * @param q Quaternion to normalize.
  343. *
  344. * @return Normalized quaternion.
  345. */
  346. template <class T>
  347. quaternion<T> normalize(const quaternion<T>& q);
  348. /**
  349. * Creates a rotation from an angle and axis.
  350. *
  351. * @param angle Angle of rotation (in radians).
  352. * @param axis Axis of rotation
  353. *
  354. * @return Quaternion representing the rotation.
  355. */
  356. template <class T>
  357. quaternion<T> angle_axis(T angle, const vector<T, 3>& axis);
  358. /**
  359. * Calculates the minimum rotation between two normalized direction vectors.
  360. *
  361. * @param source Normalized source direction.
  362. * @param destination Normalized destination direction.
  363. *
  364. * @return Quaternion representing the minimum rotation between the source and destination vectors.
  365. */
  366. template <class T>
  367. quaternion<T> rotation(const vector<T, 3>& source, const vector<T, 3>& destination);
  368. /**
  369. * Performs spherical linear interpolation between two quaternions.
  370. *
  371. * @param a First quaternion.
  372. * @param b Second quaternion.
  373. * @param t Interpolation factor.
  374. *
  375. * @return Interpolated quaternion.
  376. */
  377. template <class T>
  378. quaternion<T> slerp(const quaternion<T>& a, const quaternion<T>& b, T t, T error = T{1e-6});
  379. /**
  380. * Calculates the square length of a quaternion. The square length can be calculated faster than the length because a call to `std::sqrt` is saved.
  381. *
  382. * @param q Quaternion to calculate the square length of.
  383. *
  384. * @return Square length of the quaternion.
  385. */
  386. template <class T>
  387. constexpr T sqr_length(const quaternion<T>& q) noexcept;
  388. /**
  389. * Subtracts a quaternion from another quaternion.
  390. *
  391. * @param a First quaternion.
  392. * @param b Second quaternion.
  393. *
  394. * @return Difference between the quaternions.
  395. */
  396. template <class T>
  397. constexpr quaternion<T> sub(const quaternion<T>& a, const quaternion<T>& b) noexcept;
  398. /**
  399. * Subtracts a quaternion and a scalar.
  400. *
  401. * @param a First value.
  402. * @param b Second second.
  403. *
  404. * @return Difference between the quaternion and scalar.
  405. */
  406. /// @{
  407. template <class T>
  408. constexpr quaternion<T> sub(const quaternion<T>& a, T b) noexcept;
  409. template <class T>
  410. constexpr quaternion<T> sub(T a, const quaternion<T>& b) noexcept;
  411. /// @}
  412. /**
  413. * Decomposes a quaternion into swing and twist rotation components.
  414. *
  415. * @param[in] q Quaternion to decompose.
  416. * @param[in] a Axis of twist rotation.
  417. * @param[out] swing Swing rotation component.
  418. * @param[out] twist Twist rotation component.
  419. * @param[in] error Threshold at which a number is considered zero.
  420. *
  421. * @see https://www.euclideanspace.com/maths/geometry/rotations/for/decomposition/
  422. */
  423. template <class T>
  424. void swing_twist(const quaternion<T>& q, const vector<T, 3>& a, quaternion<T>& qs, quaternion<T>& qt, T error = T{1e-6});
  425. /**
  426. * Converts a 3x3 rotation matrix to a quaternion.
  427. *
  428. * @param m Rotation matrix.
  429. *
  430. * @return Unit quaternion representing the rotation described by @p m.
  431. */
  432. template <class T>
  433. quaternion<T> quaternion_cast(const matrix<T, 3, 3>& m);
  434. template <class T>
  435. constexpr inline quaternion<T> add(const quaternion<T>& a, const quaternion<T>& b) noexcept
  436. {
  437. return {a.r + b.r, a.i + b.i};
  438. }
  439. template <class T>
  440. constexpr inline quaternion<T> add(const quaternion<T>& a, T b) noexcept
  441. {
  442. return {a.r + b, a.i + b};
  443. }
  444. template <class T>
  445. constexpr inline quaternion<T> conjugate(const quaternion<T>& q) noexcept
  446. {
  447. return {q.r, -q.i};
  448. }
  449. template <class T>
  450. constexpr inline T dot(const quaternion<T>& a, const quaternion<T>& b) noexcept
  451. {
  452. return a.r * b.r + dot(a.i, b.i);
  453. }
  454. template <class T>
  455. constexpr inline quaternion<T> div(const quaternion<T>& a, const quaternion<T>& b) noexcept
  456. {
  457. return {a.r / b.r, a.i / b.i};
  458. }
  459. template <class T>
  460. constexpr inline quaternion<T> div(const quaternion<T>& a, T b) noexcept
  461. {
  462. return {a.r / b, a.i / b};
  463. }
  464. template <class T>
  465. constexpr inline quaternion<T> div(T a, const quaternion<T>& b) noexcept
  466. {
  467. return {a / b.r, a / b.i};
  468. }
  469. template <class T>
  470. inline T inv_length(const quaternion<T>& q)
  471. {
  472. return T{1} / length(q);
  473. }
  474. template <class T>
  475. inline T length(const quaternion<T>& q)
  476. {
  477. return std::sqrt(sqr_length(q));
  478. }
  479. template <class T>
  480. constexpr inline quaternion<T> lerp(const quaternion<T>& a, const quaternion<T>& b, T t) noexcept
  481. {
  482. return
  483. {
  484. (b.r - a.r) * t + a.r,
  485. (b.i - a.i) * t + a.i
  486. };
  487. }
  488. template <class T>
  489. quaternion<T> look_rotation(const vector<T, 3>& forward, vector<T, 3> up)
  490. {
  491. vector<T, 3> right = normalize(cross(forward, up));
  492. up = cross(right, forward);
  493. matrix<T, 3, 3> m =
  494. {
  495. right,
  496. up,
  497. -forward
  498. };
  499. // Convert to quaternion
  500. return normalize(quaternion_cast(m));
  501. }
  502. template <class T>
  503. constexpr quaternion<T> mul(const quaternion<T>& a, const quaternion<T>& b) noexcept
  504. {
  505. return
  506. {
  507. -a.x() * b.x() - a.y() * b.y() - a.z() * b.z() + a.w() * b.w(),
  508. a.x() * b.w() + a.y() * b.z() - a.z() * b.y() + a.w() * b.x(),
  509. -a.x() * b.z() + a.y() * b.w() + a.z() * b.x() + a.w() * b.y(),
  510. a.x() * b.y() - a.y() * b.x() + a.z() * b.w() + a.w() * b.z()
  511. };
  512. }
  513. template <class T>
  514. constexpr inline quaternion<T> mul(const quaternion<T>& a, T b) noexcept
  515. {
  516. return {a.r * b, a.i * b};
  517. }
  518. template <class T>
  519. constexpr vector<T, 3> mul(const quaternion<T>& a, const vector<T, 3>& b) noexcept
  520. {
  521. return a.i * dot(a.i, b) * T(2) + b * (a.r * a.r - sqr_length(a.i)) + cross(a.i, b) * a.r * T(2);
  522. }
  523. template <class T>
  524. constexpr inline vector<T, 3> mul(const vector<T, 3>& a, const quaternion<T>& b) noexcept
  525. {
  526. return mul(conjugate(b), a);
  527. }
  528. template <class T>
  529. constexpr inline quaternion<T> negate(const quaternion<T>& q) noexcept
  530. {
  531. return {-q.r, -q.i};
  532. }
  533. template <class T>
  534. quaternion<T> nlerp(const quaternion<T>& a, const quaternion<T>& b, T t)
  535. {
  536. return normalize(add(mul(a, T(1) - t), mul(b, t * std::copysign(T(1), dot(a, b)))));
  537. }
  538. template <class T>
  539. inline quaternion<T> normalize(const quaternion<T>& q)
  540. {
  541. return mul(q, inv_length(q));
  542. }
  543. template <class T>
  544. quaternion<T> angle_axis(T angle, const vector<T, 3>& axis)
  545. {
  546. angle *= T{0.5};
  547. return {std::cos(angle), axis * std::sin(angle)};
  548. }
  549. template <class T>
  550. quaternion<T> rotation(const vector<T, 3>& source, const vector<T, 3>& destination)
  551. {
  552. quaternion<T> q = {dot(source, destination), cross(source, destination)};
  553. q.w() += length(q);
  554. return normalize(q);
  555. }
  556. template <class T>
  557. quaternion<T> slerp(const quaternion<T>& a, const quaternion<T>& b, T t, T error)
  558. {
  559. T cos_theta = dot(a, b);
  560. if (cos_theta > T(1) - error)
  561. return normalize(lerp(a, b, t));
  562. cos_theta = std::max<T>(T(-1), std::min<T>(T(1), cos_theta));
  563. const T theta = std::acos(cos_theta) * t;
  564. quaternion<T> c = normalize(sub(b, mul(a, cos_theta)));
  565. return add(mul(a, std::cos(theta)), mul(c, std::sin(theta)));
  566. }
  567. template <class T>
  568. constexpr inline T sqr_length(const quaternion<T>& q) noexcept
  569. {
  570. return q.r * q.r + sqr_length(q.i);
  571. }
  572. template <class T>
  573. constexpr inline quaternion<T> sub(const quaternion<T>& a, const quaternion<T>& b) noexcept
  574. {
  575. return {a.r - b.r, a.i - b.i};
  576. }
  577. template <class T>
  578. constexpr inline quaternion<T> sub(const quaternion<T>& a, T b) noexcept
  579. {
  580. return {a.r - b, a.i - b};
  581. }
  582. template <class T>
  583. constexpr inline quaternion<T> sub(T a, const quaternion<T>& b) noexcept
  584. {
  585. return {a - b.r, a - b.i};
  586. }
  587. template <class T>
  588. void swing_twist(const quaternion<T>& q, const vector<T, 3>& a, quaternion<T>& qs, quaternion<T>& qt, T error)
  589. {
  590. if (sqr_length(q.i) > error)
  591. {
  592. qt = normalize(quaternion<T>{q.w(), a * dot(a, q.i)});
  593. qs = mul(q, conjugate(qt));
  594. }
  595. else
  596. {
  597. qt = angle_axis(pi<T>, a);
  598. const vector<T, 3> qa = mul(q, a);
  599. const vector<T, 3> sa = cross(a, qa);
  600. if (sqr_length(sa) > error)
  601. qs = angle_axis(std::acos(dot(a, qa)), sa);
  602. else
  603. qs = quaternion<T>::identity();
  604. }
  605. }
  606. template <class T>
  607. quaternion<T> quaternion_cast(const matrix<T, 3, 3>& m)
  608. {
  609. const T t = trace(m);
  610. if (t > T(0))
  611. {
  612. T s = T(0.5) / std::sqrt(t + T(1));
  613. return
  614. {
  615. T(0.25) / s,
  616. (m[1][2] - m[2][1]) * s,
  617. (m[2][0] - m[0][2]) * s,
  618. (m[0][1] - m[1][0]) * s
  619. };
  620. }
  621. else
  622. {
  623. if (m[0][0] > m[1][1] && m[0][0] > m[2][2])
  624. {
  625. T s = T(2) * std::sqrt(T(1) + m[0][0] - m[1][1] - m[2][2]);
  626. return
  627. {
  628. (m[1][2] - m[2][1]) / s,
  629. T(0.25) * s,
  630. (m[1][0] + m[0][1]) / s,
  631. (m[2][0] + m[0][2]) / s
  632. };
  633. }
  634. else if (m[1][1] > m[2][2])
  635. {
  636. T s = T(2) * std::sqrt(T(1) + m[1][1] - m[0][0] - m[2][2]);
  637. return
  638. {
  639. (m[2][0] - m[0][2]) / s,
  640. (m[1][0] + m[0][1]) / s,
  641. T(0.25) * s,
  642. (m[2][1] + m[1][2]) / s
  643. };
  644. }
  645. else
  646. {
  647. T s = T(2) * std::sqrt(T(1) + m[2][2] - m[0][0] - m[1][1]);
  648. return
  649. {
  650. (m[0][1] - m[1][0]) / s,
  651. (m[2][0] + m[0][2]) / s,
  652. (m[2][1] + m[1][2]) / s,
  653. T(0.25) * s
  654. };
  655. }
  656. }
  657. }
  658. namespace operators {
  659. /// @copydoc add(const quaternion<T>&, const quaternion<T>&)
  660. template <class T>
  661. constexpr inline quaternion<T> operator+(const quaternion<T>& a, const quaternion<T>& b) noexcept
  662. {
  663. return add(a, b);
  664. }
  665. /// @copydoc add(const quaternion<T>&, T)
  666. /// @{
  667. template <class T>
  668. constexpr inline quaternion<T> operator+(const quaternion<T>& a, T b) noexcept
  669. {
  670. return add(a, b);
  671. }
  672. template <class T>
  673. constexpr inline quaternion<T> operator+(T a, const quaternion<T>& b) noexcept
  674. {
  675. return add(b, a);
  676. }
  677. /// @}
  678. /// @copydoc div(const quaternion<T>&, const quaternion<T>&)
  679. template <class T>
  680. constexpr inline quaternion<T> operator/(const quaternion<T>& a, const quaternion<T>& b) noexcept
  681. {
  682. return div(a, b);
  683. }
  684. /// @copydoc div(const quaternion<T>&, T)
  685. template <class T>
  686. constexpr inline quaternion<T> operator/(const quaternion<T>& a, T b) noexcept
  687. {
  688. return div(a, b);
  689. }
  690. /// @copydoc div(T, const quaternion<T>&)
  691. template <class T>
  692. constexpr inline quaternion<T> operator/(T a, const quaternion<T>& b) noexcept
  693. {
  694. return div(a, b);
  695. }
  696. /// @copydoc mul(const quaternion<T>&, const quaternion<T>&)
  697. template <class T>
  698. constexpr inline quaternion<T> operator*(const quaternion<T>& a, const quaternion<T>& b) noexcept
  699. {
  700. return mul(a, b);
  701. }
  702. /// @copydoc mul(const quaternion<T>&, T)
  703. /// @{
  704. template <class T>
  705. constexpr inline quaternion<T> operator*(const quaternion<T>& a, T b) noexcept
  706. {
  707. return mul(a, b);
  708. }
  709. template <class T>
  710. constexpr inline quaternion<T> operator*(T a, const quaternion<T>& b) noexcept
  711. {
  712. return mul(b, a);
  713. }
  714. /// @}
  715. /// @copydoc mul(const quaternion<T>&, const vector<T, 3>&)
  716. template <class T>
  717. constexpr inline vector<T, 3> operator*(const quaternion<T>& a, const vector<T, 3>& b) noexcept
  718. {
  719. return mul(a, b);
  720. }
  721. /// @copydoc mul(const vector<T, 3>&, const quaternion<T>&)
  722. template <class T>
  723. constexpr inline vector<T, 3> operator*(const vector<T, 3>& a, const quaternion<T>& b) noexcept
  724. {
  725. return mul(a, b);
  726. }
  727. /// @copydoc sub(const quaternion<T>&, const quaternion<T>&)
  728. template <class T>
  729. constexpr inline quaternion<T> operator-(const quaternion<T>& a, const quaternion<T>& b) noexcept
  730. {
  731. return sub(a, b);
  732. }
  733. /// @copydoc sub(const quaternion<T>&, T)
  734. /// @{
  735. template <class T>
  736. constexpr inline quaternion<T> operator-(const quaternion<T>& a, T b) noexcept
  737. {
  738. return sub(a, b);
  739. }
  740. template <class T>
  741. constexpr inline quaternion<T> operator-(T a, const quaternion<T>& b) noexcept
  742. {
  743. return sub(a, b);
  744. }
  745. /// @}
  746. /// @copydoc negate(const quaternion<T>&)
  747. template <class T>
  748. constexpr inline quaternion<T> operator-(const quaternion<T>& q) noexcept
  749. {
  750. return negate(q);
  751. }
  752. /**
  753. * Adds two values and stores the result in the first value.
  754. *
  755. * @param a First value.
  756. * @param b Second value.
  757. *
  758. * @return Reference to the first value.
  759. */
  760. /// @{
  761. template <class T>
  762. constexpr inline quaternion<T>& operator+=(quaternion<T>& a, const quaternion<T>& b) noexcept
  763. {
  764. return (a = a + b);
  765. }
  766. template <class T>
  767. constexpr inline quaternion<T>& operator+=(quaternion<T>& a, T b) noexcept
  768. {
  769. return (a = a + b);
  770. }
  771. /// @}
  772. /**
  773. * Subtracts the first value by the second value and stores the result in the first value.
  774. *
  775. * @param a First value.
  776. * @param b Second value.
  777. *
  778. * @return Reference to the first value.
  779. */
  780. /// @{
  781. template <class T>
  782. constexpr inline quaternion<T>& operator-=(quaternion<T>& a, const quaternion<T>& b) noexcept
  783. {
  784. return (a = a - b);
  785. }
  786. template <class T>
  787. constexpr inline quaternion<T>& operator-=(quaternion<T>& a, T b) noexcept
  788. {
  789. return (a = a - b);
  790. }
  791. /// @}
  792. /**
  793. * Multiplies two values and stores the result in the first value.
  794. *
  795. * @param a First value.
  796. * @param b Second value.
  797. *
  798. * @return Reference to the first value.
  799. */
  800. /// @{
  801. template <class T>
  802. constexpr inline quaternion<T>& operator*=(quaternion<T>& a, const quaternion<T>& b) noexcept
  803. {
  804. return (a = a * b);
  805. }
  806. template <class T>
  807. constexpr inline quaternion<T>& operator*=(quaternion<T>& a, T b) noexcept
  808. {
  809. return (a = a * b);
  810. }
  811. /// @}
  812. /**
  813. * Divides the first value by the second value and stores the result in the first value.
  814. *
  815. * @param a First value.
  816. * @param b Second value.
  817. *
  818. * @return Reference to the first value.
  819. */
  820. /// @{
  821. template <class T>
  822. constexpr inline quaternion<T>& operator/=(quaternion<T>& a, const quaternion<T>& b) noexcept
  823. {
  824. return (a = a / b);
  825. }
  826. template <class T>
  827. constexpr inline quaternion<T>& operator/=(quaternion<T>& a, T b) noexcept
  828. {
  829. return (a = a / b);
  830. }
  831. /// @}
  832. /**
  833. * Writes the real and imaginary parts of a quaternion to an output stream, with each number delimeted by a space.
  834. *
  835. * @param os Output stream.
  836. * @param q Quaternion.
  837. *
  838. * @return Output stream.
  839. */
  840. template <class T>
  841. std::ostream& operator<<(std::ostream& os, const math::quaternion<T>& q)
  842. {
  843. os << q.r << ' ' << q.i;
  844. return os;
  845. }
  846. /**
  847. * Reads the real and imaginary parts of a quaternion from an input stream, with each number delimeted by a space.
  848. *
  849. * @param is Input stream.
  850. * @param q Quaternion.
  851. *
  852. * @return Input stream.
  853. */
  854. template <class T>
  855. std::istream& operator>>(std::istream& is, const math::quaternion<T>& q)
  856. {
  857. is >> q.r;
  858. is >> q.i;
  859. return is;
  860. }
  861. } // namespace operators
  862. } // namespace math
  863. using namespace math::operators;
  864. #endif // ANTKEEPER_MATH_QUATERNION_HPP