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

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