commit 4b3b38c
uint
·
2026-07-22 18:54:48 +0000 UTC
parent fe9b3a2
vendor HandmadeMath
1 files changed,
+3940,
-0
+3940,
-0
1@@ -0,0 +1,3940 @@
2+/*
3+ HandmadeMath.h v2.0.0
4+
5+ This is a single header file with a bunch of useful types and functions for
6+ games and graphics. Consider it a lightweight alternative to GLM that works
7+ both C and C++.
8+
9+ =============================================================================
10+ CONFIG
11+ =============================================================================
12+
13+ By default, all angles in Handmade Math are specified in radians. However, it
14+ can be configured to use degrees or turns instead. Use one of the following
15+ defines to specify the default unit for angles:
16+
17+ #define HANDMADE_MATH_USE_RADIANS
18+ #define HANDMADE_MATH_USE_DEGREES
19+ #define HANDMADE_MATH_USE_TURNS
20+
21+ Regardless of the default angle, you can use the following functions to
22+ specify an angle in a particular unit:
23+
24+ HMM_AngleRad(radians)
25+ HMM_AngleDeg(degrees)
26+ HMM_AngleTurn(turns)
27+
28+ The definitions of these functions change depending on the default unit.
29+
30+ -----------------------------------------------------------------------------
31+
32+ Handmade Math ships with SSE (SIMD) implementations of several common
33+ operations. To disable the use of SSE intrinsics, you must define
34+ HANDMADE_MATH_NO_SSE before including this file:
35+
36+ #define HANDMADE_MATH_NO_SSE
37+ #include "HandmadeMath.h"
38+
39+ -----------------------------------------------------------------------------
40+
41+ To use Handmade Math without the C runtime library, you must provide your own
42+ implementations of basic math functions. Otherwise, HandmadeMath.h will use
43+ the runtime library implementation of these functions.
44+
45+ Define HANDMADE_MATH_PROVIDE_MATH_FUNCTIONS and provide your own
46+ implementations of HMM_SINF, HMM_COSF, HMM_TANF, HMM_ACOSF, and HMM_SQRTF
47+ before including HandmadeMath.h, like so:
48+
49+ #define HANDMADE_MATH_PROVIDE_MATH_FUNCTIONS
50+ #define HMM_SINF MySinF
51+ #define HMM_COSF MyCosF
52+ #define HMM_TANF MyTanF
53+ #define HMM_ACOSF MyACosF
54+ #define HMM_SQRTF MySqrtF
55+ #include "HandmadeMath.h"
56+
57+ By default, it is assumed that your math functions take radians. To use
58+ different units, you must define HMM_ANGLE_USER_TO_INTERNAL and
59+ HMM_ANGLE_INTERNAL_TO_USER. For example, if you want to use degrees in your
60+ code but your math functions use turns:
61+
62+ #define HMM_ANGLE_USER_TO_INTERNAL(a) ((a)*HMM_DegToTurn)
63+ #define HMM_ANGLE_INTERNAL_TO_USER(a) ((a)*HMM_TurnToDeg)
64+
65+ =============================================================================
66+
67+ LICENSE
68+
69+ This software is in the public domain. Where that dedication is not
70+ recognized, you are granted a perpetual, irrevocable license to copy,
71+ distribute, and modify this file as you see fit.
72+
73+ =============================================================================
74+
75+ CREDITS
76+
77+ Originally written by Zakary Strange.
78+
79+ Functionality:
80+ Zakary Strange (strangezak@protonmail.com && @strangezak)
81+ Matt Mascarenhas (@miblo_)
82+ Aleph
83+ FieryDrake (@fierydrake)
84+ Gingerbill (@TheGingerBill)
85+ Ben Visness (@bvisness)
86+ Trinton Bullard (@Peliex_Dev)
87+ @AntonDan
88+ Logan Forman (@dev_dwarf)
89+
90+ Fixes:
91+ Jeroen van Rijn (@J_vanRijn)
92+ Kiljacken (@Kiljacken)
93+ Insofaras (@insofaras)
94+ Daniel Gibson (@DanielGibson)
95+*/
96+
97+#ifndef HANDMADE_MATH_H
98+#define HANDMADE_MATH_H
99+
100+// Dummy macros for when test framework is not present.
101+#ifndef COVERAGE
102+# define COVERAGE(a, b)
103+#endif
104+
105+#ifndef ASSERT_COVERED
106+# define ASSERT_COVERED(a)
107+#endif
108+
109+#ifdef HANDMADE_MATH_NO_SSE
110+# warning "HANDMADE_MATH_NO_SSE is deprecated, use HANDMADE_MATH_NO_SIMD instead"
111+# define HANDMADE_MATH_NO_SIMD
112+#endif
113+
114+/* let's figure out if SSE is really available (unless disabled anyway)
115+ (it isn't on non-x86/x86_64 platforms or even x86 without explicit SSE support)
116+ => only use "#ifdef HANDMADE_MATH__USE_SSE" to check for SSE support below this block! */
117+#ifndef HANDMADE_MATH_NO_SIMD
118+# ifdef _MSC_VER /* MSVC supports SSE in amd64 mode or _M_IX86_FP >= 1 (2 means SSE2) */
119+# if defined(_M_AMD64) || ( defined(_M_IX86_FP) && _M_IX86_FP >= 1 )
120+# define HANDMADE_MATH__USE_SSE 1
121+# endif
122+# else /* not MSVC, probably GCC, clang, icc or something that doesn't support SSE anyway */
123+# ifdef __SSE__ /* they #define __SSE__ if it's supported */
124+# define HANDMADE_MATH__USE_SSE 1
125+# endif /* __SSE__ */
126+# endif /* not _MSC_VER */
127+# ifdef __ARM_NEON
128+# define HANDMADE_MATH__USE_NEON 1
129+# endif /* NEON Supported */
130+#endif /* #ifndef HANDMADE_MATH_NO_SIMD */
131+
132+#if (!defined(__cplusplus) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
133+# define HANDMADE_MATH__USE_C11_GENERICS 1
134+#endif
135+
136+#ifdef HANDMADE_MATH__USE_SSE
137+# include <xmmintrin.h>
138+#endif
139+
140+#ifdef HANDMADE_MATH__USE_NEON
141+# include <arm_neon.h>
142+#endif
143+
144+#ifdef _MSC_VER
145+#pragma warning(disable:4201)
146+#endif
147+
148+#if defined(__GNUC__) || defined(__clang__)
149+# pragma GCC diagnostic push
150+# pragma GCC diagnostic ignored "-Wfloat-equal"
151+# pragma GCC diagnostic ignored "-Wmissing-braces"
152+# ifdef __clang__
153+# pragma GCC diagnostic ignored "-Wgnu-anonymous-struct"
154+# pragma GCC diagnostic ignored "-Wnested-anon-types"
155+# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
156+# endif
157+#endif
158+
159+#if defined(__GNUC__) || defined(__clang__)
160+# define HMM_DEPRECATED(msg) __attribute__((deprecated(msg)))
161+#elif defined(_MSC_VER)
162+# define HMM_DEPRECATED(msg) __declspec(deprecated(msg))
163+#else
164+# define HMM_DEPRECATED(msg)
165+#endif
166+
167+#ifdef __cplusplus
168+extern "C"
169+{
170+#endif
171+
172+#if !defined(HANDMADE_MATH_USE_DEGREES) \
173+ && !defined(HANDMADE_MATH_USE_TURNS) \
174+ && !defined(HANDMADE_MATH_USE_RADIANS)
175+# define HANDMADE_MATH_USE_RADIANS
176+#endif
177+
178+#define HMM_PI 3.14159265358979323846
179+#define HMM_PI32 3.14159265359f
180+#define HMM_DEG180 180.0
181+#define HMM_DEG18032 180.0f
182+#define HMM_TURNHALF 0.5
183+#define HMM_TURNHALF32 0.5f
184+#define HMM_RadToDeg ((float)(HMM_DEG180/HMM_PI))
185+#define HMM_RadToTurn ((float)(HMM_TURNHALF/HMM_PI))
186+#define HMM_DegToRad ((float)(HMM_PI/HMM_DEG180))
187+#define HMM_DegToTurn ((float)(HMM_TURNHALF/HMM_DEG180))
188+#define HMM_TurnToRad ((float)(HMM_PI/HMM_TURNHALF))
189+#define HMM_TurnToDeg ((float)(HMM_DEG180/HMM_TURNHALF))
190+
191+#if defined(HANDMADE_MATH_USE_RADIANS)
192+# define HMM_AngleRad(a) (a)
193+# define HMM_AngleDeg(a) ((a)*HMM_DegToRad)
194+# define HMM_AngleTurn(a) ((a)*HMM_TurnToRad)
195+#elif defined(HANDMADE_MATH_USE_DEGREES)
196+# define HMM_AngleRad(a) ((a)*HMM_RadToDeg)
197+# define HMM_AngleDeg(a) (a)
198+# define HMM_AngleTurn(a) ((a)*HMM_TurnToDeg)
199+#elif defined(HANDMADE_MATH_USE_TURNS)
200+# define HMM_AngleRad(a) ((a)*HMM_RadToTurn)
201+# define HMM_AngleDeg(a) ((a)*HMM_DegToTurn)
202+# define HMM_AngleTurn(a) (a)
203+#endif
204+
205+#if !defined(HANDMADE_MATH_PROVIDE_MATH_FUNCTIONS)
206+# include <math.h>
207+# define HMM_SINF sinf
208+# define HMM_COSF cosf
209+# define HMM_TANF tanf
210+# define HMM_SQRTF sqrtf
211+# define HMM_ACOSF acosf
212+#endif
213+
214+#if !defined(HMM_ANGLE_USER_TO_INTERNAL)
215+# define HMM_ANGLE_USER_TO_INTERNAL(a) (HMM_ToRad(a))
216+#endif
217+
218+#if !defined(HMM_ANGLE_INTERNAL_TO_USER)
219+# if defined(HANDMADE_MATH_USE_RADIANS)
220+# define HMM_ANGLE_INTERNAL_TO_USER(a) (a)
221+# elif defined(HANDMADE_MATH_USE_DEGREES)
222+# define HMM_ANGLE_INTERNAL_TO_USER(a) ((a)*HMM_RadToDeg)
223+# elif defined(HANDMADE_MATH_USE_TURNS)
224+# define HMM_ANGLE_INTERNAL_TO_USER(a) ((a)*HMM_RadToTurn)
225+# endif
226+#endif
227+
228+#define HMM_MIN(a, b) ((a) > (b) ? (b) : (a))
229+#define HMM_MAX(a, b) ((a) < (b) ? (b) : (a))
230+#define HMM_ABS(a) ((a) > 0 ? (a) : -(a))
231+#define HMM_MOD(a, m) (((a) % (m)) >= 0 ? ((a) % (m)) : (((a) % (m)) + (m)))
232+#define HMM_SQUARE(x) ((x) * (x))
233+
234+typedef union HMM_Vec2
235+{
236+ struct
237+ {
238+ float X, Y;
239+ };
240+
241+ struct
242+ {
243+ float U, V;
244+ };
245+
246+ struct
247+ {
248+ float Left, Right;
249+ };
250+
251+ struct
252+ {
253+ float Width, Height;
254+ };
255+
256+ float Elements[2];
257+
258+#ifdef __cplusplus
259+ inline float &operator[](int Index) { return Elements[Index]; }
260+ inline const float &operator[](int Index) const { return Elements[Index]; }
261+#endif
262+} HMM_Vec2;
263+
264+typedef union HMM_Vec3
265+{
266+ struct
267+ {
268+ float X, Y, Z;
269+ };
270+
271+ struct
272+ {
273+ float U, V, W;
274+ };
275+
276+ struct
277+ {
278+ float R, G, B;
279+ };
280+
281+ struct
282+ {
283+ HMM_Vec2 XY;
284+ float _Ignored0;
285+ };
286+
287+ struct
288+ {
289+ float _Ignored1;
290+ HMM_Vec2 YZ;
291+ };
292+
293+ struct
294+ {
295+ HMM_Vec2 UV;
296+ float _Ignored2;
297+ };
298+
299+ struct
300+ {
301+ float _Ignored3;
302+ HMM_Vec2 VW;
303+ };
304+
305+ float Elements[3];
306+
307+#ifdef __cplusplus
308+ inline float &operator[](int Index) { return Elements[Index]; }
309+ inline const float &operator[](int Index) const { return Elements[Index]; }
310+#endif
311+} HMM_Vec3;
312+
313+typedef union HMM_Vec4
314+{
315+ struct
316+ {
317+ union
318+ {
319+ HMM_Vec3 XYZ;
320+ struct
321+ {
322+ float X, Y, Z;
323+ };
324+ };
325+
326+ float W;
327+ };
328+ struct
329+ {
330+ union
331+ {
332+ HMM_Vec3 RGB;
333+ struct
334+ {
335+ float R, G, B;
336+ };
337+ };
338+
339+ float A;
340+ };
341+
342+ struct
343+ {
344+ HMM_Vec2 XY;
345+ float _Ignored0;
346+ float _Ignored1;
347+ };
348+
349+ struct
350+ {
351+ float _Ignored2;
352+ HMM_Vec2 YZ;
353+ float _Ignored3;
354+ };
355+
356+ struct
357+ {
358+ float _Ignored4;
359+ float _Ignored5;
360+ HMM_Vec2 ZW;
361+ };
362+
363+ float Elements[4];
364+
365+#ifdef HANDMADE_MATH__USE_SSE
366+ __m128 SSE;
367+#endif
368+
369+#ifdef HANDMADE_MATH__USE_NEON
370+ float32x4_t NEON;
371+#endif
372+
373+#ifdef __cplusplus
374+ inline float &operator[](int Index) { return Elements[Index]; }
375+ inline const float &operator[](int Index) const { return Elements[Index]; }
376+#endif
377+} HMM_Vec4;
378+
379+typedef union HMM_Mat2
380+{
381+ float Elements[2][2];
382+ HMM_Vec2 Columns[2];
383+
384+#ifdef __cplusplus
385+ inline HMM_Vec2 &operator[](int Index) { return Columns[Index]; }
386+ inline const HMM_Vec2 &operator[](int Index) const { return Columns[Index]; }
387+#endif
388+} HMM_Mat2;
389+
390+typedef union HMM_Mat3
391+{
392+ float Elements[3][3];
393+ HMM_Vec3 Columns[3];
394+
395+#ifdef __cplusplus
396+ inline HMM_Vec3 &operator[](int Index) { return Columns[Index]; }
397+ inline const HMM_Vec3 &operator[](int Index) const { return Columns[Index]; }
398+#endif
399+} HMM_Mat3;
400+
401+typedef union HMM_Mat4
402+{
403+ float Elements[4][4];
404+ HMM_Vec4 Columns[4];
405+
406+#ifdef __cplusplus
407+ inline HMM_Vec4 &operator[](int Index) { return Columns[Index]; }
408+ inline const HMM_Vec4 &operator[](int Index) const { return Columns[Index]; }
409+#endif
410+} HMM_Mat4;
411+
412+typedef union HMM_Quat
413+{
414+ struct
415+ {
416+ union
417+ {
418+ HMM_Vec3 XYZ;
419+ struct
420+ {
421+ float X, Y, Z;
422+ };
423+ };
424+
425+ float W;
426+ };
427+
428+ float Elements[4];
429+
430+#ifdef HANDMADE_MATH__USE_SSE
431+ __m128 SSE;
432+#endif
433+#ifdef HANDMADE_MATH__USE_NEON
434+ float32x4_t NEON;
435+#endif
436+} HMM_Quat;
437+
438+typedef signed int HMM_Bool;
439+
440+/*
441+ * Angle unit conversion functions
442+ */
443+static inline float HMM_ToRad(float Angle)
444+{
445+#if defined(HANDMADE_MATH_USE_RADIANS)
446+ float Result = Angle;
447+#elif defined(HANDMADE_MATH_USE_DEGREES)
448+ float Result = Angle * HMM_DegToRad;
449+#elif defined(HANDMADE_MATH_USE_TURNS)
450+ float Result = Angle * HMM_TurnToRad;
451+#endif
452+
453+ return Result;
454+}
455+
456+static inline float HMM_ToDeg(float Angle)
457+{
458+#if defined(HANDMADE_MATH_USE_RADIANS)
459+ float Result = Angle * HMM_RadToDeg;
460+#elif defined(HANDMADE_MATH_USE_DEGREES)
461+ float Result = Angle;
462+#elif defined(HANDMADE_MATH_USE_TURNS)
463+ float Result = Angle * HMM_TurnToDeg;
464+#endif
465+
466+ return Result;
467+}
468+
469+static inline float HMM_ToTurn(float Angle)
470+{
471+#if defined(HANDMADE_MATH_USE_RADIANS)
472+ float Result = Angle * HMM_RadToTurn;
473+#elif defined(HANDMADE_MATH_USE_DEGREES)
474+ float Result = Angle * HMM_DegToTurn;
475+#elif defined(HANDMADE_MATH_USE_TURNS)
476+ float Result = Angle;
477+#endif
478+
479+ return Result;
480+}
481+
482+/*
483+ * Floating-point math functions
484+ */
485+
486+COVERAGE(HMM_SinF, 1)
487+static inline float HMM_SinF(float Angle)
488+{
489+ ASSERT_COVERED(HMM_SinF);
490+ return HMM_SINF(HMM_ANGLE_USER_TO_INTERNAL(Angle));
491+}
492+
493+COVERAGE(HMM_CosF, 1)
494+static inline float HMM_CosF(float Angle)
495+{
496+ ASSERT_COVERED(HMM_CosF);
497+ return HMM_COSF(HMM_ANGLE_USER_TO_INTERNAL(Angle));
498+}
499+
500+COVERAGE(HMM_TanF, 1)
501+static inline float HMM_TanF(float Angle)
502+{
503+ ASSERT_COVERED(HMM_TanF);
504+ return HMM_TANF(HMM_ANGLE_USER_TO_INTERNAL(Angle));
505+}
506+
507+COVERAGE(HMM_ACosF, 1)
508+static inline float HMM_ACosF(float Arg)
509+{
510+ ASSERT_COVERED(HMM_ACosF);
511+ return HMM_ANGLE_INTERNAL_TO_USER(HMM_ACOSF(Arg));
512+}
513+
514+COVERAGE(HMM_SqrtF, 1)
515+static inline float HMM_SqrtF(float Float)
516+{
517+ ASSERT_COVERED(HMM_SqrtF);
518+
519+ float Result;
520+
521+#ifdef HANDMADE_MATH__USE_SSE
522+ __m128 In = _mm_set_ss(Float);
523+ __m128 Out = _mm_sqrt_ss(In);
524+ Result = _mm_cvtss_f32(Out);
525+#elif defined(HANDMADE_MATH__USE_NEON)
526+ float32x4_t In = vdupq_n_f32(Float);
527+ float32x4_t Out = vsqrtq_f32(In);
528+ Result = vgetq_lane_f32(Out, 0);
529+#else
530+ Result = HMM_SQRTF(Float);
531+#endif
532+
533+ return Result;
534+}
535+
536+COVERAGE(HMM_InvSqrtF, 1)
537+static inline float HMM_InvSqrtF(float Float)
538+{
539+ ASSERT_COVERED(HMM_InvSqrtF);
540+
541+ float Result;
542+
543+ Result = 1.0f/HMM_SqrtF(Float);
544+
545+ return Result;
546+}
547+
548+
549+/*
550+ * Utility functions
551+ */
552+
553+COVERAGE(HMM_Lerp, 1)
554+static inline float HMM_Lerp(float A, float Time, float B)
555+{
556+ ASSERT_COVERED(HMM_Lerp);
557+ return (1.0f - Time) * A + Time * B;
558+}
559+
560+COVERAGE(HMM_Clamp, 1)
561+static inline float HMM_Clamp(float Min, float Value, float Max)
562+{
563+ ASSERT_COVERED(HMM_Clamp);
564+
565+ float Result = Value;
566+
567+ if (Result < Min)
568+ {
569+ Result = Min;
570+ }
571+
572+ if (Result > Max)
573+ {
574+ Result = Max;
575+ }
576+
577+ return Result;
578+}
579+
580+
581+/*
582+ * Vector initialization
583+ */
584+
585+COVERAGE(HMM_V2, 1)
586+static inline HMM_Vec2 HMM_V2(float X, float Y)
587+{
588+ ASSERT_COVERED(HMM_V2);
589+
590+ HMM_Vec2 Result;
591+ Result.X = X;
592+ Result.Y = Y;
593+
594+ return Result;
595+}
596+
597+COVERAGE(HMM_V3, 1)
598+static inline HMM_Vec3 HMM_V3(float X, float Y, float Z)
599+{
600+ ASSERT_COVERED(HMM_V3);
601+
602+ HMM_Vec3 Result;
603+ Result.X = X;
604+ Result.Y = Y;
605+ Result.Z = Z;
606+
607+ return Result;
608+}
609+
610+COVERAGE(HMM_V4, 1)
611+static inline HMM_Vec4 HMM_V4(float X, float Y, float Z, float W)
612+{
613+ ASSERT_COVERED(HMM_V4);
614+
615+ HMM_Vec4 Result;
616+
617+#ifdef HANDMADE_MATH__USE_SSE
618+ Result.SSE = _mm_setr_ps(X, Y, Z, W);
619+#elif defined(HANDMADE_MATH__USE_NEON)
620+ float32x4_t v = {X, Y, Z, W};
621+ Result.NEON = v;
622+#else
623+ Result.X = X;
624+ Result.Y = Y;
625+ Result.Z = Z;
626+ Result.W = W;
627+#endif
628+
629+ return Result;
630+}
631+
632+COVERAGE(HMM_V4V, 1)
633+static inline HMM_Vec4 HMM_V4V(HMM_Vec3 Vector, float W)
634+{
635+ ASSERT_COVERED(HMM_V4V);
636+
637+ HMM_Vec4 Result;
638+
639+#ifdef HANDMADE_MATH__USE_SSE
640+ Result.SSE = _mm_setr_ps(Vector.X, Vector.Y, Vector.Z, W);
641+#elif defined(HANDMADE_MATH__USE_NEON)
642+ float32x4_t v = {Vector.X, Vector.Y, Vector.Z, W};
643+ Result.NEON = v;
644+#else
645+ Result.XYZ = Vector;
646+ Result.W = W;
647+#endif
648+
649+ return Result;
650+}
651+
652+
653+/*
654+ * Binary vector operations
655+ */
656+
657+COVERAGE(HMM_AddV2, 1)
658+static inline HMM_Vec2 HMM_AddV2(HMM_Vec2 Left, HMM_Vec2 Right)
659+{
660+ ASSERT_COVERED(HMM_AddV2);
661+
662+ HMM_Vec2 Result;
663+ Result.X = Left.X + Right.X;
664+ Result.Y = Left.Y + Right.Y;
665+
666+ return Result;
667+}
668+
669+COVERAGE(HMM_AddV3, 1)
670+static inline HMM_Vec3 HMM_AddV3(HMM_Vec3 Left, HMM_Vec3 Right)
671+{
672+ ASSERT_COVERED(HMM_AddV3);
673+
674+ HMM_Vec3 Result;
675+ Result.X = Left.X + Right.X;
676+ Result.Y = Left.Y + Right.Y;
677+ Result.Z = Left.Z + Right.Z;
678+
679+ return Result;
680+}
681+
682+COVERAGE(HMM_AddV4, 1)
683+static inline HMM_Vec4 HMM_AddV4(HMM_Vec4 Left, HMM_Vec4 Right)
684+{
685+ ASSERT_COVERED(HMM_AddV4);
686+
687+ HMM_Vec4 Result;
688+
689+#ifdef HANDMADE_MATH__USE_SSE
690+ Result.SSE = _mm_add_ps(Left.SSE, Right.SSE);
691+#elif defined(HANDMADE_MATH__USE_NEON)
692+ Result.NEON = vaddq_f32(Left.NEON, Right.NEON);
693+#else
694+ Result.X = Left.X + Right.X;
695+ Result.Y = Left.Y + Right.Y;
696+ Result.Z = Left.Z + Right.Z;
697+ Result.W = Left.W + Right.W;
698+#endif
699+
700+ return Result;
701+}
702+
703+COVERAGE(HMM_SubV2, 1)
704+static inline HMM_Vec2 HMM_SubV2(HMM_Vec2 Left, HMM_Vec2 Right)
705+{
706+ ASSERT_COVERED(HMM_SubV2);
707+
708+ HMM_Vec2 Result;
709+ Result.X = Left.X - Right.X;
710+ Result.Y = Left.Y - Right.Y;
711+
712+ return Result;
713+}
714+
715+COVERAGE(HMM_SubV3, 1)
716+static inline HMM_Vec3 HMM_SubV3(HMM_Vec3 Left, HMM_Vec3 Right)
717+{
718+ ASSERT_COVERED(HMM_SubV3);
719+
720+ HMM_Vec3 Result;
721+ Result.X = Left.X - Right.X;
722+ Result.Y = Left.Y - Right.Y;
723+ Result.Z = Left.Z - Right.Z;
724+
725+ return Result;
726+}
727+
728+COVERAGE(HMM_SubV4, 1)
729+static inline HMM_Vec4 HMM_SubV4(HMM_Vec4 Left, HMM_Vec4 Right)
730+{
731+ ASSERT_COVERED(HMM_SubV4);
732+
733+ HMM_Vec4 Result;
734+
735+#ifdef HANDMADE_MATH__USE_SSE
736+ Result.SSE = _mm_sub_ps(Left.SSE, Right.SSE);
737+#elif defined(HANDMADE_MATH__USE_NEON)
738+ Result.NEON = vsubq_f32(Left.NEON, Right.NEON);
739+#else
740+ Result.X = Left.X - Right.X;
741+ Result.Y = Left.Y - Right.Y;
742+ Result.Z = Left.Z - Right.Z;
743+ Result.W = Left.W - Right.W;
744+#endif
745+
746+ return Result;
747+}
748+
749+COVERAGE(HMM_MulV2, 1)
750+static inline HMM_Vec2 HMM_MulV2(HMM_Vec2 Left, HMM_Vec2 Right)
751+{
752+ ASSERT_COVERED(HMM_MulV2);
753+
754+ HMM_Vec2 Result;
755+ Result.X = Left.X * Right.X;
756+ Result.Y = Left.Y * Right.Y;
757+
758+ return Result;
759+}
760+
761+COVERAGE(HMM_MulV2F, 1)
762+static inline HMM_Vec2 HMM_MulV2F(HMM_Vec2 Left, float Right)
763+{
764+ ASSERT_COVERED(HMM_MulV2F);
765+
766+ HMM_Vec2 Result;
767+ Result.X = Left.X * Right;
768+ Result.Y = Left.Y * Right;
769+
770+ return Result;
771+}
772+
773+COVERAGE(HMM_MulV3, 1)
774+static inline HMM_Vec3 HMM_MulV3(HMM_Vec3 Left, HMM_Vec3 Right)
775+{
776+ ASSERT_COVERED(HMM_MulV3);
777+
778+ HMM_Vec3 Result;
779+ Result.X = Left.X * Right.X;
780+ Result.Y = Left.Y * Right.Y;
781+ Result.Z = Left.Z * Right.Z;
782+
783+ return Result;
784+}
785+
786+COVERAGE(HMM_MulV3F, 1)
787+static inline HMM_Vec3 HMM_MulV3F(HMM_Vec3 Left, float Right)
788+{
789+ ASSERT_COVERED(HMM_MulV3F);
790+
791+ HMM_Vec3 Result;
792+ Result.X = Left.X * Right;
793+ Result.Y = Left.Y * Right;
794+ Result.Z = Left.Z * Right;
795+
796+ return Result;
797+}
798+
799+COVERAGE(HMM_MulV4, 1)
800+static inline HMM_Vec4 HMM_MulV4(HMM_Vec4 Left, HMM_Vec4 Right)
801+{
802+ ASSERT_COVERED(HMM_MulV4);
803+
804+ HMM_Vec4 Result;
805+
806+#ifdef HANDMADE_MATH__USE_SSE
807+ Result.SSE = _mm_mul_ps(Left.SSE, Right.SSE);
808+#elif defined(HANDMADE_MATH__USE_NEON)
809+ Result.NEON = vmulq_f32(Left.NEON, Right.NEON);
810+#else
811+ Result.X = Left.X * Right.X;
812+ Result.Y = Left.Y * Right.Y;
813+ Result.Z = Left.Z * Right.Z;
814+ Result.W = Left.W * Right.W;
815+#endif
816+
817+ return Result;
818+}
819+
820+COVERAGE(HMM_MulV4F, 1)
821+static inline HMM_Vec4 HMM_MulV4F(HMM_Vec4 Left, float Right)
822+{
823+ ASSERT_COVERED(HMM_MulV4F);
824+
825+ HMM_Vec4 Result;
826+
827+#ifdef HANDMADE_MATH__USE_SSE
828+ __m128 Scalar = _mm_set1_ps(Right);
829+ Result.SSE = _mm_mul_ps(Left.SSE, Scalar);
830+#elif defined(HANDMADE_MATH__USE_NEON)
831+ Result.NEON = vmulq_n_f32(Left.NEON, Right);
832+#else
833+ Result.X = Left.X * Right;
834+ Result.Y = Left.Y * Right;
835+ Result.Z = Left.Z * Right;
836+ Result.W = Left.W * Right;
837+#endif
838+
839+ return Result;
840+}
841+
842+COVERAGE(HMM_DivV2, 1)
843+static inline HMM_Vec2 HMM_DivV2(HMM_Vec2 Left, HMM_Vec2 Right)
844+{
845+ ASSERT_COVERED(HMM_DivV2);
846+
847+ HMM_Vec2 Result;
848+ Result.X = Left.X / Right.X;
849+ Result.Y = Left.Y / Right.Y;
850+
851+ return Result;
852+}
853+
854+COVERAGE(HMM_DivV2F, 1)
855+static inline HMM_Vec2 HMM_DivV2F(HMM_Vec2 Left, float Right)
856+{
857+ ASSERT_COVERED(HMM_DivV2F);
858+
859+ HMM_Vec2 Result;
860+ Result.X = Left.X / Right;
861+ Result.Y = Left.Y / Right;
862+
863+ return Result;
864+}
865+
866+COVERAGE(HMM_DivV3, 1)
867+static inline HMM_Vec3 HMM_DivV3(HMM_Vec3 Left, HMM_Vec3 Right)
868+{
869+ ASSERT_COVERED(HMM_DivV3);
870+
871+ HMM_Vec3 Result;
872+ Result.X = Left.X / Right.X;
873+ Result.Y = Left.Y / Right.Y;
874+ Result.Z = Left.Z / Right.Z;
875+
876+ return Result;
877+}
878+
879+COVERAGE(HMM_DivV3F, 1)
880+static inline HMM_Vec3 HMM_DivV3F(HMM_Vec3 Left, float Right)
881+{
882+ ASSERT_COVERED(HMM_DivV3F);
883+
884+ HMM_Vec3 Result;
885+ Result.X = Left.X / Right;
886+ Result.Y = Left.Y / Right;
887+ Result.Z = Left.Z / Right;
888+
889+ return Result;
890+}
891+
892+COVERAGE(HMM_DivV4, 1)
893+static inline HMM_Vec4 HMM_DivV4(HMM_Vec4 Left, HMM_Vec4 Right)
894+{
895+ ASSERT_COVERED(HMM_DivV4);
896+
897+ HMM_Vec4 Result;
898+
899+#ifdef HANDMADE_MATH__USE_SSE
900+ Result.SSE = _mm_div_ps(Left.SSE, Right.SSE);
901+#elif defined(HANDMADE_MATH__USE_NEON)
902+ Result.NEON = vdivq_f32(Left.NEON, Right.NEON);
903+#else
904+ Result.X = Left.X / Right.X;
905+ Result.Y = Left.Y / Right.Y;
906+ Result.Z = Left.Z / Right.Z;
907+ Result.W = Left.W / Right.W;
908+#endif
909+
910+ return Result;
911+}
912+
913+COVERAGE(HMM_DivV4F, 1)
914+static inline HMM_Vec4 HMM_DivV4F(HMM_Vec4 Left, float Right)
915+{
916+ ASSERT_COVERED(HMM_DivV4F);
917+
918+ HMM_Vec4 Result;
919+
920+#ifdef HANDMADE_MATH__USE_SSE
921+ __m128 Scalar = _mm_set1_ps(Right);
922+ Result.SSE = _mm_div_ps(Left.SSE, Scalar);
923+#elif defined(HANDMADE_MATH__USE_NEON)
924+ float32x4_t Scalar = vdupq_n_f32(Right);
925+ Result.NEON = vdivq_f32(Left.NEON, Scalar);
926+#else
927+ Result.X = Left.X / Right;
928+ Result.Y = Left.Y / Right;
929+ Result.Z = Left.Z / Right;
930+ Result.W = Left.W / Right;
931+#endif
932+
933+ return Result;
934+}
935+
936+COVERAGE(HMM_EqV2, 1)
937+static inline HMM_Bool HMM_EqV2(HMM_Vec2 Left, HMM_Vec2 Right)
938+{
939+ ASSERT_COVERED(HMM_EqV2);
940+ return Left.X == Right.X && Left.Y == Right.Y;
941+}
942+
943+COVERAGE(HMM_EqV3, 1)
944+static inline HMM_Bool HMM_EqV3(HMM_Vec3 Left, HMM_Vec3 Right)
945+{
946+ ASSERT_COVERED(HMM_EqV3);
947+ return Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z;
948+}
949+
950+COVERAGE(HMM_EqV4, 1)
951+static inline HMM_Bool HMM_EqV4(HMM_Vec4 Left, HMM_Vec4 Right)
952+{
953+ ASSERT_COVERED(HMM_EqV4);
954+ return Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z && Left.W == Right.W;
955+}
956+
957+COVERAGE(HMM_DotV2, 1)
958+static inline float HMM_DotV2(HMM_Vec2 Left, HMM_Vec2 Right)
959+{
960+ ASSERT_COVERED(HMM_DotV2);
961+ return (Left.X * Right.X) + (Left.Y * Right.Y);
962+}
963+
964+COVERAGE(HMM_DotV3, 1)
965+static inline float HMM_DotV3(HMM_Vec3 Left, HMM_Vec3 Right)
966+{
967+ ASSERT_COVERED(HMM_DotV3);
968+ return (Left.X * Right.X) + (Left.Y * Right.Y) + (Left.Z * Right.Z);
969+}
970+
971+COVERAGE(HMM_DotV4, 1)
972+static inline float HMM_DotV4(HMM_Vec4 Left, HMM_Vec4 Right)
973+{
974+ ASSERT_COVERED(HMM_DotV4);
975+
976+ float Result;
977+
978+ // NOTE(zak): IN the future if we wanna check what version SSE is support
979+ // we can use _mm_dp_ps (4.3) but for now we will use the old way.
980+ // Or a r = _mm_mul_ps(v1, v2), r = _mm_hadd_ps(r, r), r = _mm_hadd_ps(r, r) for SSE3
981+#ifdef HANDMADE_MATH__USE_SSE
982+ __m128 SSEResultOne = _mm_mul_ps(Left.SSE, Right.SSE);
983+ __m128 SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(2, 3, 0, 1));
984+ SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo);
985+ SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(0, 1, 2, 3));
986+ SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo);
987+ _mm_store_ss(&Result, SSEResultOne);
988+#elif defined(HANDMADE_MATH__USE_NEON)
989+ float32x4_t NEONMultiplyResult = vmulq_f32(Left.NEON, Right.NEON);
990+ float32x4_t NEONHalfAdd = vpaddq_f32(NEONMultiplyResult, NEONMultiplyResult);
991+ float32x4_t NEONFullAdd = vpaddq_f32(NEONHalfAdd, NEONHalfAdd);
992+ Result = vgetq_lane_f32(NEONFullAdd, 0);
993+#else
994+ Result = ((Left.X * Right.X) + (Left.Z * Right.Z)) + ((Left.Y * Right.Y) + (Left.W * Right.W));
995+#endif
996+
997+ return Result;
998+}
999+
1000+COVERAGE(HMM_Cross, 1)
1001+static inline HMM_Vec3 HMM_Cross(HMM_Vec3 Left, HMM_Vec3 Right)
1002+{
1003+ ASSERT_COVERED(HMM_Cross);
1004+
1005+ HMM_Vec3 Result;
1006+ Result.X = (Left.Y * Right.Z) - (Left.Z * Right.Y);
1007+ Result.Y = (Left.Z * Right.X) - (Left.X * Right.Z);
1008+ Result.Z = (Left.X * Right.Y) - (Left.Y * Right.X);
1009+
1010+ return Result;
1011+}
1012+
1013+
1014+/*
1015+ * Unary vector operations
1016+ */
1017+
1018+COVERAGE(HMM_LenSqrV2, 1)
1019+static inline float HMM_LenSqrV2(HMM_Vec2 A)
1020+{
1021+ ASSERT_COVERED(HMM_LenSqrV2);
1022+ return HMM_DotV2(A, A);
1023+}
1024+
1025+COVERAGE(HMM_LenSqrV3, 1)
1026+static inline float HMM_LenSqrV3(HMM_Vec3 A)
1027+{
1028+ ASSERT_COVERED(HMM_LenSqrV3);
1029+ return HMM_DotV3(A, A);
1030+}
1031+
1032+COVERAGE(HMM_LenSqrV4, 1)
1033+static inline float HMM_LenSqrV4(HMM_Vec4 A)
1034+{
1035+ ASSERT_COVERED(HMM_LenSqrV4);
1036+ return HMM_DotV4(A, A);
1037+}
1038+
1039+COVERAGE(HMM_LenV2, 1)
1040+static inline float HMM_LenV2(HMM_Vec2 A)
1041+{
1042+ ASSERT_COVERED(HMM_LenV2);
1043+ return HMM_SqrtF(HMM_LenSqrV2(A));
1044+}
1045+
1046+COVERAGE(HMM_LenV3, 1)
1047+static inline float HMM_LenV3(HMM_Vec3 A)
1048+{
1049+ ASSERT_COVERED(HMM_LenV3);
1050+ return HMM_SqrtF(HMM_LenSqrV3(A));
1051+}
1052+
1053+COVERAGE(HMM_LenV4, 1)
1054+static inline float HMM_LenV4(HMM_Vec4 A)
1055+{
1056+ ASSERT_COVERED(HMM_LenV4);
1057+ return HMM_SqrtF(HMM_LenSqrV4(A));
1058+}
1059+
1060+COVERAGE(HMM_NormV2, 1)
1061+static inline HMM_Vec2 HMM_NormV2(HMM_Vec2 A)
1062+{
1063+ ASSERT_COVERED(HMM_NormV2);
1064+ return HMM_MulV2F(A, HMM_InvSqrtF(HMM_DotV2(A, A)));
1065+}
1066+
1067+COVERAGE(HMM_NormV3, 1)
1068+static inline HMM_Vec3 HMM_NormV3(HMM_Vec3 A)
1069+{
1070+ ASSERT_COVERED(HMM_NormV3);
1071+ return HMM_MulV3F(A, HMM_InvSqrtF(HMM_DotV3(A, A)));
1072+}
1073+
1074+COVERAGE(HMM_NormV4, 1)
1075+static inline HMM_Vec4 HMM_NormV4(HMM_Vec4 A)
1076+{
1077+ ASSERT_COVERED(HMM_NormV4);
1078+ return HMM_MulV4F(A, HMM_InvSqrtF(HMM_DotV4(A, A)));
1079+}
1080+
1081+/*
1082+ * Utility vector functions
1083+ */
1084+
1085+COVERAGE(HMM_LerpV2, 1)
1086+static inline HMM_Vec2 HMM_LerpV2(HMM_Vec2 A, float Time, HMM_Vec2 B)
1087+{
1088+ ASSERT_COVERED(HMM_LerpV2);
1089+ return HMM_AddV2(HMM_MulV2F(A, 1.0f - Time), HMM_MulV2F(B, Time));
1090+}
1091+
1092+COVERAGE(HMM_LerpV3, 1)
1093+static inline HMM_Vec3 HMM_LerpV3(HMM_Vec3 A, float Time, HMM_Vec3 B)
1094+{
1095+ ASSERT_COVERED(HMM_LerpV3);
1096+ return HMM_AddV3(HMM_MulV3F(A, 1.0f - Time), HMM_MulV3F(B, Time));
1097+}
1098+
1099+COVERAGE(HMM_LerpV4, 1)
1100+static inline HMM_Vec4 HMM_LerpV4(HMM_Vec4 A, float Time, HMM_Vec4 B)
1101+{
1102+ ASSERT_COVERED(HMM_LerpV4);
1103+ return HMM_AddV4(HMM_MulV4F(A, 1.0f - Time), HMM_MulV4F(B, Time));
1104+}
1105+
1106+/*
1107+ * SSE stuff
1108+ */
1109+
1110+COVERAGE(HMM_LinearCombineV4M4, 1)
1111+static inline HMM_Vec4 HMM_LinearCombineV4M4(HMM_Vec4 Left, HMM_Mat4 Right)
1112+{
1113+ ASSERT_COVERED(HMM_LinearCombineV4M4);
1114+
1115+ HMM_Vec4 Result;
1116+#ifdef HANDMADE_MATH__USE_SSE
1117+ Result.SSE = _mm_mul_ps(_mm_shuffle_ps(Left.SSE, Left.SSE, 0x00), Right.Columns[0].SSE);
1118+ Result.SSE = _mm_add_ps(Result.SSE, _mm_mul_ps(_mm_shuffle_ps(Left.SSE, Left.SSE, 0x55), Right.Columns[1].SSE));
1119+ Result.SSE = _mm_add_ps(Result.SSE, _mm_mul_ps(_mm_shuffle_ps(Left.SSE, Left.SSE, 0xaa), Right.Columns[2].SSE));
1120+ Result.SSE = _mm_add_ps(Result.SSE, _mm_mul_ps(_mm_shuffle_ps(Left.SSE, Left.SSE, 0xff), Right.Columns[3].SSE));
1121+#elif defined(HANDMADE_MATH__USE_NEON)
1122+ Result.NEON = vmulq_laneq_f32(Right.Columns[0].NEON, Left.NEON, 0);
1123+ Result.NEON = vfmaq_laneq_f32(Result.NEON, Right.Columns[1].NEON, Left.NEON, 1);
1124+ Result.NEON = vfmaq_laneq_f32(Result.NEON, Right.Columns[2].NEON, Left.NEON, 2);
1125+ Result.NEON = vfmaq_laneq_f32(Result.NEON, Right.Columns[3].NEON, Left.NEON, 3);
1126+#else
1127+ Result.X = Left.Elements[0] * Right.Columns[0].X;
1128+ Result.Y = Left.Elements[0] * Right.Columns[0].Y;
1129+ Result.Z = Left.Elements[0] * Right.Columns[0].Z;
1130+ Result.W = Left.Elements[0] * Right.Columns[0].W;
1131+
1132+ Result.X += Left.Elements[1] * Right.Columns[1].X;
1133+ Result.Y += Left.Elements[1] * Right.Columns[1].Y;
1134+ Result.Z += Left.Elements[1] * Right.Columns[1].Z;
1135+ Result.W += Left.Elements[1] * Right.Columns[1].W;
1136+
1137+ Result.X += Left.Elements[2] * Right.Columns[2].X;
1138+ Result.Y += Left.Elements[2] * Right.Columns[2].Y;
1139+ Result.Z += Left.Elements[2] * Right.Columns[2].Z;
1140+ Result.W += Left.Elements[2] * Right.Columns[2].W;
1141+
1142+ Result.X += Left.Elements[3] * Right.Columns[3].X;
1143+ Result.Y += Left.Elements[3] * Right.Columns[3].Y;
1144+ Result.Z += Left.Elements[3] * Right.Columns[3].Z;
1145+ Result.W += Left.Elements[3] * Right.Columns[3].W;
1146+#endif
1147+
1148+ return Result;
1149+}
1150+
1151+/*
1152+ * 2x2 Matrices
1153+ */
1154+
1155+COVERAGE(HMM_M2, 1)
1156+static inline HMM_Mat2 HMM_M2(void)
1157+{
1158+ ASSERT_COVERED(HMM_M2);
1159+ HMM_Mat2 Result = {0};
1160+ return Result;
1161+}
1162+
1163+COVERAGE(HMM_M2D, 1)
1164+static inline HMM_Mat2 HMM_M2D(float Diagonal)
1165+{
1166+ ASSERT_COVERED(HMM_M2D);
1167+
1168+ HMM_Mat2 Result = {0};
1169+ Result.Elements[0][0] = Diagonal;
1170+ Result.Elements[1][1] = Diagonal;
1171+
1172+ return Result;
1173+}
1174+
1175+COVERAGE(HMM_TransposeM2, 1)
1176+static inline HMM_Mat2 HMM_TransposeM2(HMM_Mat2 Matrix)
1177+{
1178+ ASSERT_COVERED(HMM_TransposeM2);
1179+
1180+ HMM_Mat2 Result = Matrix;
1181+
1182+ Result.Elements[0][1] = Matrix.Elements[1][0];
1183+ Result.Elements[1][0] = Matrix.Elements[0][1];
1184+
1185+ return Result;
1186+}
1187+
1188+COVERAGE(HMM_AddM2, 1)
1189+static inline HMM_Mat2 HMM_AddM2(HMM_Mat2 Left, HMM_Mat2 Right)
1190+{
1191+ ASSERT_COVERED(HMM_AddM2);
1192+
1193+ HMM_Mat2 Result;
1194+
1195+ Result.Elements[0][0] = Left.Elements[0][0] + Right.Elements[0][0];
1196+ Result.Elements[0][1] = Left.Elements[0][1] + Right.Elements[0][1];
1197+ Result.Elements[1][0] = Left.Elements[1][0] + Right.Elements[1][0];
1198+ Result.Elements[1][1] = Left.Elements[1][1] + Right.Elements[1][1];
1199+
1200+ return Result;
1201+}
1202+
1203+COVERAGE(HMM_SubM2, 1)
1204+static inline HMM_Mat2 HMM_SubM2(HMM_Mat2 Left, HMM_Mat2 Right)
1205+{
1206+ ASSERT_COVERED(HMM_SubM2);
1207+
1208+ HMM_Mat2 Result;
1209+
1210+ Result.Elements[0][0] = Left.Elements[0][0] - Right.Elements[0][0];
1211+ Result.Elements[0][1] = Left.Elements[0][1] - Right.Elements[0][1];
1212+ Result.Elements[1][0] = Left.Elements[1][0] - Right.Elements[1][0];
1213+ Result.Elements[1][1] = Left.Elements[1][1] - Right.Elements[1][1];
1214+
1215+ return Result;
1216+}
1217+
1218+COVERAGE(HMM_MulM2V2, 1)
1219+static inline HMM_Vec2 HMM_MulM2V2(HMM_Mat2 Matrix, HMM_Vec2 Vector)
1220+{
1221+ ASSERT_COVERED(HMM_MulM2V2);
1222+
1223+ HMM_Vec2 Result;
1224+
1225+ Result.X = Vector.Elements[0] * Matrix.Columns[0].X;
1226+ Result.Y = Vector.Elements[0] * Matrix.Columns[0].Y;
1227+
1228+ Result.X += Vector.Elements[1] * Matrix.Columns[1].X;
1229+ Result.Y += Vector.Elements[1] * Matrix.Columns[1].Y;
1230+
1231+ return Result;
1232+}
1233+
1234+COVERAGE(HMM_MulM2, 1)
1235+static inline HMM_Mat2 HMM_MulM2(HMM_Mat2 Left, HMM_Mat2 Right)
1236+{
1237+ ASSERT_COVERED(HMM_MulM2);
1238+
1239+ HMM_Mat2 Result;
1240+ Result.Columns[0] = HMM_MulM2V2(Left, Right.Columns[0]);
1241+ Result.Columns[1] = HMM_MulM2V2(Left, Right.Columns[1]);
1242+
1243+ return Result;
1244+}
1245+
1246+COVERAGE(HMM_MulM2F, 1)
1247+static inline HMM_Mat2 HMM_MulM2F(HMM_Mat2 Matrix, float Scalar)
1248+{
1249+ ASSERT_COVERED(HMM_MulM2F);
1250+
1251+ HMM_Mat2 Result;
1252+
1253+ Result.Elements[0][0] = Matrix.Elements[0][0] * Scalar;
1254+ Result.Elements[0][1] = Matrix.Elements[0][1] * Scalar;
1255+ Result.Elements[1][0] = Matrix.Elements[1][0] * Scalar;
1256+ Result.Elements[1][1] = Matrix.Elements[1][1] * Scalar;
1257+
1258+ return Result;
1259+}
1260+
1261+COVERAGE(HMM_DivM2F, 1)
1262+static inline HMM_Mat2 HMM_DivM2F(HMM_Mat2 Matrix, float Scalar)
1263+{
1264+ ASSERT_COVERED(HMM_DivM2F);
1265+
1266+ HMM_Mat2 Result;
1267+
1268+ Result.Elements[0][0] = Matrix.Elements[0][0] / Scalar;
1269+ Result.Elements[0][1] = Matrix.Elements[0][1] / Scalar;
1270+ Result.Elements[1][0] = Matrix.Elements[1][0] / Scalar;
1271+ Result.Elements[1][1] = Matrix.Elements[1][1] / Scalar;
1272+
1273+ return Result;
1274+}
1275+
1276+COVERAGE(HMM_DeterminantM2, 1)
1277+static inline float HMM_DeterminantM2(HMM_Mat2 Matrix)
1278+{
1279+ ASSERT_COVERED(HMM_DeterminantM2);
1280+ return Matrix.Elements[0][0]*Matrix.Elements[1][1] - Matrix.Elements[0][1]*Matrix.Elements[1][0];
1281+}
1282+
1283+
1284+COVERAGE(HMM_InvGeneralM2, 1)
1285+static inline HMM_Mat2 HMM_InvGeneralM2(HMM_Mat2 Matrix)
1286+{
1287+ ASSERT_COVERED(HMM_InvGeneralM2);
1288+
1289+ HMM_Mat2 Result;
1290+ float InvDeterminant = 1.0f / HMM_DeterminantM2(Matrix);
1291+ Result.Elements[0][0] = InvDeterminant * +Matrix.Elements[1][1];
1292+ Result.Elements[1][1] = InvDeterminant * +Matrix.Elements[0][0];
1293+ Result.Elements[0][1] = InvDeterminant * -Matrix.Elements[0][1];
1294+ Result.Elements[1][0] = InvDeterminant * -Matrix.Elements[1][0];
1295+
1296+ return Result;
1297+}
1298+
1299+/*
1300+ * 3x3 Matrices
1301+ */
1302+
1303+COVERAGE(HMM_M3, 1)
1304+static inline HMM_Mat3 HMM_M3(void)
1305+{
1306+ ASSERT_COVERED(HMM_M3);
1307+ HMM_Mat3 Result = {0};
1308+ return Result;
1309+}
1310+
1311+COVERAGE(HMM_M3D, 1)
1312+static inline HMM_Mat3 HMM_M3D(float Diagonal)
1313+{
1314+ ASSERT_COVERED(HMM_M3D);
1315+
1316+ HMM_Mat3 Result = {0};
1317+ Result.Elements[0][0] = Diagonal;
1318+ Result.Elements[1][1] = Diagonal;
1319+ Result.Elements[2][2] = Diagonal;
1320+
1321+ return Result;
1322+}
1323+
1324+COVERAGE(HMM_TransposeM3, 1)
1325+static inline HMM_Mat3 HMM_TransposeM3(HMM_Mat3 Matrix)
1326+{
1327+ ASSERT_COVERED(HMM_TransposeM3);
1328+
1329+ HMM_Mat3 Result = Matrix;
1330+
1331+ Result.Elements[0][1] = Matrix.Elements[1][0];
1332+ Result.Elements[0][2] = Matrix.Elements[2][0];
1333+ Result.Elements[1][0] = Matrix.Elements[0][1];
1334+ Result.Elements[1][2] = Matrix.Elements[2][1];
1335+ Result.Elements[2][1] = Matrix.Elements[1][2];
1336+ Result.Elements[2][0] = Matrix.Elements[0][2];
1337+
1338+ return Result;
1339+}
1340+
1341+COVERAGE(HMM_AddM3, 1)
1342+static inline HMM_Mat3 HMM_AddM3(HMM_Mat3 Left, HMM_Mat3 Right)
1343+{
1344+ ASSERT_COVERED(HMM_AddM3);
1345+
1346+ HMM_Mat3 Result;
1347+
1348+ Result.Elements[0][0] = Left.Elements[0][0] + Right.Elements[0][0];
1349+ Result.Elements[0][1] = Left.Elements[0][1] + Right.Elements[0][1];
1350+ Result.Elements[0][2] = Left.Elements[0][2] + Right.Elements[0][2];
1351+ Result.Elements[1][0] = Left.Elements[1][0] + Right.Elements[1][0];
1352+ Result.Elements[1][1] = Left.Elements[1][1] + Right.Elements[1][1];
1353+ Result.Elements[1][2] = Left.Elements[1][2] + Right.Elements[1][2];
1354+ Result.Elements[2][0] = Left.Elements[2][0] + Right.Elements[2][0];
1355+ Result.Elements[2][1] = Left.Elements[2][1] + Right.Elements[2][1];
1356+ Result.Elements[2][2] = Left.Elements[2][2] + Right.Elements[2][2];
1357+
1358+ return Result;
1359+}
1360+
1361+COVERAGE(HMM_SubM3, 1)
1362+static inline HMM_Mat3 HMM_SubM3(HMM_Mat3 Left, HMM_Mat3 Right)
1363+{
1364+ ASSERT_COVERED(HMM_SubM3);
1365+
1366+ HMM_Mat3 Result;
1367+
1368+ Result.Elements[0][0] = Left.Elements[0][0] - Right.Elements[0][0];
1369+ Result.Elements[0][1] = Left.Elements[0][1] - Right.Elements[0][1];
1370+ Result.Elements[0][2] = Left.Elements[0][2] - Right.Elements[0][2];
1371+ Result.Elements[1][0] = Left.Elements[1][0] - Right.Elements[1][0];
1372+ Result.Elements[1][1] = Left.Elements[1][1] - Right.Elements[1][1];
1373+ Result.Elements[1][2] = Left.Elements[1][2] - Right.Elements[1][2];
1374+ Result.Elements[2][0] = Left.Elements[2][0] - Right.Elements[2][0];
1375+ Result.Elements[2][1] = Left.Elements[2][1] - Right.Elements[2][1];
1376+ Result.Elements[2][2] = Left.Elements[2][2] - Right.Elements[2][2];
1377+
1378+ return Result;
1379+}
1380+
1381+COVERAGE(HMM_MulM3V3, 1)
1382+static inline HMM_Vec3 HMM_MulM3V3(HMM_Mat3 Matrix, HMM_Vec3 Vector)
1383+{
1384+ ASSERT_COVERED(HMM_MulM3V3);
1385+
1386+ HMM_Vec3 Result;
1387+
1388+ Result.X = Vector.Elements[0] * Matrix.Columns[0].X;
1389+ Result.Y = Vector.Elements[0] * Matrix.Columns[0].Y;
1390+ Result.Z = Vector.Elements[0] * Matrix.Columns[0].Z;
1391+
1392+ Result.X += Vector.Elements[1] * Matrix.Columns[1].X;
1393+ Result.Y += Vector.Elements[1] * Matrix.Columns[1].Y;
1394+ Result.Z += Vector.Elements[1] * Matrix.Columns[1].Z;
1395+
1396+ Result.X += Vector.Elements[2] * Matrix.Columns[2].X;
1397+ Result.Y += Vector.Elements[2] * Matrix.Columns[2].Y;
1398+ Result.Z += Vector.Elements[2] * Matrix.Columns[2].Z;
1399+
1400+ return Result;
1401+}
1402+
1403+COVERAGE(HMM_MulM3, 1)
1404+static inline HMM_Mat3 HMM_MulM3(HMM_Mat3 Left, HMM_Mat3 Right)
1405+{
1406+ ASSERT_COVERED(HMM_MulM3);
1407+
1408+ HMM_Mat3 Result;
1409+ Result.Columns[0] = HMM_MulM3V3(Left, Right.Columns[0]);
1410+ Result.Columns[1] = HMM_MulM3V3(Left, Right.Columns[1]);
1411+ Result.Columns[2] = HMM_MulM3V3(Left, Right.Columns[2]);
1412+
1413+ return Result;
1414+}
1415+
1416+COVERAGE(HMM_MulM3F, 1)
1417+static inline HMM_Mat3 HMM_MulM3F(HMM_Mat3 Matrix, float Scalar)
1418+{
1419+ ASSERT_COVERED(HMM_MulM3F);
1420+
1421+ HMM_Mat3 Result;
1422+
1423+ Result.Elements[0][0] = Matrix.Elements[0][0] * Scalar;
1424+ Result.Elements[0][1] = Matrix.Elements[0][1] * Scalar;
1425+ Result.Elements[0][2] = Matrix.Elements[0][2] * Scalar;
1426+ Result.Elements[1][0] = Matrix.Elements[1][0] * Scalar;
1427+ Result.Elements[1][1] = Matrix.Elements[1][1] * Scalar;
1428+ Result.Elements[1][2] = Matrix.Elements[1][2] * Scalar;
1429+ Result.Elements[2][0] = Matrix.Elements[2][0] * Scalar;
1430+ Result.Elements[2][1] = Matrix.Elements[2][1] * Scalar;
1431+ Result.Elements[2][2] = Matrix.Elements[2][2] * Scalar;
1432+
1433+ return Result;
1434+}
1435+
1436+COVERAGE(HMM_DivM3F, 1)
1437+static inline HMM_Mat3 HMM_DivM3F(HMM_Mat3 Matrix, float Scalar)
1438+{
1439+ ASSERT_COVERED(HMM_DivM3F);
1440+
1441+ HMM_Mat3 Result;
1442+
1443+ Result.Elements[0][0] = Matrix.Elements[0][0] / Scalar;
1444+ Result.Elements[0][1] = Matrix.Elements[0][1] / Scalar;
1445+ Result.Elements[0][2] = Matrix.Elements[0][2] / Scalar;
1446+ Result.Elements[1][0] = Matrix.Elements[1][0] / Scalar;
1447+ Result.Elements[1][1] = Matrix.Elements[1][1] / Scalar;
1448+ Result.Elements[1][2] = Matrix.Elements[1][2] / Scalar;
1449+ Result.Elements[2][0] = Matrix.Elements[2][0] / Scalar;
1450+ Result.Elements[2][1] = Matrix.Elements[2][1] / Scalar;
1451+ Result.Elements[2][2] = Matrix.Elements[2][2] / Scalar;
1452+
1453+ return Result;
1454+}
1455+
1456+COVERAGE(HMM_DeterminantM3, 1)
1457+static inline float HMM_DeterminantM3(HMM_Mat3 Matrix)
1458+{
1459+ ASSERT_COVERED(HMM_DeterminantM3);
1460+
1461+ HMM_Mat3 Cross;
1462+ Cross.Columns[0] = HMM_Cross(Matrix.Columns[1], Matrix.Columns[2]);
1463+ Cross.Columns[1] = HMM_Cross(Matrix.Columns[2], Matrix.Columns[0]);
1464+ Cross.Columns[2] = HMM_Cross(Matrix.Columns[0], Matrix.Columns[1]);
1465+
1466+ return HMM_DotV3(Cross.Columns[2], Matrix.Columns[2]);
1467+}
1468+
1469+COVERAGE(HMM_InvGeneralM3, 1)
1470+static inline HMM_Mat3 HMM_InvGeneralM3(HMM_Mat3 Matrix)
1471+{
1472+ ASSERT_COVERED(HMM_InvGeneralM3);
1473+
1474+ HMM_Mat3 Cross;
1475+ Cross.Columns[0] = HMM_Cross(Matrix.Columns[1], Matrix.Columns[2]);
1476+ Cross.Columns[1] = HMM_Cross(Matrix.Columns[2], Matrix.Columns[0]);
1477+ Cross.Columns[2] = HMM_Cross(Matrix.Columns[0], Matrix.Columns[1]);
1478+
1479+ float InvDeterminant = 1.0f / HMM_DotV3(Cross.Columns[2], Matrix.Columns[2]);
1480+
1481+ HMM_Mat3 Result;
1482+ Result.Columns[0] = HMM_MulV3F(Cross.Columns[0], InvDeterminant);
1483+ Result.Columns[1] = HMM_MulV3F(Cross.Columns[1], InvDeterminant);
1484+ Result.Columns[2] = HMM_MulV3F(Cross.Columns[2], InvDeterminant);
1485+
1486+ return HMM_TransposeM3(Result);
1487+}
1488+
1489+/*
1490+ * 4x4 Matrices
1491+ */
1492+
1493+COVERAGE(HMM_M4, 1)
1494+static inline HMM_Mat4 HMM_M4(void)
1495+{
1496+ ASSERT_COVERED(HMM_M4);
1497+ HMM_Mat4 Result = {0};
1498+ return Result;
1499+}
1500+
1501+COVERAGE(HMM_M4D, 1)
1502+static inline HMM_Mat4 HMM_M4D(float Diagonal)
1503+{
1504+ ASSERT_COVERED(HMM_M4D);
1505+
1506+ HMM_Mat4 Result = {0};
1507+ Result.Elements[0][0] = Diagonal;
1508+ Result.Elements[1][1] = Diagonal;
1509+ Result.Elements[2][2] = Diagonal;
1510+ Result.Elements[3][3] = Diagonal;
1511+
1512+ return Result;
1513+}
1514+
1515+COVERAGE(HMM_TransposeM4, 1)
1516+static inline HMM_Mat4 HMM_TransposeM4(HMM_Mat4 Matrix)
1517+{
1518+ ASSERT_COVERED(HMM_TransposeM4);
1519+
1520+ HMM_Mat4 Result;
1521+#ifdef HANDMADE_MATH__USE_SSE
1522+ Result = Matrix;
1523+ _MM_TRANSPOSE4_PS(Result.Columns[0].SSE, Result.Columns[1].SSE, Result.Columns[2].SSE, Result.Columns[3].SSE);
1524+#elif defined(HANDMADE_MATH__USE_NEON)
1525+ float32x4x4_t Transposed = vld4q_f32((float*)Matrix.Columns);
1526+ Result.Columns[0].NEON = Transposed.val[0];
1527+ Result.Columns[1].NEON = Transposed.val[1];
1528+ Result.Columns[2].NEON = Transposed.val[2];
1529+ Result.Columns[3].NEON = Transposed.val[3];
1530+#else
1531+ Result.Elements[0][0] = Matrix.Elements[0][0];
1532+ Result.Elements[0][1] = Matrix.Elements[1][0];
1533+ Result.Elements[0][2] = Matrix.Elements[2][0];
1534+ Result.Elements[0][3] = Matrix.Elements[3][0];
1535+ Result.Elements[1][0] = Matrix.Elements[0][1];
1536+ Result.Elements[1][1] = Matrix.Elements[1][1];
1537+ Result.Elements[1][2] = Matrix.Elements[2][1];
1538+ Result.Elements[1][3] = Matrix.Elements[3][1];
1539+ Result.Elements[2][0] = Matrix.Elements[0][2];
1540+ Result.Elements[2][1] = Matrix.Elements[1][2];
1541+ Result.Elements[2][2] = Matrix.Elements[2][2];
1542+ Result.Elements[2][3] = Matrix.Elements[3][2];
1543+ Result.Elements[3][0] = Matrix.Elements[0][3];
1544+ Result.Elements[3][1] = Matrix.Elements[1][3];
1545+ Result.Elements[3][2] = Matrix.Elements[2][3];
1546+ Result.Elements[3][3] = Matrix.Elements[3][3];
1547+#endif
1548+
1549+ return Result;
1550+}
1551+
1552+COVERAGE(HMM_AddM4, 1)
1553+static inline HMM_Mat4 HMM_AddM4(HMM_Mat4 Left, HMM_Mat4 Right)
1554+{
1555+ ASSERT_COVERED(HMM_AddM4);
1556+
1557+ HMM_Mat4 Result;
1558+
1559+ Result.Columns[0] = HMM_AddV4(Left.Columns[0], Right.Columns[0]);
1560+ Result.Columns[1] = HMM_AddV4(Left.Columns[1], Right.Columns[1]);
1561+ Result.Columns[2] = HMM_AddV4(Left.Columns[2], Right.Columns[2]);
1562+ Result.Columns[3] = HMM_AddV4(Left.Columns[3], Right.Columns[3]);
1563+
1564+ return Result;
1565+}
1566+
1567+COVERAGE(HMM_SubM4, 1)
1568+static inline HMM_Mat4 HMM_SubM4(HMM_Mat4 Left, HMM_Mat4 Right)
1569+{
1570+ ASSERT_COVERED(HMM_SubM4);
1571+
1572+ HMM_Mat4 Result;
1573+
1574+ Result.Columns[0] = HMM_SubV4(Left.Columns[0], Right.Columns[0]);
1575+ Result.Columns[1] = HMM_SubV4(Left.Columns[1], Right.Columns[1]);
1576+ Result.Columns[2] = HMM_SubV4(Left.Columns[2], Right.Columns[2]);
1577+ Result.Columns[3] = HMM_SubV4(Left.Columns[3], Right.Columns[3]);
1578+
1579+ return Result;
1580+}
1581+
1582+COVERAGE(HMM_MulM4, 1)
1583+static inline HMM_Mat4 HMM_MulM4(HMM_Mat4 Left, HMM_Mat4 Right)
1584+{
1585+ ASSERT_COVERED(HMM_MulM4);
1586+
1587+ HMM_Mat4 Result;
1588+ Result.Columns[0] = HMM_LinearCombineV4M4(Right.Columns[0], Left);
1589+ Result.Columns[1] = HMM_LinearCombineV4M4(Right.Columns[1], Left);
1590+ Result.Columns[2] = HMM_LinearCombineV4M4(Right.Columns[2], Left);
1591+ Result.Columns[3] = HMM_LinearCombineV4M4(Right.Columns[3], Left);
1592+
1593+ return Result;
1594+}
1595+
1596+COVERAGE(HMM_MulM4F, 1)
1597+static inline HMM_Mat4 HMM_MulM4F(HMM_Mat4 Matrix, float Scalar)
1598+{
1599+ ASSERT_COVERED(HMM_MulM4F);
1600+
1601+ HMM_Mat4 Result;
1602+
1603+
1604+#ifdef HANDMADE_MATH__USE_SSE
1605+ __m128 SSEScalar = _mm_set1_ps(Scalar);
1606+ Result.Columns[0].SSE = _mm_mul_ps(Matrix.Columns[0].SSE, SSEScalar);
1607+ Result.Columns[1].SSE = _mm_mul_ps(Matrix.Columns[1].SSE, SSEScalar);
1608+ Result.Columns[2].SSE = _mm_mul_ps(Matrix.Columns[2].SSE, SSEScalar);
1609+ Result.Columns[3].SSE = _mm_mul_ps(Matrix.Columns[3].SSE, SSEScalar);
1610+#elif defined(HANDMADE_MATH__USE_NEON)
1611+ Result.Columns[0].NEON = vmulq_n_f32(Matrix.Columns[0].NEON, Scalar);
1612+ Result.Columns[1].NEON = vmulq_n_f32(Matrix.Columns[1].NEON, Scalar);
1613+ Result.Columns[2].NEON = vmulq_n_f32(Matrix.Columns[2].NEON, Scalar);
1614+ Result.Columns[3].NEON = vmulq_n_f32(Matrix.Columns[3].NEON, Scalar);
1615+#else
1616+ Result.Elements[0][0] = Matrix.Elements[0][0] * Scalar;
1617+ Result.Elements[0][1] = Matrix.Elements[0][1] * Scalar;
1618+ Result.Elements[0][2] = Matrix.Elements[0][2] * Scalar;
1619+ Result.Elements[0][3] = Matrix.Elements[0][3] * Scalar;
1620+ Result.Elements[1][0] = Matrix.Elements[1][0] * Scalar;
1621+ Result.Elements[1][1] = Matrix.Elements[1][1] * Scalar;
1622+ Result.Elements[1][2] = Matrix.Elements[1][2] * Scalar;
1623+ Result.Elements[1][3] = Matrix.Elements[1][3] * Scalar;
1624+ Result.Elements[2][0] = Matrix.Elements[2][0] * Scalar;
1625+ Result.Elements[2][1] = Matrix.Elements[2][1] * Scalar;
1626+ Result.Elements[2][2] = Matrix.Elements[2][2] * Scalar;
1627+ Result.Elements[2][3] = Matrix.Elements[2][3] * Scalar;
1628+ Result.Elements[3][0] = Matrix.Elements[3][0] * Scalar;
1629+ Result.Elements[3][1] = Matrix.Elements[3][1] * Scalar;
1630+ Result.Elements[3][2] = Matrix.Elements[3][2] * Scalar;
1631+ Result.Elements[3][3] = Matrix.Elements[3][3] * Scalar;
1632+#endif
1633+
1634+ return Result;
1635+}
1636+
1637+COVERAGE(HMM_MulM4V4, 1)
1638+static inline HMM_Vec4 HMM_MulM4V4(HMM_Mat4 Matrix, HMM_Vec4 Vector)
1639+{
1640+ ASSERT_COVERED(HMM_MulM4V4);
1641+ return HMM_LinearCombineV4M4(Vector, Matrix);
1642+}
1643+
1644+COVERAGE(HMM_DivM4F, 1)
1645+static inline HMM_Mat4 HMM_DivM4F(HMM_Mat4 Matrix, float Scalar)
1646+{
1647+ ASSERT_COVERED(HMM_DivM4F);
1648+
1649+ HMM_Mat4 Result;
1650+
1651+#ifdef HANDMADE_MATH__USE_SSE
1652+ __m128 SSEScalar = _mm_set1_ps(Scalar);
1653+ Result.Columns[0].SSE = _mm_div_ps(Matrix.Columns[0].SSE, SSEScalar);
1654+ Result.Columns[1].SSE = _mm_div_ps(Matrix.Columns[1].SSE, SSEScalar);
1655+ Result.Columns[2].SSE = _mm_div_ps(Matrix.Columns[2].SSE, SSEScalar);
1656+ Result.Columns[3].SSE = _mm_div_ps(Matrix.Columns[3].SSE, SSEScalar);
1657+#elif defined(HANDMADE_MATH__USE_NEON)
1658+ float32x4_t NEONScalar = vdupq_n_f32(Scalar);
1659+ Result.Columns[0].NEON = vdivq_f32(Matrix.Columns[0].NEON, NEONScalar);
1660+ Result.Columns[1].NEON = vdivq_f32(Matrix.Columns[1].NEON, NEONScalar);
1661+ Result.Columns[2].NEON = vdivq_f32(Matrix.Columns[2].NEON, NEONScalar);
1662+ Result.Columns[3].NEON = vdivq_f32(Matrix.Columns[3].NEON, NEONScalar);
1663+#else
1664+ Result.Elements[0][0] = Matrix.Elements[0][0] / Scalar;
1665+ Result.Elements[0][1] = Matrix.Elements[0][1] / Scalar;
1666+ Result.Elements[0][2] = Matrix.Elements[0][2] / Scalar;
1667+ Result.Elements[0][3] = Matrix.Elements[0][3] / Scalar;
1668+ Result.Elements[1][0] = Matrix.Elements[1][0] / Scalar;
1669+ Result.Elements[1][1] = Matrix.Elements[1][1] / Scalar;
1670+ Result.Elements[1][2] = Matrix.Elements[1][2] / Scalar;
1671+ Result.Elements[1][3] = Matrix.Elements[1][3] / Scalar;
1672+ Result.Elements[2][0] = Matrix.Elements[2][0] / Scalar;
1673+ Result.Elements[2][1] = Matrix.Elements[2][1] / Scalar;
1674+ Result.Elements[2][2] = Matrix.Elements[2][2] / Scalar;
1675+ Result.Elements[2][3] = Matrix.Elements[2][3] / Scalar;
1676+ Result.Elements[3][0] = Matrix.Elements[3][0] / Scalar;
1677+ Result.Elements[3][1] = Matrix.Elements[3][1] / Scalar;
1678+ Result.Elements[3][2] = Matrix.Elements[3][2] / Scalar;
1679+ Result.Elements[3][3] = Matrix.Elements[3][3] / Scalar;
1680+#endif
1681+
1682+ return Result;
1683+}
1684+
1685+COVERAGE(HMM_DeterminantM4, 1)
1686+static inline float HMM_DeterminantM4(HMM_Mat4 Matrix)
1687+{
1688+ ASSERT_COVERED(HMM_DeterminantM4);
1689+
1690+ HMM_Vec3 C01 = HMM_Cross(Matrix.Columns[0].XYZ, Matrix.Columns[1].XYZ);
1691+ HMM_Vec3 C23 = HMM_Cross(Matrix.Columns[2].XYZ, Matrix.Columns[3].XYZ);
1692+ HMM_Vec3 B10 = HMM_SubV3(HMM_MulV3F(Matrix.Columns[0].XYZ, Matrix.Columns[1].W), HMM_MulV3F(Matrix.Columns[1].XYZ, Matrix.Columns[0].W));
1693+ HMM_Vec3 B32 = HMM_SubV3(HMM_MulV3F(Matrix.Columns[2].XYZ, Matrix.Columns[3].W), HMM_MulV3F(Matrix.Columns[3].XYZ, Matrix.Columns[2].W));
1694+
1695+ return HMM_DotV3(C01, B32) + HMM_DotV3(C23, B10);
1696+}
1697+
1698+COVERAGE(HMM_InvGeneralM4, 1)
1699+// Returns a general-purpose inverse of an HMM_Mat4. Note that special-purpose inverses of many transformations
1700+// are available and will be more efficient.
1701+static inline HMM_Mat4 HMM_InvGeneralM4(HMM_Mat4 Matrix)
1702+{
1703+ ASSERT_COVERED(HMM_InvGeneralM4);
1704+
1705+ HMM_Vec3 C01 = HMM_Cross(Matrix.Columns[0].XYZ, Matrix.Columns[1].XYZ);
1706+ HMM_Vec3 C23 = HMM_Cross(Matrix.Columns[2].XYZ, Matrix.Columns[3].XYZ);
1707+ HMM_Vec3 B10 = HMM_SubV3(HMM_MulV3F(Matrix.Columns[0].XYZ, Matrix.Columns[1].W), HMM_MulV3F(Matrix.Columns[1].XYZ, Matrix.Columns[0].W));
1708+ HMM_Vec3 B32 = HMM_SubV3(HMM_MulV3F(Matrix.Columns[2].XYZ, Matrix.Columns[3].W), HMM_MulV3F(Matrix.Columns[3].XYZ, Matrix.Columns[2].W));
1709+
1710+ float InvDeterminant = 1.0f / (HMM_DotV3(C01, B32) + HMM_DotV3(C23, B10));
1711+ C01 = HMM_MulV3F(C01, InvDeterminant);
1712+ C23 = HMM_MulV3F(C23, InvDeterminant);
1713+ B10 = HMM_MulV3F(B10, InvDeterminant);
1714+ B32 = HMM_MulV3F(B32, InvDeterminant);
1715+
1716+ HMM_Mat4 Result;
1717+ Result.Columns[0] = HMM_V4V(HMM_AddV3(HMM_Cross(Matrix.Columns[1].XYZ, B32), HMM_MulV3F(C23, Matrix.Columns[1].W)), -HMM_DotV3(Matrix.Columns[1].XYZ, C23));
1718+ Result.Columns[1] = HMM_V4V(HMM_SubV3(HMM_Cross(B32, Matrix.Columns[0].XYZ), HMM_MulV3F(C23, Matrix.Columns[0].W)), +HMM_DotV3(Matrix.Columns[0].XYZ, C23));
1719+ Result.Columns[2] = HMM_V4V(HMM_AddV3(HMM_Cross(Matrix.Columns[3].XYZ, B10), HMM_MulV3F(C01, Matrix.Columns[3].W)), -HMM_DotV3(Matrix.Columns[3].XYZ, C01));
1720+ Result.Columns[3] = HMM_V4V(HMM_SubV3(HMM_Cross(B10, Matrix.Columns[2].XYZ), HMM_MulV3F(C01, Matrix.Columns[2].W)), +HMM_DotV3(Matrix.Columns[2].XYZ, C01));
1721+
1722+ return HMM_TransposeM4(Result);
1723+}
1724+
1725+/*
1726+ * Common graphics transformations
1727+ */
1728+
1729+COVERAGE(HMM_Orthographic_RH_NO, 1)
1730+// Produces a right-handed orthographic projection matrix with Z ranging from -1 to 1 (the GL convention).
1731+// Left, Right, Bottom, and Top specify the coordinates of their respective clipping planes.
1732+// Near and Far specify the distances to the near and far clipping planes.
1733+static inline HMM_Mat4 HMM_Orthographic_RH_NO(float Left, float Right, float Bottom, float Top, float Near, float Far)
1734+{
1735+ ASSERT_COVERED(HMM_Orthographic_RH_NO);
1736+
1737+ HMM_Mat4 Result = {0};
1738+
1739+ Result.Elements[0][0] = 2.0f / (Right - Left);
1740+ Result.Elements[1][1] = 2.0f / (Top - Bottom);
1741+ Result.Elements[2][2] = 2.0f / (Near - Far);
1742+ Result.Elements[3][3] = 1.0f;
1743+
1744+ Result.Elements[3][0] = (Left + Right) / (Left - Right);
1745+ Result.Elements[3][1] = (Bottom + Top) / (Bottom - Top);
1746+ Result.Elements[3][2] = (Near + Far) / (Near - Far);
1747+
1748+ return Result;
1749+}
1750+
1751+COVERAGE(HMM_Orthographic_RH_ZO, 1)
1752+// Produces a right-handed orthographic projection matrix with Z ranging from 0 to 1 (the DirectX convention).
1753+// Left, Right, Bottom, and Top specify the coordinates of their respective clipping planes.
1754+// Near and Far specify the distances to the near and far clipping planes.
1755+static inline HMM_Mat4 HMM_Orthographic_RH_ZO(float Left, float Right, float Bottom, float Top, float Near, float Far)
1756+{
1757+ ASSERT_COVERED(HMM_Orthographic_RH_ZO);
1758+
1759+ HMM_Mat4 Result = {0};
1760+
1761+ Result.Elements[0][0] = 2.0f / (Right - Left);
1762+ Result.Elements[1][1] = 2.0f / (Top - Bottom);
1763+ Result.Elements[2][2] = 1.0f / (Near - Far);
1764+ Result.Elements[3][3] = 1.0f;
1765+
1766+ Result.Elements[3][0] = (Left + Right) / (Left - Right);
1767+ Result.Elements[3][1] = (Bottom + Top) / (Bottom - Top);
1768+ Result.Elements[3][2] = (Near) / (Near - Far);
1769+
1770+ return Result;
1771+}
1772+
1773+COVERAGE(HMM_Orthographic_LH_NO, 1)
1774+// Produces a left-handed orthographic projection matrix with Z ranging from -1 to 1 (the GL convention).
1775+// Left, Right, Bottom, and Top specify the coordinates of their respective clipping planes.
1776+// Near and Far specify the distances to the near and far clipping planes.
1777+static inline HMM_Mat4 HMM_Orthographic_LH_NO(float Left, float Right, float Bottom, float Top, float Near, float Far)
1778+{
1779+ ASSERT_COVERED(HMM_Orthographic_LH_NO);
1780+
1781+ HMM_Mat4 Result = HMM_Orthographic_RH_NO(Left, Right, Bottom, Top, Near, Far);
1782+ Result.Elements[2][2] = -Result.Elements[2][2];
1783+
1784+ return Result;
1785+}
1786+
1787+COVERAGE(HMM_Orthographic_LH_ZO, 1)
1788+// Produces a left-handed orthographic projection matrix with Z ranging from 0 to 1 (the DirectX convention).
1789+// Left, Right, Bottom, and Top specify the coordinates of their respective clipping planes.
1790+// Near and Far specify the distances to the near and far clipping planes.
1791+static inline HMM_Mat4 HMM_Orthographic_LH_ZO(float Left, float Right, float Bottom, float Top, float Near, float Far)
1792+{
1793+ ASSERT_COVERED(HMM_Orthographic_LH_ZO);
1794+
1795+ HMM_Mat4 Result = HMM_Orthographic_RH_ZO(Left, Right, Bottom, Top, Near, Far);
1796+ Result.Elements[2][2] = -Result.Elements[2][2];
1797+
1798+ return Result;
1799+}
1800+
1801+COVERAGE(HMM_InvOrthographic, 1)
1802+// Returns an inverse for the given orthographic projection matrix. Works for all orthographic
1803+// projection matrices, regardless of handedness or NDC convention.
1804+static inline HMM_Mat4 HMM_InvOrthographic(HMM_Mat4 OrthoMatrix)
1805+{
1806+ ASSERT_COVERED(HMM_InvOrthographic);
1807+
1808+ HMM_Mat4 Result = {0};
1809+ Result.Elements[0][0] = 1.0f / OrthoMatrix.Elements[0][0];
1810+ Result.Elements[1][1] = 1.0f / OrthoMatrix.Elements[1][1];
1811+ Result.Elements[2][2] = 1.0f / OrthoMatrix.Elements[2][2];
1812+ Result.Elements[3][3] = 1.0f;
1813+
1814+ Result.Elements[3][0] = -OrthoMatrix.Elements[3][0] * Result.Elements[0][0];
1815+ Result.Elements[3][1] = -OrthoMatrix.Elements[3][1] * Result.Elements[1][1];
1816+ Result.Elements[3][2] = -OrthoMatrix.Elements[3][2] * Result.Elements[2][2];
1817+
1818+ return Result;
1819+}
1820+
1821+COVERAGE(HMM_Perspective_RH_NO, 1)
1822+static inline HMM_Mat4 HMM_Perspective_RH_NO(float FOV, float AspectRatio, float Near, float Far)
1823+{
1824+ ASSERT_COVERED(HMM_Perspective_RH_NO);
1825+
1826+ HMM_Mat4 Result = {0};
1827+
1828+ // See https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml
1829+
1830+ float Cotangent = 1.0f / HMM_TanF(FOV / 2.0f);
1831+ Result.Elements[0][0] = Cotangent / AspectRatio;
1832+ Result.Elements[1][1] = Cotangent;
1833+ Result.Elements[2][3] = -1.0f;
1834+
1835+ Result.Elements[2][2] = (Near + Far) / (Near - Far);
1836+ Result.Elements[3][2] = (2.0f * Near * Far) / (Near - Far);
1837+
1838+ return Result;
1839+}
1840+
1841+COVERAGE(HMM_Perspective_RH_ZO, 1)
1842+static inline HMM_Mat4 HMM_Perspective_RH_ZO(float FOV, float AspectRatio, float Near, float Far)
1843+{
1844+ ASSERT_COVERED(HMM_Perspective_RH_ZO);
1845+
1846+ HMM_Mat4 Result = {0};
1847+
1848+ // See https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml
1849+
1850+ float Cotangent = 1.0f / HMM_TanF(FOV / 2.0f);
1851+ Result.Elements[0][0] = Cotangent / AspectRatio;
1852+ Result.Elements[1][1] = Cotangent;
1853+ Result.Elements[2][3] = -1.0f;
1854+
1855+ Result.Elements[2][2] = (Far) / (Near - Far);
1856+ Result.Elements[3][2] = (Near * Far) / (Near - Far);
1857+
1858+ return Result;
1859+}
1860+
1861+COVERAGE(HMM_Perspective_LH_NO, 1)
1862+static inline HMM_Mat4 HMM_Perspective_LH_NO(float FOV, float AspectRatio, float Near, float Far)
1863+{
1864+ ASSERT_COVERED(HMM_Perspective_LH_NO);
1865+
1866+ HMM_Mat4 Result = HMM_Perspective_RH_NO(FOV, AspectRatio, Near, Far);
1867+ Result.Elements[2][2] = -Result.Elements[2][2];
1868+ Result.Elements[2][3] = -Result.Elements[2][3];
1869+
1870+ return Result;
1871+}
1872+
1873+COVERAGE(HMM_Perspective_LH_ZO, 1)
1874+static inline HMM_Mat4 HMM_Perspective_LH_ZO(float FOV, float AspectRatio, float Near, float Far)
1875+{
1876+ ASSERT_COVERED(HMM_Perspective_LH_ZO);
1877+
1878+ HMM_Mat4 Result = HMM_Perspective_RH_ZO(FOV, AspectRatio, Near, Far);
1879+ Result.Elements[2][2] = -Result.Elements[2][2];
1880+ Result.Elements[2][3] = -Result.Elements[2][3];
1881+
1882+ return Result;
1883+}
1884+
1885+COVERAGE(HMM_InvPerspective_RH, 1)
1886+static inline HMM_Mat4 HMM_InvPerspective_RH(HMM_Mat4 PerspectiveMatrix)
1887+{
1888+ ASSERT_COVERED(HMM_InvPerspective_RH);
1889+
1890+ HMM_Mat4 Result = {0};
1891+ Result.Elements[0][0] = 1.0f / PerspectiveMatrix.Elements[0][0];
1892+ Result.Elements[1][1] = 1.0f / PerspectiveMatrix.Elements[1][1];
1893+ Result.Elements[2][2] = 0.0f;
1894+
1895+ Result.Elements[2][3] = 1.0f / PerspectiveMatrix.Elements[3][2];
1896+ Result.Elements[3][3] = PerspectiveMatrix.Elements[2][2] * Result.Elements[2][3];
1897+ Result.Elements[3][2] = PerspectiveMatrix.Elements[2][3];
1898+
1899+ return Result;
1900+}
1901+
1902+COVERAGE(HMM_InvPerspective_LH, 1)
1903+static inline HMM_Mat4 HMM_InvPerspective_LH(HMM_Mat4 PerspectiveMatrix)
1904+{
1905+ ASSERT_COVERED(HMM_InvPerspective_LH);
1906+
1907+ HMM_Mat4 Result = {0};
1908+ Result.Elements[0][0] = 1.0f / PerspectiveMatrix.Elements[0][0];
1909+ Result.Elements[1][1] = 1.0f / PerspectiveMatrix.Elements[1][1];
1910+ Result.Elements[2][2] = 0.0f;
1911+
1912+ Result.Elements[2][3] = 1.0f / PerspectiveMatrix.Elements[3][2];
1913+ Result.Elements[3][3] = PerspectiveMatrix.Elements[2][2] * -Result.Elements[2][3];
1914+ Result.Elements[3][2] = PerspectiveMatrix.Elements[2][3];
1915+
1916+ return Result;
1917+}
1918+
1919+COVERAGE(HMM_Translate, 1)
1920+static inline HMM_Mat4 HMM_Translate(HMM_Vec3 Translation)
1921+{
1922+ ASSERT_COVERED(HMM_Translate);
1923+
1924+ HMM_Mat4 Result = HMM_M4D(1.0f);
1925+ Result.Elements[3][0] = Translation.X;
1926+ Result.Elements[3][1] = Translation.Y;
1927+ Result.Elements[3][2] = Translation.Z;
1928+
1929+ return Result;
1930+}
1931+
1932+COVERAGE(HMM_InvTranslate, 1)
1933+static inline HMM_Mat4 HMM_InvTranslate(HMM_Mat4 TranslationMatrix)
1934+{
1935+ ASSERT_COVERED(HMM_InvTranslate);
1936+
1937+ HMM_Mat4 Result = TranslationMatrix;
1938+ Result.Elements[3][0] = -Result.Elements[3][0];
1939+ Result.Elements[3][1] = -Result.Elements[3][1];
1940+ Result.Elements[3][2] = -Result.Elements[3][2];
1941+
1942+ return Result;
1943+}
1944+
1945+COVERAGE(HMM_Rotate_RH, 1)
1946+static inline HMM_Mat4 HMM_Rotate_RH(float Angle, HMM_Vec3 Axis)
1947+{
1948+ ASSERT_COVERED(HMM_Rotate_RH);
1949+
1950+ HMM_Mat4 Result = HMM_M4D(1.0f);
1951+
1952+ Axis = HMM_NormV3(Axis);
1953+
1954+ float SinTheta = HMM_SinF(Angle);
1955+ float CosTheta = HMM_CosF(Angle);
1956+ float CosValue = 1.0f - CosTheta;
1957+
1958+ Result.Elements[0][0] = (Axis.X * Axis.X * CosValue) + CosTheta;
1959+ Result.Elements[0][1] = (Axis.X * Axis.Y * CosValue) + (Axis.Z * SinTheta);
1960+ Result.Elements[0][2] = (Axis.X * Axis.Z * CosValue) - (Axis.Y * SinTheta);
1961+
1962+ Result.Elements[1][0] = (Axis.Y * Axis.X * CosValue) - (Axis.Z * SinTheta);
1963+ Result.Elements[1][1] = (Axis.Y * Axis.Y * CosValue) + CosTheta;
1964+ Result.Elements[1][2] = (Axis.Y * Axis.Z * CosValue) + (Axis.X * SinTheta);
1965+
1966+ Result.Elements[2][0] = (Axis.Z * Axis.X * CosValue) + (Axis.Y * SinTheta);
1967+ Result.Elements[2][1] = (Axis.Z * Axis.Y * CosValue) - (Axis.X * SinTheta);
1968+ Result.Elements[2][2] = (Axis.Z * Axis.Z * CosValue) + CosTheta;
1969+
1970+ return Result;
1971+}
1972+
1973+COVERAGE(HMM_Rotate_LH, 1)
1974+static inline HMM_Mat4 HMM_Rotate_LH(float Angle, HMM_Vec3 Axis)
1975+{
1976+ ASSERT_COVERED(HMM_Rotate_LH);
1977+ /* NOTE(lcf): Matrix will be inverse/transpose of RH. */
1978+ return HMM_Rotate_RH(-Angle, Axis);
1979+}
1980+
1981+COVERAGE(HMM_InvRotate, 1)
1982+static inline HMM_Mat4 HMM_InvRotate(HMM_Mat4 RotationMatrix)
1983+{
1984+ ASSERT_COVERED(HMM_InvRotate);
1985+ return HMM_TransposeM4(RotationMatrix);
1986+}
1987+
1988+COVERAGE(HMM_Scale, 1)
1989+static inline HMM_Mat4 HMM_Scale(HMM_Vec3 Scale)
1990+{
1991+ ASSERT_COVERED(HMM_Scale);
1992+
1993+ HMM_Mat4 Result = HMM_M4D(1.0f);
1994+ Result.Elements[0][0] = Scale.X;
1995+ Result.Elements[1][1] = Scale.Y;
1996+ Result.Elements[2][2] = Scale.Z;
1997+
1998+ return Result;
1999+}
2000+
2001+COVERAGE(HMM_InvScale, 1)
2002+static inline HMM_Mat4 HMM_InvScale(HMM_Mat4 ScaleMatrix)
2003+{
2004+ ASSERT_COVERED(HMM_InvScale);
2005+
2006+ HMM_Mat4 Result = ScaleMatrix;
2007+ Result.Elements[0][0] = 1.0f / Result.Elements[0][0];
2008+ Result.Elements[1][1] = 1.0f / Result.Elements[1][1];
2009+ Result.Elements[2][2] = 1.0f / Result.Elements[2][2];
2010+
2011+ return Result;
2012+}
2013+
2014+static inline HMM_Mat4 _HMM_LookAt(HMM_Vec3 F, HMM_Vec3 S, HMM_Vec3 U, HMM_Vec3 Eye)
2015+{
2016+ HMM_Mat4 Result;
2017+
2018+ Result.Elements[0][0] = S.X;
2019+ Result.Elements[0][1] = U.X;
2020+ Result.Elements[0][2] = -F.X;
2021+ Result.Elements[0][3] = 0.0f;
2022+
2023+ Result.Elements[1][0] = S.Y;
2024+ Result.Elements[1][1] = U.Y;
2025+ Result.Elements[1][2] = -F.Y;
2026+ Result.Elements[1][3] = 0.0f;
2027+
2028+ Result.Elements[2][0] = S.Z;
2029+ Result.Elements[2][1] = U.Z;
2030+ Result.Elements[2][2] = -F.Z;
2031+ Result.Elements[2][3] = 0.0f;
2032+
2033+ Result.Elements[3][0] = -HMM_DotV3(S, Eye);
2034+ Result.Elements[3][1] = -HMM_DotV3(U, Eye);
2035+ Result.Elements[3][2] = HMM_DotV3(F, Eye);
2036+ Result.Elements[3][3] = 1.0f;
2037+
2038+ return Result;
2039+}
2040+
2041+COVERAGE(HMM_LookAt_RH, 1)
2042+static inline HMM_Mat4 HMM_LookAt_RH(HMM_Vec3 Eye, HMM_Vec3 Center, HMM_Vec3 Up)
2043+{
2044+ ASSERT_COVERED(HMM_LookAt_RH);
2045+
2046+ HMM_Vec3 F = HMM_NormV3(HMM_SubV3(Center, Eye));
2047+ HMM_Vec3 S = HMM_NormV3(HMM_Cross(F, Up));
2048+ HMM_Vec3 U = HMM_Cross(S, F);
2049+
2050+ return _HMM_LookAt(F, S, U, Eye);
2051+}
2052+
2053+COVERAGE(HMM_LookAt_LH, 1)
2054+static inline HMM_Mat4 HMM_LookAt_LH(HMM_Vec3 Eye, HMM_Vec3 Center, HMM_Vec3 Up)
2055+{
2056+ ASSERT_COVERED(HMM_LookAt_LH);
2057+
2058+ HMM_Vec3 F = HMM_NormV3(HMM_SubV3(Eye, Center));
2059+ HMM_Vec3 S = HMM_NormV3(HMM_Cross(F, Up));
2060+ HMM_Vec3 U = HMM_Cross(S, F);
2061+
2062+ return _HMM_LookAt(F, S, U, Eye);
2063+}
2064+
2065+COVERAGE(HMM_InvLookAt, 1)
2066+static inline HMM_Mat4 HMM_InvLookAt(HMM_Mat4 Matrix)
2067+{
2068+ ASSERT_COVERED(HMM_InvLookAt);
2069+ HMM_Mat4 Result;
2070+
2071+ HMM_Mat3 Rotation = {0};
2072+ Rotation.Columns[0] = Matrix.Columns[0].XYZ;
2073+ Rotation.Columns[1] = Matrix.Columns[1].XYZ;
2074+ Rotation.Columns[2] = Matrix.Columns[2].XYZ;
2075+ Rotation = HMM_TransposeM3(Rotation);
2076+
2077+ Result.Columns[0] = HMM_V4V(Rotation.Columns[0], 0.0f);
2078+ Result.Columns[1] = HMM_V4V(Rotation.Columns[1], 0.0f);
2079+ Result.Columns[2] = HMM_V4V(Rotation.Columns[2], 0.0f);
2080+ Result.Columns[3] = HMM_MulV4F(Matrix.Columns[3], -1.0f);
2081+ Result.Elements[3][0] = -1.0f * Matrix.Elements[3][0] /
2082+ (Rotation.Elements[0][0] + Rotation.Elements[0][1] + Rotation.Elements[0][2]);
2083+ Result.Elements[3][1] = -1.0f * Matrix.Elements[3][1] /
2084+ (Rotation.Elements[1][0] + Rotation.Elements[1][1] + Rotation.Elements[1][2]);
2085+ Result.Elements[3][2] = -1.0f * Matrix.Elements[3][2] /
2086+ (Rotation.Elements[2][0] + Rotation.Elements[2][1] + Rotation.Elements[2][2]);
2087+ Result.Elements[3][3] = 1.0f;
2088+
2089+ return Result;
2090+}
2091+
2092+/*
2093+ * Quaternion operations
2094+ */
2095+
2096+COVERAGE(HMM_Q, 1)
2097+static inline HMM_Quat HMM_Q(float X, float Y, float Z, float W)
2098+{
2099+ ASSERT_COVERED(HMM_Q);
2100+
2101+ HMM_Quat Result;
2102+
2103+#ifdef HANDMADE_MATH__USE_SSE
2104+ Result.SSE = _mm_setr_ps(X, Y, Z, W);
2105+#elif defined(HANDMADE_MATH__USE_NEON)
2106+ float32x4_t v = { X, Y, Z, W };
2107+ Result.NEON = v;
2108+#else
2109+ Result.X = X;
2110+ Result.Y = Y;
2111+ Result.Z = Z;
2112+ Result.W = W;
2113+#endif
2114+
2115+ return Result;
2116+}
2117+
2118+COVERAGE(HMM_QV4, 1)
2119+static inline HMM_Quat HMM_QV4(HMM_Vec4 Vector)
2120+{
2121+ ASSERT_COVERED(HMM_QV4);
2122+
2123+ HMM_Quat Result;
2124+
2125+#ifdef HANDMADE_MATH__USE_SSE
2126+ Result.SSE = Vector.SSE;
2127+#elif defined(HANDMADE_MATH__USE_NEON)
2128+ Result.NEON = Vector.NEON;
2129+#else
2130+ Result.X = Vector.X;
2131+ Result.Y = Vector.Y;
2132+ Result.Z = Vector.Z;
2133+ Result.W = Vector.W;
2134+#endif
2135+
2136+ return Result;
2137+}
2138+
2139+COVERAGE(HMM_AddQ, 1)
2140+static inline HMM_Quat HMM_AddQ(HMM_Quat Left, HMM_Quat Right)
2141+{
2142+ ASSERT_COVERED(HMM_AddQ);
2143+
2144+ HMM_Quat Result;
2145+
2146+#ifdef HANDMADE_MATH__USE_SSE
2147+ Result.SSE = _mm_add_ps(Left.SSE, Right.SSE);
2148+#elif defined(HANDMADE_MATH__USE_NEON)
2149+ Result.NEON = vaddq_f32(Left.NEON, Right.NEON);
2150+#else
2151+
2152+ Result.X = Left.X + Right.X;
2153+ Result.Y = Left.Y + Right.Y;
2154+ Result.Z = Left.Z + Right.Z;
2155+ Result.W = Left.W + Right.W;
2156+#endif
2157+
2158+ return Result;
2159+}
2160+
2161+COVERAGE(HMM_SubQ, 1)
2162+static inline HMM_Quat HMM_SubQ(HMM_Quat Left, HMM_Quat Right)
2163+{
2164+ ASSERT_COVERED(HMM_SubQ);
2165+
2166+ HMM_Quat Result;
2167+
2168+#ifdef HANDMADE_MATH__USE_SSE
2169+ Result.SSE = _mm_sub_ps(Left.SSE, Right.SSE);
2170+#elif defined(HANDMADE_MATH__USE_NEON)
2171+ Result.NEON = vsubq_f32(Left.NEON, Right.NEON);
2172+#else
2173+ Result.X = Left.X - Right.X;
2174+ Result.Y = Left.Y - Right.Y;
2175+ Result.Z = Left.Z - Right.Z;
2176+ Result.W = Left.W - Right.W;
2177+#endif
2178+
2179+ return Result;
2180+}
2181+
2182+COVERAGE(HMM_MulQ, 1)
2183+static inline HMM_Quat HMM_MulQ(HMM_Quat Left, HMM_Quat Right)
2184+{
2185+ ASSERT_COVERED(HMM_MulQ);
2186+
2187+ HMM_Quat Result;
2188+
2189+#ifdef HANDMADE_MATH__USE_SSE
2190+ __m128 SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.SSE, Left.SSE, _MM_SHUFFLE(0, 0, 0, 0)), _mm_setr_ps(0.f, -0.f, 0.f, -0.f));
2191+ __m128 SSEResultTwo = _mm_shuffle_ps(Right.SSE, Right.SSE, _MM_SHUFFLE(0, 1, 2, 3));
2192+ __m128 SSEResultThree = _mm_mul_ps(SSEResultTwo, SSEResultOne);
2193+
2194+ SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.SSE, Left.SSE, _MM_SHUFFLE(1, 1, 1, 1)) , _mm_setr_ps(0.f, 0.f, -0.f, -0.f));
2195+ SSEResultTwo = _mm_shuffle_ps(Right.SSE, Right.SSE, _MM_SHUFFLE(1, 0, 3, 2));
2196+ SSEResultThree = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne));
2197+
2198+ SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.SSE, Left.SSE, _MM_SHUFFLE(2, 2, 2, 2)), _mm_setr_ps(-0.f, 0.f, 0.f, -0.f));
2199+ SSEResultTwo = _mm_shuffle_ps(Right.SSE, Right.SSE, _MM_SHUFFLE(2, 3, 0, 1));
2200+ SSEResultThree = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne));
2201+
2202+ SSEResultOne = _mm_shuffle_ps(Left.SSE, Left.SSE, _MM_SHUFFLE(3, 3, 3, 3));
2203+ SSEResultTwo = _mm_shuffle_ps(Right.SSE, Right.SSE, _MM_SHUFFLE(3, 2, 1, 0));
2204+ Result.SSE = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne));
2205+#elif defined(HANDMADE_MATH__USE_NEON)
2206+ float32x4_t Right1032 = vrev64q_f32(Right.NEON);
2207+ float32x4_t Right3210 = vcombine_f32(vget_high_f32(Right1032), vget_low_f32(Right1032));
2208+ float32x4_t Right2301 = vrev64q_f32(Right3210);
2209+
2210+ float32x4_t FirstSign = {1.0f, -1.0f, 1.0f, -1.0f};
2211+ Result.NEON = vmulq_f32(Right3210, vmulq_f32(vdupq_laneq_f32(Left.NEON, 0), FirstSign));
2212+ float32x4_t SecondSign = {1.0f, 1.0f, -1.0f, -1.0f};
2213+ Result.NEON = vfmaq_f32(Result.NEON, Right2301, vmulq_f32(vdupq_laneq_f32(Left.NEON, 1), SecondSign));
2214+ float32x4_t ThirdSign = {-1.0f, 1.0f, 1.0f, -1.0f};
2215+ Result.NEON = vfmaq_f32(Result.NEON, Right1032, vmulq_f32(vdupq_laneq_f32(Left.NEON, 2), ThirdSign));
2216+ Result.NEON = vfmaq_laneq_f32(Result.NEON, Right.NEON, Left.NEON, 3);
2217+
2218+#else
2219+ Result.X = Right.Elements[3] * +Left.Elements[0];
2220+ Result.Y = Right.Elements[2] * -Left.Elements[0];
2221+ Result.Z = Right.Elements[1] * +Left.Elements[0];
2222+ Result.W = Right.Elements[0] * -Left.Elements[0];
2223+
2224+ Result.X += Right.Elements[2] * +Left.Elements[1];
2225+ Result.Y += Right.Elements[3] * +Left.Elements[1];
2226+ Result.Z += Right.Elements[0] * -Left.Elements[1];
2227+ Result.W += Right.Elements[1] * -Left.Elements[1];
2228+
2229+ Result.X += Right.Elements[1] * -Left.Elements[2];
2230+ Result.Y += Right.Elements[0] * +Left.Elements[2];
2231+ Result.Z += Right.Elements[3] * +Left.Elements[2];
2232+ Result.W += Right.Elements[2] * -Left.Elements[2];
2233+
2234+ Result.X += Right.Elements[0] * +Left.Elements[3];
2235+ Result.Y += Right.Elements[1] * +Left.Elements[3];
2236+ Result.Z += Right.Elements[2] * +Left.Elements[3];
2237+ Result.W += Right.Elements[3] * +Left.Elements[3];
2238+#endif
2239+
2240+ return Result;
2241+}
2242+
2243+COVERAGE(HMM_MulQF, 1)
2244+static inline HMM_Quat HMM_MulQF(HMM_Quat Left, float Multiplicative)
2245+{
2246+ ASSERT_COVERED(HMM_MulQF);
2247+
2248+ HMM_Quat Result;
2249+
2250+#ifdef HANDMADE_MATH__USE_SSE
2251+ __m128 Scalar = _mm_set1_ps(Multiplicative);
2252+ Result.SSE = _mm_mul_ps(Left.SSE, Scalar);
2253+#elif defined(HANDMADE_MATH__USE_NEON)
2254+ Result.NEON = vmulq_n_f32(Left.NEON, Multiplicative);
2255+#else
2256+ Result.X = Left.X * Multiplicative;
2257+ Result.Y = Left.Y * Multiplicative;
2258+ Result.Z = Left.Z * Multiplicative;
2259+ Result.W = Left.W * Multiplicative;
2260+#endif
2261+
2262+ return Result;
2263+}
2264+
2265+COVERAGE(HMM_DivQF, 1)
2266+static inline HMM_Quat HMM_DivQF(HMM_Quat Left, float Divnd)
2267+{
2268+ ASSERT_COVERED(HMM_DivQF);
2269+
2270+ HMM_Quat Result;
2271+
2272+#ifdef HANDMADE_MATH__USE_SSE
2273+ __m128 Scalar = _mm_set1_ps(Divnd);
2274+ Result.SSE = _mm_div_ps(Left.SSE, Scalar);
2275+#elif defined(HANDMADE_MATH__USE_NEON)
2276+ float32x4_t Scalar = vdupq_n_f32(Divnd);
2277+ Result.NEON = vdivq_f32(Left.NEON, Scalar);
2278+#else
2279+ Result.X = Left.X / Divnd;
2280+ Result.Y = Left.Y / Divnd;
2281+ Result.Z = Left.Z / Divnd;
2282+ Result.W = Left.W / Divnd;
2283+#endif
2284+
2285+ return Result;
2286+}
2287+
2288+COVERAGE(HMM_DotQ, 1)
2289+static inline float HMM_DotQ(HMM_Quat Left, HMM_Quat Right)
2290+{
2291+ ASSERT_COVERED(HMM_DotQ);
2292+
2293+ float Result;
2294+
2295+#ifdef HANDMADE_MATH__USE_SSE
2296+ __m128 SSEResultOne = _mm_mul_ps(Left.SSE, Right.SSE);
2297+ __m128 SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(2, 3, 0, 1));
2298+ SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo);
2299+ SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(0, 1, 2, 3));
2300+ SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo);
2301+ _mm_store_ss(&Result, SSEResultOne);
2302+#elif defined(HANDMADE_MATH__USE_NEON)
2303+ float32x4_t NEONMultiplyResult = vmulq_f32(Left.NEON, Right.NEON);
2304+ float32x4_t NEONHalfAdd = vpaddq_f32(NEONMultiplyResult, NEONMultiplyResult);
2305+ float32x4_t NEONFullAdd = vpaddq_f32(NEONHalfAdd, NEONHalfAdd);
2306+ Result = vgetq_lane_f32(NEONFullAdd, 0);
2307+#else
2308+ Result = ((Left.X * Right.X) + (Left.Z * Right.Z)) + ((Left.Y * Right.Y) + (Left.W * Right.W));
2309+#endif
2310+
2311+ return Result;
2312+}
2313+
2314+COVERAGE(HMM_InvQ, 1)
2315+static inline HMM_Quat HMM_InvQ(HMM_Quat Left)
2316+{
2317+ ASSERT_COVERED(HMM_InvQ);
2318+
2319+ HMM_Quat Result;
2320+ Result.X = -Left.X;
2321+ Result.Y = -Left.Y;
2322+ Result.Z = -Left.Z;
2323+ Result.W = Left.W;
2324+
2325+ return HMM_DivQF(Result, (HMM_DotQ(Left, Left)));
2326+}
2327+
2328+COVERAGE(HMM_NormQ, 1)
2329+static inline HMM_Quat HMM_NormQ(HMM_Quat Quat)
2330+{
2331+ ASSERT_COVERED(HMM_NormQ);
2332+
2333+ /* NOTE(lcf): Take advantage of SSE implementation in HMM_NormV4 */
2334+ HMM_Vec4 Vec = HMM_V4(Quat.X, Quat.Y, Quat.Z, Quat.W);
2335+ Vec = HMM_NormV4(Vec);
2336+ HMM_Quat Result = HMM_QV4(Vec);
2337+
2338+ return Result;
2339+}
2340+
2341+static inline HMM_Quat _HMM_MixQ(HMM_Quat Left, float MixLeft, HMM_Quat Right, float MixRight) {
2342+ HMM_Quat Result;
2343+
2344+#ifdef HANDMADE_MATH__USE_SSE
2345+ __m128 ScalarLeft = _mm_set1_ps(MixLeft);
2346+ __m128 ScalarRight = _mm_set1_ps(MixRight);
2347+ __m128 SSEResultOne = _mm_mul_ps(Left.SSE, ScalarLeft);
2348+ __m128 SSEResultTwo = _mm_mul_ps(Right.SSE, ScalarRight);
2349+ Result.SSE = _mm_add_ps(SSEResultOne, SSEResultTwo);
2350+#elif defined(HANDMADE_MATH__USE_NEON)
2351+ float32x4_t ScaledLeft = vmulq_n_f32(Left.NEON, MixLeft);
2352+ float32x4_t ScaledRight = vmulq_n_f32(Right.NEON, MixRight);
2353+ Result.NEON = vaddq_f32(ScaledLeft, ScaledRight);
2354+#else
2355+ Result.X = Left.X*MixLeft + Right.X*MixRight;
2356+ Result.Y = Left.Y*MixLeft + Right.Y*MixRight;
2357+ Result.Z = Left.Z*MixLeft + Right.Z*MixRight;
2358+ Result.W = Left.W*MixLeft + Right.W*MixRight;
2359+#endif
2360+
2361+ return Result;
2362+}
2363+
2364+COVERAGE(HMM_NLerp, 1)
2365+static inline HMM_Quat HMM_NLerp(HMM_Quat Left, float Time, HMM_Quat Right)
2366+{
2367+ ASSERT_COVERED(HMM_NLerp);
2368+
2369+ HMM_Quat Result = _HMM_MixQ(Left, 1.0f-Time, Right, Time);
2370+ Result = HMM_NormQ(Result);
2371+
2372+ return Result;
2373+}
2374+
2375+COVERAGE(HMM_SLerp, 1)
2376+static inline HMM_Quat HMM_SLerp(HMM_Quat Left, float Time, HMM_Quat Right)
2377+{
2378+ ASSERT_COVERED(HMM_SLerp);
2379+
2380+ HMM_Quat Result;
2381+
2382+ float Cos_Theta = HMM_DotQ(Left, Right);
2383+
2384+ if (Cos_Theta < 0.0f) { /* NOTE(lcf): Take shortest path on Hyper-sphere */
2385+ Cos_Theta = -Cos_Theta;
2386+ Right = HMM_Q(-Right.X, -Right.Y, -Right.Z, -Right.W);
2387+ }
2388+
2389+ /* NOTE(lcf): Use Normalized Linear interpolation when vectors are roughly not L.I. */
2390+ if (Cos_Theta > 0.9995f) {
2391+ Result = HMM_NLerp(Left, Time, Right);
2392+ } else {
2393+ float Angle = HMM_ACosF(Cos_Theta);
2394+ float MixLeft = HMM_SinF((1.0f - Time) * Angle);
2395+ float MixRight = HMM_SinF(Time * Angle);
2396+
2397+ Result = _HMM_MixQ(Left, MixLeft, Right, MixRight);
2398+ Result = HMM_NormQ(Result);
2399+ }
2400+
2401+ return Result;
2402+}
2403+
2404+COVERAGE(HMM_QToM4, 1)
2405+static inline HMM_Mat4 HMM_QToM4(HMM_Quat Left)
2406+{
2407+ ASSERT_COVERED(HMM_QToM4);
2408+
2409+ HMM_Mat4 Result;
2410+
2411+ HMM_Quat NormalizedQ = HMM_NormQ(Left);
2412+
2413+ float XX, YY, ZZ,
2414+ XY, XZ, YZ,
2415+ WX, WY, WZ;
2416+
2417+ XX = NormalizedQ.X * NormalizedQ.X;
2418+ YY = NormalizedQ.Y * NormalizedQ.Y;
2419+ ZZ = NormalizedQ.Z * NormalizedQ.Z;
2420+ XY = NormalizedQ.X * NormalizedQ.Y;
2421+ XZ = NormalizedQ.X * NormalizedQ.Z;
2422+ YZ = NormalizedQ.Y * NormalizedQ.Z;
2423+ WX = NormalizedQ.W * NormalizedQ.X;
2424+ WY = NormalizedQ.W * NormalizedQ.Y;
2425+ WZ = NormalizedQ.W * NormalizedQ.Z;
2426+
2427+ Result.Elements[0][0] = 1.0f - 2.0f * (YY + ZZ);
2428+ Result.Elements[0][1] = 2.0f * (XY + WZ);
2429+ Result.Elements[0][2] = 2.0f * (XZ - WY);
2430+ Result.Elements[0][3] = 0.0f;
2431+
2432+ Result.Elements[1][0] = 2.0f * (XY - WZ);
2433+ Result.Elements[1][1] = 1.0f - 2.0f * (XX + ZZ);
2434+ Result.Elements[1][2] = 2.0f * (YZ + WX);
2435+ Result.Elements[1][3] = 0.0f;
2436+
2437+ Result.Elements[2][0] = 2.0f * (XZ + WY);
2438+ Result.Elements[2][1] = 2.0f * (YZ - WX);
2439+ Result.Elements[2][2] = 1.0f - 2.0f * (XX + YY);
2440+ Result.Elements[2][3] = 0.0f;
2441+
2442+ Result.Elements[3][0] = 0.0f;
2443+ Result.Elements[3][1] = 0.0f;
2444+ Result.Elements[3][2] = 0.0f;
2445+ Result.Elements[3][3] = 1.0f;
2446+
2447+ return Result;
2448+}
2449+
2450+// This method taken from Mike Day at Insomniac Games.
2451+// https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf
2452+//
2453+// Note that as mentioned at the top of the paper, the paper assumes the matrix
2454+// would be *post*-multiplied to a vector to rotate it, meaning the matrix is
2455+// the transpose of what we're dealing with. But, because our matrices are
2456+// stored in column-major order, the indices *appear* to match the paper.
2457+//
2458+// For example, m12 in the paper is row 1, column 2. We need to transpose it to
2459+// row 2, column 1. But, because the column comes first when referencing
2460+// elements, it looks like M.Elements[1][2].
2461+//
2462+// Don't be confused! Or if you must be confused, at least trust this
2463+// comment. :)
2464+COVERAGE(HMM_M4ToQ_RH, 4)
2465+static inline HMM_Quat HMM_M4ToQ_RH(HMM_Mat4 M)
2466+{
2467+ float T;
2468+ HMM_Quat Q;
2469+
2470+ if (M.Elements[2][2] < 0.0f) {
2471+ if (M.Elements[0][0] > M.Elements[1][1]) {
2472+ ASSERT_COVERED(HMM_M4ToQ_RH);
2473+
2474+ T = 1 + M.Elements[0][0] - M.Elements[1][1] - M.Elements[2][2];
2475+ Q = HMM_Q(
2476+ T,
2477+ M.Elements[0][1] + M.Elements[1][0],
2478+ M.Elements[2][0] + M.Elements[0][2],
2479+ M.Elements[1][2] - M.Elements[2][1]
2480+ );
2481+ } else {
2482+ ASSERT_COVERED(HMM_M4ToQ_RH);
2483+
2484+ T = 1 - M.Elements[0][0] + M.Elements[1][1] - M.Elements[2][2];
2485+ Q = HMM_Q(
2486+ M.Elements[0][1] + M.Elements[1][0],
2487+ T,
2488+ M.Elements[1][2] + M.Elements[2][1],
2489+ M.Elements[2][0] - M.Elements[0][2]
2490+ );
2491+ }
2492+ } else {
2493+ if (M.Elements[0][0] < -M.Elements[1][1]) {
2494+ ASSERT_COVERED(HMM_M4ToQ_RH);
2495+
2496+ T = 1 - M.Elements[0][0] - M.Elements[1][1] + M.Elements[2][2];
2497+ Q = HMM_Q(
2498+ M.Elements[2][0] + M.Elements[0][2],
2499+ M.Elements[1][2] + M.Elements[2][1],
2500+ T,
2501+ M.Elements[0][1] - M.Elements[1][0]
2502+ );
2503+ } else {
2504+ ASSERT_COVERED(HMM_M4ToQ_RH);
2505+
2506+ T = 1 + M.Elements[0][0] + M.Elements[1][1] + M.Elements[2][2];
2507+ Q = HMM_Q(
2508+ M.Elements[1][2] - M.Elements[2][1],
2509+ M.Elements[2][0] - M.Elements[0][2],
2510+ M.Elements[0][1] - M.Elements[1][0],
2511+ T
2512+ );
2513+ }
2514+ }
2515+
2516+ Q = HMM_MulQF(Q, 0.5f / HMM_SqrtF(T));
2517+
2518+ return Q;
2519+}
2520+
2521+COVERAGE(HMM_M4ToQ_LH, 4)
2522+static inline HMM_Quat HMM_M4ToQ_LH(HMM_Mat4 M)
2523+{
2524+ float T;
2525+ HMM_Quat Q;
2526+
2527+ if (M.Elements[2][2] < 0.0f) {
2528+ if (M.Elements[0][0] > M.Elements[1][1]) {
2529+ ASSERT_COVERED(HMM_M4ToQ_LH);
2530+
2531+ T = 1 + M.Elements[0][0] - M.Elements[1][1] - M.Elements[2][2];
2532+ Q = HMM_Q(
2533+ T,
2534+ M.Elements[0][1] + M.Elements[1][0],
2535+ M.Elements[2][0] + M.Elements[0][2],
2536+ M.Elements[2][1] - M.Elements[1][2]
2537+ );
2538+ } else {
2539+ ASSERT_COVERED(HMM_M4ToQ_LH);
2540+
2541+ T = 1 - M.Elements[0][0] + M.Elements[1][1] - M.Elements[2][2];
2542+ Q = HMM_Q(
2543+ M.Elements[0][1] + M.Elements[1][0],
2544+ T,
2545+ M.Elements[1][2] + M.Elements[2][1],
2546+ M.Elements[0][2] - M.Elements[2][0]
2547+ );
2548+ }
2549+ } else {
2550+ if (M.Elements[0][0] < -M.Elements[1][1]) {
2551+ ASSERT_COVERED(HMM_M4ToQ_LH);
2552+
2553+ T = 1 - M.Elements[0][0] - M.Elements[1][1] + M.Elements[2][2];
2554+ Q = HMM_Q(
2555+ M.Elements[2][0] + M.Elements[0][2],
2556+ M.Elements[1][2] + M.Elements[2][1],
2557+ T,
2558+ M.Elements[1][0] - M.Elements[0][1]
2559+ );
2560+ } else {
2561+ ASSERT_COVERED(HMM_M4ToQ_LH);
2562+
2563+ T = 1 + M.Elements[0][0] + M.Elements[1][1] + M.Elements[2][2];
2564+ Q = HMM_Q(
2565+ M.Elements[2][1] - M.Elements[1][2],
2566+ M.Elements[0][2] - M.Elements[2][0],
2567+ M.Elements[1][0] - M.Elements[0][2],
2568+ T
2569+ );
2570+ }
2571+ }
2572+
2573+ Q = HMM_MulQF(Q, 0.5f / HMM_SqrtF(T));
2574+
2575+ return Q;
2576+}
2577+
2578+
2579+COVERAGE(HMM_QFromAxisAngle_RH, 1)
2580+static inline HMM_Quat HMM_QFromAxisAngle_RH(HMM_Vec3 Axis, float Angle)
2581+{
2582+ ASSERT_COVERED(HMM_QFromAxisAngle_RH);
2583+
2584+ HMM_Quat Result;
2585+
2586+ HMM_Vec3 AxisNormalized = HMM_NormV3(Axis);
2587+ float SineOfRotation = HMM_SinF(Angle / 2.0f);
2588+
2589+ Result.XYZ = HMM_MulV3F(AxisNormalized, SineOfRotation);
2590+ Result.W = HMM_CosF(Angle / 2.0f);
2591+
2592+ return Result;
2593+}
2594+
2595+COVERAGE(HMM_QFromAxisAngle_LH, 1)
2596+static inline HMM_Quat HMM_QFromAxisAngle_LH(HMM_Vec3 Axis, float Angle)
2597+{
2598+ ASSERT_COVERED(HMM_QFromAxisAngle_LH);
2599+
2600+ return HMM_QFromAxisAngle_RH(Axis, -Angle);
2601+}
2602+
2603+COVERAGE(HMM_QFromNormPair, 1)
2604+static inline HMM_Quat HMM_QFromNormPair(HMM_Vec3 Left, HMM_Vec3 Right)
2605+{
2606+ ASSERT_COVERED(HMM_QFromNormPair);
2607+
2608+ HMM_Quat Result;
2609+
2610+ Result.XYZ = HMM_Cross(Left, Right);
2611+ Result.W = 1.0f + HMM_DotV3(Left, Right);
2612+
2613+ return HMM_NormQ(Result);
2614+}
2615+
2616+COVERAGE(HMM_QFromVecPair, 1)
2617+static inline HMM_Quat HMM_QFromVecPair(HMM_Vec3 Left, HMM_Vec3 Right)
2618+{
2619+ ASSERT_COVERED(HMM_QFromVecPair);
2620+
2621+ return HMM_QFromNormPair(HMM_NormV3(Left), HMM_NormV3(Right));
2622+}
2623+
2624+COVERAGE(HMM_RotateV2, 1)
2625+static inline HMM_Vec2 HMM_RotateV2(HMM_Vec2 V, float Angle)
2626+{
2627+ ASSERT_COVERED(HMM_RotateV2)
2628+
2629+ float sinA = HMM_SinF(Angle);
2630+ float cosA = HMM_CosF(Angle);
2631+
2632+ return HMM_V2(V.X * cosA - V.Y * sinA, V.X * sinA + V.Y * cosA);
2633+}
2634+
2635+// implementation from
2636+// https://blog.molecular-matters.com/2013/05/24/a-faster-quaternion-vector-multiplication/
2637+COVERAGE(HMM_RotateV3Q, 1)
2638+static inline HMM_Vec3 HMM_RotateV3Q(HMM_Vec3 V, HMM_Quat Q)
2639+{
2640+ ASSERT_COVERED(HMM_RotateV3Q);
2641+
2642+ HMM_Vec3 t = HMM_MulV3F(HMM_Cross(Q.XYZ, V), 2);
2643+ return HMM_AddV3(V, HMM_AddV3(HMM_MulV3F(t, Q.W), HMM_Cross(Q.XYZ, t)));
2644+}
2645+
2646+COVERAGE(HMM_RotateV3AxisAngle_LH, 1)
2647+static inline HMM_Vec3 HMM_RotateV3AxisAngle_LH(HMM_Vec3 V, HMM_Vec3 Axis, float Angle) {
2648+ ASSERT_COVERED(HMM_RotateV3AxisAngle_LH);
2649+
2650+ return HMM_RotateV3Q(V, HMM_QFromAxisAngle_LH(Axis, Angle));
2651+}
2652+
2653+COVERAGE(HMM_RotateV3AxisAngle_RH, 1)
2654+static inline HMM_Vec3 HMM_RotateV3AxisAngle_RH(HMM_Vec3 V, HMM_Vec3 Axis, float Angle) {
2655+ ASSERT_COVERED(HMM_RotateV3AxisAngle_RH);
2656+
2657+ return HMM_RotateV3Q(V, HMM_QFromAxisAngle_RH(Axis, Angle));
2658+}
2659+
2660+
2661+#ifdef __cplusplus
2662+}
2663+#endif
2664+
2665+#ifdef __cplusplus
2666+
2667+COVERAGE(HMM_LenV2CPP, 1)
2668+static inline float HMM_Len(HMM_Vec2 A)
2669+{
2670+ ASSERT_COVERED(HMM_LenV2CPP);
2671+ return HMM_LenV2(A);
2672+}
2673+
2674+COVERAGE(HMM_LenV3CPP, 1)
2675+static inline float HMM_Len(HMM_Vec3 A)
2676+{
2677+ ASSERT_COVERED(HMM_LenV3CPP);
2678+ return HMM_LenV3(A);
2679+}
2680+
2681+COVERAGE(HMM_LenV4CPP, 1)
2682+static inline float HMM_Len(HMM_Vec4 A)
2683+{
2684+ ASSERT_COVERED(HMM_LenV4CPP);
2685+ return HMM_LenV4(A);
2686+}
2687+
2688+COVERAGE(HMM_LenSqrV2CPP, 1)
2689+static inline float HMM_LenSqr(HMM_Vec2 A)
2690+{
2691+ ASSERT_COVERED(HMM_LenSqrV2CPP);
2692+ return HMM_LenSqrV2(A);
2693+}
2694+
2695+COVERAGE(HMM_LenSqrV3CPP, 1)
2696+static inline float HMM_LenSqr(HMM_Vec3 A)
2697+{
2698+ ASSERT_COVERED(HMM_LenSqrV3CPP);
2699+ return HMM_LenSqrV3(A);
2700+}
2701+
2702+COVERAGE(HMM_LenSqrV4CPP, 1)
2703+static inline float HMM_LenSqr(HMM_Vec4 A)
2704+{
2705+ ASSERT_COVERED(HMM_LenSqrV4CPP);
2706+ return HMM_LenSqrV4(A);
2707+}
2708+
2709+COVERAGE(HMM_NormV2CPP, 1)
2710+static inline HMM_Vec2 HMM_Norm(HMM_Vec2 A)
2711+{
2712+ ASSERT_COVERED(HMM_NormV2CPP);
2713+ return HMM_NormV2(A);
2714+}
2715+
2716+COVERAGE(HMM_NormV3CPP, 1)
2717+static inline HMM_Vec3 HMM_Norm(HMM_Vec3 A)
2718+{
2719+ ASSERT_COVERED(HMM_NormV3CPP);
2720+ return HMM_NormV3(A);
2721+}
2722+
2723+COVERAGE(HMM_NormV4CPP, 1)
2724+static inline HMM_Vec4 HMM_Norm(HMM_Vec4 A)
2725+{
2726+ ASSERT_COVERED(HMM_NormV4CPP);
2727+ return HMM_NormV4(A);
2728+}
2729+
2730+COVERAGE(HMM_NormQCPP, 1)
2731+static inline HMM_Quat HMM_Norm(HMM_Quat A)
2732+{
2733+ ASSERT_COVERED(HMM_NormQCPP);
2734+ return HMM_NormQ(A);
2735+}
2736+
2737+COVERAGE(HMM_DotV2CPP, 1)
2738+static inline float HMM_Dot(HMM_Vec2 Left, HMM_Vec2 VecTwo)
2739+{
2740+ ASSERT_COVERED(HMM_DotV2CPP);
2741+ return HMM_DotV2(Left, VecTwo);
2742+}
2743+
2744+COVERAGE(HMM_DotV3CPP, 1)
2745+static inline float HMM_Dot(HMM_Vec3 Left, HMM_Vec3 VecTwo)
2746+{
2747+ ASSERT_COVERED(HMM_DotV3CPP);
2748+ return HMM_DotV3(Left, VecTwo);
2749+}
2750+
2751+COVERAGE(HMM_DotV4CPP, 1)
2752+static inline float HMM_Dot(HMM_Vec4 Left, HMM_Vec4 VecTwo)
2753+{
2754+ ASSERT_COVERED(HMM_DotV4CPP);
2755+ return HMM_DotV4(Left, VecTwo);
2756+}
2757+
2758+COVERAGE(HMM_LerpV2CPP, 1)
2759+static inline HMM_Vec2 HMM_Lerp(HMM_Vec2 Left, float Time, HMM_Vec2 Right)
2760+{
2761+ ASSERT_COVERED(HMM_LerpV2CPP);
2762+ return HMM_LerpV2(Left, Time, Right);
2763+}
2764+
2765+COVERAGE(HMM_LerpV3CPP, 1)
2766+static inline HMM_Vec3 HMM_Lerp(HMM_Vec3 Left, float Time, HMM_Vec3 Right)
2767+{
2768+ ASSERT_COVERED(HMM_LerpV3CPP);
2769+ return HMM_LerpV3(Left, Time, Right);
2770+}
2771+
2772+COVERAGE(HMM_LerpV4CPP, 1)
2773+static inline HMM_Vec4 HMM_Lerp(HMM_Vec4 Left, float Time, HMM_Vec4 Right)
2774+{
2775+ ASSERT_COVERED(HMM_LerpV4CPP);
2776+ return HMM_LerpV4(Left, Time, Right);
2777+}
2778+
2779+COVERAGE(HMM_TransposeM2CPP, 1)
2780+static inline HMM_Mat2 HMM_Transpose(HMM_Mat2 Matrix)
2781+{
2782+ ASSERT_COVERED(HMM_TransposeM2CPP);
2783+ return HMM_TransposeM2(Matrix);
2784+}
2785+
2786+COVERAGE(HMM_TransposeM3CPP, 1)
2787+static inline HMM_Mat3 HMM_Transpose(HMM_Mat3 Matrix)
2788+{
2789+ ASSERT_COVERED(HMM_TransposeM3CPP);
2790+ return HMM_TransposeM3(Matrix);
2791+}
2792+
2793+COVERAGE(HMM_TransposeM4CPP, 1)
2794+static inline HMM_Mat4 HMM_Transpose(HMM_Mat4 Matrix)
2795+{
2796+ ASSERT_COVERED(HMM_TransposeM4CPP);
2797+ return HMM_TransposeM4(Matrix);
2798+}
2799+
2800+COVERAGE(HMM_DeterminantM2CPP, 1)
2801+static inline float HMM_Determinant(HMM_Mat2 Matrix)
2802+{
2803+ ASSERT_COVERED(HMM_DeterminantM2CPP);
2804+ return HMM_DeterminantM2(Matrix);
2805+}
2806+
2807+COVERAGE(HMM_DeterminantM3CPP, 1)
2808+static inline float HMM_Determinant(HMM_Mat3 Matrix)
2809+{
2810+ ASSERT_COVERED(HMM_DeterminantM3CPP);
2811+ return HMM_DeterminantM3(Matrix);
2812+}
2813+
2814+COVERAGE(HMM_DeterminantM4CPP, 1)
2815+static inline float HMM_Determinant(HMM_Mat4 Matrix)
2816+{
2817+ ASSERT_COVERED(HMM_DeterminantM4CPP);
2818+ return HMM_DeterminantM4(Matrix);
2819+}
2820+
2821+COVERAGE(HMM_InvGeneralM2CPP, 1)
2822+static inline HMM_Mat2 HMM_InvGeneral(HMM_Mat2 Matrix)
2823+{
2824+ ASSERT_COVERED(HMM_InvGeneralM2CPP);
2825+ return HMM_InvGeneralM2(Matrix);
2826+}
2827+
2828+COVERAGE(HMM_InvGeneralM3CPP, 1)
2829+static inline HMM_Mat3 HMM_InvGeneral(HMM_Mat3 Matrix)
2830+{
2831+ ASSERT_COVERED(HMM_InvGeneralM3CPP);
2832+ return HMM_InvGeneralM3(Matrix);
2833+}
2834+
2835+COVERAGE(HMM_InvGeneralM4CPP, 1)
2836+static inline HMM_Mat4 HMM_InvGeneral(HMM_Mat4 Matrix)
2837+{
2838+ ASSERT_COVERED(HMM_InvGeneralM4CPP);
2839+ return HMM_InvGeneralM4(Matrix);
2840+}
2841+
2842+COVERAGE(HMM_DotQCPP, 1)
2843+static inline float HMM_Dot(HMM_Quat QuatOne, HMM_Quat QuatTwo)
2844+{
2845+ ASSERT_COVERED(HMM_DotQCPP);
2846+ return HMM_DotQ(QuatOne, QuatTwo);
2847+}
2848+
2849+COVERAGE(HMM_AddV2CPP, 1)
2850+static inline HMM_Vec2 HMM_Add(HMM_Vec2 Left, HMM_Vec2 Right)
2851+{
2852+ ASSERT_COVERED(HMM_AddV2CPP);
2853+ return HMM_AddV2(Left, Right);
2854+}
2855+
2856+COVERAGE(HMM_AddV3CPP, 1)
2857+static inline HMM_Vec3 HMM_Add(HMM_Vec3 Left, HMM_Vec3 Right)
2858+{
2859+ ASSERT_COVERED(HMM_AddV3CPP);
2860+ return HMM_AddV3(Left, Right);
2861+}
2862+
2863+COVERAGE(HMM_AddV4CPP, 1)
2864+static inline HMM_Vec4 HMM_Add(HMM_Vec4 Left, HMM_Vec4 Right)
2865+{
2866+ ASSERT_COVERED(HMM_AddV4CPP);
2867+ return HMM_AddV4(Left, Right);
2868+}
2869+
2870+COVERAGE(HMM_AddM2CPP, 1)
2871+static inline HMM_Mat2 HMM_Add(HMM_Mat2 Left, HMM_Mat2 Right)
2872+{
2873+ ASSERT_COVERED(HMM_AddM2CPP);
2874+ return HMM_AddM2(Left, Right);
2875+}
2876+
2877+COVERAGE(HMM_AddM3CPP, 1)
2878+static inline HMM_Mat3 HMM_Add(HMM_Mat3 Left, HMM_Mat3 Right)
2879+{
2880+ ASSERT_COVERED(HMM_AddM3CPP);
2881+ return HMM_AddM3(Left, Right);
2882+}
2883+
2884+COVERAGE(HMM_AddM4CPP, 1)
2885+static inline HMM_Mat4 HMM_Add(HMM_Mat4 Left, HMM_Mat4 Right)
2886+{
2887+ ASSERT_COVERED(HMM_AddM4CPP);
2888+ return HMM_AddM4(Left, Right);
2889+}
2890+
2891+COVERAGE(HMM_AddQCPP, 1)
2892+static inline HMM_Quat HMM_Add(HMM_Quat Left, HMM_Quat Right)
2893+{
2894+ ASSERT_COVERED(HMM_AddQCPP);
2895+ return HMM_AddQ(Left, Right);
2896+}
2897+
2898+COVERAGE(HMM_SubV2CPP, 1)
2899+static inline HMM_Vec2 HMM_Sub(HMM_Vec2 Left, HMM_Vec2 Right)
2900+{
2901+ ASSERT_COVERED(HMM_SubV2CPP);
2902+ return HMM_SubV2(Left, Right);
2903+}
2904+
2905+COVERAGE(HMM_SubV3CPP, 1)
2906+static inline HMM_Vec3 HMM_Sub(HMM_Vec3 Left, HMM_Vec3 Right)
2907+{
2908+ ASSERT_COVERED(HMM_SubV3CPP);
2909+ return HMM_SubV3(Left, Right);
2910+}
2911+
2912+COVERAGE(HMM_SubV4CPP, 1)
2913+static inline HMM_Vec4 HMM_Sub(HMM_Vec4 Left, HMM_Vec4 Right)
2914+{
2915+ ASSERT_COVERED(HMM_SubV4CPP);
2916+ return HMM_SubV4(Left, Right);
2917+}
2918+
2919+COVERAGE(HMM_SubM2CPP, 1)
2920+static inline HMM_Mat2 HMM_Sub(HMM_Mat2 Left, HMM_Mat2 Right)
2921+{
2922+ ASSERT_COVERED(HMM_SubM2CPP);
2923+ return HMM_SubM2(Left, Right);
2924+}
2925+
2926+COVERAGE(HMM_SubM3CPP, 1)
2927+static inline HMM_Mat3 HMM_Sub(HMM_Mat3 Left, HMM_Mat3 Right)
2928+{
2929+ ASSERT_COVERED(HMM_SubM3CPP);
2930+ return HMM_SubM3(Left, Right);
2931+}
2932+
2933+COVERAGE(HMM_SubM4CPP, 1)
2934+static inline HMM_Mat4 HMM_Sub(HMM_Mat4 Left, HMM_Mat4 Right)
2935+{
2936+ ASSERT_COVERED(HMM_SubM4CPP);
2937+ return HMM_SubM4(Left, Right);
2938+}
2939+
2940+COVERAGE(HMM_SubQCPP, 1)
2941+static inline HMM_Quat HMM_Sub(HMM_Quat Left, HMM_Quat Right)
2942+{
2943+ ASSERT_COVERED(HMM_SubQCPP);
2944+ return HMM_SubQ(Left, Right);
2945+}
2946+
2947+COVERAGE(HMM_MulV2CPP, 1)
2948+static inline HMM_Vec2 HMM_Mul(HMM_Vec2 Left, HMM_Vec2 Right)
2949+{
2950+ ASSERT_COVERED(HMM_MulV2CPP);
2951+ return HMM_MulV2(Left, Right);
2952+}
2953+
2954+COVERAGE(HMM_MulV2FCPP, 1)
2955+static inline HMM_Vec2 HMM_Mul(HMM_Vec2 Left, float Right)
2956+{
2957+ ASSERT_COVERED(HMM_MulV2FCPP);
2958+ return HMM_MulV2F(Left, Right);
2959+}
2960+
2961+COVERAGE(HMM_MulV3CPP, 1)
2962+static inline HMM_Vec3 HMM_Mul(HMM_Vec3 Left, HMM_Vec3 Right)
2963+{
2964+ ASSERT_COVERED(HMM_MulV3CPP);
2965+ return HMM_MulV3(Left, Right);
2966+}
2967+
2968+COVERAGE(HMM_MulV3FCPP, 1)
2969+static inline HMM_Vec3 HMM_Mul(HMM_Vec3 Left, float Right)
2970+{
2971+ ASSERT_COVERED(HMM_MulV3FCPP);
2972+ return HMM_MulV3F(Left, Right);
2973+}
2974+
2975+COVERAGE(HMM_MulV4CPP, 1)
2976+static inline HMM_Vec4 HMM_Mul(HMM_Vec4 Left, HMM_Vec4 Right)
2977+{
2978+ ASSERT_COVERED(HMM_MulV4CPP);
2979+ return HMM_MulV4(Left, Right);
2980+}
2981+
2982+COVERAGE(HMM_MulV4FCPP, 1)
2983+static inline HMM_Vec4 HMM_Mul(HMM_Vec4 Left, float Right)
2984+{
2985+ ASSERT_COVERED(HMM_MulV4FCPP);
2986+ return HMM_MulV4F(Left, Right);
2987+}
2988+
2989+COVERAGE(HMM_MulM2CPP, 1)
2990+static inline HMM_Mat2 HMM_Mul(HMM_Mat2 Left, HMM_Mat2 Right)
2991+{
2992+ ASSERT_COVERED(HMM_MulM2CPP);
2993+ return HMM_MulM2(Left, Right);
2994+}
2995+
2996+COVERAGE(HMM_MulM3CPP, 1)
2997+static inline HMM_Mat3 HMM_Mul(HMM_Mat3 Left, HMM_Mat3 Right)
2998+{
2999+ ASSERT_COVERED(HMM_MulM3CPP);
3000+ return HMM_MulM3(Left, Right);
3001+}
3002+
3003+COVERAGE(HMM_MulM4CPP, 1)
3004+static inline HMM_Mat4 HMM_Mul(HMM_Mat4 Left, HMM_Mat4 Right)
3005+{
3006+ ASSERT_COVERED(HMM_MulM4CPP);
3007+ return HMM_MulM4(Left, Right);
3008+}
3009+
3010+COVERAGE(HMM_MulM2FCPP, 1)
3011+static inline HMM_Mat2 HMM_Mul(HMM_Mat2 Left, float Right)
3012+{
3013+ ASSERT_COVERED(HMM_MulM2FCPP);
3014+ return HMM_MulM2F(Left, Right);
3015+}
3016+
3017+COVERAGE(HMM_MulM3FCPP, 1)
3018+static inline HMM_Mat3 HMM_Mul(HMM_Mat3 Left, float Right)
3019+{
3020+ ASSERT_COVERED(HMM_MulM3FCPP);
3021+ return HMM_MulM3F(Left, Right);
3022+}
3023+
3024+COVERAGE(HMM_MulM4FCPP, 1)
3025+static inline HMM_Mat4 HMM_Mul(HMM_Mat4 Left, float Right)
3026+{
3027+ ASSERT_COVERED(HMM_MulM4FCPP);
3028+ return HMM_MulM4F(Left, Right);
3029+}
3030+
3031+COVERAGE(HMM_MulM2V2CPP, 1)
3032+static inline HMM_Vec2 HMM_Mul(HMM_Mat2 Matrix, HMM_Vec2 Vector)
3033+{
3034+ ASSERT_COVERED(HMM_MulM2V2CPP);
3035+ return HMM_MulM2V2(Matrix, Vector);
3036+}
3037+
3038+COVERAGE(HMM_MulM3V3CPP, 1)
3039+static inline HMM_Vec3 HMM_Mul(HMM_Mat3 Matrix, HMM_Vec3 Vector)
3040+{
3041+ ASSERT_COVERED(HMM_MulM3V3CPP);
3042+ return HMM_MulM3V3(Matrix, Vector);
3043+}
3044+
3045+COVERAGE(HMM_MulM4V4CPP, 1)
3046+static inline HMM_Vec4 HMM_Mul(HMM_Mat4 Matrix, HMM_Vec4 Vector)
3047+{
3048+ ASSERT_COVERED(HMM_MulM4V4CPP);
3049+ return HMM_MulM4V4(Matrix, Vector);
3050+}
3051+
3052+COVERAGE(HMM_MulQCPP, 1)
3053+static inline HMM_Quat HMM_Mul(HMM_Quat Left, HMM_Quat Right)
3054+{
3055+ ASSERT_COVERED(HMM_MulQCPP);
3056+ return HMM_MulQ(Left, Right);
3057+}
3058+
3059+COVERAGE(HMM_MulQFCPP, 1)
3060+static inline HMM_Quat HMM_Mul(HMM_Quat Left, float Right)
3061+{
3062+ ASSERT_COVERED(HMM_MulQFCPP);
3063+ return HMM_MulQF(Left, Right);
3064+}
3065+
3066+COVERAGE(HMM_DivV2CPP, 1)
3067+static inline HMM_Vec2 HMM_Div(HMM_Vec2 Left, HMM_Vec2 Right)
3068+{
3069+ ASSERT_COVERED(HMM_DivV2CPP);
3070+ return HMM_DivV2(Left, Right);
3071+}
3072+
3073+COVERAGE(HMM_DivV2FCPP, 1)
3074+static inline HMM_Vec2 HMM_Div(HMM_Vec2 Left, float Right)
3075+{
3076+ ASSERT_COVERED(HMM_DivV2FCPP);
3077+ return HMM_DivV2F(Left, Right);
3078+}
3079+
3080+COVERAGE(HMM_DivV3CPP, 1)
3081+static inline HMM_Vec3 HMM_Div(HMM_Vec3 Left, HMM_Vec3 Right)
3082+{
3083+ ASSERT_COVERED(HMM_DivV3CPP);
3084+ return HMM_DivV3(Left, Right);
3085+}
3086+
3087+COVERAGE(HMM_DivV3FCPP, 1)
3088+static inline HMM_Vec3 HMM_Div(HMM_Vec3 Left, float Right)
3089+{
3090+ ASSERT_COVERED(HMM_DivV3FCPP);
3091+ return HMM_DivV3F(Left, Right);
3092+}
3093+
3094+COVERAGE(HMM_DivV4CPP, 1)
3095+static inline HMM_Vec4 HMM_Div(HMM_Vec4 Left, HMM_Vec4 Right)
3096+{
3097+ ASSERT_COVERED(HMM_DivV4CPP);
3098+ return HMM_DivV4(Left, Right);
3099+}
3100+
3101+COVERAGE(HMM_DivV4FCPP, 1)
3102+static inline HMM_Vec4 HMM_Div(HMM_Vec4 Left, float Right)
3103+{
3104+ ASSERT_COVERED(HMM_DivV4FCPP);
3105+ return HMM_DivV4F(Left, Right);
3106+}
3107+
3108+COVERAGE(HMM_DivM2FCPP, 1)
3109+static inline HMM_Mat2 HMM_Div(HMM_Mat2 Left, float Right)
3110+{
3111+ ASSERT_COVERED(HMM_DivM2FCPP);
3112+ return HMM_DivM2F(Left, Right);
3113+}
3114+
3115+COVERAGE(HMM_DivM3FCPP, 1)
3116+static inline HMM_Mat3 HMM_Div(HMM_Mat3 Left, float Right)
3117+{
3118+ ASSERT_COVERED(HMM_DivM3FCPP);
3119+ return HMM_DivM3F(Left, Right);
3120+}
3121+
3122+COVERAGE(HMM_DivM4FCPP, 1)
3123+static inline HMM_Mat4 HMM_Div(HMM_Mat4 Left, float Right)
3124+{
3125+ ASSERT_COVERED(HMM_DivM4FCPP);
3126+ return HMM_DivM4F(Left, Right);
3127+}
3128+
3129+COVERAGE(HMM_DivQFCPP, 1)
3130+static inline HMM_Quat HMM_Div(HMM_Quat Left, float Right)
3131+{
3132+ ASSERT_COVERED(HMM_DivQFCPP);
3133+ return HMM_DivQF(Left, Right);
3134+}
3135+
3136+COVERAGE(HMM_EqV2CPP, 1)
3137+static inline HMM_Bool HMM_Eq(HMM_Vec2 Left, HMM_Vec2 Right)
3138+{
3139+ ASSERT_COVERED(HMM_EqV2CPP);
3140+ return HMM_EqV2(Left, Right);
3141+}
3142+
3143+COVERAGE(HMM_EqV3CPP, 1)
3144+static inline HMM_Bool HMM_Eq(HMM_Vec3 Left, HMM_Vec3 Right)
3145+{
3146+ ASSERT_COVERED(HMM_EqV3CPP);
3147+ return HMM_EqV3(Left, Right);
3148+}
3149+
3150+COVERAGE(HMM_EqV4CPP, 1)
3151+static inline HMM_Bool HMM_Eq(HMM_Vec4 Left, HMM_Vec4 Right)
3152+{
3153+ ASSERT_COVERED(HMM_EqV4CPP);
3154+ return HMM_EqV4(Left, Right);
3155+}
3156+
3157+COVERAGE(HMM_AddV2Op, 1)
3158+static inline HMM_Vec2 operator+(HMM_Vec2 Left, HMM_Vec2 Right)
3159+{
3160+ ASSERT_COVERED(HMM_AddV2Op);
3161+ return HMM_AddV2(Left, Right);
3162+}
3163+
3164+COVERAGE(HMM_AddV3Op, 1)
3165+static inline HMM_Vec3 operator+(HMM_Vec3 Left, HMM_Vec3 Right)
3166+{
3167+ ASSERT_COVERED(HMM_AddV3Op);
3168+ return HMM_AddV3(Left, Right);
3169+}
3170+
3171+COVERAGE(HMM_AddV4Op, 1)
3172+static inline HMM_Vec4 operator+(HMM_Vec4 Left, HMM_Vec4 Right)
3173+{
3174+ ASSERT_COVERED(HMM_AddV4Op);
3175+ return HMM_AddV4(Left, Right);
3176+}
3177+
3178+COVERAGE(HMM_AddM2Op, 1)
3179+static inline HMM_Mat2 operator+(HMM_Mat2 Left, HMM_Mat2 Right)
3180+{
3181+ ASSERT_COVERED(HMM_AddM2Op);
3182+ return HMM_AddM2(Left, Right);
3183+}
3184+
3185+COVERAGE(HMM_AddM3Op, 1)
3186+static inline HMM_Mat3 operator+(HMM_Mat3 Left, HMM_Mat3 Right)
3187+{
3188+ ASSERT_COVERED(HMM_AddM3Op);
3189+ return HMM_AddM3(Left, Right);
3190+}
3191+
3192+COVERAGE(HMM_AddM4Op, 1)
3193+static inline HMM_Mat4 operator+(HMM_Mat4 Left, HMM_Mat4 Right)
3194+{
3195+ ASSERT_COVERED(HMM_AddM4Op);
3196+ return HMM_AddM4(Left, Right);
3197+}
3198+
3199+COVERAGE(HMM_AddQOp, 1)
3200+static inline HMM_Quat operator+(HMM_Quat Left, HMM_Quat Right)
3201+{
3202+ ASSERT_COVERED(HMM_AddQOp);
3203+ return HMM_AddQ(Left, Right);
3204+}
3205+
3206+COVERAGE(HMM_SubV2Op, 1)
3207+static inline HMM_Vec2 operator-(HMM_Vec2 Left, HMM_Vec2 Right)
3208+{
3209+ ASSERT_COVERED(HMM_SubV2Op);
3210+ return HMM_SubV2(Left, Right);
3211+}
3212+
3213+COVERAGE(HMM_SubV3Op, 1)
3214+static inline HMM_Vec3 operator-(HMM_Vec3 Left, HMM_Vec3 Right)
3215+{
3216+ ASSERT_COVERED(HMM_SubV3Op);
3217+ return HMM_SubV3(Left, Right);
3218+}
3219+
3220+COVERAGE(HMM_SubV4Op, 1)
3221+static inline HMM_Vec4 operator-(HMM_Vec4 Left, HMM_Vec4 Right)
3222+{
3223+ ASSERT_COVERED(HMM_SubV4Op);
3224+ return HMM_SubV4(Left, Right);
3225+}
3226+
3227+COVERAGE(HMM_SubM2Op, 1)
3228+static inline HMM_Mat2 operator-(HMM_Mat2 Left, HMM_Mat2 Right)
3229+{
3230+ ASSERT_COVERED(HMM_SubM2Op);
3231+ return HMM_SubM2(Left, Right);
3232+}
3233+
3234+COVERAGE(HMM_SubM3Op, 1)
3235+static inline HMM_Mat3 operator-(HMM_Mat3 Left, HMM_Mat3 Right)
3236+{
3237+ ASSERT_COVERED(HMM_SubM3Op);
3238+ return HMM_SubM3(Left, Right);
3239+}
3240+
3241+COVERAGE(HMM_SubM4Op, 1)
3242+static inline HMM_Mat4 operator-(HMM_Mat4 Left, HMM_Mat4 Right)
3243+{
3244+ ASSERT_COVERED(HMM_SubM4Op);
3245+ return HMM_SubM4(Left, Right);
3246+}
3247+
3248+COVERAGE(HMM_SubQOp, 1)
3249+static inline HMM_Quat operator-(HMM_Quat Left, HMM_Quat Right)
3250+{
3251+ ASSERT_COVERED(HMM_SubQOp);
3252+ return HMM_SubQ(Left, Right);
3253+}
3254+
3255+COVERAGE(HMM_MulV2Op, 1)
3256+static inline HMM_Vec2 operator*(HMM_Vec2 Left, HMM_Vec2 Right)
3257+{
3258+ ASSERT_COVERED(HMM_MulV2Op);
3259+ return HMM_MulV2(Left, Right);
3260+}
3261+
3262+COVERAGE(HMM_MulV3Op, 1)
3263+static inline HMM_Vec3 operator*(HMM_Vec3 Left, HMM_Vec3 Right)
3264+{
3265+ ASSERT_COVERED(HMM_MulV3Op);
3266+ return HMM_MulV3(Left, Right);
3267+}
3268+
3269+COVERAGE(HMM_MulV4Op, 1)
3270+static inline HMM_Vec4 operator*(HMM_Vec4 Left, HMM_Vec4 Right)
3271+{
3272+ ASSERT_COVERED(HMM_MulV4Op);
3273+ return HMM_MulV4(Left, Right);
3274+}
3275+
3276+COVERAGE(HMM_MulM2Op, 1)
3277+static inline HMM_Mat2 operator*(HMM_Mat2 Left, HMM_Mat2 Right)
3278+{
3279+ ASSERT_COVERED(HMM_MulM2Op);
3280+ return HMM_MulM2(Left, Right);
3281+}
3282+
3283+COVERAGE(HMM_MulM3Op, 1)
3284+static inline HMM_Mat3 operator*(HMM_Mat3 Left, HMM_Mat3 Right)
3285+{
3286+ ASSERT_COVERED(HMM_MulM3Op);
3287+ return HMM_MulM3(Left, Right);
3288+}
3289+
3290+COVERAGE(HMM_MulM4Op, 1)
3291+static inline HMM_Mat4 operator*(HMM_Mat4 Left, HMM_Mat4 Right)
3292+{
3293+ ASSERT_COVERED(HMM_MulM4Op);
3294+ return HMM_MulM4(Left, Right);
3295+}
3296+
3297+COVERAGE(HMM_MulQOp, 1)
3298+static inline HMM_Quat operator*(HMM_Quat Left, HMM_Quat Right)
3299+{
3300+ ASSERT_COVERED(HMM_MulQOp);
3301+ return HMM_MulQ(Left, Right);
3302+}
3303+
3304+COVERAGE(HMM_MulV2FOp, 1)
3305+static inline HMM_Vec2 operator*(HMM_Vec2 Left, float Right)
3306+{
3307+ ASSERT_COVERED(HMM_MulV2FOp);
3308+ return HMM_MulV2F(Left, Right);
3309+}
3310+
3311+COVERAGE(HMM_MulV3FOp, 1)
3312+static inline HMM_Vec3 operator*(HMM_Vec3 Left, float Right)
3313+{
3314+ ASSERT_COVERED(HMM_MulV3FOp);
3315+ return HMM_MulV3F(Left, Right);
3316+}
3317+
3318+COVERAGE(HMM_MulV4FOp, 1)
3319+static inline HMM_Vec4 operator*(HMM_Vec4 Left, float Right)
3320+{
3321+ ASSERT_COVERED(HMM_MulV4FOp);
3322+ return HMM_MulV4F(Left, Right);
3323+}
3324+
3325+COVERAGE(HMM_MulM2FOp, 1)
3326+static inline HMM_Mat2 operator*(HMM_Mat2 Left, float Right)
3327+{
3328+ ASSERT_COVERED(HMM_MulM2FOp);
3329+ return HMM_MulM2F(Left, Right);
3330+}
3331+
3332+COVERAGE(HMM_MulM3FOp, 1)
3333+static inline HMM_Mat3 operator*(HMM_Mat3 Left, float Right)
3334+{
3335+ ASSERT_COVERED(HMM_MulM3FOp);
3336+ return HMM_MulM3F(Left, Right);
3337+}
3338+
3339+COVERAGE(HMM_MulM4FOp, 1)
3340+static inline HMM_Mat4 operator*(HMM_Mat4 Left, float Right)
3341+{
3342+ ASSERT_COVERED(HMM_MulM4FOp);
3343+ return HMM_MulM4F(Left, Right);
3344+}
3345+
3346+COVERAGE(HMM_MulQFOp, 1)
3347+static inline HMM_Quat operator*(HMM_Quat Left, float Right)
3348+{
3349+ ASSERT_COVERED(HMM_MulQFOp);
3350+ return HMM_MulQF(Left, Right);
3351+}
3352+
3353+COVERAGE(HMM_MulV2FOpLeft, 1)
3354+static inline HMM_Vec2 operator*(float Left, HMM_Vec2 Right)
3355+{
3356+ ASSERT_COVERED(HMM_MulV2FOpLeft);
3357+ return HMM_MulV2F(Right, Left);
3358+}
3359+
3360+COVERAGE(HMM_MulV3FOpLeft, 1)
3361+static inline HMM_Vec3 operator*(float Left, HMM_Vec3 Right)
3362+{
3363+ ASSERT_COVERED(HMM_MulV3FOpLeft);
3364+ return HMM_MulV3F(Right, Left);
3365+}
3366+
3367+COVERAGE(HMM_MulV4FOpLeft, 1)
3368+static inline HMM_Vec4 operator*(float Left, HMM_Vec4 Right)
3369+{
3370+ ASSERT_COVERED(HMM_MulV4FOpLeft);
3371+ return HMM_MulV4F(Right, Left);
3372+}
3373+
3374+COVERAGE(HMM_MulM2FOpLeft, 1)
3375+static inline HMM_Mat2 operator*(float Left, HMM_Mat2 Right)
3376+{
3377+ ASSERT_COVERED(HMM_MulM2FOpLeft);
3378+ return HMM_MulM2F(Right, Left);
3379+}
3380+
3381+COVERAGE(HMM_MulM3FOpLeft, 1)
3382+static inline HMM_Mat3 operator*(float Left, HMM_Mat3 Right)
3383+{
3384+ ASSERT_COVERED(HMM_MulM3FOpLeft);
3385+ return HMM_MulM3F(Right, Left);
3386+}
3387+
3388+COVERAGE(HMM_MulM4FOpLeft, 1)
3389+static inline HMM_Mat4 operator*(float Left, HMM_Mat4 Right)
3390+{
3391+ ASSERT_COVERED(HMM_MulM4FOpLeft);
3392+ return HMM_MulM4F(Right, Left);
3393+}
3394+
3395+COVERAGE(HMM_MulQFOpLeft, 1)
3396+static inline HMM_Quat operator*(float Left, HMM_Quat Right)
3397+{
3398+ ASSERT_COVERED(HMM_MulQFOpLeft);
3399+ return HMM_MulQF(Right, Left);
3400+}
3401+
3402+COVERAGE(HMM_MulM2V2Op, 1)
3403+static inline HMM_Vec2 operator*(HMM_Mat2 Matrix, HMM_Vec2 Vector)
3404+{
3405+ ASSERT_COVERED(HMM_MulM2V2Op);
3406+ return HMM_MulM2V2(Matrix, Vector);
3407+}
3408+
3409+COVERAGE(HMM_MulM3V3Op, 1)
3410+static inline HMM_Vec3 operator*(HMM_Mat3 Matrix, HMM_Vec3 Vector)
3411+{
3412+ ASSERT_COVERED(HMM_MulM3V3Op);
3413+ return HMM_MulM3V3(Matrix, Vector);
3414+}
3415+
3416+COVERAGE(HMM_MulM4V4Op, 1)
3417+static inline HMM_Vec4 operator*(HMM_Mat4 Matrix, HMM_Vec4 Vector)
3418+{
3419+ ASSERT_COVERED(HMM_MulM4V4Op);
3420+ return HMM_MulM4V4(Matrix, Vector);
3421+}
3422+
3423+COVERAGE(HMM_DivV2Op, 1)
3424+static inline HMM_Vec2 operator/(HMM_Vec2 Left, HMM_Vec2 Right)
3425+{
3426+ ASSERT_COVERED(HMM_DivV2Op);
3427+ return HMM_DivV2(Left, Right);
3428+}
3429+
3430+COVERAGE(HMM_DivV3Op, 1)
3431+static inline HMM_Vec3 operator/(HMM_Vec3 Left, HMM_Vec3 Right)
3432+{
3433+ ASSERT_COVERED(HMM_DivV3Op);
3434+ return HMM_DivV3(Left, Right);
3435+}
3436+
3437+COVERAGE(HMM_DivV4Op, 1)
3438+static inline HMM_Vec4 operator/(HMM_Vec4 Left, HMM_Vec4 Right)
3439+{
3440+ ASSERT_COVERED(HMM_DivV4Op);
3441+ return HMM_DivV4(Left, Right);
3442+}
3443+
3444+COVERAGE(HMM_DivV2FOp, 1)
3445+static inline HMM_Vec2 operator/(HMM_Vec2 Left, float Right)
3446+{
3447+ ASSERT_COVERED(HMM_DivV2FOp);
3448+ return HMM_DivV2F(Left, Right);
3449+}
3450+
3451+COVERAGE(HMM_DivV3FOp, 1)
3452+static inline HMM_Vec3 operator/(HMM_Vec3 Left, float Right)
3453+{
3454+ ASSERT_COVERED(HMM_DivV3FOp);
3455+ return HMM_DivV3F(Left, Right);
3456+}
3457+
3458+COVERAGE(HMM_DivV4FOp, 1)
3459+static inline HMM_Vec4 operator/(HMM_Vec4 Left, float Right)
3460+{
3461+ ASSERT_COVERED(HMM_DivV4FOp);
3462+ return HMM_DivV4F(Left, Right);
3463+}
3464+
3465+COVERAGE(HMM_DivM4FOp, 1)
3466+static inline HMM_Mat4 operator/(HMM_Mat4 Left, float Right)
3467+{
3468+ ASSERT_COVERED(HMM_DivM4FOp);
3469+ return HMM_DivM4F(Left, Right);
3470+}
3471+
3472+COVERAGE(HMM_DivM3FOp, 1)
3473+static inline HMM_Mat3 operator/(HMM_Mat3 Left, float Right)
3474+{
3475+ ASSERT_COVERED(HMM_DivM3FOp);
3476+ return HMM_DivM3F(Left, Right);
3477+}
3478+
3479+COVERAGE(HMM_DivM2FOp, 1)
3480+static inline HMM_Mat2 operator/(HMM_Mat2 Left, float Right)
3481+{
3482+ ASSERT_COVERED(HMM_DivM2FOp);
3483+ return HMM_DivM2F(Left, Right);
3484+}
3485+
3486+COVERAGE(HMM_DivQFOp, 1)
3487+static inline HMM_Quat operator/(HMM_Quat Left, float Right)
3488+{
3489+ ASSERT_COVERED(HMM_DivQFOp);
3490+ return HMM_DivQF(Left, Right);
3491+}
3492+
3493+COVERAGE(HMM_AddV2Assign, 1)
3494+static inline HMM_Vec2 &operator+=(HMM_Vec2 &Left, HMM_Vec2 Right)
3495+{
3496+ ASSERT_COVERED(HMM_AddV2Assign);
3497+ return Left = Left + Right;
3498+}
3499+
3500+COVERAGE(HMM_AddV3Assign, 1)
3501+static inline HMM_Vec3 &operator+=(HMM_Vec3 &Left, HMM_Vec3 Right)
3502+{
3503+ ASSERT_COVERED(HMM_AddV3Assign);
3504+ return Left = Left + Right;
3505+}
3506+
3507+COVERAGE(HMM_AddV4Assign, 1)
3508+static inline HMM_Vec4 &operator+=(HMM_Vec4 &Left, HMM_Vec4 Right)
3509+{
3510+ ASSERT_COVERED(HMM_AddV4Assign);
3511+ return Left = Left + Right;
3512+}
3513+
3514+COVERAGE(HMM_AddM2Assign, 1)
3515+static inline HMM_Mat2 &operator+=(HMM_Mat2 &Left, HMM_Mat2 Right)
3516+{
3517+ ASSERT_COVERED(HMM_AddM2Assign);
3518+ return Left = Left + Right;
3519+}
3520+
3521+COVERAGE(HMM_AddM3Assign, 1)
3522+static inline HMM_Mat3 &operator+=(HMM_Mat3 &Left, HMM_Mat3 Right)
3523+{
3524+ ASSERT_COVERED(HMM_AddM3Assign);
3525+ return Left = Left + Right;
3526+}
3527+
3528+COVERAGE(HMM_AddM4Assign, 1)
3529+static inline HMM_Mat4 &operator+=(HMM_Mat4 &Left, HMM_Mat4 Right)
3530+{
3531+ ASSERT_COVERED(HMM_AddM4Assign);
3532+ return Left = Left + Right;
3533+}
3534+
3535+COVERAGE(HMM_AddQAssign, 1)
3536+static inline HMM_Quat &operator+=(HMM_Quat &Left, HMM_Quat Right)
3537+{
3538+ ASSERT_COVERED(HMM_AddQAssign);
3539+ return Left = Left + Right;
3540+}
3541+
3542+COVERAGE(HMM_SubV2Assign, 1)
3543+static inline HMM_Vec2 &operator-=(HMM_Vec2 &Left, HMM_Vec2 Right)
3544+{
3545+ ASSERT_COVERED(HMM_SubV2Assign);
3546+ return Left = Left - Right;
3547+}
3548+
3549+COVERAGE(HMM_SubV3Assign, 1)
3550+static inline HMM_Vec3 &operator-=(HMM_Vec3 &Left, HMM_Vec3 Right)
3551+{
3552+ ASSERT_COVERED(HMM_SubV3Assign);
3553+ return Left = Left - Right;
3554+}
3555+
3556+COVERAGE(HMM_SubV4Assign, 1)
3557+static inline HMM_Vec4 &operator-=(HMM_Vec4 &Left, HMM_Vec4 Right)
3558+{
3559+ ASSERT_COVERED(HMM_SubV4Assign);
3560+ return Left = Left - Right;
3561+}
3562+
3563+COVERAGE(HMM_SubM2Assign, 1)
3564+static inline HMM_Mat2 &operator-=(HMM_Mat2 &Left, HMM_Mat2 Right)
3565+{
3566+ ASSERT_COVERED(HMM_SubM2Assign);
3567+ return Left = Left - Right;
3568+}
3569+
3570+COVERAGE(HMM_SubM3Assign, 1)
3571+static inline HMM_Mat3 &operator-=(HMM_Mat3 &Left, HMM_Mat3 Right)
3572+{
3573+ ASSERT_COVERED(HMM_SubM3Assign);
3574+ return Left = Left - Right;
3575+}
3576+
3577+COVERAGE(HMM_SubM4Assign, 1)
3578+static inline HMM_Mat4 &operator-=(HMM_Mat4 &Left, HMM_Mat4 Right)
3579+{
3580+ ASSERT_COVERED(HMM_SubM4Assign);
3581+ return Left = Left - Right;
3582+}
3583+
3584+COVERAGE(HMM_SubQAssign, 1)
3585+static inline HMM_Quat &operator-=(HMM_Quat &Left, HMM_Quat Right)
3586+{
3587+ ASSERT_COVERED(HMM_SubQAssign);
3588+ return Left = Left - Right;
3589+}
3590+
3591+COVERAGE(HMM_MulV2Assign, 1)
3592+static inline HMM_Vec2 &operator*=(HMM_Vec2 &Left, HMM_Vec2 Right)
3593+{
3594+ ASSERT_COVERED(HMM_MulV2Assign);
3595+ return Left = Left * Right;
3596+}
3597+
3598+COVERAGE(HMM_MulV3Assign, 1)
3599+static inline HMM_Vec3 &operator*=(HMM_Vec3 &Left, HMM_Vec3 Right)
3600+{
3601+ ASSERT_COVERED(HMM_MulV3Assign);
3602+ return Left = Left * Right;
3603+}
3604+
3605+COVERAGE(HMM_MulV4Assign, 1)
3606+static inline HMM_Vec4 &operator*=(HMM_Vec4 &Left, HMM_Vec4 Right)
3607+{
3608+ ASSERT_COVERED(HMM_MulV4Assign);
3609+ return Left = Left * Right;
3610+}
3611+
3612+COVERAGE(HMM_MulV2FAssign, 1)
3613+static inline HMM_Vec2 &operator*=(HMM_Vec2 &Left, float Right)
3614+{
3615+ ASSERT_COVERED(HMM_MulV2FAssign);
3616+ return Left = Left * Right;
3617+}
3618+
3619+COVERAGE(HMM_MulV3FAssign, 1)
3620+static inline HMM_Vec3 &operator*=(HMM_Vec3 &Left, float Right)
3621+{
3622+ ASSERT_COVERED(HMM_MulV3FAssign);
3623+ return Left = Left * Right;
3624+}
3625+
3626+COVERAGE(HMM_MulV4FAssign, 1)
3627+static inline HMM_Vec4 &operator*=(HMM_Vec4 &Left, float Right)
3628+{
3629+ ASSERT_COVERED(HMM_MulV4FAssign);
3630+ return Left = Left * Right;
3631+}
3632+
3633+COVERAGE(HMM_MulM2FAssign, 1)
3634+static inline HMM_Mat2 &operator*=(HMM_Mat2 &Left, float Right)
3635+{
3636+ ASSERT_COVERED(HMM_MulM2FAssign);
3637+ return Left = Left * Right;
3638+}
3639+
3640+COVERAGE(HMM_MulM3FAssign, 1)
3641+static inline HMM_Mat3 &operator*=(HMM_Mat3 &Left, float Right)
3642+{
3643+ ASSERT_COVERED(HMM_MulM3FAssign);
3644+ return Left = Left * Right;
3645+}
3646+
3647+COVERAGE(HMM_MulM4FAssign, 1)
3648+static inline HMM_Mat4 &operator*=(HMM_Mat4 &Left, float Right)
3649+{
3650+ ASSERT_COVERED(HMM_MulM4FAssign);
3651+ return Left = Left * Right;
3652+}
3653+
3654+COVERAGE(HMM_MulQFAssign, 1)
3655+static inline HMM_Quat &operator*=(HMM_Quat &Left, float Right)
3656+{
3657+ ASSERT_COVERED(HMM_MulQFAssign);
3658+ return Left = Left * Right;
3659+}
3660+
3661+COVERAGE(HMM_DivV2Assign, 1)
3662+static inline HMM_Vec2 &operator/=(HMM_Vec2 &Left, HMM_Vec2 Right)
3663+{
3664+ ASSERT_COVERED(HMM_DivV2Assign);
3665+ return Left = Left / Right;
3666+}
3667+
3668+COVERAGE(HMM_DivV3Assign, 1)
3669+static inline HMM_Vec3 &operator/=(HMM_Vec3 &Left, HMM_Vec3 Right)
3670+{
3671+ ASSERT_COVERED(HMM_DivV3Assign);
3672+ return Left = Left / Right;
3673+}
3674+
3675+COVERAGE(HMM_DivV4Assign, 1)
3676+static inline HMM_Vec4 &operator/=(HMM_Vec4 &Left, HMM_Vec4 Right)
3677+{
3678+ ASSERT_COVERED(HMM_DivV4Assign);
3679+ return Left = Left / Right;
3680+}
3681+
3682+COVERAGE(HMM_DivV2FAssign, 1)
3683+static inline HMM_Vec2 &operator/=(HMM_Vec2 &Left, float Right)
3684+{
3685+ ASSERT_COVERED(HMM_DivV2FAssign);
3686+ return Left = Left / Right;
3687+}
3688+
3689+COVERAGE(HMM_DivV3FAssign, 1)
3690+static inline HMM_Vec3 &operator/=(HMM_Vec3 &Left, float Right)
3691+{
3692+ ASSERT_COVERED(HMM_DivV3FAssign);
3693+ return Left = Left / Right;
3694+}
3695+
3696+COVERAGE(HMM_DivV4FAssign, 1)
3697+static inline HMM_Vec4 &operator/=(HMM_Vec4 &Left, float Right)
3698+{
3699+ ASSERT_COVERED(HMM_DivV4FAssign);
3700+ return Left = Left / Right;
3701+}
3702+
3703+COVERAGE(HMM_DivM4FAssign, 1)
3704+static inline HMM_Mat4 &operator/=(HMM_Mat4 &Left, float Right)
3705+{
3706+ ASSERT_COVERED(HMM_DivM4FAssign);
3707+ return Left = Left / Right;
3708+}
3709+
3710+COVERAGE(HMM_DivQFAssign, 1)
3711+static inline HMM_Quat &operator/=(HMM_Quat &Left, float Right)
3712+{
3713+ ASSERT_COVERED(HMM_DivQFAssign);
3714+ return Left = Left / Right;
3715+}
3716+
3717+COVERAGE(HMM_EqV2Op, 1)
3718+static inline HMM_Bool operator==(HMM_Vec2 Left, HMM_Vec2 Right)
3719+{
3720+ ASSERT_COVERED(HMM_EqV2Op);
3721+ return HMM_EqV2(Left, Right);
3722+}
3723+
3724+COVERAGE(HMM_EqV3Op, 1)
3725+static inline HMM_Bool operator==(HMM_Vec3 Left, HMM_Vec3 Right)
3726+{
3727+ ASSERT_COVERED(HMM_EqV3Op);
3728+ return HMM_EqV3(Left, Right);
3729+}
3730+
3731+COVERAGE(HMM_EqV4Op, 1)
3732+static inline HMM_Bool operator==(HMM_Vec4 Left, HMM_Vec4 Right)
3733+{
3734+ ASSERT_COVERED(HMM_EqV4Op);
3735+ return HMM_EqV4(Left, Right);
3736+}
3737+
3738+COVERAGE(HMM_EqV2OpNot, 1)
3739+static inline HMM_Bool operator!=(HMM_Vec2 Left, HMM_Vec2 Right)
3740+{
3741+ ASSERT_COVERED(HMM_EqV2OpNot);
3742+ return !HMM_EqV2(Left, Right);
3743+}
3744+
3745+COVERAGE(HMM_EqV3OpNot, 1)
3746+static inline HMM_Bool operator!=(HMM_Vec3 Left, HMM_Vec3 Right)
3747+{
3748+ ASSERT_COVERED(HMM_EqV3OpNot);
3749+ return !HMM_EqV3(Left, Right);
3750+}
3751+
3752+COVERAGE(HMM_EqV4OpNot, 1)
3753+static inline HMM_Bool operator!=(HMM_Vec4 Left, HMM_Vec4 Right)
3754+{
3755+ ASSERT_COVERED(HMM_EqV4OpNot);
3756+ return !HMM_EqV4(Left, Right);
3757+}
3758+
3759+COVERAGE(HMM_UnaryMinusV2, 1)
3760+static inline HMM_Vec2 operator-(HMM_Vec2 In)
3761+{
3762+ ASSERT_COVERED(HMM_UnaryMinusV2);
3763+
3764+ HMM_Vec2 Result;
3765+ Result.X = -In.X;
3766+ Result.Y = -In.Y;
3767+
3768+ return Result;
3769+}
3770+
3771+COVERAGE(HMM_UnaryMinusV3, 1)
3772+static inline HMM_Vec3 operator-(HMM_Vec3 In)
3773+{
3774+ ASSERT_COVERED(HMM_UnaryMinusV3);
3775+
3776+ HMM_Vec3 Result;
3777+ Result.X = -In.X;
3778+ Result.Y = -In.Y;
3779+ Result.Z = -In.Z;
3780+
3781+ return Result;
3782+}
3783+
3784+COVERAGE(HMM_UnaryMinusV4, 1)
3785+static inline HMM_Vec4 operator-(HMM_Vec4 In)
3786+{
3787+ ASSERT_COVERED(HMM_UnaryMinusV4);
3788+
3789+ HMM_Vec4 Result;
3790+#if HANDMADE_MATH__USE_SSE
3791+ Result.SSE = _mm_xor_ps(In.SSE, _mm_set1_ps(-0.0f));
3792+#elif defined(HANDMADE_MATH__USE_NEON)
3793+ float32x4_t Zero = vdupq_n_f32(0.0f);
3794+ Result.NEON = vsubq_f32(Zero, In.NEON);
3795+#else
3796+ Result.X = -In.X;
3797+ Result.Y = -In.Y;
3798+ Result.Z = -In.Z;
3799+ Result.W = -In.W;
3800+#endif
3801+
3802+ return Result;
3803+}
3804+
3805+#endif /* __cplusplus*/
3806+
3807+#ifdef HANDMADE_MATH__USE_C11_GENERICS
3808+
3809+void __hmm_invalid_generic(void);
3810+
3811+#define HMM_Add(A, B) _Generic((A), \
3812+ HMM_Vec2: HMM_AddV2, \
3813+ HMM_Vec3: HMM_AddV3, \
3814+ HMM_Vec4: HMM_AddV4, \
3815+ HMM_Mat2: HMM_AddM2, \
3816+ HMM_Mat3: HMM_AddM3, \
3817+ HMM_Mat4: HMM_AddM4, \
3818+ HMM_Quat: HMM_AddQ \
3819+)(A, B)
3820+
3821+#define HMM_Sub(A, B) _Generic((A), \
3822+ HMM_Vec2: HMM_SubV2, \
3823+ HMM_Vec3: HMM_SubV3, \
3824+ HMM_Vec4: HMM_SubV4, \
3825+ HMM_Mat2: HMM_SubM2, \
3826+ HMM_Mat3: HMM_SubM3, \
3827+ HMM_Mat4: HMM_SubM4, \
3828+ HMM_Quat: HMM_SubQ \
3829+)(A, B)
3830+
3831+#define HMM_Mul(A, B) _Generic((B), \
3832+ float: _Generic((A), \
3833+ HMM_Vec2: HMM_MulV2F, \
3834+ HMM_Vec3: HMM_MulV3F, \
3835+ HMM_Vec4: HMM_MulV4F, \
3836+ HMM_Mat2: HMM_MulM2F, \
3837+ HMM_Mat3: HMM_MulM3F, \
3838+ HMM_Mat4: HMM_MulM4F, \
3839+ HMM_Quat: HMM_MulQF, \
3840+ default: __hmm_invalid_generic \
3841+ ), \
3842+ HMM_Vec2: _Generic((A), \
3843+ HMM_Vec2: HMM_MulV2, \
3844+ HMM_Mat2: HMM_MulM2V2, \
3845+ default: __hmm_invalid_generic \
3846+ ), \
3847+ HMM_Vec3: _Generic((A), \
3848+ HMM_Vec3: HMM_MulV3, \
3849+ HMM_Mat3: HMM_MulM3V3, \
3850+ default: __hmm_invalid_generic \
3851+ ), \
3852+ HMM_Vec4: _Generic((A), \
3853+ HMM_Vec4: HMM_MulV4, \
3854+ HMM_Mat4: HMM_MulM4V4, \
3855+ default: __hmm_invalid_generic \
3856+ ), \
3857+ HMM_Mat2: HMM_MulM2, \
3858+ HMM_Mat3: HMM_MulM3, \
3859+ HMM_Mat4: HMM_MulM4, \
3860+ HMM_Quat: HMM_MulQ \
3861+)(A, B)
3862+
3863+#define HMM_Div(A, B) _Generic((B), \
3864+ float: _Generic((A), \
3865+ HMM_Vec2: HMM_DivV2F, \
3866+ HMM_Vec3: HMM_DivV3F, \
3867+ HMM_Vec4: HMM_DivV4F, \
3868+ HMM_Mat2: HMM_DivM2F, \
3869+ HMM_Mat3: HMM_DivM3F, \
3870+ HMM_Mat4: HMM_DivM4F, \
3871+ HMM_Quat: HMM_DivQF \
3872+ ), \
3873+ HMM_Vec2: HMM_DivV2, \
3874+ HMM_Vec3: HMM_DivV3, \
3875+ HMM_Vec4: HMM_DivV4 \
3876+)(A, B)
3877+
3878+#define HMM_Len(A) _Generic((A), \
3879+ HMM_Vec2: HMM_LenV2, \
3880+ HMM_Vec3: HMM_LenV3, \
3881+ HMM_Vec4: HMM_LenV4 \
3882+)(A)
3883+
3884+#define HMM_LenSqr(A) _Generic((A), \
3885+ HMM_Vec2: HMM_LenSqrV2, \
3886+ HMM_Vec3: HMM_LenSqrV3, \
3887+ HMM_Vec4: HMM_LenSqrV4 \
3888+)(A)
3889+
3890+#define HMM_Norm(A) _Generic((A), \
3891+ HMM_Vec2: HMM_NormV2, \
3892+ HMM_Vec3: HMM_NormV3, \
3893+ HMM_Vec4: HMM_NormV4, \
3894+ HMM_Quat: HMM_NormQ \
3895+)(A)
3896+
3897+#define HMM_Dot(A, B) _Generic((A), \
3898+ HMM_Vec2: HMM_DotV2, \
3899+ HMM_Vec3: HMM_DotV3, \
3900+ HMM_Vec4: HMM_DotV4, \
3901+ HMM_Quat: HMM_DotQ \
3902+)(A, B)
3903+
3904+#define HMM_Lerp(A, T, B) _Generic((A), \
3905+ float: HMM_Lerp, \
3906+ HMM_Vec2: HMM_LerpV2, \
3907+ HMM_Vec3: HMM_LerpV3, \
3908+ HMM_Vec4: HMM_LerpV4 \
3909+)(A, T, B)
3910+
3911+#define HMM_Eq(A, B) _Generic((A), \
3912+ HMM_Vec2: HMM_EqV2, \
3913+ HMM_Vec3: HMM_EqV3, \
3914+ HMM_Vec4: HMM_EqV4 \
3915+)(A, B)
3916+
3917+#define HMM_Transpose(M) _Generic((M), \
3918+ HMM_Mat2: HMM_TransposeM2, \
3919+ HMM_Mat3: HMM_TransposeM3, \
3920+ HMM_Mat4: HMM_TransposeM4 \
3921+)(M)
3922+
3923+#define HMM_Determinant(M) _Generic((M), \
3924+ HMM_Mat2: HMM_DeterminantM2, \
3925+ HMM_Mat3: HMM_DeterminantM3, \
3926+ HMM_Mat4: HMM_DeterminantM4 \
3927+)(M)
3928+
3929+#define HMM_InvGeneral(M) _Generic((M), \
3930+ HMM_Mat2: HMM_InvGeneralM2, \
3931+ HMM_Mat3: HMM_InvGeneralM3, \
3932+ HMM_Mat4: HMM_InvGeneralM4 \
3933+)(M)
3934+
3935+#endif
3936+
3937+#if defined(__GNUC__) || defined(__clang__)
3938+#pragma GCC diagnostic pop
3939+#endif
3940+
3941+#endif /* HANDMADE_MATH_H */