Matrix Multiply SSE (#65)

* SSEd HMM_MultiplyMat4 and HMM_Transpose. And added HMM_LinearCombineSSE

* Maybe Travis doesn't support SSE?

* Fix compile process so the SSE option is consistently defined

* Fix link error

* Documentation

* Added function prototype for operator ==

* Added != operator for hmm_vec2, hmm_vec3, hmm_vec4

* Add C versions of equality checks

Also made the C++ tests actually run...😳

* Update documentation
This commit is contained in:
Ben Visness
2017-07-16 23:19:34 -05:00
committed by Zak Strange
parent c8ada18370
commit efd9f2f4b7
9 changed files with 345 additions and 46 deletions

View File

@@ -1,10 +1,10 @@
/* /*
HandmadeMath.h v1.1.5 HandmadeMath.h v1.1.6
This is a single header file with a bunch of useful functions for This is a single header file with a bunch of useful functions for
basic game math operations. basic game math operations.
========================================================================== =============================================================================
You MUST You MUST
@@ -18,7 +18,7 @@
All other files should just #include "HandmadeMath.h" without the #define. All other files should just #include "HandmadeMath.h" without the #define.
========================================================================== =============================================================================
For overloaded and operator overloaded versions of the base C functions, For overloaded and operator overloaded versions of the base C functions,
you MUST you MUST
@@ -34,7 +34,7 @@
All other files should just #include "HandmadeMath.h" without the #define. All other files should just #include "HandmadeMath.h" without the #define.
========================================================================== =============================================================================
To disable SSE intrinsics, you MUST To disable SSE intrinsics, you MUST
@@ -54,7 +54,7 @@
#define HANDMADE_MATH_NO_SSE #define HANDMADE_MATH_NO_SSE
#include "HandmadeMath.h" #include "HandmadeMath.h"
========================================================================== =============================================================================
To disable inlining functions, you MUST To disable inlining functions, you MUST
@@ -70,7 +70,7 @@
All other files should just #include "HandmadeMath.h" without the #define. All other files should just #include "HandmadeMath.h" without the #define.
========================================================================== =============================================================================
To use HandmadeMath without the CRT, you MUST To use HandmadeMath without the CRT, you MUST
@@ -84,9 +84,9 @@
#define HMM_ATANF MyATanF #define HMM_ATANF MyATanF
#define HMM_ATAN2F MYATan2F #define HMM_ATAN2F MYATan2F
Provide your own implementations of SinF, CosF, TanF, ACosF, ATanF, ATan2F, ExpF and LogF Provide your own implementations of SinF, CosF, TanF, ACosF, ATanF, ATan2F,
in EXACTLY one C or C++ file that includes this header, BEFORE the ExpF, and LogF in EXACTLY one C or C++ file that includes this header,
include, like this: BEFORE the include, like this:
#define HMM_SINF MySinF #define HMM_SINF MySinF
#define HMM_COSF MyCosF #define HMM_COSF MyCosF
@@ -104,7 +104,7 @@
If you do not define all five of these, HandmadeMath.h will use the If you do not define all five of these, HandmadeMath.h will use the
versions of these functions that are provided by the CRT. versions of these functions that are provided by the CRT.
========================================================================== =============================================================================
Version History: Version History:
0.2 (*) Updated documentation 0.2 (*) Updated documentation
@@ -144,9 +144,15 @@
(*) REMOVED Inner function (user should use Dot now) (*) REMOVED Inner function (user should use Dot now)
(*) REMOVED HMM_FastInverseSquareRoot function declaration (*) REMOVED HMM_FastInverseSquareRoot function declaration
0.7 0.7
(*) REMOVED HMM_LengthSquared in HANDMADE_MATH_IMPLEMENTATION (should use HMM_LengthSquaredVec3, or HANDMADE_MATH_CPP_MODE for function overloaded version) (*) REMOVED HMM_LengthSquared in HANDMADE_MATH_IMPLEMENTATION (should
(*) REMOVED HMM_Length in HANDMADE_MATH_IMPLEMENTATION (should use HMM_LengthVec3, HANDMADE_MATH_CPP_MODE for function overloaded version) use HMM_LengthSquaredVec3, or HANDMADE_MATH_CPP_MODE for function
(*) REMOVED HMM_Normalize in HANDMADE_MATH_IMPLEMENTATION (should use HMM_NormalizeVec3, or HANDMADE_MATH_CPP_MODE for function overloaded version) overloaded version)
(*) REMOVED HMM_Length in HANDMADE_MATH_IMPLEMENTATION (should use
HMM_LengthVec3, HANDMADE_MATH_CPP_MODE for function
overloaded version)
(*) REMOVED HMM_Normalize in HANDMADE_MATH_IMPLEMENTATION (should use
HMM_NormalizeVec3, or HANDMADE_MATH_CPP_MODE for function
overloaded version)
(*) Added HMM_LengthSquaredVec2 (*) Added HMM_LengthSquaredVec2
(*) Added HMM_LengthSquaredVec4 (*) Added HMM_LengthSquaredVec4
(*) Addd HMM_LengthVec2 (*) Addd HMM_LengthVec2
@@ -183,6 +189,13 @@
1.1.5 1.1.5
(*) Add Width and Height to HMM_Vec2 (*) Add Width and Height to HMM_Vec2
(*) Made it so you can supply your own SqrtF (*) Made it so you can supply your own SqrtF
1.2.0
(*) Added equality functions for HMM_Vec2, HMM_Vec3, and HMM_Vec4.
(*) Added HMM_EqualsVec2, HMM_EqualsVec3, and HMM_EqualsVec4
(*) Added C++ overloaded HMM_Equals for all three
(*) Added C++ == and != operators for all three
(*) SSE'd HMM_MultiplyMat4 (this is _WAY_ faster)
(*) SSE'd HMM_Transpose
LICENSE LICENSE
@@ -228,6 +241,7 @@
#endif /* #ifndef HANDMADE_MATH_NO_SSE */ #endif /* #ifndef HANDMADE_MATH_NO_SSE */
#include <stdint.h> // This is for types
#ifdef HANDMADE_MATH__USE_SSE #ifdef HANDMADE_MATH__USE_SSE
#include <xmmintrin.h> #include <xmmintrin.h>
@@ -440,6 +454,11 @@ typedef union hmm_vec4
typedef union hmm_mat4 typedef union hmm_mat4
{ {
float Elements[4][4]; float Elements[4][4];
#ifdef HANDMADE_MATH__USE_SSE
__m128 Rows[4];
#endif
} hmm_mat4; } hmm_mat4;
typedef union hmm_quaternion typedef union hmm_quaternion
@@ -461,6 +480,8 @@ typedef union hmm_quaternion
float Elements[4]; float Elements[4];
} hmm_quaternion; } hmm_quaternion;
typedef int32_t hmm_bool;
typedef hmm_vec2 hmm_v2; typedef hmm_vec2 hmm_v2;
typedef hmm_vec3 hmm_v3; typedef hmm_vec3 hmm_v3;
typedef hmm_vec4 hmm_v4; typedef hmm_vec4 hmm_v4;
@@ -532,10 +553,19 @@ HMMDEF hmm_vec3 HMM_DivideVec3f(hmm_vec3 Left, float Right);
HMMDEF hmm_vec4 HMM_DivideVec4(hmm_vec4 Left, hmm_vec4 Right); HMMDEF hmm_vec4 HMM_DivideVec4(hmm_vec4 Left, hmm_vec4 Right);
HMMDEF hmm_vec4 HMM_DivideVec4f(hmm_vec4 Left, float Right); HMMDEF hmm_vec4 HMM_DivideVec4f(hmm_vec4 Left, float Right);
HMMDEF hmm_bool HMM_EqualsVec2(hmm_vec2 Left, hmm_vec2 Right);
HMMDEF hmm_bool HMM_EqualsVec3(hmm_vec3 Left, hmm_vec3 Right);
HMMDEF hmm_bool HMM_EqualsVec4(hmm_vec4 Left, hmm_vec4 Right);
HMMDEF hmm_mat4 HMM_Mat4(void); HMMDEF hmm_mat4 HMM_Mat4(void);
HMMDEF hmm_mat4 HMM_Mat4d(float Diagonal); HMMDEF hmm_mat4 HMM_Mat4d(float Diagonal);
HMMDEF hmm_mat4 HMM_AddMat4(hmm_mat4 Left, hmm_mat4 Right); HMMDEF hmm_mat4 HMM_AddMat4(hmm_mat4 Left, hmm_mat4 Right);
HMMDEF hmm_mat4 HMM_SubtractMat4(hmm_mat4 Left, hmm_mat4 Right); HMMDEF hmm_mat4 HMM_SubtractMat4(hmm_mat4 Left, hmm_mat4 Right);
#ifdef HANDMADE_MATH__USE_SSE
HMMDEF __m128 HMM_LinearCombineSSE(__m128 Left, hmm_mat4 Right);
#endif
HMMDEF hmm_mat4 HMM_MultiplyMat4(hmm_mat4 Left, hmm_mat4 Right); HMMDEF hmm_mat4 HMM_MultiplyMat4(hmm_mat4 Left, hmm_mat4 Right);
HMMDEF hmm_mat4 HMM_MultiplyMat4f(hmm_mat4 Matrix, float Scalar); HMMDEF hmm_mat4 HMM_MultiplyMat4f(hmm_mat4 Matrix, float Scalar);
HMMDEF hmm_vec4 HMM_MultiplyMat4ByVec4(hmm_mat4 Matrix, hmm_vec4 Vector); HMMDEF hmm_vec4 HMM_MultiplyMat4ByVec4(hmm_mat4 Matrix, hmm_vec4 Vector);
@@ -625,6 +655,10 @@ HMMDEF hmm_mat4 HMM_Divide(hmm_mat4 Left, float Right);
HMMDEF hmm_quaternion HMM_Divide(hmm_quaternion Left, hmm_quaternion Right); HMMDEF hmm_quaternion HMM_Divide(hmm_quaternion Left, hmm_quaternion Right);
HMMDEF hmm_quaternion HMM_Divide(hmm_quaternion Left, float Right); HMMDEF hmm_quaternion HMM_Divide(hmm_quaternion Left, float Right);
HMMDEF hmm_bool HMM_Equals(hmm_vec2 Left, hmm_vec2 Right);
HMMDEF hmm_bool HMM_Equals(hmm_vec3 Left, hmm_vec3 Right);
HMMDEF hmm_bool HMM_Equals(hmm_vec4 Left, hmm_vec4 Right);
HMMDEF hmm_vec2 operator+(hmm_vec2 Left, hmm_vec2 Right); HMMDEF hmm_vec2 operator+(hmm_vec2 Left, hmm_vec2 Right);
HMMDEF hmm_vec3 operator+(hmm_vec3 Left, hmm_vec3 Right); HMMDEF hmm_vec3 operator+(hmm_vec3 Left, hmm_vec3 Right);
HMMDEF hmm_vec4 operator+(hmm_vec4 Left, hmm_vec4 Right); HMMDEF hmm_vec4 operator+(hmm_vec4 Left, hmm_vec4 Right);
@@ -699,6 +733,14 @@ HMMDEF hmm_vec4 &operator/=(hmm_vec4 &Left, float Right);
HMMDEF hmm_mat4 &operator/=(hmm_mat4 &Left, float Right); HMMDEF hmm_mat4 &operator/=(hmm_mat4 &Left, float Right);
HMMDEF hmm_quaternion &operator/=(hmm_quaternion &Left, float Right); HMMDEF hmm_quaternion &operator/=(hmm_quaternion &Left, float Right);
HMMDEF hmm_bool operator==(hmm_vec2 Left, hmm_vec2 Right);
HMMDEF hmm_bool operator==(hmm_vec3 Left, hmm_vec3 Right);
HMMDEF hmm_bool operator==(hmm_vec4 Left, hmm_vec4 Right);
HMMDEF hmm_bool operator!=(hmm_vec2 Left, hmm_vec2 Right);
HMMDEF hmm_bool operator!=(hmm_vec3 Left, hmm_vec3 Right);
HMMDEF hmm_bool operator!=(hmm_vec4 Left, hmm_vec4 Right);
#endif /* HANDMADE_MATH_CPP */ #endif /* HANDMADE_MATH_CPP */
#ifdef __clang__ #ifdef __clang__
@@ -1329,6 +1371,36 @@ HMM_DivideVec4f(hmm_vec4 Left, float Right)
return (Result); return (Result);
} }
HINLINE hmm_bool
HMM_EqualsVec2(hmm_vec2 Left, hmm_vec2 Right)
{
hmm_bool Result = 0;
Result = (Left.X == Right.X && Left.Y == Right.Y);
return (Result);
}
HINLINE hmm_bool
HMM_EqualsVec3(hmm_vec3 Left, hmm_vec3 Right)
{
hmm_bool Result = 0;
Result = (Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z);
return (Result);
}
HINLINE hmm_bool
HMM_EqualsVec4(hmm_vec4 Left, hmm_vec4 Right)
{
hmm_bool Result = 0;
Result = (Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z && Left.W == Right.W);
return (Result);
}
HINLINE hmm_mat4 HINLINE hmm_mat4
HMM_Mat4(void) HMM_Mat4(void)
{ {
@@ -1386,11 +1458,38 @@ HMM_SubtractMat4(hmm_mat4 Left, hmm_mat4 Right)
return (Result); return (Result);
} }
#ifdef HANDMADE_MATH__USE_SSE
HINLINE __m128
HMM_LinearCombineSSE(__m128 Left, hmm_mat4 Right)
{
__m128 Result = {};
Result = _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0x00), Right.Rows[0]);
Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0x55), Right.Rows[1]));
Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0xaa), Right.Rows[2]));
Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0xff), Right.Rows[3]));
return(Result);
}
#endif
HINLINE hmm_mat4 HINLINE hmm_mat4
HMM_MultiplyMat4(hmm_mat4 Left, hmm_mat4 Right) HMM_MultiplyMat4(hmm_mat4 Left, hmm_mat4 Right)
{ {
hmm_mat4 Result = HMM_Mat4(); hmm_mat4 Result = HMM_Mat4();
#ifdef HANDMADE_MATH__USE_SSE
hmm_mat4 TransposedLeft = HMM_Transpose(Left);
hmm_mat4 TransposedRight = HMM_Transpose(Right);
Result.Rows[0] = HMM_LinearCombineSSE(TransposedLeft.Rows[0], TransposedRight);
Result.Rows[1] = HMM_LinearCombineSSE(TransposedLeft.Rows[1], TransposedRight);
Result.Rows[2] = HMM_LinearCombineSSE(TransposedLeft.Rows[2], TransposedRight);
Result.Rows[3] = HMM_LinearCombineSSE(TransposedLeft.Rows[3], TransposedRight);
Result = HMM_Transpose(Result);
#else
int Columns; int Columns;
for(Columns = 0; Columns < 4; ++Columns) for(Columns = 0; Columns < 4; ++Columns)
{ {
@@ -1407,7 +1506,7 @@ HMM_MultiplyMat4(hmm_mat4 Left, hmm_mat4 Right)
Result.Elements[Columns][Rows] = Sum; Result.Elements[Columns][Rows] = Sum;
} }
} }
#endif
return (Result); return (Result);
} }
@@ -1472,6 +1571,11 @@ HMM_Transpose(hmm_mat4 Matrix)
{ {
hmm_mat4 Result = HMM_Mat4(); hmm_mat4 Result = HMM_Mat4();
#ifdef HANDMADE_MATH__USE_SSE
Result = Matrix;
_MM_TRANSPOSE4_PS(Result.Rows[0], Result.Rows[1], Result.Rows[2], Result.Rows[3]);
#else
int Columns; int Columns;
for(Columns = 0; Columns < 4; ++Columns) for(Columns = 0; Columns < 4; ++Columns)
{ {
@@ -1481,7 +1585,8 @@ HMM_Transpose(hmm_mat4 Matrix)
Result.Elements[Rows][Columns] = Matrix.Elements[Columns][Rows]; Result.Elements[Rows][Columns] = Matrix.Elements[Columns][Rows];
} }
} }
#endif
return (Result); return (Result);
} }
@@ -2239,6 +2344,33 @@ HMM_Divide(hmm_quaternion Left, float Right)
return (Result); return (Result);
} }
HINLINE hmm_bool
HMM_Equals(hmm_vec2 Left, hmm_vec2 Right)
{
hmm_bool Result = 0;
Result = HMM_EqualsVec2(Left, Right);
return (Result);
}
HINLINE hmm_bool
HMM_Equals(hmm_vec3 Left, hmm_vec3 Right)
{
hmm_bool Result = 0;
Result = HMM_EqualsVec3(Left, Right);
return (Result);
}
HINLINE hmm_bool
HMM_Equals(hmm_vec4 Left, hmm_vec4 Right)
{
hmm_bool Result = 0;
Result = HMM_EqualsVec4(Left, Right);
return (Result);
}
HINLINE hmm_vec2 HINLINE hmm_vec2
operator+(hmm_vec2 Left, hmm_vec2 Right) operator+(hmm_vec2 Left, hmm_vec2 Right)
{ {
@@ -2701,6 +2833,43 @@ operator*=(hmm_quaternion &Left, float Right)
return (Left = Left * Right); return (Left = Left * Right);
} }
HINLINE hmm_bool
operator==(hmm_vec2 Left, hmm_vec2 Right)
{
return HMM_EqualsVec2(Left, Right);
}
HINLINE hmm_bool
operator==(hmm_vec3 Left, hmm_vec3 Right)
{
return HMM_EqualsVec3(Left, Right);
}
HINLINE hmm_bool
operator==(hmm_vec4 Left, hmm_vec4 Right)
{
return HMM_EqualsVec4(Left, Right);
}
HINLINE hmm_bool
operator!=(hmm_vec2 Left, hmm_vec2 Right)
{
return !HMM_EqualsVec2(Left, Right);
}
HINLINE hmm_bool
operator!=(hmm_vec3 Left, hmm_vec3 Right)
{
return !HMM_EqualsVec3(Left, Right);
}
HINLINE hmm_bool
operator!=(hmm_vec4 Left, hmm_vec4 Right)
{
return !HMM_EqualsVec4(Left, Right);
}
#endif /* HANDMADE_MATH_CPP_MODE */ #endif /* HANDMADE_MATH_CPP_MODE */
#endif /* HANDMADE_MATH_IMPLEMENTATION */ #endif /* HANDMADE_MATH_IMPLEMENTATION */

View File

@@ -12,6 +12,7 @@ _This library is free and will stay free, but if you would like to support devel
Version | Changes | Version | Changes |
----------------|----------------| ----------------|----------------|
**1.2.0** | Added equality functions for `HMM_Vec2`, `HMM_Vec3`, and `HMM_Vec4`, and SSE'd `HMM_MultiplyMat4` and `HMM_Transpose`.
**1.1.5** | Added `Width` and `Height` to `HMM_Vec2`, and made it so you can supply your own `SqrtF`. **1.1.5** | Added `Width` and `Height` to `HMM_Vec2`, and made it so you can supply your own `SqrtF`.
**1.1.4** | Fixed SSE being included on platforms that don't support it, and fixed divide-by-zero errors when normalizing zero vectors. **1.1.4** | Fixed SSE being included on platforms that don't support it, and fixed divide-by-zero errors when normalizing zero vectors.
**1.1.3** | Fixed compile error in C mode **1.1.3** | Fixed compile error in C mode

View File

@@ -1,5 +1,2 @@
#include "HandmadeMath.c"
#define HANDMADE_MATH_IMPLEMENTATION // C++ compilers complain when compiling a .c file...
#define HANDMADE_MATH_CPP_MODE
#define HANDMADE_MATH_NO_INLINE
#include "../HandmadeMath.h"

View File

@@ -1,5 +0,0 @@
#define HANDMADE_MATH_IMPLEMENTATION
#define HANDMADE_MATH_NO_SSE
#define HANDMADE_MATH_NO_INLINE
#include "../HandmadeMath.h"

View File

@@ -1,6 +0,0 @@
#define HANDMADE_MATH_IMPLEMENTATION
#define HANDMADE_MATH_CPP_MODE
#define HANDMADE_MATH_NO_SSE
#define HANDMADE_MATH_NO_INLINE
#include "../HandmadeMath.h"

View File

@@ -45,6 +45,20 @@ int hmt_count_failures = 0;
/* /*
* Asserts and expects * Asserts and expects
*/ */
#define EXPECT_TRUE(_actual) do { \
if (!(_actual)) { \
CASE_FAIL(); \
printf("Expected true but got something false"); \
} \
} while (0)
#define EXPECT_FALSE(_actual) do { \
if (_actual) { \
CASE_FAIL(); \
printf("Expected false but got something true"); \
} \
} while (0)
#define EXPECT_FLOAT_EQ(_actual, _expected) do { \ #define EXPECT_FLOAT_EQ(_actual, _expected) do { \
float actual = (_actual); \ float actual = (_actual); \
float diff = actual - (_expected); \ float diff = actual - (_expected); \

View File

@@ -1,6 +1,6 @@
ROOT_DIR = .. ROOT_DIR=..
CXXFLAGS += -g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers CXXFLAGS+=-g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers
all: c c_no_sse cpp cpp_no_sse all: c c_no_sse cpp cpp_no_sse
@@ -8,17 +8,30 @@ clean:
rm -f hmm_test_c hmm_test_cpp hmm_test_c_no_sse hmm_test_cpp_no_sse *.o rm -f hmm_test_c hmm_test_cpp hmm_test_c_no_sse hmm_test_cpp_no_sse *.o
c: $(ROOT_DIR)/test/HandmadeMath.c test_impl c: $(ROOT_DIR)/test/HandmadeMath.c test_impl
$(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 -c $(ROOT_DIR)/test/HandmadeMath.c $(ROOT_DIR)/test/hmm_test.c -lm @echo "\nCompiling in C mode"
$(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
-c $(ROOT_DIR)/test/HandmadeMath.c $(ROOT_DIR)/test/hmm_test.c \
-lm
$(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm
c_no_sse: $(ROOT_DIR)/test/HandmadeMath_NoSSE.c test_impl c_no_sse: $(ROOT_DIR)/test/HandmadeMath.c test_impl
$(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 -c $(ROOT_DIR)/test/HandmadeMath_NoSSE.c $(ROOT_DIR)/test/hmm_test.c -lm @echo "\nCompiling in C mode (no SSE)"
$(CC) -ohmm_test_c_no_sse HandmadeMath_NoSSE.o hmm_test.o -lm $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
-DHANDMADE_MATH_NO_SSE \
-c $(ROOT_DIR)/test/HandmadeMath.c $(ROOT_DIR)/test/hmm_test.c \
-lm
$(CC) -ohmm_test_c_no_sse HandmadeMath.o hmm_test.o -lm
cpp: $(ROOT_DIR)/test/HandmadeMath.cpp test_impl cpp: $(ROOT_DIR)/test/HandmadeMath.cpp test_impl
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp $(ROOT_DIR)/test/HandmadeMath.cpp $(ROOT_DIR)/test/hmm_test.cpp @echo "\nCompiling in C++ mode"
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp \
-DHANDMADE_MATH_CPP_MODE \
$(ROOT_DIR)/test/HandmadeMath.cpp $(ROOT_DIR)/test/hmm_test.cpp
cpp_no_sse: $(ROOT_DIR)/test/HandmadeMath_NoSSE.cpp test_impl cpp_no_sse: $(ROOT_DIR)/test/HandmadeMath.cpp test_impl
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_no_sse $(ROOT_DIR)/test/HandmadeMath_NoSSE.cpp $(ROOT_DIR)/test/hmm_test.cpp @echo "\nCompiling in C++ mode (no SSE)"
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_no_sse \
-DHANDMADE_MATH_CPP_MODE -DHANDMADE_MATH_NO_SSE \
$(ROOT_DIR)/test/HandmadeMath.cpp $(ROOT_DIR)/test/hmm_test.cpp
test_impl: $(ROOT_DIR)/test/hmm_test.cpp $(ROOT_DIR)/test/hmm_test.c test_impl: $(ROOT_DIR)/test/hmm_test.cpp $(ROOT_DIR)/test/hmm_test.c

11
test/README.md Normal file
View File

@@ -0,0 +1,11 @@
# Testing
You can compile and run the tests yourself by running:
```
make
./hmm_test_c
./hmm_test_c_no_sse
./hmm_test_cpp
./hmm_test_cpp_no_sse
```

View File

@@ -827,7 +827,7 @@ int run_tests()
{ {
for (int Row = 0; Row < 4; ++Row) for (int Row = 0; Row < 4; ++Row)
{ {
EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected) << "At column " << Column << ", row " << Row; EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected);
Expected += 2.0f; Expected += 2.0f;
} }
} }
@@ -839,7 +839,7 @@ int run_tests()
{ {
for (int Row = 0; Row < 4; ++Row) for (int Row = 0; Row < 4; ++Row)
{ {
EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected) << "At column " << Column << ", row " << Row; EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected);
Expected += 2.0f; Expected += 2.0f;
} }
} }
@@ -851,7 +851,7 @@ int run_tests()
{ {
for (int Row = 0; Row < 4; ++Row) for (int Row = 0; Row < 4; ++Row)
{ {
EXPECT_FLOAT_EQ(m4_1.Elements[Column][Row], Expected) << "At column " << Column << ", row " << Row; EXPECT_FLOAT_EQ(m4_1.Elements[Column][Row], Expected);
Expected += 2.0f; Expected += 2.0f;
} }
} }
@@ -1041,7 +1041,7 @@ int run_tests()
{ {
for (int Row = 0; Row < 4; ++Row) for (int Row = 0; Row < 4; ++Row)
{ {
EXPECT_FLOAT_EQ(result.Elements[Column][Row], -16.0f) << "At column " << Column << ", row " << Row; EXPECT_FLOAT_EQ(result.Elements[Column][Row], -16.0f);
} }
} }
} }
@@ -1051,7 +1051,7 @@ int run_tests()
{ {
for (int Row = 0; Row < 4; ++Row) for (int Row = 0; Row < 4; ++Row)
{ {
EXPECT_FLOAT_EQ(result.Elements[Column][Row], -16.0f) << "At column " << Column << ", row " << Row; EXPECT_FLOAT_EQ(result.Elements[Column][Row], -16.0f);
} }
} }
} }
@@ -1061,7 +1061,7 @@ int run_tests()
{ {
for (int Row = 0; Row < 4; ++Row) for (int Row = 0; Row < 4; ++Row)
{ {
EXPECT_FLOAT_EQ(m4_1.Elements[Column][Row], -16.0f) << "At column " << Column << ", row " << Row; EXPECT_FLOAT_EQ(m4_1.Elements[Column][Row], -16.0f);
} }
} }
#endif #endif
@@ -1993,6 +1993,67 @@ int run_tests()
} }
CATEGORY_END() CATEGORY_END()
CATEGORY_BEGIN(Equality)
{
TEST_BEGIN(Vec2)
{
hmm_vec2 a = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 b = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 c = HMM_Vec2(3.0f, 4.0f);
EXPECT_TRUE(HMM_EqualsVec2(a, b));
EXPECT_FALSE(HMM_EqualsVec2(a, c));
#ifdef HANDMADE_MATH_CPP_MODE
EXPECT_TRUE(HMM_Equals(a, b));
EXPECT_FALSE(HMM_Equals(a, c));
EXPECT_TRUE(a == b);
EXPECT_FALSE(a == c);
#endif
}
TEST_END()
TEST_BEGIN(Vec3)
{
hmm_vec3 a = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 b = HMM_Vec3(1.0f, 2.0f, 3.0f);
hmm_vec3 c = HMM_Vec3(4.0f, 5.0f, 6.0f);
EXPECT_TRUE(HMM_EqualsVec3(a, b));
EXPECT_FALSE(HMM_EqualsVec3(a, c));
#ifdef HANDMADE_MATH_CPP_MODE
EXPECT_TRUE(HMM_Equals(a, b));
EXPECT_FALSE(HMM_Equals(a, c));
EXPECT_TRUE(a == b);
EXPECT_FALSE(a == c);
#endif
}
TEST_END()
TEST_BEGIN(Vec4)
{
hmm_vec4 a = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 b = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 c = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
EXPECT_TRUE(HMM_EqualsVec4(a, b));
EXPECT_FALSE(HMM_EqualsVec4(a, c));
#ifdef HANDMADE_MATH_CPP_MODE
EXPECT_TRUE(HMM_Equals(a, b));
EXPECT_FALSE(HMM_Equals(a, c));
EXPECT_TRUE(a == b);
EXPECT_FALSE(a == c);
#endif
}
TEST_END()
}
CATEGORY_END()
CATEGORY_BEGIN(Projection) CATEGORY_BEGIN(Projection)
{ {
TEST_BEGIN(Orthographic) TEST_BEGIN(Orthographic)
@@ -2093,5 +2154,49 @@ int run_tests()
} }
CATEGORY_END() CATEGORY_END()
#ifdef HANDMADE_MATH__USE_SSE
CATEGORY_BEGIN(SSE)
{
TEST_BEGIN(LinearCombine)
{
hmm_mat4 MatrixOne = HMM_Mat4d(2.0f);
hmm_mat4 MatrixTwo = HMM_Mat4d(4.0f);
hmm_mat4 Result;
Result.Rows[0] = HMM_LinearCombineSSE(MatrixOne.Rows[0], MatrixTwo);
Result.Rows[1] = HMM_LinearCombineSSE(MatrixOne.Rows[1], MatrixTwo);
Result.Rows[2] = HMM_LinearCombineSSE(MatrixOne.Rows[2], MatrixTwo);
Result.Rows[3] = HMM_LinearCombineSSE(MatrixOne.Rows[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][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][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][2], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[3][3], 8.0f);
}
}
TEST_END()
}
CATEGORY_END()
#endif
return 0; return 0;
} }