Compare commits

..

3 Commits

Author SHA1 Message Date
Ben Visness
9fa107b09b Fix tests 2019-07-09 17:15:10 -05:00
Ben Visness
242353b78b Update readme 2019-07-09 17:13:10 -05:00
Ben Visness
568df57575 Use vertical instead of horizontal FOV 2019-07-09 17:10:42 -05:00
22 changed files with 1574 additions and 2583 deletions

View File

@@ -1,9 +0,0 @@
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

View File

@@ -1,23 +1,12 @@
language: cpp language: cpp
os:
- linux
- osx
compiler: compiler:
- clang - clang
- gcc - gcc
matrix:
include:
# Windows x64 builds (MSVC)
- os: windows
script:
- ./test.bat travis
before_install:
- eval "${MATRIX_EVAL}"
install: install:
- cd test - cd test
- make
script: script:
- make c - build/hmm_test_c
- make c_no_sse - build/hmm_test_c_no_sse
- make cpp - build/hmm_test_cpp
- make cpp_no_sse - build/hmm_test_cpp_no_sse

View File

@@ -1,6 +1,8 @@
# Understanding the structure of Handmade Math # Understanding the structure of Handmade Math
Most of the functions in Handmade Math are very short, and all are the kind of functions you want to be easily inlined for performance. Because of this, all functions in Handmade Math are defined with `HMM_INLINE`, which is defined as `static inline`. 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 # Quick style guide
@@ -12,7 +14,7 @@ Most of the functions in Handmade Math are very short, and all are the kind of f
0.5f; 0.5f;
1.0f; 1.0f;
3.14159f; 3.14159f;
// Bad // Bad
1.f 1.f
.0f .0f

File diff suppressed because it is too large Load Diff

View File

@@ -10,9 +10,6 @@ To get started, go download [the latest release](https://github.com/HandmadeMath
Version | Changes | Version | Changes |
----------------|----------------| ----------------|----------------|
**1.11.1** | Added HMM_PREFIX macro to a few functions that were missing it. |
**1.11.0** | Added ability to customize or remove the default `HMM_` prefix on function names by defining a macro called `HMM_PREFIX(name)`. |
**1.10.1** | Removed stdint.h, this doesn't exist on some really old compilers and we didn't really use it anyways. |
**1.10.0** | Made HMM_Perspective use vertical FOV instead of horizontal FOV for consistency with other graphics APIs. | **1.10.0** | Made HMM_Perspective use vertical FOV instead of horizontal FOV for consistency with other graphics APIs. |
**1.9.0** | Added SSE versions of quaternion operations. | **1.9.0** | Added SSE versions of quaternion operations. |
**1.8.0** | Added fast vector normalization routines that use fast inverse square roots. **1.8.0** | Added fast vector normalization routines that use fast inverse square roots.

View File

@@ -1,5 +1,3 @@
#ifndef WITHOUT_COVERAGE #define HANDMADE_MATH_IMPLEMENTATION
#include "HandmadeTest.h" #define HANDMADE_MATH_NO_INLINE
#endif
#include "../HandmadeMath.h" #include "../HandmadeMath.h"

View File

@@ -1,12 +0,0 @@
#define HMM_PREFIX(name) WOW_##name
#define HANDMADE_MATH_IMPLEMENTATION
#define HANDMADE_MATH_NO_INLINE
#include "../HandmadeMath.h"
int main() {
hmm_vec4 a = WOW_Vec4(1, 2, 3, 4);
hmm_vec4 b = WOW_Vec4(5, 6, 7, 8);
WOW_Add(a, b);
}

View File

@@ -4,46 +4,19 @@
This is Handmade Math's test framework. It is fully compatible with both C This is Handmade Math's test framework. It is fully compatible with both C
and C++, although it requires some compiler-specific features. 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 The basic way of creating a test is using the TEST macro, which registers a
single test to be run: single test to be run:
TEST(MyCategory, MyTestName) { TEST(MyCategory, MyTestName) {
// test code, including asserts/expects // test code, including asserts/expects
} }
Handmade Test also provides macros you can use to check the coverage of The main function of your test code should then call hmt_run_all_tests and
important parts of your code. Define a coverage case by using the COVERAGE return the result:
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:
COVERAGE(MyCoverageCase, 3) int main() {
void MyFunction(int a, int b) { return hmt_run_all_tests();
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();
}
============================================================================= =============================================================================
@@ -67,7 +40,7 @@
#define HMT_RED "\033[31m" #define HMT_RED "\033[31m"
#define HMT_GREEN "\033[32m" #define HMT_GREEN "\033[32m"
#define HMT_ARRAY_SIZE 1024 #define HMT_INITIAL_ARRAY_SIZE 1024
typedef struct hmt_testresult_struct { typedef struct hmt_testresult_struct {
int count_cases; int count_cases;
@@ -84,137 +57,20 @@ typedef struct hmt_test_struct {
typedef struct hmt_category_struct { typedef struct hmt_category_struct {
const char* name; const char* name;
int num_tests; int num_tests;
int tests_capacity;
hmt_test* tests; hmt_test* tests;
} hmt_category; } hmt_category;
typedef struct hmt_covercase_struct { int hmt_num_categories = 0;
const char* name; int hmt_category_capacity = HMT_INITIAL_ARRAY_SIZE;
int expected_asserts; hmt_category* categories = 0;
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 _hmt_new_category(const char* name) {
hmt_category cat = { hmt_category cat = {
name, // name .name = name,
0, // num_tests .num_tests = 0,
(hmt_test*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_test)), // tests .tests_capacity = HMT_INITIAL_ARRAY_SIZE,
.tests = (hmt_test*) malloc(HMT_INITIAL_ARRAY_SIZE * sizeof(hmt_test))
}; };
return cat; return cat;
@@ -222,105 +78,60 @@ hmt_category _hmt_new_category(const char* name) {
hmt_test _hmt_new_test(const char* name, hmt_test_func func) { hmt_test _hmt_new_test(const char* name, hmt_test_func func) {
hmt_test test = { hmt_test test = {
name, // name .name = name,
func, // func .func = func
}; };
return test; return test;
} }
hmt_covercase _hmt_new_covercase(const char* name, int expected) { int hmt_register_test(const char* category, const char* name, hmt_test_func func) {
hmt_covercase covercase = {
name, // name
expected, // expected_asserts
0, // actual_asserts
(int*) malloc(HMT_ARRAY_SIZE * sizeof(int)), // asserted_lines
};
return covercase;
}
void _hmt_register_test(const char* category, const char* name, hmt_test_func func) {
// initialize categories array if not initialized // initialize categories array if not initialized
if (!_hmt_categories) { if (!categories) {
_hmt_categories = (hmt_category*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_category)); categories = (hmt_category*) malloc(hmt_category_capacity * sizeof(hmt_category));
} }
// Find the matching category, if possible // Find the matching category, if possible
int cat_index; int cat_index;
for (cat_index = 0; cat_index < _hmt_num_categories; cat_index++) { for (cat_index = 0; cat_index < hmt_num_categories; cat_index++) {
if (strcmp(_hmt_categories[cat_index].name, category) == 0) { if (strcmp(categories[cat_index].name, category) == 0) {
break; break;
} }
} }
// Add a new category if necessary // Expand the array of categories if necessary
if (cat_index >= _hmt_num_categories) { if (cat_index >= hmt_category_capacity) {
_hmt_categories[cat_index] = _hmt_new_category(category); // TODO: If/when we ever split HandmadeTest off into its own package,
_hmt_num_categories++; // we should start with a smaller initial capacity and dynamically expand.
} }
hmt_category* cat = &_hmt_categories[cat_index]; // Add a new category if necessary
if (cat_index >= hmt_num_categories) {
categories[cat_index] = _hmt_new_category(category);
hmt_num_categories++;
}
hmt_category* cat = &categories[cat_index];
// Add the test to the category // 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->tests[cat->num_tests] = _hmt_new_test(name, func);
cat->num_tests++; 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; 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 hmt_run_all_tests() {
int count_alltests = 0; int count_alltests = 0;
int count_allfailedtests = 0; // failed test cases int count_allfailedtests = 0; // failed test cases
int count_allfailures = 0; // failed asserts int count_allfailures = 0; // failed asserts
for (int i = 0; i < _hmt_num_categories; i++) { for (int i = 0; i < hmt_num_categories; i++) {
hmt_category cat = _hmt_categories[i]; hmt_category cat = categories[i];
int count_catfailedtests = 0; int count_catfailedtests = 0;
int count_catfailures = 0; int count_catfailures = 0;
printf("\n%s:\n", cat.name); printf("\n%s:\n", cat.name);
@@ -331,8 +142,8 @@ int hmt_run_all_tests() {
printf(" %s:", test.name); printf(" %s:", test.name);
hmt_testresult result = { hmt_testresult result = {
0, // count_cases .count_cases = 0,
0, // count_failures .count_failures = 0
}; };
test.func(&result); test.func(&result);
@@ -366,33 +177,87 @@ int hmt_run_all_tests() {
return (count_allfailedtests > 0); return (count_allfailedtests > 0);
} }
int hmt_check_all_coverage() { #define _HMT_TEST_FUNCNAME(category, name) category ## _ ## name
printf("Coverage:\n"); #define _HMT_TEST_FUNCNAME_INIT(category, name) category ## _ ## name ## _init
int count_failures = 0; #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)
for (int i = 0; i < _hmt_num_covercases; i++) { #define _HMT_CASE_START() \
hmt_covercase covercase = _hmt_covercases[i]; _result->count_cases++;
if (covercase.expected_asserts != covercase.actual_asserts) { #define _HMT_CASE_FAIL() \
count_failures++; _result->count_failures++; \
printf("%s: " HMT_RED "FAIL (expected %d asserts, got %d)\n" HMT_RESET, covercase.name, covercase.expected_asserts, covercase.actual_asserts); printf("\n - " HMT_RED "[FAIL] (%d) " HMT_RESET, __LINE__);
}
}
if (count_failures > 0) { /*
printf("\n"); * Asserts and expects
printf(HMT_RED); */
} else { #define HMT_EXPECT_TRUE(_actual) do { \
printf(HMT_GREEN); _HMT_CASE_START(); \
} if (!(_actual)) { \
printf("%d coverage cases tested, %d failures\n", _hmt_num_covercases, count_failures); _HMT_CASE_FAIL(); \
printf(HMT_RESET); printf("Expected true but got something false"); \
} \
} while (0)
printf("\n"); #define HMT_EXPECT_FALSE(_actual) do { \
_HMT_CASE_START(); \
if (_actual) { \
_HMT_CASE_FAIL(); \
printf("Expected false but got something true"); \
} \
} while (0)
return (count_failures > 0); #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)
#endif // HANDMADE_TEST_IMPLEMENTATION_GUARD #define HMT_EXPECT_NEAR(_actual, _expected, _epsilon) do { \
#endif // HANDMADE_TEST_IMPLEMENTATION _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

View File

@@ -1,18 +1,13 @@
BUILD_DIR=./build BUILD_DIR=build
CXXFLAGS+=-g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers -Wfloat-equal CXXFLAGS+=-g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers
all: c c_no_sse cpp cpp_no_sse build_c_without_coverage build_cpp_without_coverage build_cpp_different_prefix all: c c_no_sse cpp cpp_no_sse
build_all: build_c build_c_no_sse build_cpp build_cpp_no_sse
clean: clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)
c: build_c c: HandmadeMath.c test_impl
$(BUILD_DIR)/hmm_test_c
build_c: HandmadeMath.c test_impl
@echo "\nCompiling in C mode" @echo "\nCompiling in C mode"
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR)\ cd $(BUILD_DIR)\
@@ -21,10 +16,7 @@ build_c: HandmadeMath.c test_impl
-lm \ -lm \
&& $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm && $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm
c_no_sse: build_c_no_sse c_no_sse: HandmadeMath.c test_impl
$(BUILD_DIR)/hmm_test_c_no_sse
build_c_no_sse: HandmadeMath.c test_impl
@echo "\nCompiling in C mode (no SSE)" @echo "\nCompiling in C mode (no SSE)"
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \ cd $(BUILD_DIR) \
@@ -34,10 +26,7 @@ build_c_no_sse: HandmadeMath.c test_impl
-lm \ -lm \
&& $(CC) -ohmm_test_c_no_sse HandmadeMath.o hmm_test.o -lm && $(CC) -ohmm_test_c_no_sse HandmadeMath.o hmm_test.o -lm
cpp: build_cpp cpp: HandmadeMath.cpp test_impl
$(BUILD_DIR)/hmm_test_cpp
build_cpp: HandmadeMath.cpp test_impl
@echo "\nCompiling in C++ mode" @echo "\nCompiling in C++ mode"
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \ cd $(BUILD_DIR) \
@@ -45,10 +34,7 @@ build_cpp: HandmadeMath.cpp test_impl
-DHANDMADE_MATH_CPP_MODE \ -DHANDMADE_MATH_CPP_MODE \
../HandmadeMath.cpp ../hmm_test.cpp ../HandmadeMath.cpp ../hmm_test.cpp
cpp_no_sse: build_cpp_no_sse cpp_no_sse: HandmadeMath.cpp test_impl
$(BUILD_DIR)/hmm_test_cpp_no_sse
build_cpp_no_sse: HandmadeMath.cpp test_impl
@echo "\nCompiling in C++ mode (no SSE)" @echo "\nCompiling in C++ mode (no SSE)"
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \ cd $(BUILD_DIR) \
@@ -57,29 +43,3 @@ build_cpp_no_sse: HandmadeMath.cpp test_impl
../HandmadeMath.cpp ../hmm_test.cpp ../HandmadeMath.cpp ../hmm_test.cpp
test_impl: hmm_test.cpp hmm_test.c test_impl: hmm_test.cpp hmm_test.c
build_c_without_coverage: HandmadeMath.c test_impl
@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
build_cpp_different_prefix: HandmadeMath.cpp
@echo "\nCompiling C++ with different prefix"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_different_prefix \
-DHANDMADE_MATH_CPP_MODE -DDIFFERENT_PREFIX \
../HandmadeMathDifferentPrefix.cpp

View File

@@ -4,13 +4,8 @@ You can compile and run the tests yourself by running:
``` ```
make make
``` build/hmm_test_c
build/hmm_test_c_no_sse
To run a specific test configuration, run one of: build/hmm_test_cpp
build/hmm_test_cpp_no_sse
```
make c
make c_no_sse
make cpp
make cpp_no_sse
``` ```

View File

@@ -37,7 +37,7 @@ TEST(Addition, Vec3)
hmm_vec3 result = HMM_AddVec3(v3_1, v3_2); hmm_vec3 result = HMM_AddVec3(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 5.0f); EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 7.0f); EXPECT_FLOAT_EQ(result.Y, 7.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f); EXPECT_FLOAT_EQ(result.Z, 9.0f);
} }
#ifdef __cplusplus #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_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 v4_2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
{ {
hmm_vec4 result = HMM_AddVec4(v4_1, v4_2); hmm_vec4 result = HMM_AddVec4(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 6.0f); EXPECT_FLOAT_EQ(result.X, 6.0f);

View File

@@ -15,9 +15,6 @@ TEST(Equality, Vec2)
EXPECT_TRUE(a == b); EXPECT_TRUE(a == b);
EXPECT_FALSE(a == c); EXPECT_FALSE(a == c);
EXPECT_FALSE(a != b);
EXPECT_TRUE(a != c);
#endif #endif
} }
@@ -36,9 +33,6 @@ TEST(Equality, Vec3)
EXPECT_TRUE(a == b); EXPECT_TRUE(a == b);
EXPECT_FALSE(a == c); EXPECT_FALSE(a == c);
EXPECT_FALSE(a != b);
EXPECT_TRUE(a != c);
#endif #endif
} }
@@ -57,8 +51,5 @@ TEST(Equality, Vec4)
EXPECT_TRUE(a == b); EXPECT_TRUE(a == b);
EXPECT_FALSE(a == c); EXPECT_FALSE(a == c);
EXPECT_FALSE(a != b);
EXPECT_TRUE(a != c);
#endif #endif
} }

View File

@@ -4,9 +4,9 @@ TEST(Initialization, Vectors)
{ {
// //
// Test vec2 // Test vec2
// //
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f); hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f);
hmm_vec2 v2i = HMM_Vec2i(1, 2); hmm_vec2 v2i = HMM_Vec2(1, 2);
EXPECT_FLOAT_EQ(v2.X, 1.0f); EXPECT_FLOAT_EQ(v2.X, 1.0f);
EXPECT_FLOAT_EQ(v2.Y, 2.0f); EXPECT_FLOAT_EQ(v2.Y, 2.0f);

View File

@@ -15,7 +15,7 @@ TEST(Projection, Orthographic)
TEST(Projection, Perspective) TEST(Projection, Perspective)
{ {
hmm_mat4 projection = HMM_Perspective(HMM_ToRadians(90.0f), 2.0f, 5.0f, 15.0f); hmm_mat4 projection = HMM_Perspective(90.0f, 2.0f, 5.0f, 15.0f);
{ {
hmm_vec3 original = HMM_Vec3(5.0f, 5.0f, -15.0f); hmm_vec3 original = HMM_Vec3(5.0f, 5.0f, -15.0f);

View File

@@ -76,7 +76,7 @@ TEST(QuaternionOps, Slerp)
EXPECT_FLOAT_EQ(result.W, 0.86602540f); EXPECT_FLOAT_EQ(result.W, 0.86602540f);
} }
TEST(QuaternionOps, QuatToMat4) TEST(QuaternionOps, ToMat4)
{ {
const float abs_error = 0.0001f; const float abs_error = 0.0001f;
@@ -105,67 +105,6 @@ TEST(QuaternionOps, QuatToMat4)
EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error); EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error);
} }
TEST(QuaternionOps, Mat4ToQuat)
{
const float abs_error = 0.0001f;
// Rotate 90 degrees on the X axis
{
hmm_mat4 m = HMM_Rotate(HMM_ToRadians(90.0f), HMM_Vec3(1, 0, 0));
hmm_quaternion result = HMM_Mat4ToQuaternion(m);
float cosf = 0.707107f; // cos(90/2 degrees)
float sinf = 0.707107f; // sin(90/2 degrees)
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);
}
// Rotate 90 degrees on the Y axis (axis not normalized, just for fun)
{
hmm_mat4 m = HMM_Rotate(HMM_ToRadians(90.0f), HMM_Vec3(0, 2, 0));
hmm_quaternion result = HMM_Mat4ToQuaternion(m);
float cosf = 0.707107f; // cos(90/2 degrees)
float sinf = 0.707107f; // sin(90/2 degrees)
EXPECT_NEAR(result.X, 0.0f, abs_error);
EXPECT_NEAR(result.Y, sinf, abs_error);
EXPECT_NEAR(result.Z, 0.0f, abs_error);
EXPECT_NEAR(result.W, cosf, abs_error);
}
// Rotate 90 degrees on the Z axis
{
hmm_mat4 m = HMM_Rotate(HMM_ToRadians(90.0f), HMM_Vec3(0, 0, 1));
hmm_quaternion result = HMM_Mat4ToQuaternion(m);
float cosf = 0.707107f; // cos(90/2 degrees)
float sinf = 0.707107f; // sin(90/2 degrees)
EXPECT_NEAR(result.X, 0.0f, abs_error);
EXPECT_NEAR(result.Y, 0.0f, abs_error);
EXPECT_NEAR(result.Z, sinf, abs_error);
EXPECT_NEAR(result.W, cosf, abs_error);
}
// Rotate 45 degrees on the X axis (this hits case 4)
{
hmm_mat4 m = HMM_Rotate(HMM_ToRadians(45.0f), HMM_Vec3(1, 0, 0));
hmm_quaternion result = HMM_Mat4ToQuaternion(m);
float cosf = 0.9238795325f; // cos(90/2 degrees)
float sinf = 0.3826834324f; // sin(90/2 degrees)
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);
}
}
TEST(QuaternionOps, FromAxisAngle) TEST(QuaternionOps, FromAxisAngle)
{ {
hmm_vec3 axis = HMM_Vec3(1.0f, 0.0f, 0.0f); hmm_vec3 axis = HMM_Vec3(1.0f, 0.0f, 0.0f);
@@ -176,4 +115,4 @@ TEST(QuaternionOps, FromAxisAngle)
EXPECT_FLOAT_EQ(result.Y, 0.0f); EXPECT_FLOAT_EQ(result.Y, 0.0f);
EXPECT_FLOAT_EQ(result.Z, 0.0f); EXPECT_FLOAT_EQ(result.Z, 0.0f);
EXPECT_NEAR(result.W, 0.707107f, FLT_EPSILON * 2); EXPECT_NEAR(result.W, 0.707107f, FLT_EPSILON * 2);
} }

View File

@@ -7,33 +7,33 @@ TEST(SSE, LinearCombine)
hmm_mat4 MatrixOne = HMM_Mat4d(2.0f); hmm_mat4 MatrixOne = HMM_Mat4d(2.0f);
hmm_mat4 MatrixTwo = HMM_Mat4d(4.0f); hmm_mat4 MatrixTwo = HMM_Mat4d(4.0f);
hmm_mat4 Result; hmm_mat4 Result;
Result.Columns[0] = HMM_LinearCombineSSE(MatrixOne.Columns[0], MatrixTwo); Result.Columns[0] = HMM_LinearCombineSSE(MatrixOne.Columns[0], MatrixTwo);
Result.Columns[1] = HMM_LinearCombineSSE(MatrixOne.Columns[1], MatrixTwo); Result.Columns[1] = HMM_LinearCombineSSE(MatrixOne.Columns[1], MatrixTwo);
Result.Columns[2] = HMM_LinearCombineSSE(MatrixOne.Columns[2], MatrixTwo); Result.Columns[2] = HMM_LinearCombineSSE(MatrixOne.Columns[2], MatrixTwo);
Result.Columns[3] = HMM_LinearCombineSSE(MatrixOne.Columns[3], 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][0], 8.0f);
EXPECT_FLOAT_EQ(Result.Elements[0][1], 0.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][2], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[0][3], 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][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][2], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[1][3], 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][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][2], 8.0f);
EXPECT_FLOAT_EQ(Result.Elements[2][3], 0.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][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][2], 0.0f);
EXPECT_FLOAT_EQ(Result.Elements[3][3], 8.0f); EXPECT_FLOAT_EQ(Result.Elements[3][3], 8.0f);
} }
} }
#endif #endif

View File

@@ -24,25 +24,10 @@ TEST(ScalarMath, Trigonometry)
EXPECT_NEAR(HMM_TanF(HMM_PI32), 0.0f, trigAbsError); EXPECT_NEAR(HMM_TanF(HMM_PI32), 0.0f, trigAbsError);
EXPECT_NEAR(HMM_TanF(-HMM_PI32 / 4), -1.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- // This isn't the most rigorous because we're really just sanity-
// checking that things work by default. // checking that things work by default.
} }
TEST(ScalarMath, ToDegrees)
{
EXPECT_FLOAT_EQ(HMM_ToDegrees(0.0f), 0.0f);
EXPECT_FLOAT_EQ(HMM_ToDegrees(HMM_PI32), 180.0f);
EXPECT_FLOAT_EQ(HMM_ToDegrees(-HMM_PI32), -180.0f);
}
TEST(ScalarMath, ToRadians) TEST(ScalarMath, ToRadians)
{ {
EXPECT_FLOAT_EQ(HMM_ToRadians(0.0f), 0.0f); EXPECT_FLOAT_EQ(HMM_ToRadians(0.0f), 0.0f);
@@ -50,18 +35,6 @@ TEST(ScalarMath, ToRadians)
EXPECT_FLOAT_EQ(HMM_ToRadians(-180.0f), -HMM_PI32); 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) TEST(ScalarMath, SquareRoot)
{ {
EXPECT_FLOAT_EQ(HMM_SquareRootF(16.0f), 4.0f); EXPECT_FLOAT_EQ(HMM_SquareRootF(16.0f), 4.0f);
@@ -75,27 +48,27 @@ TEST(ScalarMath, RSquareRootF)
TEST(ScalarMath, Power) TEST(ScalarMath, Power)
{ {
EXPECT_FLOAT_EQ(HMM_Power(2.0f, 0), 1.0f); 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); EXPECT_FLOAT_EQ(HMM_Power(2.0f, -2), 0.25f);
} }
TEST(ScalarMath, PowerF) TEST(ScalarMath, PowerF)
{ {
EXPECT_FLOAT_EQ(HMM_PowerF(2.0f, 0.0f), 1.0f); EXPECT_FLOAT_EQ(HMM_PowerF(2.0f, 0), 1.0f);
EXPECT_NEAR(HMM_PowerF(2.0f, 4.1f), 17.148376f, 0.0001f); EXPECT_NEAR(HMM_PowerF(2.0f, 4.1), 17.148376f, 0.0001f);
EXPECT_NEAR(HMM_PowerF(2.0f, -2.5f), 0.176777f, 0.0001f); EXPECT_NEAR(HMM_PowerF(2.0f, -2.5), 0.176777f, 0.0001f);
} }
TEST(ScalarMath, Lerp) TEST(ScalarMath, Lerp)
{ {
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.0f, 2.0f), -2.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, 0.5f, 2.0f), 0.0f);
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 1.0f, 2.0f), 2.0f); EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 1.0f, 2.0f), 2.0f);
} }
TEST(ScalarMath, Clamp) TEST(ScalarMath, Clamp)
{ {
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, 0.0f, 2.0f), 0.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);
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);
} }

View File

@@ -17,23 +17,21 @@ TEST(Transformations, Rotate)
{ {
hmm_vec3 original = HMM_Vec3(1.0f, 1.0f, 1.0f); hmm_vec3 original = HMM_Vec3(1.0f, 1.0f, 1.0f);
float angle = HMM_ToRadians(90.0f); hmm_mat4 rotateX = HMM_Rotate(90, HMM_Vec3(1, 0, 0));
hmm_mat4 rotateX = HMM_Rotate(angle, HMM_Vec3(1, 0, 0));
hmm_vec4 rotatedX = HMM_MultiplyMat4ByVec4(rotateX, HMM_Vec4v(original, 1)); hmm_vec4 rotatedX = HMM_MultiplyMat4ByVec4(rotateX, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(rotatedX.X, 1.0f); EXPECT_FLOAT_EQ(rotatedX.X, 1.0f);
EXPECT_FLOAT_EQ(rotatedX.Y, -1.0f); EXPECT_FLOAT_EQ(rotatedX.Y, -1.0f);
EXPECT_FLOAT_EQ(rotatedX.Z, 1.0f); EXPECT_FLOAT_EQ(rotatedX.Z, 1.0f);
EXPECT_FLOAT_EQ(rotatedX.W, 1.0f); EXPECT_FLOAT_EQ(rotatedX.W, 1.0f);
hmm_mat4 rotateY = HMM_Rotate(angle, HMM_Vec3(0, 1, 0)); hmm_mat4 rotateY = HMM_Rotate(90, HMM_Vec3(0, 1, 0));
hmm_vec4 rotatedY = HMM_MultiplyMat4ByVec4(rotateY, HMM_Vec4v(original, 1)); hmm_vec4 rotatedY = HMM_MultiplyMat4ByVec4(rotateY, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(rotatedY.X, 1.0f); EXPECT_FLOAT_EQ(rotatedY.X, 1.0f);
EXPECT_FLOAT_EQ(rotatedY.Y, 1.0f); EXPECT_FLOAT_EQ(rotatedY.Y, 1.0f);
EXPECT_FLOAT_EQ(rotatedY.Z, -1.0f); EXPECT_FLOAT_EQ(rotatedY.Z, -1.0f);
EXPECT_FLOAT_EQ(rotatedY.W, 1.0f); EXPECT_FLOAT_EQ(rotatedY.W, 1.0f);
hmm_mat4 rotateZ = HMM_Rotate(angle, HMM_Vec3(0, 0, 1)); hmm_mat4 rotateZ = HMM_Rotate(90, HMM_Vec3(0, 0, 1));
hmm_vec4 rotatedZ = HMM_MultiplyMat4ByVec4(rotateZ, HMM_Vec4v(original, 1)); hmm_vec4 rotatedZ = HMM_MultiplyMat4ByVec4(rotateZ, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(rotatedZ.X, -1.0f); EXPECT_FLOAT_EQ(rotatedZ.X, -1.0f);
EXPECT_FLOAT_EQ(rotatedZ.Y, 1.0f); EXPECT_FLOAT_EQ(rotatedZ.Y, 1.0f);

View File

@@ -3,7 +3,7 @@
TEST(VectorOps, LengthSquared) TEST(VectorOps, LengthSquared)
{ {
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f); 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); hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, 1.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec2(v2), 5.0f); EXPECT_FLOAT_EQ(HMM_LengthSquaredVec2(v2), 5.0f);
@@ -37,7 +37,7 @@ TEST(VectorOps, Length)
TEST(VectorOps, Normalize) TEST(VectorOps, Normalize)
{ {
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f); 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); hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, -1.0f);
{ {

View File

@@ -1,9 +1,7 @@
#include "HandmadeTest.h"
#include "hmm_test.h" #include "hmm_test.h"
int main() int main()
{ {
int tests_failed = hmt_run_all_tests(); return hmt_run_all_tests();
int coverage_failed = hmt_check_all_coverage();
return tests_failed || coverage_failed;
} }

View File

@@ -1,9 +1,6 @@
#include <float.h> #include <float.h>
#define HANDMADE_TEST_IMPLEMENTATION
#include "HandmadeTest.h" #include "HandmadeTest.h"
#undef COVERAGE // Make sure we don't double-define initializers from the header part
#include "../HandmadeMath.h" #include "../HandmadeMath.h"
#include "categories/ScalarMath.h" #include "categories/ScalarMath.h"

View File

@@ -1,27 +0,0 @@
@echo off
if "%1%"=="travis" (
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\Tools\VsDevCmd.bat" -host_arch=amd64 -arch=amd64
) else (
where /q cl
if ERRORLEVEL 1 (
for /f "delims=" %%a in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -find VC\Auxiliary\Build\vcvarsall.bat') do (%%a x64)
)
)
if not exist "build" mkdir build
pushd build
cl /Fehmm_test_c.exe ..\HandmadeMath.c ..\hmm_test.c || popd && exit /B
hmm_test_c
cl /Fehmm_test_c_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.c ..\hmm_test.c || popd && exit /B
hmm_test_c_no_sse
cl /Fehmm_test_cpp.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || popd && exit /B
hmm_test_cpp
cl /Fehmm_test_cpp_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.cpp ..\hmm_test.cpp || popd && exit /B
hmm_test_cpp_no_sse
popd