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 */