Compare commits

...

21 Commits

Author SHA1 Message Date
Ben Visness
4981d5ab89 Convert everything to new inline scheme (#57) (#72)
* Convert everything to new inline scheme

* Add both extern and inline for some SSE vs. non-SSE functions

Some functions had nice, compact SSE implementations but bulky non-SSE
implementations, so this commit inlines just the implementations that make
sense. Also updated documentation.

* Convert HINLINE and HEXTERN to HMM_INLINE and HMM_EXTERN
2017-10-31 10:16:36 -05:00
Ben Visness
5f173e0176 Update CONTRIBUTING.md 2017-10-31 10:09:27 -05:00
Ben Visness
575fcb767d Update README.md 2017-10-31 10:06:22 -05:00
strangezak
a08262b2d9 Removed old instructions 2017-10-14 19:34:51 -07:00
strangezak
53bc939d8e Updated email 2017-10-04 09:40:31 -07:00
Ben Visness
7eb4ae1846 Update README for 1.4.0 2017-10-02 11:17:11 -05:00
StrangeZak
48bd24b05e Updated docs 2017-10-01 10:32:53 -07:00
Zak Strange
064baeb5b9 V1.4 - SSE upgrades and bug fixes (#70)
* Fixed bug when using handmademath in C mode

* SSEd vec4 operations

* Fixed hmm_vec4 for non-sse builds. Added SSE option for HMM_Vec4 to load in one instruction

* Whoops. We were loading in the wrong order

* SSEd more things

* SSEd more functions

* Minor fixups

* SSE'd hmm_vec4 initialization

* Removed zeroing

* Vector normalization should be zero'd

* Removed old comments
2017-09-30 14:38:28 -07:00
Ben Visness
afd726ab0b Automatically include C++ definitions (#67) 2017-08-02 10:12:06 -05:00
strangezak
98fffbd7cc Forgot to update version 2017-07-16 21:29:26 -07:00
Ben Visness
efd9f2f4b7 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
2017-07-16 21:19:34 -07:00
Ben Visness
c8ada18370 Update README for 1.1.5 2017-06-21 09:31:20 -05:00
Zak Strange
70ac2b7e5b 1.1.5 (#64)
* Added Width, and Height to hmm_vec2, and fixed SqrtF when compiling without the CRT

* Syntax error

* Test all the vector access methods
2017-06-14 20:49:44 -07:00
Ben Visness
924ee43923 Update history to include @DanielGibson's SSE fixes 2017-06-13 11:39:42 -05:00
Ben Visness
440b885d59 Update version to 1.1.4 2017-06-13 11:26:46 -05:00
Emil Lauridsen
98f535aeec Handle zero-vector normalization. (#63)
* Handle zero-vector normalization.

When normalizing a vectors, we have to check whether vector length is
not zero, to avoid dividing by zero when normalizing zero-vectors.

* Test for normalization of zero vectors
2017-06-13 11:21:55 -05:00
Ben Visness
09524f72ed Merge branch 'sse-testing'
# Conflicts:
#	HandmadeMath.h
2017-06-11 18:54:06 -05:00
Emil Lauridsen
be30046a5a C89 style comments (#62) 2017-06-11 10:32:46 -07:00
Daniel Gibson
ff4513ff33 Make it usable on non-SSE platforms (#60)
* at one place HANDMADE_NO_SSE instead of HANDMADE_MATH_NO_SSE was used
* introduce HANDMADE_MATH__USE_SSE for the SSE #ifdefs throughout code
  - use #ifdef HANDMADE_MATH_NO_SSE at only one place
* only use SSE (#define HANDMADE_MATH__USE_SSE) if the targetplatform
  actually supports it
  => users don't have to #define HANDMADE_MATH_NO_SSE on ARM etc
* at one place HMM_SqrtF instead of HMM_SquareRootF was used
2017-06-09 17:14:24 -07:00
Ben Visness
364569abe9 Fix wrong name for square root function 2017-06-09 10:43:11 -05:00
Ben Visness
a9972e71da Test both with and without SSE 2017-06-09 10:37:38 -05:00
10 changed files with 2171 additions and 2064 deletions

View File

@@ -7,4 +7,6 @@ install:
- make
script:
- ./hmm_test_c
- ./hmm_test_c_no_sse
- ./hmm_test_cpp
- ./hmm_test_cpp_no_sse

View File

@@ -1,3 +1,9 @@
# Understanding the structure of Handmade Math
Most of the functions in Handmade Math are very short, and are the kind of functions you want to have inlined. Because of this, most functions in Handmade Math are defined with `HINLINE`, which is defined as `static inline`.
The exceptions are functions like `HMM_Rotate`, which are long enough that it doesn't make sense to inline them. These functions are defined with an `HEXTERN` prototype, and implemented in the `#ifdef HANDMADE_MATH_IMPLEMENTATION` block.
# Quick style guide
* Put braces on a new line
@@ -13,23 +19,6 @@
1.f
.0f
```
* Put macros and return types on a separate line from the function definition:
```cpp
HINLINE float
HMM_MyFunction()
{
// ...
}
```
* Explicitly initialize variables to zero:
```cpp
HINLINE float
HMM_MyFunction()
{
float MyFloat = 0.0f;
hmm_vec3 MyVector = {0};
}
```
* Put parentheses around the returned value:
```cpp
HINLINE float
@@ -40,7 +29,7 @@
```
# Other notes
## Other style notes
* If a new function is defined with different names for different datatypes, also add C++ overloaded versions of the functions. For example, if you have `HMM_LengthVec2(hmm_vec2)` and `HMM_LengthVec3(hmm_vec3)`, also provide `HMM_Length(hmm_vec2)` and `HMM_Length(hmm_vec3)`.
@@ -49,3 +38,6 @@
* Try to define functions in the same order as the prototypes.
* Don't forget that Handmade Math uses column-major order for matrices!
# Versioning
We use [semantic versioning](http://semver.org/) because it's reasonable.

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,9 @@
[![Build Status](https://travis-ci.org/StrangeZak/Handmade-Math.svg?branch=master)](https://travis-ci.org/StrangeZak/Handmade-Math)
Single-file cross-platform public domain game math library for C/C++
A single-file, cross-platform, public domain game math library for C/C++.
To get started, go download [the latest release](https://github.com/HandmadeMath/Handmade-Math/releases).
_This library is free and will stay free, but if you would like to support development, or you are a company using HandmadeMath, please consider financial support._
@@ -12,6 +14,12 @@ _This library is free and will stay free, but if you would like to support devel
Version | Changes |
----------------|----------------|
**1.5.0** | Changed internal structure for better performance and inlining. As a result, `HANDMADE_MATH_NO_INLINE` has been removed and no longer has any effect.
**1.4.0** | Fixed bug when using C mode. SSE'd all vec4 operations. Removed zeroing for better performance.
**1.3.0** | Removed need to `#define HANDMADE_MATH_CPP_MODE`. C++ definitions are now included automatically in C++ environments.
**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.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.2** | Fixed invalid HMMDEF's in the function definitions
**1.1.1** | Resolved compiler warnings on gcc and g++
@@ -40,4 +48,4 @@ This library is in the public domain. You can do whatever you want with it.
**Where can I contact you to ask questions?**
You can email me at: Zak@Handmade.Network
Feel free to make Github issues for any questions, concerns, or problems you encounter.

View File

@@ -1,4 +1,3 @@
#define HANDMADE_MATH_IMPLEMENTATION
#define HANDMADE_MATH_NO_INLINE
#include "../HandmadeMath.h"

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

@@ -25,27 +25,48 @@ int hmt_count_failures = 0;
}
#define TEST_BEGIN(name) { \
int count_testfailures = 0; \
int count_testcases = 0, count_testfailures = 0; \
count_categorytests++; \
printf(" " #name ":");
#define TEST_END() \
count_categoryfailures += count_testfailures; \
if (count_testfailures > 0) { \
count_categoryfailedtests++; \
printf("\n " RED "(%d/%d passed)" RESET, count_testcases - count_testfailures, count_testcases); \
printf("\n"); \
} else { \
printf(GREEN " [PASS]\n" RESET); \
printf(GREEN " [PASS] (%d/%d passed) \n" RESET, count_testcases - count_testfailures, count_testcases); \
} \
}
#define CASE_START() \
count_testcases++;
#define CASE_FAIL() \
count_testfailures++; \
printf("\n - " RED "[FAIL] (%d) " RESET, __LINE__)
printf("\n - " RED "[FAIL] (%d) " RESET, __LINE__);
/*
* Asserts and expects
*/
#define EXPECT_TRUE(_actual) do { \
CASE_START(); \
if (!(_actual)) { \
CASE_FAIL(); \
printf("Expected true but got something false"); \
} \
} while (0)
#define EXPECT_FALSE(_actual) do { \
CASE_START(); \
if (_actual) { \
CASE_FAIL(); \
printf("Expected false but got something true"); \
} \
} while (0)
#define EXPECT_FLOAT_EQ(_actual, _expected) do { \
CASE_START(); \
float actual = (_actual); \
float diff = actual - (_expected); \
if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
@@ -55,6 +76,7 @@ int hmt_count_failures = 0;
} while (0)
#define EXPECT_NEAR(_actual, _expected, _epsilon) do { \
CASE_START(); \
float actual = (_actual); \
float diff = actual - (_expected); \
if (diff < -(_epsilon) || (_epsilon) < diff) { \
@@ -64,6 +86,7 @@ int hmt_count_failures = 0;
} while (0)
#define EXPECT_LT(_actual, _expected) do { \
CASE_START(); \
if ((_actual) >= (_expected)) { \
CASE_FAIL(); \
printf("Expected %f to be less than %f", (_actual), (_expected)); \
@@ -71,6 +94,7 @@ int hmt_count_failures = 0;
} while (0)
#define EXPECT_GT(_actual, _expected) do { \
CASE_START(); \
if ((_actual) <= (_expected)) { \
CASE_FAIL(); \
printf("Expected %f to be greater than %f", (_actual), (_expected)); \

View File

@@ -1,17 +1,37 @@
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 cpp
all: c c_no_sse cpp cpp_no_sse
clean:
rm -f hmm_test_c hmm_test_cpp *.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
$(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.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.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

@@ -70,7 +70,7 @@ int run_tests()
TEST_BEGIN(RSquareRootF)
{
EXPECT_FLOAT_EQ(HMM_RSquareRootF(10.0f), 0.31616211f);
EXPECT_NEAR(HMM_RSquareRootF(10.0f), 0.31616211f, 0.0001f);
}
TEST_END()
@@ -120,9 +120,25 @@ int run_tests()
EXPECT_FLOAT_EQ(v2.X, 1.0f);
EXPECT_FLOAT_EQ(v2.Y, 2.0f);
EXPECT_FLOAT_EQ(v2.U, 1.0f);
EXPECT_FLOAT_EQ(v2.V, 2.0f);
EXPECT_FLOAT_EQ(v2.Left, 1.0f);
EXPECT_FLOAT_EQ(v2.Right, 2.0f);
EXPECT_FLOAT_EQ(v2.Width, 1.0f);
EXPECT_FLOAT_EQ(v2.Height, 2.0f);
EXPECT_FLOAT_EQ(v2.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v2.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v2i.X, 1.0f);
EXPECT_FLOAT_EQ(v2i.Y, 2.0f);
EXPECT_FLOAT_EQ(v2i.U, 1.0f);
EXPECT_FLOAT_EQ(v2i.V, 2.0f);
EXPECT_FLOAT_EQ(v2i.Left, 1.0f);
EXPECT_FLOAT_EQ(v2i.Right, 2.0f);
EXPECT_FLOAT_EQ(v2i.Width, 1.0f);
EXPECT_FLOAT_EQ(v2i.Height, 2.0f);
EXPECT_FLOAT_EQ(v2i.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v2i.Elements[1], 2.0f);
//
// Test vec3
@@ -133,10 +149,44 @@ int run_tests()
EXPECT_FLOAT_EQ(v3.X, 1.0f);
EXPECT_FLOAT_EQ(v3.Y, 2.0f);
EXPECT_FLOAT_EQ(v3.Z, 3.0f);
EXPECT_FLOAT_EQ(v3.U, 1.0f);
EXPECT_FLOAT_EQ(v3.V, 2.0f);
EXPECT_FLOAT_EQ(v3.W, 3.0f);
EXPECT_FLOAT_EQ(v3.R, 1.0f);
EXPECT_FLOAT_EQ(v3.G, 2.0f);
EXPECT_FLOAT_EQ(v3.B, 3.0f);
EXPECT_FLOAT_EQ(v3.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v3.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v3.Elements[2], 3.0f);
EXPECT_FLOAT_EQ(v3.XY.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v3.XY.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v3.YZ.Elements[0], 2.0f);
EXPECT_FLOAT_EQ(v3.YZ.Elements[1], 3.0f);
EXPECT_FLOAT_EQ(v3.UV.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v3.UV.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v3.VW.Elements[0], 2.0f);
EXPECT_FLOAT_EQ(v3.VW.Elements[1], 3.0f);
EXPECT_FLOAT_EQ(v3i.X, 1.0f);
EXPECT_FLOAT_EQ(v3i.Y, 2.0f);
EXPECT_FLOAT_EQ(v3i.Z, 3.0f);
EXPECT_FLOAT_EQ(v3i.U, 1.0f);
EXPECT_FLOAT_EQ(v3i.V, 2.0f);
EXPECT_FLOAT_EQ(v3i.W, 3.0f);
EXPECT_FLOAT_EQ(v3i.R, 1.0f);
EXPECT_FLOAT_EQ(v3i.G, 2.0f);
EXPECT_FLOAT_EQ(v3i.B, 3.0f);
EXPECT_FLOAT_EQ(v3i.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v3i.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v3i.Elements[2], 3.0f);
EXPECT_FLOAT_EQ(v3i.XY.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v3i.XY.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v3i.YZ.Elements[0], 2.0f);
EXPECT_FLOAT_EQ(v3i.YZ.Elements[1], 3.0f);
EXPECT_FLOAT_EQ(v3i.UV.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v3i.UV.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v3i.VW.Elements[0], 2.0f);
EXPECT_FLOAT_EQ(v3i.VW.Elements[1], 3.0f);
//
// Test vec4
@@ -149,16 +199,70 @@ int run_tests()
EXPECT_FLOAT_EQ(v4.Y, 2.0f);
EXPECT_FLOAT_EQ(v4.Z, 3.0f);
EXPECT_FLOAT_EQ(v4.W, 4.0f);
EXPECT_FLOAT_EQ(v4.R, 1.0f);
EXPECT_FLOAT_EQ(v4.G, 2.0f);
EXPECT_FLOAT_EQ(v4.B, 3.0f);
EXPECT_FLOAT_EQ(v4.A, 4.0f);
EXPECT_FLOAT_EQ(v4.XY.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4.XY.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4.YZ.Elements[0], 2.0f);
EXPECT_FLOAT_EQ(v4.YZ.Elements[1], 3.0f);
EXPECT_FLOAT_EQ(v4.ZW.Elements[0], 3.0f);
EXPECT_FLOAT_EQ(v4.ZW.Elements[1], 4.0f);
EXPECT_FLOAT_EQ(v4.XY.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4.XY.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4.XYZ.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4.XYZ.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4.XYZ.Elements[2], 3.0f);
EXPECT_FLOAT_EQ(v4.RGB.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4.RGB.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4.RGB.Elements[2], 3.0f);
EXPECT_FLOAT_EQ(v4i.X, 1.0f);
EXPECT_FLOAT_EQ(v4i.Y, 2.0f);
EXPECT_FLOAT_EQ(v4i.Z, 3.0f);
EXPECT_FLOAT_EQ(v4i.W, 4.0f);
EXPECT_FLOAT_EQ(v4i.R, 1.0f);
EXPECT_FLOAT_EQ(v4i.G, 2.0f);
EXPECT_FLOAT_EQ(v4i.B, 3.0f);
EXPECT_FLOAT_EQ(v4i.A, 4.0f);
EXPECT_FLOAT_EQ(v4i.XY.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4i.XY.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4i.YZ.Elements[0], 2.0f);
EXPECT_FLOAT_EQ(v4i.YZ.Elements[1], 3.0f);
EXPECT_FLOAT_EQ(v4i.ZW.Elements[0], 3.0f);
EXPECT_FLOAT_EQ(v4i.ZW.Elements[1], 4.0f);
EXPECT_FLOAT_EQ(v4i.XY.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4i.XY.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4i.XYZ.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4i.XYZ.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4i.XYZ.Elements[2], 3.0f);
EXPECT_FLOAT_EQ(v4i.RGB.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4i.RGB.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4i.RGB.Elements[2], 3.0f);
EXPECT_FLOAT_EQ(v4v.X, 1.0f);
EXPECT_FLOAT_EQ(v4v.Y, 2.0f);
EXPECT_FLOAT_EQ(v4v.Z, 3.0f);
EXPECT_FLOAT_EQ(v4v.W, 4.0f);
EXPECT_FLOAT_EQ(v4v.R, 1.0f);
EXPECT_FLOAT_EQ(v4v.G, 2.0f);
EXPECT_FLOAT_EQ(v4v.B, 3.0f);
EXPECT_FLOAT_EQ(v4v.A, 4.0f);
EXPECT_FLOAT_EQ(v4v.XY.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4v.XY.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4v.YZ.Elements[0], 2.0f);
EXPECT_FLOAT_EQ(v4v.YZ.Elements[1], 3.0f);
EXPECT_FLOAT_EQ(v4v.ZW.Elements[0], 3.0f);
EXPECT_FLOAT_EQ(v4v.ZW.Elements[1], 4.0f);
EXPECT_FLOAT_EQ(v4v.XY.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4v.XY.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4v.XYZ.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4v.XYZ.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4v.XYZ.Elements[2], 3.0f);
EXPECT_FLOAT_EQ(v4v.RGB.Elements[0], 1.0f);
EXPECT_FLOAT_EQ(v4v.RGB.Elements[1], 2.0f);
EXPECT_FLOAT_EQ(v4v.RGB.Elements[2], 3.0f);
}
TEST_END()
@@ -230,7 +334,7 @@ int run_tests()
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec3(v3), 14.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec4(v4), 15.0f);
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
EXPECT_FLOAT_EQ(HMM_LengthSquared(v2), 5.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquared(v3), 14.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquared(v4), 15.0f);
@@ -248,7 +352,7 @@ int run_tests()
EXPECT_FLOAT_EQ(HMM_LengthVec3(v3), 7.0f);
EXPECT_FLOAT_EQ(HMM_LengthVec4(v4), 13.892444f);
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
EXPECT_FLOAT_EQ(HMM_Length(v2), 9.0553856f);
EXPECT_FLOAT_EQ(HMM_Length(v3), 7.0f);
EXPECT_FLOAT_EQ(HMM_Length(v4), 13.892444f);
@@ -284,7 +388,7 @@ int run_tests()
EXPECT_LT(result.W, 0.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec2 result = HMM_Normalize(v2);
EXPECT_FLOAT_EQ(HMM_LengthVec2(result), 1.0f);
@@ -310,6 +414,54 @@ int run_tests()
}
TEST_END()
TEST_BEGIN(NormalizeZero)
{
hmm_vec2 v2 = HMM_Vec2(0.0f, 0.0f);
hmm_vec3 v3 = HMM_Vec3(0.0f, 0.0f, 0.0f);
hmm_vec4 v4 = HMM_Vec4(0.0f, 0.0f, 0.0f, 0.0f);
{
hmm_vec2 result = HMM_NormalizeVec2(v2);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
}
{
hmm_vec3 result = HMM_NormalizeVec3(v3);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
EXPECT_FLOAT_EQ(result.Z, 0.0f);
}
{
hmm_vec4 result = HMM_NormalizeVec4(v4);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
EXPECT_FLOAT_EQ(result.Z, 0.0f);
EXPECT_FLOAT_EQ(result.W, 0.0f);
}
#ifdef __cplusplus
{
hmm_vec2 result = HMM_Normalize(v2);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
}
{
hmm_vec3 result = HMM_Normalize(v3);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
EXPECT_FLOAT_EQ(result.Z, 0.0f);
}
{
hmm_vec4 result = HMM_Normalize(v4);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
EXPECT_FLOAT_EQ(result.Z, 0.0f);
EXPECT_FLOAT_EQ(result.W, 0.0f);
}
#endif
}
TEST_END()
TEST_BEGIN(Cross)
{
hmm_vec3 v1 = HMM_Vec3(1.0f, 2.0f, 3.0f);
@@ -329,7 +481,7 @@ int run_tests()
hmm_vec2 v2 = HMM_Vec2(3.0f, 4.0f);
EXPECT_FLOAT_EQ(HMM_DotVec2(v1, v2), 11.0f);
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 11.0f);
#endif
}
@@ -341,7 +493,7 @@ int run_tests()
hmm_vec3 v2 = HMM_Vec3(4.0f, 5.0f, 6.0f);
EXPECT_FLOAT_EQ(HMM_DotVec3(v1, v2), 32.0f);
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 32.0f);
#endif
}
@@ -353,7 +505,7 @@ int run_tests()
hmm_vec4 v2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
EXPECT_FLOAT_EQ(HMM_DotVec4(v1, v2), 70.0f);
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 70.0f);
#endif
}
@@ -426,7 +578,7 @@ int run_tests()
float result = HMM_DotQuaternion(q1, q2);
EXPECT_FLOAT_EQ(result, 70.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
float result = HMM_Dot(q1, q2);
EXPECT_FLOAT_EQ(result, 70.0f);
@@ -446,7 +598,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Z, 0.5477225575f);
EXPECT_FLOAT_EQ(result.W, 0.7302967433f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_quaternion result = HMM_Normalize(q);
EXPECT_FLOAT_EQ(result.X, 0.1825741858f);
@@ -541,7 +693,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec2 result = HMM_Add(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 4.0f);
@@ -571,7 +723,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Y, 7.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec3 result = HMM_Add(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 5.0f);
@@ -605,7 +757,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec4 result = HMM_Add(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 6.0f);
@@ -667,7 +819,7 @@ int run_tests()
}
}
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_mat4 result = HMM_Add(m4_1, m4_2);
float Expected = 18.0f;
@@ -675,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;
}
}
@@ -687,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;
}
}
@@ -699,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;
}
}
@@ -719,7 +871,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_quaternion result = HMM_Add(q1, q2);
EXPECT_FLOAT_EQ(result.X, 6.0f);
@@ -758,7 +910,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.X, -2.0f);
EXPECT_FLOAT_EQ(result.Y, -2.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec2 result = HMM_Subtract(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, -2.0f);
@@ -788,7 +940,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Y, -3.0f);
EXPECT_FLOAT_EQ(result.Z, -3.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec3 result = HMM_Subtract(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, -3.0f);
@@ -822,7 +974,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec4 result = HMM_Subtract(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, -4.0f);
@@ -882,14 +1034,14 @@ int run_tests()
}
}
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_mat4 result = HMM_Subtract(m4_1, m4_2);
for (int Column = 0; Column < 4; ++Column)
{
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);
}
}
}
@@ -899,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);
}
}
}
@@ -909,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
@@ -928,7 +1080,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_quaternion result = HMM_Subtract(q1, q2);
EXPECT_FLOAT_EQ(result.X, -4.0f);
@@ -967,7 +1119,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec2 result = HMM_Multiply(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 3.0f);
@@ -996,7 +1148,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec2 result = HMM_Multiply(v2, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
@@ -1031,7 +1183,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Y, 10.0f);
EXPECT_FLOAT_EQ(result.Z, 18.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec3 result = HMM_Multiply(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 4.0f);
@@ -1064,7 +1216,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec3 result = HMM_Multiply(v3, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
@@ -1104,7 +1256,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Z, 21.0f);
EXPECT_FLOAT_EQ(result.W, 32.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec4 result = HMM_Multiply(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 5.0f);
@@ -1141,7 +1293,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Z, 9.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec4 result = HMM_Multiply(v4, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
@@ -1216,7 +1368,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_mat4 result = HMM_Multiply(m4_1, m4_2);
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
@@ -1299,7 +1451,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_mat4 result = HMM_Multiply(m4, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
@@ -1403,7 +1555,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Z, 110.0f);
EXPECT_FLOAT_EQ(result.W, 120.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec4 result = HMM_Multiply(m4, v4);
EXPECT_FLOAT_EQ(result.X, 90.0f);
@@ -1436,7 +1588,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Z, 48.0f);
EXPECT_FLOAT_EQ(result.W, -6.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_quaternion result = HMM_Multiply(q1, q2);
EXPECT_FLOAT_EQ(result.X, 24.0f);
@@ -1471,7 +1623,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Z, 6.0f);
EXPECT_FLOAT_EQ(result.W, 8.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_quaternion result = HMM_Multiply(q, f);
EXPECT_FLOAT_EQ(result.X, 2.0f);
@@ -1517,7 +1669,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec2 result = HMM_Divide(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -1546,7 +1698,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec2 result = HMM_Divide(v2, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -1576,7 +1728,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec3 result = HMM_Divide(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -1609,7 +1761,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec3 result = HMM_Divide(v3, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -1643,7 +1795,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 0.25f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec4 result = HMM_Divide(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -1680,7 +1832,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_vec4 result = HMM_Divide(v4, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -1741,7 +1893,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_mat4 result = HMM_Divide(m4, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
@@ -1814,7 +1966,7 @@ int run_tests()
EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f);
}
#ifdef HANDMADE_MATH_CPP_MODE
#ifdef __cplusplus
{
hmm_quaternion result = HMM_Divide(q, f);
EXPECT_FLOAT_EQ(result.X, 0.5f);
@@ -1841,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 __cplusplus
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 __cplusplus
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 __cplusplus
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)
@@ -1941,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;
}