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,5 +1,2 @@
#define HANDMADE_MATH_IMPLEMENTATION
#define HANDMADE_MATH_CPP_MODE
#define HANDMADE_MATH_NO_INLINE
#include "../HandmadeMath.h"
#include "HandmadeMath.c"
// C++ compilers complain when compiling a .c file...

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
*/
#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 { \
float actual = (_actual); \
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
@@ -8,17 +8,30 @@ clean:
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
$(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
c_no_sse: $(ROOT_DIR)/test/HandmadeMath_NoSSE.c test_impl
$(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 -c $(ROOT_DIR)/test/HandmadeMath_NoSSE.c $(ROOT_DIR)/test/hmm_test.c -lm
$(CC) -ohmm_test_c_no_sse HandmadeMath_NoSSE.o hmm_test.o -lm
c_no_sse: $(ROOT_DIR)/test/HandmadeMath.c test_impl
@echo "\nCompiling in C mode (no SSE)"
$(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
$(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
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_no_sse $(ROOT_DIR)/test/HandmadeMath_NoSSE.cpp $(ROOT_DIR)/test/hmm_test.cpp
cpp_no_sse: $(ROOT_DIR)/test/HandmadeMath.cpp test_impl
@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

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)
{
EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected) << "At column " << Column << ", row " << Row;
EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected);
Expected += 2.0f;
}
}
@@ -839,7 +839,7 @@ int run_tests()
{
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;
}
}
@@ -851,7 +851,7 @@ int run_tests()
{
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;
}
}
@@ -1041,7 +1041,7 @@ int run_tests()
{
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)
{
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)
{
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
@@ -1993,6 +1993,67 @@ int run_tests()
}
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)
{
TEST_BEGIN(Orthographic)
@@ -2093,5 +2154,49 @@ int run_tests()
}
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;
}