[nnm] No Nonsense Math 0.5.0
A No-Nonsense, C++ 17, single-header-only Math library geared towards graphics programming.
Loading...
Searching...
No Matches
nnm.hpp
Go to the documentation of this file.
1/* NNM - "No Nonsense Math"
2 * v0.5.0
3 * Copyright (c) 2025-present Matthew Oros
4 * Licensed under MIT
5 */
6
7#ifndef NNM_HPP
8#define NNM_HPP
9
10#include <cmath>
11#include <cstdint>
12#include <functional>
13#include <optional>
14
15// ReSharper disable CppDFATimeOver
16
17#if defined(NNM_BOUNDS_CHECK)
18#include <stdexcept>
19#define NNM_BOUNDS_CHECK_ASSERT(msg, expression) \
20 if (!(expression)) \
21 throw std::out_of_range(msg);
22#else
23#define NNM_BOUNDS_CHECK_ASSERT(msg, expression)
24#endif
25
26namespace nnm {
27
33template <typename Real>
34constexpr Real pi()
35{
36 return static_cast<Real>(3.141592653589793238462643383279502);
37}
38
44template <typename Real>
45constexpr Real epsilon()
46{
47 return static_cast<Real>(0.00001);
48}
49
56template <typename Num>
57constexpr Num sign(const Num value)
58{
59 if (value < static_cast<Num>(0)) {
60 return static_cast<Num>(-1);
61 }
62 return static_cast<Num>(1);
63}
64
71template <typename Num>
72constexpr Num abs(const Num value)
73{
74 if (value < static_cast<Num>(0)) {
75 return -value;
76 }
77 return value;
78}
79
87template <typename Num>
88constexpr Num max(const Num a, const Num b)
89{
90 if (a > b) {
91 return a;
92 }
93 return b;
94}
95
104template <typename Num, typename... Rest>
105constexpr Num max(const Num first, const Rest... rest)
106{
107 Num max_value = first;
108 max_value = max(first, max(rest...));
109 return max_value;
110}
111
118template <typename Real>
119constexpr bool approx_zero(const Real value)
120{
121 Real tolerance = epsilon<Real>() * abs(value);
122 tolerance = max(tolerance, epsilon<Real>());
123 return abs(value) <= tolerance;
124}
125
133template <typename Real>
134constexpr bool approx_equal(const Real a, const Real b)
135{
136 if (a == b) {
137 return true;
138 }
139 Real tolerance = epsilon<Real>() * max(abs(a), abs(b));
140 tolerance = max(tolerance, epsilon<Real>());
141 return abs(a - b) <= tolerance;
142}
143
151template <typename Real>
152constexpr bool approx_less(const Real a, const Real b)
153{
154 return a < b && !approx_equal(a, b);
155}
156
164template <typename Real>
165constexpr bool approx_greater(const Real a, const Real b)
166{
167 return a > b && !approx_equal(a, b);
168}
169
177template <typename Real>
178constexpr bool approx_less_equal(const Real a, const Real b)
179{
180 return a <= b || approx_equal(a, b);
181}
182
190template <typename Real>
191constexpr bool approx_greater_equal(const Real a, const Real b)
192{
193 return a >= b || approx_equal(a, b);
194}
195
202template <typename Real>
203constexpr bool approx_less_zero(const Real value)
204{
205 return value < static_cast<Real>(0) && !approx_zero(value);
206}
207
214template <typename Real>
215constexpr bool approx_greater_zero(const Real value)
216{
217 return value > static_cast<Real>(0) && !approx_zero(value);
218}
219
226template <typename Real>
227constexpr bool approx_less_equal_zero(const Real value)
228{
229 return value <= static_cast<Real>(0) || approx_zero(value);
230}
231
238template <typename Real>
239constexpr bool approx_greater_equal_zero(const Real value)
240{
241 return value >= static_cast<Real>(0) || approx_zero(value);
242}
243
250template <typename Real>
251Real ceil(const Real value)
252{
253 return std::ceil(value);
254}
255
264template <typename Num>
265constexpr Num clamp(const Num value, const Num min, const Num max)
266{
267 if (value < min) {
268 return min;
269 }
270 if (value > max) {
271 return max;
272 }
273 return value;
274}
275
282template <typename Real>
283Real sqrt(const Real value)
284{
285 return std::sqrt(value);
286}
287
295template <typename Real>
296Real pow(const Real base, const Real power)
297{
298 return std::pow(base, power);
299}
300
307template <typename Num>
308constexpr Num sqrd(const Num value)
309{
310 return value * value;
311}
312
320template <typename Real>
321Real modf(const Real dividend, const Real divisor)
322{
323 const Real result = std::fmod(dividend, divisor);
324 const Real zero = static_cast<Real>(0);
325 if ((result < zero && divisor > zero) || (result > zero && divisor < zero)) {
326 return result + divisor;
327 }
328 return result;
329}
330
338template <typename Int>
339constexpr Int mod(const Int dividend, const Int divisor)
340{
341 const Int result = dividend % divisor;
342 if ((result < 0 && divisor > 0) || (result > 0 && divisor < 0)) {
343 return result + divisor;
344 }
345 return result;
346}
347
355template <typename Real>
356Real remf(const Real dividend, const Real divisor)
357{
358 return std::fmod(dividend, divisor);
359}
360
368template <typename Int>
369constexpr Int rem(const Int dividend, const Int divisor)
370{
371 return dividend % divisor;
372}
373
380template <typename Real>
381Real normalize_angle(const Real angle)
382{
383 return modf(angle + pi<Real>(), static_cast<Real>(2) * pi<Real>()) - pi<Real>();
384}
385
394template <typename Real>
395bool angle_in_range(const Real angle, const Real from, const Real to)
396{
397 const Real two_pi = static_cast<Real>(2) * pi<Real>();
398 if (from <= to) {
399 return modf(angle - from, two_pi) <= modf(to - from, two_pi);
400 }
401 return modf(angle - from, two_pi) >= modf(to - from, two_pi);
402}
403
410template <typename Real>
411Real floor(const Real value)
412{
413 return std::floor(value);
414}
415
424template <typename Real>
425constexpr Real lerp(const Real from, const Real to, const Real weight)
426{
427 return from + weight * (to - from);
428}
429
438template <typename Real>
439constexpr Real lerp_clamped(const Real from, const Real to, const Real weight)
440{
441 if (weight >= static_cast<Real>(1)) {
442 return to;
443 }
444 if (weight <= static_cast<Real>(0)) {
445 return from;
446 }
447 return lerp(from, to, weight);
448}
449
456template <typename Real>
457Real sin(const Real value)
458{
459 return std::sin(value);
460}
461
468template <typename Real>
469Real cos(const Real value)
470{
471 return std::cos(value);
472}
473
480template <typename Real>
481Real tan(const Real value)
482{
483 return std::tan(value);
484}
485
492template <typename Real>
493Real round(const Real value)
494{
495 return std::round(value);
496}
497
504template <typename Real>
505Real atan(const Real value)
506{
507 return std::atan(value);
508}
509
517template <typename Real>
518Real atan2(const Real y, const Real x)
519{
520 return std::atan2(y, x);
521}
522
529template <typename Real>
530constexpr Real radians(const Real degrees)
531{
532 return pi<Real>() / static_cast<Real>(180) * degrees;
533}
534
541template <typename Real>
542constexpr Real degrees(const Real radians)
543{
544 return static_cast<Real>(180) / pi<Real>() * radians;
545}
546
553template <typename Real>
554Real asin(const Real value)
555{
556 return std::asin(value);
557}
558
565template <typename Real>
566Real acos(const Real value)
567{
568 return std::acos(value);
569}
570
578template <typename Num>
579constexpr Num min(const Num a, const Num b)
580{
581 if (a < b) {
582 return a;
583 }
584 return b;
585}
586
595template <typename Num, typename... Rest>
596constexpr Num min(const Num first, const Rest... rest)
597{
598 Num min_value = first;
599 min_value = min(first, min(rest...));
600 return min_value;
601}
602
609template <typename Real>
610Real log2(const Real value)
611{
612 return std::log2(value);
613}
614
615template <typename Real>
616class Vector2;
619template <typename Int>
620class Vector2i;
631template <typename Real>
632class Vector3;
635template <typename Int>
636class Vector3i;
647template <typename Real>
648class Vector4;
651template <typename Real>
652class Quaternion;
655template <typename Real>
656class Matrix2;
659template <typename Real>
660class Basis2;
663template <typename Real>
664class Matrix3;
667template <typename Real>
668class Transform2;
671template <typename Real>
672class Basis3;
675template <typename Real>
676class Matrix4;
679template <typename Real>
680class Transform3;
683
688template <typename Real>
689class Vector2 {
690public:
691 Real x;
692 Real y;
693
697 constexpr Vector2()
698 : x { static_cast<Real>(0) }
699 , y { static_cast<Real>(0) }
700 {
701 }
702
708 template <typename Int>
709 explicit constexpr Vector2(const Vector2i<Int>& vector);
710
716 template <typename Other>
717 explicit constexpr Vector2(const Vector2<Other>& vector)
718 : x { static_cast<Real>(vector.x) }
719 , y { static_cast<Real>(vector.y) }
720 {
721 }
722
728 constexpr Vector2(const Real x, const Real y)
729 : x { x }
730 , y { y }
731 {
732 }
733
739 static constexpr Vector2 all(const Real value)
740 {
741 return { value, value };
742 }
743
748 static constexpr Vector2 zero()
749 {
750 return all(static_cast<Real>(0));
751 }
752
757 static constexpr Vector2 one()
758 {
759 return all(static_cast<Real>(1));
760 }
761
766 static constexpr Vector2 axis_x()
767 {
768 return { static_cast<Real>(1), static_cast<Real>(0) };
769 }
770
775 static constexpr Vector2 axis_y()
776 {
777 return { static_cast<Real>(0), static_cast<Real>(1) };
778 }
779
784 [[nodiscard]] constexpr Vector2 abs() const
785 {
786 return { nnm::abs(x), nnm::abs(y) };
787 }
788
793 [[nodiscard]] Vector2 ceil() const
794 {
795 return { nnm::ceil(x), nnm::ceil(y) };
796 }
797
802 [[nodiscard]] Vector2 floor() const
803 {
804 return { nnm::floor(x), nnm::floor(y) };
805 }
806
811 [[nodiscard]] Vector2 round() const
812 {
813 return { nnm::round(x), nnm::round(y) };
814 }
815
820 [[nodiscard]] constexpr Real aspect_ratio() const
821 {
822 return x / y;
823 }
824
831 [[nodiscard]] constexpr Vector2 clamp(const Vector2& min, const Vector2& max) const
832 {
833 return { nnm::clamp(x, min.x, max.x), nnm::clamp(y, min.y, max.y) };
834 }
835
841 [[nodiscard]] Vector2 direction(const Vector2& to) const
842 {
843 return (to - *this).normalize();
844 }
845
851 [[nodiscard]] constexpr Vector2 direction_unnormalized(const Vector2& to) const
852 {
853 return to - *this;
854 }
855
861 [[nodiscard]] constexpr Real distance_sqrd(const Vector2& to) const
862 {
863 const Real diff_x = to.x - x;
864 const Real diff_y = to.y - y;
865 return sqrd(diff_x) + sqrd(diff_y);
866 }
867
873 [[nodiscard]] Real distance(const Vector2& to) const
874 {
875 return sqrt(this->distance_sqrd(to));
876 }
877
883 [[nodiscard]] constexpr Real manhattan_distance(const Vector2& to) const
884 {
885 return nnm::abs(x - to.x) + nnm::abs(y - to.y);
886 }
887
892 [[nodiscard]] constexpr Real length_sqrd() const
893 {
894 return sqrd(x) + sqrd(y);
895 }
896
901 [[nodiscard]] Real length() const
902 {
903 return sqrt(length_sqrd());
904 }
905
913 [[nodiscard]] Vector2 clamp_length(const Real min, const Real max) const
914 {
915 const Real length = this->length();
916 if (length == static_cast<Real>(0)) {
917 return zero();
918 }
919 const auto norm = normalize();
920 if (length < min) {
921 return norm * min;
922 }
923 if (length > max) {
924 return norm * max;
925 }
926 return *this;
927 }
928
933 [[nodiscard]] Vector2 normalize() const
934 {
935 if (const Real length = this->length(); length > static_cast<Real>(0)) {
936 return *this / length;
937 }
938 return zero();
939 }
940
947 [[nodiscard]] constexpr Vector2 lerp(const Vector2& to, const Real weight) const
948 {
949 return { nnm::lerp(x, to.x, weight), nnm::lerp(y, to.y, weight) };
950 }
951
958 [[nodiscard]] constexpr Vector2 lerp_clamped(const Vector2& to, const Real weight) const
959 {
960 return { nnm::lerp_clamped(x, to.x, weight), nnm::lerp_clamped(y, to.y, weight) };
961 }
962
968 [[nodiscard]] constexpr Real dot(const Vector2& other) const
969 {
970 return x * other.x + y * other.y;
971 }
972
978 [[nodiscard]] constexpr Real cross(const Vector2& other) const
979 {
980 return x * other.y - y * other.x;
981 }
982
988 [[nodiscard]] constexpr Matrix2<Real> outer(const Vector2& other) const;
989
995 [[nodiscard]] constexpr Vector2 reflect(const Vector2& normal) const
996 {
997 const Real dot = this->dot(normal);
998 Vector2 result;
999 result.x = x - static_cast<Real>(2) * normal.x * dot;
1000 result.y = y - static_cast<Real>(2) * normal.y * dot;
1001 return result;
1002 }
1003
1009 [[nodiscard]] constexpr Vector2 project(const Vector2& onto) const
1010 {
1011 const Real onto_length_sqrd = onto.length_sqrd();
1012 if (onto_length_sqrd == static_cast<Real>(0)) {
1013 return zero();
1014 }
1015 const Real scale = dot(onto) / onto_length_sqrd;
1016 return onto * scale;
1017 }
1018
1023 [[nodiscard]] constexpr Vector2 inverse() const
1024 {
1025 return { static_cast<Real>(1) / x, static_cast<Real>(1) / y };
1026 }
1027
1033 [[nodiscard]] Real angle_between(const Vector2& other) const
1034 {
1035 const Real lengths = length() * other.length();
1036 if (lengths == 0) {
1037 return static_cast<Real>(0);
1038 }
1039 const Real cos_angle = nnm::clamp(dot(other) / lengths, static_cast<Real>(-1), static_cast<Real>(1));
1040 const Real angle = acos(cos_angle);
1041 return cross(other) < static_cast<Real>(0) ? -angle : angle;
1042 }
1043
1049 [[nodiscard]] Real angle_to(const Vector2& to) const
1050 {
1051 return atan2(to.y - y, to.x - x);
1052 }
1053
1059 [[nodiscard]] constexpr bool parallel(const Vector2& other) const
1060 {
1061 return nnm::approx_zero(cross(other));
1062 }
1063
1069 [[nodiscard]] constexpr bool perpendicular(const Vector2& other) const
1070 {
1071 return nnm::approx_zero(dot(other));
1072 }
1073
1079 [[nodiscard]] constexpr Vector2 arbitrary_perpendicular() const
1080 {
1081 return { -y, x };
1082 }
1083
1089 [[nodiscard]] constexpr Vector2 translate(const Vector2& by) const;
1090
1096 [[nodiscard]] Vector2 rotate(Real angle) const;
1097
1104 [[nodiscard]] Vector2 rotate_at(const Vector2& origin, Real angle) const;
1105
1111 [[nodiscard]] constexpr Vector2 scale(const Vector2& factor) const;
1112
1119 [[nodiscard]] constexpr Vector2 scale_at(const Vector2& origin, const Vector2& factor) const;
1120
1126 [[nodiscard]] constexpr Vector2 shear_x(Real factor) const;
1127
1134 [[nodiscard]] constexpr Vector2 shear_x_at(const Vector2& origin, Real factor) const;
1135
1141 [[nodiscard]] constexpr Vector2 shear_y(Real factor) const;
1142
1149 [[nodiscard]] constexpr Vector2 shear_y_at(const Vector2& origin, Real factor) const;
1150
1156 [[nodiscard]] constexpr Vector2 transform(const Basis2<Real>& by) const;
1157
1164 [[nodiscard]] constexpr Vector2 transform_at(const Vector2& origin, const Basis2<Real>& by) const;
1165
1172 [[nodiscard]] constexpr Vector2 transform(const Transform2<Real>& by, Real z = static_cast<Real>(1)) const;
1173
1181 [[nodiscard]] constexpr Vector2 transform_at(
1182 const Vector2& origin, const Transform2<Real>& by, Real z = static_cast<Real>(1)) const;
1183
1188 [[nodiscard]] constexpr Real max() const
1189 {
1190 return at(max_index());
1191 }
1192
1197 [[nodiscard]] constexpr Real abs_max() const
1198 {
1199 return at(abs_max_index());
1200 }
1201
1206 [[nodiscard]] constexpr Real min() const
1207 {
1208 return at(min_index());
1209 }
1210
1215 [[nodiscard]] constexpr Real abs_min() const
1216 {
1217 return at(abs_min_index());
1218 }
1219
1224 [[nodiscard]] constexpr uint8_t max_index() const
1225 {
1226 if (y > x) {
1227 return 1;
1228 }
1229 return 0;
1230 }
1231
1236 [[nodiscard]] constexpr uint8_t abs_max_index() const
1237 {
1238 if (nnm::abs(y) > nnm::abs(x)) {
1239 return 1;
1240 }
1241 return 0;
1242 }
1243
1248 [[nodiscard]] constexpr uint8_t min_index() const
1249 {
1250 if (y < x) {
1251 return 1;
1252 }
1253 return 0;
1254 }
1255
1260 [[nodiscard]] constexpr uint8_t abs_min_index() const
1261 {
1262 if (nnm::abs(y) < nnm::abs(x)) {
1263 return 1;
1264 }
1265 return 0;
1266 }
1267
1273 [[nodiscard]] constexpr bool approx_equal(const Vector2& other) const
1274 {
1275 return nnm::approx_equal(x, other.x) && nnm::approx_equal(y, other.y);
1276 }
1277
1282 [[nodiscard]] constexpr bool approx_zero() const
1283 {
1285 }
1286
1291 [[nodiscard]] const Real* begin() const
1292 {
1293 return &x;
1294 }
1295
1300 [[nodiscard]] const Real* end() const
1301 {
1302 return &y + 1;
1303 }
1304
1309 Real* begin()
1310 {
1311 return &x;
1312 }
1313
1318 Real* end()
1319 {
1320 return &y + 1;
1321 }
1322
1328 [[nodiscard]] constexpr const Real& at(const uint8_t index) const
1329 {
1330 NNM_BOUNDS_CHECK_ASSERT("Vector2", index <= 1);
1331 switch (index) {
1332 case 0:
1333 return x;
1334 case 1:
1335 return y;
1336 default:
1337 return x;
1338 }
1339 }
1340
1346 constexpr Real& at(const uint8_t index)
1347 {
1348 NNM_BOUNDS_CHECK_ASSERT("Vector2", index <= 1);
1349 switch (index) {
1350 case 0:
1351 return x;
1352 case 1:
1353 return y;
1354 default:
1355 return x;
1356 }
1357 }
1358
1364 [[nodiscard]] constexpr const Real& operator[](const uint8_t index) const
1365 {
1366 NNM_BOUNDS_CHECK_ASSERT("Vector2", index <= 1);
1367 switch (index) {
1368 case 0:
1369 return x;
1370 case 1:
1371 return y;
1372 default:
1373 return x;
1374 }
1375 }
1376
1382 constexpr Real& operator[](const uint8_t index)
1383 {
1384 NNM_BOUNDS_CHECK_ASSERT("Vector2", index <= 1);
1385 switch (index) {
1386 case 0:
1387 return x;
1388 case 1:
1389 return y;
1390 default:
1391 return x;
1392 }
1393 }
1394
1400 [[nodiscard]] constexpr bool operator==(const Vector2& other) const
1401 {
1402 return x == other.x && y == other.y;
1403 }
1404
1410 [[nodiscard]] constexpr bool operator!=(const Vector2& other) const
1411 {
1412 return x != other.x || y != other.y;
1413 }
1414
1420 [[nodiscard]] constexpr Vector2 operator+(const Vector2& other) const
1421 {
1422 return { x + other.x, y + other.y };
1423 }
1424
1430 constexpr Vector2& operator+=(const Vector2& other)
1431 {
1432 x += other.x;
1433 y += other.y;
1434 return *this;
1435 }
1436
1442 [[nodiscard]] constexpr Vector2 operator-(const Vector2& other) const
1443 {
1444 return { x - other.x, y - other.y };
1445 }
1446
1452 constexpr Vector2& operator-=(const Vector2& other)
1453 {
1454 x -= other.x;
1455 y -= other.y;
1456 return *this;
1457 }
1458
1464 [[nodiscard]] constexpr Vector2 operator*(const Vector2& other) const
1465 {
1466 return { x * other.x, y * other.y };
1467 }
1468
1474 constexpr Vector2& operator*=(const Vector2& other)
1475 {
1476 x *= other.x;
1477 y *= other.y;
1478 return *this;
1479 }
1480
1486 [[nodiscard]] constexpr Vector2 operator*(const Matrix2<Real>& matrix) const;
1487
1493 [[nodiscard]] constexpr Vector2 operator*(const Real value) const
1494 {
1495 return { x * value, y * value };
1496 }
1497
1503 constexpr Vector2& operator*=(const Real value)
1504 {
1505 x *= value;
1506 y *= value;
1507 return *this;
1508 }
1509
1515 [[nodiscard]] constexpr Vector2 operator/(const Vector2& other) const
1516 {
1517 return { x / other.x, y / other.y };
1518 }
1519
1525 constexpr Vector2& operator/=(const Vector2& other)
1526 {
1527 x /= other.x;
1528 y /= other.y;
1529 return *this;
1530 }
1531
1537 [[nodiscard]] constexpr Vector2 operator/(const Real value) const
1538 {
1539 return { x / value, y / value };
1540 }
1541
1547 constexpr Vector2& operator/=(const Real value)
1548 {
1549 x /= value;
1550 y /= value;
1551 return *this;
1552 }
1553
1558 [[nodiscard]] constexpr Vector2 operator+() const
1559 {
1560 return { x, y };
1561 }
1562
1567 [[nodiscard]] constexpr Vector2 operator-() const
1568 {
1569 return { -x, -y };
1570 }
1571
1577 [[nodiscard]] constexpr bool operator<(const Vector2& other) const
1578 {
1579 if (x < other.x) {
1580 return true;
1581 }
1582 if (x > other.x) {
1583 return false;
1584 }
1585 return y < other.y;
1586 }
1587
1591 [[nodiscard]] explicit constexpr operator bool() const
1592 {
1593 return x != 0 || y != 0;
1594 }
1595};
1596
1604template <typename Real>
1605Vector2<Real> constexpr operator*(const Real value, const Vector2<Real>& vector)
1606{
1607 return { value * vector.x, value * vector.y };
1608}
1609
1617template <typename Real>
1618Vector2<Real> constexpr operator/(const Real value, const Vector2<Real>& vector)
1619{
1620 return { value / vector.x, value / vector.y };
1621}
1622
1627template <typename Int>
1629public:
1630 Int x;
1631 Int y;
1632
1636 constexpr Vector2i()
1637 : x { 0 }
1638 , y { 0 }
1639 {
1640 }
1641
1647 template <typename Real>
1648 explicit constexpr Vector2i(const Vector2<Real>& vector)
1649 : x { static_cast<Int>(vector.x) }
1650 , y { static_cast<Int>(vector.y) }
1651 {
1652 }
1653
1659 constexpr Vector2i(const Int x, const Int y)
1660 : x { x }
1661 , y { y }
1662 {
1663 }
1664
1670 static constexpr Vector2i all(Int value)
1671 {
1672 return { value, value };
1673 }
1674
1679 static constexpr Vector2i zero()
1680 {
1681 return { 0, 0 };
1682 }
1683
1688 static constexpr Vector2i one()
1689 {
1690 return { 1, 1 };
1691 }
1692
1697 static constexpr Vector2i axis_x()
1698 {
1699 return { 1, 0 };
1700 }
1701
1706 static constexpr Vector2i axis_y()
1707 {
1708 return { 0, 1 };
1709 }
1710
1715 [[nodiscard]] constexpr Vector2i abs() const
1716 {
1717 return { nnm::abs(x), nnm::abs(y) };
1718 }
1719
1726 [[nodiscard]] constexpr Vector2i clamp(const Vector2i& min, const Vector2i& max) const
1727 {
1728 return { nnm::clamp(x, min.x, max.x), nnm::clamp(y, min.y, max.y) };
1729 }
1730
1736 [[nodiscard]] constexpr Int manhattan_distance(const Vector2i& to) const
1737 {
1738 return nnm::abs(x - to.x) + nnm::abs(y - to.y);
1739 }
1740
1745 [[nodiscard]] constexpr Int length_sqrd() const
1746 {
1747 return sqrd(x) + sqrd(y);
1748 }
1749
1755 [[nodiscard]] constexpr Int dot(const Vector2i& other) const
1756 {
1757 return x * other.x + y * other.y;
1758 }
1759
1765 [[nodiscard]] constexpr Int cross(const Vector2i& other) const
1766 {
1767 return x * other.y - y * other.x;
1768 }
1769
1775 [[nodiscard]] constexpr bool parallel(const Vector2i& other) const
1776 {
1777 return cross(other) == 0;
1778 }
1779
1785 [[nodiscard]] constexpr bool perpendicular(const Vector2i& other) const
1786 {
1787 return dot(other) == 0;
1788 }
1789
1795 [[nodiscard]] constexpr Vector2i arbitrary_perpendicular() const
1796 {
1797 return { -y, x };
1798 }
1799
1804 [[nodiscard]] constexpr Int max() const
1805 {
1806 return at(max_index());
1807 }
1808
1813 [[nodiscard]] constexpr Int abs_max() const
1814 {
1815 return at(abs_max_index());
1816 }
1817
1822 [[nodiscard]] constexpr Int min() const
1823 {
1824 return at(min_index());
1825 }
1826
1831 [[nodiscard]] constexpr Int abs_min() const
1832 {
1833 return at(abs_min_index());
1834 }
1835
1840 [[nodiscard]] constexpr uint8_t max_index() const
1841 {
1842 if (y > x) {
1843 return 1;
1844 }
1845 return 0;
1846 }
1847
1852 [[nodiscard]] constexpr uint8_t abs_max_index() const
1853 {
1854 if (nnm::abs(y) > nnm::abs(x)) {
1855 return 1;
1856 }
1857 return 0;
1858 }
1859
1864 [[nodiscard]] constexpr uint8_t min_index() const
1865 {
1866 if (y < x) {
1867 return 1;
1868 }
1869 return 0;
1870 }
1871
1876 [[nodiscard]] constexpr uint8_t abs_min_index() const
1877 {
1878 if (nnm::abs(y) < nnm::abs(x)) {
1879 return 1;
1880 }
1881 return 0;
1882 }
1883
1888 [[nodiscard]] const Int* begin() const
1889 {
1890 return &x;
1891 }
1892
1897 [[nodiscard]] const Int* end() const
1898 {
1899 return &y + 1;
1900 }
1901
1906 Int* begin()
1907 {
1908 return &x;
1909 }
1910
1915 Int* end()
1916 {
1917 return &y + 1;
1918 }
1919
1925 [[nodiscard]] constexpr const Int& at(const uint8_t index) const
1926 {
1927 NNM_BOUNDS_CHECK_ASSERT("Vector2i", index <= 1);
1928 switch (index) {
1929 case 0:
1930 return x;
1931 case 1:
1932 return y;
1933 default:
1934 return x;
1935 }
1936 }
1937
1943 constexpr Int& at(const uint8_t index)
1944 {
1945 NNM_BOUNDS_CHECK_ASSERT("Vector2i", index <= 1);
1946 switch (index) {
1947 case 0:
1948 return x;
1949 case 1:
1950 return y;
1951 default:
1952 return x;
1953 }
1954 }
1955
1961 [[nodiscard]] constexpr const Int& operator[](const uint8_t index) const
1962 {
1963 NNM_BOUNDS_CHECK_ASSERT("Vector2i", index <= 1);
1964 switch (index) {
1965 case 0:
1966 return x;
1967 case 1:
1968 return y;
1969 default:
1970 return x;
1971 }
1972 }
1973
1979 constexpr Int& operator[](const uint8_t index)
1980 {
1981 NNM_BOUNDS_CHECK_ASSERT("Vector2i", index <= 1);
1982 switch (index) {
1983 case 0:
1984 return x;
1985 case 1:
1986 return y;
1987 default:
1988 return x;
1989 }
1990 }
1991
1997 [[nodiscard]] constexpr bool operator==(const Vector2i& other) const
1998 {
1999 return x == other.x && y == other.y;
2000 }
2001
2007 [[nodiscard]] constexpr bool operator!=(const Vector2i& other) const
2008 {
2009 return x != other.x || y != other.y;
2010 }
2011
2017 [[nodiscard]] constexpr Vector2i operator+(const Vector2i& other) const
2018 {
2019 return { x + other.x, y + other.y };
2020 }
2021
2027 constexpr Vector2i& operator+=(const Vector2i& other)
2028 {
2029 x += other.x;
2030 y += other.y;
2031 return *this;
2032 }
2033
2039 [[nodiscard]] constexpr Vector2i operator-(const Vector2i& other) const
2040 {
2041 return { x - other.x, y - other.y };
2042 }
2043
2049 constexpr Vector2i& operator-=(const Vector2i& other)
2050 {
2051 x -= other.x;
2052 y -= other.y;
2053 return *this;
2054 }
2055
2061 [[nodiscard]] constexpr Vector2i operator*(const Vector2i& other) const
2062 {
2063 return { x * other.x, y * other.y };
2064 }
2065
2071 constexpr Vector2i& operator*=(const Vector2i& other)
2072 {
2073 x *= other.x;
2074 y *= other.y;
2075 return *this;
2076 }
2077
2083 [[nodiscard]] constexpr Vector2i operator*(const Int value) const
2084 {
2085 return { x * value, y * value };
2086 }
2087
2093 constexpr Vector2i& operator*=(const Int value)
2094 {
2095 x *= value;
2096 y *= value;
2097 return *this;
2098 }
2099
2105 [[nodiscard]] constexpr Vector2i operator/(const Vector2i& other) const
2106 {
2107 return { x / other.x, y / other.y };
2108 }
2109
2115 constexpr Vector2i& operator/=(const Vector2i& other)
2116 {
2117 x /= other.x;
2118 y /= other.y;
2119 return *this;
2120 }
2121
2127 [[nodiscard]] constexpr Vector2i operator/(const Int value) const
2128 {
2129 return { x / value, y / value };
2130 }
2131
2137 constexpr Vector2i& operator/=(const Int value)
2138 {
2139 x /= value;
2140 y /= value;
2141 return *this;
2142 }
2143
2149 [[nodiscard]] constexpr Vector2i operator%(const Vector2i& other) const
2150 {
2151 return { x % other.x, y % other.y };
2152 }
2153
2159 constexpr Vector2i& operator%=(const Vector2i& other)
2160 {
2161 x %= other.x;
2162 y %= other.y;
2163 return *this;
2164 }
2165
2171 [[nodiscard]] constexpr Vector2i operator%(const Int value) const
2172 {
2173 return { x % value, y % value };
2174 }
2175
2181 constexpr Vector2i& operator%=(const Int value)
2182 {
2183 x %= value;
2184 y %= value;
2185 return *this;
2186 }
2187
2192 [[nodiscard]] constexpr Vector2i operator+() const
2193 {
2194 return { x, y };
2195 }
2196
2201 [[nodiscard]] constexpr Vector2i operator-() const
2202 {
2203 return { -x, -y };
2204 }
2205
2211 [[nodiscard]] constexpr bool operator<(const Vector2i& other) const
2212 {
2213 if (x < other.x) {
2214 return true;
2215 }
2216 if (x > other.x) {
2217 return false;
2218 }
2219 return y < other.y;
2220 }
2221
2225 [[nodiscard]] explicit constexpr operator bool() const
2226 {
2227 return x != 0 || y != 0;
2228 }
2229
2233 struct Hash {
2234 size_t operator()(const Vector2i& vector) const noexcept
2235 {
2236 // Based on Boost's hash_combine.
2237 size_t seed = std::hash<Int>()(vector.x);
2238 seed ^= std::hash<Int>()(vector.y) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
2239 return seed;
2240 }
2241 };
2242};
2243
2251template <typename Int>
2252constexpr Vector2i<Int> operator*(const Int value, const Vector2i<Int>& vector)
2253{
2254 return { value * vector.x, value * vector.y };
2255}
2256
2264template <typename Int>
2265constexpr Vector2i<Int> operator/(const Int value, const Vector2i<Int>& vector)
2266{
2267 return { value / vector.x, value / vector.y };
2268}
2269
2277template <typename Int>
2278constexpr Vector2i<Int> operator%(const Int value, const Vector2i<Int>& vector)
2279{
2280 return { value % vector.x, value % vector.y };
2281}
2282
2287template <typename Real>
2288class Vector3 {
2289public:
2290 Real x;
2291 Real y;
2292 Real z;
2293
2297 constexpr Vector3()
2298 : x { static_cast<Real>(0) }
2299 , y { static_cast<Real>(0) }
2300 , z { static_cast<Real>(0) }
2301 {
2302 }
2303
2309 template <typename Int>
2310 explicit constexpr Vector3(const Vector3i<Int>& vector);
2311
2317 template <typename Other>
2318 explicit constexpr Vector3(const Vector3<Other>& vector)
2319 : x { static_cast<Real>(vector.x) }
2320 , y { static_cast<Real>(vector.y) }
2321 , z { static_cast<Real>(vector.z) }
2322 {
2323 }
2324
2330 constexpr Vector3(const Vector2<Real>& vector, const Real z)
2331 : x { vector.x }
2332 , y { vector.y }
2333 , z { z }
2334 {
2335 }
2336
2343 constexpr Vector3(const Real x, const Real y, const Real z)
2344 : x { x }
2345 , y { y }
2346 , z { z }
2347 {
2348 }
2349
2355 static constexpr Vector3 all(Real value)
2356 {
2357 return { value, value, value };
2358 }
2359
2364 static constexpr Vector3 zero()
2365 {
2366 return all(static_cast<Real>(0));
2367 }
2368
2373 static constexpr Vector3 one()
2374 {
2375 return all(static_cast<Real>(1));
2376 }
2377
2382 static constexpr Vector3 axis_x()
2383 {
2384 return { static_cast<Real>(1), static_cast<Real>(0), static_cast<Real>(0) };
2385 }
2386
2391 static constexpr Vector3 axis_y()
2392 {
2393 return { static_cast<Real>(0), static_cast<Real>(1), static_cast<Real>(0) };
2394 }
2395
2400 static constexpr Vector3 axis_z()
2401 {
2402 return { static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(1) };
2403 }
2404
2409 [[nodiscard]] constexpr Vector3 abs() const
2410 {
2411 return { nnm::abs(x), nnm::abs(y), nnm::abs(z) };
2412 }
2413
2418 [[nodiscard]] Vector3 ceil() const
2419 {
2420 return { nnm::ceil(x), nnm::ceil(y), nnm::ceil(z) };
2421 }
2422
2427 [[nodiscard]] Vector3 floor() const
2428 {
2429 return { nnm::floor(x), nnm::floor(y), nnm::floor(z) };
2430 }
2431
2436 [[nodiscard]] Vector3 round() const
2437 {
2438 return { nnm::round(x), nnm::round(y), nnm::round(z) };
2439 }
2440
2447 [[nodiscard]] constexpr Vector3 clamp(const Vector3& min, const Vector3& max) const
2448 {
2449 return { nnm::clamp(x, min.x, max.x), nnm::clamp(y, min.y, max.y), nnm::clamp(z, min.z, max.z) };
2450 }
2451
2457 [[nodiscard]] Vector3 direction(const Vector3& to) const
2458 {
2459 return (to - *this).normalize();
2460 }
2461
2467 [[nodiscard]] constexpr Vector3 direction_unnormalized(const Vector3& to) const
2468 {
2469 return to - *this;
2470 }
2471
2477 [[nodiscard]] constexpr Real distance_sqrd(const Vector3& to) const
2478 {
2479 const Real diff_x = to.x - x;
2480 const Real diff_y = to.y - y;
2481 const Real diff_z = to.z - z;
2482 return sqrd(diff_x) + sqrd(diff_y) + sqrd(diff_z);
2483 }
2484
2490 [[nodiscard]] Real distance(const Vector3& to) const
2491 {
2492 return sqrt(this->distance_sqrd(to));
2493 }
2494
2500 [[nodiscard]] constexpr Real manhattan_distance(const Vector3& to) const
2501 {
2502 return nnm::abs(x - to.x) + nnm::abs(y - to.y) + nnm::abs(z - to.z);
2503 }
2504
2509 [[nodiscard]] constexpr Real length_sqrd() const
2510 {
2511 return sqrd(x) + sqrd(y) + sqrd(z);
2512 }
2513
2518 [[nodiscard]] Real length() const
2519 {
2520 return sqrt(length_sqrd());
2521 }
2522
2529 [[nodiscard]] Vector3 clamp_length(const Real min, const Real max) const
2530 {
2531 const Real length = this->length();
2532 if (length == static_cast<Real>(0)) {
2533 return zero();
2534 }
2535 const auto norm = normalize();
2536 if (length < min) {
2537 return norm * min;
2538 }
2539 if (length > max) {
2540 return norm * max;
2541 }
2542 return *this;
2543 }
2544
2549 [[nodiscard]] Vector3 normalize() const
2550 {
2551 if (const auto length = this->length(); length > static_cast<Real>(0)) {
2552 return *this / length;
2553 }
2554 return zero();
2555 }
2556
2563 [[nodiscard]] constexpr Vector3 lerp(const Vector3& to, const Real weight) const
2564 {
2565 return { nnm::lerp(x, to.x, weight), nnm::lerp(y, to.y, weight), nnm::lerp(z, to.z, weight) };
2566 }
2567
2574 [[nodiscard]] constexpr Vector3 lerp_clamped(const Vector3& to, const Real weight) const
2575 {
2576 return { nnm::lerp_clamped(x, to.x, weight),
2577 nnm::lerp_clamped(y, to.y, weight),
2578 nnm::lerp_clamped(z, to.z, weight) };
2579 }
2580
2586 [[nodiscard]] constexpr Real dot(const Vector3& other) const
2587 {
2588 return x * other.x + y * other.y + z * other.z;
2589 }
2590
2596 [[nodiscard]] constexpr Vector3 cross(const Vector3& other) const
2597 {
2598 return { y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x };
2599 }
2600
2606 [[nodiscard]] constexpr Matrix3<Real> outer(const Vector3& other) const;
2607
2613 [[nodiscard]] constexpr Vector3 reflect(const Vector3& normal) const
2614 {
2615 Vector3 result;
2616 const Real dot = this->dot(normal);
2617 result.x = x - static_cast<Real>(2) * normal.x * dot;
2618 result.y = y - static_cast<Real>(2) * normal.y * dot;
2619 result.z = z - static_cast<Real>(2) * normal.z * dot;
2620 return result;
2621 }
2622
2628 [[nodiscard]] constexpr Vector3 project(const Vector3& onto) const
2629 {
2630 const Real onto_length_sqrd = onto.length_sqrd();
2631 if (onto_length_sqrd == static_cast<Real>(0)) {
2632 return zero();
2633 }
2634 const Real scale = dot(onto) / onto_length_sqrd;
2635 return onto * scale;
2636 }
2637
2642 [[nodiscard]] constexpr Vector3 inverse() const
2643 {
2644 return { static_cast<Real>(1) / x, static_cast<Real>(1) / y, static_cast<Real>(1) / z };
2645 }
2646
2652 [[nodiscard]] Real angle(const Vector3& to) const
2653 {
2654 return atan2(this->cross(to).length(), this->dot(to));
2655 }
2656
2662 [[nodiscard]] constexpr bool parallel(const Vector3& other) const
2663 {
2664 return cross(other).approx_zero();
2665 }
2666
2672 [[nodiscard]] constexpr bool perpendicular(const Vector3& other) const
2673 {
2674 return nnm::approx_zero(dot(other));
2675 }
2676
2682 [[nodiscard]] constexpr Vector3 arbitrary_perpendicular() const
2683 {
2684 const Vector3 other = nnm::abs(x) > nnm::abs(y) ? Vector3 { 0, 1, 0 } : Vector3 { 1, 0, 0 };
2685 return cross(other);
2686 }
2687
2693 [[nodiscard]] constexpr Vector3 translate(const Vector3& by) const;
2694
2701 [[nodiscard]] Vector3 rotate_axis_angle(const Vector3& axis, Real angle) const;
2702
2710 [[nodiscard]] Vector3 rotate_axis_angle_at(const Vector3& origin, const Vector3& axis, Real angle) const;
2711
2717 [[nodiscard]] constexpr Vector3 rotate_quaternion(const Quaternion<Real>& quaternion) const;
2718
2725 [[nodiscard]] constexpr Vector3 rotate_quaternion_at(
2726 const Vector3& origin, const Quaternion<Real>& quaternion) const;
2727
2733 [[nodiscard]] constexpr Vector3 scale(const Vector3& factor) const;
2734
2741 [[nodiscard]] constexpr Vector3 scale_at(const Vector3& origin, const Vector3& factor) const;
2742
2749 [[nodiscard]] constexpr Vector3 shear_x(Real factor_y, Real factor_z) const;
2750
2758 [[nodiscard]] constexpr Vector3 shear_x_at(const Vector3& origin, Real factor_y, Real factor_z) const;
2759
2766 [[nodiscard]] constexpr Vector3 shear_y(Real factor_x, Real factor_z) const;
2767
2775 [[nodiscard]] constexpr Vector3 shear_y_at(const Vector3& origin, Real factor_x, Real factor_z) const;
2776
2783 [[nodiscard]] constexpr Vector3 shear_z(Real factor_x, Real factor_y) const;
2784
2792 [[nodiscard]] constexpr Vector3 shear_z_at(const Vector3& origin, Real factor_x, Real factor_y) const;
2793
2799 [[nodiscard]] constexpr Vector3 transform(const Basis3<Real>& by) const;
2800
2807 [[nodiscard]] constexpr Vector3 transform_at(const Vector3& origin, const Basis3<Real>& by) const;
2808
2814 [[nodiscard]] constexpr Vector3 transform(const Transform2<Real>& by) const;
2815
2822 [[nodiscard]] constexpr Vector3 transform_at(const Vector2<Real>& origin, const Transform2<Real>& by) const;
2823
2830 [[nodiscard]] constexpr Vector3 transform(const Transform3<Real>& by, Real w = static_cast<Real>(1)) const;
2831
2839 [[nodiscard]] constexpr Vector3 transform_at(
2840 const Vector3& origin, const Transform3<Real>& by, Real w = static_cast<Real>(1)) const;
2841
2846 [[nodiscard]] constexpr Real max() const
2847 {
2848 return at(max_index());
2849 }
2850
2855 [[nodiscard]] constexpr Real abs_max() const
2856 {
2857 return at(abs_max_index());
2858 }
2859
2864 [[nodiscard]] constexpr Real min() const
2865 {
2866 return nnm::min(x, nnm::min(y, z));
2867 }
2868
2873 [[nodiscard]] constexpr Real abs_min() const
2874 {
2875 return at(abs_min_index());
2876 }
2877
2882 [[nodiscard]] constexpr uint8_t max_index() const
2883 {
2884 Real max_val = x;
2885 uint8_t max_axis = 0;
2886 if (y > max_val) {
2887 max_val = y;
2888 max_axis = 1;
2889 }
2890 if (z > max_val) {
2891 max_axis = 2;
2892 }
2893 return max_axis;
2894 }
2895
2900 [[nodiscard]] constexpr uint8_t abs_max_index() const
2901 {
2902 Real max_val = nnm::abs(x);
2903 uint8_t max_axis = 0;
2904 const Real y_abs = nnm::abs(y);
2905 if (y_abs > max_val) {
2906 max_val = y_abs;
2907 max_axis = 1;
2908 }
2909 if (nnm::abs(z) > max_val) {
2910 max_axis = 2;
2911 }
2912 return max_axis;
2913 }
2914
2919 [[nodiscard]] constexpr uint8_t min_index() const
2920 {
2921 Real min_val = x;
2922 uint8_t min_axis = 0;
2923 if (y < min_val) {
2924 min_val = y;
2925 min_axis = 1;
2926 }
2927 if (z < min_val) {
2928 min_axis = 2;
2929 }
2930 return min_axis;
2931 }
2932
2937 [[nodiscard]] constexpr uint8_t abs_min_index() const
2938 {
2939 Real min_val = nnm::abs(x);
2940 uint8_t min_axis = 0;
2941 const Real y_abs = nnm::abs(y);
2942 if (y_abs < min_val) {
2943 min_val = y;
2944 min_axis = 1;
2945 }
2946 if (nnm::abs(z) < min_val) {
2947 min_axis = 2;
2948 }
2949 return min_axis;
2950 }
2951
2957 [[nodiscard]] constexpr bool approx_equal(const Vector3& other) const
2958 {
2959 return nnm::approx_equal(x, other.x) && nnm::approx_equal(y, other.y) && nnm::approx_equal(z, other.z);
2960 }
2961
2966 [[nodiscard]] constexpr bool approx_zero() const
2967 {
2969 }
2970
2975 [[nodiscard]] constexpr Vector2<Real> xy() const
2976 {
2977 return { x, y };
2978 }
2979
2984 [[nodiscard]] const Real* begin() const
2985 {
2986 return &x;
2987 }
2988
2993 [[nodiscard]] const Real* end() const
2994 {
2995 return &z + 1;
2996 }
2997
3002 Real* begin()
3003 {
3004 return &x;
3005 }
3006
3011 Real* end()
3012 {
3013 return &z + 1;
3014 }
3015
3021 [[nodiscard]] constexpr const Real& at(const uint8_t index) const
3022 {
3023 NNM_BOUNDS_CHECK_ASSERT("Vector3", index <= 2);
3024 switch (index) {
3025 case 0:
3026 return x;
3027 case 1:
3028 return y;
3029 case 2:
3030 return z;
3031 default:
3032 return x;
3033 }
3034 }
3035
3041 constexpr Real& at(const uint8_t index)
3042 {
3043 NNM_BOUNDS_CHECK_ASSERT("Vector3", index <= 2);
3044 switch (index) {
3045 case 0:
3046 return x;
3047 case 1:
3048 return y;
3049 case 2:
3050 return z;
3051 default:
3052 return x;
3053 }
3054 }
3055
3061 [[nodiscard]] constexpr const Real& operator[](const uint8_t index) const
3062 {
3063 NNM_BOUNDS_CHECK_ASSERT("Vector3", index <= 2);
3064 switch (index) {
3065 case 0:
3066 return x;
3067 case 1:
3068 return y;
3069 case 2:
3070 return z;
3071 default:
3072 return x;
3073 }
3074 }
3075
3081 constexpr Real& operator[](const uint8_t index)
3082 {
3083 NNM_BOUNDS_CHECK_ASSERT("Vector3", index <= 2);
3084 switch (index) {
3085 case 0:
3086 return x;
3087 case 1:
3088 return y;
3089 case 2:
3090 return z;
3091 default:
3092 return x;
3093 }
3094 }
3095
3101 [[nodiscard]] constexpr bool operator==(const Vector3& other) const
3102 {
3103 return x == other.x && y == other.y && z == other.z;
3104 }
3105
3111 [[nodiscard]] constexpr bool operator!=(const Vector3& other) const
3112 {
3113 return x != other.x || y != other.y || z != other.z;
3114 }
3115
3121 [[nodiscard]] constexpr Vector3 operator+(const Vector3& other) const
3122 {
3123 return { x + other.x, y + other.y, z + other.z };
3124 }
3125
3131 constexpr Vector3& operator+=(const Vector3& other)
3132 {
3133 x += other.x;
3134 y += other.y;
3135 z += other.z;
3136 return *this;
3137 }
3138
3144 [[nodiscard]] constexpr Vector3 operator-(const Vector3& other) const
3145 {
3146 return { x - other.x, y - other.y, z - other.z };
3147 }
3148
3154 constexpr Vector3& operator-=(const Vector3& other)
3155 {
3156 x -= other.x;
3157 y -= other.y;
3158 z -= other.z;
3159 return *this;
3160 }
3161
3167 [[nodiscard]] constexpr Vector3 operator*(const Vector3& other) const
3168 {
3169 return { x * other.x, y * other.y, z * other.z };
3170 }
3171
3177 constexpr Vector3& operator*=(const Vector3& other)
3178 {
3179 x *= other.x;
3180 y *= other.y;
3181 z *= other.z;
3182 return *this;
3183 }
3184
3190 [[nodiscard]] constexpr Vector3 operator*(const Matrix3<Real>& matrix) const;
3191
3197 [[nodiscard]] constexpr Vector3 operator*(const Real value) const
3198 {
3199 return { x * value, y * value, z * value };
3200 }
3201
3207 constexpr Vector3& operator*=(const Real value)
3208 {
3209 x *= value;
3210 y *= value;
3211 z *= value;
3212 return *this;
3213 }
3214
3220 [[nodiscard]] constexpr Vector3 operator/(const Vector3& other) const
3221 {
3222 return { x / other.x, y / other.y, z / other.z };
3223 }
3224
3230 constexpr Vector3& operator/=(const Vector3& other)
3231 {
3232 x /= other.x;
3233 y /= other.y;
3234 z /= other.z;
3235 return *this;
3236 }
3237
3243 [[nodiscard]] constexpr Vector3 operator/(const Real value) const
3244 {
3245 return { x / value, y / value, z / value };
3246 }
3247
3253 constexpr Vector3& operator/=(const Real value)
3254 {
3255 x /= value;
3256 y /= value;
3257 z /= value;
3258 return *this;
3259 }
3260
3265 [[nodiscard]] constexpr Vector3 operator+() const
3266 {
3267 return { x, y, z };
3268 }
3269
3274 [[nodiscard]] constexpr Vector3 operator-() const
3275 {
3276 return { -x, -y, -z };
3277 }
3278
3284 [[nodiscard]] constexpr bool operator<(const Vector3& other) const
3285 {
3286 for (uint8_t i = 0; i < 3; ++i) {
3287 if (at(i) < other.at(i)) {
3288 return true;
3289 }
3290 if (at(i) > other.at(i)) {
3291 return false;
3292 }
3293 }
3294 return false;
3295 }
3296
3300 [[nodiscard]] explicit constexpr operator bool() const
3301 {
3302 return x != static_cast<Real>(0) || y != static_cast<Real>(0) || z != static_cast<Real>(0);
3303 }
3304};
3305
3313template <typename Real>
3314constexpr Vector3<Real> operator*(const Real value, const Vector3<Real>& vector)
3315{
3316 return { value * vector.x, value * vector.y, value * vector.z };
3317}
3318
3326template <typename Real>
3327constexpr Vector3<Real> operator/(const Real value, const Vector3<Real>& vector)
3328{
3329 return { value / vector.x, value / vector.y, value / vector.z };
3330}
3331
3336template <typename Int>
3338public:
3339 Int x;
3340 Int y;
3341 Int z;
3342
3346 constexpr Vector3i()
3347 : x { 0 }
3348 , y { 0 }
3349 , z { 0 }
3350 {
3351 }
3352
3358 template <typename Real>
3359 explicit constexpr Vector3i(const Vector3<Real>& vector)
3360 : x { static_cast<Int>(vector.x) }
3361 , y { static_cast<Int>(vector.y) }
3362 , z { static_cast<Int>(vector.z) }
3363 {
3364 }
3365
3371 constexpr Vector3i(const Vector2i<Int>& vector, const Int z)
3372 : x { vector.x }
3373 , y { vector.y }
3374 , z { z }
3375 {
3376 }
3377
3384 constexpr Vector3i(const Int x, const Int y, const Int z)
3385 : x { x }
3386 , y { y }
3387 , z { z }
3388 {
3389 }
3390
3396 static constexpr Vector3i all(const Int value)
3397 {
3398 return { value, value, value };
3399 }
3400
3405 static constexpr Vector3i zero()
3406 {
3407 return { 0, 0, 0 };
3408 }
3409
3414 static constexpr Vector3i one()
3415 {
3416 return { 1, 1, 1 };
3417 }
3418
3423 static constexpr Vector3i axis_x()
3424 {
3425 return { 1, 0, 0 };
3426 }
3427
3432 static constexpr Vector3i axis_y()
3433 {
3434 return { 0, 1, 0 };
3435 }
3436
3441 static constexpr Vector3i axis_z()
3442 {
3443 return { 0, 0, 1 };
3444 }
3445
3450 [[nodiscard]] constexpr Vector3i abs() const
3451 {
3452 return { nnm::abs(x), nnm::abs(y), nnm::abs(z) };
3453 }
3454
3461 [[nodiscard]] constexpr Vector3i clamp(const Vector3i& min, const Vector3i& max) const
3462 {
3463 return { nnm::clamp(x, min.x, max.x), nnm::clamp(y, min.y, max.y), nnm::clamp(z, min.z, max.z) };
3464 }
3465
3471 [[nodiscard]] constexpr Int manhattan_distance(const Vector3i& to) const
3472 {
3473 return nnm::abs(x - to.x) + nnm::abs(y - to.y) + nnm::abs(z - to.z);
3474 }
3475
3480 [[nodiscard]] constexpr Int length_sqrd() const
3481 {
3482 return sqrd(x) + sqrd(y) + sqrd(z);
3483 }
3484
3490 [[nodiscard]] constexpr Int dot(const Vector3i& other) const
3491 {
3492 return x * other.x + y * other.y + z * other.z;
3493 }
3494
3500 [[nodiscard]] constexpr Vector3i cross(const Vector3i& other) const
3501 {
3502 return { y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x };
3503 }
3504
3510 [[nodiscard]] constexpr bool parallel(const Vector3i& other) const
3511 {
3512 return cross(other) == zero();
3513 }
3514
3520 [[nodiscard]] constexpr bool perpendicular(const Vector3i& other) const
3521 {
3522 return dot(other) == 0;
3523 }
3524
3530 [[nodiscard]] constexpr Vector3i arbitrary_perpendicular() const
3531 {
3532 const Vector3i other = nnm::abs(x) > nnm::abs(y) ? Vector3i { 0, 1, 0 } : Vector3i { 1, 0, 0 };
3533 return cross(other);
3534 }
3535
3540 [[nodiscard]] constexpr Int max() const
3541 {
3542 return at(max_index());
3543 }
3544
3549 [[nodiscard]] constexpr Int abs_max() const
3550 {
3551 return at(abs_max_index());
3552 }
3553
3558 [[nodiscard]] constexpr Int min() const
3559 {
3560 return at(min_index());
3561 }
3562
3567 [[nodiscard]] constexpr Int abs_min() const
3568 {
3569 return at(abs_min_index());
3570 }
3571
3576 [[nodiscard]] constexpr uint8_t max_index() const
3577 {
3578 Int max_val = x;
3579 uint8_t max_axis = 0;
3580 if (y > max_val) {
3581 max_val = y;
3582 max_axis = 1;
3583 }
3584 if (z > max_val) {
3585 max_axis = 2;
3586 }
3587 return max_axis;
3588 }
3589
3594 [[nodiscard]] constexpr uint8_t abs_max_index() const
3595 {
3596 Int max_val = nnm::abs(x);
3597 uint8_t max_axis = 0;
3598 const Int y_abs = nnm::abs(y);
3599 if (y_abs > max_val) {
3600 max_val = y_abs;
3601 max_axis = 1;
3602 }
3603 if (nnm::abs(z) > max_val) {
3604 max_axis = 2;
3605 }
3606 return max_axis;
3607 }
3608
3613 [[nodiscard]] constexpr uint8_t min_index() const
3614 {
3615 Int min_val = x;
3616 uint8_t min_axis = 0;
3617 if (y < min_val) {
3618 min_val = y;
3619 min_axis = 1;
3620 }
3621 if (z < min_val) {
3622 min_axis = 2;
3623 }
3624 return min_axis;
3625 }
3626
3631 [[nodiscard]] constexpr uint8_t abs_min_index() const
3632 {
3633 Int min_val = nnm::abs(x);
3634 uint8_t min_axis = 0;
3635 const Int y_abs = nnm::abs(y);
3636 if (y_abs < min_val) {
3637 min_val = y_abs;
3638 min_axis = 1;
3639 }
3640 if (nnm::abs(z) < min_val) {
3641 min_axis = 2;
3642 }
3643 return min_axis;
3644 }
3645
3650 [[nodiscard]] constexpr Vector2i<Int> xy() const
3651 {
3652 return { x, y };
3653 }
3654
3659 [[nodiscard]] const Int* begin() const
3660 {
3661 return &x;
3662 }
3663
3668 [[nodiscard]] const Int* end() const
3669 {
3670 return &z + 1;
3671 }
3672
3677 Int* begin()
3678 {
3679 return &x;
3680 }
3681
3686 Int* end()
3687 {
3688 return &z + 1;
3689 }
3690
3696 [[nodiscard]] constexpr const Int& at(const uint8_t index) const
3697 {
3698 NNM_BOUNDS_CHECK_ASSERT("Vector3i", index <= 2);
3699 switch (index) {
3700 case 0:
3701 return x;
3702 case 1:
3703 return y;
3704 case 2:
3705 return z;
3706 default:
3707 return x;
3708 }
3709 }
3710
3716 constexpr Int& at(const uint8_t index)
3717 {
3718 NNM_BOUNDS_CHECK_ASSERT("Vector3i", index <= 2);
3719 switch (index) {
3720 case 0:
3721 return x;
3722 case 1:
3723 return y;
3724 case 2:
3725 return z;
3726 default:
3727 return x;
3728 }
3729 }
3730
3736 [[nodiscard]] constexpr const Int& operator[](const uint8_t index) const
3737 {
3738 NNM_BOUNDS_CHECK_ASSERT("Vector3i", index <= 2);
3739 switch (index) {
3740 case 0:
3741 return x;
3742 case 1:
3743 return y;
3744 case 2:
3745 return z;
3746 default:
3747 return x;
3748 }
3749 }
3750
3756 constexpr Int& operator[](const uint8_t index)
3757 {
3758 NNM_BOUNDS_CHECK_ASSERT("Vector3i", index <= 2);
3759 switch (index) {
3760 case 0:
3761 return x;
3762 case 1:
3763 return y;
3764 case 2:
3765 return z;
3766 default:
3767 return x;
3768 }
3769 }
3770
3776 [[nodiscard]] constexpr bool operator==(const Vector3i& other) const
3777 {
3778 return x == other.x && y == other.y && z == other.z;
3779 }
3780
3786 [[nodiscard]] constexpr bool operator!=(const Vector3i& other) const
3787 {
3788 return x != other.x || y != other.y || z != other.z;
3789 }
3790
3796 [[nodiscard]] constexpr Vector3i operator+(const Vector3i& other) const
3797 {
3798 return { x + other.x, y + other.y, z + other.z };
3799 }
3800
3806 constexpr Vector3i& operator+=(const Vector3i& other)
3807 {
3808 x += other.x;
3809 y += other.y;
3810 z += other.z;
3811 return *this;
3812 }
3813
3819 [[nodiscard]] constexpr Vector3i operator-(const Vector3i& other) const
3820 {
3821 return { x - other.x, y - other.y, z - other.z };
3822 }
3823
3829 constexpr Vector3i& operator-=(const Vector3i& other)
3830 {
3831 x -= other.x;
3832 y -= other.y;
3833 z -= other.z;
3834 return *this;
3835 }
3836
3842 [[nodiscard]] constexpr Vector3i operator*(const Vector3i& other) const
3843 {
3844 return { x * other.x, y * other.y, z * other.z };
3845 }
3846
3852 constexpr Vector3i& operator*=(const Vector3i& other)
3853 {
3854 x *= other.x;
3855 y *= other.y;
3856 z *= other.z;
3857 return *this;
3858 }
3859
3865 [[nodiscard]] constexpr Vector3i operator*(const Int value) const
3866 {
3867 return { x * value, y * value, z * value };
3868 }
3869
3875 constexpr Vector3i& operator*=(const Int value)
3876 {
3877 x *= value;
3878 y *= value;
3879 z *= value;
3880 return *this;
3881 }
3882
3888 [[nodiscard]] constexpr Vector3i operator/(const Vector3i& other) const
3889 {
3890 return { x / other.x, y / other.y, z / other.z };
3891 }
3892
3898 constexpr Vector3i& operator/=(const Vector3i& other)
3899 {
3900 x /= other.x;
3901 y /= other.y;
3902 z /= other.z;
3903 return *this;
3904 }
3905
3911 [[nodiscard]] constexpr Vector3i operator/(const Int value) const
3912 {
3913 return { x / value, y / value, z / value };
3914 }
3915
3921 constexpr Vector3i& operator/=(const Int value)
3922 {
3923 x /= value;
3924 y /= value;
3925 z /= value;
3926 return *this;
3927 }
3928
3934 [[nodiscard]] constexpr Vector3i operator%(const Vector3i& other) const
3935 {
3936 return { x % other.x, y % other.y, z % other.z };
3937 }
3938
3944 constexpr Vector3i& operator%=(const Vector3i& other)
3945 {
3946 x %= other.x;
3947 y %= other.y;
3948 z %= other.z;
3949 return *this;
3950 }
3951
3957 [[nodiscard]] constexpr Vector3i operator%(const Int value) const
3958 {
3959 return { x % value, y % value, z % value };
3960 }
3961
3967 constexpr Vector3i& operator%=(const Int value)
3968 {
3969 x %= value;
3970 y %= value;
3971 z %= value;
3972 return *this;
3973 }
3974
3979 [[nodiscard]] constexpr Vector3i operator+() const
3980 {
3981 return { x, y, z };
3982 }
3983
3988 [[nodiscard]] constexpr Vector3i operator-() const
3989 {
3990 return { -x, -y, -z };
3991 }
3992
3998 [[nodiscard]] constexpr bool operator<(const Vector3i& other) const
3999 {
4000 for (uint8_t i = 0; i < 3; ++i) {
4001 if (at(i) < other.at(i)) {
4002 return true;
4003 }
4004 if (at(i) > other.at(i)) {
4005 return false;
4006 }
4007 }
4008 return false;
4009 }
4010
4014 [[nodiscard]] constexpr explicit operator bool() const
4015 {
4016 return x != 0 || y != 0 || z != 0;
4017 }
4018
4022 struct Hash {
4023 size_t operator()(const Vector3i& vector) const noexcept
4024 {
4025 // Based on Boost's hash_combine.
4026 size_t seed = std::hash<Int>()(vector.x);
4027 seed ^= std::hash<Int>()(vector.y) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
4028 seed ^= std::hash<Int>()(vector.z) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
4029 return seed;
4030 }
4031 };
4032};
4033
4041template <typename Int>
4042constexpr Vector3i<Int> operator*(const Int value, const Vector3i<Int>& vector)
4043{
4044 return { value * vector.x, value * vector.y, value * vector.z };
4045}
4046
4054template <typename Int>
4055constexpr Vector3i<Int> operator/(const Int value, const Vector3i<Int>& vector)
4056{
4057 return { value / vector.x, value / vector.y, value / vector.z };
4058}
4059
4067template <typename Int>
4068constexpr Vector3i<Int> operator%(const Int value, const Vector3i<Int>& vector)
4069{
4070 return { value % vector.x, value % vector.y, value % vector.z };
4071}
4072
4077template <typename Real>
4078class Vector4 {
4079public:
4080 Real x;
4081 Real y;
4082 Real z;
4083 Real w;
4084
4088 constexpr Vector4()
4089 : x { static_cast<Real>(0) }
4090 , y { static_cast<Real>(0) }
4091 , z { static_cast<Real>(0) }
4092 , w { static_cast<Real>(0) }
4093 {
4094 }
4095
4101 template <typename Other>
4102 explicit constexpr Vector4(const Vector4<Other>& vector)
4103 : x { static_cast<Real>(vector.x) }
4104 , y { static_cast<Real>(vector.y) }
4105 , z { static_cast<Real>(vector.z) }
4106 , w { static_cast<Real>(vector.w) }
4107 {
4108 }
4109
4116 constexpr Vector4(const Vector2<Real>& vector, const Real z, const Real w)
4117 : x { vector.x }
4118 , y { vector.y }
4119 , z { z }
4120 , w { w }
4121 {
4122 }
4123
4129 constexpr Vector4(const Vector3<Real>& vector, const Real w)
4130 : x { vector.x }
4131 , y { vector.y }
4132 , z { vector.z }
4133 , w { w }
4134 {
4135 }
4136
4144 constexpr Vector4(const Real x, const Real y, const Real z, const Real w)
4145 : x { x }
4146 , y { y }
4147 , z { z }
4148 , w { w }
4149 {
4150 }
4151
4157 static constexpr Vector4 from_quaternion(const Quaternion<Real>& quaternion);
4158
4164 static constexpr Vector4 all(const Real value)
4165 {
4166 return { value, value, value, value };
4167 }
4168
4173 static constexpr Vector4 zero()
4174 {
4175 return all(static_cast<Real>(0));
4176 }
4177
4182 static constexpr Vector4 one()
4183 {
4184 return all(static_cast<Real>(1));
4185 }
4186
4191 static constexpr Vector4 axis_x()
4192 {
4193 return { static_cast<Real>(1), static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(0) };
4194 }
4195
4200 static constexpr Vector4 axis_y()
4201 {
4202 return { static_cast<Real>(0), static_cast<Real>(1), static_cast<Real>(0), static_cast<Real>(0) };
4203 }
4204
4209 static constexpr Vector4 axis_z()
4210 {
4211 return { static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(1), static_cast<Real>(0) };
4212 }
4213
4218 static constexpr Vector4 axis_w()
4219 {
4220 return { static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(1) };
4221 }
4222
4227 [[nodiscard]] constexpr Vector4 abs() const
4228 {
4229 return { nnm::abs(x), nnm::abs(y), nnm::abs(z), nnm::abs(w) };
4230 }
4231
4236 [[nodiscard]] Vector4 ceil() const
4237 {
4238 return { nnm::ceil(x), nnm::ceil(y), nnm::ceil(z), nnm::ceil(w) };
4239 }
4240
4245 [[nodiscard]] Vector4 floor() const
4246 {
4247 return { nnm::floor(x), nnm::floor(y), nnm::floor(z), nnm::floor(w) };
4248 }
4249
4254 [[nodiscard]] Vector4 round() const
4255 {
4256 return { nnm::round(x), nnm::round(y), nnm::round(z), nnm::round(w) };
4257 }
4258
4265 [[nodiscard]] constexpr Vector4 clamp(const Vector4& min, const Vector4& max) const
4266 {
4267 return { nnm::clamp(x, min.x, max.x),
4268 nnm::clamp(y, min.y, max.y),
4269 nnm::clamp(z, min.z, max.z),
4270 nnm::clamp(w, min.w, max.w) };
4271 }
4272
4277 [[nodiscard]] constexpr Real length_sqrd() const
4278 {
4279 return sqrd(x) + sqrd(y) + sqrd(z) + sqrd(w);
4280 }
4281
4286 [[nodiscard]] Real length() const
4287 {
4288 return sqrt(length_sqrd());
4289 }
4290
4297 [[nodiscard]] Vector4 clamp_length(const Real min, const Real max) const
4298 {
4299 const Real length = this->length();
4300 if (length == static_cast<Real>(0)) {
4301 return zero();
4302 }
4303 const auto norm = normalize();
4304 if (length < min) {
4305 return norm * min;
4306 }
4307 if (length > max) {
4308 return norm * max;
4309 }
4310 return *this;
4311 }
4312
4317 [[nodiscard]] Vector4 normalize() const
4318 {
4319 if (const Real length = this->length(); length > static_cast<Real>(0)) {
4320 return *this / length;
4321 }
4322 return zero();
4323 }
4324
4331 [[nodiscard]] constexpr Vector4 lerp(const Vector4& to, const Real weight) const
4332 {
4333 return { nnm::lerp(x, to.x, weight),
4334 nnm::lerp(y, to.y, weight),
4335 nnm::lerp(z, to.z, weight),
4336 nnm::lerp(w, to.w, weight) };
4337 }
4338
4345 [[nodiscard]] constexpr Vector4 lerp_clamped(const Vector4& to, const Real weight) const
4346 {
4347 return { nnm::lerp_clamped(x, to.x, weight),
4348 nnm::lerp_clamped(y, to.y, weight),
4349 nnm::lerp_clamped(z, to.z, weight),
4350 nnm::lerp_clamped(w, to.w, weight) };
4351 }
4352
4358 [[nodiscard]] constexpr Real dot(const Vector4& other) const
4359 {
4360 return x * other.x + y * other.y + z * other.z + w * other.w;
4361 }
4362
4368 [[nodiscard]] constexpr Matrix4<Real> outer(const Vector4& other) const;
4369
4374 [[nodiscard]] constexpr Vector4 inverse() const
4375 {
4376 return {
4377 static_cast<Real>(1) / x, static_cast<Real>(1) / y, static_cast<Real>(1) / z, static_cast<Real>(1) / w
4378 };
4379 }
4380
4386 [[nodiscard]] constexpr Vector4 transform(const Transform3<Real>& by) const;
4387
4394 [[nodiscard]] constexpr Vector4 transform_at(const Vector3<Real>& origin, const Transform3<Real>& by) const;
4395
4400 [[nodiscard]] constexpr Real max() const
4401 {
4402 return at(max_index());
4403 }
4404
4409 [[nodiscard]] constexpr Real abs_max() const
4410 {
4411 return at(abs_max_index());
4412 }
4413
4418 [[nodiscard]] constexpr Real min() const
4419 {
4420 return at(min_index());
4421 }
4422
4427 [[nodiscard]] constexpr Real abs_min() const
4428 {
4429 return at(abs_min_index());
4430 }
4431
4436 [[nodiscard]] constexpr uint8_t max_index() const
4437 {
4438 Real max_val = x;
4439 uint8_t max_axis = 0;
4440 if (y > max_val) {
4441 max_val = y;
4442 max_axis = 1;
4443 }
4444 if (z > max_val) {
4445 max_val = z;
4446 max_axis = 2;
4447 }
4448 if (w > max_val) {
4449 max_axis = 3;
4450 }
4451 return max_axis;
4452 }
4453
4454 [[nodiscard]] constexpr uint8_t abs_max_index() const
4455 {
4456 Real max_val = nnm::abs(x);
4457 uint8_t max_axis = 0;
4458 const Real y_abs = nnm::abs(y);
4459 if (y_abs > max_val) {
4460 max_val = y_abs;
4461 max_axis = 1;
4462 }
4463 const Real z_abs = nnm::abs(z);
4464 if (z_abs > max_val) {
4465 max_val = z_abs;
4466 max_axis = 2;
4467 }
4468 if (nnm::abs(w) > max_val) {
4469 max_axis = 3;
4470 }
4471 return max_axis;
4472 }
4473
4478 [[nodiscard]] constexpr uint8_t min_index() const
4479 {
4480 Real min_val = x;
4481 uint8_t min_axis = 0;
4482 if (y < min_val) {
4483 min_val = y;
4484 min_axis = 1;
4485 }
4486 if (z < min_val) {
4487 min_val = z;
4488 min_axis = 2;
4489 }
4490 if (w < min_val) {
4491 min_axis = 3;
4492 }
4493 return min_axis;
4494 }
4495
4500 [[nodiscard]] constexpr uint8_t abs_min_index() const
4501 {
4502 Real min_val = nnm::abs(x);
4503 uint8_t min_axis = 0;
4504 const Real y_abs = nnm::abs(y);
4505 if (y_abs < min_val) {
4506 min_val = y_abs;
4507 min_axis = 1;
4508 }
4509 const Real z_abs = nnm::abs(z);
4510 if (z_abs < min_val) {
4511 min_val = z_abs;
4512 min_axis = 2;
4513 }
4514 if (nnm::abs(w) < min_val) {
4515 min_axis = 3;
4516 }
4517 return min_axis;
4518 }
4519
4525 [[nodiscard]] constexpr bool approx_equal(const Vector4& other) const
4526 {
4527 return nnm::approx_equal(x, other.x) && nnm::approx_equal(y, other.y) && nnm::approx_equal(z, other.z)
4528 && nnm::approx_equal(w, other.w);
4529 }
4530
4535 [[nodiscard]] constexpr bool approx_zero() const
4536 {
4538 }
4539
4544 [[nodiscard]] constexpr Vector2<Real> xy() const
4545 {
4546 return { x, y };
4547 }
4548
4553 [[nodiscard]] constexpr Vector3<Real> xyz() const
4554 {
4555 return { x, y, z };
4556 }
4557
4562 [[nodiscard]] const Real* begin() const
4563 {
4564 return &x;
4565 }
4566
4571 [[nodiscard]] const Real* end() const
4572 {
4573 return &w + 1;
4574 }
4575
4580 Real* begin()
4581 {
4582 return &x;
4583 }
4584
4589 Real* end()
4590 {
4591 return &w + 1;
4592 }
4593
4599 [[nodiscard]] constexpr const Real& at(const uint8_t index) const
4600 {
4601 NNM_BOUNDS_CHECK_ASSERT("Vector4", index <= 3);
4602 switch (index) {
4603 case 0:
4604 return x;
4605 case 1:
4606 return y;
4607 case 2:
4608 return z;
4609 case 3:
4610 return w;
4611 default:
4612 return x;
4613 }
4614 }
4615
4621 constexpr Real& at(const uint8_t index)
4622 {
4623 NNM_BOUNDS_CHECK_ASSERT("Vector4", index <= 3);
4624 switch (index) {
4625 case 0:
4626 return x;
4627 case 1:
4628 return y;
4629 case 2:
4630 return z;
4631 case 3:
4632 return w;
4633 default:
4634 return x;
4635 }
4636 }
4637
4643 [[nodiscard]] constexpr const Real& operator[](const uint8_t index) const
4644 {
4645 NNM_BOUNDS_CHECK_ASSERT("Vector4", index <= 3);
4646 switch (index) {
4647 case 0:
4648 return x;
4649 case 1:
4650 return y;
4651 case 2:
4652 return z;
4653 case 3:
4654 return w;
4655 default:
4656 return x;
4657 }
4658 }
4659
4665 constexpr Real& operator[](const uint8_t index)
4666 {
4667 NNM_BOUNDS_CHECK_ASSERT("Vector4", index <= 3);
4668 switch (index) {
4669 case 0:
4670 return x;
4671 case 1:
4672 return y;
4673 case 2:
4674 return z;
4675 case 3:
4676 return w;
4677 default:
4678 return x;
4679 }
4680 }
4681
4687 [[nodiscard]] constexpr bool operator==(const Vector4& other) const
4688 {
4689 return x == other.x && y == other.y && z == other.z && w == other.w;
4690 }
4691
4697 [[nodiscard]] constexpr bool operator!=(const Vector4& other) const
4698 {
4699 return x != other.x || y != other.y || z != other.z || w != other.w;
4700 }
4701
4707 [[nodiscard]] constexpr Vector4 operator+(const Vector4& other) const
4708 {
4709 return { x + other.x, y + other.y, z + other.z, w + other.w };
4710 }
4711
4717 constexpr Vector4& operator+=(const Vector4& other)
4718 {
4719 x += other.x;
4720 y += other.y;
4721 z += other.z;
4722 w += other.w;
4723 return *this;
4724 }
4725
4731 [[nodiscard]] constexpr Vector4 operator-(const Vector4& other) const
4732 {
4733 return { x - other.x, y - other.y, z - other.z, w - other.w };
4734 }
4735
4741 constexpr Vector4& operator-=(const Vector4& other)
4742 {
4743 x -= other.x;
4744 y -= other.y;
4745 z -= other.z;
4746 w -= other.w;
4747 return *this;
4748 }
4749
4755 [[nodiscard]] constexpr Vector4 operator*(const Vector4& other) const
4756 {
4757 return { x * other.x, y * other.y, z * other.z, w * other.w };
4758 }
4759
4765 constexpr Vector4& operator*=(const Vector4& other)
4766 {
4767 x *= other.x;
4768 y *= other.y;
4769 z *= other.z;
4770 w *= other.w;
4771 return *this;
4772 }
4773
4779 [[nodiscard]] constexpr Vector4 operator*(const Matrix4<Real>& matrix) const;
4780
4786 [[nodiscard]] constexpr Vector4 operator*(const Real value) const
4787 {
4788 return { x * value, y * value, z * value, w * value };
4789 }
4790
4796 constexpr Vector4& operator*=(const Real value)
4797 {
4798 x *= value;
4799 y *= value;
4800 z *= value;
4801 w *= value;
4802 return *this;
4803 }
4804
4810 [[nodiscard]] constexpr Vector4 operator/(const Vector4& other) const
4811 {
4812 return { x / other.x, y / other.y, z / other.z, w / other.w };
4813 }
4814
4820 constexpr Vector4& operator/=(const Vector4& other)
4821 {
4822 x /= other.x;
4823 y /= other.y;
4824 z /= other.z;
4825 w /= other.w;
4826 return *this;
4827 }
4828
4834 [[nodiscard]] constexpr Vector4 operator/(const Real value) const
4835 {
4836 return { x / value, y / value, z / value, w / value };
4837 }
4838
4844 constexpr Vector4& operator/=(const Real value)
4845 {
4846 x /= value;
4847 y /= value;
4848 z /= value;
4849 w /= value;
4850 return *this;
4851 }
4852
4858 [[nodiscard]] constexpr bool operator<(const Vector4& other) const
4859 {
4860 for (uint8_t i = 0; i < 4; ++i) {
4861 if (at(i) < other.at(i)) {
4862 return true;
4863 }
4864 if (at(i) > other.at(i)) {
4865 return false;
4866 }
4867 }
4868 return false;
4869 }
4870
4875 [[nodiscard]] constexpr Vector4 operator+() const
4876 {
4877 return { x, y, z, w };
4878 }
4879
4884 [[nodiscard]] constexpr Vector4 operator-() const
4885 {
4886 return { -x, -y, -z, -w };
4887 }
4888
4892 [[nodiscard]] explicit constexpr operator bool() const
4893 {
4894 return x != static_cast<Real>(0) || y != static_cast<Real>(0) || z != static_cast<Real>(0)
4895 || w != static_cast<Real>(0);
4896 }
4897};
4898
4906template <typename Real>
4907constexpr Vector4<Real> operator*(const Real value, const Vector4<Real>& vector)
4908{
4909 return { value * vector.x, value * vector.y, value * vector.z, value * vector.w };
4910}
4911
4919template <typename Real>
4920constexpr Vector4<Real> operator/(const Real value, const Vector4<Real>& vector)
4921{
4922 return { value / vector.x, value / vector.y, value / vector.z, value / vector.w };
4923}
4924
4929template <typename Real>
4931public:
4932 Real x;
4933 Real y;
4934 Real z;
4935 Real w;
4936
4940 constexpr Quaternion()
4941 : x { static_cast<Real>(0) }
4942 , y { static_cast<Real>(0) }
4943 , z { static_cast<Real>(0) }
4944 , w { static_cast<Real>(1) }
4945 {
4946 }
4947
4953 template <typename Other>
4954 explicit constexpr Quaternion(const Quaternion<Other>& quaternion)
4955 : x { static_cast<Real>(quaternion.x) }
4956 , y { static_cast<Real>(quaternion.y) }
4957 , z { static_cast<Real>(quaternion.z) }
4958 , w { static_cast<Real>(quaternion.w) }
4959 {
4960 }
4961
4966 explicit constexpr Quaternion(const Vector4<Real>& vector)
4967 : x { vector.x }
4968 , y { vector.y }
4969 , z { vector.z }
4970 , w { vector.w }
4971 {
4972 }
4973
4981 constexpr Quaternion(const Real x, const Real y, const Real z, const Real w)
4982 : x { x }
4983 , y { y }
4984 , z { z }
4985 , w { w }
4986 {
4987 }
4988
4993 [[nodiscard]] static constexpr Quaternion identity()
4994 {
4995 return { static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(1) };
4996 }
4997
5004 [[nodiscard]] static Quaternion from_axis_angle(const Vector3<Real>& axis, const Real angle)
5005 {
5006 const Vector3<Real> norm = axis.normalize();
5007 const Real half_sin = sin(angle / static_cast<Real>(2));
5008 Quaternion result;
5009 result.x = norm.x * half_sin;
5010 result.y = norm.y * half_sin;
5011 result.z = norm.z * half_sin;
5012 result.w = cos(angle / static_cast<Real>(2));
5013 return result;
5014 }
5015
5022 [[nodiscard]] static Quaternion from_vector_to_vector(const Vector3<Real>& from, const Vector3<Real>& to)
5023 {
5024 const Vector3<Real> from_norm = from.normalize();
5025 const Vector3<Real> to_norm = to.normalize();
5026 const Vector3<Real> axis = from_norm.cross(to_norm).normalize();
5027 const Real dot = clamp(from_norm.dot(to_norm), static_cast<Real>(-1), static_cast<Real>(1));
5028 const Real angle = acos(dot);
5029 return from_axis_angle(axis, angle);
5030 }
5031
5036 [[nodiscard]] Quaternion normalize() const
5037 {
5038 return Quaternion(Vector4<Real>::from_quaternion(*this).normalize());
5039 }
5040
5046 [[nodiscard]] Vector3<Real> axis_to(const Quaternion& to) const
5047 {
5048 const Quaternion relative = (to * inverse()).normalize();
5049 const Real sin_half_angle = sqrt(static_cast<Real>(1) - sqrd(relative.w));
5050 if (sin_half_angle == static_cast<Real>(0)) {
5051 return Vector3<Real>::axis_x();
5052 }
5053 return Vector4<Real>::from_quaternion(relative).xyz() / sin_half_angle;
5054 }
5055
5061 [[nodiscard]] Real angle_to(const Quaternion& to) const
5062 {
5064 dot = clamp(dot, static_cast<Real>(-1), static_cast<Real>(1));
5065 return static_cast<Real>(2) * acos(dot);
5066 }
5067
5072 [[nodiscard]] Vector3<Real> axis() const
5073 {
5074 const Real sin_half_angle = sqrt(static_cast<Real>(1) - sqrd(w));
5075 if (sin_half_angle == static_cast<Real>(0)) {
5076 return Vector4<Real>::from_quaternion(*this).xyz();
5077 }
5078 return Vector4<Real>::from_quaternion(*this).xyz() / sin_half_angle;
5079 }
5080
5085 [[nodiscard]] Real angle() const
5086 {
5087 return static_cast<Real>(2) * acos(w);
5088 }
5089
5094 [[nodiscard]] constexpr Quaternion inverse() const
5095 {
5096 return { -x, -y, -z, w };
5097 }
5098
5103 [[nodiscard]] constexpr Real length_sqrd() const
5104 {
5105 return sqrd(x) + sqrd(y) + sqrd(z) + sqrd(w);
5106 }
5107
5112 [[nodiscard]] Real length() const
5113 {
5114 return sqrt(length_sqrd());
5115 }
5116
5123 [[nodiscard]] Quaternion slerp(const Quaternion& to, const Real weight) const
5124 {
5125 const Vector4 vector = Vector4<Real>::from_quaternion(*this);
5126 const Vector4 vector_to = Vector4<Real>::from_quaternion(to);
5127 const Real dot = clamp(vector.dot(vector_to), static_cast<Real>(-1), static_cast<Real>(1));
5128 const Real angle = acos(dot);
5129 const Real sin_angle = sin(angle);
5130 if (sin_angle == static_cast<Real>(0)) {
5131 return Quaternion(vector.lerp(vector_to, weight));
5132 }
5133 return Quaternion(
5134 (vector * sin((static_cast<Real>(1) - weight) * angle) + vector_to * sin(weight * angle)) / sin_angle);
5135 }
5136
5143 [[nodiscard]] Quaternion rotate_axis_angle(const Vector3<Real>& axis, const Real angle) const
5144 {
5145 return from_axis_angle(axis, angle) * *this;
5146 }
5147
5153 [[nodiscard]] constexpr Quaternion rotate_quaternion(const Quaternion& by) const
5154 {
5155 return by * *this;
5156 }
5157
5163 [[nodiscard]] constexpr bool approx_equal(const Quaternion& other) const
5164 {
5165 return nnm::approx_equal(x, other.x) && nnm::approx_equal(y, other.y) && nnm::approx_equal(z, other.z)
5166 && nnm::approx_equal(w, other.w);
5167 }
5168
5174 [[nodiscard]] constexpr const Real& at(const uint8_t index) const
5175 {
5176 NNM_BOUNDS_CHECK_ASSERT("Quaternion", index <= 3);
5177 switch (index) {
5178 case 0:
5179 return x;
5180 case 1:
5181 return y;
5182 case 2:
5183 return z;
5184 case 3:
5185 return w;
5186 default:
5187 return x;
5188 }
5189 }
5190
5196 constexpr Real& at(const uint8_t index)
5197 {
5198 NNM_BOUNDS_CHECK_ASSERT("Quaternion", index <= 3);
5199 switch (index) {
5200 case 0:
5201 return x;
5202 case 1:
5203 return y;
5204 case 2:
5205 return z;
5206 case 3:
5207 return w;
5208 default:
5209 return x;
5210 }
5211 }
5212
5218 [[nodiscard]] constexpr const Real& operator[](const uint8_t index) const
5219 {
5220 NNM_BOUNDS_CHECK_ASSERT("Quaternion", index <= 3);
5221 switch (index) {
5222 case 0:
5223 return x;
5224 case 1:
5225 return y;
5226 case 2:
5227 return z;
5228 case 3:
5229 return w;
5230 default:
5231 return x;
5232 }
5233 }
5234
5240 [[nodiscard]] constexpr Real& operator[](const uint8_t index)
5241 {
5242 NNM_BOUNDS_CHECK_ASSERT("Quaternion", index <= 3);
5243 switch (index) {
5244 case 0:
5245 return x;
5246 case 1:
5247 return y;
5248 case 2:
5249 return z;
5250 case 3:
5251 return w;
5252 default:
5253 return x;
5254 }
5255 }
5256
5262 [[nodiscard]] constexpr bool operator==(const Quaternion& other) const
5263 {
5264 return x == other.x && y == other.y && z == other.z && w == other.w;
5265 }
5266
5272 [[nodiscard]] constexpr bool operator!=(const Quaternion& other) const
5273 {
5274 return x != other.x || y != other.y || z != other.z || w != other.w;
5275 }
5276
5282 [[nodiscard]] constexpr Quaternion operator*(const Quaternion& other) const
5283 {
5284 Vector4<Real> vector;
5285 vector.x = w * other.x + x * other.w + y * other.z - z * other.y;
5286 vector.y = w * other.y - x * other.z + y * other.w + z * other.x;
5287 vector.z = w * other.z + x * other.y - y * other.x + z * other.w;
5288 vector.w = w * other.w - x * other.x - y * other.y - z * other.z;
5289 return Quaternion(vector);
5290 }
5291
5297 constexpr Quaternion& operator*=(const Quaternion& other)
5298 {
5299 *this = *this * other;
5300 return *this;
5301 }
5302
5308 [[nodiscard]] constexpr bool operator<(const Quaternion& other) const
5309 {
5311 }
5312
5316 [[nodiscard]] explicit constexpr operator bool() const
5317 {
5318 return x != static_cast<Real>(0) || y != static_cast<Real>(0) || z != static_cast<Real>(0)
5319 || w != static_cast<Real>(0);
5320 }
5321};
5322
5327template <typename Real>
5328class Matrix2 {
5329public:
5331
5335 constexpr Matrix2()
5336 : columns { { static_cast<Real>(1), static_cast<Real>(0) }, { static_cast<Real>(0), static_cast<Real>(1) } }
5337 {
5338 }
5339
5345 template <typename Other>
5346 explicit constexpr Matrix2(const Matrix2<Other>& matrix)
5347 : columns { { static_cast<Real>(matrix.columns[0].x), static_cast<Real>(matrix.columns[0].y) },
5348 { static_cast<Real>(matrix.columns[1].x), static_cast<Real>(matrix.columns[1].y) } }
5349 {
5350 }
5351
5357 constexpr Matrix2(const Vector2<Real>& column0, const Vector2<Real>& column1)
5358 : columns { column0, column1 }
5359 {
5360 }
5361
5369 constexpr Matrix2(const Real col0_row0, const Real col0_row1, const Real col1_row0, const Real col1_row1)
5370 : columns { { col0_row0, col0_row1 }, { col1_row0, col1_row1 } }
5371 {
5372 }
5373
5379 [[nodiscard]] static constexpr Matrix2 all(const Real value)
5380 {
5381 return { { value, value }, { value, value } };
5382 }
5383
5388 [[nodiscard]] static constexpr Matrix2 zero()
5389 {
5390 return all(static_cast<Real>(0));
5391 }
5392
5397 [[nodiscard]] static constexpr Matrix2 one()
5398 {
5399 return all(static_cast<Real>(1));
5400 }
5401
5406 [[nodiscard]] static constexpr Matrix2 identity()
5407 {
5408 return { { static_cast<Real>(1), static_cast<Real>(0) }, { static_cast<Real>(0), static_cast<Real>(1) } };
5409 }
5410
5415 [[nodiscard]] constexpr Real trace() const
5416 {
5417 return at(0, 0) + at(1, 1);
5418 }
5419
5424 [[nodiscard]] constexpr Real determinant() const
5425 {
5426 return at(0, 0) * at(1, 1) - at(1, 0) * at(0, 1);
5427 }
5428
5435 [[nodiscard]] constexpr Real minor_at(const uint8_t column, const uint8_t row) const
5436 {
5437 NNM_BOUNDS_CHECK_ASSERT("Matrix2", column <= 1 && row <= 1);
5438 const uint8_t other_column = (column + 1) % 2;
5439 const uint8_t other_row = (row + 1) % 2;
5440 return at(other_column, other_row);
5441 }
5442
5447 [[nodiscard]] constexpr Matrix2 minor() const
5448 {
5449 Matrix2 result;
5450 for (uint8_t c = 0; c < 2; ++c) {
5451 for (uint8_t r = 0; r < 2; ++r) {
5452 result.at(c, r) = minor_at(c, r);
5453 }
5454 }
5455 return result;
5456 }
5457
5464 [[nodiscard]] constexpr Real cofactor_at(const uint8_t column, const uint8_t row) const
5465 {
5466 NNM_BOUNDS_CHECK_ASSERT("Matrix2", column <= 1 && row <= 1);
5467 return ((column + row) % 2 == 0 ? static_cast<Real>(1) : static_cast<Real>(-1)) * minor_at(column, row);
5468 }
5469
5474 [[nodiscard]] constexpr Matrix2 cofactor() const
5475 {
5476 return { { cofactor_at(0, 0), cofactor_at(0, 1) }, { cofactor_at(1, 0), cofactor_at(1, 1) } };
5477 }
5478
5483 [[nodiscard]] constexpr Matrix2 transpose() const
5484 {
5485 return { { at(0, 0), at(1, 0) }, { at(0, 1), at(1, 1) } };
5486 }
5487
5492 [[nodiscard]] constexpr Matrix2 adjugate() const
5493 {
5494 return cofactor().transpose();
5495 }
5496
5501 [[nodiscard]] constexpr Matrix2 unchecked_inverse() const
5502 {
5503 return adjugate() / determinant();
5504 }
5505
5510 [[nodiscard]] constexpr std::optional<Matrix2> inverse() const
5511 {
5512 const Real det = determinant();
5513 if (det == static_cast<Real>(0)) {
5514 return std::nullopt;
5515 }
5516 return adjugate() / det;
5517 }
5518
5524 [[nodiscard]] constexpr bool approx_equal(const Matrix2& other) const
5525 {
5526 for (uint8_t c = 0; c < 2; ++c) {
5527 for (uint8_t r = 0; r < 2; ++r) {
5528 if (!nnm::approx_equal(at(c, r), other.at(c, r))) {
5529 return false;
5530 }
5531 }
5532 }
5533 return true;
5534 }
5535
5540 [[nodiscard]] constexpr bool approx_zero() const
5541 {
5542 for (uint8_t c = 0; c < 2; ++c) {
5543 for (uint8_t r = 0; r < 2; ++r) {
5544 if (!nnm::approx_zero(at(c, r))) {
5545 return false;
5546 }
5547 }
5548 }
5549 return true;
5550 }
5551
5557 [[nodiscard]] constexpr const Vector2<Real>& at(const uint8_t column) const
5558 {
5559 NNM_BOUNDS_CHECK_ASSERT("Matrix2", column <= 1);
5560 return columns[column];
5561 }
5562
5568 constexpr Vector2<Real>& at(const uint8_t column)
5569 {
5570 NNM_BOUNDS_CHECK_ASSERT("Matrix2", column <= 1);
5571 return columns[column];
5572 }
5573
5580 [[nodiscard]] constexpr const Real& at(const uint8_t column, const uint8_t row) const
5581 {
5582 NNM_BOUNDS_CHECK_ASSERT("Matrix2", column <= 1 && row <= 1);
5583 return columns[column][row];
5584 }
5585
5592 constexpr Real& at(const uint8_t column, const uint8_t row)
5593 {
5594 NNM_BOUNDS_CHECK_ASSERT("Matrix2", column <= 1 && row <= 1);
5595 return columns[column][row];
5596 }
5597
5602 [[nodiscard]] const Real* begin() const
5603 {
5604 return columns[0].begin();
5605 }
5606
5611 [[nodiscard]] const Real* end() const
5612 {
5613 return columns[1].end();
5614 }
5615
5620 Real* begin()
5621 {
5622 return columns[0].begin();
5623 }
5624
5629 Real* end()
5630 {
5631 return columns[1].end();
5632 }
5633
5639 constexpr const Vector2<Real>& operator[](const uint8_t column) const
5640 {
5641 NNM_BOUNDS_CHECK_ASSERT("Matrix2", column <= 1);
5642 return columns[column];
5643 }
5644
5650 constexpr Vector2<Real>& operator[](const uint8_t column)
5651 {
5652 NNM_BOUNDS_CHECK_ASSERT("Matrix2", column <= 1);
5653 return columns[column];
5654 }
5655
5661 constexpr bool operator==(const Matrix2& other) const
5662 {
5663 for (uint8_t i = 0; i < 2; ++i) {
5664 if (at(i) != other.at(i)) {
5665 return false;
5666 }
5667 }
5668 return true;
5669 }
5670
5676 constexpr bool operator!=(const Matrix2& other) const
5677 {
5678 for (uint8_t i = 0; i < 2; ++i) {
5679 if (at(i) != other.at(i)) {
5680 return true;
5681 }
5682 }
5683 return false;
5684 }
5685
5691 [[nodiscard]] constexpr Matrix2 operator+(const Matrix2& other) const
5692 {
5693 Matrix2 result;
5694 for (uint8_t c = 0; c < 2; ++c) {
5695 result.at(c) = at(c) + other.at(c);
5696 }
5697 return result;
5698 }
5699
5705 constexpr Matrix2& operator+=(const Matrix2& other)
5706 {
5707 for (uint8_t c = 0; c < 2; ++c) {
5708 at(c) += other.at(c);
5709 }
5710 return *this;
5711 }
5712
5718 [[nodiscard]] constexpr Matrix2 operator-(const Matrix2& other) const
5719 {
5720 Matrix2 result;
5721 for (uint8_t c = 0; c < 2; ++c) {
5722 result.at(c) = at(c) - other.at(c);
5723 }
5724 return result;
5725 }
5726
5732 constexpr Matrix2& operator-=(const Matrix2& other)
5733 {
5734 for (uint8_t c = 0; c < 2; ++c) {
5735 at(c) -= other.at(c);
5736 }
5737 return *this;
5738 }
5739
5745 [[nodiscard]] constexpr Matrix2 operator*(const Matrix2& other) const
5746 {
5747 auto result = zero();
5748 for (uint8_t c = 0; c < 2; ++c) {
5749 for (uint8_t r = 0; r < 2; ++r) {
5750 for (uint8_t i = 0; i < 2; ++i) {
5751 result.at(c, r) += at(i, r) * other.at(c, i);
5752 }
5753 }
5754 }
5755 return result;
5756 }
5757
5763 constexpr Matrix2& operator*=(const Matrix2& other)
5764 {
5765 *this = *this * other;
5766 return *this;
5767 }
5768
5774 [[nodiscard]] constexpr Vector2<Real> operator*(const Vector2<Real>& vector) const
5775 {
5776 Vector2<Real> result;
5777 for (uint8_t r = 0; r < 2; ++r) {
5778 result.at(r) = at(0, r) * vector.at(0) + at(1, r) * vector.at(1);
5779 }
5780 return result;
5781 }
5782
5788 [[nodiscard]] constexpr Matrix2 operator*(const Real value) const
5789 {
5790 return { at(0) * value, at(1) * value };
5791 }
5792
5798 constexpr Matrix2& operator*=(const Real value)
5799 {
5800 at(0) *= value;
5801 at(1) *= value;
5802 return *this;
5803 }
5804
5810 [[nodiscard]] constexpr Matrix2 operator/(const Real value) const
5811 {
5812 return { at(0) / value, at(1) / value };
5813 }
5814
5820 constexpr Matrix2& operator/=(const Real value)
5821 {
5822 at(0) /= value;
5823 at(1) /= value;
5824 return *this;
5825 }
5826
5832 constexpr bool operator<(const Matrix2& other) const
5833 {
5834 for (uint8_t i = 0; i < 4; ++i) {
5835 if (at(i) < other.at(i)) {
5836 return true;
5837 }
5838 if (at(i) != other.at(i)) {
5839 return false;
5840 }
5841 }
5842 return false;
5843 }
5844
5848 constexpr explicit operator bool() const
5849 {
5850 for (uint8_t c = 0; c < 2; ++c) {
5851 for (uint8_t r = 0; r < 2; ++r) {
5852 if (at(c, r) != 0) {
5853 return true;
5854 }
5855 }
5856 }
5857 return false;
5858 }
5859};
5860
5868template <typename Real>
5869constexpr Matrix2<Real> operator*(const Real value, const Matrix2<Real>& matrix)
5870{
5871 Matrix2<Real> result;
5872 for (uint8_t c = 0; c < 2; ++c) {
5873 for (uint8_t r = 0; r < 2; ++r) {
5874 result.at(c, r) = value * matrix.at(c, r);
5875 }
5876 }
5877 return result;
5878}
5879
5887template <typename Real>
5888constexpr Matrix2<Real> operator/(const Real value, const Matrix2<Real>& matrix)
5889{
5890 Matrix2<Real> result;
5891 for (uint8_t c = 0; c < 2; ++c) {
5892 for (uint8_t r = 0; r < 2; ++r) {
5893 result.at(c, r) = value / matrix.at(c, r);
5894 }
5895 }
5896 return result;
5897}
5898
5903template <typename Real>
5904class Basis2 {
5905public:
5907
5911 constexpr Basis2()
5912 : matrix(Matrix2<Real>::identity())
5913 {
5914 }
5915
5921 template <typename Other>
5922 explicit constexpr Basis2(const Basis2<Other>& basis)
5923 : matrix(Matrix2<Real>(basis.matrix))
5924 {
5925 }
5926
5931 explicit constexpr Basis2(const Matrix2<Real>& matrix)
5932 : matrix(matrix)
5933 {
5934 }
5935
5941 static Basis2 from_rotation(const Real angle)
5942 {
5943 return Basis2({ { cos(angle), sin(angle) }, { -sin(angle), cos(angle) } });
5944 }
5945
5951 static constexpr Basis2 from_scale(const Vector2<Real>& factor)
5952 {
5953 return Basis2({ { factor.x, static_cast<Real>(0) }, { static_cast<Real>(0), factor.y } });
5954 }
5955
5961 static constexpr Basis2 from_shear_x(const Real factor)
5962 {
5963 return Basis2({ { static_cast<Real>(1), static_cast<Real>(0) }, { factor, static_cast<Real>(1) } });
5964 }
5965
5971 static constexpr Basis2 from_shear_y(const Real factor)
5972 {
5973 return Basis2({ { static_cast<Real>(1), factor }, { static_cast<Real>(0), static_cast<Real>(1) } });
5974 }
5975
5980 [[nodiscard]] constexpr Real trace() const
5981 {
5982 return matrix.trace();
5983 }
5984
5989 [[nodiscard]] constexpr Real determinant() const
5990 {
5991 return matrix.determinant();
5992 }
5993
5998 [[nodiscard]] constexpr Basis2 unchecked_inverse() const
5999 {
6000 return Basis2(matrix.unchecked_inverse());
6001 }
6002
6007 [[nodiscard]] constexpr std::optional<Basis2> inverse() const
6008 {
6009 if (valid()) {
6010 return Basis2(matrix.unchecked_inverse());
6011 }
6012 return std::nullopt;
6013 }
6014
6019 [[nodiscard]] constexpr bool valid() const
6020 {
6021 return matrix.determinant() != static_cast<Real>(0);
6022 }
6023
6029 [[nodiscard]] Basis2 rotate(const Real angle) const
6030 {
6031 return transform(from_rotation(angle));
6032 }
6033
6039 [[nodiscard]] Basis2 rotate_local(const Real angle) const
6040 {
6041 return transform_local(from_rotation(angle));
6042 }
6043
6049 [[nodiscard]] constexpr Basis2 scale(const Vector2<Real>& factor) const
6050 {
6051 return transform(from_scale(factor));
6052 }
6053
6059 [[nodiscard]] constexpr Basis2 scale_local(const Vector2<Real>& factor) const
6060 {
6061 return transform_local(from_scale(factor));
6062 }
6063
6069 [[nodiscard]] constexpr Basis2 shear_x(const Real factor) const
6070 {
6071 return transform(from_shear_x(factor));
6072 }
6073
6079 [[nodiscard]] constexpr Basis2 shear_x_local(const Real factor) const
6080 {
6081 return transform_local(from_shear_x(factor));
6082 }
6083
6089 [[nodiscard]] constexpr Basis2 shear_y(const Real factor) const
6090 {
6091 return transform(from_shear_y(factor));
6092 }
6093
6099 [[nodiscard]] constexpr Basis2 shear_y_local(const Real factor) const
6100 {
6101 return transform_local(from_shear_y(factor));
6102 }
6103
6109 [[nodiscard]] constexpr Basis2 transform(const Basis2& by) const
6110 {
6111 return Basis2(by.matrix * matrix);
6112 }
6113
6119 [[nodiscard]] constexpr Basis2 transform_local(const Basis2& by) const
6120 {
6121 return Basis2(matrix * by.matrix);
6122 }
6123
6129 [[nodiscard]] constexpr bool approx_equal(const Basis2& other) const
6130 {
6131 for (uint8_t c = 0; c < 2; ++c) {
6132 if (!at(c).approx_equal(other.at(c))) {
6133 return false;
6134 }
6135 }
6136 return true;
6137 }
6138
6144 [[nodiscard]] constexpr const Vector2<Real>& at(const uint8_t column) const
6145 {
6146 NNM_BOUNDS_CHECK_ASSERT("Basis2", column <= 1);
6147 return matrix[column];
6148 }
6149
6155 constexpr Vector2<Real>& at(const uint8_t column)
6156 {
6157 NNM_BOUNDS_CHECK_ASSERT("Basis2", column <= 1);
6158 return matrix[column];
6159 }
6160
6167 [[nodiscard]] constexpr const Real& at(const uint8_t column, const uint8_t row) const
6168 {
6169 NNM_BOUNDS_CHECK_ASSERT("Basis2", column <= 1 && row <= 1);
6170 return matrix[column][row];
6171 }
6172
6179 constexpr Real& at(const uint8_t column, const uint8_t row)
6180 {
6181 NNM_BOUNDS_CHECK_ASSERT("Basis2", column <= 1 && row <= 1);
6182 return matrix[column][row];
6183 }
6184
6190 constexpr const Vector2<Real>& operator[](const uint8_t index) const
6191 {
6192 NNM_BOUNDS_CHECK_ASSERT("Basis2", index <= 1);
6193 return matrix[index];
6194 }
6195
6201 constexpr Vector2<Real>& operator[](const uint8_t index)
6202 {
6203 NNM_BOUNDS_CHECK_ASSERT("Basis2", index <= 1);
6204 return matrix[index];
6205 }
6206
6212 constexpr bool operator==(const Basis2& other) const
6213 {
6214 return matrix == other.matrix;
6215 }
6216
6222 constexpr bool operator!=(const Basis2& other) const
6223 {
6224 return matrix != other.matrix;
6225 }
6226
6232 constexpr bool operator<(const Basis2& other) const
6233 {
6234 return matrix < other.matrix;
6235 }
6236};
6237
6242template <typename Real>
6243class Matrix3 {
6244public:
6246
6250 constexpr Matrix3()
6251 : columns { { static_cast<Real>(1), static_cast<Real>(0), static_cast<Real>(0) },
6252 { static_cast<Real>(0), static_cast<Real>(1), static_cast<Real>(0) },
6253 { static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(1) } }
6254 {
6255 }
6256
6262 template <typename Other>
6263 explicit constexpr Matrix3(const Matrix3<Other>& matrix)
6264 : columns { { static_cast<Real>(matrix.columns[0].x),
6265 static_cast<Real>(matrix.columns[0].y),
6266 static_cast<Real>(matrix.columns[0].z) },
6267 { static_cast<Real>(matrix.columns[1].x),
6268 static_cast<Real>(matrix.columns[1].y),
6269 static_cast<Real>(matrix.columns[1].z) },
6270 { static_cast<Real>(matrix.columns[2].x),
6271 static_cast<Real>(matrix.columns[2].y),
6272 static_cast<Real>(matrix.columns[2].z) } }
6273 {
6274 }
6275
6282 constexpr Matrix3(const Vector3<Real>& column0, const Vector3<Real>& column1, const Vector3<Real>& column2)
6283 : columns { column0, column1, column2 }
6284 {
6285 }
6286
6299 constexpr Matrix3(
6300 const Real col0_row0,
6301 const Real col0_row1,
6302 const Real col0_row2,
6303 const Real col1_row0,
6304 const Real col1_row1,
6305 const Real col1_row2,
6306 const Real col2_row0,
6307 const Real col2_row1,
6308 const Real col2_row2)
6309 : columns { { col0_row0, col0_row1, col0_row2 },
6310 { col1_row0, col1_row1, col1_row2 },
6311 { col2_row0, col2_row1, col2_row2 } }
6312 {
6313 }
6314
6320 [[nodiscard]] static constexpr Matrix3 all(const Real value)
6321 {
6322 return { { value, value, value }, { value, value, value }, { value, value, value } };
6323 }
6324
6329 [[nodiscard]] static constexpr Matrix3 zero()
6330 {
6331 return all(static_cast<Real>(0));
6332 }
6333
6338 [[nodiscard]] static constexpr Matrix3 one()
6339 {
6340 return all(static_cast<Real>(1));
6341 }
6342
6347 [[nodiscard]] static constexpr Matrix3 identity()
6348 {
6349 return { { static_cast<Real>(1), static_cast<Real>(0), static_cast<Real>(0) },
6350 { static_cast<Real>(0), static_cast<Real>(1), static_cast<Real>(0) },
6351 { static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(1) } };
6352 }
6353
6358 [[nodiscard]] constexpr Real trace() const
6359 {
6360 return at(0, 0) + at(1, 1) + at(2, 2);
6361 }
6362
6367 [[nodiscard]] constexpr Real determinant() const
6368 {
6369 Real det = static_cast<Real>(0);
6370 for (uint8_t c = 0; c < 3; ++c) {
6371 const Real det_minor = minor_at(c, 0);
6372 det += (c % 2 == 0 ? static_cast<Real>(1) : -static_cast<Real>(1)) * at(c, 0) * det_minor;
6373 }
6374 return det;
6375 }
6376
6383 [[nodiscard]] constexpr Matrix2<Real> minor_matrix_at(const uint8_t column, const uint8_t row) const
6384 {
6385 Matrix2<Real> minor_matrix;
6386 uint8_t minor_col = 0;
6387 for (uint8_t c = 0; c < 3; ++c) {
6388 if (c == column) {
6389 continue;
6390 }
6391 uint8_t minor_row = 0;
6392 for (uint8_t r = 0; r < 3; ++r) {
6393 if (r == row) {
6394 continue;
6395 }
6396 minor_matrix[minor_col][minor_row] = at(c, r);
6397 ++minor_row;
6398 }
6399 ++minor_col;
6400 }
6401 return minor_matrix;
6402 }
6403
6410 [[nodiscard]] constexpr Real minor_at(const uint8_t column, const uint8_t row) const
6411 {
6412 NNM_BOUNDS_CHECK_ASSERT("Matrix3", column <= 2 && row <= 2);
6413 return minor_matrix_at(column, row).determinant();
6414 }
6415
6420 [[nodiscard]] constexpr Matrix3 minor() const
6421 {
6422 Matrix3 result;
6423 for (uint8_t c = 0; c < 3; ++c) {
6424 for (uint8_t r = 0; r < 3; ++r) {
6425 result.at(c, r) = minor_at(c, r);
6426 }
6427 }
6428 return result;
6429 }
6430
6437 [[nodiscard]] constexpr Real cofactor_at(const uint8_t column, const uint8_t row) const
6438 {
6439 NNM_BOUNDS_CHECK_ASSERT("Matrix3", column <= 2 && row <= 2);
6440 return ((column + row) % 2 == 0 ? static_cast<Real>(1) : static_cast<Real>(-1)) * minor_at(column, row);
6441 }
6442
6447 [[nodiscard]] constexpr Matrix3 cofactor() const
6448 {
6449 Matrix3 result;
6450 for (uint8_t c = 0; c < 3; ++c) {
6451 for (uint8_t r = 0; r < 3; ++r) {
6452 result.at(c, r) = cofactor_at(c, r);
6453 }
6454 }
6455 return result;
6456 }
6457
6462 [[nodiscard]] constexpr Matrix3 transpose() const
6463 {
6464 return { { at(0, 0), at(1, 0), at(2, 0) }, { at(0, 1), at(1, 1), at(2, 1) }, { at(0, 2), at(1, 2), at(2, 2) } };
6465 }
6466
6471 [[nodiscard]] constexpr Matrix3 adjugate() const
6472 {
6473 return cofactor().transpose();
6474 }
6475
6480 [[nodiscard]] constexpr Matrix3 unchecked_inverse() const
6481 {
6482 return adjugate() / determinant();
6483 }
6484
6489 [[nodiscard]] constexpr std::optional<Matrix3> inverse() const
6490 {
6491 const Real det = determinant();
6492 if (det == static_cast<Real>(0)) {
6493 return std::nullopt;
6494 }
6495 return adjugate() / det;
6496 }
6497
6503 [[nodiscard]] constexpr bool approx_equal(const Matrix3& other) const
6504 {
6505 for (uint8_t c = 0; c < 3; ++c) {
6506 for (uint8_t r = 0; r < 3; ++r) {
6507 if (!nnm::approx_equal(at(c, r), other.at(c, r))) {
6508 return false;
6509 }
6510 }
6511 }
6512 return true;
6513 }
6514
6519 [[nodiscard]] constexpr bool approx_zero() const
6520 {
6521 for (uint8_t c = 0; c < 3; ++c) {
6522 for (uint8_t r = 0; r < 3; ++r) {
6523 if (!nnm::approx_zero(at(c, r))) {
6524 return false;
6525 }
6526 }
6527 }
6528 return true;
6529 }
6530
6536 [[nodiscard]] constexpr const Vector3<Real>& at(const uint8_t column) const
6537 {
6538 NNM_BOUNDS_CHECK_ASSERT("Matrix3", column <= 2);
6539 return columns[column];
6540 }
6541
6547 constexpr Vector3<Real>& at(const uint8_t column)
6548 {
6549 NNM_BOUNDS_CHECK_ASSERT("Matrix3", column <= 2);
6550 return columns[column];
6551 }
6552
6559 [[nodiscard]] constexpr const Real& at(const uint8_t column, const uint8_t row) const
6560 {
6561 NNM_BOUNDS_CHECK_ASSERT("Matrix3", column <= 2 && row <= 2);
6562 return columns[column][row];
6563 }
6564
6571 constexpr Real& at(const uint8_t column, const uint8_t row)
6572 {
6573 NNM_BOUNDS_CHECK_ASSERT("Matrix3", column <= 2 && row <= 2);
6574 return columns[column][row];
6575 }
6576
6581 [[nodiscard]] const Real* begin() const
6582 {
6583 return columns[0].begin();
6584 }
6585
6590 [[nodiscard]] const Real* end() const
6591 {
6592 return columns[2].end();
6593 }
6594
6599 Real* begin()
6600 {
6601 return columns[0].begin();
6602 }
6603
6608 Real* end()
6609 {
6610 return columns[2].end();
6611 }
6612
6618 constexpr const Vector3<Real>& operator[](const uint8_t column) const
6619 {
6620 NNM_BOUNDS_CHECK_ASSERT("Matrix3", column <= 2);
6621 return columns[column];
6622 }
6623
6629 constexpr Vector3<Real>& operator[](const uint8_t column)
6630 {
6631 NNM_BOUNDS_CHECK_ASSERT("Matrix3", column <= 2);
6632 return columns[column];
6633 }
6634
6640 [[nodiscard]] constexpr bool operator==(const Matrix3& other) const
6641 {
6642 for (uint8_t i = 0; i < 3; ++i) {
6643 if (at(i) != other.at(i)) {
6644 return false;
6645 }
6646 }
6647 return true;
6648 }
6649
6655 constexpr bool operator!=(const Matrix3& other) const
6656 {
6657 for (uint8_t i = 0; i < 3; ++i) {
6658 if (at(i) != other.at(i)) {
6659 return true;
6660 }
6661 }
6662 return false;
6663 }
6664
6670 [[nodiscard]] constexpr Matrix3 operator+(const Matrix3& other) const
6671 {
6672 Matrix3 result;
6673 for (uint8_t c = 0; c < 3; ++c) {
6674 result.at(c) = at(c) + other.at(c);
6675 }
6676 return result;
6677 }
6678
6684 constexpr Matrix3& operator+=(const Matrix3& other)
6685 {
6686 for (uint8_t c = 0; c < 3; ++c) {
6687 at(c) += other.at(c);
6688 }
6689 return *this;
6690 }
6691
6697 [[nodiscard]] constexpr Matrix3 operator-(const Matrix3& other) const
6698 {
6699 Matrix3 result;
6700 for (uint8_t c = 0; c < 3; ++c) {
6701 result.at(c) = at(c) - other.at(c);
6702 }
6703 return result;
6704 }
6705
6711 constexpr Matrix3& operator-=(const Matrix3& other)
6712 {
6713 for (uint8_t c = 0; c < 3; ++c) {
6714 at(c) -= other.at(c);
6715 }
6716 return *this;
6717 }
6718
6724 [[nodiscard]] constexpr Matrix3 operator*(const Matrix3& other) const
6725 {
6726 auto result = zero();
6727 for (uint8_t c = 0; c < 3; ++c) {
6728 for (uint8_t r = 0; r < 3; ++r) {
6729 for (uint8_t i = 0; i < 3; ++i) {
6730 result.at(c, r) += at(i, r) * other.at(c, i);
6731 }
6732 }
6733 }
6734 return result;
6735 }
6736
6742 constexpr Matrix3& operator*=(const Matrix3& other)
6743 {
6744 *this = *this * other;
6745 return *this;
6746 }
6747
6753 [[nodiscard]] constexpr Vector3<Real> operator*(const Vector3<Real>& vector) const
6754 {
6755 auto result = Vector3<Real>::zero();
6756 for (uint8_t r = 0; r < 3; ++r) {
6757 for (uint8_t c = 0; c < 3; ++c) {
6758 result.at(r) += at(c, r) * vector.at(c);
6759 }
6760 }
6761 return result;
6762 }
6763
6769 [[nodiscard]] constexpr Matrix3 operator*(const Real value) const
6770 {
6771 return { at(0) * value, at(1) * value, at(2) * value };
6772 }
6773
6779 constexpr Matrix3& operator*=(const Real value)
6780 {
6781 at(0) *= value;
6782 at(1) *= value;
6783 at(2) *= value;
6784 return *this;
6785 }
6786
6792 [[nodiscard]] constexpr Matrix3 operator/(const Real value) const
6793 {
6794 return { at(0) / value, at(1) / value, at(2) / value };
6795 }
6796
6802 constexpr Matrix3& operator/=(const Real value)
6803 {
6804 at(0) /= value;
6805 at(1) /= value;
6806 at(2) /= value;
6807 return *this;
6808 }
6809
6815 [[nodiscard]] constexpr bool operator<(const Matrix3& other) const
6816 {
6817 for (uint8_t i = 0; i < 3; ++i) {
6818 if (at(i) < other.at(i)) {
6819 return true;
6820 }
6821 if (at(i) != other.at(i)) {
6822 return false;
6823 }
6824 }
6825 return false;
6826 }
6827
6831 constexpr explicit operator bool() const
6832 {
6833 for (uint8_t c = 0; c < 3; ++c) { // NOLINT(*-loop-convert)
6834 if (!static_cast<bool>(at(c))) {
6835 return false;
6836 }
6837 }
6838 return true;
6839 }
6840};
6841
6849template <typename Real>
6850constexpr Matrix3<Real> operator*(const Real value, const Matrix3<Real>& matrix)
6851{
6852 Matrix3<Real> result;
6853 for (uint8_t c = 0; c < 3; ++c) {
6854 for (uint8_t r = 0; r < 3; ++r) {
6855 result.at(c, r) = value * matrix.at(c, r);
6856 }
6857 }
6858 return result;
6859}
6860
6868template <typename Real>
6869constexpr Matrix3<Real> operator/(const Real value, const Matrix3<Real>& matrix)
6870{
6871 Matrix3<Real> result;
6872 for (uint8_t c = 0; c < 3; ++c) {
6873 for (uint8_t r = 0; r < 3; ++r) {
6874 result.at(c, r) = value / matrix.at(c, r);
6875 }
6876 }
6877 return result;
6878}
6879
6884template <typename Real>
6886public:
6888
6892 constexpr Transform2()
6893 : matrix(Matrix3<Real>::identity())
6894 {
6895 }
6896
6902 template <typename Other>
6903 explicit constexpr Transform2(const Transform2<Other>& transform)
6904 : matrix(Matrix3<Real>(transform.matrix))
6905 {
6906 }
6907
6912 explicit constexpr Transform2(const Matrix3<Real>& matrix)
6913 : matrix(matrix)
6914 {
6915 }
6916
6924 {
6926 for (uint8_t c = 0; c < 2; ++c) {
6927 for (uint8_t r = 0; r < 2; ++r) {
6928 matrix.at(c, r) = basis.at(c, r);
6929 }
6930 }
6931 matrix.at(2, 0) = translation.x;
6932 matrix.at(2, 1) = translation.y;
6933 return Transform2(matrix);
6934 }
6935
6941 static constexpr Transform2 from_basis(const Basis2<Real>& basis)
6942 {
6944 }
6945
6955
6961 static Transform2 from_rotation(const Real angle)
6962 {
6964 }
6965
6971 static constexpr Transform2 from_scale(const Vector2<Real>& factor)
6972 {
6974 }
6975
6981 static constexpr Transform2 from_shear_x(const Real factor)
6982 {
6984 }
6985
6991 static constexpr Transform2 from_shear_y(const Real factor)
6992 {
6994 }
6995
7000 [[nodiscard]] constexpr Real trace() const
7001 {
7002 return matrix.trace();
7003 }
7004
7009 [[nodiscard]] constexpr Real determinant() const
7010 {
7011 return matrix.determinant();
7012 }
7013
7018 [[nodiscard]] constexpr Transform2 unchecked_inverse() const
7019 {
7020 return Transform2(matrix.unchecked_inverse());
7021 }
7022
7027 [[nodiscard]] constexpr std::optional<Transform2> inverse() const
7028 {
7029 if (valid()) {
7030 return unchecked_inverse();
7031 }
7032 return std::nullopt;
7033 }
7034
7039 [[nodiscard]] constexpr bool valid() const
7040 {
7041 return basis().valid();
7042 }
7043
7048 [[nodiscard]] constexpr bool affine() const
7049 {
7050 return valid() && matrix.at(0, 2) == static_cast<Real>(0) && matrix.at(1, 2) == static_cast<Real>(0)
7051 && matrix.at(2, 2) == static_cast<Real>(1);
7052 }
7053
7058 [[nodiscard]] constexpr Basis2<Real> basis() const
7059 {
7060 return Basis2(matrix.minor_matrix_at(2, 2));
7061 }
7062
7067 [[nodiscard]] constexpr Vector2<Real> translation() const
7068 {
7069 return { matrix.at(2, 0), matrix.at(2, 1) };
7070 }
7071
7077 [[nodiscard]] constexpr Transform2 translate(const Vector2<Real>& offset) const
7078 {
7079 return transform(from_translation(offset));
7080 }
7081
7087 [[nodiscard]] constexpr Transform2 translate_local(const Vector2<Real>& offset) const
7088 {
7089 return transform_local(from_translation(offset));
7090 }
7091
7097 [[nodiscard]] Transform2 rotate(const Real angle) const
7098 {
7099 return transform(from_rotation(angle));
7100 }
7101
7107 [[nodiscard]] Transform2 rotate_local(const Real angle) const
7108 {
7109 return transform_local(from_rotation(angle));
7110 }
7111
7117 [[nodiscard]] constexpr Transform2 scale(const Vector2<Real>& factor) const
7118 {
7119 return transform(from_scale(factor));
7120 }
7121
7127 [[nodiscard]] constexpr Transform2 scale_local(const Vector2<Real>& factor) const
7128 {
7129 return transform_local(from_scale(factor));
7130 }
7131
7137 [[nodiscard]] constexpr Transform2 shear_x(const Real factor) const
7138 {
7139 return transform(from_shear_x(factor));
7140 }
7141
7147 [[nodiscard]] constexpr Transform2 shear_x_local(const Real factor) const
7148 {
7149 return transform_local(from_shear_x(factor));
7150 }
7151
7157 [[nodiscard]] constexpr Transform2 shear_y(const Real factor) const
7158 {
7159 return transform(from_shear_y(factor));
7160 }
7161
7167 [[nodiscard]] constexpr Transform2 shear_y_local(const Real factor) const
7168 {
7169 return transform_local(from_shear_y(factor));
7170 }
7171
7177 [[nodiscard]] constexpr Transform2 transform(const Transform2& by) const
7178 {
7179 return Transform2(by.matrix * matrix);
7180 }
7181
7187 [[nodiscard]] constexpr Transform2 transform_local(const Transform2& by) const
7188 {
7189 return Transform2(matrix * by.matrix);
7190 }
7191
7197 [[nodiscard]] constexpr bool approx_equal(const Transform2& other) const
7198 {
7199 return matrix.approx_equal(other.matrix);
7200 }
7201
7207 [[nodiscard]] constexpr const Vector3<Real>& at(const uint8_t column) const
7208 {
7209 NNM_BOUNDS_CHECK_ASSERT("Transform2", column <= 2);
7210 return matrix[column];
7211 }
7212
7218 constexpr Vector3<Real>& at(const uint8_t column)
7219 {
7220 NNM_BOUNDS_CHECK_ASSERT("Transform2", column <= 2);
7221 return matrix[column];
7222 }
7223
7230 [[nodiscard]] constexpr const Real& at(const uint8_t column, const uint8_t row) const
7231 {
7232 NNM_BOUNDS_CHECK_ASSERT("Transform2", column <= 2 && row <= 2);
7233 return matrix.at(column, row);
7234 }
7235
7242 constexpr Real& at(const uint8_t column, const uint8_t row)
7243 {
7244 NNM_BOUNDS_CHECK_ASSERT("Transform2", column <= 2 && row <= 2);
7245 return matrix.at(column, row);
7246 }
7247
7253 [[nodiscard]] constexpr const Vector3<Real>& operator[](const uint8_t column) const
7254 {
7255 NNM_BOUNDS_CHECK_ASSERT("Transform2", column <= 2);
7256 return matrix[column];
7257 }
7258
7264 constexpr Vector3<Real>& operator[](const uint8_t column)
7265 {
7266 NNM_BOUNDS_CHECK_ASSERT("Transform2", column <= 2);
7267 return matrix[column];
7268 }
7269
7275 [[nodiscard]] constexpr bool operator==(const Transform2& other) const
7276 {
7277 return matrix == other.matrix;
7278 }
7279
7285 [[nodiscard]] constexpr bool operator!=(const Transform2& other) const
7286 {
7287 return matrix != other.matrix;
7288 }
7289
7295 [[nodiscard]] constexpr bool operator<(const Transform2& other) const
7296 {
7297 return matrix < other.matrix;
7298 }
7299};
7300
7305template <typename Real>
7306class Basis3 {
7307public:
7309
7313 constexpr Basis3()
7314 : matrix(Matrix3<Real>::identity())
7315 {
7316 }
7317
7323 template <typename Other>
7324 explicit constexpr Basis3(const Basis3<Other>& basis)
7325 : matrix(Matrix3<Real>(basis.matrix))
7326 {
7327 }
7328
7333 explicit constexpr Basis3(const Matrix3<Real>& matrix)
7334 : matrix(matrix)
7335 {
7336 }
7337
7344 static Basis3 from_rotation_axis_angle(const Vector3<Real>& axis, const Real angle)
7345 {
7346 const Vector3<Real> norm = axis.normalize();
7347 // Rodrigues' formula
7348 const Matrix3<Real> k_matrix { { static_cast<Real>(0), norm.z, -norm.y },
7349 { -norm.z, static_cast<Real>(0), norm.x },
7350 { norm.y, -norm.x, static_cast<Real>(0) } };
7351 const Matrix3<Real> r_matrix = Matrix3<Real>::identity() + sin(angle) * k_matrix
7352 + (static_cast<Real>(1) - cos(angle)) * k_matrix * k_matrix;
7353 return Basis3(r_matrix);
7354 }
7355
7361 static constexpr Basis3 from_rotation_quaternion(const Quaternion<Real>& quaternion)
7362 {
7363 const Quaternion<Real>& q = quaternion;
7365 const Real one = static_cast<Real>(1);
7366 const Real two = static_cast<Real>(2);
7367 matrix.at(0, 0) = one - two * (sqrd(q.y) + sqrd(q.z));
7368 matrix.at(0, 1) = two * (q.x * q.y + q.z * q.w);
7369 matrix.at(0, 2) = two * (q.x * q.z - q.y * q.w);
7370 matrix.at(1, 0) = two * (q.x * q.y - q.z * q.w);
7371 matrix.at(1, 2) = two * (q.y * q.z + q.x * q.w);
7372 matrix.at(2, 0) = two * (q.x * q.z + q.y * q.w);
7373 matrix.at(1, 1) = one - two * (sqrd(q.x) + sqrd(q.z));
7374 matrix.at(2, 1) = two * (q.y * q.z - q.x * q.w);
7375 matrix.at(2, 2) = one - two * (sqrd(q.x) + sqrd(q.y));
7376 return Basis3(matrix);
7377 }
7378
7384 static constexpr Basis3 from_scale(const Vector3<Real>& factor)
7385 {
7386 return Basis3(
7387 { { factor.x, static_cast<Real>(0), static_cast<Real>(0) },
7388 { static_cast<Real>(0), factor.y, static_cast<Real>(0) },
7389 { static_cast<Real>(0), static_cast<Real>(0), factor.z } });
7390 }
7391
7398 static constexpr Basis3 from_shear_x(const Real factor_y, const Real factor_z)
7399 {
7400 return Basis3(
7401 { { static_cast<Real>(1), factor_y, factor_z },
7402 { static_cast<Real>(0), static_cast<Real>(1), static_cast<Real>(0) },
7403 { static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(1) } });
7404 }
7405
7412 static constexpr Basis3 from_shear_y(const Real factor_x, const Real factor_z)
7413 {
7414 return Basis3(
7415 { { static_cast<Real>(1), static_cast<Real>(0), static_cast<Real>(0) },
7416 { factor_x, static_cast<Real>(1), factor_z },
7417 { static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(1) } });
7418 }
7419
7426 static constexpr Basis3 from_shear_z(const Real factor_x, const Real factor_y)
7427 {
7428 return Basis3(
7429 { { static_cast<Real>(1), static_cast<Real>(0), static_cast<Real>(0) },
7430 { static_cast<Real>(0), static_cast<Real>(1), static_cast<Real>(0) },
7431 { factor_x, factor_y, static_cast<Real>(1) } });
7432 }
7433
7438 [[nodiscard]] constexpr Real trace() const
7439 {
7440 return matrix.trace();
7441 }
7442
7447 [[nodiscard]] constexpr Real determinant() const
7448 {
7449 return matrix.determinant();
7450 }
7451
7456 [[nodiscard]] constexpr Basis3 unchecked_inverse() const
7457 {
7458 return Basis3(matrix.unchecked_inverse());
7459 }
7460
7465 [[nodiscard]] constexpr std::optional<Basis3> inverse() const
7466 {
7467 if (valid()) {
7468 return unchecked_inverse();
7469 }
7470 return std::nullopt;
7471 }
7472
7477 [[nodiscard]] constexpr bool valid() const
7478 {
7479 return matrix.determinant() != static_cast<Real>(0);
7480 }
7481
7488 [[nodiscard]] Basis3 rotate_axis_angle(const Vector3<Real>& axis, const Real angle) const
7489 {
7490 return transform(from_rotation_axis_angle(axis, angle));
7491 }
7492
7499 [[nodiscard]] Basis3 rotate_axis_angle_local(const Vector3<Real>& axis, const Real angle) const
7500 {
7501 return transform_local(from_rotation_axis_angle(axis, angle));
7502 }
7503
7509 [[nodiscard]] constexpr Basis3 rotate_quaternion(const Quaternion<Real>& quaternion) const
7510 {
7511 return transform(from_rotation_quaternion(quaternion));
7512 }
7513
7519 [[nodiscard]] constexpr Basis3 rotate_quaternion_local(const Quaternion<Real>& quaternion) const
7520 {
7521 return transform_local(from_rotation_quaternion(quaternion));
7522 }
7523
7529 [[nodiscard]] constexpr Basis3 scale(const Vector3<Real>& factor) const
7530 {
7531 return transform(from_scale(factor));
7532 }
7533
7539 [[nodiscard]] constexpr Basis3 scale_local(const Vector3<Real>& factor) const
7540 {
7541 return transform_local(from_scale(factor));
7542 }
7543
7550 [[nodiscard]] constexpr Basis3 shear_x(const Real factor_y, const Real factor_z) const
7551 {
7552 return transform(from_shear_x(factor_y, factor_z));
7553 }
7554
7561 [[nodiscard]] constexpr Basis3 shear_x_local(const Real factor_y, const Real factor_z) const
7562 {
7563 return transform_local(from_shear_x(factor_y, factor_z));
7564 }
7565
7572 [[nodiscard]] constexpr Basis3 shear_y(const Real factor_x, const Real factor_z) const
7573 {
7574 return transform(from_shear_y(factor_x, factor_z));
7575 }
7576
7583 [[nodiscard]] constexpr Basis3 shear_y_local(const Real factor_x, const Real factor_z) const
7584 {
7585 return transform_local(from_shear_y(factor_x, factor_z));
7586 }
7587
7594 [[nodiscard]] constexpr Basis3 shear_z(const Real factor_x, const Real factor_y) const
7595 {
7596 return transform(from_shear_z(factor_x, factor_y));
7597 }
7598
7605 [[nodiscard]] constexpr Basis3 shear_z_local(const Real factor_x, const Real factor_y) const
7606 {
7607 return transform_local(from_shear_z(factor_x, factor_y));
7608 }
7609
7615 [[nodiscard]] constexpr Basis3 transform(const Basis3& by) const
7616 {
7617 return Basis3(by.matrix * matrix);
7618 }
7619
7625 [[nodiscard]] constexpr Basis3 transform_local(const Basis3& by) const
7626 {
7627 return Basis3(matrix * by.matrix);
7628 }
7629
7635 [[nodiscard]] constexpr bool approx_equal(const Basis3& other) const
7636 {
7637 return matrix.approx_equal(other.matrix);
7638 }
7639
7645 [[nodiscard]] constexpr const Vector3<Real>& at(const uint8_t column) const
7646 {
7647 NNM_BOUNDS_CHECK_ASSERT("Basis3", column <= 3);
7648 return matrix.at(column);
7649 }
7650
7656 constexpr Vector3<Real>& at(const uint8_t column)
7657 {
7658 NNM_BOUNDS_CHECK_ASSERT("Basis3", column <= 3);
7659 return matrix.at(column);
7660 }
7661
7668 [[nodiscard]] constexpr const Real& at(const uint8_t column, const uint8_t row) const
7669 {
7670 NNM_BOUNDS_CHECK_ASSERT("Basis3", column <= 3 && row <= 3);
7671 return matrix.at(column, row);
7672 }
7673
7680 constexpr Real& at(const uint8_t column, const uint8_t row)
7681 {
7682 NNM_BOUNDS_CHECK_ASSERT("Basis3", column <= 3 && row <= 3);
7683 return matrix.at(column, row);
7684 }
7685
7691 [[nodiscard]] constexpr const Vector3<Real>& operator[](const uint8_t index) const
7692 {
7693 NNM_BOUNDS_CHECK_ASSERT("Basis3", index <= 3);
7694 return matrix[index];
7695 }
7696
7702 constexpr Vector3<Real>& operator[](const uint8_t index)
7703 {
7704 NNM_BOUNDS_CHECK_ASSERT("Basis3", index <= 3);
7705 return matrix[index];
7706 }
7707
7713 [[nodiscard]] constexpr bool operator==(const Basis3& other) const
7714 {
7715 return matrix == other.matrix;
7716 }
7717
7723 [[nodiscard]] constexpr bool operator!=(const Basis3& other) const
7724 {
7725 return matrix != other.matrix;
7726 }
7727
7733 [[nodiscard]] constexpr bool operator<(const Basis3& other) const
7734 {
7735 return matrix < other.matrix;
7736 }
7737};
7738
7743template <typename Real>
7744class Matrix4 {
7745public:
7750
7754 constexpr Matrix4()
7755 : columns { { static_cast<Real>(1), static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(0) },
7756 { static_cast<Real>(0), static_cast<Real>(1), static_cast<Real>(0), static_cast<Real>(0) },
7757 { static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(1), static_cast<Real>(0) },
7758 { static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(1) } }
7759
7760 {
7761 }
7762
7768 template <typename Other>
7769 explicit constexpr Matrix4(const Matrix4<Other>& matrix)
7770 : columns { { static_cast<Real>(matrix.columns[0].x),
7771 static_cast<Real>(matrix.columns[0].y),
7772 static_cast<Real>(matrix.columns[0].z),
7773 static_cast<Real>(matrix.columns[0].w) },
7774 { static_cast<Real>(matrix.columns[1].x),
7775 static_cast<Real>(matrix.columns[1].y),
7776 static_cast<Real>(matrix.columns[1].z),
7777 static_cast<Real>(matrix.columns[1].w) },
7778 { static_cast<Real>(matrix.columns[2].x),
7779 static_cast<Real>(matrix.columns[2].y),
7780 static_cast<Real>(matrix.columns[2].z),
7781 static_cast<Real>(matrix.columns[2].w) },
7782 { static_cast<Real>(matrix.columns[3].x),
7783 static_cast<Real>(matrix.columns[3].y),
7784 static_cast<Real>(matrix.columns[3].z),
7785 static_cast<Real>(matrix.columns[3].w) } }
7786 {
7787 }
7788
7796 constexpr Matrix4(
7797 const Vector4<Real>& column0,
7798 const Vector4<Real>& column1,
7799 const Vector4<Real>& column2,
7800 const Vector4<Real>& column3)
7801 : columns { column0, column1, column2, column3 }
7802 {
7803 }
7804
7824 constexpr Matrix4(
7825 const Real col0_row0,
7826 const Real col0_row1,
7827 const Real col0_row2,
7828 const Real col0_row3,
7829 const Real col1_row0,
7830 const Real col1_row1,
7831 const Real col1_row2,
7832 const Real col1_row3,
7833 const Real col2_row0,
7834 const Real col2_row1,
7835 const Real col2_row2,
7836 const Real col2_row3,
7837 const Real col3_row0,
7838 const Real col3_row1,
7839 const Real col3_row2,
7840 const Real col3_row3)
7841 : columns { { col0_row0, col0_row1, col0_row2, col0_row3 },
7842 { col1_row0, col1_row1, col1_row2, col1_row3 },
7843 { col2_row0, col2_row1, col2_row2, col2_row3 },
7844 { col3_row0, col3_row1, col3_row2, col3_row3 } }
7845 {
7846 }
7847
7853 [[nodiscard]] static constexpr Matrix4 all(const Real value)
7854 {
7855 return { { value, value, value, value },
7856 { value, value, value, value },
7857 { value, value, value, value },
7858 { value, value, value, value } };
7859 }
7860
7865 [[nodiscard]] static constexpr Matrix4 zero()
7866 {
7867 return all(static_cast<Real>(0));
7868 }
7869
7874 [[nodiscard]] static constexpr Matrix4 one()
7875 {
7876 return all(static_cast<Real>(1));
7877 }
7878
7883 [[nodiscard]] static constexpr Matrix4 identity()
7884 {
7885 return { { static_cast<Real>(1), static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(0) },
7886 { static_cast<Real>(0), static_cast<Real>(1), static_cast<Real>(0), static_cast<Real>(0) },
7887 { static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(1), static_cast<Real>(0) },
7888 { static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(0), static_cast<Real>(1) } };
7889 }
7890
7895 [[nodiscard]] constexpr Real trace() const
7896 {
7897 return at(0, 0) + at(1, 1) + at(2, 2) + at(3, 3);
7898 }
7899
7904 [[nodiscard]] constexpr Real determinant() const
7905 {
7906 Real det = static_cast<Real>(0);
7907 for (uint8_t c = 0; c < 4; ++c) {
7908 const Real det_minor = minor_at(c, 0);
7909 det += (c % 2 == 0 ? static_cast<Real>(1) : -static_cast<Real>(1)) * at(c, 0) * det_minor;
7910 }
7911 return det;
7912 }
7913
7920 [[nodiscard]] constexpr Matrix3<Real> minor_matrix_at(const uint8_t column, const uint8_t row) const
7921 {
7922 NNM_BOUNDS_CHECK_ASSERT("Matrix4", column <= 3 && row <= 3);
7923 Matrix3<Real> minor_matrix;
7924 uint8_t minor_col = 0;
7925 for (uint8_t c = 0; c < 4; ++c) {
7926 if (c == column) {
7927 continue;
7928 }
7929 uint8_t minor_row = 0;
7930 for (uint8_t r = 0; r < 4; ++r) {
7931 if (r == row) {
7932 continue;
7933 }
7934 minor_matrix[minor_col][minor_row] = at(c, r);
7935 ++minor_row;
7936 }
7937 ++minor_col;
7938 }
7939 return minor_matrix;
7940 }
7941
7948 [[nodiscard]] constexpr Real minor_at(const uint8_t column, const uint8_t row) const
7949 {
7950 NNM_BOUNDS_CHECK_ASSERT("Matrix4", column <= 3 && row <= 3);
7951 return minor_matrix_at(column, row).determinant();
7952 }
7953
7958 [[nodiscard]] constexpr Matrix4 minor() const
7959 {
7960 Matrix4 result;
7961 for (uint8_t c = 0; c < 4; ++c) {
7962 for (uint8_t r = 0; r < 4; ++r) {
7963 result.at(c, r) = minor_at(c, r);
7964 }
7965 }
7966 return result;
7967 }
7968
7975 [[nodiscard]] constexpr Real cofactor_at(const uint8_t column, const uint8_t row) const
7976 {
7977 NNM_BOUNDS_CHECK_ASSERT("Matrix4", column <= 3 && row <= 3);
7978 return ((column + row) % 2 == 0 ? static_cast<Real>(1) : static_cast<Real>(-1)) * minor_at(column, row);
7979 }
7980
7985 [[nodiscard]] constexpr Matrix4 cofactor() const
7986 {
7987 Matrix4 result;
7988 for (uint8_t c = 0; c < 4; ++c) {
7989 for (uint8_t r = 0; r < 4; ++r) {
7990 result.at(c, r) = cofactor_at(c, r);
7991 }
7992 }
7993 return result;
7994 }
7995
8000 [[nodiscard]] constexpr Matrix4 transpose() const
8001 {
8002 return { { at(0, 0), at(1, 0), at(2, 0), at(3, 0) },
8003 { at(0, 1), at(1, 1), at(2, 1), at(3, 1) },
8004 { at(0, 2), at(1, 2), at(2, 2), at(3, 2) },
8005 { at(0, 3), at(1, 3), at(2, 3), at(3, 3) } };
8006 }
8007
8012 [[nodiscard]] constexpr Matrix4 adjugate() const
8013 {
8014 return cofactor().transpose();
8015 }
8016
8021 [[nodiscard]] constexpr Matrix4 unchecked_inverse() const
8022 {
8023 return adjugate() / determinant();
8024 }
8025
8030 [[nodiscard]] constexpr std::optional<Matrix4> inverse() const
8031 {
8032 const Real det = determinant();
8033 if (det == static_cast<Real>(0)) {
8034 return std::nullopt;
8035 }
8036 return adjugate() / det;
8037 }
8038
8044 [[nodiscard]] constexpr bool approx_equal(const Matrix4& other) const
8045 {
8046 for (uint8_t c = 0; c < 4; ++c) {
8047 if (!at(c).approx_equal(other.at(c))) {
8048 return false;
8049 }
8050 }
8051 return true;
8052 }
8053
8058 [[nodiscard]] constexpr bool approx_zero() const
8059 {
8060 for (uint8_t c = 0; c < 4; ++c) {
8061 if (!at(c).approx_zero()) {
8062 return false;
8063 }
8064 }
8065 return true;
8066 }
8067
8073 [[nodiscard]] constexpr const Vector4<Real>& at(const uint8_t column) const
8074 {
8075 NNM_BOUNDS_CHECK_ASSERT("Matrix4", column <= 3);
8076 return columns[column];
8077 }
8078
8084 constexpr Vector4<Real>& at(const uint8_t column)
8085 {
8086 NNM_BOUNDS_CHECK_ASSERT("Matrix4", column <= 3);
8087 return columns[column];
8088 }
8089
8096 [[nodiscard]] constexpr const Real& at(const uint8_t column, const uint8_t row) const
8097 {
8098 NNM_BOUNDS_CHECK_ASSERT("Matrix4", column <= 3 && row <= 3);
8099 return columns[column][row];
8100 }
8101
8108 constexpr Real& at(const uint8_t column, const uint8_t row)
8109 {
8110 NNM_BOUNDS_CHECK_ASSERT("Matrix4", column <= 3 && row <= 3);
8111 return columns[column][row];
8112 }
8113
8118 [[nodiscard]] const Real* begin() const
8119 {
8120 return columns[0].begin();
8121 }
8122
8127 [[nodiscard]] const Real* end() const
8128 {
8129 return columns[3].end();
8130 }
8131
8136 Real* begin()
8137 {
8138 return columns[0].begin();
8139 }
8140
8145 Real* end()
8146 {
8147 return columns[3].end();
8148 }
8149
8155 constexpr const Vector4<Real>& operator[](const uint8_t index) const
8156 {
8157 NNM_BOUNDS_CHECK_ASSERT("Matrix4", index <= 3);
8158 return columns[index];
8159 }
8160
8166 constexpr Vector4<Real>& operator[](const uint8_t index)
8167 {
8168 NNM_BOUNDS_CHECK_ASSERT("Matrix4", index <= 3);
8169 return columns[index];
8170 }
8171
8177 [[nodiscard]] constexpr bool operator==(const Matrix4& other) const
8178 {
8179 for (uint8_t i = 0; i < 4; ++i) {
8180 if (at(i) != other.at(i)) {
8181 return false;
8182 }
8183 }
8184 return true;
8185 }
8186
8192 constexpr bool operator!=(const Matrix4& other) const
8193 {
8194 for (uint8_t i = 0; i < 4; ++i) {
8195 if (at(i) != other.at(i)) {
8196 return true;
8197 }
8198 }
8199 return false;
8200 }
8201
8207 [[nodiscard]] constexpr Matrix4 operator+(const Matrix4& other) const
8208 {
8209 Matrix4 result;
8210 for (uint8_t c = 0; c < 4; ++c) {
8211 result.at(c) = at(c) + other.at(c);
8212 }
8213 return result;
8214 }
8215
8221 constexpr Matrix4& operator+=(const Matrix4& other)
8222 {
8223 for (uint8_t c = 0; c < 4; ++c) {
8224 at(c) += other.at(c);
8225 }
8226 return *this;
8227 }
8228
8234 [[nodiscard]] constexpr Matrix4 operator-(const Matrix4& other) const
8235 {
8236 Matrix4 result;
8237 for (uint8_t c = 0; c < 4; ++c) {
8238 result.at(c) = at(c) - other.at(c);
8239 }
8240 return result;
8241 }
8242
8248 constexpr Matrix4& operator-=(const Matrix4& other)
8249 {
8250 for (uint8_t c = 0; c < 4; ++c) {
8251 at(c) -= other.at(c);
8252 }
8253 return *this;
8254 }
8255
8261 constexpr Matrix4 operator*(const Matrix4& other) const
8262 {
8263 auto result = zero();
8264 for (uint8_t c = 0; c < 4; ++c) {
8265 for (uint8_t r = 0; r < 4; ++r) {
8266 for (uint8_t i = 0; i < 4; ++i) {
8267 result.at(c, r) += at(i, r) * other.at(c, i);
8268 }
8269 }
8270 }
8271 return result;
8272 }
8273
8279 constexpr Matrix4& operator*=(const Matrix4& other)
8280 {
8281 *this = *this * other;
8282 return *this;
8283 }
8284
8290 constexpr Vector4<Real> operator*(const Vector4<Real>& vector) const
8291 {
8292 auto result = Vector4<Real>::zero();
8293 for (uint8_t r = 0; r < 4; ++r) {
8294 for (uint8_t c = 0; c < 4; ++c) {
8295 result.at(r) += at(c, r) * vector.at(c);
8296 }
8297 }
8298 return result;
8299 }
8300
8306 [[nodiscard]] constexpr Matrix4 operator*(const Real value) const
8307 {
8308 Matrix4 result;
8309 for (uint8_t c = 0; c < 4; ++c) {
8310 result.at(c) = at(c) * value;
8311 }
8312 return result;
8313 }
8314
8320 constexpr Matrix4& operator*=(const Real value)
8321 {
8322 for (uint8_t c = 0; c < 4; ++c) {
8323 at(c) *= value;
8324 }
8325 return *this;
8326 }
8327
8333 [[nodiscard]] constexpr Matrix4 operator/(const Real value) const
8334 {
8335 Matrix4 result;
8336 for (uint8_t c = 0; c < 4; ++c) {
8337 result.at(c) = at(c) / value;
8338 }
8339 return result;
8340 }
8341
8347 constexpr Matrix4& operator/=(const Real value)
8348 {
8349 for (uint8_t c = 0; c < 4; ++c) {
8350 at(c) /= value;
8351 }
8352 return *this;
8353 }
8354
8360 constexpr bool operator<(const Matrix4& other) const
8361 {
8362 for (uint8_t i = 0; i < 4; ++i) {
8363 if (at(i) < other.at(i)) {
8364 return true;
8365 }
8366 if (at(i) != other.at(i)) {
8367 return false;
8368 }
8369 }
8370 return false;
8371 }
8372
8376 constexpr explicit operator bool() const
8377 {
8378 for (uint8_t c = 0; c < 4; ++c) {
8379 if (!static_cast<bool>(at(c))) {
8380 return false;
8381 }
8382 }
8383 return true;
8384 }
8385};
8386
8394template <typename Real>
8395constexpr Matrix4<Real> operator*(const Real value, const Matrix4<Real>& matrix)
8396{
8397 Matrix4<Real> result;
8398 for (uint8_t c = 0; c < 4; ++c) {
8399 for (uint8_t r = 0; r < 4; ++r) {
8400 result.at(c, r) = value * matrix.at(c, r);
8401 }
8402 }
8403 return result;
8404}
8405
8413template <typename Real>
8414constexpr Matrix4<Real> operator/(const Real value, const Matrix4<Real>& matrix)
8415{
8416 Matrix4<Real> result;
8417 for (uint8_t c = 0; c < 4; ++c) {
8418 for (uint8_t r = 0; r < 4; ++r) {
8419 result.at(c, r) = value / matrix.at(c, r);
8420 }
8421 }
8422 return result;
8423}
8424
8429template <typename Real>
8431public:
8436
8440 constexpr Transform3()
8441 : matrix(Matrix4<Real>::identity())
8442 {
8443 }
8444
8450 template <typename Other>
8451 explicit constexpr Transform3(const Transform3<Other>& transform)
8452 : matrix(Matrix4<Real>(transform.matrix))
8453 {
8454 }
8455
8460 explicit constexpr Transform3(const Matrix4<Real>& matrix)
8461 : matrix(matrix)
8462 {
8463 }
8464
8472 {
8474 for (uint8_t c = 0; c < 3; ++c) {
8475 for (uint8_t r = 0; r < 3; ++r) {
8476 matrix.at(c, r) = basis.at(c, r);
8477 }
8478 }
8479 matrix.at(3, 0) = translation.x;
8480 matrix.at(3, 1) = translation.y;
8481 matrix.at(3, 2) = translation.z;
8482 return Transform3(matrix);
8483 }
8484
8490 static constexpr Transform3 from_basis(const Basis3<Real>& basis)
8491 {
8493 }
8494
8504
8511 static Transform3 from_rotation_axis_angle(const Vector3<Real>& axis, const Real angle)
8512 {
8513 const auto basis = Basis3<Real>::from_rotation_axis_angle(axis, angle);
8515 }
8516
8522 static constexpr Transform3 from_rotation_quaternion(const Quaternion<Real>& quaternion)
8523 {
8524 const auto basis = Basis3<Real>::from_rotation_quaternion(quaternion);
8526 }
8527
8533 static constexpr Transform3 from_scale(const Vector3<Real>& factor)
8534 {
8535 return from_basis(Basis3<Real>::from_scale(factor));
8536 }
8537
8544 static constexpr Transform3 from_shear_x(const Real factor_y, const Real factor_z)
8545 {
8546 return from_basis(Basis3<Real>::from_shear_x(factor_y, factor_z));
8547 }
8548
8555 static constexpr Transform3 from_shear_y(const Real factor_x, const Real factor_z)
8556 {
8557 return from_basis(Basis3<Real>::from_shear_y(factor_x, factor_z));
8558 }
8559
8566 static constexpr Transform3 from_shear_z(const Real factor_x, const Real factor_y)
8567 {
8568 return from_basis(Basis3<Real>::from_shear_z(factor_x, factor_y));
8569 }
8570
8580 const Real fov, const Real aspect_ratio, const Real near_clip, const Real far_clip)
8581 {
8582 auto matrix = Matrix4<Real>::zero();
8583 const Real tan_half_fov = tan(fov / static_cast<Real>(2));
8584 matrix.at(0, 0) = static_cast<Real>(1) / (aspect_ratio * tan_half_fov);
8585 matrix.at(1, 1) = static_cast<Real>(1) / tan_half_fov;
8586 matrix.at(2, 2) = -(far_clip + near_clip) / (far_clip - near_clip);
8587 matrix.at(2, 3) = -static_cast<Real>(1);
8588 matrix.at(3, 2) = -(static_cast<Real>(2) * far_clip * near_clip) / (far_clip - near_clip);
8589 return Transform3(matrix);
8590 }
8591
8601 const Real fov, const Real aspect_ratio, const Real near_clip, const Real far_clip)
8602 {
8603 auto matrix = Matrix4<Real>::zero();
8604 const Real tan_half_fov = tan(fov / static_cast<Real>(2));
8605 matrix.at(0, 0) = static_cast<Real>(1) / (aspect_ratio * tan_half_fov);
8606 matrix.at(1, 1) = static_cast<Real>(1) / tan_half_fov;
8607 matrix.at(2, 2) = -far_clip / (far_clip - near_clip);
8608 matrix.at(2, 3) = -static_cast<Real>(1);
8609 matrix.at(3, 2) = -(far_clip * near_clip) / (far_clip - near_clip);
8610 return Transform3(matrix);
8611 }
8612
8622 const Real fov, const Real aspect_ratio, const Real near_clip, const Real far_clip)
8623 {
8624 auto matrix = Matrix4<Real>::zero();
8625 const Real tan_half_fov = tan(fov / static_cast<Real>(2));
8626 matrix.at(0, 0) = static_cast<Real>(1) / (aspect_ratio * tan_half_fov);
8627 matrix.at(1, 1) = static_cast<Real>(1) / tan_half_fov;
8628 matrix.at(2, 2) = (far_clip + near_clip) / (far_clip - near_clip);
8629 matrix.at(2, 3) = static_cast<Real>(1);
8630 matrix.at(3, 2) = -(static_cast<Real>(2) * far_clip * near_clip) / (far_clip - near_clip);
8631 return Transform3(matrix);
8632 }
8633
8643 const Real fov, const Real aspect_ratio, const Real near_clip, const Real far_clip)
8644 {
8645 auto matrix = Matrix4<Real>::zero();
8646 const Real tan_half_fov = tan(fov / static_cast<Real>(2));
8647 matrix.at(0, 0) = static_cast<Real>(1) / (aspect_ratio * tan_half_fov);
8648 matrix.at(1, 1) = static_cast<Real>(1) / tan_half_fov;
8649 matrix.at(2, 2) = far_clip / (far_clip - near_clip);
8650 matrix.at(2, 3) = static_cast<Real>(1);
8651 matrix.at(3, 2) = -(far_clip * near_clip) / (far_clip - near_clip);
8652 return Transform3(matrix);
8653 }
8654
8666 const Real left, const Real right, const Real bottom, const Real top, const Real near_clip, const Real far_clip)
8667 {
8669 matrix.at(0, 0) = static_cast<Real>(2) / (right - left);
8670 matrix.at(1, 1) = static_cast<Real>(2) / (top - bottom);
8671 matrix.at(2, 2) = -static_cast<Real>(2) / (far_clip - near_clip);
8672 matrix.at(3, 0) = -(right + left) / (right - left);
8673 matrix.at(3, 1) = -(top + bottom) / (top - bottom);
8674 matrix.at(3, 2) = -(far_clip + near_clip) / (far_clip - near_clip);
8675 return Transform3(matrix);
8676 }
8677
8689 const Real left, const Real right, const Real bottom, const Real top, const Real near_clip, const Real far_clip)
8690 {
8692 matrix.at(0, 0) = static_cast<Real>(2) / (right - left);
8693 matrix.at(1, 1) = static_cast<Real>(2) / (top - bottom);
8694 matrix.at(2, 2) = -static_cast<Real>(1) / (far_clip - near_clip);
8695 matrix.at(3, 0) = -(right + left) / (right - left);
8696 matrix.at(3, 1) = -(top + bottom) / (top - bottom);
8697 matrix.at(3, 2) = -near_clip / (far_clip - near_clip);
8698 return Transform3(matrix);
8699 }
8700
8712 const Real left, const Real right, const Real bottom, const Real top, const Real near_clip, const Real far_clip)
8713 {
8715 matrix.at(0, 0) = static_cast<Real>(2) / (right - left);
8716 matrix.at(1, 1) = static_cast<Real>(2) / (top - bottom);
8717 matrix.at(2, 2) = static_cast<Real>(2) / (far_clip - near_clip);
8718 matrix.at(3, 0) = -(right + left) / (right - left);
8719 matrix.at(3, 1) = -(top + bottom) / (top - bottom);
8720 matrix.at(3, 2) = -(far_clip + near_clip) / (far_clip - near_clip);
8721 return Transform3(matrix);
8722 }
8723
8735 const Real left, const Real right, const Real bottom, const Real top, const Real near_clip, const Real far_clip)
8736 {
8738 matrix.at(0, 0) = static_cast<Real>(2) / (right - left);
8739 matrix.at(1, 1) = static_cast<Real>(2) / (top - bottom);
8740 matrix.at(2, 2) = static_cast<Real>(1) / (far_clip - near_clip);
8741 matrix.at(3, 0) = -(right + left) / (right - left);
8742 matrix.at(3, 1) = -(top + bottom) / (top - bottom);
8743 matrix.at(3, 2) = -near_clip / (far_clip - near_clip);
8744 return Transform3(matrix);
8745 }
8746
8751 [[nodiscard]] constexpr Real trace() const
8752 {
8753 return matrix.trace();
8754 }
8755
8760 [[nodiscard]] constexpr Real determinant() const
8761 {
8762 return matrix.determinant();
8763 }
8764
8769 [[nodiscard]] constexpr Transform3 unchecked_inverse() const
8770 {
8771 return Transform3(matrix.unchecked_inverse());
8772 }
8773
8778 [[nodiscard]] constexpr std::optional<Transform3> inverse() const
8779 {
8780 if (valid()) {
8781 return unchecked_inverse();
8782 }
8783 return std::nullopt;
8784 }
8785
8790 [[nodiscard]] constexpr bool valid() const
8791 {
8792 return basis().valid();
8793 }
8794
8799 [[nodiscard]] constexpr bool affine() const
8800 {
8801 return valid() && matrix.at(0, 3) == static_cast<Real>(0) && matrix.at(1, 3) == static_cast<Real>(0)
8802 && matrix.at(2, 3) == static_cast<Real>(0) && matrix.at(3, 3) == static_cast<Real>(1);
8803 }
8804
8809 [[nodiscard]] constexpr Basis3<Real> basis() const
8810 {
8811 return Basis3(matrix.minor_matrix_at(3, 3));
8812 }
8813
8818 [[nodiscard]] constexpr Vector3<Real> translation() const
8819 {
8820 return { matrix.at(3, 0), matrix.at(3, 1), matrix.at(3, 2) };
8821 }
8822
8828 [[nodiscard]] constexpr Transform3 translate(const Vector3<Real>& offset) const
8829 {
8830 return transform(from_translation(offset));
8831 }
8832
8838 [[nodiscard]] constexpr Transform3 translate_local(const Vector3<Real>& offset) const
8839 {
8840 return transform_local(from_translation(offset));
8841 }
8842
8849 [[nodiscard]] Transform3 rotate_axis_angle(const Vector3<Real>& axis, const Real angle) const
8850 {
8851 return transform(from_rotation_axis_angle(axis, angle));
8852 }
8853
8860 [[nodiscard]] Transform3 rotate_axis_angle_local(const Vector3<Real>& axis, const Real angle) const
8861 {
8862 return transform_local(from_rotation_axis_angle(axis, angle));
8863 }
8864
8870 [[nodiscard]] constexpr Transform3 rotate_quaternion(const Quaternion<Real>& quaternion) const
8871 {
8872 return transform(from_rotation_quaternion(quaternion));
8873 }
8874
8880 [[nodiscard]] constexpr Transform3 rotate_quaternion_local(const Quaternion<Real>& quaternion) const
8881 {
8882 return transform_local(from_rotation_quaternion(quaternion));
8883 }
8884
8890 [[nodiscard]] constexpr Transform3 scale(const Vector3<Real>& factor) const
8891 {
8892 return transform(from_scale(factor));
8893 }
8894
8900 [[nodiscard]] constexpr Transform3 scale_local(const Vector3<Real>& factor) const
8901 {
8902 return transform_local(from_scale(factor));
8903 }
8904
8911 [[nodiscard]] constexpr Transform3 shear_x(const Real factor_y, const Real factor_z) const
8912 {
8913 return transform(from_shear_x(factor_y, factor_z));
8914 }
8915
8922 [[nodiscard]] constexpr Transform3 shear_x_local(const Real factor_y, const Real factor_z) const
8923 {
8924 return transform_local(from_shear_x(factor_y, factor_z));
8925 }
8926
8933 [[nodiscard]] constexpr Transform3 shear_y(const Real factor_x, const Real factor_z) const
8934 {
8935 return transform(from_shear_y(factor_x, factor_z));
8936 }
8937
8944 [[nodiscard]] constexpr Transform3 shear_y_local(const Real factor_x, const Real factor_z) const
8945 {
8946 return transform_local(from_shear_y(factor_x, factor_z));
8947 }
8948
8955 [[nodiscard]] constexpr Transform3 shear_z(const Real factor_x, const Real factor_y) const
8956 {
8957 return transform(from_shear_z(factor_x, factor_y));
8958 }
8959
8966 [[nodiscard]] constexpr Transform3 shear_z_local(const Real factor_x, const Real factor_y) const
8967 {
8968 return transform_local(from_shear_z(factor_x, factor_y));
8969 }
8970
8976 [[nodiscard]] constexpr Transform3 transform(const Transform3& by) const
8977 {
8978 return Transform3(by.matrix * matrix);
8979 }
8980
8986 [[nodiscard]] constexpr Transform3 transform_local(const Transform3& by) const
8987 {
8988 return Transform3(matrix * by.matrix);
8989 }
8990
8996 [[nodiscard]] constexpr bool approx_equal(const Transform3& other) const
8997 {
8998 return matrix.approx_equal(other.matrix);
8999 }
9000
9006 [[nodiscard]] constexpr const Vector4<Real>& at(const uint8_t column) const
9007 {
9008 NNM_BOUNDS_CHECK_ASSERT("Transform3", column <= 3);
9009 return matrix.at(column);
9010 }
9011
9017 constexpr Vector4<Real>& at(const uint8_t column)
9018 {
9019 NNM_BOUNDS_CHECK_ASSERT("Transform3", column <= 3);
9020 return matrix.at(column);
9021 }
9022
9029 [[nodiscard]] constexpr const Real& at(const uint8_t column, const uint8_t row) const
9030 {
9031 NNM_BOUNDS_CHECK_ASSERT("Transform3", column <= 3 && row <= 3);
9032 return matrix.at(column, row);
9033 }
9034
9041 constexpr Real& at(const uint8_t column, const uint8_t row)
9042 {
9043 NNM_BOUNDS_CHECK_ASSERT("Transform3", column <= 3 && row <= 3);
9044 return matrix.at(column, row);
9045 }
9046
9052 [[nodiscard]] constexpr const Vector4<Real>& operator[](const uint8_t column) const
9053 {
9054 NNM_BOUNDS_CHECK_ASSERT("Transform3", column <= 3);
9055 return matrix[column];
9056 }
9057
9063 constexpr Vector4<Real>& operator[](const uint8_t column)
9064 {
9065 NNM_BOUNDS_CHECK_ASSERT("Transform3", column <= 3);
9066 return matrix[column];
9067 }
9068
9074 [[nodiscard]] constexpr bool operator==(const Transform3& other) const
9075 {
9076 return matrix == other.matrix;
9077 }
9078
9084 [[nodiscard]] constexpr bool operator!=(const Transform3& other) const
9085 {
9086 return matrix != other.matrix;
9087 }
9088
9094 [[nodiscard]] constexpr bool operator<(const Transform3& other) const
9095 {
9096 return matrix < other.matrix;
9097 }
9098};
9099
9100template <typename Real>
9101template <typename Int>
9103 : x { static_cast<Real>(vector.x) }
9104 , y { static_cast<Real>(vector.y) }
9105{
9106}
9107
9108template <typename Real>
9109constexpr Matrix2<Real> Vector2<Real>::outer(const Vector2& other) const
9110{
9111 Matrix2<Real> result;
9112 for (uint8_t c = 0; c < 2; ++c) {
9113 for (uint8_t r = 0; r < 2; ++r) {
9114 result.at(c, r) = at(c) * other.at(r);
9115 }
9116 }
9117 return result;
9118}
9119
9120template <typename Real>
9122{
9124}
9125
9126template <typename Real>
9128{
9130}
9131
9132template <typename Real>
9133Vector2<Real> Vector2<Real>::rotate_at(const Vector2& origin, Real angle) const
9134{
9135 return transform_at(origin, Basis2<Real>::from_rotation(angle));
9136}
9137
9138template <typename Real>
9139constexpr Vector2<Real> Vector2<Real>::scale(const Vector2& factor) const
9140{
9141 return transform(Basis2<Real>::from_scale(factor));
9142}
9143
9144template <typename Real>
9145constexpr Vector2<Real> Vector2<Real>::scale_at(const Vector2& origin, const Vector2& factor) const
9146{
9147 return transform_at(origin, Basis2<Real>::from_scale(factor));
9148}
9149
9150template <typename Real>
9151constexpr Vector2<Real> Vector2<Real>::shear_x(const Real factor) const
9152{
9153 return transform(Basis2<Real>::from_shear_x(factor));
9154}
9155
9156template <typename Real>
9157constexpr Vector2<Real> Vector2<Real>::shear_x_at(const Vector2& origin, Real factor) const
9158{
9159 return transform_at(origin, Basis2<Real>::from_shear_x(factor));
9160}
9161
9162template <typename Real>
9163constexpr Vector2<Real> Vector2<Real>::shear_y(const Real factor) const
9164{
9165 return transform(Basis2<Real>::from_shear_y(factor));
9166}
9167
9168template <typename Real>
9169constexpr Vector2<Real> Vector2<Real>::shear_y_at(const Vector2& origin, Real factor) const
9170{
9171 return transform_at(origin, Basis2<Real>::from_shear_y(factor));
9172}
9173
9174template <typename Real>
9176{
9177 return by.matrix * *this;
9178}
9179
9180template <typename Real>
9181constexpr Vector2<Real> Vector2<Real>::transform_at(const Vector2& origin, const Basis2<Real>& by) const
9182{
9183 return (*this - origin).transform(by) + origin;
9184}
9185
9186template <typename Real>
9187constexpr Vector2<Real> Vector2<Real>::transform(const Transform2<Real>& by, const Real z) const
9188{
9189 return Vector3<Real>(*this, z).transform(by).xy();
9190}
9191
9192template <typename Real>
9193constexpr Vector2<Real> Vector2<Real>::transform_at(const Vector2& origin, const Transform2<Real>& by, Real z) const
9194{
9195 return (*this - origin).transform(by, z) + origin;
9196}
9197
9198template <typename Real>
9200{
9201 Vector2 result;
9202 result.x = x * matrix.at(0, 0) + y * matrix.at(0, 1);
9203 result.y = x * matrix.at(1, 0) + y * matrix.at(1, 1);
9204 return result;
9205}
9206
9207template <typename Real>
9208template <typename Int>
9210 : x { static_cast<Real>(vector.x) }
9211 , y { static_cast<Real>(vector.y) }
9212 , z { static_cast<Real>(vector.z) }
9213{
9214}
9215
9216template <typename Real>
9217constexpr Matrix3<Real> Vector3<Real>::outer(const Vector3& other) const
9218{
9219 Matrix3<Real> result;
9220 for (uint8_t c = 0; c < 3; ++c) {
9221 for (uint8_t r = 0; r < 3; ++r) {
9222 result.at(c, r) = at(c) * other.at(r);
9223 }
9224 }
9225 return result;
9226}
9227
9228template <typename Real>
9230{
9232}
9233
9234template <typename Real>
9239
9240template <typename Real>
9242{
9244}
9245
9246template <typename Real>
9248{
9250}
9251
9252template <typename Real>
9254 const Vector3& origin, const Quaternion<Real>& quaternion) const
9255{
9256 return transform_at(origin, Basis3<Real>::from_rotation_quaternion(quaternion));
9257}
9258
9259template <typename Real>
9260constexpr Vector3<Real> Vector3<Real>::scale(const Vector3& factor) const
9261{
9262 return transform(Basis3<Real>::from_scale(factor));
9263}
9264
9265template <typename Real>
9266constexpr Vector3<Real> Vector3<Real>::scale_at(const Vector3& origin, const Vector3& factor) const
9267{
9268 return transform_at(origin, Basis3<Real>::from_scale(factor));
9269}
9270
9271template <typename Real>
9272constexpr Vector3<Real> Vector3<Real>::shear_x(const Real factor_y, const Real factor_z) const
9273{
9274 return transform(Basis3<Real>::from_shear_x(factor_y, factor_z));
9275}
9276
9277template <typename Real>
9278constexpr Vector3<Real> Vector3<Real>::shear_x_at(const Vector3& origin, Real factor_y, Real factor_z) const
9279{
9280 return transform_at(origin, Basis3<Real>::from_shear_x(factor_y, factor_z));
9281}
9282
9283template <typename Real>
9284constexpr Vector3<Real> Vector3<Real>::shear_y(const Real factor_x, const Real factor_z) const
9285{
9286 return transform(Basis3<Real>::from_shear_y(factor_x, factor_z));
9287}
9288
9289template <typename Real>
9290constexpr Vector3<Real> Vector3<Real>::shear_y_at(const Vector3& origin, Real factor_x, Real factor_z) const
9291{
9292 return transform_at(origin, Basis3<Real>::from_shear_y(factor_x, factor_z));
9293}
9294
9295template <typename Real>
9296constexpr Vector3<Real> Vector3<Real>::shear_z(const Real factor_x, const Real factor_y) const
9297{
9298 return transform(Basis3<Real>::from_shear_z(factor_x, factor_y));
9299}
9300
9301template <typename Real>
9302constexpr Vector3<Real> Vector3<Real>::shear_z_at(const Vector3& origin, Real factor_x, Real factor_y) const
9303{
9304 return transform_at(origin, Basis3<Real>::from_shear_z(factor_x, factor_y));
9305}
9306
9307template <typename Real>
9309{
9310 return by.matrix * *this;
9311}
9312
9313template <typename Real>
9314constexpr Vector3<Real> Vector3<Real>::transform_at(const Vector3& origin, const Basis3<Real>& by) const
9315{
9316 return (*this - origin).transform(by) + origin;
9317}
9318
9319template <typename Real>
9321{
9322 return by.matrix * *this;
9323}
9324
9325template <typename Real>
9327{
9328 return (*this - Vector3 { origin, static_cast<Real>(0) }).transform(by) + Vector3 { origin, static_cast<Real>(0) };
9329}
9330
9331template <typename Real>
9332constexpr Vector3<Real> Vector3<Real>::transform(const Transform3<Real>& by, const Real w) const
9333{
9334 return Vector4<Real>(*this, w).transform(by).xyz();
9335}
9336
9337template <typename Real>
9338constexpr Vector3<Real> Vector3<Real>::transform_at(const Vector3& origin, const Transform3<Real>& by, Real w) const
9339{
9340 return (*this - origin).transform(by, w) + origin;
9341}
9342
9343template <typename Real>
9345{
9346 auto result = zero();
9347 for (uint8_t c = 0; c < 3; ++c) {
9348 for (uint8_t r = 0; r < 3; ++r) {
9349 result.at(c) += at(r) * matrix.at(c, r);
9350 }
9351 }
9352 return result;
9353}
9354
9355template <typename Real>
9357{
9358 return { quaternion.x, quaternion.y, quaternion.z, quaternion.w };
9359}
9360
9361template <typename Real>
9362constexpr Matrix4<Real> Vector4<Real>::outer(const Vector4& other) const
9363{
9364 Matrix4<Real> result;
9365 for (uint8_t c = 0; c < 4; ++c) {
9366 for (uint8_t r = 0; r < 4; ++r) {
9367 result.at(c, r) = at(c) * other.at(r);
9368 }
9369 }
9370 return result;
9371}
9372
9373template <typename Real>
9375{
9376 return by.matrix * *this;
9377}
9378
9379template <typename Real>
9381{
9382 return (*this - Vector4 { origin, static_cast<Real>(0) }).transform(by) + Vector4 { origin, static_cast<Real>(0) };
9383}
9384
9385template <typename Real>
9387{
9388 auto result = zero();
9389 for (uint8_t c = 0; c < 4; ++c) {
9390 for (uint8_t r = 0; r < 4; ++r) {
9391 result.at(c) += at(r) * matrix.at(c, r);
9392 }
9393 }
9394 return result;
9395}
9396}
9397
9398#endif
Definition nnm.hpp:5904
constexpr Real determinant() const
Definition nnm.hpp:5989
constexpr Basis2 scale(const Vector2< Real > &factor) const
Definition nnm.hpp:6049
constexpr Basis2(const Matrix2< Real > &matrix)
Definition nnm.hpp:5931
constexpr Basis2 shear_y_local(const Real factor) const
Definition nnm.hpp:6099
Matrix2< float > matrix
Definition nnm.hpp:5906
constexpr Basis2()
Definition nnm.hpp:5911
static constexpr Basis2 from_scale(const Vector2< Real > &factor)
Definition nnm.hpp:5951
constexpr Vector2< Real > & operator[](const uint8_t index)
Definition nnm.hpp:6201
constexpr Real trace() const
Definition nnm.hpp:5980
constexpr Basis2 shear_x_local(const Real factor) const
Definition nnm.hpp:6079
constexpr Real & at(const uint8_t column, const uint8_t row)
Definition nnm.hpp:6179
Basis2 rotate_local(const Real angle) const
Definition nnm.hpp:6039
static constexpr Basis2 from_shear_x(const Real factor)
Definition nnm.hpp:5961
Basis2 rotate(const Real angle) const
Definition nnm.hpp:6029
constexpr Basis2(const Basis2< Other > &basis)
Definition nnm.hpp:5922
constexpr const Real & at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:6167
static constexpr Basis2 from_shear_y(const Real factor)
Definition nnm.hpp:5971
constexpr bool operator!=(const Basis2 &other) const
Definition nnm.hpp:6222
constexpr Basis2 transform_local(const Basis2 &by) const
Definition nnm.hpp:6119
constexpr Basis2 shear_x(const Real factor) const
Definition nnm.hpp:6069
constexpr Basis2 shear_y(const Real factor) const
Definition nnm.hpp:6089
constexpr bool valid() const
Definition nnm.hpp:6019
constexpr bool operator<(const Basis2 &other) const
Definition nnm.hpp:6232
constexpr bool operator==(const Basis2 &other) const
Definition nnm.hpp:6212
constexpr bool approx_equal(const Basis2 &other) const
Definition nnm.hpp:6129
constexpr std::optional< Basis2 > inverse() const
Definition nnm.hpp:6007
constexpr Basis2 transform(const Basis2 &by) const
Definition nnm.hpp:6109
constexpr const Vector2< float > & at(const uint8_t column) const
Definition nnm.hpp:6144
constexpr Basis2 unchecked_inverse() const
Definition nnm.hpp:5998
constexpr Vector2< Real > & at(const uint8_t column)
Definition nnm.hpp:6155
static Basis2 from_rotation(const Real angle)
Definition nnm.hpp:5941
constexpr const Vector2< Real > & operator[](const uint8_t index) const
Definition nnm.hpp:6190
constexpr Basis2 scale_local(const Vector2< Real > &factor) const
Definition nnm.hpp:6059
Definition nnm.hpp:7306
constexpr Real trace() const
Definition nnm.hpp:7438
constexpr Basis3 shear_x(const Real factor_y, const Real factor_z) const
Definition nnm.hpp:7550
constexpr Basis3 rotate_quaternion(const Quaternion< Real > &quaternion) const
Definition nnm.hpp:7509
constexpr bool operator==(const Basis3 &other) const
Definition nnm.hpp:7713
static Basis3 from_rotation_axis_angle(const Vector3< Real > &axis, const Real angle)
Definition nnm.hpp:7344
constexpr Basis3 unchecked_inverse() const
Definition nnm.hpp:7456
Basis3 rotate_axis_angle_local(const Vector3< Real > &axis, const Real angle) const
Definition nnm.hpp:7499
constexpr const Vector3< Real > & at(const uint8_t column) const
Definition nnm.hpp:7645
constexpr bool approx_equal(const Basis3 &other) const
Definition nnm.hpp:7635
constexpr Basis3 shear_z(const Real factor_x, const Real factor_y) const
Definition nnm.hpp:7594
constexpr const Real & at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:7668
constexpr Basis3(const Basis3< Other > &basis)
Definition nnm.hpp:7324
constexpr Basis3 shear_z_local(const Real factor_x, const Real factor_y) const
Definition nnm.hpp:7605
Basis3 rotate_axis_angle(const Vector3< Real > &axis, const Real angle) const
Definition nnm.hpp:7488
constexpr Basis3()
Definition nnm.hpp:7313
constexpr Basis3 transform_local(const Basis3 &by) const
Definition nnm.hpp:7625
static constexpr Basis3 from_scale(const Vector3< Real > &factor)
Definition nnm.hpp:7384
constexpr Basis3(const Matrix3< Real > &matrix)
Definition nnm.hpp:7333
static constexpr Basis3 from_shear_x(const Real factor_y, const Real factor_z)
Definition nnm.hpp:7398
constexpr Basis3 shear_y(const Real factor_x, const Real factor_z) const
Definition nnm.hpp:7572
constexpr Real & at(const uint8_t column, const uint8_t row)
Definition nnm.hpp:7680
constexpr bool valid() const
Definition nnm.hpp:7477
constexpr bool operator<(const Basis3 &other) const
Definition nnm.hpp:7733
constexpr Basis3 scale(const Vector3< Real > &factor) const
Definition nnm.hpp:7529
constexpr std::optional< Basis3 > inverse() const
Definition nnm.hpp:7465
constexpr Vector3< Real > & at(const uint8_t column)
Definition nnm.hpp:7656
constexpr bool operator!=(const Basis3 &other) const
Definition nnm.hpp:7723
Matrix3< float > matrix
Definition nnm.hpp:7308
static constexpr Basis3 from_shear_z(const Real factor_x, const Real factor_y)
Definition nnm.hpp:7426
constexpr Basis3 shear_x_local(const Real factor_y, const Real factor_z) const
Definition nnm.hpp:7561
constexpr Basis3 scale_local(const Vector3< Real > &factor) const
Definition nnm.hpp:7539
constexpr Basis3 shear_y_local(const Real factor_x, const Real factor_z) const
Definition nnm.hpp:7583
static constexpr Basis3 from_shear_y(const Real factor_x, const Real factor_z)
Definition nnm.hpp:7412
constexpr Basis3 rotate_quaternion_local(const Quaternion< Real > &quaternion) const
Definition nnm.hpp:7519
static constexpr Basis3 from_rotation_quaternion(const Quaternion< Real > &quaternion)
Definition nnm.hpp:7361
constexpr const Vector3< Real > & operator[](const uint8_t index) const
Definition nnm.hpp:7691
constexpr Basis3 transform(const Basis3 &by) const
Definition nnm.hpp:7615
constexpr Real determinant() const
Definition nnm.hpp:7447
constexpr Vector3< Real > & operator[](const uint8_t index)
Definition nnm.hpp:7702
Definition nnm.hpp:5328
constexpr Vector2< Real > operator*(const Vector2< Real > &vector) const
Definition nnm.hpp:5774
constexpr bool operator!=(const Matrix2 &other) const
Definition nnm.hpp:5676
constexpr Matrix2 transpose() const
Definition nnm.hpp:5483
constexpr std::optional< Matrix2 > inverse() const
Definition nnm.hpp:5510
constexpr Matrix2 unchecked_inverse() const
Definition nnm.hpp:5501
static constexpr Matrix2 one()
Definition nnm.hpp:5397
constexpr Real determinant() const
Definition nnm.hpp:5424
constexpr Matrix2 operator-(const Matrix2 &other) const
Definition nnm.hpp:5718
constexpr bool approx_equal(const Matrix2 &other) const
Definition nnm.hpp:5524
constexpr Matrix2 operator/(const Real value) const
Definition nnm.hpp:5810
constexpr Matrix2(const Real col0_row0, const Real col0_row1, const Real col1_row0, const Real col1_row1)
Definition nnm.hpp:5369
constexpr const Vector2< Real > & operator[](const uint8_t column) const
Definition nnm.hpp:5639
constexpr Vector2< Real > & at(const uint8_t column)
Definition nnm.hpp:5568
static constexpr Matrix2 all(const Real value)
Definition nnm.hpp:5379
Vector2< float > columns[2]
Definition nnm.hpp:5330
constexpr Matrix2 cofactor() const
Definition nnm.hpp:5474
constexpr Vector2< Real > & operator[](const uint8_t column)
Definition nnm.hpp:5650
constexpr Real minor_at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:5435
constexpr Matrix2 & operator/=(const Real value)
Definition nnm.hpp:5820
constexpr Real & at(const uint8_t column, const uint8_t row)
Definition nnm.hpp:5592
constexpr Matrix2 & operator-=(const Matrix2 &other)
Definition nnm.hpp:5732
const Real * begin() const
Definition nnm.hpp:5602
static constexpr Matrix2 identity()
Definition nnm.hpp:5406
Real * end()
Definition nnm.hpp:5629
constexpr Matrix2(const Matrix2< Other > &matrix)
Definition nnm.hpp:5346
constexpr const Real & at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:5580
constexpr Matrix2 & operator+=(const Matrix2 &other)
Definition nnm.hpp:5705
const Real * end() const
Definition nnm.hpp:5611
constexpr bool operator==(const Matrix2 &other) const
Definition nnm.hpp:5661
constexpr Matrix2()
Definition nnm.hpp:5335
constexpr Matrix2 & operator*=(const Real value)
Definition nnm.hpp:5798
Real * begin()
Definition nnm.hpp:5620
static constexpr Matrix2 zero()
Definition nnm.hpp:5388
constexpr Matrix2 operator+(const Matrix2 &other) const
Definition nnm.hpp:5691
constexpr bool approx_zero() const
Definition nnm.hpp:5540
constexpr Matrix2 minor() const
Definition nnm.hpp:5447
constexpr Matrix2 adjugate() const
Definition nnm.hpp:5492
constexpr Matrix2 operator*(const Real value) const
Definition nnm.hpp:5788
constexpr Matrix2 operator*(const Matrix2 &other) const
Definition nnm.hpp:5745
constexpr Matrix2 & operator*=(const Matrix2 &other)
Definition nnm.hpp:5763
constexpr const Vector2< float > & at(const uint8_t column) const
Definition nnm.hpp:5557
constexpr Real trace() const
Definition nnm.hpp:5415
constexpr bool operator<(const Matrix2 &other) const
Definition nnm.hpp:5832
constexpr Real cofactor_at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:5464
constexpr Matrix2(const Vector2< Real > &column0, const Vector2< Real > &column1)
Definition nnm.hpp:5357
Definition nnm.hpp:6243
constexpr Matrix3 operator-(const Matrix3 &other) const
Definition nnm.hpp:6697
constexpr float minor_at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:6410
Real * begin()
Definition nnm.hpp:6599
constexpr std::optional< Matrix3 > inverse() const
Definition nnm.hpp:6489
static constexpr Matrix3 all(const Real value)
Definition nnm.hpp:6320
constexpr Matrix3 & operator*=(const Matrix3 &other)
Definition nnm.hpp:6742
constexpr const Real & at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:6559
constexpr Matrix3 transpose() const
Definition nnm.hpp:6462
constexpr Vector3< Real > & at(const uint8_t column)
Definition nnm.hpp:6547
constexpr Real determinant() const
Definition nnm.hpp:6367
constexpr bool operator<(const Matrix3 &other) const
Definition nnm.hpp:6815
constexpr Matrix3 operator*(const Matrix3 &other) const
Definition nnm.hpp:6724
constexpr Matrix3 & operator/=(const Real value)
Definition nnm.hpp:6802
constexpr Matrix3 operator/(const Real value) const
Definition nnm.hpp:6792
constexpr Real trace() const
Definition nnm.hpp:6358
Real * end()
Definition nnm.hpp:6608
constexpr Matrix3(const Matrix3< Other > &matrix)
Definition nnm.hpp:6263
constexpr Matrix3(const Real col0_row0, const Real col0_row1, const Real col0_row2, const Real col1_row0, const Real col1_row1, const Real col1_row2, const Real col2_row0, const Real col2_row1, const Real col2_row2)
Definition nnm.hpp:6299
constexpr Matrix3 & operator+=(const Matrix3 &other)
Definition nnm.hpp:6684
Vector3< float > columns[3]
Definition nnm.hpp:6245
constexpr Matrix3 & operator-=(const Matrix3 &other)
Definition nnm.hpp:6711
constexpr bool operator==(const Matrix3 &other) const
Definition nnm.hpp:6640
constexpr Matrix3 adjugate() const
Definition nnm.hpp:6471
constexpr const Vector3< Real > & operator[](const uint8_t column) const
Definition nnm.hpp:6618
constexpr Matrix3 minor() const
Definition nnm.hpp:6420
constexpr const Vector3< float > & at(const uint8_t column) const
Definition nnm.hpp:6536
const Real * end() const
Definition nnm.hpp:6590
constexpr Matrix3 operator*(const Real value) const
Definition nnm.hpp:6769
constexpr Matrix3 & operator*=(const Real value)
Definition nnm.hpp:6779
constexpr Matrix3 operator+(const Matrix3 &other) const
Definition nnm.hpp:6670
constexpr Real cofactor_at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:6437
constexpr bool approx_equal(const Matrix3 &other) const
Definition nnm.hpp:6503
constexpr Vector3< Real > operator*(const Vector3< Real > &vector) const
Definition nnm.hpp:6753
constexpr bool approx_zero() const
Definition nnm.hpp:6519
static constexpr Matrix3 identity()
Definition nnm.hpp:6347
const Real * begin() const
Definition nnm.hpp:6581
constexpr Matrix3 unchecked_inverse() const
Definition nnm.hpp:6480
constexpr Matrix3 cofactor() const
Definition nnm.hpp:6447
constexpr Matrix3(const Vector3< Real > &column0, const Vector3< Real > &column1, const Vector3< Real > &column2)
Definition nnm.hpp:6282
static constexpr Matrix3 zero()
Definition nnm.hpp:6329
constexpr Vector3< Real > & operator[](const uint8_t column)
Definition nnm.hpp:6629
constexpr Real & at(const uint8_t column, const uint8_t row)
Definition nnm.hpp:6571
constexpr Matrix3()
Definition nnm.hpp:6250
static constexpr Matrix3 one()
Definition nnm.hpp:6338
constexpr bool operator!=(const Matrix3 &other) const
Definition nnm.hpp:6655
constexpr Matrix2< Real > minor_matrix_at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:6383
Definition nnm.hpp:7744
static constexpr Matrix4 all(const Real value)
Definition nnm.hpp:7853
constexpr const Real & at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:8096
constexpr bool approx_equal(const Matrix4 &other) const
Definition nnm.hpp:8044
static constexpr Matrix4 one()
Definition nnm.hpp:7874
constexpr Vector4< Real > & operator[](const uint8_t index)
Definition nnm.hpp:8166
constexpr const Vector4< float > & at(const uint8_t column) const
Definition nnm.hpp:8073
constexpr Matrix4 adjugate() const
Definition nnm.hpp:8012
constexpr Matrix4 operator/(const Real value) const
Definition nnm.hpp:8333
const Real * end() const
Definition nnm.hpp:8127
constexpr Matrix3< Real > minor_matrix_at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:7920
constexpr Matrix4()
Definition nnm.hpp:7754
constexpr Matrix4 & operator*=(const Real value)
Definition nnm.hpp:8320
constexpr const Vector4< Real > & operator[](const uint8_t index) const
Definition nnm.hpp:8155
constexpr Matrix4 operator*(const Matrix4 &other) const
Definition nnm.hpp:8261
constexpr Matrix4(const Matrix4< Other > &matrix)
Definition nnm.hpp:7769
constexpr Matrix4 operator-(const Matrix4 &other) const
Definition nnm.hpp:8234
Real * end()
Definition nnm.hpp:8145
const Real * begin() const
Definition nnm.hpp:8118
constexpr Real cofactor_at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:7975
constexpr bool operator==(const Matrix4 &other) const
Definition nnm.hpp:8177
constexpr Matrix4(const Vector4< Real > &column0, const Vector4< Real > &column1, const Vector4< Real > &column2, const Vector4< Real > &column3)
Definition nnm.hpp:7796
constexpr bool operator<(const Matrix4 &other) const
Definition nnm.hpp:8360
Vector4< float > columns[4]
Definition nnm.hpp:7749
constexpr Matrix4(const Real col0_row0, const Real col0_row1, const Real col0_row2, const Real col0_row3, const Real col1_row0, const Real col1_row1, const Real col1_row2, const Real col1_row3, const Real col2_row0, const Real col2_row1, const Real col2_row2, const Real col2_row3, const Real col3_row0, const Real col3_row1, const Real col3_row2, const Real col3_row3)
Definition nnm.hpp:7824
constexpr Real trace() const
Definition nnm.hpp:7895
constexpr Matrix4 cofactor() const
Definition nnm.hpp:7985
constexpr Vector4< Real > & at(const uint8_t column)
Definition nnm.hpp:8084
constexpr Matrix4 unchecked_inverse() const
Definition nnm.hpp:8021
constexpr Matrix4 transpose() const
Definition nnm.hpp:8000
constexpr Matrix4 & operator+=(const Matrix4 &other)
Definition nnm.hpp:8221
constexpr Matrix4 operator+(const Matrix4 &other) const
Definition nnm.hpp:8207
constexpr Matrix4 minor() const
Definition nnm.hpp:7958
constexpr float minor_at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:7948
constexpr std::optional< Matrix4 > inverse() const
Definition nnm.hpp:8030
Real * begin()
Definition nnm.hpp:8136
constexpr bool operator!=(const Matrix4 &other) const
Definition nnm.hpp:8192
constexpr Real & at(const uint8_t column, const uint8_t row)
Definition nnm.hpp:8108
constexpr Matrix4 operator*(const Real value) const
Definition nnm.hpp:8306
static constexpr Matrix4 identity()
Definition nnm.hpp:7883
constexpr Matrix4 & operator*=(const Matrix4 &other)
Definition nnm.hpp:8279
constexpr Vector4< Real > operator*(const Vector4< Real > &vector) const
Definition nnm.hpp:8290
static constexpr Matrix4 zero()
Definition nnm.hpp:7865
constexpr Matrix4 & operator/=(const Real value)
Definition nnm.hpp:8347
constexpr Matrix4 & operator-=(const Matrix4 &other)
Definition nnm.hpp:8248
constexpr Real determinant() const
Definition nnm.hpp:7904
constexpr bool approx_zero() const
Definition nnm.hpp:8058
Definition nnm.hpp:4930
float w
Definition nnm.hpp:4935
static constexpr Quaternion identity()
Definition nnm.hpp:4993
constexpr Quaternion(const Quaternion< Other > &quaternion)
Definition nnm.hpp:4954
constexpr Real length_sqrd() const
Definition nnm.hpp:5103
constexpr Quaternion & operator*=(const Quaternion &other)
Definition nnm.hpp:5297
constexpr bool operator==(const Quaternion &other) const
Definition nnm.hpp:5262
float angle() const
Definition nnm.hpp:5085
Real angle_to(const Quaternion &to) const
Definition nnm.hpp:5061
static Quaternion from_axis_angle(const Vector3< Real > &axis, const Real angle)
Definition nnm.hpp:5004
constexpr Quaternion operator*(const Quaternion &other) const
Definition nnm.hpp:5282
float x
Definition nnm.hpp:4932
constexpr bool approx_equal(const Quaternion &other) const
Definition nnm.hpp:5163
Vector3< Real > axis_to(const Quaternion &to) const
Definition nnm.hpp:5046
float z
Definition nnm.hpp:4934
constexpr Quaternion rotate_quaternion(const Quaternion &by) const
Definition nnm.hpp:5153
constexpr Quaternion(const Vector4< Real > &vector)
Definition nnm.hpp:4966
Vector3< float > axis() const
Definition nnm.hpp:5072
constexpr Real & at(const uint8_t index)
Definition nnm.hpp:5196
constexpr Quaternion inverse() const
Definition nnm.hpp:5094
constexpr bool operator!=(const Quaternion &other) const
Definition nnm.hpp:5272
Real length() const
Definition nnm.hpp:5112
constexpr bool operator<(const Quaternion &other) const
Definition nnm.hpp:5308
constexpr Real & operator[](const uint8_t index)
Definition nnm.hpp:5240
Quaternion normalize() const
Definition nnm.hpp:5036
Quaternion slerp(const Quaternion &to, const Real weight) const
Definition nnm.hpp:5123
float y
Definition nnm.hpp:4933
constexpr Quaternion(const Real x, const Real y, const Real z, const Real w)
Definition nnm.hpp:4981
constexpr const Real & operator[](const uint8_t index) const
Definition nnm.hpp:5218
Quaternion rotate_axis_angle(const Vector3< Real > &axis, const Real angle) const
Definition nnm.hpp:5143
static Quaternion from_vector_to_vector(const Vector3< Real > &from, const Vector3< Real > &to)
Definition nnm.hpp:5022
constexpr const Real & at(const uint8_t index) const
Definition nnm.hpp:5174
constexpr Quaternion()
Definition nnm.hpp:4940
Definition nnm.hpp:6885
constexpr Transform2()
Definition nnm.hpp:6892
constexpr const Vector3< Real > & operator[](const uint8_t column) const
Definition nnm.hpp:7253
constexpr bool affine() const
Definition nnm.hpp:7048
constexpr bool approx_equal(const Transform2 &other) const
Definition nnm.hpp:7197
constexpr Transform2(const Matrix3< Real > &matrix)
Definition nnm.hpp:6912
static constexpr Transform2 from_shear_y(const Real factor)
Definition nnm.hpp:6991
constexpr Vector3< Real > & at(const uint8_t column)
Definition nnm.hpp:7218
constexpr Transform2 shear_y_local(const Real factor) const
Definition nnm.hpp:7167
constexpr Transform2(const Transform2< Other > &transform)
Definition nnm.hpp:6903
Matrix3< float > matrix
Definition nnm.hpp:6887
constexpr Real trace() const
Definition nnm.hpp:7000
constexpr Transform2 unchecked_inverse() const
Definition nnm.hpp:7018
constexpr Transform2 shear_x_local(const Real factor) const
Definition nnm.hpp:7147
constexpr bool operator!=(const Transform2 &other) const
Definition nnm.hpp:7285
constexpr Transform2 shear_y(const Real factor) const
Definition nnm.hpp:7157
Transform2 rotate_local(const Real angle) const
Definition nnm.hpp:7107
constexpr bool valid() const
Definition nnm.hpp:7039
constexpr Real determinant() const
Definition nnm.hpp:7009
static constexpr Transform2 from_basis(const Basis2< Real > &basis)
Definition nnm.hpp:6941
static constexpr Transform2 from_scale(const Vector2< Real > &factor)
Definition nnm.hpp:6971
constexpr Transform2 translate(const Vector2< Real > &offset) const
Definition nnm.hpp:7077
constexpr Vector3< Real > & operator[](const uint8_t column)
Definition nnm.hpp:7264
constexpr const Vector3< Real > & at(const uint8_t column) const
Definition nnm.hpp:7207
constexpr Basis2< float > basis() const
Definition nnm.hpp:7058
constexpr bool operator==(const Transform2 &other) const
Definition nnm.hpp:7275
constexpr std::optional< Transform2 > inverse() const
Definition nnm.hpp:7027
constexpr Vector2< float > translation() const
Definition nnm.hpp:7067
constexpr Real & at(const uint8_t column, const uint8_t row)
Definition nnm.hpp:7242
Transform2 rotate(const Real angle) const
Definition nnm.hpp:7097
static Transform2 from_rotation(const Real angle)
Definition nnm.hpp:6961
static constexpr Transform2 from_shear_x(const Real factor)
Definition nnm.hpp:6981
constexpr Transform2 shear_x(const Real factor) const
Definition nnm.hpp:7137
constexpr Transform2 scale(const Vector2< Real > &factor) const
Definition nnm.hpp:7117
constexpr bool operator<(const Transform2 &other) const
Definition nnm.hpp:7295
constexpr const Real & at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:7230
constexpr Transform2 translate_local(const Vector2< Real > &offset) const
Definition nnm.hpp:7087
static constexpr Transform2 from_translation(const Vector2< Real > &translation)
Definition nnm.hpp:6951
constexpr Transform2 transform(const Transform2 &by) const
Definition nnm.hpp:7177
constexpr Transform2 scale_local(const Vector2< Real > &factor) const
Definition nnm.hpp:7127
constexpr Transform2 transform_local(const Transform2 &by) const
Definition nnm.hpp:7187
static constexpr Transform2 from_basis_translation(const Basis2< Real > &basis, const Vector2< Real > &translation)
Definition nnm.hpp:6923
Definition nnm.hpp:8430
constexpr Transform3 rotate_quaternion_local(const Quaternion< Real > &quaternion) const
Definition nnm.hpp:8880
static Transform3 from_perspective_right_hand_0to1(const Real fov, const Real aspect_ratio, const Real near_clip, const Real far_clip)
Definition nnm.hpp:8642
constexpr bool operator<(const Transform3 &other) const
Definition nnm.hpp:9094
constexpr Transform3 shear_x(const Real factor_y, const Real factor_z) const
Definition nnm.hpp:8911
constexpr bool approx_equal(const Transform3 &other) const
Definition nnm.hpp:8996
constexpr bool valid() const
Definition nnm.hpp:8790
constexpr Transform3 shear_y_local(const Real factor_x, const Real factor_z) const
Definition nnm.hpp:8944
static constexpr Transform3 from_shear_z(const Real factor_x, const Real factor_y)
Definition nnm.hpp:8566
static Transform3 from_perspective_left_hand_0to1(const Real fov, const Real aspect_ratio, const Real near_clip, const Real far_clip)
Definition nnm.hpp:8600
static Transform3 from_perspective_left_hand_neg1to1(const Real fov, const Real aspect_ratio, const Real near_clip, const Real far_clip)
Definition nnm.hpp:8579
static Transform3 from_perspective_right_hand_neg1to1(const Real fov, const Real aspect_ratio, const Real near_clip, const Real far_clip)
Definition nnm.hpp:8621
constexpr Transform3(const Transform3< Other > &transform)
Definition nnm.hpp:8451
Transform3 rotate_axis_angle(const Vector3< Real > &axis, const Real angle) const
Definition nnm.hpp:8849
constexpr Transform3()
Definition nnm.hpp:8440
constexpr std::optional< Transform3 > inverse() const
Definition nnm.hpp:8778
static constexpr Transform3 from_orthographic_right_hand_0to1(const Real left, const Real right, const Real bottom, const Real top, const Real near_clip, const Real far_clip)
Definition nnm.hpp:8734
constexpr Real & at(const uint8_t column, const uint8_t row)
Definition nnm.hpp:9041
constexpr Transform3 scale(const Vector3< Real > &factor) const
Definition nnm.hpp:8890
static constexpr Transform3 from_shear_y(const Real factor_x, const Real factor_z)
Definition nnm.hpp:8555
static constexpr Transform3 from_basis(const Basis3< Real > &basis)
Definition nnm.hpp:8490
constexpr Transform3 shear_z_local(const Real factor_x, const Real factor_y) const
Definition nnm.hpp:8966
constexpr Transform3 scale_local(const Vector3< Real > &factor) const
Definition nnm.hpp:8900
constexpr Transform3 translate_local(const Vector3< Real > &offset) const
Definition nnm.hpp:8838
static constexpr Transform3 from_orthographic_right_hand_neg1to1(const Real left, const Real right, const Real bottom, const Real top, const Real near_clip, const Real far_clip)
Definition nnm.hpp:8711
Transform3 rotate_axis_angle_local(const Vector3< Real > &axis, const Real angle) const
Definition nnm.hpp:8860
static constexpr Transform3 from_shear_x(const Real factor_y, const Real factor_z)
Definition nnm.hpp:8544
constexpr bool operator!=(const Transform3 &other) const
Definition nnm.hpp:9084
constexpr Transform3 unchecked_inverse() const
Definition nnm.hpp:8769
static constexpr Transform3 from_scale(const Vector3< Real > &factor)
Definition nnm.hpp:8533
constexpr Transform3 transform(const Transform3 &by) const
Definition nnm.hpp:8976
constexpr Vector4< Real > & operator[](const uint8_t column)
Definition nnm.hpp:9063
constexpr Transform3 transform_local(const Transform3 &by) const
Definition nnm.hpp:8986
Matrix4< float > matrix
Definition nnm.hpp:8435
static Transform3 from_rotation_axis_angle(const Vector3< Real > &axis, const Real angle)
Definition nnm.hpp:8511
constexpr bool affine() const
Definition nnm.hpp:8799
constexpr Transform3(const Matrix4< Real > &matrix)
Definition nnm.hpp:8460
constexpr Vector3< float > translation() const
Definition nnm.hpp:8818
constexpr const Vector4< Real > & operator[](const uint8_t column) const
Definition nnm.hpp:9052
constexpr Basis3< float > basis() const
Definition nnm.hpp:8809
constexpr Transform3 shear_y(const Real factor_x, const Real factor_z) const
Definition nnm.hpp:8933
constexpr Transform3 shear_z(const Real factor_x, const Real factor_y) const
Definition nnm.hpp:8955
constexpr Transform3 translate(const Vector3< Real > &offset) const
Definition nnm.hpp:8828
constexpr Real determinant() const
Definition nnm.hpp:8760
static constexpr Transform3 from_orthographic_left_hand_0to1(const Real left, const Real right, const Real bottom, const Real top, const Real near_clip, const Real far_clip)
Definition nnm.hpp:8688
static constexpr Transform3 from_rotation_quaternion(const Quaternion< Real > &quaternion)
Definition nnm.hpp:8522
constexpr Transform3 shear_x_local(const Real factor_y, const Real factor_z) const
Definition nnm.hpp:8922
constexpr Real trace() const
Definition nnm.hpp:8751
constexpr Transform3 rotate_quaternion(const Quaternion< Real > &quaternion) const
Definition nnm.hpp:8870
constexpr const Real & at(const uint8_t column, const uint8_t row) const
Definition nnm.hpp:9029
static constexpr Transform3 from_translation(const Vector3< Real > &translation)
Definition nnm.hpp:8500
constexpr Vector4< Real > & at(const uint8_t column)
Definition nnm.hpp:9017
static constexpr Transform3 from_basis_translation(const Basis3< Real > &basis, const Vector3< Real > &translation)
Definition nnm.hpp:8471
static constexpr Transform3 from_orthographic_left_hand_neg1to1(const Real left, const Real right, const Real bottom, const Real top, const Real near_clip, const Real far_clip)
Definition nnm.hpp:8665
constexpr const Vector4< Real > & at(const uint8_t column) const
Definition nnm.hpp:9006
constexpr bool operator==(const Transform3 &other) const
Definition nnm.hpp:9074
Definition nnm.hpp:689
constexpr Real aspect_ratio() const
Definition nnm.hpp:820
Vector2 ceil() const
Definition nnm.hpp:793
constexpr bool operator==(const Vector2 &other) const
Definition nnm.hpp:1400
constexpr Vector2 operator/(const Real value) const
Definition nnm.hpp:1537
constexpr Vector2 transform_at(const Vector2 &origin, const Basis2< Real > &by) const
Definition nnm.hpp:9181
float y
Definition nnm.hpp:692
constexpr uint8_t min_index() const
Definition nnm.hpp:1248
constexpr bool perpendicular(const Vector2 &other) const
Definition nnm.hpp:1069
constexpr bool approx_zero() const
Definition nnm.hpp:1282
constexpr Vector2 shear_y(Real factor) const
Definition nnm.hpp:9163
constexpr Vector2 & operator-=(const Vector2 &other)
Definition nnm.hpp:1452
constexpr Vector2(const Vector2i< Int > &vector)
Definition nnm.hpp:9102
constexpr Real & at(const uint8_t index)
Definition nnm.hpp:1346
static constexpr Vector2 axis_y()
Definition nnm.hpp:775
Vector2 rotate(Real angle) const
Definition nnm.hpp:9127
Vector2 normalize() const
Definition nnm.hpp:933
constexpr float min() const
Definition nnm.hpp:1206
constexpr uint8_t max_index() const
Definition nnm.hpp:1224
constexpr Real cross(const Vector2 &other) const
Definition nnm.hpp:978
constexpr Vector2 abs() const
Definition nnm.hpp:784
constexpr Real abs_max() const
Definition nnm.hpp:1197
constexpr uint8_t abs_min_index() const
Definition nnm.hpp:1260
constexpr Vector2 operator+() const
Definition nnm.hpp:1558
const Real * begin() const
Definition nnm.hpp:1291
constexpr Vector2 & operator/=(const Real value)
Definition nnm.hpp:1547
constexpr uint8_t abs_max_index() const
Definition nnm.hpp:1236
constexpr Vector2 project(const Vector2 &onto) const
Definition nnm.hpp:1009
constexpr Real & operator[](const uint8_t index)
Definition nnm.hpp:1382
constexpr Vector2()
Definition nnm.hpp:697
constexpr Vector2(const Vector2< Other > &vector)
Definition nnm.hpp:717
constexpr const Real & operator[](const uint8_t index) const
Definition nnm.hpp:1364
constexpr Vector2 lerp_clamped(const Vector2 &to, const Real weight) const
Definition nnm.hpp:958
static constexpr Vector2 all(const Real value)
Definition nnm.hpp:739
constexpr Vector2 & operator*=(const Real value)
Definition nnm.hpp:1503
Real angle_to(const Vector2 &to) const
Definition nnm.hpp:1049
constexpr Vector2 operator-() const
Definition nnm.hpp:1567
constexpr Real length_sqrd() const
Definition nnm.hpp:892
constexpr Matrix2< Real > outer(const Vector2 &other) const
Definition nnm.hpp:9109
constexpr Vector2(const Real x, const Real y)
Definition nnm.hpp:728
Vector2 direction(const Vector2 &to) const
Definition nnm.hpp:841
constexpr Vector2 & operator+=(const Vector2 &other)
Definition nnm.hpp:1430
constexpr Vector2 shear_x(Real factor) const
Definition nnm.hpp:9151
constexpr Real dot(const Vector2 &other) const
Definition nnm.hpp:968
Real angle_between(const Vector2 &other) const
Definition nnm.hpp:1033
constexpr Vector2 lerp(const Vector2 &to, const Real weight) const
Definition nnm.hpp:947
constexpr Vector2 operator*(const Real value) const
Definition nnm.hpp:1493
Real distance(const Vector2 &to) const
Definition nnm.hpp:873
constexpr Vector2 clamp(const Vector2 &min, const Vector2 &max) const
Definition nnm.hpp:831
constexpr Vector2 operator+(const Vector2 &other) const
Definition nnm.hpp:1420
constexpr Real manhattan_distance(const Vector2 &to) const
Definition nnm.hpp:883
static constexpr Vector2 axis_x()
Definition nnm.hpp:766
float x
Definition nnm.hpp:691
constexpr Vector2 & operator*=(const Vector2 &other)
Definition nnm.hpp:1474
constexpr bool approx_equal(const Vector2 &other) const
Definition nnm.hpp:1273
constexpr const Real & at(const uint8_t index) const
Definition nnm.hpp:1328
constexpr Vector2 reflect(const Vector2 &normal) const
Definition nnm.hpp:995
constexpr Vector2 operator*(const Vector2 &other) const
Definition nnm.hpp:1464
constexpr bool operator!=(const Vector2 &other) const
Definition nnm.hpp:1410
constexpr Vector2 inverse() const
Definition nnm.hpp:1023
Vector2 round() const
Definition nnm.hpp:811
Real * end()
Definition nnm.hpp:1318
constexpr Vector2 shear_y_at(const Vector2 &origin, Real factor) const
Definition nnm.hpp:9169
constexpr Vector2 scale_at(const Vector2 &origin, const Vector2 &factor) const
Definition nnm.hpp:9145
constexpr bool operator<(const Vector2 &other) const
Definition nnm.hpp:1577
constexpr Vector2 operator/(const Vector2 &other) const
Definition nnm.hpp:1515
Vector2 floor() const
Definition nnm.hpp:802
static constexpr Vector2 zero()
Definition nnm.hpp:748
static constexpr Vector2 one()
Definition nnm.hpp:757
constexpr float max() const
Definition nnm.hpp:1188
constexpr Vector2 & operator/=(const Vector2 &other)
Definition nnm.hpp:1525
constexpr Vector2 shear_x_at(const Vector2 &origin, Real factor) const
Definition nnm.hpp:9157
Vector2 clamp_length(const Real min, const Real max) const
Definition nnm.hpp:913
constexpr Real abs_min() const
Definition nnm.hpp:1215
constexpr Vector2 transform(const Basis2< Real > &by) const
Definition nnm.hpp:9175
constexpr Vector2 scale(const Vector2 &factor) const
constexpr Vector2 transform_at(const Vector2 &origin, const Transform2< Real > &by, Real z=static_cast< Real >(1)) const
Definition nnm.hpp:9193
Real length() const
Definition nnm.hpp:901
constexpr Real distance_sqrd(const Vector2 &to) const
Definition nnm.hpp:861
constexpr Vector2 translate(const Vector2 &by) const
Definition nnm.hpp:9121
constexpr Vector2 transform(const Transform2< Real > &by, Real z=static_cast< Real >(1)) const
Definition nnm.hpp:9187
Real * begin()
Definition nnm.hpp:1309
Vector2 rotate_at(const Vector2 &origin, Real angle) const
Definition nnm.hpp:9133
constexpr bool parallel(const Vector2 &other) const
Definition nnm.hpp:1059
constexpr Vector2 arbitrary_perpendicular() const
Definition nnm.hpp:1079
const Real * end() const
Definition nnm.hpp:1300
constexpr Vector2 operator*(const Matrix2< Real > &matrix) const
Definition nnm.hpp:9199
constexpr Vector2 direction_unnormalized(const Vector2 &to) const
Definition nnm.hpp:851
constexpr Vector2 operator-(const Vector2 &other) const
Definition nnm.hpp:1442
Definition nnm.hpp:1628
constexpr uint8_t abs_min_index() const
Definition nnm.hpp:1876
constexpr uint8_t abs_max_index() const
Definition nnm.hpp:1852
int x
Definition nnm.hpp:1630
constexpr Int abs_max() const
Definition nnm.hpp:1813
constexpr Int & operator[](const uint8_t index)
Definition nnm.hpp:1979
constexpr Vector2i & operator-=(const Vector2i &other)
Definition nnm.hpp:2049
constexpr Int manhattan_distance(const Vector2i &to) const
Definition nnm.hpp:1736
constexpr uint8_t max_index() const
Definition nnm.hpp:1840
constexpr Int abs_min() const
Definition nnm.hpp:1831
constexpr Vector2i operator-(const Vector2i &other) const
Definition nnm.hpp:2039
constexpr int max() const
Definition nnm.hpp:1804
constexpr Vector2i operator%(const Int value) const
Definition nnm.hpp:2171
constexpr Vector2i operator+() const
Definition nnm.hpp:2192
constexpr Vector2i arbitrary_perpendicular() const
Definition nnm.hpp:1795
int y
Definition nnm.hpp:1631
constexpr Vector2i & operator*=(const Int value)
Definition nnm.hpp:2093
static constexpr Vector2i axis_x()
Definition nnm.hpp:1697
static constexpr Vector2i axis_y()
Definition nnm.hpp:1706
Int * begin()
Definition nnm.hpp:1906
constexpr Vector2i()
Definition nnm.hpp:1636
constexpr bool operator<(const Vector2i &other) const
Definition nnm.hpp:2211
constexpr Vector2i operator*(const Int value) const
Definition nnm.hpp:2083
constexpr uint8_t min_index() const
Definition nnm.hpp:1864
static constexpr Vector2i zero()
Definition nnm.hpp:1679
constexpr const Int & operator[](const uint8_t index) const
Definition nnm.hpp:1961
constexpr Vector2i & operator/=(const Int value)
Definition nnm.hpp:2137
constexpr bool operator!=(const Vector2i &other) const
Definition nnm.hpp:2007
constexpr Vector2i(const Vector2< Real > &vector)
Definition nnm.hpp:1648
constexpr Vector2i operator/(const Int value) const
Definition nnm.hpp:2127
constexpr Vector2i abs() const
Definition nnm.hpp:1715
constexpr bool perpendicular(const Vector2i &other) const
Definition nnm.hpp:1785
constexpr const Int & at(const uint8_t index) const
Definition nnm.hpp:1925
static constexpr Vector2i one()
Definition nnm.hpp:1688
constexpr bool parallel(const Vector2i &other) const
Definition nnm.hpp:1775
constexpr bool operator==(const Vector2i &other) const
Definition nnm.hpp:1997
constexpr Vector2i & operator%=(const Vector2i &other)
Definition nnm.hpp:2159
constexpr Vector2i operator/(const Vector2i &other) const
Definition nnm.hpp:2105
constexpr Vector2i & operator+=(const Vector2i &other)
Definition nnm.hpp:2027
constexpr Vector2i operator*(const Vector2i &other) const
Definition nnm.hpp:2061
constexpr Int cross(const Vector2i &other) const
Definition nnm.hpp:1765
constexpr Vector2i & operator%=(const Int value)
Definition nnm.hpp:2181
const Int * end() const
Definition nnm.hpp:1897
constexpr Int dot(const Vector2i &other) const
Definition nnm.hpp:1755
const Int * begin() const
Definition nnm.hpp:1888
constexpr Vector2i clamp(const Vector2i &min, const Vector2i &max) const
Definition nnm.hpp:1726
constexpr Vector2i & operator*=(const Vector2i &other)
Definition nnm.hpp:2071
constexpr Int & at(const uint8_t index)
Definition nnm.hpp:1943
constexpr Vector2i operator%(const Vector2i &other) const
Definition nnm.hpp:2149
constexpr Vector2i(const Int x, const Int y)
Definition nnm.hpp:1659
constexpr Vector2i operator-() const
Definition nnm.hpp:2201
constexpr Vector2i operator+(const Vector2i &other) const
Definition nnm.hpp:2017
constexpr Vector2i & operator/=(const Vector2i &other)
Definition nnm.hpp:2115
constexpr Int length_sqrd() const
Definition nnm.hpp:1745
static constexpr Vector2i all(Int value)
Definition nnm.hpp:1670
Int * end()
Definition nnm.hpp:1915
constexpr int min() const
Definition nnm.hpp:1822
Definition nnm.hpp:2288
constexpr Real distance_sqrd(const Vector3 &to) const
Definition nnm.hpp:2477
constexpr Vector3 operator*(const Vector3 &other) const
Definition nnm.hpp:3167
constexpr Vector3 operator/(const Real value) const
Definition nnm.hpp:3243
Real distance(const Vector3 &to) const
Definition nnm.hpp:2490
Real angle(const Vector3 &to) const
Definition nnm.hpp:2652
Vector3 floor() const
Definition nnm.hpp:2427
constexpr Vector3 operator+() const
Definition nnm.hpp:3265
constexpr uint8_t max_index() const
Definition nnm.hpp:2882
constexpr float min() const
Definition nnm.hpp:2864
constexpr bool operator<(const Vector3 &other) const
Definition nnm.hpp:3284
constexpr Vector3 inverse() const
Definition nnm.hpp:2642
constexpr Vector3 scale(const Vector3 &factor) const
constexpr Vector3 lerp_clamped(const Vector3 &to, const Real weight) const
Definition nnm.hpp:2574
constexpr Vector3(const Real x, const Real y, const Real z)
Definition nnm.hpp:2343
Vector3 rotate_axis_angle(const Vector3 &axis, Real angle) const
Definition nnm.hpp:9235
static constexpr Vector3 axis_x()
Definition nnm.hpp:2382
constexpr Vector3 clamp(const Vector3 &min, const Vector3 &max) const
Definition nnm.hpp:2447
constexpr Vector3 shear_z(Real factor_x, Real factor_y) const
Definition nnm.hpp:9296
constexpr uint8_t abs_max_index() const
Definition nnm.hpp:2900
constexpr Vector3 transform(const Basis3< Real > &by) const
Definition nnm.hpp:9308
float x
Definition nnm.hpp:2290
static constexpr Vector3 axis_y()
Definition nnm.hpp:2391
constexpr Vector3(const Vector3i< Int > &vector)
Definition nnm.hpp:9209
constexpr Vector3 translate(const Vector3 &by) const
Definition nnm.hpp:9229
constexpr bool operator==(const Vector3 &other) const
Definition nnm.hpp:3101
constexpr Vector3 rotate_quaternion_at(const Vector3 &origin, const Quaternion< Real > &quaternion) const
Definition nnm.hpp:9253
Vector3 clamp_length(const Real min, const Real max) const
Definition nnm.hpp:2529
constexpr Vector3()
Definition nnm.hpp:2297
static constexpr Vector3 one()
Definition nnm.hpp:2373
Real * begin()
Definition nnm.hpp:3002
constexpr Vector3 shear_z_at(const Vector3 &origin, Real factor_x, Real factor_y) const
Definition nnm.hpp:9302
constexpr Vector3 transform_at(const Vector2< Real > &origin, const Transform2< Real > &by) const
Definition nnm.hpp:9326
static constexpr Vector3 zero()
Definition nnm.hpp:2364
float z
Definition nnm.hpp:2292
constexpr Vector3 & operator-=(const Vector3 &other)
Definition nnm.hpp:3154
constexpr Vector3 rotate_quaternion(const Quaternion< Real > &quaternion) const
Definition nnm.hpp:9247
constexpr Real dot(const Vector3 &other) const
Definition nnm.hpp:2586
constexpr bool perpendicular(const Vector3 &other) const
Definition nnm.hpp:2672
static constexpr Vector3 axis_z()
Definition nnm.hpp:2400
constexpr Vector3 shear_x(Real factor_y, Real factor_z) const
Definition nnm.hpp:9272
constexpr Vector2< Real > xy() const
Definition nnm.hpp:2975
Real length() const
Definition nnm.hpp:2518
constexpr Vector3 operator-(const Vector3 &other) const
Definition nnm.hpp:3144
float y
Definition nnm.hpp:2291
constexpr Matrix3< Real > outer(const Vector3 &other) const
Definition nnm.hpp:9217
constexpr Vector3 operator-() const
Definition nnm.hpp:3274
constexpr Vector3 operator*(const Real value) const
Definition nnm.hpp:3197
static constexpr Vector3 all(Real value)
Definition nnm.hpp:2355
Vector3 ceil() const
Definition nnm.hpp:2418
constexpr Vector3 & operator*=(const Real value)
Definition nnm.hpp:3207
constexpr bool approx_equal(const Vector3 &other) const
Definition nnm.hpp:2957
constexpr Vector3 abs() const
Definition nnm.hpp:2409
constexpr Vector3 shear_x_at(const Vector3 &origin, Real factor_y, Real factor_z) const
Definition nnm.hpp:9278
constexpr Vector3(const Vector2< Real > &vector, const Real z)
Definition nnm.hpp:2330
constexpr Vector3 & operator+=(const Vector3 &other)
Definition nnm.hpp:3131
constexpr Real & at(const uint8_t index)
Definition nnm.hpp:3041
Vector3 direction(const Vector3 &to) const
Definition nnm.hpp:2457
constexpr bool parallel(const Vector3 &other) const
Definition nnm.hpp:2662
constexpr uint8_t abs_min_index() const
Definition nnm.hpp:2937
constexpr const Real & operator[](const uint8_t index) const
Definition nnm.hpp:3061
constexpr Real manhattan_distance(const Vector3 &to) const
Definition nnm.hpp:2500
constexpr Vector3 operator/(const Vector3 &other) const
Definition nnm.hpp:3220
constexpr Vector3 & operator*=(const Vector3 &other)
Definition nnm.hpp:3177
constexpr bool operator!=(const Vector3 &other) const
Definition nnm.hpp:3111
constexpr const Real & at(const uint8_t index) const
Definition nnm.hpp:3021
constexpr Real abs_min() const
Definition nnm.hpp:2873
constexpr bool approx_zero() const
Definition nnm.hpp:2966
constexpr Real abs_max() const
Definition nnm.hpp:2855
constexpr Real & operator[](const uint8_t index)
Definition nnm.hpp:3081
constexpr Vector3 & operator/=(const Vector3 &other)
Definition nnm.hpp:3230
const Real * end() const
Definition nnm.hpp:2993
constexpr Vector3 shear_y(Real factor_x, Real factor_z) const
Definition nnm.hpp:9284
constexpr Vector3 & operator/=(const Real value)
Definition nnm.hpp:3253
Vector3 round() const
Definition nnm.hpp:2436
constexpr Vector3 scale_at(const Vector3 &origin, const Vector3 &factor) const
Definition nnm.hpp:9266
Vector3 normalize() const
Definition nnm.hpp:2549
constexpr Vector3 lerp(const Vector3 &to, const Real weight) const
Definition nnm.hpp:2563
constexpr Vector3 arbitrary_perpendicular() const
Definition nnm.hpp:2682
constexpr Vector3(const Vector3< Other > &vector)
Definition nnm.hpp:2318
constexpr uint8_t min_index() const
Definition nnm.hpp:2919
Vector3 rotate_axis_angle_at(const Vector3 &origin, const Vector3 &axis, Real angle) const
Definition nnm.hpp:9241
Real * end()
Definition nnm.hpp:3011
constexpr Vector3 reflect(const Vector3 &normal) const
Definition nnm.hpp:2613
constexpr Real length_sqrd() const
Definition nnm.hpp:2509
constexpr Vector3 transform_at(const Vector3 &origin, const Transform3< Real > &by, Real w=static_cast< Real >(1)) const
Definition nnm.hpp:9338
constexpr Vector3 transform(const Transform3< Real > &by, Real w=static_cast< Real >(1)) const
Definition nnm.hpp:9332
constexpr Vector3 direction_unnormalized(const Vector3 &to) const
Definition nnm.hpp:2467
constexpr Vector3 cross(const Vector3 &other) const
Definition nnm.hpp:2596
constexpr Vector3 project(const Vector3 &onto) const
Definition nnm.hpp:2628
constexpr Vector3 shear_y_at(const Vector3 &origin, Real factor_x, Real factor_z) const
Definition nnm.hpp:9290
constexpr float max() const
Definition nnm.hpp:2846
constexpr Vector3 transform_at(const Vector3 &origin, const Basis3< Real > &by) const
Definition nnm.hpp:9314
constexpr Vector3 operator*(const Matrix3< Real > &matrix) const
Definition nnm.hpp:9344
const Real * begin() const
Definition nnm.hpp:2984
constexpr Vector3 operator+(const Vector3 &other) const
Definition nnm.hpp:3121
constexpr Vector3 transform(const Transform2< Real > &by) const
Definition nnm.hpp:9320
Definition nnm.hpp:3337
constexpr Vector3i(const Vector2i< Int > &vector, const Int z)
Definition nnm.hpp:3371
constexpr Vector3i abs() const
Definition nnm.hpp:3450
constexpr Int abs_min() const
Definition nnm.hpp:3567
constexpr const Int & at(const uint8_t index) const
Definition nnm.hpp:3696
constexpr Vector3i & operator/=(const Int value)
Definition nnm.hpp:3921
constexpr Int manhattan_distance(const Vector3i &to) const
Definition nnm.hpp:3471
const Int * begin() const
Definition nnm.hpp:3659
constexpr Vector3i operator%(const Int value) const
Definition nnm.hpp:3957
constexpr Vector3i operator/(const Int value) const
Definition nnm.hpp:3911
static constexpr Vector3i zero()
Definition nnm.hpp:3405
constexpr uint8_t max_index() const
Definition nnm.hpp:3576
const Int * end() const
Definition nnm.hpp:3668
constexpr uint8_t abs_max_index() const
Definition nnm.hpp:3594
constexpr Vector3i & operator%=(const Vector3i &other)
Definition nnm.hpp:3944
constexpr Int & at(const uint8_t index)
Definition nnm.hpp:3716
int z
Definition nnm.hpp:3341
static constexpr Vector3i all(const Int value)
Definition nnm.hpp:3396
constexpr Vector3i operator/(const Vector3i &other) const
Definition nnm.hpp:3888
constexpr Vector3i & operator%=(const Int value)
Definition nnm.hpp:3967
constexpr Vector3i(const Vector3< Real > &vector)
Definition nnm.hpp:3359
constexpr bool perpendicular(const Vector3i &other) const
Definition nnm.hpp:3520
static constexpr Vector3i axis_y()
Definition nnm.hpp:3432
constexpr Vector3i operator+() const
Definition nnm.hpp:3979
constexpr int min() const
Definition nnm.hpp:3558
constexpr Int length_sqrd() const
Definition nnm.hpp:3480
constexpr Vector3i operator%(const Vector3i &other) const
Definition nnm.hpp:3934
constexpr Vector3i operator+(const Vector3i &other) const
Definition nnm.hpp:3796
constexpr Vector3i operator*(const Int value) const
Definition nnm.hpp:3865
constexpr Vector3i & operator+=(const Vector3i &other)
Definition nnm.hpp:3806
constexpr Int abs_max() const
Definition nnm.hpp:3549
constexpr Vector3i & operator*=(const Vector3i &other)
Definition nnm.hpp:3852
constexpr Vector3i(const Int x, const Int y, const Int z)
Definition nnm.hpp:3384
constexpr Vector3i cross(const Vector3i &other) const
Definition nnm.hpp:3500
constexpr Vector3i clamp(const Vector3i &min, const Vector3i &max) const
Definition nnm.hpp:3461
constexpr Vector3i()
Definition nnm.hpp:3346
constexpr bool operator==(const Vector3i &other) const
Definition nnm.hpp:3776
constexpr Vector3i & operator*=(const Int value)
Definition nnm.hpp:3875
static constexpr Vector3i one()
Definition nnm.hpp:3414
static constexpr Vector3i axis_x()
Definition nnm.hpp:3423
int x
Definition nnm.hpp:3339
constexpr Vector3i operator-() const
Definition nnm.hpp:3988
constexpr bool parallel(const Vector3i &other) const
Definition nnm.hpp:3510
constexpr Vector3i & operator-=(const Vector3i &other)
Definition nnm.hpp:3829
Int * begin()
Definition nnm.hpp:3677
constexpr int max() const
Definition nnm.hpp:3540
constexpr const Int & operator[](const uint8_t index) const
Definition nnm.hpp:3736
constexpr Vector2i< Int > xy() const
Definition nnm.hpp:3650
constexpr Int & operator[](const uint8_t index)
Definition nnm.hpp:3756
constexpr Vector3i & operator/=(const Vector3i &other)
Definition nnm.hpp:3898
constexpr Vector3i operator*(const Vector3i &other) const
Definition nnm.hpp:3842
static constexpr Vector3i axis_z()
Definition nnm.hpp:3441
constexpr bool operator!=(const Vector3i &other) const
Definition nnm.hpp:3786
constexpr Vector3i operator-(const Vector3i &other) const
Definition nnm.hpp:3819
constexpr uint8_t abs_min_index() const
Definition nnm.hpp:3631
constexpr bool operator<(const Vector3i &other) const
Definition nnm.hpp:3998
int y
Definition nnm.hpp:3340
Int * end()
Definition nnm.hpp:3686
constexpr uint8_t min_index() const
Definition nnm.hpp:3613
constexpr Vector3i arbitrary_perpendicular() const
Definition nnm.hpp:3530
constexpr Int dot(const Vector3i &other) const
Definition nnm.hpp:3490
Definition nnm.hpp:4078
constexpr const Real & operator[](const uint8_t index) const
Definition nnm.hpp:4643
constexpr Real abs_min() const
Definition nnm.hpp:4427
Vector4 floor() const
Definition nnm.hpp:4245
const Real * end() const
Definition nnm.hpp:4571
constexpr float min() const
Definition nnm.hpp:4418
float x
Definition nnm.hpp:4080
constexpr Vector4 operator+(const Vector4 &other) const
Definition nnm.hpp:4707
constexpr Real dot(const Vector4 &other) const
Definition nnm.hpp:4358
constexpr Vector4 operator*(const Vector4 &other) const
Definition nnm.hpp:4755
Real length() const
Definition nnm.hpp:4286
constexpr Vector2< Real > xy() const
Definition nnm.hpp:4544
constexpr float max() const
Definition nnm.hpp:4400
constexpr Vector4 & operator+=(const Vector4 &other)
Definition nnm.hpp:4717
constexpr uint8_t max_index() const
Definition nnm.hpp:4436
constexpr Vector4 abs() const
Definition nnm.hpp:4227
Real * begin()
Definition nnm.hpp:4580
static constexpr Vector4 one()
Definition nnm.hpp:4182
constexpr Vector4 & operator*=(const Vector4 &other)
Definition nnm.hpp:4765
constexpr bool operator!=(const Vector4 &other) const
Definition nnm.hpp:4697
constexpr Real & at(const uint8_t index)
Definition nnm.hpp:4621
Real * end()
Definition nnm.hpp:4589
constexpr Real abs_max() const
Definition nnm.hpp:4409
static constexpr Vector4 axis_w()
Definition nnm.hpp:4218
constexpr Vector4 operator-(const Vector4 &other) const
Definition nnm.hpp:4731
static constexpr Vector4 from_quaternion(const Quaternion< Real > &quaternion)
Definition nnm.hpp:9356
constexpr Matrix4< Real > outer(const Vector4 &other) const
Definition nnm.hpp:9362
constexpr uint8_t min_index() const
Definition nnm.hpp:4478
constexpr Vector4 operator/(const Vector4 &other) const
Definition nnm.hpp:4810
Vector4 normalize() const
Definition nnm.hpp:4317
static constexpr Vector4 axis_z()
Definition nnm.hpp:4209
static constexpr Vector4 all(const Real value)
Definition nnm.hpp:4164
constexpr Vector4 & operator-=(const Vector4 &other)
Definition nnm.hpp:4741
constexpr Vector4 operator+() const
Definition nnm.hpp:4875
Vector4 round() const
Definition nnm.hpp:4254
constexpr Real & operator[](const uint8_t index)
Definition nnm.hpp:4665
static constexpr Vector4 axis_y()
Definition nnm.hpp:4200
constexpr Real length_sqrd() const
Definition nnm.hpp:4277
constexpr Vector4 lerp_clamped(const Vector4 &to, const Real weight) const
Definition nnm.hpp:4345
float z
Definition nnm.hpp:4082
constexpr Vector4()
Definition nnm.hpp:4088
constexpr uint8_t abs_max_index() const
Definition nnm.hpp:4454
constexpr const Real & at(const uint8_t index) const
Definition nnm.hpp:4599
constexpr Vector4 & operator/=(const Real value)
Definition nnm.hpp:4844
constexpr bool operator==(const Vector4 &other) const
Definition nnm.hpp:4687
constexpr bool operator<(const Vector4 &other) const
Definition nnm.hpp:4858
static constexpr Vector4 zero()
Definition nnm.hpp:4173
constexpr Vector4 & operator*=(const Real value)
Definition nnm.hpp:4796
constexpr Vector4 transform(const Transform3< Real > &by) const
Definition nnm.hpp:9374
constexpr Vector4 lerp(const Vector4 &to, const Real weight) const
Definition nnm.hpp:4331
constexpr Vector4 operator-() const
Definition nnm.hpp:4884
constexpr Vector4 inverse() const
Definition nnm.hpp:4374
constexpr Vector4 clamp(const Vector4 &min, const Vector4 &max) const
Definition nnm.hpp:4265
static constexpr Vector4 axis_x()
Definition nnm.hpp:4191
constexpr Vector4 operator*(const Matrix4< Real > &matrix) const
Definition nnm.hpp:9386
constexpr Vector4(const Vector3< Real > &vector, const Real w)
Definition nnm.hpp:4129
constexpr Vector4(const Vector2< Real > &vector, const Real z, const Real w)
Definition nnm.hpp:4116
float y
Definition nnm.hpp:4081
constexpr Vector4 operator*(const Real value) const
Definition nnm.hpp:4786
constexpr Vector4(const Real x, const Real y, const Real z, const Real w)
Definition nnm.hpp:4144
constexpr Vector4 & operator/=(const Vector4 &other)
Definition nnm.hpp:4820
const Real * begin() const
Definition nnm.hpp:4562
constexpr Vector4 transform_at(const Vector3< Real > &origin, const Transform3< Real > &by) const
Definition nnm.hpp:9380
constexpr bool approx_zero() const
Definition nnm.hpp:4535
Vector4 ceil() const
Definition nnm.hpp:4236
float w
Definition nnm.hpp:4083
constexpr Vector4(const Vector4< Other > &vector)
Definition nnm.hpp:4102
constexpr bool approx_equal(const Vector4 &other) const
Definition nnm.hpp:4525
constexpr Vector3< Real > xyz() const
Definition nnm.hpp:4553
Vector4 clamp_length(const Real min, const Real max) const
Definition nnm.hpp:4297
constexpr uint8_t abs_min_index() const
Definition nnm.hpp:4500
constexpr Vector4 operator/(const Real value) const
Definition nnm.hpp:4834
Definition nnm.hpp:26
constexpr Num max(const Num a, const Num b)
Definition nnm.hpp:88
Vector3i< uint32_t > Vector3u32
Definition nnm.hpp:645
constexpr Num abs(const Num value)
Definition nnm.hpp:72
constexpr bool approx_equal(const Real a, const Real b)
Definition nnm.hpp:134
constexpr Num clamp(const Num value, const Num min, const Num max)
Definition nnm.hpp:265
constexpr Real lerp(const Real from, const Real to, const Real weight)
Definition nnm.hpp:425
Vector2i< uint64_t > Vector2u64
Definition nnm.hpp:630
Vector3< float > Vector3f
Definition nnm.hpp:633
Vector4< double > Vector4d
Definition nnm.hpp:650
Real acos(const Real value)
Definition nnm.hpp:566
Vector2i< int > Vector2ii
Definition nnm.hpp:621
constexpr bool approx_less(const Real a, const Real b)
Definition nnm.hpp:152
constexpr bool approx_less_zero(const Real value)
Definition nnm.hpp:203
Vector2< Real > constexpr operator*(const Real value, const Vector2< Real > &vector)
Definition nnm.hpp:1605
constexpr Real degrees(const Real radians)
Definition nnm.hpp:542
bool angle_in_range(const Real angle, const Real from, const Real to)
Definition nnm.hpp:395
constexpr Int mod(const Int dividend, const Int divisor)
Definition nnm.hpp:339
Quaternion< float > QuaternionF
Definition nnm.hpp:653
constexpr Num sqrd(const Num value)
Definition nnm.hpp:308
Basis3< float > Basis3f
Definition nnm.hpp:673
Vector2< double > Vector2d
Definition nnm.hpp:618
Vector3< double > Vector3d
Definition nnm.hpp:634
Vector3i< int64_t > Vector3i64
Definition nnm.hpp:641
constexpr Real epsilon()
Definition nnm.hpp:45
Vector2i< int32_t > Vector2i32
Definition nnm.hpp:624
Quaternion< double > QuaternionD
Definition nnm.hpp:654
Vector3i< uint8_t > Vector3u8
Definition nnm.hpp:643
Transform3< float > Transform3f
Definition nnm.hpp:681
Real pow(const Real base, const Real power)
Definition nnm.hpp:296
Vector2i< uint8_t > Vector2u8
Definition nnm.hpp:627
Real tan(const Real value)
Definition nnm.hpp:481
Real asin(const Real value)
Definition nnm.hpp:554
Vector2i< uint32_t > Vector2u32
Definition nnm.hpp:629
constexpr bool approx_greater_equal_zero(const Real value)
Definition nnm.hpp:239
Vector3i< int > Vector3ii
Definition nnm.hpp:637
constexpr Int rem(const Int dividend, const Int divisor)
Definition nnm.hpp:369
Vector2< Real > constexpr operator/(const Real value, const Vector2< Real > &vector)
Definition nnm.hpp:1618
constexpr bool approx_less_equal_zero(const Real value)
Definition nnm.hpp:227
Vector2i< int16_t > Vector2i16
Definition nnm.hpp:623
constexpr bool approx_greater(const Real a, const Real b)
Definition nnm.hpp:165
Matrix4< float > Matrix4f
Definition nnm.hpp:677
constexpr Num sign(const Num value)
Definition nnm.hpp:57
Real atan2(const Real y, const Real x)
Definition nnm.hpp:518
Real cos(const Real value)
Definition nnm.hpp:469
Transform2< double > Transform2d
Definition nnm.hpp:670
constexpr bool approx_greater_equal(const Real a, const Real b)
Definition nnm.hpp:191
constexpr Real radians(const Real degrees)
Definition nnm.hpp:530
Real sin(const Real value)
Definition nnm.hpp:457
Basis3< double > Basis3d
Definition nnm.hpp:674
Vector3i< uint16_t > Vector3u16
Definition nnm.hpp:644
Real log2(const Real value)
Definition nnm.hpp:610
Vector2i< uint16_t > Vector2u16
Definition nnm.hpp:628
Real floor(const Real value)
Definition nnm.hpp:411
constexpr bool approx_less_equal(const Real a, const Real b)
Definition nnm.hpp:178
Transform3< double > Transform3d
Definition nnm.hpp:682
Matrix4< double > Matrix4d
Definition nnm.hpp:678
Real modf(const Real dividend, const Real divisor)
Definition nnm.hpp:321
Real normalize_angle(const Real angle)
Definition nnm.hpp:381
Real atan(const Real value)
Definition nnm.hpp:505
Vector2i< int8_t > Vector2i8
Definition nnm.hpp:622
Vector3i< int16_t > Vector3i16
Definition nnm.hpp:639
Vector2i< unsigned int > Vector2iu
Definition nnm.hpp:626
Vector2< float > Vector2f
Definition nnm.hpp:617
Vector3i< int8_t > Vector3i8
Definition nnm.hpp:638
constexpr Real lerp_clamped(const Real from, const Real to, const Real weight)
Definition nnm.hpp:439
Vector3i< uint64_t > Vector3u64
Definition nnm.hpp:646
Basis2< double > Basis2d
Definition nnm.hpp:662
Matrix2< float > Matrix2f
Definition nnm.hpp:657
Real sqrt(const Real value)
Definition nnm.hpp:283
Matrix2< double > Matrix2d
Definition nnm.hpp:658
constexpr bool approx_zero(const Real value)
Definition nnm.hpp:119
Matrix3< double > Matrix3d
Definition nnm.hpp:666
Real remf(const Real dividend, const Real divisor)
Definition nnm.hpp:356
Basis2< float > Basis2f
Definition nnm.hpp:661
constexpr Vector2i< Int > operator%(const Int value, const Vector2i< Int > &vector)
Definition nnm.hpp:2278
constexpr Num min(const Num a, const Num b)
Definition nnm.hpp:579
Real ceil(const Real value)
Definition nnm.hpp:251
Matrix3< float > Matrix3f
Definition nnm.hpp:665
Vector4< float > Vector4f
Definition nnm.hpp:649
Vector2i< int64_t > Vector2i64
Definition nnm.hpp:625
Real round(const Real value)
Definition nnm.hpp:493
constexpr bool approx_greater_zero(const Real value)
Definition nnm.hpp:215
Vector3i< int32_t > Vector3i32
Definition nnm.hpp:640
Vector3i< unsigned int > Vector3iu
Definition nnm.hpp:642
constexpr Real pi()
Definition nnm.hpp:34
Transform2< float > Transform2f
Definition nnm.hpp:669
#define NNM_BOUNDS_CHECK_ASSERT(msg, expression)
Definition nnm.hpp:23
Definition nnm.hpp:2233
size_t operator()(const Vector2i &vector) const noexcept
Definition nnm.hpp:2234
Definition nnm.hpp:4022
size_t operator()(const Vector3i &vector) const noexcept
Definition nnm.hpp:4023