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

1903 lines
49 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_VECTOR_HPP
  20. #define ANTKEEPER_MATH_VECTOR_HPP
  21. #include <algorithm>
  22. #include <cstddef>
  23. #include <cstring>
  24. #include <cmath>
  25. #include <concepts>
  26. #include <format>
  27. #include <iterator>
  28. #include <limits>
  29. #include <type_traits>
  30. #include <utility>
  31. namespace math {
  32. /**
  33. * *n*-dimensional vector.
  34. *
  35. * @tparam T Element type.
  36. * @tparam N Number of elements.
  37. */
  38. template <class T, std::size_t N>
  39. struct vector
  40. {
  41. /// Element type.
  42. using element_type = T;
  43. /// Number of elements.
  44. static constexpr std::size_t element_count = N;
  45. /// Array of elements.
  46. element_type elements[N];
  47. /// @name Conversion
  48. /// @{
  49. /// @private
  50. template <class U, std::size_t... I>
  51. [[nodiscard]] inline constexpr vector<U, N> type_cast(std::index_sequence<I...>) const noexcept
  52. {
  53. return {static_cast<U>(elements[I])...};
  54. }
  55. /**
  56. * Type-casts the elements of this vector using `static_cast`.
  57. *
  58. * @tparam U Target element type.
  59. *
  60. * @return Vector containing the type-casted elements.
  61. */
  62. template <class U>
  63. [[nodiscard]] inline constexpr explicit operator vector<U, N>() const noexcept
  64. {
  65. return type_cast<U>(std::make_index_sequence<N>{});
  66. }
  67. /// @private
  68. template <std::size_t M, std::size_t... I>
  69. [[nodiscard]] inline constexpr vector<T, M> size_cast(std::index_sequence<I...>) const noexcept
  70. {
  71. return {(I < N) ? elements[I] : T{0} ...};
  72. }
  73. /**
  74. * Size-casts this vector to a vector with a different number of elements. Casting to a greater number of elements causes new elements to be set to zero.
  75. *
  76. * @tparam M Target number of elements.
  77. *
  78. * @return *m*-dimensional vector.
  79. */
  80. template <std::size_t M>
  81. [[nodiscard]] inline constexpr explicit operator vector<T, M>() const noexcept
  82. {
  83. return size_cast<M>(std::make_index_sequence<M>{});
  84. }
  85. /// @}
  86. /// @name Element access
  87. /// @{
  88. /**
  89. * Returns a reference to the element at a given index.
  90. *
  91. * @param i Index of an element.
  92. *
  93. * @return Reference to the element at index @p i.
  94. */
  95. /// @{
  96. [[nodiscard]] inline constexpr element_type& operator[](std::size_t i) noexcept
  97. {
  98. return elements[i];
  99. }
  100. [[nodiscard]] inline constexpr const element_type& operator[](std::size_t i) const noexcept
  101. {
  102. return elements[i];
  103. }
  104. /// @}
  105. /**
  106. * Returns a reference to the first element.
  107. */
  108. /// @{
  109. [[nodiscard]] inline constexpr element_type& front() noexcept
  110. {
  111. return elements[0];
  112. }
  113. [[nodiscard]] inline constexpr const element_type& front() const noexcept
  114. {
  115. return elements[0];
  116. }
  117. /// @}
  118. /**
  119. * Returns a reference to the last element.
  120. */
  121. /// @{
  122. [[nodiscard]] inline constexpr element_type& back() noexcept
  123. {
  124. return elements[N - 1];
  125. }
  126. [[nodiscard]] inline constexpr const element_type& back() const noexcept
  127. {
  128. return elements[N - 1];
  129. }
  130. /// @}
  131. /**
  132. * Returns a pointer to the element array.
  133. */
  134. /// @{
  135. [[nodiscard]] inline constexpr element_type* data() noexcept
  136. {
  137. return elements;
  138. };
  139. [[nodiscard]] inline constexpr const element_type* data() const noexcept
  140. {
  141. return elements;
  142. };
  143. /// @}
  144. /// Returns a reference to the first element.
  145. /// @{
  146. [[nodiscard]] inline constexpr element_type& x() noexcept
  147. {
  148. static_assert(N > 0, "Vector does not contain an x element.");
  149. return elements[0];
  150. }
  151. [[nodiscard]] inline constexpr const element_type& x() const noexcept
  152. {
  153. static_assert(N > 0, "Vector does not contain an x element.");
  154. return elements[0];
  155. }
  156. /// @}
  157. /**
  158. * Returns a reference to the second element.
  159. */
  160. /// @{
  161. [[nodiscard]] inline constexpr element_type& y() noexcept
  162. {
  163. static_assert(N > 1, "Vector does not contain a y element.");
  164. return elements[1];
  165. }
  166. [[nodiscard]] inline constexpr const element_type& y() const noexcept
  167. {
  168. static_assert(N > 1, "Vector does not contain a y element.");
  169. return elements[1];
  170. }
  171. /// @}
  172. /**
  173. * Returns a reference to the third element.
  174. */
  175. /// @{
  176. [[nodiscard]] inline constexpr element_type& z() noexcept
  177. {
  178. static_assert(N > 2, "Vector does not contain a z element.");
  179. return elements[2];
  180. }
  181. [[nodiscard]] inline constexpr const element_type& z() const noexcept
  182. {
  183. static_assert(N > 2, "Vector does not contain a z element.");
  184. return elements[2];
  185. }
  186. /// @}
  187. /// @}
  188. /// @name Iterators
  189. /// @{
  190. /**
  191. * Returns an iterator to the first element.
  192. */
  193. /// @{
  194. [[nodiscard]] inline constexpr element_type* begin() noexcept
  195. {
  196. return elements;
  197. }
  198. [[nodiscard]] inline constexpr const element_type* begin() const noexcept
  199. {
  200. return elements;
  201. }
  202. [[nodiscard]] inline constexpr const element_type* cbegin() const noexcept
  203. {
  204. return elements;
  205. }
  206. /// @}
  207. /**
  208. * Returns an iterator to the element following the last element.
  209. */
  210. /// @{
  211. [[nodiscard]] inline constexpr element_type* end() noexcept
  212. {
  213. return elements + N;
  214. }
  215. [[nodiscard]] inline constexpr const element_type* end() const noexcept
  216. {
  217. return elements + N;
  218. }
  219. [[nodiscard]] inline constexpr const element_type* cend() const noexcept
  220. {
  221. return elements + N;
  222. }
  223. /// @}
  224. /**
  225. * Returns a reverse iterator to the first element of the reversed vector.
  226. */
  227. /// @{
  228. [[nodiscard]] inline constexpr std::reverse_iterator<element_type*> rbegin() noexcept
  229. {
  230. return std::reverse_iterator<element_type*>(elements + N);
  231. }
  232. [[nodiscard]] inline constexpr std::reverse_iterator<const element_type*> rbegin() const noexcept
  233. {
  234. return std::reverse_iterator<const element_type*>(elements + N);
  235. }
  236. [[nodiscard]] inline constexpr std::reverse_iterator<const element_type*> crbegin() const noexcept
  237. {
  238. return std::reverse_iterator<const element_type*>(elements + N);
  239. }
  240. /// @}
  241. /**
  242. * Returns a reverse iterator to the element following the last element of the reversed vector.
  243. */
  244. /// @{
  245. [[nodiscard]] inline constexpr std::reverse_iterator<element_type*> rend() noexcept
  246. {
  247. return std::reverse_iterator<element_type*>(elements);
  248. }
  249. [[nodiscard]] inline constexpr std::reverse_iterator<const element_type*> rend() const noexcept
  250. {
  251. return std::reverse_iterator<const element_type*>(elements);
  252. }
  253. [[nodiscard]] inline constexpr std::reverse_iterator<const element_type*> crend() const noexcept
  254. {
  255. return std::reverse_iterator<const element_type*>(elements);
  256. }
  257. /// @}
  258. /// @}
  259. /// @name Capacity
  260. /// @{
  261. /**
  262. * Returns the number of elements in the vector.
  263. */
  264. [[nodiscard]] inline constexpr std::size_t size() const noexcept
  265. {
  266. return N;
  267. };
  268. /// @}
  269. /// @name Constants
  270. /// @{
  271. /**
  272. * Returns a zero vector, where every element is equal to zero.
  273. */
  274. [[nodiscard]] inline static constexpr vector zero() noexcept
  275. {
  276. return {};
  277. }
  278. /// @private
  279. template <std::size_t... I>
  280. [[nodiscard]] inline static constexpr vector one(std::index_sequence<I...>) noexcept
  281. {
  282. //return {element_type{1}...};
  283. // MSVC bug workaround (I must be referenced for parameter pack expansion)
  284. return {(I ? element_type{1} : element_type{1})...};
  285. }
  286. /**
  287. * Returns a vector of ones, where every element is equal to one.
  288. */
  289. [[nodiscard]] inline static constexpr vector one() noexcept
  290. {
  291. return one(std::make_index_sequence<N>{});
  292. }
  293. /// @private
  294. template <std::size_t... I>
  295. [[nodiscard]] inline static constexpr vector infinity(std::index_sequence<I...>) noexcept
  296. {
  297. //return {element_type{1}...};
  298. // MSVC bug workaround (I must be referenced for parameter pack expansion)
  299. return {(I ? std::numeric_limits<element_type>::infinity() : std::numeric_limits<element_type>::infinity())...};
  300. }
  301. /**
  302. * Returns a vector of infinities, where every element is equal to infinity.
  303. */
  304. [[nodiscard]] inline static constexpr vector infinity() noexcept
  305. {
  306. return infinity(std::make_index_sequence<N>{});
  307. }
  308. /// @}
  309. };
  310. /// Vector types.
  311. namespace vector_types {
  312. /**
  313. * 2-dimensional vector.
  314. *
  315. * @tparam T Element type.
  316. */
  317. template <class T>
  318. using vec2 = vector<T, 2>;
  319. /**
  320. * 3-dimensional vector.
  321. *
  322. * @tparam T Element type.
  323. */
  324. template <class T>
  325. using vec3 = vector<T, 3>;
  326. /**
  327. * 4-dimensional vector.
  328. *
  329. * @tparam T Element type.
  330. */
  331. template <class T>
  332. using vec4 = vector<T, 4>;
  333. /**
  334. * *n*-dimensional vector of Boolean values.
  335. *
  336. * @tparam N Number of elements
  337. */
  338. /// @{
  339. template <std::size_t N>
  340. using bvec = vector<bool, N>;
  341. using bvec2 = bvec<2>;
  342. using bvec3 = bvec<3>;
  343. using bvec4 = bvec<4>;
  344. /// @}
  345. /**
  346. * *n*-dimensional vector of signed integers.
  347. *
  348. * @tparam N Number of elements
  349. */
  350. /// @{
  351. template <std::size_t N>
  352. using ivec = vector<int, N>;
  353. using ivec2 = ivec<2>;
  354. using ivec3 = ivec<3>;
  355. using ivec4 = ivec<4>;
  356. /// @}
  357. /**
  358. * *n*-dimensional vector of unsigned integers.
  359. *
  360. * @tparam N Number of elements
  361. */
  362. /// @{
  363. template <std::size_t N>
  364. using uvec = vector<unsigned int, N>;
  365. using uvec2 = uvec<2>;
  366. using uvec3 = uvec<3>;
  367. using uvec4 = uvec<4>;
  368. /// @}
  369. /**
  370. * *n*-dimensional vector of single-precision floating-point numbers.
  371. *
  372. * @tparam N Number of elements
  373. */
  374. /// @{
  375. template <std::size_t N>
  376. using fvec = vector<float, N>;
  377. using fvec2 = fvec<2>;
  378. using fvec3 = fvec<3>;
  379. using fvec4 = fvec<4>;
  380. /// @}
  381. /**
  382. * *n*-dimensional vector of double-precision floating-point numbers.
  383. *
  384. * @tparam N Number of elements
  385. */
  386. /// @{
  387. template <std::size_t N>
  388. using dvec = vector<double, N>;
  389. using dvec2 = dvec<2>;
  390. using dvec3 = dvec<3>;
  391. using dvec4 = dvec<4>;
  392. /// @}
  393. } // namespace vector_types
  394. // Bring vector types into math namespace
  395. using namespace vector_types;
  396. // Bring vector types into math::types namespace
  397. namespace types { using namespace math::vector_types; }
  398. /**
  399. * Returns the absolute values of each element.
  400. *
  401. * @param x Input vector.
  402. *
  403. * @return Absolute values of input vector elements.
  404. */
  405. template <class T, std::size_t N>
  406. [[nodiscard]] constexpr vector<T, N> abs(const vector<T, N>& x);
  407. /**
  408. * Adds two values.
  409. *
  410. * @param x First value.
  411. * @param y Second value.
  412. *
  413. * @return Sum of the two values.
  414. */
  415. /// @{
  416. template <class T, std::size_t N>
  417. [[nodiscard]] constexpr vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y) noexcept;
  418. template <class T, std::size_t N>
  419. [[nodiscard]] constexpr vector<T, N> add(const vector<T, N>& x, T y) noexcept;
  420. /// @}
  421. /**
  422. * Checks if all elements of a boolean vector are `true`.
  423. *
  424. * @param x Vector to be tested for truth.
  425. *
  426. * @return `true` if all elements are `true`, `false` otherwise.
  427. */
  428. template <std::size_t N>
  429. [[nodiscard]] constexpr bool all(const vector<bool, N>& x) noexcept;
  430. /**
  431. * Calculates the angle between two direction vectors.
  432. *
  433. * @param from First direction vector.
  434. * @param to Second direction vector.
  435. *
  436. * @return Angle between the two direction vectors, in radians.
  437. */
  438. template <std::floating_point T, std::size_t N>
  439. [[nodiscard]] T angle(const vector<T, N>& from, const vector<T, N>& to);
  440. /**
  441. * Checks if any elements of a boolean vector are `true`.
  442. *
  443. * @param x Vector to be tested for truth.
  444. *
  445. * @return `true` if any elements are `true`, `false` otherwise.
  446. */
  447. template <std::size_t N>
  448. [[nodiscard]] constexpr bool any(const vector<bool, N>& x) noexcept;
  449. /**
  450. * Performs an element-wise ceil operation.
  451. *
  452. * @param x Input vector.
  453. *
  454. * @return Component-wise ceil of input vector.
  455. */
  456. template <std::floating_point T, std::size_t N>
  457. [[nodiscard]] constexpr vector<T, N> ceil(const vector<T, N>& x);
  458. /**
  459. * Clamps the values of a vector's elements.
  460. *
  461. * @param x Vector to clamp.
  462. * @param min Minimum value.
  463. * @param max Maximum value.
  464. *
  465. * @return Clamped vector.
  466. */
  467. /// @{
  468. template <class T, std::size_t N>
  469. [[nodiscard]] constexpr vector<T, N> clamp(const vector<T, N>& x, const vector<T, N>& min, const vector<T, N>& max);
  470. template <class T, std::size_t N>
  471. [[nodiscard]] constexpr vector<T, N> clamp(const vector<T, N>& x, T min, T max);
  472. /// @}
  473. /**
  474. * Clamps the length of a vector.
  475. *
  476. * @param x Vector to clamp.
  477. * @param max_length Maximum length.
  478. *
  479. * @return Length-clamped vector.
  480. */
  481. template <std::floating_point T, std::size_t N>
  482. [[nodiscard]] vector<T, N> clamp_length(const vector<T, N>& x, T max_length);
  483. /**
  484. * Calculates the cross product of two vectors.
  485. *
  486. * @param x First vector.
  487. * @param y Second vector.
  488. *
  489. * @return Cross product of the two vectors.
  490. */
  491. template <class T>
  492. [[nodiscard]] constexpr vector<T, 3> cross(const vector<T, 3>& x, const vector<T, 3>& y) noexcept;
  493. /**
  494. * Calculates the distance between two points.
  495. *
  496. * @param p0 First of two points.
  497. * @param p1 Second of two points.
  498. *
  499. * @return Distance between the two points.
  500. */
  501. template <std::floating_point T, std::size_t N>
  502. [[nodiscard]] T distance(const vector<T, N>& p0, const vector<T, N>& p1);
  503. /**
  504. * Divides a vector by a value.
  505. *
  506. * @param x First value.
  507. * @param y Second value.
  508. *
  509. * @return Result of the division.
  510. */
  511. /// @{
  512. template <class T, std::size_t N>
  513. [[nodiscard]] constexpr vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y) noexcept;
  514. template <class T, std::size_t N>
  515. [[nodiscard]] constexpr vector<T, N> div(const vector<T, N>& x, T y) noexcept;
  516. template <class T, std::size_t N>
  517. [[nodiscard]] constexpr vector<T, N> div(T x, const vector<T, N>& y) noexcept;
  518. /// @}
  519. /**
  520. * Calculates the dot product of two vectors.
  521. *
  522. * @param x First vector.
  523. * @param y Second vector.
  524. *
  525. * @return Dot product of the two vectors.
  526. */
  527. template <class T, std::size_t N>
  528. [[nodiscard]] constexpr T dot(const vector<T, N>& x, const vector<T, N>& y) noexcept;
  529. /**
  530. * Compares two vectors for equality
  531. *
  532. * @param x First vector.
  533. * @param y Second vector.
  534. *
  535. * @return Boolean vector containing the result of the element comparisons.
  536. */
  537. template <class T, std::size_t N>
  538. [[nodiscard]] constexpr vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y) noexcept;
  539. /**
  540. * Performs a element-wise floor operation.
  541. *
  542. * @param x Input vector.
  543. *
  544. * @return Component-wise floor of input vector.
  545. */
  546. template <std::floating_point T, std::size_t N>
  547. [[nodiscard]] constexpr vector<T, N> floor(const vector<T, N>& x);
  548. /**
  549. * Performs a multiply-add operation.
  550. *
  551. * @param x Input vector
  552. * @param y Value to multiply.
  553. * @param z Value to add.
  554. *
  555. * @return Vector containing the multiply-add results.
  556. */
  557. /// @{
  558. template <class T, std::size_t N>
  559. [[nodiscard]] constexpr vector<T, N> fma(const vector<T, N>& x, const vector<T, N>& y, const vector<T, N>& z);
  560. template <class T, std::size_t N>
  561. [[nodiscard]] constexpr vector<T, N> fma(const vector<T, N>& x, T y, T z);
  562. /// @}
  563. /**
  564. * Returns a vector containing the fractional part of each element.
  565. *
  566. * @param x Input vector.
  567. *
  568. * @return Fractional parts of input vector.
  569. */
  570. template <std::floating_point T, std::size_t N>
  571. [[nodiscard]] constexpr vector<T, N> fract(const vector<T, N>& x);
  572. /**
  573. * Extracts the Ith element from a vector.
  574. *
  575. * @tparam I Index of an element.
  576. * @tparam T Element type.
  577. * @tparam N Number of elements.
  578. *
  579. * @param v Vector from which to extract an element.
  580. *
  581. * @return Reference to the Ith element of @p v.
  582. */
  583. /// @{
  584. template<std::size_t I, class T, std::size_t N>
  585. [[nodiscard]] constexpr T& get(math::vector<T, N>& v) noexcept;
  586. template<std::size_t I, class T, std::size_t N>
  587. [[nodiscard]] constexpr T&& get(math::vector<T, N>&& v) noexcept;
  588. template<std::size_t I, class T, std::size_t N>
  589. [[nodiscard]] constexpr const T& get(const math::vector<T, N>& v) noexcept;
  590. template<std::size_t I, class T, std::size_t N>
  591. [[nodiscard]] constexpr const T&& get(const math::vector<T, N>&& v) noexcept;
  592. /// @}
  593. /**
  594. * Performs a element-wise greater-than comparison of two vectors.
  595. *
  596. * @param x First vector.
  597. * @param y Second vector.
  598. *
  599. * @return Boolean vector containing the result of the element comparisons.
  600. */
  601. template <class T, std::size_t N>
  602. [[nodiscard]] constexpr vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y) noexcept;
  603. /**
  604. * Performs a element-wise greater-than or equal-to comparison of two vectors.
  605. *
  606. * @param x First vector.
  607. * @param y Second vector.
  608. *
  609. * @return Boolean vector containing the result of the element comparisons.
  610. */
  611. template <class T, std::size_t N>
  612. [[nodiscard]] constexpr vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y) noexcept;
  613. /**
  614. * Calculates the inverse length of a vector.
  615. *
  616. * @param x Vector of which to calculate the inverse length.
  617. *
  618. * @return Inverse length of the vector.
  619. */
  620. template <std::floating_point T, std::size_t N>
  621. [[nodiscard]] T inv_length(const vector<T, N>& x);
  622. /**
  623. * Calculates the length of a vector.
  624. *
  625. * @param x Vector of which to calculate the length.
  626. *
  627. * @return Length of the vector.
  628. */
  629. template <std::floating_point T, std::size_t N>
  630. [[nodiscard]] T length(const vector<T, N>& x);
  631. /**
  632. * Performs a element-wise less-than comparison of two vectors.
  633. *
  634. * @param x First vector.
  635. * @param y Second vector.
  636. *
  637. * @return Boolean vector containing the result of the element comparisons.
  638. */
  639. template <class T, std::size_t N>
  640. [[nodiscard]] constexpr vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y) noexcept;
  641. /**
  642. * Performs a element-wise less-than or equal-to comparison of two vectors.
  643. *
  644. * @param x First vector.
  645. * @param y Second vector.
  646. *
  647. * @return Boolean vector containing the result of the element comparisons.
  648. */
  649. template <class T, std::size_t N>
  650. [[nodiscard]] constexpr vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y) noexcept;
  651. /**
  652. * Returns a vector containing the maximum elements of two vectors.
  653. *
  654. * @param x First vector.
  655. * @param y Second vector.
  656. *
  657. * @return Maximum elements of the two vectors.
  658. */
  659. template <class T, std::size_t N>
  660. [[nodiscard]] constexpr vector<T, N> max(const vector<T, N>& x, const vector<T, N>& y);
  661. /**
  662. * Returns the value of the greatest element in a vector.
  663. *
  664. * @param x Input vector.
  665. *
  666. * @return Value of the greatest element in the input vector.
  667. */
  668. template <class T, std::size_t N>
  669. [[nodiscard]] constexpr T max(const vector<T, N>& x);
  670. /**
  671. * Returns a vector containing the minimum elements of two vectors.
  672. *
  673. * @param x First vector.
  674. * @param y Second vector.
  675. *
  676. * @return Minimum elements of the two vectors.
  677. */
  678. template <class T, std::size_t N>
  679. [[nodiscard]] constexpr vector<T, N> min(const vector<T, N>& x, const vector<T, N>& y);
  680. /**
  681. * Returns the value of the smallest element in a vector.
  682. *
  683. * @param x Input vector.
  684. *
  685. * @return Value of the smallest element in the input vector.
  686. */
  687. template <class T, std::size_t N>
  688. [[nodiscard]] constexpr T min(const vector<T, N>& x);
  689. /**
  690. * Calculates the element-wise remainder of the division operation `x / y`.
  691. *
  692. * @param x First vector.
  693. * @param y Second vector.
  694. *
  695. * @return Remainders of `x / y`.
  696. */
  697. /// @{
  698. template <std::floating_point T, std::size_t N>
  699. [[nodiscard]] constexpr vector<T, N> mod(const vector<T, N>& x, const vector<T, N>& y);
  700. template <std::floating_point T, std::size_t N>
  701. [[nodiscard]] constexpr vector<T, N> mod(const vector<T, N>& x, T y);
  702. /// @}
  703. /**
  704. * Multiplies two values.
  705. *
  706. * @param x First value.
  707. * @param y Second value.
  708. *
  709. * @return Product of the two values.
  710. */
  711. /// @{
  712. template <class T, std::size_t N>
  713. [[nodiscard]] constexpr vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y) noexcept;
  714. template <class T, std::size_t N>
  715. [[nodiscard]] constexpr vector<T, N> mul(const vector<T, N>& x, T y) noexcept;
  716. /// @}
  717. /**
  718. * Negates a vector.
  719. *
  720. * @param x Vector to negate.
  721. *
  722. * @return Negated vector.
  723. */
  724. template <class T, std::size_t N>
  725. [[nodiscard]] constexpr vector<T, N> negate(const vector<T, N>& x) noexcept;
  726. /**
  727. * Calculates the unit vector in the same direction as the original vector.
  728. *
  729. * @param x Vector to normalize.
  730. *
  731. * @return Unit vector.
  732. */
  733. template <std::floating_point T, std::size_t N>
  734. [[nodiscard]] vector<T, N> normalize(const vector<T, N>& x);
  735. /**
  736. * Logically inverts a boolean vector.
  737. *
  738. * @param x Vector to be inverted.
  739. *
  740. * @return Logically inverted vector.
  741. */
  742. template <class T, std::size_t N>
  743. [[nodiscard]] constexpr vector<bool, N> logical_not(const vector<T, N>& x) noexcept;
  744. /**
  745. * Compares two vectors for inequality
  746. *
  747. * @param x First vector.
  748. * @param y Second vector.
  749. *
  750. * @return Boolean vector containing the result of the element comparisons.
  751. */
  752. template <class T, std::size_t N>
  753. [[nodiscard]] constexpr vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y) noexcept;
  754. /**
  755. * Raises each element to a power.
  756. *
  757. * @param x Input vector
  758. * @param y Exponent.
  759. *
  760. * @return Vector with its elements raised to the given power.
  761. */
  762. /// @{
  763. template <std::floating_point T, std::size_t N>
  764. [[nodiscard]] vector<T, N> pow(const vector<T, N>& x, const vector<T, N>& y);
  765. template <std::floating_point T, std::size_t N>
  766. [[nodiscard]] vector<T, N> pow(const vector<T, N>& x, T y);
  767. /// @}
  768. /**
  769. * Performs a element-wise round operation.
  770. *
  771. * @param x Input vector
  772. *
  773. * @return Component-wise round of input vector.
  774. */
  775. template <std::floating_point T, std::size_t N>
  776. [[nodiscard]] constexpr vector<T, N> round(const vector<T, N>& x);
  777. /**
  778. * Returns a vector containing the signs of each element.
  779. *
  780. * @param x Input vector
  781. * @return Signs of input vector elements.
  782. */
  783. template <std::floating_point T, std::size_t N>
  784. [[nodiscard]] constexpr vector<T, N> sign(const vector<T, N>& x);
  785. /**
  786. * Calculates the signed angle between two direction vectors about axis.
  787. *
  788. * @param from First direction vector.
  789. * @param to Second direction vector.
  790. * @param axis Axis direction vector.
  791. *
  792. * @return Signed angle between @p from and @p to about @p axis, in radians.
  793. */
  794. template <std::floating_point T>
  795. [[nodiscard]] T signed_angle(const vector<T, 3>& x, const vector<T, 3>& y, const vector<T, 3>& n);
  796. /**
  797. * Calculates the square distance between two points. The square distance can be calculated faster than the distance because a call to `std::sqrt` is saved.
  798. *
  799. * @param p0 First of two points.
  800. * @param p1 Second of two points.
  801. *
  802. * @return Square distance between the two points.
  803. */
  804. template <class T, std::size_t N>
  805. [[nodiscard]] constexpr T sqr_distance(const vector<T, N>& p0, const vector<T, N>& p1) noexcept;
  806. /**
  807. * Calculates the square length of a vector. The square length can be calculated faster than the length because a call to `std::sqrt` is saved.
  808. *
  809. * @param x Vector of which to calculate the square length.
  810. *
  811. * @return Square length of the vector.
  812. */
  813. template <class T, std::size_t N>
  814. [[nodiscard]] constexpr T sqr_length(const vector<T, N>& x) noexcept;
  815. /**
  816. * Takes the square root of each element.
  817. *
  818. * @param x Input vector
  819. *
  820. * @return Square roots of the input vector elements.
  821. */
  822. template <std::floating_point T, std::size_t N>
  823. [[nodiscard]] vector<T, N> sqrt(const vector<T, N>& x);
  824. /**
  825. * Subtracts a value by another value.
  826. *
  827. * @param x First value.
  828. * @param y Second value.
  829. *
  830. * @return Difference between the two values.
  831. */
  832. /// @{
  833. template <class T, std::size_t N>
  834. [[nodiscard]] constexpr vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y) noexcept;
  835. template <class T, std::size_t N>
  836. [[nodiscard]] constexpr vector<T, N> sub(const vector<T, N>& x, T y) noexcept;
  837. template <class T, std::size_t N>
  838. [[nodiscard]] constexpr vector<T, N> sub(T x, const vector<T, N>& y) noexcept;
  839. /// @}
  840. /**
  841. * Calculates the sum of all elements in a vector.
  842. *
  843. * @param x Vector to sum.
  844. * @return Sum of the vector's elements.
  845. */
  846. template <class T, std::size_t N>
  847. [[nodiscard]] constexpr T sum(const vector<T, N>& x) noexcept;
  848. /**
  849. * Makes an *m*-dimensional vector by rearranging and/or duplicating elements of an *n*-dimensional vector.
  850. *
  851. * @tparam Indices List of indices of elements in @p x.
  852. * @tparam T Vector element type.
  853. * @tparam N Number of dimensions in @p x.
  854. *
  855. * @param x Vector to swizzle.
  856. *
  857. * @return Vector containing elements from @p x in the order specified by @p Indices. The size of the returned vector is equivalent to the number of indices in @p Indices.
  858. */
  859. template <std::size_t... Indices, class T, std::size_t N>
  860. [[nodiscard]] constexpr vector<T, sizeof...(Indices)> swizzle(const vector<T, N>& x) noexcept;
  861. /**
  862. * Calculates the triple product of three vectors.
  863. *
  864. * @param x First vector.
  865. * @param y Second vector.
  866. * @param z Third vector.
  867. *
  868. * @return Triple product of the three vectors (`dot(x, cross(y, z)`).
  869. */
  870. template <class T>
  871. [[nodiscard]] constexpr T triple(const vector<T, 3>& x, const vector<T, 3>& y, const vector<T, 3>& z) noexcept;
  872. /**
  873. * Performs a element-wise trunc operation.
  874. *
  875. * @param x Input vector
  876. * @return Component-wise trunc of input vector.
  877. */
  878. template <std::floating_point T, std::size_t N>
  879. [[nodiscard]] constexpr vector<T, N> trunc(const vector<T, N>& x);
  880. /// @private
  881. template <class T, std::size_t N, std::size_t... I>
  882. inline constexpr vector<T, N> abs(const vector<T, N>& x, std::index_sequence<I...>)
  883. {
  884. return {std::abs(x[I])...};
  885. }
  886. template <class T, std::size_t N>
  887. inline constexpr vector<T, N> abs(const vector<T, N>& x)
  888. {
  889. return abs(x, std::make_index_sequence<N>{});
  890. }
  891. /// @private
  892. template <class T, std::size_t N, std::size_t... I>
  893. inline constexpr vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
  894. {
  895. return {(x[I] + y[I])...};
  896. }
  897. template <class T, std::size_t N>
  898. inline constexpr vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y) noexcept
  899. {
  900. return add(x, y, std::make_index_sequence<N>{});
  901. }
  902. /// @private
  903. template <class T, std::size_t N, std::size_t... I>
  904. inline constexpr vector<T, N> add(const vector<T, N>& x, T y, std::index_sequence<I...>) noexcept
  905. {
  906. return {(x[I] + y)...};
  907. }
  908. template <class T, std::size_t N>
  909. inline constexpr vector<T, N> add(const vector<T, N>& x, T y) noexcept
  910. {
  911. return add(x, y, std::make_index_sequence<N>{});
  912. }
  913. /// @private
  914. template <std::size_t N, std::size_t... I>
  915. inline constexpr bool all(const vector<bool, N>& x, std::index_sequence<I...>) noexcept
  916. {
  917. return (x[I] && ...);
  918. }
  919. template <std::size_t N>
  920. inline constexpr bool all(const vector<bool, N>& x) noexcept
  921. {
  922. return all(x, std::make_index_sequence<N>{});
  923. }
  924. template <std::floating_point T, std::size_t N>
  925. T angle(const vector<T, N>& from, const vector<T, N>& to)
  926. {
  927. return std::acos(std::min<T>(std::max<T>(dot(from, to), T{-1}), T{1}));
  928. }
  929. /// @private
  930. template <std::size_t N, std::size_t... I>
  931. inline constexpr bool any(const vector<bool, N>& x, std::index_sequence<I...>) noexcept
  932. {
  933. return (x[I] || ...);
  934. }
  935. template <std::size_t N>
  936. inline constexpr bool any(const vector<bool, N>& x) noexcept
  937. {
  938. return any(x, std::make_index_sequence<N>{});
  939. }
  940. /// @private
  941. template <std::floating_point T, std::size_t N, std::size_t... I>
  942. inline constexpr vector<T, N> ceil(const vector<T, N>& x, std::index_sequence<I...>)
  943. {
  944. return {std::ceil(x[I])...};
  945. }
  946. template <std::floating_point T, std::size_t N>
  947. inline constexpr vector<T, N> ceil(const vector<T, N>& x)
  948. {
  949. return ceil(x, std::make_index_sequence<N>{});
  950. }
  951. /// @private
  952. template <class T, std::size_t N, std::size_t... I>
  953. inline constexpr vector<T, N> clamp(const vector<T, N>& x, const vector<T, N>& min_val, const vector<T, N>& max_val, std::index_sequence<I...>)
  954. {
  955. return {std::min<T>(max_val[I], std::max<T>(min_val[I], x[I]))...};
  956. }
  957. template <class T, std::size_t N>
  958. inline constexpr vector<T, N> clamp(const vector<T, N>& x, const vector<T, N>& min, const vector<T, N>& max)
  959. {
  960. return clamp(x, min, max, std::make_index_sequence<N>{});
  961. }
  962. /// @private
  963. template <class T, std::size_t N, std::size_t... I>
  964. inline constexpr vector<T, N> clamp(const vector<T, N>& x, T min, T max, std::index_sequence<I...>)
  965. {
  966. return {std::min<T>(max, std::max<T>(min, x[I]))...};
  967. }
  968. template <class T, std::size_t N>
  969. inline constexpr vector<T, N> clamp(const vector<T, N>& x, T min, T max)
  970. {
  971. return clamp(x, min, max, std::make_index_sequence<N>{});
  972. }
  973. template <std::floating_point T, std::size_t N>
  974. vector<T, N> clamp_length(const vector<T, N>& x, T max_length)
  975. {
  976. const auto length2 = sqr_length(x);
  977. return (length2 > max_length * max_length) ? (x * (max_length / std::sqrt(length2))) : x;
  978. }
  979. template <class T>
  980. inline constexpr vector<T, 3> cross(const vector<T, 3>& x, const vector<T, 3>& y) noexcept
  981. {
  982. return
  983. {
  984. x[1] * y[2] - x[2] * y[1],
  985. x[2] * y[0] - x[0] * y[2],
  986. x[0] * y[1] - x[1] * y[0]
  987. };
  988. }
  989. template <std::floating_point T, std::size_t N>
  990. inline T distance(const vector<T, N>& p0, const vector<T, N>& p1)
  991. {
  992. return length(sub(p0, p1));
  993. }
  994. /// @private
  995. template <class T, std::size_t N, std::size_t... I>
  996. inline constexpr vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
  997. {
  998. return {(x[I] / y[I])...};
  999. }
  1000. template <class T, std::size_t N>
  1001. inline constexpr vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1002. {
  1003. return div(x, y, std::make_index_sequence<N>{});
  1004. }
  1005. /// @private
  1006. template <class T, std::size_t N, std::size_t... I>
  1007. inline constexpr vector<T, N> div(const vector<T, N>& x, T y, std::index_sequence<I...>) noexcept
  1008. {
  1009. return {(x[I] / y)...};
  1010. }
  1011. template <class T, std::size_t N>
  1012. inline constexpr vector<T, N> div(const vector<T, N>& x, T y) noexcept
  1013. {
  1014. return div(x, y, std::make_index_sequence<N>{});
  1015. }
  1016. /// @private
  1017. template <class T, std::size_t N, std::size_t... I>
  1018. inline constexpr vector<T, N> div(T x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
  1019. {
  1020. return {(x / y[I])...};
  1021. }
  1022. template <class T, std::size_t N>
  1023. inline constexpr vector<T, N> div(T x, const vector<T, N>& y) noexcept
  1024. {
  1025. return div(x, y, std::make_index_sequence<N>{});
  1026. }
  1027. /// @private
  1028. template <class T, std::size_t N, std::size_t... I>
  1029. inline constexpr T dot(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
  1030. {
  1031. return ((x[I] * y[I]) + ...);
  1032. }
  1033. template <class T, std::size_t N>
  1034. inline constexpr T dot(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1035. {
  1036. return dot(x, y, std::make_index_sequence<N>{});
  1037. }
  1038. /// @private
  1039. template <class T, std::size_t N, std::size_t... I>
  1040. inline constexpr vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
  1041. {
  1042. return {(x[I] == y[I])...};
  1043. }
  1044. template <class T, std::size_t N>
  1045. inline constexpr vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1046. {
  1047. return equal(x, y, std::make_index_sequence<N>{});
  1048. }
  1049. /// @private
  1050. template <std::floating_point T, std::size_t N, std::size_t... I>
  1051. inline constexpr vector<T, N> floor(const vector<T, N>& x, std::index_sequence<I...>)
  1052. {
  1053. return {std::floor(x[I])...};
  1054. }
  1055. template <std::floating_point T, std::size_t N>
  1056. inline constexpr vector<T, N> floor(const vector<T, N>& x)
  1057. {
  1058. return floor(x, std::make_index_sequence<N>{});
  1059. }
  1060. /// @private
  1061. template <std::floating_point T, std::size_t N, std::size_t... I>
  1062. inline constexpr vector<T, N> fma(const vector<T, N>& x, const vector<T, N>& y, const vector<T, N>& z, std::index_sequence<I...>)
  1063. {
  1064. return {std::fma(x[I], y[I], z[I])...};
  1065. }
  1066. template <std::floating_point T, std::size_t N>
  1067. inline constexpr vector<T, N> fma(const vector<T, N>& x, const vector<T, N>& y, const vector<T, N>& z)
  1068. {
  1069. return fma(x, y, z, std::make_index_sequence<N>{});
  1070. }
  1071. /// @private
  1072. template <std::floating_point T, std::size_t N, std::size_t... I>
  1073. inline constexpr vector<T, N> fma(const vector<T, N>& x, T y, T z, std::index_sequence<I...>)
  1074. {
  1075. return {std::fma(x[I], y, z)...};
  1076. }
  1077. template <std::floating_point T, std::size_t N>
  1078. inline constexpr vector<T, N> fma(const vector<T, N>& x, T y, T z)
  1079. {
  1080. return fma(x, y, z, std::make_index_sequence<N>{});
  1081. }
  1082. /// @private
  1083. template <std::floating_point T, std::size_t N, std::size_t... I>
  1084. inline constexpr vector<T, N> fract(const vector<T, N>& x, std::index_sequence<I...>)
  1085. {
  1086. return {x[I] - std::floor(x[I])...};
  1087. }
  1088. template <std::floating_point T, std::size_t N>
  1089. inline constexpr vector<T, N> fract(const vector<T, N>& x)
  1090. {
  1091. return fract(x, std::make_index_sequence<N>{});
  1092. }
  1093. template<std::size_t I, class T, std::size_t N>
  1094. inline constexpr T& get(math::vector<T, N>& v) noexcept
  1095. {
  1096. static_assert(I < N);
  1097. return v.elements[I];
  1098. }
  1099. template<std::size_t I, class T, std::size_t N>
  1100. inline constexpr T&& get(math::vector<T, N>&& v) noexcept
  1101. {
  1102. static_assert(I < N);
  1103. return std::move(v.elements[I]);
  1104. }
  1105. template<std::size_t I, class T, std::size_t N>
  1106. inline constexpr const T& get(const math::vector<T, N>& v) noexcept
  1107. {
  1108. static_assert(I < N);
  1109. return v.elements[I];
  1110. }
  1111. template<std::size_t I, class T, std::size_t N>
  1112. inline constexpr const T&& get(const math::vector<T, N>&& v) noexcept
  1113. {
  1114. static_assert(I < N);
  1115. return std::move(v.elements[I]);
  1116. }
  1117. /// @private
  1118. template <class T, std::size_t N, std::size_t... I>
  1119. inline constexpr vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
  1120. {
  1121. return {(x[I] > y[I])...};
  1122. }
  1123. template <class T, std::size_t N>
  1124. inline constexpr vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1125. {
  1126. return greater_than(x, y, std::make_index_sequence<N>{});
  1127. }
  1128. /// @private
  1129. template <class T, std::size_t N, std::size_t... I>
  1130. inline constexpr vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
  1131. {
  1132. return {(x[I] >= y[I])...};
  1133. }
  1134. template <class T, std::size_t N>
  1135. inline constexpr vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1136. {
  1137. return greater_than_equal(x, y, std::make_index_sequence<N>{});
  1138. }
  1139. template <std::floating_point T, std::size_t N>
  1140. inline T inv_length(const vector<T, N>& x)
  1141. {
  1142. return T{1} / length(x);
  1143. }
  1144. template <std::floating_point T, std::size_t N>
  1145. inline T length(const vector<T, N>& x)
  1146. {
  1147. return std::sqrt(sqr_length(x));
  1148. }
  1149. /// @private
  1150. template <class T, std::size_t N, std::size_t... I>
  1151. inline constexpr vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
  1152. {
  1153. return {(x[I] < y[I])...};
  1154. }
  1155. template <class T, std::size_t N>
  1156. inline constexpr vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1157. {
  1158. return less_than(x, y, std::make_index_sequence<N>{});
  1159. }
  1160. /// @private
  1161. template <class T, std::size_t N, std::size_t... I>
  1162. inline constexpr vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
  1163. {
  1164. return {(x[I] <= y[I])...};
  1165. }
  1166. template <class T, std::size_t N>
  1167. inline constexpr vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1168. {
  1169. return less_than_equal(x, y, std::make_index_sequence<N>{});
  1170. }
  1171. /// @private
  1172. template <class T, std::size_t N, std::size_t... I>
  1173. inline constexpr vector<T, N> max(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  1174. {
  1175. return {std::max<T>(x[I], y[I])...};
  1176. }
  1177. template <class T, std::size_t N>
  1178. constexpr vector<T, N> max(const vector<T, N>& x, const vector<T, N>& y)
  1179. {
  1180. return max(x, y, std::make_index_sequence<N>{});
  1181. }
  1182. template <class T, std::size_t N>
  1183. inline constexpr T max(const vector<T, N>& x)
  1184. {
  1185. return *std::max_element(x.elements, x.elements + N);
  1186. }
  1187. /// @private
  1188. template <class T, std::size_t N, std::size_t... I>
  1189. inline constexpr vector<T, N> min(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  1190. {
  1191. return {std::min<T>(x[I], y[I])...};
  1192. }
  1193. template <class T, std::size_t N>
  1194. constexpr vector<T, N> min(const vector<T, N>& x, const vector<T, N>& y)
  1195. {
  1196. return min(x, y, std::make_index_sequence<N>{});
  1197. }
  1198. template <class T, std::size_t N>
  1199. inline constexpr T min(const vector<T, N>& x)
  1200. {
  1201. return *std::min_element(x.elements, x.elements + N);
  1202. }
  1203. /// @private
  1204. template <std::floating_point T, std::size_t N, std::size_t... I>
  1205. inline constexpr vector<T, N> mod(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  1206. {
  1207. return {std::fmod(x[I], y[I])...};
  1208. }
  1209. template <std::floating_point T, std::size_t N>
  1210. inline constexpr vector<T, N> mod(const vector<T, N>& x, const vector<T, N>& y)
  1211. {
  1212. return mod(x, y, std::make_index_sequence<N>{});
  1213. }
  1214. /// @private
  1215. template <std::floating_point T, std::size_t N, std::size_t... I>
  1216. inline constexpr vector<T, N> mod(const vector<T, N>& x, T y, std::index_sequence<I...>)
  1217. {
  1218. return {std::fmod(x[I], y)...};
  1219. }
  1220. template <std::floating_point T, std::size_t N>
  1221. inline constexpr vector<T, N> mod(const vector<T, N>& x, T y)
  1222. {
  1223. return mod(x, y, std::make_index_sequence<N>{});
  1224. }
  1225. /// @private
  1226. template <class T, std::size_t N, std::size_t... I>
  1227. inline constexpr vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
  1228. {
  1229. return {(x[I] * y[I])...};
  1230. }
  1231. template <class T, std::size_t N>
  1232. inline constexpr vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1233. {
  1234. return mul(x, y, std::make_index_sequence<N>{});
  1235. }
  1236. /// @private
  1237. template <class T, std::size_t N, std::size_t... I>
  1238. inline constexpr vector<T, N> mul(const vector<T, N>& x, T y, std::index_sequence<I...>) noexcept
  1239. {
  1240. return {(x[I] * y)...};
  1241. }
  1242. template <class T, std::size_t N>
  1243. inline constexpr vector<T, N> mul(const vector<T, N>& x, T y) noexcept
  1244. {
  1245. return mul(x, y, std::make_index_sequence<N>{});
  1246. }
  1247. /// @private
  1248. template <class T, std::size_t N, std::size_t... I>
  1249. inline constexpr vector<T, N> negate(const vector<T, N>& x, std::index_sequence<I...>) noexcept
  1250. {
  1251. return {(-x[I])...};
  1252. }
  1253. template <class T, std::size_t N>
  1254. inline constexpr vector<T, N> negate(const vector<T, N>& x) noexcept
  1255. {
  1256. return negate(x, std::make_index_sequence<N>{});
  1257. }
  1258. template <std::floating_point T, std::size_t N>
  1259. inline vector<T, N> normalize(const vector<T, N>& x)
  1260. {
  1261. return mul(x, inv_length(x));
  1262. }
  1263. /// @private
  1264. template <class T, std::size_t N, std::size_t... I>
  1265. inline constexpr vector<bool, N> logical_not(const vector<T, N>& x, std::index_sequence<I...>) noexcept
  1266. {
  1267. return {!x[I]...};
  1268. }
  1269. template <class T, std::size_t N>
  1270. inline constexpr vector<bool, N> logical_not(const vector<T, N>& x) noexcept
  1271. {
  1272. return logical_not(x, std::make_index_sequence<N>{});
  1273. }
  1274. /// @private
  1275. template <class T, std::size_t N, std::size_t... I>
  1276. inline constexpr vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
  1277. {
  1278. return {(x[I] != y[I])...};
  1279. }
  1280. template <class T, std::size_t N>
  1281. inline constexpr vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1282. {
  1283. return not_equal(x, y, std::make_index_sequence<N>{});
  1284. }
  1285. /// @private
  1286. template <std::floating_point T, std::size_t N, std::size_t... I>
  1287. inline vector<T, N> pow(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  1288. {
  1289. return {std::pow(x[I], y[I])...};
  1290. }
  1291. template <std::floating_point T, std::size_t N>
  1292. inline vector<T, N> pow(const vector<T, N>& x, const vector<T, N>& y)
  1293. {
  1294. return pow(x, y, std::make_index_sequence<N>{});
  1295. }
  1296. /// @private
  1297. template <std::floating_point T, std::size_t N, std::size_t... I>
  1298. inline vector<T, N> pow(const vector<T, N>& x, T y, std::index_sequence<I...>)
  1299. {
  1300. return {std::pow(x[I], y)...};
  1301. }
  1302. template <std::floating_point T, std::size_t N>
  1303. inline vector<T, N> pow(const vector<T, N>& x, T y)
  1304. {
  1305. return pow(x, y, std::make_index_sequence<N>{});
  1306. }
  1307. /// @private
  1308. template <std::floating_point T, std::size_t N, std::size_t... I>
  1309. inline constexpr vector<T, N> round(const vector<T, N>& x, std::index_sequence<I...>)
  1310. {
  1311. return {std::round(x[I])...};
  1312. }
  1313. template <std::floating_point T, std::size_t N>
  1314. inline constexpr vector<T, N> round(const vector<T, N>& x)
  1315. {
  1316. return round(x, std::make_index_sequence<N>{});
  1317. }
  1318. /// @private
  1319. template <std::floating_point T, std::size_t N, std::size_t... I>
  1320. inline constexpr vector<T, N> sign(const vector<T, N>& x, std::index_sequence<I...>)
  1321. {
  1322. return {std::copysign(T{1}, x[I])...};
  1323. }
  1324. template <std::floating_point T, std::size_t N>
  1325. inline constexpr vector<T, N> sign(const vector<T, N>& x)
  1326. {
  1327. return sign(x, std::make_index_sequence<N>{});
  1328. }
  1329. template <std::floating_point T>
  1330. T signed_angle(const vector<T, 3>& from, const vector<T, 3>& to, const vector<T, 3>& axis)
  1331. {
  1332. return std::atan2(triple(axis, from, to), dot(from, to));
  1333. }
  1334. template <class T, std::size_t N>
  1335. inline constexpr T sqr_distance(const vector<T, N>& p0, const vector<T, N>& p1) noexcept
  1336. {
  1337. return sqr_length(sub(p0, p1));
  1338. }
  1339. template <class T, std::size_t N>
  1340. inline constexpr T sqr_length(const vector<T, N>& x) noexcept
  1341. {
  1342. return dot(x, x);
  1343. }
  1344. /// @private
  1345. template <std::floating_point T, std::size_t N, std::size_t... I>
  1346. inline vector<T, N> sqrt(const vector<T, N>& x, std::index_sequence<I...>)
  1347. {
  1348. return {std::sqrt(x[I])...};
  1349. }
  1350. template <std::floating_point T, std::size_t N>
  1351. inline vector<T, N> sqrt(const vector<T, N>& x, const vector<T, N>& y)
  1352. {
  1353. return sqrt(x, std::make_index_sequence<N>{});
  1354. }
  1355. /// @private
  1356. template <class T, std::size_t N, std::size_t... I>
  1357. inline constexpr vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
  1358. {
  1359. return {(x[I] - y[I])...};
  1360. }
  1361. template <class T, std::size_t N>
  1362. inline constexpr vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1363. {
  1364. return sub(x, y, std::make_index_sequence<N>{});
  1365. }
  1366. /// @private
  1367. template <class T, std::size_t N, std::size_t... I>
  1368. inline constexpr vector<T, N> sub(const vector<T, N>& x, T y, std::index_sequence<I...>) noexcept
  1369. {
  1370. return {(x[I] - y)...};
  1371. }
  1372. template <class T, std::size_t N>
  1373. inline constexpr vector<T, N> sub(const vector<T, N>& x, T y) noexcept
  1374. {
  1375. return sub(x, y, std::make_index_sequence<N>{});
  1376. }
  1377. /// @private
  1378. template <class T, std::size_t N, std::size_t... I>
  1379. inline constexpr vector<T, N> sub(T x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
  1380. {
  1381. return {(x - y[I])...};
  1382. }
  1383. template <class T, std::size_t N>
  1384. inline constexpr vector<T, N> sub(T x, const vector<T, N>& y) noexcept
  1385. {
  1386. return sub(x, y, std::make_index_sequence<N>{});
  1387. }
  1388. /// @private
  1389. template <class T, std::size_t N, std::size_t... I>
  1390. inline constexpr T sum(const vector<T, N>& x, std::index_sequence<I...>) noexcept
  1391. {
  1392. return (x[I] + ...);
  1393. }
  1394. template <class T, std::size_t N>
  1395. inline constexpr T sum(const vector<T, N>& x) noexcept
  1396. {
  1397. return sum(x, std::make_index_sequence<N>{});
  1398. }
  1399. template <std::size_t... Indices, class T, std::size_t N>
  1400. inline constexpr vector<T, sizeof...(Indices)> swizzle(const vector<T, N>& x) noexcept
  1401. {
  1402. return {x[Indices]...};
  1403. }
  1404. template <class T>
  1405. inline constexpr T triple(const vector<T, 3>& x, const vector<T, 3>& y, const vector<T, 3>& z) noexcept
  1406. {
  1407. return dot(x, cross(y, z));
  1408. }
  1409. /// @private
  1410. template <std::floating_point T, std::size_t N, std::size_t... I>
  1411. inline constexpr vector<T, N> trunc(const vector<T, N>& x, std::index_sequence<I...>)
  1412. {
  1413. return {std::trunc(x[I])...};
  1414. }
  1415. template <std::floating_point T, std::size_t N>
  1416. inline constexpr vector<T, N> trunc(const vector<T, N>& x)
  1417. {
  1418. return trunc(x, std::make_index_sequence<N>{});
  1419. }
  1420. namespace operators {
  1421. /// @copydoc add(const vector<T, N>&, const vector<T, N>&)
  1422. template <class T, std::size_t N>
  1423. [[nodiscard]] inline constexpr vector<T, N> operator+(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1424. {
  1425. return add(x, y);
  1426. }
  1427. /// @copydoc add(const vector<T, N>&, T)
  1428. /// @{
  1429. template <class T, std::size_t N>
  1430. [[nodiscard]] inline constexpr vector<T, N> operator+(const vector<T, N>& x, T y) noexcept
  1431. {
  1432. return add(x, y);
  1433. }
  1434. template <class T, std::size_t N>
  1435. [[nodiscard]] inline constexpr vector<T, N> operator+(T x, const vector<T, N>& y) noexcept
  1436. {
  1437. return add(y, x);
  1438. }
  1439. /// @}
  1440. /// @copydoc div(const vector<T, N>&, const vector<T, N>&)
  1441. template <class T, std::size_t N>
  1442. [[nodiscard]] inline constexpr vector<T, N> operator/(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1443. {
  1444. return div(x, y);
  1445. }
  1446. /// @copydoc div(const vector<T, N>&, T)
  1447. template <class T, std::size_t N>
  1448. [[nodiscard]] inline constexpr vector<T, N> operator/(const vector<T, N>& x, T y) noexcept
  1449. {
  1450. return div(x, y);
  1451. }
  1452. /// @copydoc div(T, const vector<T, N>&)
  1453. template <class T, std::size_t N>
  1454. [[nodiscard]] inline constexpr vector<T, N> operator/(T x, const vector<T, N>& y) noexcept
  1455. {
  1456. return div(x, y);
  1457. }
  1458. /// @copydoc mul(const vector<T, N>&, const vector<T, N>&)
  1459. template <class T, std::size_t N>
  1460. [[nodiscard]] inline constexpr vector<T, N> operator*(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1461. {
  1462. return mul(x, y);
  1463. }
  1464. /// @copydoc mul(const vector<T, N>&, T)
  1465. /// @{
  1466. template <class T, std::size_t N>
  1467. [[nodiscard]] inline constexpr vector<T, N> operator*(const vector<T, N>& x, T y) noexcept
  1468. {
  1469. return mul(x, y);
  1470. }
  1471. template <class T, std::size_t N>
  1472. [[nodiscard]] inline constexpr vector<T, N> operator*(T x, const vector<T, N>& y) noexcept
  1473. {
  1474. return mul(y, x);
  1475. }
  1476. /// @}
  1477. /// @copydoc negate(const vector<T, N>&)
  1478. template <class T, std::size_t N>
  1479. [[nodiscard]] inline constexpr vector<T, N> operator-(const vector<T, N>& x) noexcept
  1480. {
  1481. return negate(x);
  1482. }
  1483. /// @copydoc sub(const vector<T, N>&, const vector<T, N>&)
  1484. template <class T, std::size_t N>
  1485. [[nodiscard]] inline constexpr vector<T, N> operator-(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1486. {
  1487. return sub(x, y);
  1488. }
  1489. /// @copydoc sub(const vector<T, N>&, T)
  1490. template <class T, std::size_t N>
  1491. [[nodiscard]] inline constexpr vector<T, N> operator-(const vector<T, N>& x, T y) noexcept
  1492. {
  1493. return sub(x, y);
  1494. }
  1495. /// @copydoc sub(T, const vector<T, N>&)
  1496. template <class T, std::size_t N>
  1497. [[nodiscard]] inline constexpr vector<T, N> operator-(T x, const vector<T, N>& y) noexcept
  1498. {
  1499. return sub(x, y);
  1500. }
  1501. /**
  1502. * Adds two values and stores the result in the first value.
  1503. *
  1504. * @param x First value.
  1505. * @param y Second value.
  1506. *
  1507. * @return Reference to the first value.
  1508. */
  1509. /// @{
  1510. template <class T, std::size_t N>
  1511. inline constexpr vector<T, N>& operator+=(vector<T, N>& x, const vector<T, N>& y) noexcept
  1512. {
  1513. return (x = x + y);
  1514. }
  1515. template <class T, std::size_t N>
  1516. inline constexpr vector<T, N>& operator+=(vector<T, N>& x, T y) noexcept
  1517. {
  1518. return (x = x + y);
  1519. }
  1520. /// @}
  1521. /**
  1522. * Subtracts the first value by the second value and stores the result in the first value.
  1523. *
  1524. * @param x First value.
  1525. * @param y Second value.
  1526. *
  1527. * @return Reference to the first value.
  1528. */
  1529. /// @{
  1530. template <class T, std::size_t N>
  1531. inline constexpr vector<T, N>& operator-=(vector<T, N>& x, const vector<T, N>& y) noexcept
  1532. {
  1533. return (x = x - y);
  1534. }
  1535. template <class T, std::size_t N>
  1536. inline constexpr vector<T, N>& operator-=(vector<T, N>& x, T y) noexcept
  1537. {
  1538. return (x = x - y);
  1539. }
  1540. /// @}
  1541. /**
  1542. * Multiplies two values and stores the result in the first value.
  1543. *
  1544. * @param x First value.
  1545. * @param y Second value.
  1546. *
  1547. * @return Reference to the first value.
  1548. */
  1549. /// @{
  1550. template <class T, std::size_t N>
  1551. inline constexpr vector<T, N>& operator*=(vector<T, N>& x, const vector<T, N>& y) noexcept
  1552. {
  1553. return (x = x * y);
  1554. }
  1555. template <class T, std::size_t N>
  1556. inline constexpr vector<T, N>& operator*=(vector<T, N>& x, T y) noexcept
  1557. {
  1558. return (x = x * y);
  1559. }
  1560. /// @}
  1561. /**
  1562. * Divides the first value by the second value and stores the result in the first value.
  1563. *
  1564. * @param x First value.
  1565. * @param y Second value.
  1566. *
  1567. * @return Reference to the first value.
  1568. */
  1569. /// @{
  1570. template <class T, std::size_t N>
  1571. inline constexpr vector<T, N>& operator/=(vector<T, N>& x, const vector<T, N>& y) noexcept
  1572. {
  1573. return (x = x / y);
  1574. }
  1575. template <class T, std::size_t N>
  1576. inline constexpr vector<T, N>& operator/=(vector<T, N>& x, T y) noexcept
  1577. {
  1578. return (x = x / y);
  1579. }
  1580. /// @}
  1581. /**
  1582. * Tests two vector for equality
  1583. *
  1584. * @param x First value.
  1585. * @param y Second value.
  1586. *
  1587. * @return `true` if the vectors are identical, `false` otherwise.
  1588. */
  1589. template <class T, std::size_t N>
  1590. inline constexpr bool operator==(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1591. {
  1592. // if consteval
  1593. // {
  1594. for (std::size_t i = 0; i < N; ++i)
  1595. {
  1596. if (x[i] != y[i])
  1597. {
  1598. return false;
  1599. }
  1600. }
  1601. return true;
  1602. // }
  1603. // else
  1604. // {
  1605. // !std::memcmp(x.data(), y.data(), N * sizeof(T));
  1606. // }
  1607. }
  1608. /**
  1609. * Tests two vector for inequality
  1610. *
  1611. * @param x First value.
  1612. * @param y Second value.
  1613. *
  1614. * @return `false` if the vectors are identical, `true` otherwise.
  1615. */
  1616. template <class T, std::size_t N>
  1617. inline constexpr bool operator!=(const vector<T, N>& x, const vector<T, N>& y) noexcept
  1618. {
  1619. return !(x == y);
  1620. }
  1621. } // namespace operators
  1622. } // namespace math
  1623. // Bring vector operators into global namespace
  1624. using namespace math::operators;
  1625. namespace std
  1626. {
  1627. /**
  1628. * Provides access to the number of elements in a math::vector as a compile-time constant expression.
  1629. *
  1630. * @tparam T Element type.
  1631. * @tparam N Number of elements.
  1632. */
  1633. template<class T, std::size_t N>
  1634. struct tuple_size<math::vector<T, N>>
  1635. {
  1636. /// Number of elements in the vector.
  1637. static constexpr std::size_t value = math::vector<T, N>::element_count;
  1638. };
  1639. /**
  1640. * Provides compile-time indexed access to the type of the elements in a math::vector using a tuple-like interface.
  1641. *
  1642. * @tparam I Index of an element.
  1643. * @tparam T Element type.
  1644. * @tparam N Number of elements.
  1645. */
  1646. template<std::size_t I, class T, std::size_t N>
  1647. struct tuple_element<I, math::vector<T, N>>
  1648. {
  1649. /// Type of elements in the vector.
  1650. using type = math::vector<T, N>::element_type;
  1651. };
  1652. /**
  1653. * Specialization of std::formatter for math::vector.
  1654. *
  1655. * @tparam T Element type.
  1656. * @tparam N Number of elements.
  1657. */
  1658. template <class T, std::size_t N>
  1659. struct formatter<math::vector<T, N>>: formatter<T>
  1660. {
  1661. auto format(const math::vector<T, N>& t, format_context& fc) const
  1662. {
  1663. auto&& out = fc.out();
  1664. format_to(out, "{{");
  1665. for (std::size_t i = 0; i < N; ++i)
  1666. {
  1667. formatter<T>::format(t[i], fc);
  1668. if (i < N - 1)
  1669. {
  1670. format_to(out, ", ");
  1671. }
  1672. }
  1673. return format_to(out, "}}");
  1674. }
  1675. };
  1676. }
  1677. // Ensure vectors are POD types
  1678. static_assert(std::is_standard_layout_v<math::fvec3>);
  1679. static_assert(std::is_trivial_v<math::fvec3>);
  1680. #endif // ANTKEEPER_MATH_VECTOR_HPP