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