From f376f2a2a7e33f25f627f940b68d3f11b82c9cd3 Mon Sep 17 00:00:00 2001 From: Ben Visness Date: Wed, 31 Jul 2019 16:43:56 -0500 Subject: [PATCH] Add test coverage macros (#104) * Add coverage features and add it, laboriously, to everything * Fix easy tests * Add tests for != operators * Clean up test framework a little * Add documentation of coverage macros * Fix tests for mat4 to quaternion * Slightly improve formatting of coverage output * Trailing whitespace must die --- .editorconfig | 9 + .travis.yml | 5 +- HandmadeMath.h | 1045 ++++++++++++++++++++++++------ test/HandmadeMath.c | 4 + test/HandmadeTest.h | 361 +++++++---- test/Makefile | 46 +- test/README.md | 13 +- test/categories/Addition.h | 4 +- test/categories/Equality.h | 9 + test/categories/Initialization.h | 4 +- test/categories/QuaternionOps.h | 14 +- test/categories/SSE.h | 18 +- test/categories/ScalarMath.h | 30 +- test/categories/VectorOps.h | 4 +- test/hmm_test.c | 6 +- test/hmm_test.h | 2 + 16 files changed, 1220 insertions(+), 354 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ebe9f23 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*.{c,cpp,h}] +charset = utf-8 +indent_style = space +indent_size = 4 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.travis.yml b/.travis.yml index 38708be..8c20e61 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,4 +5,7 @@ compiler: install: - cd test script: - - make all + - make c + - make c_no_sse + - make cpp + - make cpp_no_sse diff --git a/HandmadeMath.h b/HandmadeMath.h index 87006f2..792257d 100644 --- a/HandmadeMath.h +++ b/HandmadeMath.h @@ -1,40 +1,40 @@ /* HandmadeMath.h v1.9.0 - + This is a single header file with a bunch of useful functions for game and graphics math operations. - + ============================================================================= - + You MUST - + #define HANDMADE_MATH_IMPLEMENTATION - + in EXACTLY one C or C++ file that includes this header, BEFORE the include, like this: - + #define HANDMADE_MATH_IMPLEMENTATION #include "HandmadeMath.h" - + All other files should just #include "HandmadeMath.h" without the #define. - + ============================================================================= - + To disable SSE intrinsics, you MUST - + #define HANDMADE_MATH_NO_SSE - + in EXACTLY one C or C++ file that includes this header, BEFORE the include, like this: - + #define HANDMADE_MATH_IMPLEMENTATION #define HANDMADE_MATH_NO_SSE #include "HandmadeMath.h" - + ============================================================================= - - To use HandmadeMath without the CRT, you MUST - + + To use HandmadeMath without the CRT, you MUST + #define HMM_SINF MySinF #define HMM_COSF MyCosF #define HMM_TANF MyTanF @@ -44,11 +44,11 @@ #define HMM_ACOSF MyACosF #define HMM_ATANF MyATanF #define HMM_ATAN2F MYATan2F - - Provide your own implementations of SinF, CosF, TanF, ACosF, ATanF, ATan2F, + + Provide your own implementations of SinF, CosF, TanF, ACosF, ATanF, ATan2F, ExpF, and LogF in EXACTLY one C or C++ file that includes this header, - BEFORE the include, like this: - + BEFORE the include, like this: + #define HMM_SINF MySinF #define HMM_COSF MyCosF #define HMM_TANF MyTanF @@ -60,31 +60,31 @@ #define HMM_ATAN2F MyATan2F #define HANDMADE_MATH_IMPLEMENTATION #include "HandmadeMath.h" - + If you do not define all of these, HandmadeMath.h will use the versions of these functions that are provided by the CRT. - + ============================================================================= LICENSE - + This software is in the public domain. Where that dedication is not recognized, you are granted a perpetual, irrevocable license to copy, distribute, and modify this file as you see fit. - + CREDITS - + Written by Zakary Strange (zak@strangedev.net && @strangezak) - + Functionality: Matt Mascarenhas (@miblo_) Aleph FieryDrake (@fierydrake) Gingerbill (@TheGingerBill) - Ben Visness (@bvisness) + Ben Visness (@bvisness) Trinton Bullard (@Peliex_Dev) @AntonDan - + Fixes: Jeroen van Rijn (@J_vanRijn) Kiljacken (@Kiljacken) @@ -92,6 +92,14 @@ Daniel Gibson (@DanielGibson) */ +// Dummy macros for when test framework is not present. +#ifndef COVERAGE +#define COVERAGE(a, b) +#endif + +#ifndef ASSERT_COVERED +#define ASSERT_COVERED(a) +#endif /* let's figure out if SSE is really available (unless disabled anyway) (it isn't on non-x86/x86_64 platforms or even x86 without explicit SSE support) @@ -145,25 +153,25 @@ extern "C" #if !defined(HMM_SINF) || !defined(HMM_COSF) || !defined(HMM_TANF) || \ !defined(HMM_SQRTF) || !defined(HMM_EXPF) || !defined(HMM_LOGF) || \ !defined(HMM_ACOSF) || !defined(HMM_ATANF)|| !defined(HMM_ATAN2F) -#include +#include #endif - + #ifndef HMM_SINF #define HMM_SINF sinf -#endif - +#endif + #ifndef HMM_COSF #define HMM_COSF cosf -#endif - +#endif + #ifndef HMM_TANF #define HMM_TANF tanf -#endif +#endif #ifndef HMM_SQRTF #define HMM_SQRTF sqrtf -#endif - +#endif + #ifndef HMM_EXPF #define HMM_EXPF expf #endif @@ -209,7 +217,7 @@ typedef union hmm_vec2 { float Left, Right; }; - + struct { float Width, Height; @@ -327,8 +335,8 @@ typedef union hmm_vec4 }; float Elements[4]; - -#ifdef HANDMADE_MATH__USE_SSE + +#ifdef HANDMADE_MATH__USE_SSE __m128 InternalElementsSSE; #endif @@ -343,7 +351,7 @@ typedef union hmm_vec4 typedef union hmm_mat4 { float Elements[4][4]; - + #ifdef HANDMADE_MATH__USE_SSE __m128 Columns[4]; @@ -380,13 +388,13 @@ typedef union hmm_quaternion float X, Y, Z; }; }; - + float W; }; - + float Elements[4]; -#ifdef HANDMADE_MATH__USE_SSE +#ifdef HANDMADE_MATH__USE_SSE __m128 InternalElementsSSE; #endif } hmm_quaternion; @@ -396,71 +404,98 @@ typedef int32_t hmm_bool; typedef hmm_vec2 hmm_v2; typedef hmm_vec3 hmm_v3; typedef hmm_vec4 hmm_v4; -typedef hmm_mat4 hmm_m4; +typedef hmm_mat4 hmm_m4; /* * Floating-point math functions */ +COVERAGE(HMM_SinF, 1) HMM_INLINE float HMM_SinF(float Radians) { + ASSERT_COVERED(HMM_SinF); + float Result = HMM_SINF(Radians); - + return (Result); } +COVERAGE(HMM_CosF, 1) HMM_INLINE float HMM_CosF(float Radians) { + ASSERT_COVERED(HMM_CosF); + float Result = HMM_COSF(Radians); - + return (Result); } +COVERAGE(HMM_TanF, 1) HMM_INLINE float HMM_TanF(float Radians) { + ASSERT_COVERED(HMM_TanF); + float Result = HMM_TANF(Radians); - + return (Result); } +COVERAGE(HMM_ACosF, 1) HMM_INLINE float HMM_ACosF(float Radians) { + ASSERT_COVERED(HMM_ACosF); + float Result = HMM_ACOSF(Radians); - + return (Result); } +COVERAGE(HMM_ATanF, 1) HMM_INLINE float HMM_ATanF(float Radians) { + ASSERT_COVERED(HMM_ATanF); + float Result = HMM_ATANF(Radians); - + return (Result); } +COVERAGE(HMM_ATan2F, 1) HMM_INLINE float HMM_ATan2F(float Left, float Right) { + ASSERT_COVERED(HMM_ATan2F); + float Result = HMM_ATAN2F(Left, Right); - + return (Result); } +COVERAGE(HMM_ExpF, 1) HMM_INLINE float HMM_ExpF(float Float) { + ASSERT_COVERED(HMM_ExpF); + float Result = HMM_EXPF(Float); - + return (Result); } +COVERAGE(HMM_LogF, 1) HMM_INLINE float HMM_LogF(float Float) { + ASSERT_COVERED(HMM_LogF); + float Result = HMM_LOGF(Float); - + return (Result); } +COVERAGE(HMM_SquareRootF, 1) HMM_INLINE float HMM_SquareRootF(float Float) { + ASSERT_COVERED(HMM_SquareRootF); + float Result; #ifdef HANDMADE_MATH__USE_SSE @@ -469,13 +504,16 @@ HMM_INLINE float HMM_SquareRootF(float Float) Result = _mm_cvtss_f32(Out); #else Result = HMM_SQRTF(Float); -#endif +#endif return(Result); } +COVERAGE(HMM_RSquareRootF, 1) HMM_INLINE float HMM_RSquareRootF(float Float) { + ASSERT_COVERED(HMM_RSquareRootF); + float Result; #ifdef HANDMADE_MATH__USE_SSE @@ -491,8 +529,11 @@ HMM_INLINE float HMM_RSquareRootF(float Float) HMM_EXTERN float HMM_Power(float Base, int Exponent); +COVERAGE(HMM_PowerF, 1) HMM_INLINE float HMM_PowerF(float Base, float Exponent) { + ASSERT_COVERED(HMM_PowerF); + float Result = HMM_EXPF(Exponent * HMM_LOGF(Base)); return (Result); @@ -502,22 +543,32 @@ HMM_INLINE float HMM_PowerF(float Base, float Exponent) /* * Utility functions */ + +COVERAGE(HMM_ToRadians, 1) HMM_INLINE float HMM_ToRadians(float Degrees) { + ASSERT_COVERED(HMM_ToRadians); + float Result = Degrees * (HMM_PI32 / 180.0f); - + return (Result); } +COVERAGE(HMM_Lerp, 1) HMM_INLINE float HMM_Lerp(float A, float Time, float B) { + ASSERT_COVERED(HMM_Lerp); + float Result = (1.0f - Time) * A + Time * B; return (Result); } +COVERAGE(HMM_Clamp, 1) HMM_INLINE float HMM_Clamp(float Min, float Value, float Max) { + ASSERT_COVERED(HMM_Clamp); + float Result = Value; if(Result < Min) @@ -537,8 +588,11 @@ HMM_INLINE float HMM_Clamp(float Min, float Value, float Max) * Vector initialization */ +COVERAGE(HMM_Vec2, 1) HMM_INLINE hmm_vec2 HMM_Vec2(float X, float Y) { + ASSERT_COVERED(HMM_Vec2); + hmm_vec2 Result; Result.X = X; @@ -547,8 +601,11 @@ HMM_INLINE hmm_vec2 HMM_Vec2(float X, float Y) return (Result); } +COVERAGE(HMM_Vec2i, 1) HMM_INLINE hmm_vec2 HMM_Vec2i(int X, int Y) { + ASSERT_COVERED(HMM_Vec2i); + hmm_vec2 Result; Result.X = (float)X; @@ -557,8 +614,11 @@ HMM_INLINE hmm_vec2 HMM_Vec2i(int X, int Y) return (Result); } +COVERAGE(HMM_Vec3, 1) HMM_INLINE hmm_vec3 HMM_Vec3(float X, float Y, float Z) { + ASSERT_COVERED(HMM_Vec3); + hmm_vec3 Result; Result.X = X; @@ -568,8 +628,11 @@ HMM_INLINE hmm_vec3 HMM_Vec3(float X, float Y, float Z) return (Result); } +COVERAGE(HMM_Vec3i, 1) HMM_INLINE hmm_vec3 HMM_Vec3i(int X, int Y, int Z) { + ASSERT_COVERED(HMM_Vec3i); + hmm_vec3 Result; Result.X = (float)X; @@ -579,8 +642,11 @@ HMM_INLINE hmm_vec3 HMM_Vec3i(int X, int Y, int Z) return (Result); } +COVERAGE(HMM_Vec4, 1) HMM_INLINE hmm_vec4 HMM_Vec4(float X, float Y, float Z, float W) { + ASSERT_COVERED(HMM_Vec4); + hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE @@ -595,8 +661,11 @@ HMM_INLINE hmm_vec4 HMM_Vec4(float X, float Y, float Z, float W) return (Result); } +COVERAGE(HMM_Vec4i, 1) HMM_INLINE hmm_vec4 HMM_Vec4i(int X, int Y, int Z, int W) { + ASSERT_COVERED(HMM_Vec4i); + hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE @@ -611,17 +680,20 @@ HMM_INLINE hmm_vec4 HMM_Vec4i(int X, int Y, int Z, int W) return (Result); } +COVERAGE(HMM_Vec4v, 1) HMM_INLINE hmm_vec4 HMM_Vec4v(hmm_vec3 Vector, float W) { + ASSERT_COVERED(HMM_Vec4v); + hmm_vec4 Result; - + #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_setr_ps(Vector.X, Vector.Y, Vector.Z, W); #else Result.XYZ = Vector; Result.W = W; #endif - + return (Result); } @@ -630,8 +702,11 @@ HMM_INLINE hmm_vec4 HMM_Vec4v(hmm_vec3 Vector, float W) * Binary vector operations */ +COVERAGE(HMM_AddVec2, 1) HMM_INLINE hmm_vec2 HMM_AddVec2(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_AddVec2); + hmm_vec2 Result; Result.X = Left.X + Right.X; @@ -640,8 +715,11 @@ HMM_INLINE hmm_vec2 HMM_AddVec2(hmm_vec2 Left, hmm_vec2 Right) return (Result); } +COVERAGE(HMM_AddVec3, 1) HMM_INLINE hmm_vec3 HMM_AddVec3(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_AddVec3); + hmm_vec3 Result; Result.X = Left.X + Right.X; @@ -651,24 +729,30 @@ HMM_INLINE hmm_vec3 HMM_AddVec3(hmm_vec3 Left, hmm_vec3 Right) return (Result); } +COVERAGE(HMM_AddVec4, 1) HMM_INLINE hmm_vec4 HMM_AddVec4(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_AddVec4); + hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_add_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); -#else +#else Result.X = Left.X + Right.X; Result.Y = Left.Y + Right.Y; Result.Z = Left.Z + Right.Z; - Result.W = Left.W + Right.W; + Result.W = Left.W + Right.W; #endif return (Result); } +COVERAGE(HMM_SubtractVec2, 1) HMM_INLINE hmm_vec2 HMM_SubtractVec2(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_SubtractVec2); + hmm_vec2 Result; Result.X = Left.X - Right.X; @@ -677,8 +761,11 @@ HMM_INLINE hmm_vec2 HMM_SubtractVec2(hmm_vec2 Left, hmm_vec2 Right) return (Result); } +COVERAGE(HMM_SubtractVec3, 1) HMM_INLINE hmm_vec3 HMM_SubtractVec3(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_SubtractVec3); + hmm_vec3 Result; Result.X = Left.X - Right.X; @@ -688,24 +775,30 @@ HMM_INLINE hmm_vec3 HMM_SubtractVec3(hmm_vec3 Left, hmm_vec3 Right) return (Result); } +COVERAGE(HMM_SubtractVec4, 1) HMM_INLINE hmm_vec4 HMM_SubtractVec4(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_SubtractVec4); + hmm_vec4 Result; - + #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_sub_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); -#else +#else Result.X = Left.X - Right.X; Result.Y = Left.Y - Right.Y; Result.Z = Left.Z - Right.Z; - Result.W = Left.W - Right.W; + Result.W = Left.W - Right.W; #endif return (Result); } +COVERAGE(HMM_MultiplyVec2, 1) HMM_INLINE hmm_vec2 HMM_MultiplyVec2(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_MultiplyVec2); + hmm_vec2 Result; Result.X = Left.X * Right.X; @@ -714,8 +807,11 @@ HMM_INLINE hmm_vec2 HMM_MultiplyVec2(hmm_vec2 Left, hmm_vec2 Right) return (Result); } +COVERAGE(HMM_MultiplyVec2f, 1) HMM_INLINE hmm_vec2 HMM_MultiplyVec2f(hmm_vec2 Left, float Right) { + ASSERT_COVERED(HMM_MultiplyVec2f); + hmm_vec2 Result; Result.X = Left.X * Right; @@ -724,8 +820,11 @@ HMM_INLINE hmm_vec2 HMM_MultiplyVec2f(hmm_vec2 Left, float Right) return (Result); } +COVERAGE(HMM_MultiplyVec3, 1) HMM_INLINE hmm_vec3 HMM_MultiplyVec3(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_MultiplyVec3); + hmm_vec3 Result; Result.X = Left.X * Right.X; @@ -735,8 +834,11 @@ HMM_INLINE hmm_vec3 HMM_MultiplyVec3(hmm_vec3 Left, hmm_vec3 Right) return (Result); } +COVERAGE(HMM_MultiplyVec3f, 1) HMM_INLINE hmm_vec3 HMM_MultiplyVec3f(hmm_vec3 Left, float Right) { + ASSERT_COVERED(HMM_MultiplyVec3f); + hmm_vec3 Result; Result.X = Left.X * Right; @@ -746,8 +848,11 @@ HMM_INLINE hmm_vec3 HMM_MultiplyVec3f(hmm_vec3 Left, float Right) return (Result); } +COVERAGE(HMM_MultiplyVec4, 1) HMM_INLINE hmm_vec4 HMM_MultiplyVec4(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_MultiplyVec4); + hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE @@ -756,31 +861,37 @@ HMM_INLINE hmm_vec4 HMM_MultiplyVec4(hmm_vec4 Left, hmm_vec4 Right) Result.X = Left.X * Right.X; Result.Y = Left.Y * Right.Y; Result.Z = Left.Z * Right.Z; - Result.W = Left.W * Right.W; + Result.W = Left.W * Right.W; #endif return (Result); } +COVERAGE(HMM_MultiplyVec4f, 1) HMM_INLINE hmm_vec4 HMM_MultiplyVec4f(hmm_vec4 Left, float Right) { + ASSERT_COVERED(HMM_MultiplyVec4f); + hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE __m128 Scalar = _mm_set1_ps(Right); Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Scalar); -#else +#else Result.X = Left.X * Right; Result.Y = Left.Y * Right; Result.Z = Left.Z * Right; Result.W = Left.W * Right; #endif - + return (Result); } +COVERAGE(HMM_DivideVec2, 1) HMM_INLINE hmm_vec2 HMM_DivideVec2(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_DivideVec2); + hmm_vec2 Result; Result.X = Left.X / Right.X; @@ -789,8 +900,11 @@ HMM_INLINE hmm_vec2 HMM_DivideVec2(hmm_vec2 Left, hmm_vec2 Right) return (Result); } +COVERAGE(HMM_DivideVec2f, 1) HMM_INLINE hmm_vec2 HMM_DivideVec2f(hmm_vec2 Left, float Right) { + ASSERT_COVERED(HMM_DivideVec2f); + hmm_vec2 Result; Result.X = Left.X / Right; @@ -799,8 +913,11 @@ HMM_INLINE hmm_vec2 HMM_DivideVec2f(hmm_vec2 Left, float Right) return (Result); } +COVERAGE(HMM_DivideVec3, 1) HMM_INLINE hmm_vec3 HMM_DivideVec3(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_DivideVec3); + hmm_vec3 Result; Result.X = Left.X / Right.X; @@ -810,8 +927,11 @@ HMM_INLINE hmm_vec3 HMM_DivideVec3(hmm_vec3 Left, hmm_vec3 Right) return (Result); } +COVERAGE(HMM_DivideVec3f, 1) HMM_INLINE hmm_vec3 HMM_DivideVec3f(hmm_vec3 Left, float Right) { + ASSERT_COVERED(HMM_DivideVec3f); + hmm_vec3 Result; Result.X = Left.X / Right; @@ -821,10 +941,13 @@ HMM_INLINE hmm_vec3 HMM_DivideVec3f(hmm_vec3 Left, float Right) return (Result); } +COVERAGE(HMM_DivideVec4, 1) HMM_INLINE hmm_vec4 HMM_DivideVec4(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_DivideVec4); + hmm_vec4 Result; - + #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); #else @@ -833,85 +956,109 @@ HMM_INLINE hmm_vec4 HMM_DivideVec4(hmm_vec4 Left, hmm_vec4 Right) Result.Z = Left.Z / Right.Z; Result.W = Left.W / Right.W; #endif - + return (Result); } +COVERAGE(HMM_DivideVec4f, 1) HMM_INLINE hmm_vec4 HMM_DivideVec4f(hmm_vec4 Left, float Right) { + ASSERT_COVERED(HMM_DivideVec4f); + hmm_vec4 Result; #ifdef HANDMADE_MATH__USE_SSE __m128 Scalar = _mm_set1_ps(Right); Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Scalar); -#else +#else Result.X = Left.X / Right; Result.Y = Left.Y / Right; Result.Z = Left.Z / Right; Result.W = Left.W / Right; #endif - + return (Result); } +COVERAGE(HMM_EqualsVec2, 1) HMM_INLINE hmm_bool HMM_EqualsVec2(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_EqualsVec2); + hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y); return (Result); } +COVERAGE(HMM_EqualsVec3, 1) HMM_INLINE hmm_bool HMM_EqualsVec3(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_EqualsVec3); + hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z); return (Result); } +COVERAGE(HMM_EqualsVec4, 1) HMM_INLINE hmm_bool HMM_EqualsVec4(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_EqualsVec4); + hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z && Left.W == Right.W); return (Result); } +COVERAGE(HMM_DotVec2, 1) HMM_INLINE float HMM_DotVec2(hmm_vec2 VecOne, hmm_vec2 VecTwo) { + ASSERT_COVERED(HMM_DotVec2); + float Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y); - + return (Result); } +COVERAGE(HMM_DotVec3, 1) HMM_INLINE float HMM_DotVec3(hmm_vec3 VecOne, hmm_vec3 VecTwo) { + ASSERT_COVERED(HMM_DotVec3); + float Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y) + (VecOne.Z * VecTwo.Z); - + return (Result); } +COVERAGE(HMM_DotVec4, 1) HMM_INLINE float HMM_DotVec4(hmm_vec4 VecOne, hmm_vec4 VecTwo) { + ASSERT_COVERED(HMM_DotVec4); + float Result; - // NOTE(zak): IN the future if we wanna check what version SSE is support - // we can use _mm_dp_ps (4.3) but for now we will use the old way. + // NOTE(zak): IN the future if we wanna check what version SSE is support + // we can use _mm_dp_ps (4.3) but for now we will use the old way. // Or a r = _mm_mul_ps(v1, v2), r = _mm_hadd_ps(r, r), r = _mm_hadd_ps(r, r) for SSE3 #ifdef HANDMADE_MATH__USE_SSE __m128 SSEResultOne = _mm_mul_ps(VecOne.InternalElementsSSE, VecTwo.InternalElementsSSE); __m128 SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(2, 3, 0, 1)); SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(0, 1, 2, 3)); - SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); + SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); _mm_store_ss(&Result, SSEResultOne); #else Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y) + (VecOne.Z * VecTwo.Z) + (VecOne.W * VecTwo.W); #endif - + return (Result); } +COVERAGE(HMM_Cross, 1) HMM_INLINE hmm_vec3 HMM_Cross(hmm_vec3 VecOne, hmm_vec3 VecTwo) { + ASSERT_COVERED(HMM_Cross); + hmm_vec3 Result; Result.X = (VecOne.Y * VecTwo.Z) - (VecOne.Z * VecTwo.Y); @@ -926,118 +1073,160 @@ HMM_INLINE hmm_vec3 HMM_Cross(hmm_vec3 VecOne, hmm_vec3 VecTwo) * Unary vector operations */ +COVERAGE(HMM_LengthSquaredVec2, 1) HMM_INLINE float HMM_LengthSquaredVec2(hmm_vec2 A) { + ASSERT_COVERED(HMM_LengthSquaredVec2); + float Result = HMM_DotVec2(A, A); - - return(Result); + + return (Result); } +COVERAGE(HMM_LengthSquaredVec3, 1) HMM_INLINE float HMM_LengthSquaredVec3(hmm_vec3 A) { + ASSERT_COVERED(HMM_LengthSquaredVec3); + float Result = HMM_DotVec3(A, A); - + return (Result); } +COVERAGE(HMM_LengthSquaredVec4, 1) HMM_INLINE float HMM_LengthSquaredVec4(hmm_vec4 A) { + ASSERT_COVERED(HMM_LengthSquaredVec4); + float Result = HMM_DotVec4(A, A); - + return (Result); } +COVERAGE(HMM_LengthVec2, 1) HMM_INLINE float HMM_LengthVec2(hmm_vec2 A) { + ASSERT_COVERED(HMM_LengthVec2); + float Result = HMM_SquareRootF(HMM_LengthSquaredVec2(A)); - + return (Result); } +COVERAGE(HMM_LengthVec3, 1) HMM_INLINE float HMM_LengthVec3(hmm_vec3 A) { + ASSERT_COVERED(HMM_LengthVec3); + float Result = HMM_SquareRootF(HMM_LengthSquaredVec3(A)); - + return (Result); } +COVERAGE(HMM_LengthVec4, 1) HMM_INLINE float HMM_LengthVec4(hmm_vec4 A) { + ASSERT_COVERED(HMM_LengthVec4); + float Result = HMM_SquareRootF(HMM_LengthSquaredVec4(A)); - + return(Result); } +COVERAGE(HMM_NormalizeVec2, 2) HMM_INLINE hmm_vec2 HMM_NormalizeVec2(hmm_vec2 A) { + ASSERT_COVERED(HMM_NormalizeVec2); + hmm_vec2 Result = {0}; float VectorLength = HMM_LengthVec2(A); - + /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ if (VectorLength != 0.0f) { + ASSERT_COVERED(HMM_NormalizeVec2); + Result.X = A.X * (1.0f / VectorLength); Result.Y = A.Y * (1.0f / VectorLength); } - + return (Result); } +COVERAGE(HMM_NormalizeVec3, 2) HMM_INLINE hmm_vec3 HMM_NormalizeVec3(hmm_vec3 A) { + ASSERT_COVERED(HMM_NormalizeVec3); + hmm_vec3 Result = {0}; float VectorLength = HMM_LengthVec3(A); - + /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ if (VectorLength != 0.0f) { + ASSERT_COVERED(HMM_NormalizeVec3); + Result.X = A.X * (1.0f / VectorLength); Result.Y = A.Y * (1.0f / VectorLength); Result.Z = A.Z * (1.0f / VectorLength); } - + return (Result); } +COVERAGE(HMM_NormalizeVec4, 2) HMM_INLINE hmm_vec4 HMM_NormalizeVec4(hmm_vec4 A) { + ASSERT_COVERED(HMM_NormalizeVec4); + hmm_vec4 Result = {0}; float VectorLength = HMM_LengthVec4(A); - + /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ if (VectorLength != 0.0f) { + ASSERT_COVERED(HMM_NormalizeVec4); + float Multiplier = 1.0f / VectorLength; - + #ifdef HANDMADE_MATH__USE_SSE __m128 SSEMultiplier = _mm_set1_ps(Multiplier); - Result.InternalElementsSSE = _mm_mul_ps(A.InternalElementsSSE, SSEMultiplier); -#else + Result.InternalElementsSSE = _mm_mul_ps(A.InternalElementsSSE, SSEMultiplier); +#else Result.X = A.X * Multiplier; Result.Y = A.Y * Multiplier; Result.Z = A.Z * Multiplier; Result.W = A.W * Multiplier; #endif } - + return (Result); } +COVERAGE(HMM_FastNormalizeVec2, 1) HMM_INLINE hmm_vec2 HMM_FastNormalizeVec2(hmm_vec2 A) { + ASSERT_COVERED(HMM_FastNormalizeVec2); + return HMM_MultiplyVec2f(A, HMM_RSquareRootF(HMM_DotVec2(A, A))); } +COVERAGE(HMM_FastNormalizeVec3, 1) HMM_INLINE hmm_vec3 HMM_FastNormalizeVec3(hmm_vec3 A) { + ASSERT_COVERED(HMM_FastNormalizeVec3); + return HMM_MultiplyVec3f(A, HMM_RSquareRootF(HMM_DotVec3(A, A))); } +COVERAGE(HMM_FastNormalizeVec4, 1) HMM_INLINE hmm_vec4 HMM_FastNormalizeVec4(hmm_vec4 A) { + ASSERT_COVERED(HMM_FastNormalizeVec4); + return HMM_MultiplyVec4f(A, HMM_RSquareRootF(HMM_DotVec4(A, A))); } @@ -1047,14 +1236,17 @@ HMM_INLINE hmm_vec4 HMM_FastNormalizeVec4(hmm_vec4 A) */ #ifdef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_LinearCombineSSE, 1) HMM_INLINE __m128 HMM_LinearCombineSSE(__m128 Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_LinearCombineSSE); + __m128 Result; Result = _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0x00), Right.Columns[0]); Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0x55), Right.Columns[1])); Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0xaa), Right.Columns[2])); Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0xff), Right.Columns[3])); - + return (Result); } #endif @@ -1064,17 +1256,23 @@ HMM_INLINE __m128 HMM_LinearCombineSSE(__m128 Left, hmm_mat4 Right) * Matrix functions */ +COVERAGE(HMM_Mat4, 1) HMM_INLINE hmm_mat4 HMM_Mat4(void) { + ASSERT_COVERED(HMM_Mat4); + hmm_mat4 Result = {0}; return (Result); } +COVERAGE(HMM_Mat4d, 1) HMM_INLINE hmm_mat4 HMM_Mat4d(float Diagonal) { + ASSERT_COVERED(HMM_Mat4d); + hmm_mat4 Result = HMM_Mat4(); - + Result.Elements[0][0] = Diagonal; Result.Elements[1][1] = Diagonal; Result.Elements[2][2] = Diagonal; @@ -1084,10 +1282,13 @@ HMM_INLINE hmm_mat4 HMM_Mat4d(float Diagonal) } #ifdef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_Transpose, 1) HMM_INLINE hmm_mat4 HMM_Transpose(hmm_mat4 Matrix) { + ASSERT_COVERED(HMM_Transpose); + hmm_mat4 Result = Matrix; - + _MM_TRANSPOSE4_PS(Result.Columns[0], Result.Columns[1], Result.Columns[2], Result.Columns[3]); return (Result); @@ -1097,14 +1298,17 @@ HMM_EXTERN hmm_mat4 HMM_Transpose(hmm_mat4 Matrix); #endif #ifdef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_AddMat4, 1) HMM_INLINE hmm_mat4 HMM_AddMat4(hmm_mat4 Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_AddMat4); + hmm_mat4 Result; Result.Columns[0] = _mm_add_ps(Left.Columns[0], Right.Columns[0]); Result.Columns[1] = _mm_add_ps(Left.Columns[1], Right.Columns[1]); Result.Columns[2] = _mm_add_ps(Left.Columns[2], Right.Columns[2]); - Result.Columns[3] = _mm_add_ps(Left.Columns[3], Right.Columns[3]); + Result.Columns[3] = _mm_add_ps(Left.Columns[3], Right.Columns[3]); return (Result); } @@ -1113,8 +1317,11 @@ HMM_EXTERN hmm_mat4 HMM_AddMat4(hmm_mat4 Left, hmm_mat4 Right); #endif #ifdef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_SubtractMat4, 1) HMM_INLINE hmm_mat4 HMM_SubtractMat4(hmm_mat4 Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_SubtractMat4); + hmm_mat4 Result; Result.Columns[0] = _mm_sub_ps(Left.Columns[0], Right.Columns[0]); @@ -1131,8 +1338,11 @@ HMM_EXTERN hmm_mat4 HMM_SubtractMat4(hmm_mat4 Left, hmm_mat4 Right); HMM_EXTERN hmm_mat4 HMM_MultiplyMat4(hmm_mat4 Left, hmm_mat4 Right); #ifdef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_MultiplyMat4f, 1) HMM_INLINE hmm_mat4 HMM_MultiplyMat4f(hmm_mat4 Matrix, float Scalar) { + ASSERT_COVERED(HMM_MultiplyMat4f); + hmm_mat4 Result; __m128 SSEScalar = _mm_set1_ps(Scalar); @@ -1150,15 +1360,18 @@ HMM_EXTERN hmm_mat4 HMM_MultiplyMat4f(hmm_mat4 Matrix, float Scalar); HMM_EXTERN hmm_vec4 HMM_MultiplyMat4ByVec4(hmm_mat4 Matrix, hmm_vec4 Vector); #ifdef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_DivideMat4f, 1) HMM_INLINE hmm_mat4 HMM_DivideMat4f(hmm_mat4 Matrix, float Scalar) { + ASSERT_COVERED(HMM_DivideMat4f); + hmm_mat4 Result; - + __m128 SSEScalar = _mm_set1_ps(Scalar); Result.Columns[0] = _mm_div_ps(Matrix.Columns[0], SSEScalar); Result.Columns[1] = _mm_div_ps(Matrix.Columns[1], SSEScalar); Result.Columns[2] = _mm_div_ps(Matrix.Columns[2], SSEScalar); - Result.Columns[3] = _mm_div_ps(Matrix.Columns[3], SSEScalar); + Result.Columns[3] = _mm_div_ps(Matrix.Columns[3], SSEScalar); return (Result); } @@ -1171,8 +1384,11 @@ HMM_EXTERN hmm_mat4 HMM_DivideMat4f(hmm_mat4 Matrix, float Scalar); * Common graphics transformations */ +COVERAGE(HMM_Orthographic, 1) HMM_INLINE hmm_mat4 HMM_Orthographic(float Left, float Right, float Bottom, float Top, float Near, float Far) { + ASSERT_COVERED(HMM_Orthographic); + hmm_mat4 Result = HMM_Mat4(); Result.Elements[0][0] = 2.0f / (Right - Left); @@ -1187,14 +1403,17 @@ HMM_INLINE hmm_mat4 HMM_Orthographic(float Left, float Right, float Bottom, floa return (Result); } +COVERAGE(HMM_Perspective, 1) HMM_INLINE hmm_mat4 HMM_Perspective(float FOV, float AspectRatio, float Near, float Far) { + ASSERT_COVERED(HMM_Perspective); + hmm_mat4 Result = HMM_Mat4(); // See https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml float Cotangent = 1.0f / HMM_TanF(FOV * (HMM_PI32 / 360.0f)); - + Result.Elements[0][0] = Cotangent / AspectRatio; Result.Elements[1][1] = Cotangent; Result.Elements[2][3] = -1.0f; @@ -1205,8 +1424,11 @@ HMM_INLINE hmm_mat4 HMM_Perspective(float FOV, float AspectRatio, float Near, fl return (Result); } +COVERAGE(HMM_Translate, 1) HMM_INLINE hmm_mat4 HMM_Translate(hmm_vec3 Translation) { + ASSERT_COVERED(HMM_Translate); + hmm_mat4 Result = HMM_Mat4d(1.0f); Result.Elements[3][0] = Translation.X; @@ -1218,8 +1440,11 @@ HMM_INLINE hmm_mat4 HMM_Translate(hmm_vec3 Translation) HMM_EXTERN hmm_mat4 HMM_Rotate(float Angle, hmm_vec3 Axis); +COVERAGE(HMM_Scale, 1) HMM_INLINE hmm_mat4 HMM_Scale(hmm_vec3 Scale) { + ASSERT_COVERED(HMM_Scale); + hmm_mat4 Result = HMM_Mat4d(1.0f); Result.Elements[0][0] = Scale.X; @@ -1236,8 +1461,11 @@ HMM_EXTERN hmm_mat4 HMM_LookAt(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up); * Quaternion operations */ +COVERAGE(HMM_Quaternion, 1) HMM_INLINE hmm_quaternion HMM_Quaternion(float X, float Y, float Z, float W) { + ASSERT_COVERED(HMM_Quaternion); + hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE @@ -1252,8 +1480,11 @@ HMM_INLINE hmm_quaternion HMM_Quaternion(float X, float Y, float Z, float W) return (Result); } +COVERAGE(HMM_QuaternionV4, 1) HMM_INLINE hmm_quaternion HMM_QuaternionV4(hmm_vec4 Vector) { + ASSERT_COVERED(HMM_QuaternionV4); + hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE @@ -1268,8 +1499,11 @@ HMM_INLINE hmm_quaternion HMM_QuaternionV4(hmm_vec4 Vector) return (Result); } +COVERAGE(HMM_AddQuaternion, 1) HMM_INLINE hmm_quaternion HMM_AddQuaternion(hmm_quaternion Left, hmm_quaternion Right) { + ASSERT_COVERED(HMM_AddQuaternion); + hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE @@ -1285,8 +1519,11 @@ HMM_INLINE hmm_quaternion HMM_AddQuaternion(hmm_quaternion Left, hmm_quaternion return (Result); } +COVERAGE(HMM_SubtractQuaternion, 1) HMM_INLINE hmm_quaternion HMM_SubtractQuaternion(hmm_quaternion Left, hmm_quaternion Right) { + ASSERT_COVERED(HMM_SubtractQuaternion); + hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE @@ -1302,26 +1539,29 @@ HMM_INLINE hmm_quaternion HMM_SubtractQuaternion(hmm_quaternion Left, hmm_quater return (Result); } +COVERAGE(HMM_MultiplyQuaternion, 1) HMM_INLINE hmm_quaternion HMM_MultiplyQuaternion(hmm_quaternion Left, hmm_quaternion Right) { + ASSERT_COVERED(HMM_MultiplyQuaternion); + hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE - __m128 SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(0, 0, 0, 0)), _mm_setr_ps(0.f, -0.f, 0.f, -0.f)); - __m128 SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(0, 1, 2, 3)); - __m128 SSEResultThree = _mm_mul_ps(SSEResultTwo, SSEResultOne); + __m128 SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(0, 0, 0, 0)), _mm_setr_ps(0.f, -0.f, 0.f, -0.f)); + __m128 SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(0, 1, 2, 3)); + __m128 SSEResultThree = _mm_mul_ps(SSEResultTwo, SSEResultOne); - SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(1, 1, 1, 1)) , _mm_setr_ps(0.f, 0.f, -0.f, -0.f)); - SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(1, 0, 3, 2)); - SSEResultThree = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); + SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(1, 1, 1, 1)) , _mm_setr_ps(0.f, 0.f, -0.f, -0.f)); + SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(1, 0, 3, 2)); + SSEResultThree = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); - SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(2, 2, 2, 2)), _mm_setr_ps(-0.f, 0.f, 0.f, -0.f)); - SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(2, 3, 0, 1)); - SSEResultThree = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); + SSEResultOne = _mm_xor_ps(_mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(2, 2, 2, 2)), _mm_setr_ps(-0.f, 0.f, 0.f, -0.f)); + SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(2, 3, 0, 1)); + SSEResultThree = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); - SSEResultOne = _mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(3, 3, 3, 3)); - SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(3, 2, 1, 0)); - Result.InternalElementsSSE = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); + SSEResultOne = _mm_shuffle_ps(Left.InternalElementsSSE, Left.InternalElementsSSE, _MM_SHUFFLE(3, 3, 3, 3)); + SSEResultTwo = _mm_shuffle_ps(Right.InternalElementsSSE, Right.InternalElementsSSE, _MM_SHUFFLE(3, 2, 1, 0)); + Result.InternalElementsSSE = _mm_add_ps(SSEResultThree, _mm_mul_ps(SSEResultTwo, SSEResultOne)); #else Result.X = (Left.X * Right.W) + (Left.Y * Right.Z) - (Left.Z * Right.Y) + (Left.W * Right.X); Result.Y = (-Left.X * Right.Z) + (Left.Y * Right.W) + (Left.Z * Right.X) + (Left.W * Right.Y); @@ -1332,8 +1572,11 @@ HMM_INLINE hmm_quaternion HMM_MultiplyQuaternion(hmm_quaternion Left, hmm_quater return (Result); } +COVERAGE(HMM_MultiplyQuaternionF, 1) HMM_INLINE hmm_quaternion HMM_MultiplyQuaternionF(hmm_quaternion Left, float Multiplicative) { + ASSERT_COVERED(HMM_MultiplyQuaternionF); + hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE @@ -1349,8 +1592,11 @@ HMM_INLINE hmm_quaternion HMM_MultiplyQuaternionF(hmm_quaternion Left, float Mul return (Result); } +COVERAGE(HMM_DivideQuaternionF, 1) HMM_INLINE hmm_quaternion HMM_DivideQuaternionF(hmm_quaternion Left, float Dividend) { + ASSERT_COVERED(HMM_DivideQuaternionF); + hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE @@ -1368,8 +1614,11 @@ HMM_INLINE hmm_quaternion HMM_DivideQuaternionF(hmm_quaternion Left, float Divid HMM_EXTERN hmm_quaternion HMM_InverseQuaternion(hmm_quaternion Left); +COVERAGE(HMM_DotQuaternion, 1) HMM_INLINE float HMM_DotQuaternion(hmm_quaternion Left, hmm_quaternion Right) { + ASSERT_COVERED(HMM_DotQuaternion); + float Result; #ifdef HANDMADE_MATH__USE_SSE @@ -1386,8 +1635,11 @@ HMM_INLINE float HMM_DotQuaternion(hmm_quaternion Left, hmm_quaternion Right) return (Result); } +COVERAGE(HMM_NormalizeQuaternion, 1) HMM_INLINE hmm_quaternion HMM_NormalizeQuaternion(hmm_quaternion Left) { + ASSERT_COVERED(HMM_NormalizeQuaternion); + hmm_quaternion Result; float Length = HMM_SquareRootF(HMM_DotQuaternion(Left, Left)); @@ -1396,8 +1648,11 @@ HMM_INLINE hmm_quaternion HMM_NormalizeQuaternion(hmm_quaternion Left) return (Result); } +COVERAGE(HMM_NLerp, 1) HMM_INLINE hmm_quaternion HMM_NLerp(hmm_quaternion Left, float Time, hmm_quaternion Right) { + ASSERT_COVERED(HMM_NLerp); + hmm_quaternion Result; #ifdef HANDMADE_MATH__USE_SSE @@ -1428,744 +1683,1089 @@ HMM_EXTERN hmm_quaternion HMM_QuaternionFromAxisAngle(hmm_vec3 Axis, float Angle #ifdef __cplusplus +COVERAGE(HMM_LengthVec2CPP, 1) HMM_INLINE float HMM_Length(hmm_vec2 A) { + ASSERT_COVERED(HMM_LengthVec2CPP); + float Result = HMM_LengthVec2(A); - + return (Result); } +COVERAGE(HMM_LengthVec3CPP, 1) HMM_INLINE float HMM_Length(hmm_vec3 A) { + ASSERT_COVERED(HMM_LengthVec3CPP); + float Result = HMM_LengthVec3(A); - + return (Result); } +COVERAGE(HMM_LengthVec4CPP, 1) HMM_INLINE float HMM_Length(hmm_vec4 A) { + ASSERT_COVERED(HMM_LengthVec4CPP); + float Result = HMM_LengthVec4(A); - + return (Result); } +COVERAGE(HMM_LengthSquaredVec2CPP, 1) HMM_INLINE float HMM_LengthSquared(hmm_vec2 A) { + ASSERT_COVERED(HMM_LengthSquaredVec2CPP); + float Result = HMM_LengthSquaredVec2(A); - + return (Result); } +COVERAGE(HMM_LengthSquaredVec3CPP, 1) HMM_INLINE float HMM_LengthSquared(hmm_vec3 A) { + ASSERT_COVERED(HMM_LengthSquaredVec3CPP); + float Result = HMM_LengthSquaredVec3(A); - + return (Result); } +COVERAGE(HMM_LengthSquaredVec4CPP, 1) HMM_INLINE float HMM_LengthSquared(hmm_vec4 A) { + ASSERT_COVERED(HMM_LengthSquaredVec4CPP); + float Result = HMM_LengthSquaredVec4(A); - + return (Result); } +COVERAGE(HMM_NormalizeVec2CPP, 1) HMM_INLINE hmm_vec2 HMM_Normalize(hmm_vec2 A) { - hmm_vec2 Result = HMM_NormalizeVec2(A); - + ASSERT_COVERED(HMM_NormalizeVec2CPP); + + hmm_vec2 Result = HMM_NormalizeVec2(A); + return (Result); } +COVERAGE(HMM_NormalizeVec3CPP, 1) HMM_INLINE hmm_vec3 HMM_Normalize(hmm_vec3 A) { + ASSERT_COVERED(HMM_NormalizeVec3CPP); + hmm_vec3 Result = HMM_NormalizeVec3(A); - + return (Result); } +COVERAGE(HMM_NormalizeVec4CPP, 1) HMM_INLINE hmm_vec4 HMM_Normalize(hmm_vec4 A) { + ASSERT_COVERED(HMM_NormalizeVec4CPP); + hmm_vec4 Result = HMM_NormalizeVec4(A); - + return (Result); } +COVERAGE(HMM_FastNormalizeVec2CPP, 1) HMM_INLINE hmm_vec2 HMM_FastNormalize(hmm_vec2 A) { + ASSERT_COVERED(HMM_FastNormalizeVec2CPP); + hmm_vec2 Result = HMM_FastNormalizeVec2(A); return (Result); } +COVERAGE(HMM_FastNormalizeVec3CPP, 1) HMM_INLINE hmm_vec3 HMM_FastNormalize(hmm_vec3 A) { + ASSERT_COVERED(HMM_FastNormalizeVec3CPP); + hmm_vec3 Result = HMM_FastNormalizeVec3(A); return (Result); } +COVERAGE(HMM_FastNormalizeVec4CPP, 1) HMM_INLINE hmm_vec4 HMM_FastNormalize(hmm_vec4 A) { + ASSERT_COVERED(HMM_FastNormalizeVec4CPP); + hmm_vec4 Result = HMM_FastNormalizeVec4(A); return (Result); } +COVERAGE(HMM_NormalizeQuaternionCPP, 1) HMM_INLINE hmm_quaternion HMM_Normalize(hmm_quaternion A) { + ASSERT_COVERED(HMM_NormalizeQuaternionCPP); + hmm_quaternion Result = HMM_NormalizeQuaternion(A); return (Result); } +COVERAGE(HMM_DotVec2CPP, 1) HMM_INLINE float HMM_Dot(hmm_vec2 VecOne, hmm_vec2 VecTwo) { + ASSERT_COVERED(HMM_DotVec2CPP); + float Result = HMM_DotVec2(VecOne, VecTwo); - + return (Result); } +COVERAGE(HMM_DotVec3CPP, 1) HMM_INLINE float HMM_Dot(hmm_vec3 VecOne, hmm_vec3 VecTwo) { + ASSERT_COVERED(HMM_DotVec3CPP); + float Result = HMM_DotVec3(VecOne, VecTwo); - + return (Result); } +COVERAGE(HMM_DotVec4CPP, 1) HMM_INLINE float HMM_Dot(hmm_vec4 VecOne, hmm_vec4 VecTwo) { + ASSERT_COVERED(HMM_DotVec4CPP); + float Result = HMM_DotVec4(VecOne, VecTwo); - + return (Result); } +COVERAGE(HMM_DotQuaternionCPP, 1) HMM_INLINE float HMM_Dot(hmm_quaternion QuatOne, hmm_quaternion QuatTwo) { + ASSERT_COVERED(HMM_DotQuaternionCPP); + float Result = HMM_DotQuaternion(QuatOne, QuatTwo); return (Result); } +COVERAGE(HMM_AddVec2CPP, 1) HMM_INLINE hmm_vec2 HMM_Add(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_AddVec2CPP); + hmm_vec2 Result = HMM_AddVec2(Left, Right); - + return (Result); } +COVERAGE(HMM_AddVec3CPP, 1) HMM_INLINE hmm_vec3 HMM_Add(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_AddVec3CPP); + hmm_vec3 Result = HMM_AddVec3(Left, Right); - + return (Result); } +COVERAGE(HMM_AddVec4CPP, 1) HMM_INLINE hmm_vec4 HMM_Add(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_AddVec4CPP); + hmm_vec4 Result = HMM_AddVec4(Left, Right); - + return (Result); } +COVERAGE(HMM_AddMat4CPP, 1) HMM_INLINE hmm_mat4 HMM_Add(hmm_mat4 Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_AddMat4CPP); + hmm_mat4 Result = HMM_AddMat4(Left, Right); - + return (Result); } +COVERAGE(HMM_AddQuaternionCPP, 1) HMM_INLINE hmm_quaternion HMM_Add(hmm_quaternion Left, hmm_quaternion Right) { + ASSERT_COVERED(HMM_AddQuaternionCPP); + hmm_quaternion Result = HMM_AddQuaternion(Left, Right); - + return (Result); } +COVERAGE(HMM_SubtractVec2CPP, 1) HMM_INLINE hmm_vec2 HMM_Subtract(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_SubtractVec2CPP); + hmm_vec2 Result = HMM_SubtractVec2(Left, Right); - + return (Result); } +COVERAGE(HMM_SubtractVec3CPP, 1) HMM_INLINE hmm_vec3 HMM_Subtract(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_SubtractVec3CPP); + hmm_vec3 Result = HMM_SubtractVec3(Left, Right); - + return (Result); } +COVERAGE(HMM_SubtractVec4CPP, 1) HMM_INLINE hmm_vec4 HMM_Subtract(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_SubtractVec4CPP); + hmm_vec4 Result = HMM_SubtractVec4(Left, Right); - + return (Result); } +COVERAGE(HMM_SubtractMat4CPP, 1) HMM_INLINE hmm_mat4 HMM_Subtract(hmm_mat4 Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_SubtractMat4CPP); + hmm_mat4 Result = HMM_SubtractMat4(Left, Right); - + return (Result); } +COVERAGE(HMM_SubtractQuaternionCPP, 1) HMM_INLINE hmm_quaternion HMM_Subtract(hmm_quaternion Left, hmm_quaternion Right) { + ASSERT_COVERED(HMM_SubtractQuaternionCPP); + hmm_quaternion Result = HMM_SubtractQuaternion(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyVec2CPP, 1) HMM_INLINE hmm_vec2 HMM_Multiply(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_MultiplyVec2CPP); + hmm_vec2 Result = HMM_MultiplyVec2(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyVec2fCPP, 1) HMM_INLINE hmm_vec2 HMM_Multiply(hmm_vec2 Left, float Right) { + ASSERT_COVERED(HMM_MultiplyVec2fCPP); + hmm_vec2 Result = HMM_MultiplyVec2f(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyVec3CPP, 1) HMM_INLINE hmm_vec3 HMM_Multiply(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_MultiplyVec3CPP); + hmm_vec3 Result = HMM_MultiplyVec3(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyVec3fCPP, 1) HMM_INLINE hmm_vec3 HMM_Multiply(hmm_vec3 Left, float Right) { + ASSERT_COVERED(HMM_MultiplyVec3fCPP); + hmm_vec3 Result = HMM_MultiplyVec3f(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyVec4CPP, 1) HMM_INLINE hmm_vec4 HMM_Multiply(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_MultiplyVec4CPP); + hmm_vec4 Result = HMM_MultiplyVec4(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyVec4fCPP, 1) HMM_INLINE hmm_vec4 HMM_Multiply(hmm_vec4 Left, float Right) { + ASSERT_COVERED(HMM_MultiplyVec4fCPP); + hmm_vec4 Result = HMM_MultiplyVec4f(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyMat4CPP, 1) HMM_INLINE hmm_mat4 HMM_Multiply(hmm_mat4 Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_MultiplyMat4CPP); + hmm_mat4 Result = HMM_MultiplyMat4(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyMat4fCPP, 1) HMM_INLINE hmm_mat4 HMM_Multiply(hmm_mat4 Left, float Right) { + ASSERT_COVERED(HMM_MultiplyMat4fCPP); + hmm_mat4 Result = HMM_MultiplyMat4f(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyMat4ByVec4CPP, 1) HMM_INLINE hmm_vec4 HMM_Multiply(hmm_mat4 Matrix, hmm_vec4 Vector) { + ASSERT_COVERED(HMM_MultiplyMat4ByVec4CPP); + hmm_vec4 Result = HMM_MultiplyMat4ByVec4(Matrix, Vector); - + return (Result); } +COVERAGE(HMM_MultiplyQuaternionCPP, 1) HMM_INLINE hmm_quaternion HMM_Multiply(hmm_quaternion Left, hmm_quaternion Right) { + ASSERT_COVERED(HMM_MultiplyQuaternionCPP); + hmm_quaternion Result = HMM_MultiplyQuaternion(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyQuaternionFCPP, 1) HMM_INLINE hmm_quaternion HMM_Multiply(hmm_quaternion Left, float Right) { + ASSERT_COVERED(HMM_MultiplyQuaternionFCPP); + hmm_quaternion Result = HMM_MultiplyQuaternionF(Left, Right); - + return (Result); } +COVERAGE(HMM_DivideVec2CPP, 1) HMM_INLINE hmm_vec2 HMM_Divide(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_DivideVec2CPP); + hmm_vec2 Result = HMM_DivideVec2(Left, Right); - + return (Result); } +COVERAGE(HMM_DivideVec2fCPP, 1) HMM_INLINE hmm_vec2 HMM_Divide(hmm_vec2 Left, float Right) { + ASSERT_COVERED(HMM_DivideVec2fCPP); + hmm_vec2 Result = HMM_DivideVec2f(Left, Right); - + return (Result); } +COVERAGE(HMM_DivideVec3CPP, 1) HMM_INLINE hmm_vec3 HMM_Divide(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_DivideVec3CPP); + hmm_vec3 Result = HMM_DivideVec3(Left, Right); - + return (Result); } +COVERAGE(HMM_DivideVec3fCPP, 1) HMM_INLINE hmm_vec3 HMM_Divide(hmm_vec3 Left, float Right) { + ASSERT_COVERED(HMM_DivideVec3fCPP); + hmm_vec3 Result = HMM_DivideVec3f(Left, Right); - + return (Result); } +COVERAGE(HMM_DivideVec4CPP, 1) HMM_INLINE hmm_vec4 HMM_Divide(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_DivideVec4CPP); + hmm_vec4 Result = HMM_DivideVec4(Left, Right); - + return (Result); } +COVERAGE(HMM_DivideVec4fCPP, 1) HMM_INLINE hmm_vec4 HMM_Divide(hmm_vec4 Left, float Right) { + ASSERT_COVERED(HMM_DivideVec4fCPP); + hmm_vec4 Result = HMM_DivideVec4f(Left, Right); - + return (Result); } +COVERAGE(HMM_DivideMat4fCPP, 1) HMM_INLINE hmm_mat4 HMM_Divide(hmm_mat4 Left, float Right) { + ASSERT_COVERED(HMM_DivideMat4fCPP); + hmm_mat4 Result = HMM_DivideMat4f(Left, Right); - + return (Result); } +COVERAGE(HMM_DivideQuaternionFCPP, 1) HMM_INLINE hmm_quaternion HMM_Divide(hmm_quaternion Left, float Right) { + ASSERT_COVERED(HMM_DivideQuaternionFCPP); + hmm_quaternion Result = HMM_DivideQuaternionF(Left, Right); - + return (Result); } +COVERAGE(HMM_EqualsVec2CPP, 1) HMM_INLINE hmm_bool HMM_Equals(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_EqualsVec2CPP); + hmm_bool Result = HMM_EqualsVec2(Left, Right); - + return (Result); } +COVERAGE(HMM_EqualsVec3CPP, 1) HMM_INLINE hmm_bool HMM_Equals(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_EqualsVec3CPP); + hmm_bool Result = HMM_EqualsVec3(Left, Right); - + return (Result); } +COVERAGE(HMM_EqualsVec4CPP, 1) HMM_INLINE hmm_bool HMM_Equals(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_EqualsVec4CPP); + hmm_bool Result = HMM_EqualsVec4(Left, Right); - + return (Result); } +COVERAGE(HMM_AddVec2Op, 1) HMM_INLINE hmm_vec2 operator+(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_AddVec2Op); + hmm_vec2 Result = HMM_AddVec2(Left, Right); - + return (Result); } +COVERAGE(HMM_AddVec3Op, 1) HMM_INLINE hmm_vec3 operator+(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_AddVec3Op); + hmm_vec3 Result = HMM_AddVec3(Left, Right); - + return (Result); } +COVERAGE(HMM_AddVec4Op, 1) HMM_INLINE hmm_vec4 operator+(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_AddVec4Op); + hmm_vec4 Result = HMM_AddVec4(Left, Right); - + return (Result); } +COVERAGE(HMM_AddMat4Op, 1) HMM_INLINE hmm_mat4 operator+(hmm_mat4 Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_AddMat4Op); + hmm_mat4 Result = HMM_AddMat4(Left, Right); - + return (Result); } +COVERAGE(HMM_AddQuaternionOp, 1) HMM_INLINE hmm_quaternion operator+(hmm_quaternion Left, hmm_quaternion Right) { + ASSERT_COVERED(HMM_AddQuaternionOp); + hmm_quaternion Result = HMM_AddQuaternion(Left, Right); - + return (Result); } +COVERAGE(HMM_SubtractVec2Op, 1) HMM_INLINE hmm_vec2 operator-(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_SubtractVec2Op); + hmm_vec2 Result = HMM_SubtractVec2(Left, Right); - + return (Result); } +COVERAGE(HMM_SubtractVec3Op, 1) HMM_INLINE hmm_vec3 operator-(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_SubtractVec3Op); + hmm_vec3 Result = HMM_SubtractVec3(Left, Right); - + return (Result); } +COVERAGE(HMM_SubtractVec4Op, 1) HMM_INLINE hmm_vec4 operator-(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_SubtractVec4Op); + hmm_vec4 Result = HMM_SubtractVec4(Left, Right); - + return (Result); } +COVERAGE(HMM_SubtractMat4Op, 1) HMM_INLINE hmm_mat4 operator-(hmm_mat4 Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_SubtractMat4Op); + hmm_mat4 Result = HMM_SubtractMat4(Left, Right); - + return (Result); } +COVERAGE(HMM_SubtractQuaternionOp, 1) HMM_INLINE hmm_quaternion operator-(hmm_quaternion Left, hmm_quaternion Right) { + ASSERT_COVERED(HMM_SubtractQuaternionOp); + hmm_quaternion Result = HMM_SubtractQuaternion(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyVec2Op, 1) HMM_INLINE hmm_vec2 operator*(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_MultiplyVec2Op); + hmm_vec2 Result = HMM_MultiplyVec2(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyVec3Op, 1) HMM_INLINE hmm_vec3 operator*(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_MultiplyVec3Op); + hmm_vec3 Result = HMM_MultiplyVec3(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyVec4Op, 1) HMM_INLINE hmm_vec4 operator*(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_MultiplyVec4Op); + hmm_vec4 Result = HMM_MultiplyVec4(Left, Right); return (Result); } +COVERAGE(HMM_MultiplyMat4Op, 1) HMM_INLINE hmm_mat4 operator*(hmm_mat4 Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_MultiplyMat4Op); + hmm_mat4 Result = HMM_MultiplyMat4(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyQuaternionOp, 1) HMM_INLINE hmm_quaternion operator*(hmm_quaternion Left, hmm_quaternion Right) { + ASSERT_COVERED(HMM_MultiplyQuaternionOp); + hmm_quaternion Result = HMM_MultiplyQuaternion(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyVec2fOp, 1) HMM_INLINE hmm_vec2 operator*(hmm_vec2 Left, float Right) { + ASSERT_COVERED(HMM_MultiplyVec2fOp); + hmm_vec2 Result = HMM_MultiplyVec2f(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyVec3fOp, 1) HMM_INLINE hmm_vec3 operator*(hmm_vec3 Left, float Right) { + ASSERT_COVERED(HMM_MultiplyVec3fOp); + hmm_vec3 Result = HMM_MultiplyVec3f(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyVec4fOp, 1) HMM_INLINE hmm_vec4 operator*(hmm_vec4 Left, float Right) { + ASSERT_COVERED(HMM_MultiplyVec4fOp); + hmm_vec4 Result = HMM_MultiplyVec4f(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyMat4fOp, 1) HMM_INLINE hmm_mat4 operator*(hmm_mat4 Left, float Right) { + ASSERT_COVERED(HMM_MultiplyMat4fOp); + hmm_mat4 Result = HMM_MultiplyMat4f(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyQuaternionFOp, 1) HMM_INLINE hmm_quaternion operator*(hmm_quaternion Left, float Right) { + ASSERT_COVERED(HMM_MultiplyQuaternionFOp); + hmm_quaternion Result = HMM_MultiplyQuaternionF(Left, Right); - + return (Result); } +COVERAGE(HMM_MultiplyVec2fOpLeft, 1) HMM_INLINE hmm_vec2 operator*(float Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_MultiplyVec2fOpLeft); + hmm_vec2 Result = HMM_MultiplyVec2f(Right, Left); - + return (Result); } +COVERAGE(HMM_MultiplyVec3fOpLeft, 1) HMM_INLINE hmm_vec3 operator*(float Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_MultiplyVec3fOpLeft); + hmm_vec3 Result = HMM_MultiplyVec3f(Right, Left); return (Result); } +COVERAGE(HMM_MultiplyVec4fOpLeft, 1) HMM_INLINE hmm_vec4 operator*(float Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_MultiplyVec4fOpLeft); + hmm_vec4 Result = HMM_MultiplyVec4f(Right, Left); return (Result); } +COVERAGE(HMM_MultiplyMat4fOpLeft, 1) HMM_INLINE hmm_mat4 operator*(float Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_MultiplyMat4fOpLeft); + hmm_mat4 Result = HMM_MultiplyMat4f(Right, Left); return (Result); } +COVERAGE(HMM_MultiplyQuaternionFOpLeft, 1) HMM_INLINE hmm_quaternion operator*(float Left, hmm_quaternion Right) { + ASSERT_COVERED(HMM_MultiplyQuaternionFOpLeft); + hmm_quaternion Result = HMM_MultiplyQuaternionF(Right, Left); return (Result); } +COVERAGE(HMM_MultiplyMat4ByVec4Op, 1) HMM_INLINE hmm_vec4 operator*(hmm_mat4 Matrix, hmm_vec4 Vector) { + ASSERT_COVERED(HMM_MultiplyMat4ByVec4Op); + hmm_vec4 Result = HMM_MultiplyMat4ByVec4(Matrix, Vector); return (Result); } +COVERAGE(HMM_DivideVec2Op, 1) HMM_INLINE hmm_vec2 operator/(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_DivideVec2Op); + hmm_vec2 Result = HMM_DivideVec2(Left, Right); - + return (Result); } +COVERAGE(HMM_DivideVec3Op, 1) HMM_INLINE hmm_vec3 operator/(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_DivideVec3Op); + hmm_vec3 Result = HMM_DivideVec3(Left, Right); return (Result); } +COVERAGE(HMM_DivideVec4Op, 1) HMM_INLINE hmm_vec4 operator/(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_DivideVec4Op); + hmm_vec4 Result = HMM_DivideVec4(Left, Right); return (Result); } +COVERAGE(HMM_DivideVec2fOp, 1) HMM_INLINE hmm_vec2 operator/(hmm_vec2 Left, float Right) { + ASSERT_COVERED(HMM_DivideVec2fOp); + hmm_vec2 Result = HMM_DivideVec2f(Left, Right); - + return (Result); } +COVERAGE(HMM_DivideVec3fOp, 1) HMM_INLINE hmm_vec3 operator/(hmm_vec3 Left, float Right) { + ASSERT_COVERED(HMM_DivideVec3fOp); + hmm_vec3 Result = HMM_DivideVec3f(Left, Right); - + return (Result); } +COVERAGE(HMM_DivideVec4fOp, 1) HMM_INLINE hmm_vec4 operator/(hmm_vec4 Left, float Right) { + ASSERT_COVERED(HMM_DivideVec4fOp); + hmm_vec4 Result = HMM_DivideVec4f(Left, Right); - + return (Result); } +COVERAGE(HMM_DivideMat4fOp, 1) HMM_INLINE hmm_mat4 operator/(hmm_mat4 Left, float Right) { + ASSERT_COVERED(HMM_DivideMat4fOp); + hmm_mat4 Result = HMM_DivideMat4f(Left, Right); - + return (Result); } +COVERAGE(HMM_DivideQuaternionFOp, 1) HMM_INLINE hmm_quaternion operator/(hmm_quaternion Left, float Right) { + ASSERT_COVERED(HMM_DivideQuaternionFOp); + hmm_quaternion Result = HMM_DivideQuaternionF(Left, Right); - + return (Result); } +COVERAGE(HMM_AddVec2Assign, 1) HMM_INLINE hmm_vec2 &operator+=(hmm_vec2 &Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_AddVec2Assign); + return (Left = Left + Right); } +COVERAGE(HMM_AddVec3Assign, 1) HMM_INLINE hmm_vec3 &operator+=(hmm_vec3 &Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_AddVec3Assign); + return (Left = Left + Right); } +COVERAGE(HMM_AddVec4Assign, 1) HMM_INLINE hmm_vec4 &operator+=(hmm_vec4 &Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_AddVec4Assign); + return (Left = Left + Right); } +COVERAGE(HMM_AddMat4Assign, 1) HMM_INLINE hmm_mat4 &operator+=(hmm_mat4 &Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_AddMat4Assign); + return (Left = Left + Right); } +COVERAGE(HMM_AddQuaternionAssign, 1) HMM_INLINE hmm_quaternion &operator+=(hmm_quaternion &Left, hmm_quaternion Right) { + ASSERT_COVERED(HMM_AddQuaternionAssign); + return (Left = Left + Right); } +COVERAGE(HMM_SubtractVec2Assign, 1) HMM_INLINE hmm_vec2 &operator-=(hmm_vec2 &Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_SubtractVec2Assign); + return (Left = Left - Right); } +COVERAGE(HMM_SubtractVec3Assign, 1) HMM_INLINE hmm_vec3 &operator-=(hmm_vec3 &Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_SubtractVec3Assign); + return (Left = Left - Right); } +COVERAGE(HMM_SubtractVec4Assign, 1) HMM_INLINE hmm_vec4 &operator-=(hmm_vec4 &Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_SubtractVec4Assign); + return (Left = Left - Right); } +COVERAGE(HMM_SubtractMat4Assign, 1) HMM_INLINE hmm_mat4 &operator-=(hmm_mat4 &Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_SubtractMat4Assign); + return (Left = Left - Right); } +COVERAGE(HMM_SubtractQuaternionAssign, 1) HMM_INLINE hmm_quaternion &operator-=(hmm_quaternion &Left, hmm_quaternion Right) { + ASSERT_COVERED(HMM_SubtractQuaternionAssign); + return (Left = Left - Right); } +COVERAGE(HMM_MultiplyVec2Assign, 1) HMM_INLINE hmm_vec2 &operator*=(hmm_vec2 &Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_MultiplyVec2Assign); + return (Left = Left * Right); } +COVERAGE(HMM_MultiplyVec3Assign, 1) HMM_INLINE hmm_vec3 &operator*=(hmm_vec3 &Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_MultiplyVec3Assign); + return (Left = Left * Right); } +COVERAGE(HMM_MultiplyVec4Assign, 1) HMM_INLINE hmm_vec4 &operator*=(hmm_vec4 &Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_MultiplyVec4Assign); + return (Left = Left * Right); } +COVERAGE(HMM_MultiplyVec2fAssign, 1) HMM_INLINE hmm_vec2 &operator*=(hmm_vec2 &Left, float Right) { + ASSERT_COVERED(HMM_MultiplyVec2fAssign); + return (Left = Left * Right); } +COVERAGE(HMM_MultiplyVec3fAssign, 1) HMM_INLINE hmm_vec3 &operator*=(hmm_vec3 &Left, float Right) { + ASSERT_COVERED(HMM_MultiplyVec3fAssign); + return (Left = Left * Right); } +COVERAGE(HMM_MultiplyVec4fAssign, 1) HMM_INLINE hmm_vec4 &operator*=(hmm_vec4 &Left, float Right) { + ASSERT_COVERED(HMM_MultiplyVec4fAssign); + return (Left = Left * Right); } +COVERAGE(HMM_MultiplyMat4fAssign, 1) HMM_INLINE hmm_mat4 &operator*=(hmm_mat4 &Left, float Right) { + ASSERT_COVERED(HMM_MultiplyMat4fAssign); + return (Left = Left * Right); } +COVERAGE(HMM_MultiplyQuaternionFAssign, 1) HMM_INLINE hmm_quaternion &operator*=(hmm_quaternion &Left, float Right) { + ASSERT_COVERED(HMM_MultiplyQuaternionFAssign); + return (Left = Left * Right); } +COVERAGE(HMM_DivideVec2Assign, 1) HMM_INLINE hmm_vec2 &operator/=(hmm_vec2 &Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_DivideVec2Assign); + return (Left = Left / Right); } +COVERAGE(HMM_DivideVec3Assign, 1) HMM_INLINE hmm_vec3 &operator/=(hmm_vec3 &Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_DivideVec3Assign); + return (Left = Left / Right); } +COVERAGE(HMM_DivideVec4Assign, 1) HMM_INLINE hmm_vec4 &operator/=(hmm_vec4 &Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_DivideVec4Assign); + return (Left = Left / Right); } +COVERAGE(HMM_DivideVec2fAssign, 1) HMM_INLINE hmm_vec2 &operator/=(hmm_vec2 &Left, float Right) { + ASSERT_COVERED(HMM_DivideVec2fAssign); + return (Left = Left / Right); } +COVERAGE(HMM_DivideVec3fAssign, 1) HMM_INLINE hmm_vec3 &operator/=(hmm_vec3 &Left, float Right) { + ASSERT_COVERED(HMM_DivideVec3fAssign); + return (Left = Left / Right); } +COVERAGE(HMM_DivideVec4fAssign, 1) HMM_INLINE hmm_vec4 &operator/=(hmm_vec4 &Left, float Right) { + ASSERT_COVERED(HMM_DivideVec4fAssign); + return (Left = Left / Right); } +COVERAGE(HMM_DivideMat4fAssign, 1) HMM_INLINE hmm_mat4 &operator/=(hmm_mat4 &Left, float Right) { + ASSERT_COVERED(HMM_DivideMat4fAssign); + return (Left = Left / Right); } +COVERAGE(HMM_DivideQuaternionFAssign, 1) HMM_INLINE hmm_quaternion &operator/=(hmm_quaternion &Left, float Right) { + ASSERT_COVERED(HMM_DivideQuaternionFAssign); + return (Left = Left / Right); } +COVERAGE(HMM_EqualsVec2Op, 1) HMM_INLINE hmm_bool operator==(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_EqualsVec2Op); + return HMM_EqualsVec2(Left, Right); } +COVERAGE(HMM_EqualsVec3Op, 1) HMM_INLINE hmm_bool operator==(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_EqualsVec3Op); + return HMM_EqualsVec3(Left, Right); } +COVERAGE(HMM_EqualsVec4Op, 1) HMM_INLINE hmm_bool operator==(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_EqualsVec4Op); + return HMM_EqualsVec4(Left, Right); } +COVERAGE(HMM_EqualsVec2OpNot, 1) HMM_INLINE hmm_bool operator!=(hmm_vec2 Left, hmm_vec2 Right) { + ASSERT_COVERED(HMM_EqualsVec2OpNot); + return !HMM_EqualsVec2(Left, Right); } +COVERAGE(HMM_EqualsVec3OpNot, 1) HMM_INLINE hmm_bool operator!=(hmm_vec3 Left, hmm_vec3 Right) { + ASSERT_COVERED(HMM_EqualsVec3OpNot); + return !HMM_EqualsVec3(Left, Right); } +COVERAGE(HMM_EqualsVec4OpNot, 1) HMM_INLINE hmm_bool operator!=(hmm_vec4 Left, hmm_vec4 Right) { + ASSERT_COVERED(HMM_EqualsVec4OpNot); + return !HMM_EqualsVec4(Left, Right); } @@ -2183,8 +2783,11 @@ HMM_INLINE hmm_bool operator!=(hmm_vec4 Left, hmm_vec4 Right) #ifdef HANDMADE_MATH_IMPLEMENTATION +COVERAGE(HMM_Power, 2) float HMM_Power(float Base, int Exponent) { + ASSERT_COVERED(HMM_Power); + float Result = 1.0f; float Mul = Exponent < 0 ? 1.f / Base : Base; int X = Exponent < 0 ? -Exponent : Exponent; @@ -2192,19 +2795,24 @@ float HMM_Power(float Base, int Exponent) { if (X & 1) { + ASSERT_COVERED(HMM_Power); + Result *= Mul; } - + Mul *= Mul; X >>= 1; } - + return (Result); } #ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_Transpose, 1) hmm_mat4 HMM_Transpose(hmm_mat4 Matrix) { + ASSERT_COVERED(HMM_Transpose); + hmm_mat4 Result; int Columns; @@ -2222,8 +2830,11 @@ hmm_mat4 HMM_Transpose(hmm_mat4 Matrix) #endif #ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_AddMat4, 1) hmm_mat4 HMM_AddMat4(hmm_mat4 Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_AddMat4); + hmm_mat4 Result; int Columns; @@ -2241,8 +2852,11 @@ hmm_mat4 HMM_AddMat4(hmm_mat4 Left, hmm_mat4 Right) #endif #ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_SubtractMat4, 1) hmm_mat4 HMM_SubtractMat4(hmm_mat4 Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_SubtractMat4); + hmm_mat4 Result; int Columns; @@ -2259,17 +2873,18 @@ hmm_mat4 HMM_SubtractMat4(hmm_mat4 Left, hmm_mat4 Right) } #endif +COVERAGE(HMM_MultiplyMat4, 1) hmm_mat4 HMM_MultiplyMat4(hmm_mat4 Left, hmm_mat4 Right) { + ASSERT_COVERED(HMM_MultiplyMat4); + hmm_mat4 Result; #ifdef HANDMADE_MATH__USE_SSE - Result.Columns[0] = HMM_LinearCombineSSE(Right.Columns[0], Left); Result.Columns[1] = HMM_LinearCombineSSE(Right.Columns[1], Left); Result.Columns[2] = HMM_LinearCombineSSE(Right.Columns[2], Left); - Result.Columns[3] = HMM_LinearCombineSSE(Right.Columns[3], Left); - + Result.Columns[3] = HMM_LinearCombineSSE(Right.Columns[3], Left); #else int Columns; for(Columns = 0; Columns < 4; ++Columns) @@ -2293,8 +2908,11 @@ hmm_mat4 HMM_MultiplyMat4(hmm_mat4 Left, hmm_mat4 Right) } #ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_MultiplyMat4f, 1) hmm_mat4 HMM_MultiplyMat4f(hmm_mat4 Matrix, float Scalar) { + ASSERT_COVERED(HMM_MultiplyMat4f); + hmm_mat4 Result; int Columns; @@ -2311,10 +2929,13 @@ hmm_mat4 HMM_MultiplyMat4f(hmm_mat4 Matrix, float Scalar) } #endif +COVERAGE(HMM_MultiplyMat4ByVec4, 1) hmm_vec4 HMM_MultiplyMat4ByVec4(hmm_mat4 Matrix, hmm_vec4 Vector) { + ASSERT_COVERED(HMM_MultiplyMat4ByVec4); + hmm_vec4 Result; - + #ifdef HANDMADE_MATH__USE_SSE Result.InternalElementsSSE = HMM_LinearCombineSSE(Vector.InternalElementsSSE, Matrix); #else @@ -2326,7 +2947,7 @@ hmm_vec4 HMM_MultiplyMat4ByVec4(hmm_mat4 Matrix, hmm_vec4 Vector) { Sum += Matrix.Elements[Columns][Rows] * Vector.Elements[Columns]; } - + Result.Elements[Rows] = Sum; } #endif @@ -2335,10 +2956,13 @@ hmm_vec4 HMM_MultiplyMat4ByVec4(hmm_mat4 Matrix, hmm_vec4 Vector) } #ifndef HANDMADE_MATH__USE_SSE +COVERAGE(HMM_DivideMat4f, 1); hmm_mat4 HMM_DivideMat4f(hmm_mat4 Matrix, float Scalar) { + ASSERT_COVERED(HMM_DivideMat4f); + hmm_mat4 Result; - + int Columns; for(Columns = 0; Columns < 4; ++Columns) { @@ -2353,33 +2977,39 @@ hmm_mat4 HMM_DivideMat4f(hmm_mat4 Matrix, float Scalar) } #endif +COVERAGE(HMM_Rotate, 1) hmm_mat4 HMM_Rotate(float Angle, hmm_vec3 Axis) { + ASSERT_COVERED(HMM_Rotate); + hmm_mat4 Result = HMM_Mat4d(1.0f); - + Axis = HMM_NormalizeVec3(Axis); - + float SinTheta = HMM_SinF(HMM_ToRadians(Angle)); float CosTheta = HMM_CosF(HMM_ToRadians(Angle)); float CosValue = 1.0f - CosTheta; - + Result.Elements[0][0] = (Axis.X * Axis.X * CosValue) + CosTheta; Result.Elements[0][1] = (Axis.X * Axis.Y * CosValue) + (Axis.Z * SinTheta); Result.Elements[0][2] = (Axis.X * Axis.Z * CosValue) - (Axis.Y * SinTheta); - + Result.Elements[1][0] = (Axis.Y * Axis.X * CosValue) - (Axis.Z * SinTheta); Result.Elements[1][1] = (Axis.Y * Axis.Y * CosValue) + CosTheta; Result.Elements[1][2] = (Axis.Y * Axis.Z * CosValue) + (Axis.X * SinTheta); - + Result.Elements[2][0] = (Axis.Z * Axis.X * CosValue) + (Axis.Y * SinTheta); Result.Elements[2][1] = (Axis.Z * Axis.Y * CosValue) - (Axis.X * SinTheta); Result.Elements[2][2] = (Axis.Z * Axis.Z * CosValue) + CosTheta; - + return (Result); } +COVERAGE(HMM_LookAt, 1) hmm_mat4 HMM_LookAt(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up) { + ASSERT_COVERED(HMM_LookAt); + hmm_mat4 Result; hmm_vec3 F = HMM_NormalizeVec3(HMM_SubtractVec3(Center, Eye)); @@ -2409,8 +3039,11 @@ hmm_mat4 HMM_LookAt(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up) return (Result); } +COVERAGE(HMM_InverseQuaternion, 1) hmm_quaternion HMM_InverseQuaternion(hmm_quaternion Left) { + ASSERT_COVERED(HMM_InverseQuaternion); + hmm_quaternion Conjugate; hmm_quaternion Result; float Norm = 0; @@ -2429,15 +3062,18 @@ hmm_quaternion HMM_InverseQuaternion(hmm_quaternion Left) return (Result); } +COVERAGE(HMM_Slerp, 1) hmm_quaternion HMM_Slerp(hmm_quaternion Left, float Time, hmm_quaternion Right) { + ASSERT_COVERED(HMM_Slerp); + hmm_quaternion Result; hmm_quaternion QuaternionLeft; hmm_quaternion QuaternionRight; float Cos_Theta = HMM_DotQuaternion(Left, Right); float Angle = HMM_ACosF(Cos_Theta); - + float S1 = HMM_SinF((1.0f - Time) * Angle); float S2 = HMM_SinF(Time * Angle); float Is = 1.0f / HMM_SinF(Angle); @@ -2451,12 +3087,15 @@ hmm_quaternion HMM_Slerp(hmm_quaternion Left, float Time, hmm_quaternion Right) return (Result); } +COVERAGE(HMM_QuaternionToMat4, 1) hmm_mat4 HMM_QuaternionToMat4(hmm_quaternion Left) { + ASSERT_COVERED(HMM_QuaternionToMat4); + hmm_mat4 Result; hmm_quaternion NormalizedQuaternion = HMM_NormalizeQuaternion(Left); - + float XX, YY, ZZ, XY, XZ, YZ, WX, WY, WZ; @@ -2508,6 +3147,7 @@ hmm_mat4 HMM_QuaternionToMat4(hmm_quaternion Left) // // Don't be confused! Or if you must be confused, at least trust this // comment. :) +COVERAGE(HMM_Mat4ToQuaternion, 4) hmm_quaternion HMM_Mat4ToQuaternion(hmm_mat4 M) { float T; @@ -2515,6 +3155,8 @@ hmm_quaternion HMM_Mat4ToQuaternion(hmm_mat4 M) if (M.Elements[2][2] < 0.0f) { if (M.Elements[0][0] > M.Elements[1][1]) { + ASSERT_COVERED(HMM_Mat4ToQuaternion); + T = 1 + M.Elements[0][0] - M.Elements[1][1] - M.Elements[2][2]; Q = HMM_Quaternion( T, @@ -2523,6 +3165,8 @@ hmm_quaternion HMM_Mat4ToQuaternion(hmm_mat4 M) M.Elements[1][2] - M.Elements[2][1] ); } else { + ASSERT_COVERED(HMM_Mat4ToQuaternion); + T = 1 - M.Elements[0][0] + M.Elements[1][1] - M.Elements[2][2]; Q = HMM_Quaternion( M.Elements[0][1] + M.Elements[1][0], @@ -2533,6 +3177,8 @@ hmm_quaternion HMM_Mat4ToQuaternion(hmm_mat4 M) } } else { if (M.Elements[0][0] < -M.Elements[1][1]) { + ASSERT_COVERED(HMM_Mat4ToQuaternion); + T = 1 - M.Elements[0][0] - M.Elements[1][1] + M.Elements[2][2]; Q = HMM_Quaternion( M.Elements[2][0] + M.Elements[0][2], @@ -2541,6 +3187,8 @@ hmm_quaternion HMM_Mat4ToQuaternion(hmm_mat4 M) M.Elements[0][1] - M.Elements[1][0] ); } else { + ASSERT_COVERED(HMM_Mat4ToQuaternion); + T = 1 + M.Elements[0][0] + M.Elements[1][1] + M.Elements[2][2]; Q = HMM_Quaternion( M.Elements[1][2] - M.Elements[2][1], @@ -2556,8 +3204,11 @@ hmm_quaternion HMM_Mat4ToQuaternion(hmm_mat4 M) return Q; } +COVERAGE(HMM_QuaternionFromAxisAngle, 1) hmm_quaternion HMM_QuaternionFromAxisAngle(hmm_vec3 Axis, float AngleOfRotation) { + ASSERT_COVERED(HMM_QuaternionFromAxisAngle); + hmm_quaternion Result; hmm_vec3 AxisNormalized = HMM_NormalizeVec3(Axis); diff --git a/test/HandmadeMath.c b/test/HandmadeMath.c index f771d4f..2bb61ae 100644 --- a/test/HandmadeMath.c +++ b/test/HandmadeMath.c @@ -1,3 +1,7 @@ +#ifndef WITHOUT_COVERAGE +#include "HandmadeTest.h" +#endif + #define HANDMADE_MATH_IMPLEMENTATION #define HANDMADE_MATH_NO_INLINE #include "../HandmadeMath.h" diff --git a/test/HandmadeTest.h b/test/HandmadeTest.h index feab82b..66b556d 100644 --- a/test/HandmadeTest.h +++ b/test/HandmadeTest.h @@ -4,19 +4,46 @@ This is Handmade Math's test framework. It is fully compatible with both C and C++, although it requires some compiler-specific features. + To use Handmade Test, you must #define HANDMADE_TEST_IMPLEMENTATION in + exactly one C or C++ file that includes the header, like this: + + #define HANDMADE_TEST_IMPLEMENTATION + #include "HandmadeTest.h" + The basic way of creating a test is using the TEST macro, which registers a single test to be run: - TEST(MyCategory, MyTestName) { + TEST(MyCategory, MyTestName) { // test code, including asserts/expects - } + } - The main function of your test code should then call hmt_run_all_tests and - return the result: + Handmade Test also provides macros you can use to check the coverage of + important parts of your code. Define a coverage case by using the COVERAGE + macro outside the function you wish to test, providing both a name and the + number of asserts you expect to see covered over the course of your test. + Then use the ASSERT_COVERED macro in every part of the function you wish to + check coverage on. For example: - int main() { - return hmt_run_all_tests(); - } + COVERAGE(MyCoverageCase, 3) + void MyFunction(int a, int b) { + if (a > b) { + ASSERT_COVERED(MyCoverageCase); + return 10; + } else if (a < b) { + ASSERT_COVERED(MyCoverageCase); + return -10; + } + + ASSERT_COVERED(MyCoverageCase); + return 0; + } + + The main function of your test code should then call hmt_run_all_tests (and + optionally hmt_check_all_coverage) and return the result: + + int main() { + return hmt_run_all_tests() || hmt_check_all_coverage(); + } ============================================================================= @@ -40,7 +67,7 @@ #define HMT_RED "\033[31m" #define HMT_GREEN "\033[32m" -#define HMT_INITIAL_ARRAY_SIZE 1024 +#define HMT_ARRAY_SIZE 1024 typedef struct hmt_testresult_struct { int count_cases; @@ -57,20 +84,137 @@ typedef struct hmt_test_struct { typedef struct hmt_category_struct { const char* name; int num_tests; - int tests_capacity; hmt_test* tests; } hmt_category; -int hmt_num_categories = 0; -int hmt_category_capacity = HMT_INITIAL_ARRAY_SIZE; -hmt_category* categories = 0; +typedef struct hmt_covercase_struct { + const char* name; + int expected_asserts; + int actual_asserts; + int* asserted_lines; +} hmt_covercase; + +hmt_category _hmt_new_category(const char* name); +hmt_test _hmt_new_test(const char* name, hmt_test_func func); +hmt_covercase _hmt_new_covercase(const char* name, int expected); +void _hmt_register_test(const char* category, const char* name, hmt_test_func func); +void _hmt_register_covercase(const char* name, const char* expected_asserts); +void _hmt_count_cover(const char* name, int line); + +#define _HMT_TEST_FUNCNAME(category, name) _hmt_test_ ## category ## _ ## name +#define _HMT_TEST_FUNCNAME_INIT(category, name) _hmt_test_ ## category ## _ ## name ## _init +#define _HMT_COVERCASE_FUNCNAME_INIT(name) _hmt_covercase_ ## name ## _init + +#define HMT_TEST(category, name) \ +void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result); \ +INITIALIZER(_HMT_TEST_FUNCNAME_INIT(category, name)) { \ + _hmt_register_test(#category, #name, _HMT_TEST_FUNCNAME(category, name)); \ +} \ +void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result) + +#define _HMT_CASE_START() \ + _result->count_cases++; + +#define _HMT_CASE_FAIL() \ + _result->count_failures++; \ + printf("\n - " HMT_RED "[FAIL] (line %d) " HMT_RESET, __LINE__); + +#define HMT_COVERAGE(name, num_asserts) \ +INITIALIZER(_HMT_COVERCASE_FUNCNAME_INIT(name)) { \ + _hmt_register_covercase(#name, #num_asserts); \ +} \ + +#define HMT_ASSERT_COVERED(name) \ +{ \ + _hmt_count_cover(#name, __LINE__); \ +} \ + +/* + * Asserts and expects + */ +#define HMT_EXPECT_TRUE(_actual) { \ + _HMT_CASE_START(); \ + if (!(_actual)) { \ + _HMT_CASE_FAIL(); \ + printf("Expected true but got something false"); \ + } \ +} \ + +#define HMT_EXPECT_FALSE(_actual) { \ + _HMT_CASE_START(); \ + if (_actual) { \ + _HMT_CASE_FAIL(); \ + printf("Expected false but got something true"); \ + } \ +} \ + +#define HMT_EXPECT_FLOAT_EQ(_actual, _expected) { \ + _HMT_CASE_START(); \ + float actual = (_actual); \ + float diff = actual - (_expected); \ + if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \ + _HMT_CASE_FAIL(); \ + printf("Expected %f, got %f", (_expected), actual); \ + } \ +} \ + +#define HMT_EXPECT_NEAR(_actual, _expected, _epsilon) { \ + _HMT_CASE_START(); \ + float actual = (_actual); \ + float diff = actual - (_expected); \ + if (diff < -(_epsilon) || (_epsilon) < diff) { \ + _HMT_CASE_FAIL(); \ + printf("Expected %f, got %f", (_expected), actual); \ + } \ +} \ + +#define HMT_EXPECT_LT(_actual, _expected) { \ + _HMT_CASE_START(); \ + if ((_actual) >= (_expected)) { \ + _HMT_CASE_FAIL(); \ + printf("Expected %f to be less than %f", (_actual), (_expected)); \ + } \ +} \ + +#define HMT_EXPECT_GT(_actual, _expected) { \ + _HMT_CASE_START(); \ + if ((_actual) <= (_expected)) { \ + _HMT_CASE_FAIL(); \ + printf("Expected %f to be greater than %f", (_actual), (_expected)); \ + } \ +} \ + +#ifndef HMT_SAFE_MACROS +// Friendly defines +#define TEST(category, name) HMT_TEST(category, name) +#define COVERAGE(name, expected_asserts) HMT_COVERAGE(name, expected_asserts) +#define ASSERT_COVERED(name) HMT_ASSERT_COVERED(name) +#define EXPECT_TRUE(_actual) HMT_EXPECT_TRUE(_actual) +#define EXPECT_FALSE(_actual) HMT_EXPECT_FALSE(_actual) +#define EXPECT_FLOAT_EQ(_actual, _expected) HMT_EXPECT_FLOAT_EQ(_actual, _expected) +#define EXPECT_NEAR(_actual, _expected, _epsilon) HMT_EXPECT_NEAR(_actual, _expected, _epsilon) +#define EXPECT_LT(_actual, _expected) HMT_EXPECT_LT(_actual, _expected) +#define EXPECT_GT(_actual, _expected) HMT_EXPECT_GT(_actual, _expected) +#endif // HMT_SAFE_MACROS + +#endif // HANDMADETEST_H + +#ifdef HANDMADE_TEST_IMPLEMENTATION + +#ifndef HANDMADE_TEST_IMPLEMENTATION_GUARD +#define HANDMADE_TEST_IMPLEMENTATION_GUARD + +int _hmt_num_categories = 0; +hmt_category* _hmt_categories = 0; + +int _hmt_num_covercases = 0; +hmt_covercase* _hmt_covercases = 0; hmt_category _hmt_new_category(const char* name) { hmt_category cat = { .name = name, .num_tests = 0, - .tests_capacity = HMT_INITIAL_ARRAY_SIZE, - .tests = (hmt_test*) malloc(HMT_INITIAL_ARRAY_SIZE * sizeof(hmt_test)) + .tests = (hmt_test*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_test)) }; return cat; @@ -85,53 +229,98 @@ hmt_test _hmt_new_test(const char* name, hmt_test_func func) { return test; } -int hmt_register_test(const char* category, const char* name, hmt_test_func func) { +hmt_covercase _hmt_new_covercase(const char* name, int expected) { + hmt_covercase covercase = { + .name = name, + .expected_asserts = expected, + .actual_asserts = 0, + .asserted_lines = (int*) malloc(HMT_ARRAY_SIZE * sizeof(int)), + }; + + return covercase; +} + +void _hmt_register_test(const char* category, const char* name, hmt_test_func func) { // initialize categories array if not initialized - if (!categories) { - categories = (hmt_category*) malloc(hmt_category_capacity * sizeof(hmt_category)); + if (!_hmt_categories) { + _hmt_categories = (hmt_category*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_category)); } // Find the matching category, if possible int cat_index; - for (cat_index = 0; cat_index < hmt_num_categories; cat_index++) { - if (strcmp(categories[cat_index].name, category) == 0) { + for (cat_index = 0; cat_index < _hmt_num_categories; cat_index++) { + if (strcmp(_hmt_categories[cat_index].name, category) == 0) { break; } } - // Expand the array of categories if necessary - if (cat_index >= hmt_category_capacity) { - // TODO: If/when we ever split HandmadeTest off into its own package, - // we should start with a smaller initial capacity and dynamically expand. - } - // Add a new category if necessary - if (cat_index >= hmt_num_categories) { - categories[cat_index] = _hmt_new_category(category); - hmt_num_categories++; + if (cat_index >= _hmt_num_categories) { + _hmt_categories[cat_index] = _hmt_new_category(category); + _hmt_num_categories++; } - hmt_category* cat = &categories[cat_index]; + hmt_category* cat = &_hmt_categories[cat_index]; // Add the test to the category - if (cat->num_tests >= cat->tests_capacity) { - // TODO: If/when we ever split HandmadeTest off into its own package, - // we should start with a smaller initial capacity and dynamically expand. - } cat->tests[cat->num_tests] = _hmt_new_test(name, func); cat->num_tests++; +} + +void _hmt_register_covercase(const char* name, const char* expected_asserts) { + // initialize cases array if not initialized + if (!_hmt_covercases) { + _hmt_covercases = (hmt_covercase*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_covercase)); + } + + // check for existing case with that name, because the macro can run multiple + // times in different translation units + for (int i = 0; i < _hmt_num_covercases; i++) { + if (strcmp(_hmt_covercases[i].name, name) == 0) { + return; + } + } + + _hmt_covercases[_hmt_num_covercases] = _hmt_new_covercase(name, atoi(expected_asserts)); + _hmt_num_covercases++; +} + +hmt_covercase* _hmt_find_covercase(const char* name) { + for (int i = 0; i < _hmt_num_covercases; i++) { + if (strcmp(_hmt_covercases[i].name, name) == 0) { + return &_hmt_covercases[i]; + } + } return 0; } +void _hmt_count_cover(const char* name, int line) { + hmt_covercase* covercase = _hmt_find_covercase(name); + if (covercase == 0) { + printf(HMT_RED "ERROR (line %d): Could not find coverage case with name \"%s\".\n" HMT_RESET, line, name); + return; + } + + // see if this line has already been covered + for (int i = 0; i < covercase->actual_asserts; i++) { + if (covercase->asserted_lines[i] == line) { + return; + } + } + + covercase->asserted_lines[covercase->actual_asserts] = line; + covercase->actual_asserts++; +} + int hmt_run_all_tests() { int count_alltests = 0; int count_allfailedtests = 0; // failed test cases int count_allfailures = 0; // failed asserts - for (int i = 0; i < hmt_num_categories; i++) { - hmt_category cat = categories[i]; - int count_catfailedtests = 0; + for (int i = 0; i < _hmt_num_categories; i++) { + hmt_category cat = _hmt_categories[i]; + int count_catfailedtests = 0; int count_catfailures = 0; printf("\n%s:\n", cat.name); @@ -177,87 +366,33 @@ int hmt_run_all_tests() { return (count_allfailedtests > 0); } -#define _HMT_TEST_FUNCNAME(category, name) category ## _ ## name -#define _HMT_TEST_FUNCNAME_INIT(category, name) category ## _ ## name ## _init +int hmt_check_all_coverage() { + printf("Coverage:\n"); -#define HMT_TEST(category, name) \ -void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result); \ -INITIALIZER(_HMT_TEST_FUNCNAME_INIT(category, name)) { \ - hmt_register_test(#category, #name, _HMT_TEST_FUNCNAME(category, name)); \ -} \ -void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result) + int count_failures = 0; -#define _HMT_CASE_START() \ - _result->count_cases++; + for (int i = 0; i < _hmt_num_covercases; i++) { + hmt_covercase covercase = _hmt_covercases[i]; -#define _HMT_CASE_FAIL() \ - _result->count_failures++; \ - printf("\n - " HMT_RED "[FAIL] (%d) " HMT_RESET, __LINE__); + if (covercase.expected_asserts != covercase.actual_asserts) { + count_failures++; + printf("%s: " HMT_RED "FAIL (expected %d asserts, got %d)\n" HMT_RESET, covercase.name, covercase.expected_asserts, covercase.actual_asserts); + } + } -/* - * Asserts and expects - */ -#define HMT_EXPECT_TRUE(_actual) do { \ - _HMT_CASE_START(); \ - if (!(_actual)) { \ - _HMT_CASE_FAIL(); \ - printf("Expected true but got something false"); \ - } \ -} while (0) + if (count_failures > 0) { + printf("\n"); + printf(HMT_RED); + } else { + printf(HMT_GREEN); + } + printf("%d coverage cases tested, %d failures\n", _hmt_num_covercases, count_failures); + printf(HMT_RESET); -#define HMT_EXPECT_FALSE(_actual) do { \ - _HMT_CASE_START(); \ - if (_actual) { \ - _HMT_CASE_FAIL(); \ - printf("Expected false but got something true"); \ - } \ -} while (0) + printf("\n"); -#define HMT_EXPECT_FLOAT_EQ(_actual, _expected) do { \ - _HMT_CASE_START(); \ - float actual = (_actual); \ - float diff = actual - (_expected); \ - if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \ - _HMT_CASE_FAIL(); \ - printf("Expected %f, got %f", (_expected), actual); \ - } \ -} while (0) + return (count_failures > 0); +} -#define HMT_EXPECT_NEAR(_actual, _expected, _epsilon) do { \ - _HMT_CASE_START(); \ - float actual = (_actual); \ - float diff = actual - (_expected); \ - if (diff < -(_epsilon) || (_epsilon) < diff) { \ - _HMT_CASE_FAIL(); \ - printf("Expected %f, got %f", (_expected), actual); \ - } \ -} while (0) - -#define HMT_EXPECT_LT(_actual, _expected) do { \ - _HMT_CASE_START(); \ - if ((_actual) >= (_expected)) { \ - _HMT_CASE_FAIL(); \ - printf("Expected %f to be less than %f", (_actual), (_expected)); \ - } \ -} while (0) - -#define HMT_EXPECT_GT(_actual, _expected) do { \ - _HMT_CASE_START(); \ - if ((_actual) <= (_expected)) { \ - _HMT_CASE_FAIL(); \ - printf("Expected %f to be greater than %f", (_actual), (_expected)); \ - } \ -} while (0) - -#ifndef HMT_SAFE_MACROS -// Friendly defines -#define TEST(category, name) HMT_TEST(category, name) -#define EXPECT_TRUE(_actual) HMT_EXPECT_TRUE(_actual) -#define EXPECT_FALSE(_actual) HMT_EXPECT_FALSE(_actual) -#define EXPECT_FLOAT_EQ(_actual, _expected) HMT_EXPECT_FLOAT_EQ(_actual, _expected) -#define EXPECT_NEAR(_actual, _expected, _epsilon) HMT_EXPECT_NEAR(_actual, _expected, _epsilon) -#define EXPECT_LT(_actual, _expected) HMT_EXPECT_LT(_actual, _expected) -#define EXPECT_GT(_actual, _expected) HMT_EXPECT_GT(_actual, _expected) -#endif // HMT_SAFE_MACROS - -#endif // HANDMADETEST_H +#endif // HANDMADE_TEST_IMPLEMENTATION_GUARD +#endif // HANDMADE_TEST_IMPLEMENTATION diff --git a/test/Makefile b/test/Makefile index efd324b..935a354 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,18 +2,17 @@ BUILD_DIR=./build CXXFLAGS+=-g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers -all: build_all - $(BUILD_DIR)/hmm_test_c - $(BUILD_DIR)/hmm_test_c_no_sse - $(BUILD_DIR)/hmm_test_cpp - $(BUILD_DIR)/hmm_test_cpp_no_sse +all: c c_no_sse cpp cpp_no_sse build_c_without_coverage build_cpp_without_coverage -build_all: c c_no_sse cpp cpp_no_sse +build_all: build_c build_c_no_sse build_cpp build_cpp_no_sse clean: rm -rf $(BUILD_DIR) -c: HandmadeMath.c test_impl +c: build_c + $(BUILD_DIR)/hmm_test_c + +build_c: HandmadeMath.c test_impl @echo "\nCompiling in C mode" mkdir -p $(BUILD_DIR) cd $(BUILD_DIR)\ @@ -22,7 +21,10 @@ c: HandmadeMath.c test_impl -lm \ && $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm -c_no_sse: HandmadeMath.c test_impl +c_no_sse: build_c_no_sse + $(BUILD_DIR)/hmm_test_c_no_sse + +build_c_no_sse: HandmadeMath.c test_impl @echo "\nCompiling in C mode (no SSE)" mkdir -p $(BUILD_DIR) cd $(BUILD_DIR) \ @@ -32,7 +34,10 @@ c_no_sse: HandmadeMath.c test_impl -lm \ && $(CC) -ohmm_test_c_no_sse HandmadeMath.o hmm_test.o -lm -cpp: HandmadeMath.cpp test_impl +cpp: build_cpp + $(BUILD_DIR)/hmm_test_cpp + +build_cpp: HandmadeMath.cpp test_impl @echo "\nCompiling in C++ mode" mkdir -p $(BUILD_DIR) cd $(BUILD_DIR) \ @@ -40,7 +45,10 @@ cpp: HandmadeMath.cpp test_impl -DHANDMADE_MATH_CPP_MODE \ ../HandmadeMath.cpp ../hmm_test.cpp -cpp_no_sse: HandmadeMath.cpp test_impl +cpp_no_sse: build_cpp_no_sse + $(BUILD_DIR)/hmm_test_cpp_no_sse + +build_cpp_no_sse: HandmadeMath.cpp test_impl @echo "\nCompiling in C++ mode (no SSE)" mkdir -p $(BUILD_DIR) cd $(BUILD_DIR) \ @@ -49,3 +57,21 @@ cpp_no_sse: HandmadeMath.cpp test_impl ../HandmadeMath.cpp ../hmm_test.cpp test_impl: hmm_test.cpp hmm_test.c + +build_c_without_coverage: HandmadeMath.c + @echo "\nCompiling in C mode" + mkdir -p $(BUILD_DIR) + cd $(BUILD_DIR)\ + && $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \ + -DWITHOUT_COVERAGE \ + -c ../HandmadeMath.c ../hmm_test.c \ + -lm \ + && $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm + +build_cpp_without_coverage: HandmadeMath.cpp test_impl + @echo "\nCompiling in C++ mode (no SSE)" + mkdir -p $(BUILD_DIR) + cd $(BUILD_DIR) \ + && $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_no_sse \ + -DHANDMADE_MATH_CPP_MODE -DWITHOUT_COVERAGE \ + ../HandmadeMath.cpp ../hmm_test.cpp diff --git a/test/README.md b/test/README.md index efed87e..b52d0a6 100644 --- a/test/README.md +++ b/test/README.md @@ -4,8 +4,13 @@ You can compile and run the tests yourself by running: ``` make -build/hmm_test_c -build/hmm_test_c_no_sse -build/hmm_test_cpp -build/hmm_test_cpp_no_sse +``` + +To run a specific test configuration, run one of: + +``` +make c +make c_no_sse +make cpp +make cpp_no_sse ``` diff --git a/test/categories/Addition.h b/test/categories/Addition.h index c18463e..eb02fed 100644 --- a/test/categories/Addition.h +++ b/test/categories/Addition.h @@ -37,7 +37,7 @@ TEST(Addition, Vec3) hmm_vec3 result = HMM_AddVec3(v3_1, v3_2); EXPECT_FLOAT_EQ(result.X, 5.0f); EXPECT_FLOAT_EQ(result.Y, 7.0f); - EXPECT_FLOAT_EQ(result.Z, 9.0f); + EXPECT_FLOAT_EQ(result.Z, 9.0f); } #ifdef __cplusplus { @@ -64,7 +64,7 @@ TEST(Addition, Vec4) { hmm_vec4 v4_1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f); hmm_vec4 v4_2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f); - + { hmm_vec4 result = HMM_AddVec4(v4_1, v4_2); EXPECT_FLOAT_EQ(result.X, 6.0f); diff --git a/test/categories/Equality.h b/test/categories/Equality.h index b73ffcb..367bc6f 100644 --- a/test/categories/Equality.h +++ b/test/categories/Equality.h @@ -15,6 +15,9 @@ TEST(Equality, Vec2) EXPECT_TRUE(a == b); EXPECT_FALSE(a == c); + + EXPECT_FALSE(a != b); + EXPECT_TRUE(a != c); #endif } @@ -33,6 +36,9 @@ TEST(Equality, Vec3) EXPECT_TRUE(a == b); EXPECT_FALSE(a == c); + + EXPECT_FALSE(a != b); + EXPECT_TRUE(a != c); #endif } @@ -51,5 +57,8 @@ TEST(Equality, Vec4) EXPECT_TRUE(a == b); EXPECT_FALSE(a == c); + + EXPECT_FALSE(a != b); + EXPECT_TRUE(a != c); #endif } diff --git a/test/categories/Initialization.h b/test/categories/Initialization.h index 99d390d..d6709eb 100644 --- a/test/categories/Initialization.h +++ b/test/categories/Initialization.h @@ -4,9 +4,9 @@ TEST(Initialization, Vectors) { // // Test vec2 - // + // hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f); - hmm_vec2 v2i = HMM_Vec2(1, 2); + hmm_vec2 v2i = HMM_Vec2i(1, 2); EXPECT_FLOAT_EQ(v2.X, 1.0f); EXPECT_FLOAT_EQ(v2.Y, 2.0f); diff --git a/test/categories/QuaternionOps.h b/test/categories/QuaternionOps.h index 06b5a3e..a373106 100644 --- a/test/categories/QuaternionOps.h +++ b/test/categories/QuaternionOps.h @@ -151,16 +151,16 @@ TEST(QuaternionOps, Mat4ToQuat) EXPECT_NEAR(result.W, cosf, abs_error); } - // Rotate 135 degrees on the Y axis (this hits case 4) + // Rotate 45 degrees on the X axis (this hits case 4) { - hmm_mat4 m = HMM_Rotate(135, HMM_Vec3(0, 1, 0)); + hmm_mat4 m = HMM_Rotate(45, HMM_Vec3(1, 0, 0)); hmm_quaternion result = HMM_Mat4ToQuaternion(m); - float cosf = 0.3826834324f; // cos(135/2 degrees) - float sinf = 0.9238795325f; // sin(135/2 degrees) + float cosf = 0.9238795325f; // cos(90/2 degrees) + float sinf = 0.3826834324f; // sin(90/2 degrees) - EXPECT_NEAR(result.X, 0.0f, abs_error); - EXPECT_NEAR(result.Y, sinf, abs_error); + EXPECT_NEAR(result.X, sinf, abs_error); + EXPECT_NEAR(result.Y, 0.0f, abs_error); EXPECT_NEAR(result.Z, 0.0f, abs_error); EXPECT_NEAR(result.W, cosf, abs_error); } @@ -176,4 +176,4 @@ TEST(QuaternionOps, FromAxisAngle) EXPECT_FLOAT_EQ(result.Y, 0.0f); EXPECT_FLOAT_EQ(result.Z, 0.0f); EXPECT_NEAR(result.W, 0.707107f, FLT_EPSILON * 2); -} \ No newline at end of file +} diff --git a/test/categories/SSE.h b/test/categories/SSE.h index fc966e0..7d7ac2e 100644 --- a/test/categories/SSE.h +++ b/test/categories/SSE.h @@ -7,33 +7,33 @@ TEST(SSE, LinearCombine) hmm_mat4 MatrixOne = HMM_Mat4d(2.0f); hmm_mat4 MatrixTwo = HMM_Mat4d(4.0f); hmm_mat4 Result; - + Result.Columns[0] = HMM_LinearCombineSSE(MatrixOne.Columns[0], MatrixTwo); Result.Columns[1] = HMM_LinearCombineSSE(MatrixOne.Columns[1], MatrixTwo); Result.Columns[2] = HMM_LinearCombineSSE(MatrixOne.Columns[2], MatrixTwo); Result.Columns[3] = HMM_LinearCombineSSE(MatrixOne.Columns[3], MatrixTwo); - + { EXPECT_FLOAT_EQ(Result.Elements[0][0], 8.0f); EXPECT_FLOAT_EQ(Result.Elements[0][1], 0.0f); EXPECT_FLOAT_EQ(Result.Elements[0][2], 0.0f); EXPECT_FLOAT_EQ(Result.Elements[0][3], 0.0f); - + EXPECT_FLOAT_EQ(Result.Elements[1][0], 0.0f); - EXPECT_FLOAT_EQ(Result.Elements[1][1], 8.0f); + EXPECT_FLOAT_EQ(Result.Elements[1][1], 8.0f); EXPECT_FLOAT_EQ(Result.Elements[1][2], 0.0f); EXPECT_FLOAT_EQ(Result.Elements[1][3], 0.0f); - + EXPECT_FLOAT_EQ(Result.Elements[2][0], 0.0f); - EXPECT_FLOAT_EQ(Result.Elements[2][1], 0.0f); + EXPECT_FLOAT_EQ(Result.Elements[2][1], 0.0f); EXPECT_FLOAT_EQ(Result.Elements[2][2], 8.0f); EXPECT_FLOAT_EQ(Result.Elements[2][3], 0.0f); EXPECT_FLOAT_EQ(Result.Elements[3][0], 0.0f); - EXPECT_FLOAT_EQ(Result.Elements[3][1], 0.0f); + EXPECT_FLOAT_EQ(Result.Elements[3][1], 0.0f); EXPECT_FLOAT_EQ(Result.Elements[3][2], 0.0f); - EXPECT_FLOAT_EQ(Result.Elements[3][3], 8.0f); - } + EXPECT_FLOAT_EQ(Result.Elements[3][3], 8.0f); + } } #endif diff --git a/test/categories/ScalarMath.h b/test/categories/ScalarMath.h index 38fa7a2..d5350fe 100644 --- a/test/categories/ScalarMath.h +++ b/test/categories/ScalarMath.h @@ -24,6 +24,14 @@ TEST(ScalarMath, Trigonometry) EXPECT_NEAR(HMM_TanF(HMM_PI32), 0.0f, trigAbsError); EXPECT_NEAR(HMM_TanF(-HMM_PI32 / 4), -1.0f, trigAbsError); + EXPECT_NEAR(HMM_ATanF(0.0f), 0.0f, trigAbsError); + EXPECT_NEAR(HMM_ATanF(HMM_PI32), 1.2626272557f, trigAbsError); + EXPECT_NEAR(HMM_ATanF(-HMM_PI32), -1.2626272557f, trigAbsError); + + EXPECT_NEAR(HMM_ATan2F(0.0f, 1.0f), 0.0f, trigAbsError); + EXPECT_NEAR(HMM_ATan2F(1.0f, 1.0f), HMM_PI32 / 4.0f, trigAbsError); + EXPECT_NEAR(HMM_ATan2F(1.0f, 0.0f), HMM_PI32 / 2.0f, trigAbsError); + // This isn't the most rigorous because we're really just sanity- // checking that things work by default. } @@ -35,6 +43,18 @@ TEST(ScalarMath, ToRadians) EXPECT_FLOAT_EQ(HMM_ToRadians(-180.0f), -HMM_PI32); } +TEST(ScalarMath, ExpF) +{ + EXPECT_NEAR(HMM_ExpF(0.0f), 1.0f, 0.0001f); + EXPECT_NEAR(HMM_ExpF(1.0f), 2.7182818285f, 0.0001f); +} + +TEST(ScalarMath, LogF) +{ + EXPECT_NEAR(HMM_LogF(1.0f), 0.0f, 0.0001f); + EXPECT_NEAR(HMM_LogF(2.7182818285f), 1.0f, 0.0001f); +} + TEST(ScalarMath, SquareRoot) { EXPECT_FLOAT_EQ(HMM_SquareRootF(16.0f), 4.0f); @@ -48,7 +68,7 @@ TEST(ScalarMath, RSquareRootF) TEST(ScalarMath, Power) { EXPECT_FLOAT_EQ(HMM_Power(2.0f, 0), 1.0f); - EXPECT_FLOAT_EQ(HMM_Power(2.0f, 4), 16.0f); + EXPECT_FLOAT_EQ(HMM_Power(2.0f, 4), 16.0f); EXPECT_FLOAT_EQ(HMM_Power(2.0f, -2), 0.25f); } @@ -61,14 +81,14 @@ TEST(ScalarMath, PowerF) TEST(ScalarMath, Lerp) { - EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.0f, 2.0f), -2.0f); - EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.5f, 2.0f), 0.0f); + EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.0f, 2.0f), -2.0f); + EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.5f, 2.0f), 0.0f); EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 1.0f, 2.0f), 2.0f); } TEST(ScalarMath, Clamp) { - EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, 0.0f, 2.0f), 0.0f); - EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, -3.0f, 2.0f), -2.0f); + EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, 0.0f, 2.0f), 0.0f); + EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, -3.0f, 2.0f), -2.0f); EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, 3.0f, 2.0f), 2.0f); } diff --git a/test/categories/VectorOps.h b/test/categories/VectorOps.h index 27262b1..92ea060 100644 --- a/test/categories/VectorOps.h +++ b/test/categories/VectorOps.h @@ -3,7 +3,7 @@ TEST(VectorOps, LengthSquared) { hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f); - hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f); + hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f); hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, 1.0f); EXPECT_FLOAT_EQ(HMM_LengthSquaredVec2(v2), 5.0f); @@ -37,7 +37,7 @@ TEST(VectorOps, Length) TEST(VectorOps, Normalize) { hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f); - hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f); + hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f); hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, -1.0f); { diff --git a/test/hmm_test.c b/test/hmm_test.c index 85695de..2ec2e5a 100644 --- a/test/hmm_test.c +++ b/test/hmm_test.c @@ -1,7 +1,9 @@ -#include "HandmadeTest.h" #include "hmm_test.h" int main() { - return hmt_run_all_tests(); + int tests_failed = hmt_run_all_tests(); + int coverage_failed = hmt_check_all_coverage(); + + return tests_failed || coverage_failed; } diff --git a/test/hmm_test.h b/test/hmm_test.h index 5774c09..60fbfd0 100644 --- a/test/hmm_test.h +++ b/test/hmm_test.h @@ -1,6 +1,8 @@ #include +#define HANDMADE_TEST_IMPLEMENTATION #include "HandmadeTest.h" + #include "../HandmadeMath.h" #include "categories/ScalarMath.h"