Compare commits

...

56 Commits

Author SHA1 Message Date
Ben Visness
142ba3cd9d Align backslashes for great aesthetics (very important) 2025-02-24 17:45:35 -06:00
Ben Visness
8c2ac269ba Redo test scripts 2025-02-23 20:33:06 -06:00
Ben Visness
736ebaaf23 Test and fix _Generic 2025-02-23 20:33:06 -06:00
Ben Visness
bdc7dd2a51 Merge pull request #172 from jonasgf/whitespace
Remove trailing whitespace and extra newlines at end of file
2024-05-28 09:46:45 -05:00
Ben Visness
b4ce44823b Merge pull request #171 from jonasgf/missing-braces
Ignore missing braces warning for all GCC versions
2024-05-28 09:46:22 -05:00
Jonas
2901e70ca3 Remove trailing whitespace and extra newlines at end of file 2024-04-27 22:56:11 +02:00
Jonas
21b4a0d209 Ignore missing braces warning for all GCC versions 2024-04-27 22:46:15 +02:00
Ben Visness
43836aa3a6 Merge pull request #170 from B-Y-P/master
Add HMM_QFromNormPair() and HMM_QFromVecPair()
2024-04-11 11:08:32 -05:00
BYP
bdc04881de Add HMM_QFromNormPair() and HMM_QFromVecPair() 2024-04-08 21:21:54 -04:00
Ben Visness
322826bcee Merge pull request #169 from Jack-Punter/neon_support
Neon support
2023-12-15 20:14:20 -06:00
jack punter
4e1e97522d Address Ben's changes 2023-12-14 21:39:50 +00:00
Jack Punter
6603c796cc Update test Makefile to use NO_SIMD over NO_SSE 2023-12-12 01:53:43 +00:00
Jack Punter
623215b228 NEON Quaternion Multiply 2023-12-12 01:47:01 +00:00
Jack Punter
fcc510f767 Fix scalar 2023-12-12 01:42:37 +00:00
Jack Punter
133a595b6f Better Neon tranpose
vld can de-interleave up to 4-float element structures in one go into multiple registers. This allows us to load each column of the matrix and put each element into a corresponding vector, essentially doing the entire transpose in 1 instruction

Fixed it
2023-12-12 01:42:37 +00:00
Jack Punter
5f20d693c9 Add Neon implementations for all but Quaternion multiply 2023-12-11 22:57:19 +00:00
Ben Visness
e210d8729b Add HMM_RotateV2 2023-11-03 11:34:49 -05:00
dev_dwarf
a1c84320f9 Style tweaks to RotateV3Q + axis angle variant 2023-10-31 13:09:20 -06:00
Olivier Perret
8df5da57f5 Clean trailing whitespace in HandmadeMath.h 2023-10-29 18:33:31 +01:00
Olivier Perret
149c18d449 Add HMM_RotateQV3(), for rotating a vec3 by a quaternion 2023-10-29 18:32:09 +01:00
Olivier Perret
98748f702c Provide const versions of operator[] (#166)
This makes it possible use to do something like

const HMM_Vec3 v{1,2,3};
float val = v[1];
2023-10-27 13:15:58 -05:00
Logan Forman
6cf6226c57 remove most references from operators (#164) 2023-08-05 12:57:56 -04:00
Ben Visness
aaa767bf0b Update README.md 2023-02-20 13:29:24 -06:00
Ben Visness
422bc588e9 Fix inverse perspective 2023-02-20 13:03:46 -06:00
Ben Visness
beb837a3c6 Tweak docs, add tests, find bugs 2023-02-02 19:18:24 -06:00
Ben Visness
50ab55b3bc Rewrite the update tool in Python
Less than 200 lines, properly cross platform, actually outputs error
messages if things break, better flag handling. Everyone has
Python anyway.
2023-01-27 03:39:38 -06:00
Ben Visness
22d743ce3d Change naming convention for NO/ZO (the update tool needs updating) 2023-01-26 22:27:09 -06:00
Logan Forman
d4918a514e Drop Projection Matrix Config; Make explicit. (#154)
* Add N0/Z0 projection

Remove configuration macro

* Update update_hmm.c

Co-authored-by: Ben Visness <bvisness@users.noreply.github.com>
2023-01-26 21:01:31 -06:00
Logan Forman
37aa3fa6a0 Unroll sse (#153)
* Unroll loops and SSE consistency

* Fix tranposes
2023-01-26 20:56:28 -06:00
dev_dwarf
7e493a5481 Fix LH perspective matrix
Off by a sign before.
2023-01-26 19:55:21 -06:00
Ben Visness
f106a0f5f3 Style and docs pass for release
Remove V2I, V3I, V4I (and style changes)

Totally useless.

Add update tool, update docs

Tweak docs

Create ci.yml

Big style pass

Maybe fix CI on Windows

Report coverage errors

Fix a missing coverage case

Try setting up MSVC another way

Update readmes

Fix remaining use of the name UpdateTool
2023-01-22 21:46:22 -06:00
Logan Forman
c24e4ff873 HMM2.0 (#149)
These changes were all made by @dev-dwarf. Many thanks for his work on this!

* Renaming

* First Pass on 2.0UpdateTool

* Another pass on UpdateTool, changed name

* Another pass on UpdateTool, changed name

* Do Renaming

* Working on Angles Consistency

* Passing Coverage

* Remove unused arc-tangent functions

* Change macro defaults

By default if user is overriding trig functions assume their input and internal units are the same.

* wrap in AngleDeg instead of AngleRad

* Remove HMM_PREFIX configuration

* Fix for Slerp

https://discord.com/channels/239737791225790464/489148972305350656/1055167647274246265

Justified by most implementations of Slerp. EX: http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/

* Handedness Changes

* More renaming. C11 _Generics

Generics enable by default when available (see lines 97-104). User can also force them by defining HANDMADE_MATH_C11_GENERICS

Also fixed some missed things w.r.t renaming. My old tool didn't catch cases like HMM_MultiplyVec3f needing to be HMM_MulV3F instead of HMM_MulV3f.

* Reuse more SSE codepaths for Quaternions

Also improved quaternion tests. More work could be done here, see discussion here about optimizing slerp: https://discord.com/channels/239737791225790464/489148972305350656/1055167647274246265

* Just saving these alternate versions of SLerp

* Reduce V4/M4 Linear Comb. codepaths

* Simple implementation of 2x2 and 3x3 basic matrix operations.

Also renamed Transpose to TransposeM4, so that we can have TransposeM2,M3

* Norm is dead! Long live Norm!

As can be seen from the tests, precision has declined quite a bit from using the FastNorm implementations for various things. We can only guarantee about 0.001f precision for anything where a norm happens now. If this is undesired we can change back easily.

* Started work on Matrix Inverses

TODO: Tests for simple 4x4 Inverses

* Matrix Inverses + Tests

* Generics for Matrices and Rename MXd/f functions

* Fixes + Better Output for UpdateTool

* I think I count as a contributor : )

* Ported UpdateTool, Inlined my library code.

* Moved tool to different repo

https://github.com/dev-dwarf/HMM2.0UpdateTool

* Remove small test change

* Found some more references to atan functions

* Standardize angle function names, use short names

* Remove other slerp comments

* woops that wasnt meant to be commited.

* Finish changing ToRadians to ToRad

* Fix [] overloads

per https://discord.com/channels/239737791225790464/600063880533770251/1051600188302692402

* Tests for 2x2, 3x3 Matrices and Other Matrix Ops

* Add an option to use Z: [0, 1] range for projection matrices.

This will make HMM more convenient to use with other graphics APIs such as Direct3d and Metal.

* Update test imports

* #if should've been #ifdef!

* Implement requested changes
2023-01-22 17:34:50 -06:00
Zak Strange
ba5405ac0f Update README.md 2021-08-31 17:11:42 -07:00
Zak Strange
d69a859d73 Fully inlined HandmadeMath.h (#139)
* Fully inlined HandmadeMath.h, renamed test.bat to run_test_msvc.bat, and introduced run_test_clang.bat

* General Cleanup
2021-08-31 17:10:46 -07:00
strangezak
8c18186b3b Removed Unnecessary Square Root from InverseQuaternion. Closes #136 2021-08-31 09:28:02 -07:00
Tim Gates
5f816bf9b3 docs: fix simple typo, percision -> precision (#137)
There is a small typo in README.md.

Should read `precision` rather than `percision`.
2021-08-31 09:22:29 -07:00
Jørgen P. Tjernø
c5bc802042 Suppress two warnings on clang 12 (#138)
Building with clang 12 with -Wextra, the following two warnings are
generated:

```
HandmadeMath.h:1167:25: warning: missing field 'Y' initializer [-Wmissing-field-initializers]
    hmm_vec2 Result = {0};
                        ^
HandmadeMath.h:1167:24: warning: suggest braces around initialization of subobject [-Wmissing-braces]
```

This expands the `-Wmissing-braces` ignore to also target clang, and adds an
ignore for `-Wmissing-field-initializers`
2021-08-31 09:37:54 -05:00
Ben Visness
43afc87fa7 Remove non-functioning issue link 2021-03-24 10:04:17 -05:00
Ben Visness
5bbac2167e Update version and changelog 2021-03-24 10:02:08 -05:00
Wayde Reitsma
655c662528 Add brackets around HMM_MIN, HMM_MAX, and HMM_MOD (#133)
* Add brackets around HMM_MIN and HMM_MAX

* Add brackets around HMM_MOD
2021-03-24 09:54:13 -05:00
Zak Strange
1f0c6ba493 Update Docs. 2021-03-09 16:37:00 -08:00
Zak Strange
1d82b4f0bc Unary minus vectors (#130)
* Unary Minus operator for vec2, vec3, and vec4

* Update README.md

Co-authored-by: zak <zak@DESKTOP-V1AQ0IT>
2021-03-06 18:39:17 -06:00
Zak Strange
2fa0b36715 Add HMM_STATIC option to statically link instead of extern (#127)
Co-authored-by: zak <zak@DESKTOP-V1AQ0IT>
2021-02-17 19:36:05 -08:00
Ben Visness
ad169e649c Make HMM_Clamp branchless in optimized builds (#122) 2020-12-22 11:19:58 -06:00
Zak Strange
1900cc9275 Updated email in HandmadeMath.h 2020-07-09 18:22:22 -07:00
Ben Visness
ddb9971e71 Update README 2020-07-09 08:51:53 -05:00
GsxCasper
341a376a17 Added HMM_PREFIX macro to function implementations (#120) 2020-07-08 16:32:29 -05:00
Ben Visness
c825fe48cf Update version and release notes 2020-04-06 10:02:16 -05:00
Ben Visness
15bef820db Add ability to customize HMM_ prefix (#114)
* Add prefix macro and use it everywhere

* Add lightweight test for prefix

* Add a little doc blurb
2020-04-06 09:57:10 -05:00
Ben Visness
fe32f081f2 Suppress float equality warnings (#113)
* Add a macro to help with deprecations

* Suppress warnings about float equality
2020-04-06 09:55:40 -05:00
Zak Strange
785f19d4a7 Removed use of stdint.h (#110) 2020-01-11 17:13:09 -08:00
Ben Visness
a9b08b9147 Run tests on Linux, macOS, and Windows (#105)
* Try running tests on all three operating systems

* Try adding an MSVC build

* Make tests work on Windows

* Try reconfiguring Travis for this

* Maybe it's because we're in git bash

* Try explicitly doing something else for travis

* Remove a part I think is unnecessary

* Run the test EXEs as they compile
2019-07-31 17:22:33 -05:00
Ben Visness
f376f2a2a7 Add test coverage macros (#104)
* Add coverage features and add it, laboriously, to everything

* Fix easy tests

* Add tests for != operators

* Clean up test framework a little

* Add documentation of coverage macros

* Fix tests for mat4 to quaternion

* Slightly improve formatting of coverage output

* Trailing whitespace must die
2019-07-31 16:43:56 -05:00
Ben Visness
78e6feea82 Add HMM_Mat4ToQuaternion (#103)
* Add mat4 to quaternion method

* Capitalize variables
2019-07-31 16:38:03 -05:00
Zak Strange
21aa828a08 Fixed issue related to unsigned/signed-ness of HMM_Power (#102)
* Fixed issue related to unsigned/signed-ness of HMM_Power

* Fixes missing braces around initializer warning with -Weverything with GCC.
2019-07-17 14:48:59 -07:00
Ben Visness
93e56be543 Use vertical instead of horizontal FOV in HMM_Perspective (#101)
* Use vertical instead of horizontal FOV

* Update readme

* Fix tests
2019-07-10 11:29:51 -05:00
29 changed files with 6212 additions and 2853 deletions

34
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: CI
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
test:
name: Test on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v3
- uses: TheMrMilchmann/setup-msvc-dev@v2
with:
arch: x64
if: matrix.os == 'windows-latest'
- name: Test (Windows, MSVC)
run: ./run_test_msvc.bat
working-directory: ./test
if: matrix.os == 'windows-latest'
- name: Test (Windows, clang)
run: ./run_test_clang.bat
working-directory: ./test
if: matrix.os == 'windows-latest'
- name: Test (${{ matrix.os }})
run: make all
working-directory: ./test
if: matrix.os != 'windows-latest'

0
.gitmodules vendored
View File

View File

@@ -1,12 +0,0 @@
language: cpp
compiler:
- clang
- gcc
install:
- cd test
- make
script:
- build/hmm_test_c
- build/hmm_test_c_no_sse
- build/hmm_test_cpp
- build/hmm_test_cpp_no_sse

View File

@@ -1,43 +0,0 @@
# 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
* Float literals should have digits both before and after the decimal.
```cpp
// Good
0.0f;
0.5f;
1.0f;
3.14159f;
// Bad
1.f
.0f
```
* Put parentheses around the returned value:
```cpp
HINLINE float
HMM_MyFunction()
{
return (1.0f);
}
```
## 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)`.
It is fine for the overloaded versions to call the C versions.
* Only use operator overloading for analogous operators in C. That means `+` for vector addition is fine, but no using `^` for cross product or `|` for dot product.
* 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

@@ -1,52 +1,43 @@
# Handmade Math # Handmade Math
[![Build Status](https://travis-ci.org/HandmadeMath/Handmade-Math.svg?branch=master)](https://travis-ci.org/StrangeZak/Handmade-Math) A single-file, cross-platform, public domain graphics math library for both C and C++. Supports vectors, matrices, quaternions, and all the utilities you'd expect.
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/HandmadeMath/releases).
To get started, go download [the latest release](https://github.com/HandmadeMath/Handmade-Math/releases). > If you are upgrading to Handmade Math 2.0, save yourself some time and use our [automatic update tool](./update).
----- Here's what sets Handmade Math apart:
Version | Changes | - **A simple single-header library.** Just `#include "HandmadeMath.h"`.
----------------|----------------| - **Supports both C and C++.** While libraries like GLM only support C++, Handmade Math supports both C and C++, with convenient overloads wherever possible. For example, C++ codebases get operator overloading, and C11 codebases get `_Generic` versions of common operations.
**1.9.0** | Added SSE versions of quaternion operations. | - **Supports all graphics APIs.** Handmade Math has left- and right-handed versions of each operation, as well as support for zero-to-one and negative-one-to-one NDC conventions.
**1.8.0** | Added fast vector normalization routines that use fast inverse square roots. - **Swizzling, sort of.** Handmade Math's vector types use unions to provide several ways of accessing the same underlying data. For example, the components of an `HMM_Vec3` can be accessed as `XYZ`, `RGB`, or `UVW` - or subsets can be accessed like `.XY` and `.YZ`.
**1.7.1** | Changed operator[] to take a const ref int instead of an int. - **Your choice of angle unit.** While Handmade Math uses radians by default, you can configure it to use degrees or [turns](https://www.computerenhance.com/p/turns-are-better-than-radians) instead.
**1.7.0** | Renamed the 'Rows' member of hmm_mat4 to 'Columns'. Since our matrices are column-major, this should have been named 'Columns' from the start. 'Rows' is still present, but has been deprecated.
**1.6.0** | Added array subscript operators for vector and matrix types in C++. This is provided as a convenience, but be aware that it may incur an extra function call in unoptimized builds.
**1.5.1** | Fixed a bug with uninitialized elements in HMM_LookAt. ## Usage
**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. Simply `#include "HandmadeMath.h"`. All functions are `static inline`, so there is no need for an "implementation" file as with some other single-header libraries.
**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`. A few config options are available. See the header comment in [the source](./HandmadeMath.h) for details.
**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++
**1.1** | Quaternions! |
**1.0** | Lots of testing |
**0.7** | Added HMM_Vec2, and HMM_Vec4 versions of HMM_LengthSquared, HMM_Length, and HMM_Normalize. |
**0.6** | Made HMM_Power faster, Fixed possible efficiency problem with HMM_Normalize, RENAMED HMM_LengthSquareRoot to HMM_LengthSquared, RENAMED HMM_RSqrtF to HMM_RSquareRootF, RENAMED HMM_SqrtF to HMM_SquareRootF, REMOVED Inner function (user should use Dot now), REMOVED HMM_FastInverseSquareRoot function declaration |
**0.5.2** | Fixed SSE code in HMM_SqrtF and HMM_RSqrtF |
**0.5.1** | Fixed HMM_Translate producing row-major matrices, ensured column-major order for matrices throughout |
**0.5** | Added scalar operations on vectors and matrices, added += and -= for hmm_mat4, reconciled headers and implementations, tidied up in general |
**0.4** | Added SSE Optimized HMM_SqrtF, HMM_RSqrtF, Removed use of C Runtime |
**0.3** | Added +=,-=, *=, /= for hmm_vec2, hmm_vec3, hmm_vec4 |
**0.2b** | Disabled warning C4201 on MSVC, Added 64bit percision on HMM_PI |
**0.2a** | Prefixed Macros |
**0.2** | Updated Documentation, Fixed C Compliance, Prefixed all functions, and added better operator overloading |
**0.1** | Initial Version |
-----
## FAQ ## FAQ
**What conventions does HMM use, e.g. row vs. column major, handedness, etc.?**
Handmade Math's matrices are column-major, i.e. data is stored by columns, then rows. It also assumes column vectors, i.e. vectors are written vertically and matrix-vector multiplication is `M * V` instead of `V * M`. For more information, see [this issue](https://github.com/HandmadeMath/HandmadeMath/issues/124#issuecomment-775737253).
For other properties, we provide variants for each common convention. Functions that care about handedness have left-handed (`LH`) and right-handed (`RH`) variants. Projection functions have zero-to-one (`ZO`) and negative-one-to-one (`NO`) variants for different NDC conventions.
**What if I don't want the `HMM_` prefix?**
Do a find and replace in the library source.
**What's the license?** **What's the license?**
This library is in the public domain. You can do whatever you want with it. This library is in the public domain. You can do whatever you want with it.
**Where can I contact you to ask questions?** **Where can I contact you to ask questions?**
Feel free to make Github issues for any questions, concerns, or problems you encounter. Feel free to make GitHub issues for any questions, concerns, or problems you encounter.

View File

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

View File

@@ -4,19 +4,46 @@
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
} }
The main function of your test code should then call hmt_run_all_tests and Handmade Test also provides macros you can use to check the coverage of
return the result: important parts of your code. Define a coverage case by using the COVERAGE
macro outside the function you wish to test, providing both a name and the
number of asserts you expect to see covered over the course of your test.
Then use the ASSERT_COVERED macro in every part of the function you wish to
check coverage on. For example:
int main() { COVERAGE(MyCoverageCase, 3)
return hmt_run_all_tests(); void MyFunction(int a, int b) {
} if (a > b) {
ASSERT_COVERED(MyCoverageCase);
return 10;
} else if (a < b) {
ASSERT_COVERED(MyCoverageCase);
return -10;
}
ASSERT_COVERED(MyCoverageCase);
return 0;
}
The main function of your test code should then call hmt_run_all_tests (and
optionally hmt_check_all_coverage) and return the result:
int main() {
return hmt_run_all_tests() || hmt_check_all_coverage();
}
============================================================================= =============================================================================
@@ -40,7 +67,7 @@
#define HMT_RED "\033[31m" #define HMT_RED "\033[31m"
#define HMT_GREEN "\033[32m" #define HMT_GREEN "\033[32m"
#define HMT_INITIAL_ARRAY_SIZE 1024 #define HMT_ARRAY_SIZE 1024
typedef struct hmt_testresult_struct { typedef struct hmt_testresult_struct {
int count_cases; int count_cases;
@@ -57,20 +84,188 @@ 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;
int hmt_num_categories = 0; typedef struct hmt_covercase_struct {
int hmt_category_capacity = HMT_INITIAL_ARRAY_SIZE; const char* name;
hmt_category* categories = 0; int expected_asserts;
int actual_asserts;
int* asserted_lines;
} hmt_covercase;
hmt_category _hmt_new_category(const char* name);
hmt_test _hmt_new_test(const char* name, hmt_test_func func);
hmt_covercase _hmt_new_covercase(const char* name, int expected);
void _hmt_register_test(const char* category, const char* name, hmt_test_func func);
void _hmt_register_covercase(const char* name, const char* expected_asserts);
void _hmt_count_cover(const char* name, int line);
#define _HMT_TEST_FUNCNAME(category, name) _hmt_test_ ## category ## _ ## name
#define _HMT_TEST_FUNCNAME_INIT(category, name) _hmt_test_ ## category ## _ ## name ## _init
#define _HMT_COVERCASE_FUNCNAME_INIT(name) _hmt_covercase_ ## name ## _init
#define HMT_TEST(category, name) \
void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result); \
INITIALIZER(_HMT_TEST_FUNCNAME_INIT(category, name)) { \
_hmt_register_test(#category, #name, _HMT_TEST_FUNCNAME(category, name)); \
} \
void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result)
#define _HMT_CASE_START() \
_result->count_cases++;
#define _HMT_CASE_FAIL() \
_result->count_failures++; \
printf("\n - " HMT_RED "[FAIL] (line %d) " HMT_RESET, __LINE__);
#define HMT_COVERAGE(name, num_asserts) \
INITIALIZER(_HMT_COVERCASE_FUNCNAME_INIT(name)) { \
_hmt_register_covercase(#name, #num_asserts); \
} \
#define HMT_ASSERT_COVERED(name) \
{ \
_hmt_count_cover(#name, __LINE__); \
} \
/*
* Asserts and expects
*/
#define HMT_EXPECT_TRUE(_actual) { \
_HMT_CASE_START(); \
if (!(_actual)) { \
_HMT_CASE_FAIL(); \
printf("Expected true but got something false"); \
} \
} \
#define HMT_EXPECT_FALSE(_actual) { \
_HMT_CASE_START(); \
if (_actual) { \
_HMT_CASE_FAIL(); \
printf("Expected false but got something true"); \
} \
} \
#define HMT_EXPECT_FLOAT_EQ_MSG(_actual, _expected, _msg) { \
_HMT_CASE_START(); \
float actual = (_actual); \
float diff = actual - (_expected); \
if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
_HMT_CASE_FAIL(); \
if ((_msg)[0] == 0) { \
printf("Expected %f, got %f (error: %.9g)", (_expected), actual, diff); \
} else { \
printf("%s: Expected %f, got %f (error: %.9g)", (_msg), (_expected), actual, diff); \
} \
} \
}
#define HMT_EXPECT_FLOAT_EQ(_actual, _expected) HMT_EXPECT_FLOAT_EQ_MSG(_actual, _expected, "");
#define HMT_EXPECT_NEAR_MSG(_actual, _expected, _epsilon, _msg) { \
_HMT_CASE_START(); \
float actual = (_actual); \
float diff = actual - (_expected); \
if (diff < -(_epsilon) || (_epsilon) < diff) { \
_HMT_CASE_FAIL(); \
if ((_msg)[0] == 0) { \
printf("Expected %f, got %f", (_expected), actual); \
} else { \
printf("%s: Expected %f, got %f", (_msg), (_expected), actual); \
} \
} \
}
#define HMT_EXPECT_NEAR(_actual, _expected, _epsilon) HMT_EXPECT_NEAR_MSG(_actual, _expected, _epsilon, "");
#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_V4_EQ(_actual, _expected) \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.X, _expected.X, "incorrect X"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Y, _expected.Y, "incorrect Y"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Z, _expected.Z, "incorrect Z"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.W, _expected.W, "incorrect W");
#define EXPECT_M4_EQ(_actual, _expected) \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[0][0], _expected.Elements[0][0], "incorrect [0][0]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[0][1], _expected.Elements[0][1], "incorrect [0][1]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[0][2], _expected.Elements[0][2], "incorrect [0][2]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[0][3], _expected.Elements[0][3], "incorrect [0][3]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[1][0], _expected.Elements[1][0], "incorrect [1][0]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[1][1], _expected.Elements[1][1], "incorrect [1][1]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[1][2], _expected.Elements[1][2], "incorrect [1][2]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[1][3], _expected.Elements[1][3], "incorrect [1][3]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[2][0], _expected.Elements[2][0], "incorrect [2][0]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[2][1], _expected.Elements[2][1], "incorrect [2][1]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[2][2], _expected.Elements[2][2], "incorrect [2][2]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[2][3], _expected.Elements[2][3], "incorrect [2][3]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[3][0], _expected.Elements[3][0], "incorrect [3][0]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[3][1], _expected.Elements[3][1], "incorrect [3][1]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[3][2], _expected.Elements[3][2], "incorrect [3][2]"); \
HMT_EXPECT_FLOAT_EQ_MSG(_actual.Elements[3][3], _expected.Elements[3][3], "incorrect [3][3]");
#define EXPECT_NEAR(_actual, _expected, _epsilon) HMT_EXPECT_NEAR(_actual, _expected, _epsilon)
#define EXPECT_M4_NEAR(_actual, _expected, _epsilon) \
HMT_EXPECT_NEAR_MSG(_actual.Elements[0][0], _expected.Elements[0][0], _epsilon, "incorrect [0][0]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[0][1], _expected.Elements[0][1], _epsilon, "incorrect [0][1]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[0][2], _expected.Elements[0][2], _epsilon, "incorrect [0][2]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[0][3], _expected.Elements[0][3], _epsilon, "incorrect [0][3]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[1][0], _expected.Elements[1][0], _epsilon, "incorrect [1][0]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[1][1], _expected.Elements[1][1], _epsilon, "incorrect [1][1]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[1][2], _expected.Elements[1][2], _epsilon, "incorrect [1][2]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[1][3], _expected.Elements[1][3], _epsilon, "incorrect [1][3]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[2][0], _expected.Elements[2][0], _epsilon, "incorrect [2][0]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[2][1], _expected.Elements[2][1], _epsilon, "incorrect [2][1]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[2][2], _expected.Elements[2][2], _epsilon, "incorrect [2][2]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[2][3], _expected.Elements[2][3], _epsilon, "incorrect [2][3]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[3][0], _expected.Elements[3][0], _epsilon, "incorrect [3][0]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[3][1], _expected.Elements[3][1], _epsilon, "incorrect [3][1]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[3][2], _expected.Elements[3][2], _epsilon, "incorrect [3][2]"); \
HMT_EXPECT_NEAR_MSG(_actual.Elements[3][3], _expected.Elements[3][3], _epsilon, "incorrect [3][3]");
#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;
int _hmt_num_covererrors = 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
.num_tests = 0, 0, // num_tests
.tests_capacity = HMT_INITIAL_ARRAY_SIZE, (hmt_test*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_test)), // tests
.tests = (hmt_test*) malloc(HMT_INITIAL_ARRAY_SIZE * sizeof(hmt_test))
}; };
return cat; return cat;
@@ -78,60 +273,106 @@ 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;
} }
int hmt_register_test(const char* category, const char* name, hmt_test_func func) { hmt_covercase _hmt_new_covercase(const char* name, int expected) {
hmt_covercase covercase = {
name, // name
expected, // 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 (!categories) { if (!_hmt_categories) {
categories = (hmt_category*) malloc(hmt_category_capacity * sizeof(hmt_category)); _hmt_categories = (hmt_category*) malloc(HMT_ARRAY_SIZE * 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(categories[cat_index].name, category) == 0) { if (strcmp(_hmt_categories[cat_index].name, category) == 0) {
break; break;
} }
} }
// Expand the array of categories if necessary
if (cat_index >= hmt_category_capacity) {
// TODO: If/when we ever split HandmadeTest off into its own package,
// we should start with a smaller initial capacity and dynamically expand.
}
// Add a new category if necessary // Add a new category if necessary
if (cat_index >= hmt_num_categories) { if (cat_index >= _hmt_num_categories) {
categories[cat_index] = _hmt_new_category(category); _hmt_categories[cat_index] = _hmt_new_category(category);
hmt_num_categories++; _hmt_num_categories++;
} }
hmt_category* cat = &categories[cat_index]; hmt_category* cat = &_hmt_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);
_hmt_num_covererrors++;
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 = categories[i]; hmt_category cat = _hmt_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);
@@ -142,8 +383,8 @@ int hmt_run_all_tests() {
printf(" %s:", test.name); printf(" %s:", test.name);
hmt_testresult result = { hmt_testresult result = {
.count_cases = 0, 0, // count_cases
.count_failures = 0 0, // count_failures
}; };
test.func(&result); test.func(&result);
@@ -177,87 +418,38 @@ int hmt_run_all_tests() {
return (count_allfailedtests > 0); return (count_allfailedtests > 0);
} }
#define _HMT_TEST_FUNCNAME(category, name) category ## _ ## name int hmt_check_all_coverage() {
#define _HMT_TEST_FUNCNAME_INIT(category, name) category ## _ ## name ## _init printf("Coverage:\n");
#define HMT_TEST(category, name) \ int count_failures = 0;
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() \ for (int i = 0; i < _hmt_num_covercases; i++) {
_result->count_cases++; hmt_covercase covercase = _hmt_covercases[i];
#define _HMT_CASE_FAIL() \ if (covercase.expected_asserts != covercase.actual_asserts) {
_result->count_failures++; \ count_failures++;
printf("\n - " HMT_RED "[FAIL] (%d) " HMT_RESET, __LINE__); printf("%s: " HMT_RED "FAIL (expected %d asserts, got %d)\n" HMT_RESET, covercase.name, covercase.expected_asserts, covercase.actual_asserts);
}
}
/* if (count_failures > 0) {
* Asserts and expects printf("\n");
*/ printf(HMT_RED);
#define HMT_EXPECT_TRUE(_actual) do { \ } else {
_HMT_CASE_START(); \ printf(HMT_GREEN);
if (!(_actual)) { \ }
_HMT_CASE_FAIL(); \ printf("%d coverage cases tested, %d failures\n", _hmt_num_covercases, count_failures);
printf("Expected true but got something false"); \ printf(HMT_RESET);
} \
} while (0)
#define HMT_EXPECT_FALSE(_actual) do { \ printf("\n");
_HMT_CASE_START(); \
if (_actual) { \
_HMT_CASE_FAIL(); \
printf("Expected false but got something true"); \
} \
} while (0)
#define HMT_EXPECT_FLOAT_EQ(_actual, _expected) do { \ if (_hmt_num_covererrors > 0) {
_HMT_CASE_START(); \ printf(HMT_RED "There were %d other coverage errors; scroll up to see them.\n", _hmt_num_covererrors);
float actual = (_actual); \ return 1;
float diff = actual - (_expected); \ }
if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
_HMT_CASE_FAIL(); \
printf("Expected %f, got %f", (_expected), actual); \
} \
} while (0)
#define HMT_EXPECT_NEAR(_actual, _expected, _epsilon) do { \ return (count_failures > 0);
_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 { \ #endif // HANDMADE_TEST_IMPLEMENTATION_GUARD
_HMT_CASE_START(); \ #endif // HANDMADE_TEST_IMPLEMENTATION
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,45 +1,124 @@
BUILD_DIR=build BUILD_DIR=./build
CXXFLAGS+=-g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers CXXFLAGS+=-g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers -Wfloat-equal
all: c c_no_sse cpp cpp_no_sse .PHONY: all all_c all_cpp
all: all_c all_cpp
all_c: c99 c99_no_simd c11 c17
all_cpp: cpp98 cpp98_no_simd cpp03 cpp11 cpp14 cpp17 cpp20
.PHONY: clean
clean: clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)
c: HandmadeMath.c test_impl .PHONY: c99
@echo "\nCompiling in C mode" c99:
@echo "\nCompiling as C99"
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR)\ cd $(BUILD_DIR)\
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \ && $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
-c ../HandmadeMath.c ../hmm_test.c \ ../HandmadeMath.c ../hmm_test.c \
-lm \ -lm -o hmm_test_c99 \
&& $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm && ./hmm_test_c99
c_no_sse: HandmadeMath.c test_impl .PHONY: c99_no_simd
@echo "\nCompiling in C mode (no SSE)" c99_no_simd:
@echo "\nCompiling as C99 (no SIMD)"
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \ cd $(BUILD_DIR) \
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \ && $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
-DHANDMADE_MATH_NO_SSE \ -DHANDMADE_MATH_NO_SIMD \
-c ../HandmadeMath.c ../hmm_test.c \ ../HandmadeMath.c ../hmm_test.c \
-lm \ -lm -o hmm_test_c99_no_simd \
&& $(CC) -ohmm_test_c_no_sse HandmadeMath.o hmm_test.o -lm && ./hmm_test_c99_no_simd
cpp: HandmadeMath.cpp test_impl .PHONY: c11
@echo "\nCompiling in C++ mode" c11:
@echo "\nCompiling as C11"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR)\
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c11 \
../HandmadeMath.c ../hmm_test.c \
-lm -o hmm_test_c11 \
&& ./hmm_test_c11
.PHONY: c17
c17:
@echo "\nCompiling as C17"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR)\
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c17 \
../HandmadeMath.c ../hmm_test.c \
-lm -o hmm_test_c17 \
&& ./hmm_test_c17
.PHONY: cpp98
cpp98:
@echo "\nCompiling as C++98"
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \ cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp \ && $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++98 \
-DHANDMADE_MATH_CPP_MODE \ ../HandmadeMath.cpp ../hmm_test.cpp \
../HandmadeMath.cpp ../hmm_test.cpp -lm -o hmm_test_cpp98 \
&& ./hmm_test_cpp98
cpp_no_sse: HandmadeMath.cpp test_impl .PHONY: cpp98_no_simd
@echo "\nCompiling in C++ mode (no SSE)" cpp98_no_simd:
@echo "\nCompiling as C++98 (no SIMD)"
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \ cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_no_sse \ && $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++98 \
-DHANDMADE_MATH_CPP_MODE -DHANDMADE_MATH_NO_SSE \ -DHANDMADE_MATH_NO_SIMD \
../HandmadeMath.cpp ../hmm_test.cpp ../HandmadeMath.cpp ../hmm_test.cpp \
-lm -o hmm_test_cpp98 \
&& ./hmm_test_cpp98
test_impl: hmm_test.cpp hmm_test.c .PHONY: cpp03
cpp03:
@echo "\nCompiling as C++03"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++03 \
../HandmadeMath.cpp ../hmm_test.cpp \
-lm -o hmm_test_cpp03 \
&& ./hmm_test_cpp03
.PHONY: cpp11
cpp11:
@echo "\nCompiling as C++11"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++11 \
../HandmadeMath.cpp ../hmm_test.cpp \
-lm -o hmm_test_cpp11 \
&& ./hmm_test_cpp11
.PHONY: cpp14
cpp14:
@echo "\nCompiling as C++14"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++14 \
../HandmadeMath.cpp ../hmm_test.cpp \
-lm -o hmm_test_cpp14 \
&& ./hmm_test_cpp14
.PHONY: cpp17
cpp17:
@echo "\nCompiling as C++17"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++17 \
../HandmadeMath.cpp ../hmm_test.cpp \
-lm -o hmm_test_cpp17 \
&& ./hmm_test_cpp17
.PHONY: cpp20
cpp20:
@echo "\nCompiling as C++20"
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -std=c++20 \
../HandmadeMath.cpp ../hmm_test.cpp \
-lm -o hmm_test_cpp20 \
&& ./hmm_test_cpp20

View File

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

View File

@@ -2,22 +2,24 @@
TEST(Addition, Vec2) TEST(Addition, Vec2)
{ {
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 2.0f); HMM_Vec2 v2_1 = HMM_V2(1.0f, 2.0f);
hmm_vec2 v2_2 = HMM_Vec2(3.0f, 4.0f); HMM_Vec2 v2_2 = HMM_V2(3.0f, 4.0f);
{ {
hmm_vec2 result = HMM_AddVec2(v2_1, v2_2); HMM_Vec2 result = HMM_AddV2(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 4.0f); EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Add(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec2 result = HMM_Add(v2_1, v2_2); HMM_Vec2 result = v2_1 + v2_2;
EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
{
hmm_vec2 result = v2_1 + v2_2;
EXPECT_FLOAT_EQ(result.X, 4.0f); EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
} }
@@ -30,24 +32,26 @@ TEST(Addition, Vec2)
TEST(Addition, Vec3) TEST(Addition, Vec3)
{ {
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 2.0f, 3.0f); HMM_Vec3 v3_1 = HMM_V3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3_2 = HMM_Vec3(4.0f, 5.0f, 6.0f); HMM_Vec3 v3_2 = HMM_V3(4.0f, 5.0f, 6.0f);
{ {
hmm_vec3 result = HMM_AddVec3(v3_1, v3_2); HMM_Vec3 result = HMM_AddV3(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 7.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
#ifdef __cplusplus
{
hmm_vec3 result = HMM_Add(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);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
hmm_vec3 result = v3_1 + v3_2; HMM_Vec3 result = HMM_Add(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 7.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec3 result = 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);
@@ -62,26 +66,28 @@ TEST(Addition, Vec3)
TEST(Addition, Vec4) TEST(Addition, Vec4)
{ {
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f); HMM_Vec4 v4_1 = HMM_V4(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_V4(5.0f, 6.0f, 7.0f, 8.0f);
{ {
hmm_vec4 result = HMM_AddVec4(v4_1, v4_2); HMM_Vec4 result = HMM_AddV4(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 6.0f); EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f); EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f); EXPECT_FLOAT_EQ(result.W, 12.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Add(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec4 result = HMM_Add(v4_1, v4_2); HMM_Vec4 result = v4_1 + v4_2;
EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
{
hmm_vec4 result = v4_1 + v4_2;
EXPECT_FLOAT_EQ(result.X, 6.0f); EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f); EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
@@ -96,10 +102,138 @@ TEST(Addition, Vec4)
#endif #endif
} }
TEST(Addition, Mat2)
{
HMM_Mat2 a = HMM_M2();
HMM_Mat2 b = HMM_M2();
int Counter = 1;
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
a.Elements[Column][Row] = Counter++;
}
}
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
b.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat2 result = HMM_AddM2(a, b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 8.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 12.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat2 result = HMM_Add(a, b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 8.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 12.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat2 result = a + b;
EXPECT_FLOAT_EQ(result.Elements[0][0], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 8.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 12.0f);
}
a += b;
EXPECT_FLOAT_EQ(a.Elements[0][0], 6.0f);
EXPECT_FLOAT_EQ(a.Elements[0][1], 8.0f);
EXPECT_FLOAT_EQ(a.Elements[1][0], 10.0f);
EXPECT_FLOAT_EQ(a.Elements[1][1], 12.0f);
#endif
}
TEST(Addition, Mat3)
{
HMM_Mat3 a = HMM_M3();
HMM_Mat3 b = HMM_M3();
int Counter = 1;
for (int Column = 0; Column < 3; ++Column)
{
for (int Row = 0; Row < 3; ++Row)
{
a.Elements[Column][Row] = Counter++;
}
}
for (int Column = 0; Column < 3; ++Column)
{
for (int Row = 0; Row < 3; ++Row)
{
b.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat3 result = HMM_AddM3(a, b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 11.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 13.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 15.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 17.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 19.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 25.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 27.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat3 result = HMM_Add(a, b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 11.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 13.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 15.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 17.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 19.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 25.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 27.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat3 result = a + b;
EXPECT_FLOAT_EQ(result.Elements[0][0], 11.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 13.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 15.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 17.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 19.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 25.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 27.0f);
}
a += b;
EXPECT_FLOAT_EQ(a.Elements[0][0], 11.0f);
EXPECT_FLOAT_EQ(a.Elements[0][1], 13.0f);
EXPECT_FLOAT_EQ(a.Elements[0][2], 15.0f);
EXPECT_FLOAT_EQ(a.Elements[1][0], 17.0f);
EXPECT_FLOAT_EQ(a.Elements[1][1], 19.0f);
EXPECT_FLOAT_EQ(a.Elements[1][2], 21.0f);
EXPECT_FLOAT_EQ(a.Elements[2][0], 23.0f);
EXPECT_FLOAT_EQ(a.Elements[2][1], 25.0f);
EXPECT_FLOAT_EQ(a.Elements[2][2], 27.0f);
#endif
}
TEST(Addition, Mat4) TEST(Addition, Mat4)
{ {
hmm_mat4 m4_1 = HMM_Mat4(); // will have 1 - 16 HMM_Mat4 m4_1 = HMM_M4(); // will have 1 - 16
hmm_mat4 m4_2 = HMM_Mat4(); // will have 17 - 32 HMM_Mat4 m4_2 = HMM_M4(); // will have 17 - 32
// Fill the matrices // Fill the matrices
int Counter = 1; int Counter = 1;
@@ -122,7 +256,7 @@ TEST(Addition, Mat4)
// Test the results // Test the results
{ {
hmm_mat4 result = HMM_AddMat4(m4_1, m4_2); HMM_Mat4 result = HMM_AddM4(m4_1, m4_2);
float Expected = 18.0f; float Expected = 18.0f;
for (int Column = 0; Column < 4; ++Column) for (int Column = 0; Column < 4; ++Column)
{ {
@@ -133,21 +267,23 @@ TEST(Addition, Mat4)
} }
} }
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat4 result = HMM_Add(m4_1, m4_2);
float Expected = 18.0f;
for (int Column = 0; Column < 4; ++Column)
{
for (int Row = 0; Row < 4; ++Row)
{
EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected);
Expected += 2.0f;
}
}
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_mat4 result = HMM_Add(m4_1, m4_2); HMM_Mat4 result = m4_1 + m4_2;
float Expected = 18.0f;
for (int Column = 0; Column < 4; ++Column)
{
for (int Row = 0; Row < 4; ++Row)
{
EXPECT_FLOAT_EQ(result.Elements[Column][Row], Expected);
Expected += 2.0f;
}
}
}
{
hmm_mat4 result = m4_1 + m4_2;
float Expected = 18.0f; float Expected = 18.0f;
for (int Column = 0; Column < 4; ++Column) for (int Column = 0; Column < 4; ++Column)
{ {
@@ -174,26 +310,28 @@ TEST(Addition, Mat4)
TEST(Addition, Quaternion) TEST(Addition, Quaternion)
{ {
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f); HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f); HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
{ {
hmm_quaternion result = HMM_AddQuaternion(q1, q2); HMM_Quat result = HMM_AddQ(q1, q2);
EXPECT_FLOAT_EQ(result.X, 6.0f); EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f); EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f); EXPECT_FLOAT_EQ(result.W, 12.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Quat result = HMM_Add(q1, q2);
EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_quaternion result = HMM_Add(q1, q2); HMM_Quat result = q1 + q2;
EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
{
hmm_quaternion result = q1 + q2;
EXPECT_FLOAT_EQ(result.X, 6.0f); EXPECT_FLOAT_EQ(result.X, 6.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f); EXPECT_FLOAT_EQ(result.Y, 8.0f);
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);

View File

@@ -2,22 +2,24 @@
TEST(Division, Vec2Vec2) TEST(Division, Vec2Vec2)
{ {
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 3.0f); HMM_Vec2 v2_1 = HMM_V2(1.0f, 3.0f);
hmm_vec2 v2_2 = HMM_Vec2(2.0f, 4.0f); HMM_Vec2 v2_2 = HMM_V2(2.0f, 4.0f);
{ {
hmm_vec2 result = HMM_DivideVec2(v2_1, v2_2); HMM_Vec2 result = HMM_DivV2(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f); EXPECT_FLOAT_EQ(result.Y, 0.75f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Div(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec2 result = HMM_Divide(v2_1, v2_2); HMM_Vec2 result = v2_1 / v2_2;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
}
{
hmm_vec2 result = v2_1 / v2_2;
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f); EXPECT_FLOAT_EQ(result.Y, 0.75f);
} }
@@ -30,22 +32,24 @@ TEST(Division, Vec2Vec2)
TEST(Division, Vec2Scalar) TEST(Division, Vec2Scalar)
{ {
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f); HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
float s = 2; float s = 2;
{ {
hmm_vec2 result = HMM_DivideVec2f(v2, s); HMM_Vec2 result = HMM_DivV2F(v2, s);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f); EXPECT_FLOAT_EQ(result.Y, 1.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Div(v2, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec2 result = HMM_Divide(v2, s); HMM_Vec2 result = v2 / s;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
}
{
hmm_vec2 result = v2 / s;
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f); EXPECT_FLOAT_EQ(result.Y, 1.0f);
} }
@@ -58,24 +62,26 @@ TEST(Division, Vec2Scalar)
TEST(Division, Vec3Vec3) TEST(Division, Vec3Vec3)
{ {
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 3.0f, 5.0f); HMM_Vec3 v3_1 = HMM_V3(1.0f, 3.0f, 5.0f);
hmm_vec3 v3_2 = HMM_Vec3(2.0f, 4.0f, 0.5f); HMM_Vec3 v3_2 = HMM_V3(2.0f, 4.0f, 0.5f);
{ {
hmm_vec3 result = HMM_DivideVec3(v3_1, v3_2); HMM_Vec3 result = HMM_DivV3(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f); EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Div(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec3 result = HMM_Divide(v3_1, v3_2); HMM_Vec3 result = v3_1 / v3_2;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
}
{
hmm_vec3 result = v3_1 / v3_2;
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f); EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
@@ -90,24 +96,26 @@ TEST(Division, Vec3Vec3)
TEST(Division, Vec3Scalar) TEST(Division, Vec3Scalar)
{ {
hmm_vec3 v3 = HMM_Vec3(1.0f, 2.0f, 3.0f); HMM_Vec3 v3 = HMM_V3(1.0f, 2.0f, 3.0f);
float s = 2; float s = 2;
{ {
hmm_vec3 result = HMM_DivideVec3f(v3, s); HMM_Vec3 result = HMM_DivV3F(v3, s);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f); EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f); EXPECT_FLOAT_EQ(result.Z, 1.5f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Div(v3, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec3 result = HMM_Divide(v3, s); HMM_Vec3 result = v3 / s;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
}
{
hmm_vec3 result = v3 / s;
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f); EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f); EXPECT_FLOAT_EQ(result.Z, 1.5f);
@@ -122,26 +130,28 @@ TEST(Division, Vec3Scalar)
TEST(Division, Vec4Vec4) TEST(Division, Vec4Vec4)
{ {
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 3.0f, 5.0f, 1.0f); HMM_Vec4 v4_1 = HMM_V4(1.0f, 3.0f, 5.0f, 1.0f);
hmm_vec4 v4_2 = HMM_Vec4(2.0f, 4.0f, 0.5f, 4.0f); HMM_Vec4 v4_2 = HMM_V4(2.0f, 4.0f, 0.5f, 4.0f);
{ {
hmm_vec4 result = HMM_DivideVec4(v4_1, v4_2); HMM_Vec4 result = HMM_DivV4(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f); EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 0.25f); EXPECT_FLOAT_EQ(result.W, 0.25f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Div(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 0.25f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec4 result = HMM_Divide(v4_1, v4_2); HMM_Vec4 result = v4_1 / v4_2;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f);
EXPECT_FLOAT_EQ(result.W, 0.25f);
}
{
hmm_vec4 result = v4_1 / v4_2;
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.75f); EXPECT_FLOAT_EQ(result.Y, 0.75f);
EXPECT_FLOAT_EQ(result.Z, 10.0f); EXPECT_FLOAT_EQ(result.Z, 10.0f);
@@ -158,26 +168,28 @@ TEST(Division, Vec4Vec4)
TEST(Division, Vec4Scalar) TEST(Division, Vec4Scalar)
{ {
hmm_vec4 v4 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f); HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
float s = 2; float s = 2;
{ {
hmm_vec4 result = HMM_DivideVec4f(v4, s); HMM_Vec4 result = HMM_DivV4F(v4, s);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f); EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f); EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f); EXPECT_FLOAT_EQ(result.W, 2.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Div(v4, s);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec4 result = HMM_Divide(v4, s); HMM_Vec4 result = v4 / s;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f);
}
{
hmm_vec4 result = v4 / s;
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f); EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f); EXPECT_FLOAT_EQ(result.Z, 1.5f);
@@ -192,9 +204,107 @@ TEST(Division, Vec4Scalar)
#endif #endif
} }
TEST(Division, Mat2Scalar)
{
HMM_Mat2 m = HMM_M2();
float s = 0.5f;
int Counter = 1;
for (int Column = 0; Column < 2; ++Column) {
for (int Row = 0; Row < 2; ++Row) {
m.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat2 result = HMM_DivM2F(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 8.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat2 result = HMM_Div(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 8.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat2 result = m / s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 8.0f);
}
#endif
}
TEST(Division, Mat3Scalar)
{
HMM_Mat3 m = HMM_M3();
float s = 0.5f;
int Counter = 1;
for (int Column = 0; Column < 3; ++Column) {
for (int Row = 0; Row < 3; ++Row) {
m.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat3 result = HMM_DivM3F(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 8.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 12.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 14.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 16.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 18.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat3 result = HMM_Div(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 8.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 12.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 14.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 16.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 18.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat3 result = m / s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 8.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 12.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 14.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 16.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 18.0f);
}
#endif
}
TEST(Division, Mat4Scalar) TEST(Division, Mat4Scalar)
{ {
hmm_mat4 m4 = HMM_Mat4(); // will have 1 - 16 HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
float s = 2; float s = 2;
// Fill the matrix // Fill the matrix
@@ -210,7 +320,7 @@ TEST(Division, Mat4Scalar)
// Test the results // Test the results
{ {
hmm_mat4 result = HMM_DivideMat4f(m4, s); HMM_Mat4 result = HMM_DivM4F(m4, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f); EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f); EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f); EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
@@ -228,28 +338,30 @@ TEST(Division, Mat4Scalar)
EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f); EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f); EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat4 result = HMM_Div(m4, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
EXPECT_FLOAT_EQ(result.Elements[0][3], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 2.5f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 3.5f);
EXPECT_FLOAT_EQ(result.Elements[1][3], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 4.5f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 5.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 5.5f);
EXPECT_FLOAT_EQ(result.Elements[2][3], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[3][0], 6.5f);
EXPECT_FLOAT_EQ(result.Elements[3][1], 7.0f);
EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_mat4 result = HMM_Divide(m4, s); HMM_Mat4 result = m4 / s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
EXPECT_FLOAT_EQ(result.Elements[0][3], 2.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 2.5f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 3.5f);
EXPECT_FLOAT_EQ(result.Elements[1][3], 4.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 4.5f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 5.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 5.5f);
EXPECT_FLOAT_EQ(result.Elements[2][3], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[3][0], 6.5f);
EXPECT_FLOAT_EQ(result.Elements[3][1], 7.0f);
EXPECT_FLOAT_EQ(result.Elements[3][2], 7.5f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 8.0f);
}
{
hmm_mat4 result = m4 / s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f); EXPECT_FLOAT_EQ(result.Elements[0][0], 0.5f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f); EXPECT_FLOAT_EQ(result.Elements[0][1], 1.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f); EXPECT_FLOAT_EQ(result.Elements[0][2], 1.5f);
@@ -290,26 +402,28 @@ TEST(Division, Mat4Scalar)
TEST(Division, QuaternionScalar) TEST(Division, QuaternionScalar)
{ {
hmm_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f); HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
float f = 2.0f; float f = 2.0f;
{ {
hmm_quaternion result = HMM_DivideQuaternionF(q, f); HMM_Quat result = HMM_DivQF(q, f);
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f); EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f); EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f); EXPECT_FLOAT_EQ(result.W, 2.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Quat result = HMM_Div(q, f);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_quaternion result = HMM_Divide(q, f); HMM_Quat result = q / f;
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f);
EXPECT_FLOAT_EQ(result.W, 2.0f);
}
{
hmm_quaternion result = q / f;
EXPECT_FLOAT_EQ(result.X, 0.5f); EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f); EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 1.5f); EXPECT_FLOAT_EQ(result.Z, 1.5f);

View File

@@ -2,54 +2,69 @@
TEST(Equality, Vec2) TEST(Equality, Vec2)
{ {
hmm_vec2 a = HMM_Vec2(1.0f, 2.0f); HMM_Vec2 a = HMM_V2(1.0f, 2.0f);
hmm_vec2 b = HMM_Vec2(1.0f, 2.0f); HMM_Vec2 b = HMM_V2(1.0f, 2.0f);
hmm_vec2 c = HMM_Vec2(3.0f, 4.0f); HMM_Vec2 c = HMM_V2(3.0f, 4.0f);
EXPECT_TRUE(HMM_EqualsVec2(a, b)); EXPECT_TRUE(HMM_EqV2(a, b));
EXPECT_FALSE(HMM_EqualsVec2(a, c)); EXPECT_FALSE(HMM_EqV2(a, c));
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_TRUE(HMM_Eq(a, b));
EXPECT_FALSE(HMM_Eq(a, c));
#endif
#ifdef __cplusplus #ifdef __cplusplus
EXPECT_TRUE(HMM_Equals(a, b));
EXPECT_FALSE(HMM_Equals(a, c));
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
} }
TEST(Equality, Vec3) TEST(Equality, Vec3)
{ {
hmm_vec3 a = HMM_Vec3(1.0f, 2.0f, 3.0f); HMM_Vec3 a = HMM_V3(1.0f, 2.0f, 3.0f);
hmm_vec3 b = HMM_Vec3(1.0f, 2.0f, 3.0f); HMM_Vec3 b = HMM_V3(1.0f, 2.0f, 3.0f);
hmm_vec3 c = HMM_Vec3(4.0f, 5.0f, 6.0f); HMM_Vec3 c = HMM_V3(4.0f, 5.0f, 6.0f);
EXPECT_TRUE(HMM_EqualsVec3(a, b)); EXPECT_TRUE(HMM_EqV3(a, b));
EXPECT_FALSE(HMM_EqualsVec3(a, c)); EXPECT_FALSE(HMM_EqV3(a, c));
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_TRUE(HMM_Eq(a, b));
EXPECT_FALSE(HMM_Eq(a, c));
#endif
#ifdef __cplusplus #ifdef __cplusplus
EXPECT_TRUE(HMM_Equals(a, b));
EXPECT_FALSE(HMM_Equals(a, c));
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
} }
TEST(Equality, Vec4) TEST(Equality, Vec4)
{ {
hmm_vec4 a = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f); HMM_Vec4 a = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 b = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f); HMM_Vec4 b = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 c = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f); HMM_Vec4 c = HMM_V4(5.0f, 6.0f, 7.0f, 8.0f);
EXPECT_TRUE(HMM_EqualsVec4(a, b)); EXPECT_TRUE(HMM_EqV4(a, b));
EXPECT_FALSE(HMM_EqualsVec4(a, c)); EXPECT_FALSE(HMM_EqV4(a, c));
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_TRUE(HMM_Eq(a, b));
EXPECT_FALSE(HMM_Eq(a, c));
#endif
#ifdef __cplusplus #ifdef __cplusplus
EXPECT_TRUE(HMM_Equals(a, b));
EXPECT_FALSE(HMM_Equals(a, c));
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,8 @@ TEST(Initialization, Vectors)
{ {
// //
// Test vec2 // Test vec2
// //
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f); HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
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);
@@ -23,26 +22,10 @@ TEST(Initialization, Vectors)
EXPECT_FLOAT_EQ(v2[1], 2.0f); EXPECT_FLOAT_EQ(v2[1], 2.0f);
#endif #endif
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);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(v2i[0], 1.0f);
EXPECT_FLOAT_EQ(v2i[1], 2.0f);
#endif
// //
// Test vec3 // Test vec3
// //
hmm_vec3 v3 = HMM_Vec3(1.0f, 2.0f, 3.0f); HMM_Vec3 v3 = HMM_V3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3i = HMM_Vec3i(1, 2, 3);
EXPECT_FLOAT_EQ(v3.X, 1.0f); EXPECT_FLOAT_EQ(v3.X, 1.0f);
EXPECT_FLOAT_EQ(v3.Y, 2.0f); EXPECT_FLOAT_EQ(v3.Y, 2.0f);
@@ -70,38 +53,11 @@ TEST(Initialization, Vectors)
EXPECT_FLOAT_EQ(v3[2], 3.0f); EXPECT_FLOAT_EQ(v3[2], 3.0f);
#endif #endif
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);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(v3i[0], 1.0f);
EXPECT_FLOAT_EQ(v3i[1], 2.0f);
EXPECT_FLOAT_EQ(v3i[2], 3.0f);
#endif
// //
// Test vec4 // Test vec4
// //
hmm_vec4 v4 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f); HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 v4i = HMM_Vec4i(1, 2, 3, 4); HMM_Vec4 v4v = HMM_V4V(v3, 4.0f);
hmm_vec4 v4v = HMM_Vec4v(v3, 4.0f);
EXPECT_FLOAT_EQ(v4.X, 1.0f); EXPECT_FLOAT_EQ(v4.X, 1.0f);
EXPECT_FLOAT_EQ(v4.Y, 2.0f); EXPECT_FLOAT_EQ(v4.Y, 2.0f);
@@ -132,35 +88,6 @@ TEST(Initialization, Vectors)
EXPECT_FLOAT_EQ(v4[3], 4.0f); EXPECT_FLOAT_EQ(v4[3], 4.0f);
#endif #endif
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);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(v4i[0], 1.0f);
EXPECT_FLOAT_EQ(v4i[1], 2.0f);
EXPECT_FLOAT_EQ(v4i[2], 3.0f);
EXPECT_FLOAT_EQ(v4i[3], 4.0f);
#endif
EXPECT_FLOAT_EQ(v4v.X, 1.0f); EXPECT_FLOAT_EQ(v4v.X, 1.0f);
EXPECT_FLOAT_EQ(v4v.Y, 2.0f); EXPECT_FLOAT_EQ(v4v.Y, 2.0f);
EXPECT_FLOAT_EQ(v4v.Z, 3.0f); EXPECT_FLOAT_EQ(v4v.Z, 3.0f);
@@ -193,7 +120,40 @@ TEST(Initialization, Vectors)
TEST(Initialization, MatrixEmpty) TEST(Initialization, MatrixEmpty)
{ {
hmm_mat4 m4 = HMM_Mat4(); //
// Test mat2
//
HMM_Mat2 m2 = HMM_M2();
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
EXPECT_FLOAT_EQ(m2.Elements[Column][Row], 0.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(m2[Column][Row], 0.0f);
#endif
}
}
//
// Test mat3
//
HMM_Mat3 m3 = HMM_M3();
for (int Column = 0; Column < 3; ++Column)
{
for (int Row = 0; Row < 3; ++Row)
{
EXPECT_FLOAT_EQ(m3.Elements[Column][Row], 0.0f);
#ifdef __cplusplus
EXPECT_FLOAT_EQ(m3[Column][Row], 0.0f);
#endif
}
}
//
// Test mat4
//
HMM_Mat4 m4 = HMM_M4();
for (int Column = 0; Column < 4; ++Column) for (int Column = 0; Column < 4; ++Column)
{ {
for (int Row = 0; Row < 4; ++Row) for (int Row = 0; Row < 4; ++Row)
@@ -208,7 +168,42 @@ TEST(Initialization, MatrixEmpty)
TEST(Initialization, MatrixDiagonal) TEST(Initialization, MatrixDiagonal)
{ {
hmm_mat4 m4d = HMM_Mat4d(1.0f); //
// Test mat2
//
HMM_Mat2 m2d = HMM_M2D(1.0f);
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
if (Column == Row) {
EXPECT_FLOAT_EQ(m2d.Elements[Column][Row], 1.0f);
} else {
EXPECT_FLOAT_EQ(m2d.Elements[Column][Row], 0.0f);
}
}
}
//
// Test mat3
//
HMM_Mat3 m3d = HMM_M3D(1.0f);
for (int Column = 0; Column < 3; ++Column)
{
for (int Row = 0; Row < 3; ++Row)
{
if (Column == Row) {
EXPECT_FLOAT_EQ(m3d.Elements[Column][Row], 1.0f);
} else {
EXPECT_FLOAT_EQ(m3d.Elements[Column][Row], 0.0f);
}
}
}
//
// Test mat4
//
HMM_Mat4 m4d = HMM_M4D(1.0f);
for (int Column = 0; Column < 4; ++Column) for (int Column = 0; Column < 4; ++Column)
{ {
for (int Row = 0; Row < 4; ++Row) for (int Row = 0; Row < 4; ++Row)
@@ -224,7 +219,7 @@ TEST(Initialization, MatrixDiagonal)
TEST(Initialization, Quaternion) TEST(Initialization, Quaternion)
{ {
hmm_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f); HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
EXPECT_FLOAT_EQ(q.X, 1.0f); EXPECT_FLOAT_EQ(q.X, 1.0f);
EXPECT_FLOAT_EQ(q.Y, 2.0f); EXPECT_FLOAT_EQ(q.Y, 2.0f);
@@ -236,11 +231,91 @@ TEST(Initialization, Quaternion)
EXPECT_FLOAT_EQ(q.Elements[2], 3.0f); EXPECT_FLOAT_EQ(q.Elements[2], 3.0f);
EXPECT_FLOAT_EQ(q.Elements[3], 4.0f); EXPECT_FLOAT_EQ(q.Elements[3], 4.0f);
hmm_vec4 v = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f); HMM_Vec4 v = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion qv = HMM_QuaternionV4(v); HMM_Quat qv = HMM_QV4(v);
EXPECT_FLOAT_EQ(qv.X, 1.0f); EXPECT_FLOAT_EQ(qv.X, 1.0f);
EXPECT_FLOAT_EQ(qv.Y, 2.0f); EXPECT_FLOAT_EQ(qv.Y, 2.0f);
EXPECT_FLOAT_EQ(qv.Z, 3.0f); EXPECT_FLOAT_EQ(qv.Z, 3.0f);
EXPECT_FLOAT_EQ(qv.W, 4.0f); EXPECT_FLOAT_EQ(qv.W, 4.0f);
} }
#ifdef __cplusplus
TEST(Initialization, MatrixOverloads)
{
// Operator overloads for matrix columns must allow mutation.
//
// Test mat2
//
HMM_Mat2 m2 = {0};
m2[0][0] = 1.0f;
m2[0][1] = 2.0f;
m2[1][0] = 3.0f;
m2[1][1] = 4.0f;
EXPECT_FLOAT_EQ(m2.Elements[0][0], 1.0f);
EXPECT_FLOAT_EQ(m2.Elements[0][1], 2.0f);
EXPECT_FLOAT_EQ(m2.Elements[1][0], 3.0f);
EXPECT_FLOAT_EQ(m2.Elements[1][1], 4.0f);
//
// Test mat3
//
HMM_Mat3 m3 = {0};
m3[0][0] = 1.0f;
m3[0][1] = 2.0f;
m3[0][2] = 3.0f;
m3[1][0] = 4.0f;
m3[1][1] = 5.0f;
m3[1][2] = 6.0f;
m3[2][0] = 7.0f;
m3[2][1] = 8.0f;
m3[2][2] = 9.0f;
EXPECT_FLOAT_EQ(m3.Elements[0][0], 1.0f);
EXPECT_FLOAT_EQ(m3.Elements[0][1], 2.0f);
EXPECT_FLOAT_EQ(m3.Elements[0][2], 3.0f);
EXPECT_FLOAT_EQ(m3.Elements[1][0], 4.0f);
EXPECT_FLOAT_EQ(m3.Elements[1][1], 5.0f);
EXPECT_FLOAT_EQ(m3.Elements[1][2], 6.0f);
EXPECT_FLOAT_EQ(m3.Elements[2][0], 7.0f);
EXPECT_FLOAT_EQ(m3.Elements[2][1], 8.0f);
EXPECT_FLOAT_EQ(m3.Elements[2][2], 9.0f);
//
// Test mat4
//
HMM_Mat4 m4 = {0};
m4[0][0] = 1.0f;
m4[0][1] = 2.0f;
m4[0][2] = 3.0f;
m4[0][3] = 4.0f;
m4[1][0] = 5.0f;
m4[1][1] = 6.0f;
m4[1][2] = 7.0f;
m4[1][3] = 8.0f;
m4[2][0] = 9.0f;
m4[2][1] = 10.0f;
m4[2][2] = 11.0f;
m4[2][3] = 12.0f;
m4[3][0] = 13.0f;
m4[3][1] = 14.0f;
m4[3][2] = 15.0f;
m4[3][3] = 16.0f;
EXPECT_FLOAT_EQ(m4.Elements[0][0], 1.0f);
EXPECT_FLOAT_EQ(m4.Elements[0][1], 2.0f);
EXPECT_FLOAT_EQ(m4.Elements[0][2], 3.0f);
EXPECT_FLOAT_EQ(m4.Elements[0][3], 4.0f);
EXPECT_FLOAT_EQ(m4.Elements[1][0], 5.0f);
EXPECT_FLOAT_EQ(m4.Elements[1][1], 6.0f);
EXPECT_FLOAT_EQ(m4.Elements[1][2], 7.0f);
EXPECT_FLOAT_EQ(m4.Elements[1][3], 8.0f);
EXPECT_FLOAT_EQ(m4.Elements[2][0], 9.0f);
EXPECT_FLOAT_EQ(m4.Elements[2][1], 10.0f);
EXPECT_FLOAT_EQ(m4.Elements[2][2], 11.0f);
EXPECT_FLOAT_EQ(m4.Elements[2][3], 12.0f);
EXPECT_FLOAT_EQ(m4.Elements[3][0], 13.0f);
EXPECT_FLOAT_EQ(m4.Elements[3][1], 14.0f);
EXPECT_FLOAT_EQ(m4.Elements[3][2], 15.0f);
EXPECT_FLOAT_EQ(m4.Elements[3][3], 16.0f);
}
#endif

359
test/categories/MatrixOps.h Normal file
View File

@@ -0,0 +1,359 @@
#include "../HandmadeTest.h"
TEST(InvMatrix, Transpose)
{
{
HMM_Mat2 Matrix = {
1.0f, 3.0f,
2.0f, 4.0f,
};
HMM_Mat2 Expect = {
1.0f, 2.0f,
3.0f, 4.0f,
};
{
HMM_Mat2 result = HMM_TransposeM2(Matrix);
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
EXPECT_FLOAT_EQ(result.Elements[0][1], Expect.Elements[0][1]);
EXPECT_FLOAT_EQ(result.Elements[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat2 result = HMM_Transpose(Matrix);
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
EXPECT_FLOAT_EQ(result.Elements[0][1], Expect.Elements[0][1]);
EXPECT_FLOAT_EQ(result.Elements[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
}
#endif
}
{
HMM_Mat3 Matrix = {
1.0f, 4.0f, 7.0f,
2.0f, 5.0f, 8.0f,
3.0f, 6.0f, 9.0f,
};
HMM_Mat3 Expect = {
1.0f, 2.0f, 3.0f,
4.0f, 5.0f, 6.0f,
7.0f, 8.0f, 9.0f
};
{
HMM_Mat3 result = HMM_TransposeM3(Matrix);
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
EXPECT_FLOAT_EQ(result.Elements[0][1], Expect.Elements[0][1]);
EXPECT_FLOAT_EQ(result.Elements[0][2], Expect.Elements[0][2]);
EXPECT_FLOAT_EQ(result.Elements[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
EXPECT_FLOAT_EQ(result.Elements[1][2], Expect.Elements[1][2]);
EXPECT_FLOAT_EQ(result.Elements[2][0], Expect.Elements[2][0]);
EXPECT_FLOAT_EQ(result.Elements[2][1], Expect.Elements[2][1]);
EXPECT_FLOAT_EQ(result.Elements[2][2], Expect.Elements[2][2]);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat3 result = HMM_Transpose(Matrix);
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
EXPECT_FLOAT_EQ(result.Elements[0][1], Expect.Elements[0][1]);
EXPECT_FLOAT_EQ(result.Elements[0][2], Expect.Elements[0][2]);
EXPECT_FLOAT_EQ(result.Elements[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
EXPECT_FLOAT_EQ(result.Elements[1][2], Expect.Elements[1][2]);
EXPECT_FLOAT_EQ(result.Elements[2][0], Expect.Elements[2][0]);
EXPECT_FLOAT_EQ(result.Elements[2][1], Expect.Elements[2][1]);
EXPECT_FLOAT_EQ(result.Elements[2][2], Expect.Elements[2][2]);
}
#endif
}
{
HMM_Mat4 Matrix = {
1.0f, 5.0f, 9.0f, 13.0f,
2.0f, 6.0f, 10.0f, 14.0f,
3.0f, 7.0f, 11.0f, 15.0f,
4.0f, 8.0f, 12.0f, 16.0f
};
HMM_Mat4 Expect = {
1.0f, 2.0f, 3.0f, 4.0f,
5.0f, 6.0f, 7.0f, 8.0f,
9.0f, 10.0f, 11.0f, 12.0f,
13.0f, 14.0f, 15.0f, 16.0f,
};
{
HMM_Mat4 result = HMM_TransposeM4(Matrix);
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
EXPECT_FLOAT_EQ(result.Elements[0][1], Expect.Elements[0][1]);
EXPECT_FLOAT_EQ(result.Elements[0][2], Expect.Elements[0][2]);
EXPECT_FLOAT_EQ(result.Elements[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
EXPECT_FLOAT_EQ(result.Elements[1][2], Expect.Elements[1][2]);
EXPECT_FLOAT_EQ(result.Elements[2][0], Expect.Elements[2][0]);
EXPECT_FLOAT_EQ(result.Elements[2][1], Expect.Elements[2][1]);
EXPECT_FLOAT_EQ(result.Elements[2][2], Expect.Elements[2][2]);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat4 result = HMM_Transpose(Matrix);
EXPECT_FLOAT_EQ(result.Elements[0][0], Expect.Elements[0][0]);
EXPECT_FLOAT_EQ(result.Elements[0][1], Expect.Elements[0][1]);
EXPECT_FLOAT_EQ(result.Elements[0][2], Expect.Elements[0][2]);
EXPECT_FLOAT_EQ(result.Elements[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(result.Elements[1][1], Expect.Elements[1][1]);
EXPECT_FLOAT_EQ(result.Elements[1][2], Expect.Elements[1][2]);
EXPECT_FLOAT_EQ(result.Elements[2][0], Expect.Elements[2][0]);
EXPECT_FLOAT_EQ(result.Elements[2][1], Expect.Elements[2][1]);
EXPECT_FLOAT_EQ(result.Elements[2][2], Expect.Elements[2][2]);
}
#endif
}
}
TEST(InvMatrix, InvGeneral)
{
{
HMM_Mat4 Matrix = {
12.0f, 2.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 5.0f, 1.0f,
11.0f, 1.0f, 0.0f, 10.0f
};
HMM_Mat4 Expect = HMM_M4D(1.0);
HMM_Mat4 Inverse = HMM_InvGeneralM4(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
float Det = HMM_DeterminantM4(Matrix);
EXPECT_FLOAT_EQ(Det, -80.0f);
EXPECT_NEAR(Result.Elements[0][0], Expect.Elements[0][0], 0.00001f);
EXPECT_NEAR(Result.Elements[0][1], Expect.Elements[0][1], 0.00001f);
EXPECT_NEAR(Result.Elements[0][2], Expect.Elements[0][2], 0.00001f);
EXPECT_NEAR(Result.Elements[0][3], Expect.Elements[0][3], 0.00001f);
EXPECT_NEAR(Result.Elements[1][0], Expect.Elements[1][0], 0.00001f);
EXPECT_NEAR(Result.Elements[1][1], Expect.Elements[1][1], 0.00001f);
EXPECT_NEAR(Result.Elements[1][2], Expect.Elements[1][2], 0.00001f);
EXPECT_NEAR(Result.Elements[1][3], Expect.Elements[1][3], 0.00001f);
EXPECT_NEAR(Result.Elements[2][0], Expect.Elements[2][0], 0.00001f);
EXPECT_NEAR(Result.Elements[2][1], Expect.Elements[2][1], 0.00001f);
EXPECT_NEAR(Result.Elements[2][2], Expect.Elements[2][2], 0.00001f);
EXPECT_NEAR(Result.Elements[2][3], Expect.Elements[2][3], 0.00001f);
EXPECT_NEAR(Result.Elements[3][0], Expect.Elements[3][0], 0.00001f);
EXPECT_NEAR(Result.Elements[3][1], Expect.Elements[3][1], 0.00001f);
EXPECT_NEAR(Result.Elements[3][2], Expect.Elements[3][2], 0.00001f);
EXPECT_NEAR(Result.Elements[3][3], Expect.Elements[3][3], 0.00001f);
#ifdef __cplusplus
Inverse = HMM_InvGeneral(Matrix);
Result = HMM_Mul(Matrix, Inverse);
Det = HMM_Determinant(Matrix);
EXPECT_FLOAT_EQ(Det, -80.0f);
EXPECT_NEAR(Result.Elements[0][0], Expect.Elements[0][0], 0.00001f);
EXPECT_NEAR(Result.Elements[0][1], Expect.Elements[0][1], 0.00001f);
EXPECT_NEAR(Result.Elements[0][2], Expect.Elements[0][2], 0.00001f);
EXPECT_NEAR(Result.Elements[0][3], Expect.Elements[0][3], 0.00001f);
EXPECT_NEAR(Result.Elements[1][0], Expect.Elements[1][0], 0.00001f);
EXPECT_NEAR(Result.Elements[1][1], Expect.Elements[1][1], 0.00001f);
EXPECT_NEAR(Result.Elements[1][2], Expect.Elements[1][2], 0.00001f);
EXPECT_NEAR(Result.Elements[1][3], Expect.Elements[1][3], 0.00001f);
EXPECT_NEAR(Result.Elements[2][0], Expect.Elements[2][0], 0.00001f);
EXPECT_NEAR(Result.Elements[2][1], Expect.Elements[2][1], 0.00001f);
EXPECT_NEAR(Result.Elements[2][2], Expect.Elements[2][2], 0.00001f);
EXPECT_NEAR(Result.Elements[2][3], Expect.Elements[2][3], 0.00001f);
EXPECT_NEAR(Result.Elements[3][0], Expect.Elements[3][0], 0.00001f);
EXPECT_NEAR(Result.Elements[3][1], Expect.Elements[3][1], 0.00001f);
EXPECT_NEAR(Result.Elements[3][2], Expect.Elements[3][2], 0.00001f);
EXPECT_NEAR(Result.Elements[3][3], Expect.Elements[3][3], 0.00001f);
#endif
}
{
HMM_Mat3 Matrix = {
12.0f, 2.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 5.0f
};
HMM_Mat3 Expect = HMM_M3D(1.0);
HMM_Mat3 Inverse = HMM_InvGeneralM3(Matrix);
HMM_Mat3 Result = HMM_MulM3(Matrix, Inverse);
float Det = HMM_DeterminantM3(Matrix);
EXPECT_FLOAT_EQ(Det, -12.0f);
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]);
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]);
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]);
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]);
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]);
#ifdef __cplusplus
Inverse = HMM_InvGeneral(Matrix);
Result = HMM_Mul(Matrix, Inverse);
Det = HMM_Determinant(Matrix);
EXPECT_FLOAT_EQ(Det, -12.0f);
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
EXPECT_FLOAT_EQ(Result.Elements[0][2], Expect.Elements[0][2]);
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
EXPECT_FLOAT_EQ(Result.Elements[1][2], Expect.Elements[1][2]);
EXPECT_FLOAT_EQ(Result.Elements[2][0], Expect.Elements[2][0]);
EXPECT_FLOAT_EQ(Result.Elements[2][1], Expect.Elements[2][1]);
EXPECT_FLOAT_EQ(Result.Elements[2][2], Expect.Elements[2][2]);
#endif
}
{
HMM_Mat2 Matrix = {
12.0f, 2.0f,
1.0f, 5.0f
};
HMM_Mat2 Expect = HMM_M2D(1.0);
HMM_Mat2 Inverse = HMM_InvGeneralM2(Matrix);
HMM_Mat2 Result = HMM_MulM2(Matrix, Inverse);
float Det = HMM_DeterminantM2(Matrix);
EXPECT_FLOAT_EQ(Det, 58.0f);
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
#ifdef __cplusplus
Inverse = HMM_InvGeneral(Matrix);
Result = HMM_Mul(Matrix, Inverse);
Det = HMM_Determinant(Matrix);
EXPECT_FLOAT_EQ(Det, 58.0f);
EXPECT_FLOAT_EQ(Result.Elements[0][0], Expect.Elements[0][0]);
EXPECT_FLOAT_EQ(Result.Elements[0][1], Expect.Elements[0][1]);
EXPECT_FLOAT_EQ(Result.Elements[1][0], Expect.Elements[1][0]);
EXPECT_FLOAT_EQ(Result.Elements[1][1], Expect.Elements[1][1]);
#endif
}
}
TEST(InvMatrix, InvOrthographic)
{
{
HMM_Mat4 Matrix = HMM_Orthographic_RH_NO(-160+100, 160+100, -90+200, 90+200, 10, 10000);
HMM_Mat4 Inverse = HMM_InvOrthographic(Matrix);
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
}
{
HMM_Mat4 Matrix = HMM_Orthographic_RH_ZO(-160+100, 160+100, -90+200, 90+200, 10, 10000);
HMM_Mat4 Inverse = HMM_InvOrthographic(Matrix);
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
}
{
HMM_Mat4 Matrix = HMM_Orthographic_LH_NO(-160+100, 160+100, -90+200, 90+200, 10, 10000);
HMM_Mat4 Inverse = HMM_InvOrthographic(Matrix);
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
}
{
HMM_Mat4 Matrix = HMM_Orthographic_LH_ZO(-160+100, 160+100, -90+200, 90+200, 10, 10000);
HMM_Mat4 Inverse = HMM_InvOrthographic(Matrix);
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
}
}
TEST(InvMatrix, InvPerspective)
{
{
HMM_Mat4 Matrix = HMM_Perspective_RH_NO(HMM_AngleDeg(120), 16.0/9.0, 10, 10000);
HMM_Mat4 Inverse = HMM_InvPerspective_RH(Matrix);
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
}
{
HMM_Mat4 Matrix = HMM_Perspective_RH_ZO(HMM_AngleDeg(120), 16.0/9.0, 10, 10000);
HMM_Mat4 Inverse = HMM_InvPerspective_RH(Matrix);
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
}
{
HMM_Mat4 Matrix = HMM_Perspective_LH_NO(HMM_AngleDeg(120), 16.0/9.0, 10, 10000);
HMM_Mat4 Inverse = HMM_InvPerspective_LH(Matrix);
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
}
{
HMM_Mat4 Matrix = HMM_Perspective_LH_ZO(HMM_AngleDeg(120), 16.0/9.0, 10, 10000);
HMM_Mat4 Inverse = HMM_InvPerspective_LH(Matrix);
EXPECT_M4_EQ(HMM_MulM4(Matrix, Inverse), HMM_M4D(1.0f));
}
}
TEST(InvMatrix, InvLookAt)
{
{
HMM_Vec3 Eye = {10.0f, 10.0f, 10.0f};
HMM_Vec3 Center = {100.0f, 200.0f, 30.0f};
HMM_Vec3 Up = {0.0f, 0.0f, 1.0f};
HMM_Mat4 Matrix = HMM_LookAt_RH(Eye, Center, Up);
HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvLookAt(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_M4_NEAR(Result, Expect, 0.001f);
}
{
HMM_Vec3 Eye = {10.0f, 10.0f, 10.0f};
HMM_Vec3 Center = {100.0f, 200.0f, 30.0f};
HMM_Vec3 Up = {0.0f, 0.0f, 1.0f};
HMM_Mat4 Matrix = HMM_LookAt_LH(Eye, Center, Up);
HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvLookAt(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_M4_NEAR(Result, Expect, 0.001f);
}
}
TEST(InvMatrix, InvRotate)
{
{
HMM_Vec3 Axis = {1.0f, -1.0f, 0.5f};
HMM_Mat4 Matrix = HMM_Rotate_RH(HMM_AngleDeg(30), HMM_NormV3(Axis));
HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvRotate(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_M4_NEAR(Result, Expect, 0.001f);
}
{
HMM_Vec3 Axis = {1.0f, -1.0f, 0.5f};
HMM_Mat4 Matrix = HMM_Rotate_LH(HMM_AngleDeg(30), HMM_NormV3(Axis));
HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvRotate(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_M4_NEAR(Result, Expect, 0.001f);
}
}
TEST(InvMatrix, InvScale)
{
HMM_Vec3 Scale = {1.0f, -1.0f, 0.5f};
HMM_Mat4 Matrix = HMM_Scale(Scale);
HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvScale(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_M4_EQ(Result, Expect);
}
TEST(InvMatrix, InvTranslate)
{
HMM_Vec3 Move = {1.0f, -1.0f, 0.5f};
HMM_Mat4 Matrix = HMM_Translate(Move);
HMM_Mat4 Expect = HMM_M4D(1.0f);
HMM_Mat4 Inverse = HMM_InvTranslate(Matrix);
HMM_Mat4 Result = HMM_MulM4(Matrix, Inverse);
EXPECT_M4_EQ(Result, Expect);
}

View File

@@ -2,22 +2,24 @@
TEST(Multiplication, Vec2Vec2) TEST(Multiplication, Vec2Vec2)
{ {
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 2.0f); HMM_Vec2 v2_1 = HMM_V2(1.0f, 2.0f);
hmm_vec2 v2_2 = HMM_Vec2(3.0f, 4.0f); HMM_Vec2 v2_2 = HMM_V2(3.0f, 4.0f);
{ {
hmm_vec2 result = HMM_MultiplyVec2(v2_1, v2_2); HMM_Vec2 result = HMM_MulV2(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f); EXPECT_FLOAT_EQ(result.Y, 8.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Mul(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec2 result = HMM_Multiply(v2_1, v2_2); HMM_Vec2 result = v2_1 * v2_2;
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f);
}
{
hmm_vec2 result = v2_1 * v2_2;
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 8.0f); EXPECT_FLOAT_EQ(result.Y, 8.0f);
} }
@@ -30,27 +32,29 @@ TEST(Multiplication, Vec2Vec2)
TEST(Multiplication, Vec2Scalar) TEST(Multiplication, Vec2Scalar)
{ {
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f); HMM_Vec2 v2 = HMM_V2(1.0f, 2.0f);
float s = 3.0f; float s = 3.0f;
{ {
hmm_vec2 result = HMM_MultiplyVec2f(v2, s); HMM_Vec2 result = HMM_MulV2F(v2, s);
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Mul(v2, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec2 result = HMM_Multiply(v2, s); HMM_Vec2 result = v2 * s;
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
} }
{ {
hmm_vec2 result = v2 * s; HMM_Vec2 result = s * v2;
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
}
{
hmm_vec2 result = s * v2;
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
} }
@@ -63,24 +67,26 @@ TEST(Multiplication, Vec2Scalar)
TEST(Multiplication, Vec3Vec3) TEST(Multiplication, Vec3Vec3)
{ {
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 2.0f, 3.0f); HMM_Vec3 v3_1 = HMM_V3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3_2 = HMM_Vec3(4.0f, 5.0f, 6.0f); HMM_Vec3 v3_2 = HMM_V3(4.0f, 5.0f, 6.0f);
{ {
hmm_vec3 result = HMM_MultiplyVec3(v3_1, v3_2); HMM_Vec3 result = HMM_MulV3(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 4.0f); EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 10.0f); EXPECT_FLOAT_EQ(result.Y, 10.0f);
EXPECT_FLOAT_EQ(result.Z, 18.0f); EXPECT_FLOAT_EQ(result.Z, 18.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Mul(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 10.0f);
EXPECT_FLOAT_EQ(result.Z, 18.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec3 result = HMM_Multiply(v3_1, v3_2); HMM_Vec3 result = v3_1 * v3_2;
EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 10.0f);
EXPECT_FLOAT_EQ(result.Z, 18.0f);
}
{
hmm_vec3 result = v3_1 * v3_2;
EXPECT_FLOAT_EQ(result.X, 4.0f); EXPECT_FLOAT_EQ(result.X, 4.0f);
EXPECT_FLOAT_EQ(result.Y, 10.0f); EXPECT_FLOAT_EQ(result.Y, 10.0f);
EXPECT_FLOAT_EQ(result.Z, 18.0f); EXPECT_FLOAT_EQ(result.Z, 18.0f);
@@ -95,30 +101,32 @@ TEST(Multiplication, Vec3Vec3)
TEST(Multiplication, Vec3Scalar) TEST(Multiplication, Vec3Scalar)
{ {
hmm_vec3 v3 = HMM_Vec3(1.0f, 2.0f, 3.0f); HMM_Vec3 v3 = HMM_V3(1.0f, 2.0f, 3.0f);
float s = 3.0f; float s = 3.0f;
{ {
hmm_vec3 result = HMM_MultiplyVec3f(v3, s); HMM_Vec3 result = HMM_MulV3F(v3, s);
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f); EXPECT_FLOAT_EQ(result.Z, 9.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Mul(v3, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec3 result = HMM_Multiply(v3, s); HMM_Vec3 result = v3 * s;
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f); EXPECT_FLOAT_EQ(result.Z, 9.0f);
} }
{ {
hmm_vec3 result = v3 * s; HMM_Vec3 result = s * v3;
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
}
{
hmm_vec3 result = s * v3;
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f); EXPECT_FLOAT_EQ(result.Z, 9.0f);
@@ -133,26 +141,28 @@ TEST(Multiplication, Vec3Scalar)
TEST(Multiplication, Vec4Vec4) TEST(Multiplication, Vec4Vec4)
{ {
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f); HMM_Vec4 v4_1 = HMM_V4(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_V4(5.0f, 6.0f, 7.0f, 8.0f);
{ {
hmm_vec4 result = HMM_MultiplyVec4(v4_1, v4_2); HMM_Vec4 result = HMM_MulV4(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 5.0f); EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 12.0f); EXPECT_FLOAT_EQ(result.Y, 12.0f);
EXPECT_FLOAT_EQ(result.Z, 21.0f); EXPECT_FLOAT_EQ(result.Z, 21.0f);
EXPECT_FLOAT_EQ(result.W, 32.0f); EXPECT_FLOAT_EQ(result.W, 32.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Mul(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 12.0f);
EXPECT_FLOAT_EQ(result.Z, 21.0f);
EXPECT_FLOAT_EQ(result.W, 32.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec4 result = HMM_Multiply(v4_1, v4_2); HMM_Vec4 result = v4_1 * v4_2;
EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 12.0f);
EXPECT_FLOAT_EQ(result.Z, 21.0f);
EXPECT_FLOAT_EQ(result.W, 32.0f);
}
{
hmm_vec4 result = v4_1 * v4_2;
EXPECT_FLOAT_EQ(result.X, 5.0f); EXPECT_FLOAT_EQ(result.X, 5.0f);
EXPECT_FLOAT_EQ(result.Y, 12.0f); EXPECT_FLOAT_EQ(result.Y, 12.0f);
EXPECT_FLOAT_EQ(result.Z, 21.0f); EXPECT_FLOAT_EQ(result.Z, 21.0f);
@@ -169,33 +179,35 @@ TEST(Multiplication, Vec4Vec4)
TEST(Multiplication, Vec4Scalar) TEST(Multiplication, Vec4Scalar)
{ {
hmm_vec4 v4 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f); HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
float s = 3.0f; float s = 3.0f;
{ {
hmm_vec4 result = HMM_MultiplyVec4f(v4, s); HMM_Vec4 result = HMM_MulV4F(v4, s);
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f); EXPECT_FLOAT_EQ(result.Z, 9.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f); EXPECT_FLOAT_EQ(result.W, 12.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Mul(v4, s);
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec4 result = HMM_Multiply(v4, s); HMM_Vec4 result = v4 * s;
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f); EXPECT_FLOAT_EQ(result.Z, 9.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f); EXPECT_FLOAT_EQ(result.W, 12.0f);
} }
{ {
hmm_vec4 result = v4 * s; HMM_Vec4 result = s * v4;
EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f);
EXPECT_FLOAT_EQ(result.W, 12.0f);
}
{
hmm_vec4 result = s * v4;
EXPECT_FLOAT_EQ(result.X, 3.0f); EXPECT_FLOAT_EQ(result.X, 3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
EXPECT_FLOAT_EQ(result.Z, 9.0f); EXPECT_FLOAT_EQ(result.Z, 9.0f);
@@ -209,10 +221,320 @@ TEST(Multiplication, Vec4Scalar)
#endif #endif
} }
TEST(Multiplication, Mat2Mat2) {
HMM_Mat2 a = HMM_M2();
HMM_Mat2 b = HMM_M2();
int counter = 1;
for (int Column = 0; Column < 2; Column++) {
for (int Row = 0; Row < 2; Row++) {
a.Elements[Column][Row] = counter++;
}
}
for (int Column = 0; Column < 2; Column++) {
for (int Row = 0; Row < 2; Row++) {
b.Elements[Column][Row] = counter++;
}
}
{
HMM_Mat2 result = HMM_MulM2(a,b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 34.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 31.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 46.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat2 result = HMM_Mul(a,b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 34.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 31.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 46.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat2 result = a * b;
EXPECT_FLOAT_EQ(result.Elements[0][0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 34.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 31.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 46.0f);
}
#endif
}
TEST(Multiplication, Mat2Scalar) {
HMM_Mat2 m = HMM_M2();
float s = 10.0f;
int counter = 1;
for (int Column = 0; Column < 2; Column++) {
for (int Row = 0; Row < 2; Row++) {
m.Elements[Column][Row] = counter++;
}
}
{
HMM_Mat2 result = HMM_MulM2F(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat2 result = HMM_Mul(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat2 result = m * s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f);
}
{
HMM_Mat2 result = s * m;
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 40.0f);
}
m *= s;
EXPECT_FLOAT_EQ(m.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(m.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(m.Elements[1][0], 30.0f);
EXPECT_FLOAT_EQ(m.Elements[1][1], 40.0f);
#endif
}
TEST(Multiplication, Mat2Vec2) {
HMM_Mat2 m = HMM_M2();
HMM_Vec2 v = HMM_V2(0.0f, 0.0f);
int counter = 1;
for (int Column = 0; Column < 2; Column++) {
for (int Row = 0; Row < 2; Row++) {
m.Elements[Column][Row] = counter++;
}
}
for (int Row = 0; Row < 2; Row++) {
v.Elements[Row] = counter++;
}
{
HMM_Vec2 result = HMM_MulM2V2(m, v);
EXPECT_FLOAT_EQ(result.Elements[0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[1], 34.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Mul(m, v);
EXPECT_FLOAT_EQ(result.Elements[0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[1], 34.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec2 result = m * v;
EXPECT_FLOAT_EQ(result.Elements[0], 23.0f);
EXPECT_FLOAT_EQ(result.Elements[1], 34.0f);
}
#endif
}
TEST(Multiplication, Mat3Mat3)
{
HMM_Mat3 a = HMM_M3();
HMM_Mat3 b = HMM_M3();
int counter = 1;
for (int Column = 0; Column < 3; Column++) {
for (int Row = 0; Row < 3; Row++) {
a.Elements[Column][Row] = counter++;
}
}
for (int Column = 0; Column < 3; Column++) {
for (int Row = 0; Row < 3; Row++) {
b.Elements[Column][Row] = counter++;
}
}
{
HMM_Mat3 result = HMM_MulM3(a,b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 138.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 171.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 204.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 174.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 216.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 258.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 210.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 261.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 312.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat3 result = HMM_Mul(a,b);
EXPECT_FLOAT_EQ(result.Elements[0][0], 138.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 171.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 204.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 174.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 216.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 258.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 210.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 261.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 312.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat3 result = a * b;
EXPECT_FLOAT_EQ(result.Elements[0][0], 138.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 171.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 204.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 174.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 216.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 258.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 210.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 261.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 312.0f);
}
#endif
}
TEST(Multiplication, Mat3Scalar) {
HMM_Mat3 m = HMM_M3();
float s = 10.0f;
int counter = 1;
for (int Column = 0; Column < 3; Column++) {
for (int Row = 0; Row < 3; Row++) {
m.Elements[Column][Row] = counter++;
}
}
{
HMM_Mat3 result = HMM_MulM3F(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 40.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 50.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 60.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 70.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat3 result = HMM_Mul(m, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 40.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 50.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 60.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 70.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Mat3 result = m * s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 40.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 50.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 60.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 70.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f);
}
{
HMM_Mat3 result = s * m;
EXPECT_FLOAT_EQ(result.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 40.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 50.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 60.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 70.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 80.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 90.0f);
}
m *= s;
EXPECT_FLOAT_EQ(m.Elements[0][0], 10.0f);
EXPECT_FLOAT_EQ(m.Elements[0][1], 20.0f);
EXPECT_FLOAT_EQ(m.Elements[0][2], 30.0f);
EXPECT_FLOAT_EQ(m.Elements[1][0], 40.0f);
EXPECT_FLOAT_EQ(m.Elements[1][1], 50.0f);
EXPECT_FLOAT_EQ(m.Elements[1][2], 60.0f);
EXPECT_FLOAT_EQ(m.Elements[2][0], 70.0f);
EXPECT_FLOAT_EQ(m.Elements[2][1], 80.0f);
EXPECT_FLOAT_EQ(m.Elements[2][2], 90.0f);
#endif
}
TEST(Multiplication, Mat3Vec3) {
HMM_Mat3 m = HMM_M3();
HMM_Vec3 v = HMM_V3(0.0f, 0.0f, 0.0f);
int counter = 1;
for (int Column = 0; Column < 3; Column++) {
for (int Row = 0; Row < 3; Row++) {
m.Elements[Column][Row] = counter++;
}
}
for (int Row = 0; Row < 3; Row++) {
v.Elements[Row] = counter++;
}
{
HMM_Vec3 result = HMM_MulM3V3(m, v);
EXPECT_FLOAT_EQ(result.Elements[0], 138.0f);
EXPECT_FLOAT_EQ(result.Elements[1], 171.0f);
EXPECT_FLOAT_EQ(result.Elements[2], 204.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Mul(m, v);
EXPECT_FLOAT_EQ(result.Elements[0], 138.0f);
EXPECT_FLOAT_EQ(result.Elements[1], 171.0f);
EXPECT_FLOAT_EQ(result.Elements[2], 204.0f);
}
#endif
#ifdef __cplusplus
{
HMM_Vec3 result = m * v;
EXPECT_FLOAT_EQ(result.Elements[0], 138.0f);
EXPECT_FLOAT_EQ(result.Elements[1], 171.0f);
EXPECT_FLOAT_EQ(result.Elements[2], 204.0f);
}
#endif
}
TEST(Multiplication, Mat4Mat4) TEST(Multiplication, Mat4Mat4)
{ {
hmm_mat4 m4_1 = HMM_Mat4(); // will have 1 - 16 HMM_Mat4 m4_1 = HMM_M4(); // will have 1 - 16
hmm_mat4 m4_2 = HMM_Mat4(); // will have 17 - 32 HMM_Mat4 m4_2 = HMM_M4(); // will have 17 - 32
// Fill the matrices // Fill the matrices
int Counter = 1; int Counter = 1;
@@ -235,7 +557,7 @@ TEST(Multiplication, Mat4Mat4)
// Test the results // Test the results
{ {
hmm_mat4 result = HMM_MultiplyMat4(m4_1, m4_2); HMM_Mat4 result = HMM_MulM4(m4_1, m4_2);
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f); EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f); EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
@@ -253,28 +575,30 @@ TEST(Multiplication, Mat4Mat4)
EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f); EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f); EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat4 result = HMM_Mul(m4_1, m4_2);
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
EXPECT_FLOAT_EQ(result.Elements[0][3], 760.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 650.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 740.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 830.0f);
EXPECT_FLOAT_EQ(result.Elements[1][3], 920.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 762.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 868.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 974.0f);
EXPECT_FLOAT_EQ(result.Elements[2][3], 1080.0f);
EXPECT_FLOAT_EQ(result.Elements[3][0], 874.0f);
EXPECT_FLOAT_EQ(result.Elements[3][1], 996.0f);
EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_mat4 result = HMM_Multiply(m4_1, m4_2); HMM_Mat4 result = m4_1 * m4_2;
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
EXPECT_FLOAT_EQ(result.Elements[0][3], 760.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 650.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 740.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 830.0f);
EXPECT_FLOAT_EQ(result.Elements[1][3], 920.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 762.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 868.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 974.0f);
EXPECT_FLOAT_EQ(result.Elements[2][3], 1080.0f);
EXPECT_FLOAT_EQ(result.Elements[3][0], 874.0f);
EXPECT_FLOAT_EQ(result.Elements[3][1], 996.0f);
EXPECT_FLOAT_EQ(result.Elements[3][2], 1118.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 1240.0f);
}
{
hmm_mat4 result = m4_1 * m4_2;
EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 538.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f); EXPECT_FLOAT_EQ(result.Elements[0][1], 612.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f); EXPECT_FLOAT_EQ(result.Elements[0][2], 686.0f);
@@ -301,7 +625,7 @@ TEST(Multiplication, Mat4Mat4)
TEST(Multiplication, Mat4Scalar) TEST(Multiplication, Mat4Scalar)
{ {
hmm_mat4 m4 = HMM_Mat4(); // will have 1 - 16 HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
float s = 3; float s = 3;
// Fill the matrix // Fill the matrix
@@ -317,7 +641,7 @@ TEST(Multiplication, Mat4Scalar)
// Test the results // Test the results
{ {
hmm_mat4 result = HMM_MultiplyMat4f(m4, s); HMM_Mat4 result = HMM_MulM4F(m4, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f); EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f); EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
@@ -335,9 +659,30 @@ TEST(Multiplication, Mat4Scalar)
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f); EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f); EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat4 result = HMM_Mul(m4, s);
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
EXPECT_FLOAT_EQ(result.Elements[0][3], 12.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 15.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 18.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
EXPECT_FLOAT_EQ(result.Elements[1][3], 24.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 27.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 33.0f);
EXPECT_FLOAT_EQ(result.Elements[2][3], 36.0f);
EXPECT_FLOAT_EQ(result.Elements[3][0], 39.0f);
EXPECT_FLOAT_EQ(result.Elements[3][1], 42.0f);
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_mat4 result = HMM_Multiply(m4, s); HMM_Mat4 result = m4 * s;
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f); EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f); EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
@@ -356,26 +701,7 @@ TEST(Multiplication, Mat4Scalar)
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f); EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
} }
{ {
hmm_mat4 result = m4 * s; HMM_Mat4 result = s * m4;
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
EXPECT_FLOAT_EQ(result.Elements[0][3], 12.0f);
EXPECT_FLOAT_EQ(result.Elements[1][0], 15.0f);
EXPECT_FLOAT_EQ(result.Elements[1][1], 18.0f);
EXPECT_FLOAT_EQ(result.Elements[1][2], 21.0f);
EXPECT_FLOAT_EQ(result.Elements[1][3], 24.0f);
EXPECT_FLOAT_EQ(result.Elements[2][0], 27.0f);
EXPECT_FLOAT_EQ(result.Elements[2][1], 30.0f);
EXPECT_FLOAT_EQ(result.Elements[2][2], 33.0f);
EXPECT_FLOAT_EQ(result.Elements[2][3], 36.0f);
EXPECT_FLOAT_EQ(result.Elements[3][0], 39.0f);
EXPECT_FLOAT_EQ(result.Elements[3][1], 42.0f);
EXPECT_FLOAT_EQ(result.Elements[3][2], 45.0f);
EXPECT_FLOAT_EQ(result.Elements[3][3], 48.0f);
}
{
hmm_mat4 result = s * m4;
EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 3.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f); EXPECT_FLOAT_EQ(result.Elements[0][1], 6.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f); EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);
@@ -416,8 +742,8 @@ TEST(Multiplication, Mat4Scalar)
TEST(Multiplication, Mat4Vec4) TEST(Multiplication, Mat4Vec4)
{ {
hmm_mat4 m4 = HMM_Mat4(); // will have 1 - 16 HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
hmm_vec4 v4 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f); HMM_Vec4 v4 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
// Fill the matrix // Fill the matrix
int Counter = 1; int Counter = 1;
@@ -432,22 +758,24 @@ TEST(Multiplication, Mat4Vec4)
// Test the results // Test the results
{ {
hmm_vec4 result = HMM_MultiplyMat4ByVec4(m4, v4); HMM_Vec4 result = HMM_MulM4V4(m4, v4);
EXPECT_FLOAT_EQ(result.X, 90.0f); EXPECT_FLOAT_EQ(result.X, 90.0f);
EXPECT_FLOAT_EQ(result.Y, 100.0f); EXPECT_FLOAT_EQ(result.Y, 100.0f);
EXPECT_FLOAT_EQ(result.Z, 110.0f); EXPECT_FLOAT_EQ(result.Z, 110.0f);
EXPECT_FLOAT_EQ(result.W, 120.0f); EXPECT_FLOAT_EQ(result.W, 120.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Mul(m4, v4);
EXPECT_FLOAT_EQ(result.X, 90.0f);
EXPECT_FLOAT_EQ(result.Y, 100.0f);
EXPECT_FLOAT_EQ(result.Z, 110.0f);
EXPECT_FLOAT_EQ(result.W, 120.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec4 result = HMM_Multiply(m4, v4); HMM_Vec4 result = m4 * v4;
EXPECT_FLOAT_EQ(result.X, 90.0f);
EXPECT_FLOAT_EQ(result.Y, 100.0f);
EXPECT_FLOAT_EQ(result.Z, 110.0f);
EXPECT_FLOAT_EQ(result.W, 120.0f);
}
{
hmm_vec4 result = m4 * v4;
EXPECT_FLOAT_EQ(result.X, 90.0f); EXPECT_FLOAT_EQ(result.X, 90.0f);
EXPECT_FLOAT_EQ(result.Y, 100.0f); EXPECT_FLOAT_EQ(result.Y, 100.0f);
EXPECT_FLOAT_EQ(result.Z, 110.0f); EXPECT_FLOAT_EQ(result.Z, 110.0f);
@@ -460,26 +788,28 @@ TEST(Multiplication, Mat4Vec4)
TEST(Multiplication, QuaternionQuaternion) TEST(Multiplication, QuaternionQuaternion)
{ {
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f); HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f); HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
{ {
hmm_quaternion result = HMM_MultiplyQuaternion(q1, q2); HMM_Quat result = HMM_MulQ(q1, q2);
EXPECT_FLOAT_EQ(result.X, 24.0f); EXPECT_FLOAT_EQ(result.X, 24.0f);
EXPECT_FLOAT_EQ(result.Y, 48.0f); EXPECT_FLOAT_EQ(result.Y, 48.0f);
EXPECT_FLOAT_EQ(result.Z, 48.0f); EXPECT_FLOAT_EQ(result.Z, 48.0f);
EXPECT_FLOAT_EQ(result.W, -6.0f); EXPECT_FLOAT_EQ(result.W, -6.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Quat result = HMM_Mul(q1, q2);
EXPECT_FLOAT_EQ(result.X, 24.0f);
EXPECT_FLOAT_EQ(result.Y, 48.0f);
EXPECT_FLOAT_EQ(result.Z, 48.0f);
EXPECT_FLOAT_EQ(result.W, -6.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_quaternion result = HMM_Multiply(q1, q2); HMM_Quat result = q1 * q2;
EXPECT_FLOAT_EQ(result.X, 24.0f);
EXPECT_FLOAT_EQ(result.Y, 48.0f);
EXPECT_FLOAT_EQ(result.Z, 48.0f);
EXPECT_FLOAT_EQ(result.W, -6.0f);
}
{
hmm_quaternion result = q1 * q2;
EXPECT_FLOAT_EQ(result.X, 24.0f); EXPECT_FLOAT_EQ(result.X, 24.0f);
EXPECT_FLOAT_EQ(result.Y, 48.0f); EXPECT_FLOAT_EQ(result.Y, 48.0f);
EXPECT_FLOAT_EQ(result.Z, 48.0f); EXPECT_FLOAT_EQ(result.Z, 48.0f);
@@ -494,33 +824,35 @@ TEST(Multiplication, QuaternionQuaternion)
TEST(Multiplication, QuaternionScalar) TEST(Multiplication, QuaternionScalar)
{ {
hmm_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f); HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
float f = 2.0f; float f = 2.0f;
{ {
hmm_quaternion result = HMM_MultiplyQuaternionF(q, f); HMM_Quat result = HMM_MulQF(q, f);
EXPECT_FLOAT_EQ(result.X, 2.0f); EXPECT_FLOAT_EQ(result.X, 2.0f);
EXPECT_FLOAT_EQ(result.Y, 4.0f); EXPECT_FLOAT_EQ(result.Y, 4.0f);
EXPECT_FLOAT_EQ(result.Z, 6.0f); EXPECT_FLOAT_EQ(result.Z, 6.0f);
EXPECT_FLOAT_EQ(result.W, 8.0f); EXPECT_FLOAT_EQ(result.W, 8.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Quat result = HMM_Mul(q, f);
EXPECT_FLOAT_EQ(result.X, 2.0f);
EXPECT_FLOAT_EQ(result.Y, 4.0f);
EXPECT_FLOAT_EQ(result.Z, 6.0f);
EXPECT_FLOAT_EQ(result.W, 8.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_quaternion result = HMM_Multiply(q, f); HMM_Quat result = q * f;
EXPECT_FLOAT_EQ(result.X, 2.0f); EXPECT_FLOAT_EQ(result.X, 2.0f);
EXPECT_FLOAT_EQ(result.Y, 4.0f); EXPECT_FLOAT_EQ(result.Y, 4.0f);
EXPECT_FLOAT_EQ(result.Z, 6.0f); EXPECT_FLOAT_EQ(result.Z, 6.0f);
EXPECT_FLOAT_EQ(result.W, 8.0f); EXPECT_FLOAT_EQ(result.W, 8.0f);
} }
{ {
hmm_quaternion result = q * f; HMM_Quat result = f * q;
EXPECT_FLOAT_EQ(result.X, 2.0f);
EXPECT_FLOAT_EQ(result.Y, 4.0f);
EXPECT_FLOAT_EQ(result.Z, 6.0f);
EXPECT_FLOAT_EQ(result.W, 8.0f);
}
{
hmm_quaternion result = f * q;
EXPECT_FLOAT_EQ(result.X, 2.0f); EXPECT_FLOAT_EQ(result.X, 2.0f);
EXPECT_FLOAT_EQ(result.Y, 4.0f); EXPECT_FLOAT_EQ(result.Y, 4.0f);
EXPECT_FLOAT_EQ(result.Z, 6.0f); EXPECT_FLOAT_EQ(result.Z, 6.0f);

View File

@@ -2,35 +2,84 @@
TEST(Projection, Orthographic) TEST(Projection, Orthographic)
{ {
hmm_mat4 projection = HMM_Orthographic(-10.0f, 10.0f, -5.0f, 5.0f, 0.0f, -10.0f); #define ORTHO_BOUNDS -8.0f, 12.0f, 5.0f, 10.0f, 1.0f, 100.0f
hmm_vec3 original = HMM_Vec3(5.0f, 5.0f, -5.0f); // Right-handed
hmm_vec4 projected = HMM_MultiplyMat4ByVec4(projection, HMM_Vec4v(original, 1)); {
// Near and far distances correspond to negative Z, hence the Z coordinates here are negative.
HMM_Vec4 minCorner = HMM_V4(-8.0f, 5.0f, -1.0f, 1.0);
HMM_Vec4 maxCorner = HMM_V4(12.0f, 10.0f, -100.0f, 1.0);
EXPECT_FLOAT_EQ(projected.X, 0.5f); // Z from -1 to 1 (GL convention)
EXPECT_FLOAT_EQ(projected.Y, 1.0f); {
EXPECT_FLOAT_EQ(projected.Z, -2.0f); HMM_Mat4 projection = HMM_Orthographic_RH_NO(ORTHO_BOUNDS);
EXPECT_FLOAT_EQ(projected.W, 1.0f); EXPECT_V4_EQ(HMM_MulM4V4(projection, minCorner), HMM_V4(-1.0f, -1.0f, -1.0f, 1.0f));
EXPECT_V4_EQ(HMM_MulM4V4(projection, maxCorner), HMM_V4(1.0f, 1.0f, 1.0f, 1.0f));
}
// Z from 0 to 1 (DX convention)
{
HMM_Mat4 projection = HMM_Orthographic_RH_ZO(ORTHO_BOUNDS);
EXPECT_V4_EQ(HMM_MulM4V4(projection, minCorner), HMM_V4(-1.0f, -1.0f, 0.0f, 1.0f));
EXPECT_V4_EQ(HMM_MulM4V4(projection, maxCorner), HMM_V4(1.0f, 1.0f, 1.0f, 1.0f));
}
}
// Left-handed
{
// Near and far distances correspond to positive Z, hence the Z coordinates here are positive.
HMM_Vec4 minCorner = HMM_V4(-8.0f, 5.0f, 1.0f, 1.0);
HMM_Vec4 maxCorner = HMM_V4(12.0f, 10.0f, 100.0f, 1.0);
// Z from -1 to 1 (GL convention)
{
HMM_Mat4 projection = HMM_Orthographic_LH_NO(ORTHO_BOUNDS);
EXPECT_V4_EQ(HMM_MulM4V4(projection, minCorner), HMM_V4(-1.0f, -1.0f, -1.0f, 1.0f));
EXPECT_V4_EQ(HMM_MulM4V4(projection, maxCorner), HMM_V4(1.0f, 1.0f, 1.0f, 1.0f));
}
// Z from 0 to 1 (DX convention)
{
HMM_Mat4 projection = HMM_Orthographic_LH_ZO(ORTHO_BOUNDS);
EXPECT_V4_EQ(HMM_MulM4V4(projection, minCorner), HMM_V4(-1.0f, -1.0f, 0.0f, 1.0f));
EXPECT_V4_EQ(HMM_MulM4V4(projection, maxCorner), HMM_V4(1.0f, 1.0f, 1.0f, 1.0f));
}
}
} }
TEST(Projection, Perspective) TEST(Projection, Perspective)
{ {
hmm_mat4 projection = HMM_Perspective(90.0f, 2.0f, 5.0f, 15.0f); // Right-handed
{
// Z from -1 to 1 (GL convention)
{
HMM_Mat4 projection = HMM_Perspective_RH_NO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f);
HMM_Vec4 original = HMM_V4(5.0f, 5.0f, -1.0f, 1.0f);
EXPECT_V4_EQ(HMM_MulM4V4(projection, original), HMM_V4(2.5f, 5.0f, -1.0f, 1.0f));
}
{ // Z from 0 to 1 (DX convention)
hmm_vec3 original = HMM_Vec3(5.0f, 5.0f, -15.0f); {
hmm_vec4 projected = HMM_MultiplyMat4ByVec4(projection, HMM_Vec4v(original, 1)); HMM_Mat4 projection = HMM_Perspective_RH_ZO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f);
EXPECT_FLOAT_EQ(projected.X, 5.0f); HMM_Vec4 original = HMM_V4(5.0f, 5.0f, -1.0f, 1.0f);
EXPECT_FLOAT_EQ(projected.Y, 10.0f); EXPECT_V4_EQ(HMM_MulM4V4(projection, original), HMM_V4(2.5f, 5.0f, 0.0f, 1.0f));
EXPECT_FLOAT_EQ(projected.Z, 15.0f); }
EXPECT_FLOAT_EQ(projected.W, 15.0f);
} }
// Left-handed
{ {
hmm_vec3 original = HMM_Vec3(5.0f, 5.0f, -5.0f); // Z from -1 to 1 (GL convention)
hmm_vec4 projected = HMM_MultiplyMat4ByVec4(projection, HMM_Vec4v(original, 1)); {
EXPECT_FLOAT_EQ(projected.X, 5.0f); HMM_Mat4 projection = HMM_Perspective_LH_NO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f);
EXPECT_FLOAT_EQ(projected.Y, 10.0f); HMM_Vec4 original = HMM_V4(5.0f, 5.0f, 1.0f, 1.0f);
EXPECT_FLOAT_EQ(projected.Z, -5.0f); EXPECT_V4_EQ(HMM_MulM4V4(projection, original), HMM_V4(2.5f, 5.0f, -1.0f, 1.0f));
EXPECT_FLOAT_EQ(projected.W, 5.0f); }
// Z from 0 to 1 (DX convention)
{
HMM_Mat4 projection = HMM_Perspective_LH_ZO(HMM_AngleDeg(90.0f), 2.0f, 1.0f, 15.0f);
HMM_Vec4 original = HMM_V4(5.0f, 5.0f, 1.0f, 1.0f);
EXPECT_V4_EQ(HMM_MulM4V4(projection, original), HMM_V4(2.5f, 5.0f, 0.0f, 1.0f));
}
} }
} }

View File

@@ -2,10 +2,10 @@
TEST(QuaternionOps, Inverse) TEST(QuaternionOps, Inverse)
{ {
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f); HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion inverse = HMM_InverseQuaternion(q1); HMM_Quat inverse = HMM_InvQ(q1);
hmm_quaternion result = HMM_MultiplyQuaternion(q1, inverse); HMM_Quat result = HMM_MulQ(q1, inverse);
EXPECT_FLOAT_EQ(result.X, 0.0f); EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f); EXPECT_FLOAT_EQ(result.Y, 0.0f);
@@ -15,14 +15,14 @@ TEST(QuaternionOps, Inverse)
TEST(QuaternionOps, Dot) TEST(QuaternionOps, Dot)
{ {
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f); HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f); HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
{ {
float result = HMM_DotQuaternion(q1, q2); float result = HMM_DotQ(q1, q2);
EXPECT_FLOAT_EQ(result, 70.0f); EXPECT_FLOAT_EQ(result, 70.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
float result = HMM_Dot(q1, q2); float result = HMM_Dot(q1, q2);
EXPECT_FLOAT_EQ(result, 70.0f); EXPECT_FLOAT_EQ(result, 70.0f);
@@ -32,57 +32,87 @@ TEST(QuaternionOps, Dot)
TEST(QuaternionOps, Normalize) TEST(QuaternionOps, Normalize)
{ {
hmm_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f); HMM_Quat q = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
{ {
hmm_quaternion result = HMM_NormalizeQuaternion(q); HMM_Quat result = HMM_NormQ(q);
EXPECT_FLOAT_EQ(result.X, 0.1825741858f); EXPECT_NEAR(result.X, 0.1825741858f, 0.001f);
EXPECT_FLOAT_EQ(result.Y, 0.3651483717f); EXPECT_NEAR(result.Y, 0.3651483717f, 0.001f);
EXPECT_FLOAT_EQ(result.Z, 0.5477225575f); EXPECT_NEAR(result.Z, 0.5477225575f, 0.001f);
EXPECT_FLOAT_EQ(result.W, 0.7302967433f); EXPECT_NEAR(result.W, 0.7302967433f, 0.001f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
hmm_quaternion result = HMM_Normalize(q); HMM_Quat result = HMM_Norm(q);
EXPECT_FLOAT_EQ(result.X, 0.1825741858f); EXPECT_NEAR(result.X, 0.1825741858f, 0.001f);
EXPECT_FLOAT_EQ(result.Y, 0.3651483717f); EXPECT_NEAR(result.Y, 0.3651483717f, 0.001f);
EXPECT_FLOAT_EQ(result.Z, 0.5477225575f); EXPECT_NEAR(result.Z, 0.5477225575f, 0.001f);
EXPECT_FLOAT_EQ(result.W, 0.7302967433f); EXPECT_NEAR(result.W, 0.7302967433f, 0.001f);
} }
#endif #endif
} }
TEST(QuaternionOps, NLerp) TEST(QuaternionOps, NLerp)
{ {
hmm_quaternion from = HMM_Quaternion(0.0f, 0.0f, 0.0f, 1.0f); HMM_Quat from = HMM_Q(0.0f, 0.0f, 0.0f, 1.0f);
hmm_quaternion to = HMM_Quaternion(0.5f, 0.5f, -0.5f, 0.5f); HMM_Quat to = HMM_Q(0.5f, 0.5f, -0.5f, 0.5f);
hmm_quaternion result = HMM_NLerp(from, 0.5f, to); HMM_Quat result = HMM_NLerp(from, 0.5f, to);
EXPECT_FLOAT_EQ(result.X, 0.28867513f); EXPECT_NEAR(result.X, 0.28867513f, 0.001f);
EXPECT_FLOAT_EQ(result.Y, 0.28867513f); EXPECT_NEAR(result.Y, 0.28867513f, 0.001f);
EXPECT_FLOAT_EQ(result.Z, -0.28867513f); EXPECT_NEAR(result.Z, -0.28867513f, 0.001f);
EXPECT_FLOAT_EQ(result.W, 0.86602540f); EXPECT_NEAR(result.W, 0.86602540f, 0.001f);
} }
TEST(QuaternionOps, Slerp) TEST(QuaternionOps, SLerp)
{ {
hmm_quaternion from = HMM_Quaternion(0.0f, 0.0f, 0.0f, 1.0f); HMM_Quat from = HMM_Q(0.0f, 0.0f, 0.0f, 1.0f);
hmm_quaternion to = HMM_Quaternion(0.5f, 0.5f, -0.5f, 0.5f); HMM_Quat to = HMM_Q(0.5f, 0.5f, -0.5f, 0.5f);
hmm_quaternion result = HMM_Slerp(from, 0.5f, to); {
EXPECT_FLOAT_EQ(result.X, 0.28867513f); HMM_Quat result = HMM_SLerp(from, 0.0f, to);
EXPECT_FLOAT_EQ(result.Y, 0.28867513f); EXPECT_NEAR(result.X, 0.0f, 0.001f);
EXPECT_FLOAT_EQ(result.Z, -0.28867513f); EXPECT_NEAR(result.Y, 0.0f, 0.001f);
EXPECT_FLOAT_EQ(result.W, 0.86602540f); EXPECT_NEAR(result.Z, 0.0f, 0.001f);
EXPECT_NEAR(result.W, 1.0, 0.001f);
}
{
HMM_Quat result = HMM_SLerp(from, 0.25f, to);
EXPECT_NEAR(result.X, 0.149429246f, 0.001f);
EXPECT_NEAR(result.Y, 0.149429246f, 0.001f);
EXPECT_NEAR(result.Z, -0.149429246f, 0.001f);
EXPECT_NEAR(result.W, 0.965925812f, 0.001f);
}
{
HMM_Quat result = HMM_SLerp(from, 0.5f, to);
EXPECT_NEAR(result.X, 0.28867513f, 0.001f);
EXPECT_NEAR(result.Y, 0.28867513f, 0.001f);
EXPECT_NEAR(result.Z, -0.28867513f, 0.001f);
EXPECT_NEAR(result.W, 0.86602540f, 0.001f);
}
{
HMM_Quat result = HMM_SLerp(from, 0.75f, to);
EXPECT_NEAR(result.X, 0.40824830f, 0.001f);
EXPECT_NEAR(result.Y, 0.40824830f, 0.001f);
EXPECT_NEAR(result.Z, -0.40824830f, 0.001f);
EXPECT_NEAR(result.W, 0.70710676f, 0.001f);
}
{
HMM_Quat result = HMM_SLerp(from, 1.0f, to);
EXPECT_NEAR(result.X, 0.5f, 0.001f);
EXPECT_NEAR(result.Y, 0.5f, 0.001f);
EXPECT_NEAR(result.Z, -0.5f, 0.001f);
EXPECT_NEAR(result.W, 0.5f, 0.001f);
}
} }
TEST(QuaternionOps, ToMat4) TEST(QuaternionOps, QuatToMat4)
{ {
const float abs_error = 0.0001f; const float abs_error = 0.001f;
hmm_quaternion rot = HMM_Quaternion(0.707107f, 0.0f, 0.0f, 0.707107f); HMM_Quat rot = HMM_Q(0.707107f, 0.0f, 0.0f, 0.707107f);
hmm_mat4 result = HMM_QuaternionToMat4(rot); HMM_Mat4 result = HMM_QToM4(rot);
EXPECT_NEAR(result.Elements[0][0], 1.0f, abs_error); EXPECT_NEAR(result.Elements[0][0], 1.0f, abs_error);
EXPECT_NEAR(result.Elements[0][1], 0.0f, abs_error); EXPECT_NEAR(result.Elements[0][1], 0.0f, abs_error);
@@ -105,14 +135,163 @@ TEST(QuaternionOps, ToMat4)
EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error); EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error);
} }
TEST(QuaternionOps, FromAxisAngle) TEST(QuaternionOps, Mat4ToQuat)
{ {
hmm_vec3 axis = HMM_Vec3(1.0f, 0.0f, 0.0f); const float abs_error = 0.0001f;
float angle = HMM_PI32 / 2.0f;
hmm_quaternion result = HMM_QuaternionFromAxisAngle(axis, angle); // Rotate 90 degrees on the X axis
EXPECT_NEAR(result.X, 0.707107f, FLT_EPSILON * 2); {
EXPECT_FLOAT_EQ(result.Y, 0.0f); HMM_Mat4 m = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(1, 0, 0));
EXPECT_FLOAT_EQ(result.Z, 0.0f); HMM_Quat result = HMM_M4ToQ_RH(m);
EXPECT_NEAR(result.W, 0.707107f, FLT_EPSILON * 2);
} 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_RH(HMM_AngleDeg(90.0f), HMM_V3(0, 2, 0));
HMM_Quat result = HMM_M4ToQ_RH(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_RH(HMM_AngleDeg(90.0f), HMM_V3(0, 0, 1));
HMM_Quat result = HMM_M4ToQ_RH(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_RH(HMM_AngleDeg(45.0f), HMM_V3(1, 0, 0));
HMM_Quat result = HMM_M4ToQ_RH(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);
}
/* NOTE(lcf): Left-handed cases. Since both Rotate and M4ToQ are LH results should be
the same with no changes to input. */
// Rotate 90 degrees on the X axis
{
HMM_Mat4 m = HMM_Rotate_LH(HMM_AngleDeg(90.0f), HMM_V3(1, 0, 0));
HMM_Quat result = HMM_M4ToQ_LH(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_LH(HMM_AngleDeg(90.0f), HMM_V3(0, 2, 0));
HMM_Quat result = HMM_M4ToQ_LH(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_LH(HMM_AngleDeg(90.0f), HMM_V3(0, 0, 1));
HMM_Quat result = HMM_M4ToQ_LH(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_LH(HMM_AngleDeg(45.0f), HMM_V3(1, 0, 0));
HMM_Quat result = HMM_M4ToQ_LH(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, RotateVectorAxisAngle)
{
{
HMM_Vec3 axis = HMM_V3(0.0f, 1.0f, 0.0f);
float angle = HMM_AngleTurn(1.0/4);
HMM_Vec3 result = HMM_RotateV3AxisAngle_LH(HMM_V3(1.0f, 0.0f, 0.0f), axis, angle);
EXPECT_NEAR(result.X, 0.0f, 0.001f);
EXPECT_NEAR(result.Y, 0.0f, 0.001f);
EXPECT_NEAR(result.Z, 1.0f, 0.001f);
}
{
HMM_Vec3 axis = HMM_V3(1.0f, 0.0f, 0.0f);
float angle = HMM_AngleTurn(1.0/8);
HMM_Vec3 result = HMM_RotateV3AxisAngle_RH(HMM_V3(0.0f, 0.0f, 1.0f), axis, angle);
EXPECT_NEAR(result.X, 0.0f, 0.001f);
EXPECT_NEAR(result.Y, -0.707170f, 0.001f);
EXPECT_NEAR(result.Z, 0.707170f, 0.001f);
}
}
TEST(QuaternionOps, QuatFromPairs)
{
{
HMM_Vec3 n1 = HMM_V3(0.0f, 1.0f, 0.0f);
HMM_Vec3 n2 = HMM_V3(0.0f, 0.0f, 1.0f);
HMM_Quat q = HMM_QFromNormPair(n1, n2);
HMM_Vec3 result = HMM_RotateV3Q(n1, q);
EXPECT_NEAR(result.X, n2.X, 0.001f);
EXPECT_NEAR(result.Y, n2.Y, 0.001f);
EXPECT_NEAR(result.Z, n2.Z, 0.001f);
}
{
HMM_Vec3 v1 = HMM_V3(2.0f, 2.0f, 2.0f);
HMM_Vec3 v2 = HMM_V3(3.0f, 0.0f, 0.0f);
HMM_Quat q = HMM_QFromVecPair(v1, v2);
HMM_Vec3 result = HMM_RotateV3Q(HMM_V3(0.0f, 1.0f, 0.0f), q);
EXPECT_NEAR(result.X, 0.577350, 0.001f);
EXPECT_NEAR(result.Y, 0.788675, 0.001f);
EXPECT_NEAR(result.Z, -0.211325, 0.001f);
}
}

View File

@@ -4,36 +4,36 @@
TEST(SSE, LinearCombine) TEST(SSE, LinearCombine)
{ {
hmm_mat4 MatrixOne = HMM_Mat4d(2.0f); HMM_Mat4 MatrixOne = HMM_M4D(2.0f);
hmm_mat4 MatrixTwo = HMM_Mat4d(4.0f); HMM_Mat4 MatrixTwo = HMM_M4D(4.0f);
hmm_mat4 Result; HMM_Mat4 Result;
Result.Columns[0] = HMM_LinearCombineSSE(MatrixOne.Columns[0], MatrixTwo); Result.Columns[0] = HMM_LinearCombineV4M4(MatrixOne.Columns[0], MatrixTwo);
Result.Columns[1] = HMM_LinearCombineSSE(MatrixOne.Columns[1], MatrixTwo); Result.Columns[1] = HMM_LinearCombineV4M4(MatrixOne.Columns[1], MatrixTwo);
Result.Columns[2] = HMM_LinearCombineSSE(MatrixOne.Columns[2], MatrixTwo); Result.Columns[2] = HMM_LinearCombineV4M4(MatrixOne.Columns[2], MatrixTwo);
Result.Columns[3] = HMM_LinearCombineSSE(MatrixOne.Columns[3], MatrixTwo); Result.Columns[3] = HMM_LinearCombineV4M4(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

@@ -28,47 +28,26 @@ TEST(ScalarMath, Trigonometry)
// checking that things work by default. // checking that things work by default.
} }
TEST(ScalarMath, ToRadians)
{
EXPECT_FLOAT_EQ(HMM_ToRadians(0.0f), 0.0f);
EXPECT_FLOAT_EQ(HMM_ToRadians(180.0f), HMM_PI32);
EXPECT_FLOAT_EQ(HMM_ToRadians(-180.0f), -HMM_PI32);
}
TEST(ScalarMath, SquareRoot) TEST(ScalarMath, SquareRoot)
{ {
EXPECT_FLOAT_EQ(HMM_SquareRootF(16.0f), 4.0f); EXPECT_FLOAT_EQ(HMM_SqrtF(16.0f), 4.0f);
} }
TEST(ScalarMath, RSquareRootF) TEST(ScalarMath, RSquareRootF)
{ {
EXPECT_NEAR(HMM_RSquareRootF(10.0f), 0.31616211f, 0.0001f); EXPECT_NEAR(HMM_InvSqrtF(10.0f), 0.31616211f, 0.0001f);
}
TEST(ScalarMath, Power)
{
EXPECT_FLOAT_EQ(HMM_Power(2.0f, 0), 1.0f);
EXPECT_FLOAT_EQ(HMM_Power(2.0f, 4), 16.0f);
EXPECT_FLOAT_EQ(HMM_Power(2.0f, -2), 0.25f);
}
TEST(ScalarMath, PowerF)
{
EXPECT_FLOAT_EQ(HMM_PowerF(2.0f, 0), 1.0f);
EXPECT_NEAR(HMM_PowerF(2.0f, 4.1), 17.148376f, 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

@@ -2,22 +2,24 @@
TEST(Subtraction, Vec2) TEST(Subtraction, Vec2)
{ {
hmm_vec2 v2_1 = HMM_Vec2(1.0f, 2.0f); HMM_Vec2 v2_1 = HMM_V2(1.0f, 2.0f);
hmm_vec2 v2_2 = HMM_Vec2(3.0f, 4.0f); HMM_Vec2 v2_2 = HMM_V2(3.0f, 4.0f);
{ {
hmm_vec2 result = HMM_SubtractVec2(v2_1, v2_2); HMM_Vec2 result = HMM_SubV2(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, -2.0f); EXPECT_FLOAT_EQ(result.X, -2.0f);
EXPECT_FLOAT_EQ(result.Y, -2.0f); EXPECT_FLOAT_EQ(result.Y, -2.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Sub(v2_1, v2_2);
EXPECT_FLOAT_EQ(result.X, -2.0f);
EXPECT_FLOAT_EQ(result.Y, -2.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec2 result = HMM_Subtract(v2_1, v2_2); HMM_Vec2 result = v2_1 - v2_2;
EXPECT_FLOAT_EQ(result.X, -2.0f);
EXPECT_FLOAT_EQ(result.Y, -2.0f);
}
{
hmm_vec2 result = v2_1 - v2_2;
EXPECT_FLOAT_EQ(result.X, -2.0f); EXPECT_FLOAT_EQ(result.X, -2.0f);
EXPECT_FLOAT_EQ(result.Y, -2.0f); EXPECT_FLOAT_EQ(result.Y, -2.0f);
} }
@@ -30,24 +32,26 @@ TEST(Subtraction, Vec2)
TEST(Subtraction, Vec3) TEST(Subtraction, Vec3)
{ {
hmm_vec3 v3_1 = HMM_Vec3(1.0f, 2.0f, 3.0f); HMM_Vec3 v3_1 = HMM_V3(1.0f, 2.0f, 3.0f);
hmm_vec3 v3_2 = HMM_Vec3(4.0f, 5.0f, 6.0f); HMM_Vec3 v3_2 = HMM_V3(4.0f, 5.0f, 6.0f);
{ {
hmm_vec3 result = HMM_SubtractVec3(v3_1, v3_2); HMM_Vec3 result = HMM_SubV3(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, -3.0f); EXPECT_FLOAT_EQ(result.X, -3.0f);
EXPECT_FLOAT_EQ(result.Y, -3.0f); EXPECT_FLOAT_EQ(result.Y, -3.0f);
EXPECT_FLOAT_EQ(result.Z, -3.0f); EXPECT_FLOAT_EQ(result.Z, -3.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Sub(v3_1, v3_2);
EXPECT_FLOAT_EQ(result.X, -3.0f);
EXPECT_FLOAT_EQ(result.Y, -3.0f);
EXPECT_FLOAT_EQ(result.Z, -3.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec3 result = HMM_Subtract(v3_1, v3_2); HMM_Vec3 result = v3_1 - v3_2;
EXPECT_FLOAT_EQ(result.X, -3.0f);
EXPECT_FLOAT_EQ(result.Y, -3.0f);
EXPECT_FLOAT_EQ(result.Z, -3.0f);
}
{
hmm_vec3 result = v3_1 - v3_2;
EXPECT_FLOAT_EQ(result.X, -3.0f); EXPECT_FLOAT_EQ(result.X, -3.0f);
EXPECT_FLOAT_EQ(result.Y, -3.0f); EXPECT_FLOAT_EQ(result.Y, -3.0f);
EXPECT_FLOAT_EQ(result.Z, -3.0f); EXPECT_FLOAT_EQ(result.Z, -3.0f);
@@ -62,26 +66,28 @@ TEST(Subtraction, Vec3)
TEST(Subtraction, Vec4) TEST(Subtraction, Vec4)
{ {
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f); HMM_Vec4 v4_1 = HMM_V4(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_V4(5.0f, 6.0f, 7.0f, 8.0f);
{ {
hmm_vec4 result = HMM_SubtractVec4(v4_1, v4_2); HMM_Vec4 result = HMM_SubV4(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, -4.0f); EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f); EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f); EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f); EXPECT_FLOAT_EQ(result.W, -4.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Sub(v4_1, v4_2);
EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_vec4 result = HMM_Subtract(v4_1, v4_2); HMM_Vec4 result = v4_1 - v4_2;
EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f);
}
{
hmm_vec4 result = v4_1 - v4_2;
EXPECT_FLOAT_EQ(result.X, -4.0f); EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f); EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f); EXPECT_FLOAT_EQ(result.Z, -4.0f);
@@ -96,10 +102,127 @@ TEST(Subtraction, Vec4)
#endif #endif
} }
TEST(Subtraction, Mat2)
{
HMM_Mat2 a = HMM_M2();
HMM_Mat2 b = HMM_M2();
int Counter = 1;
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
a.Elements[Column][Row] = Counter++;
}
}
for (int Column = 0; Column < 2; ++Column)
{
for (int Row = 0; Row < 2; ++Row)
{
b.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat2 result = HMM_SubM2(b,a);
EXPECT_FLOAT_EQ(result.Elements[0][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][1], 4.0);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat2 result = HMM_Sub(b,a);
EXPECT_FLOAT_EQ(result.Elements[0][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][1], 4.0);
}
#endif
#ifdef __cplusplus
{
HMM_Mat2 result = b - a;
EXPECT_FLOAT_EQ(result.Elements[0][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[0][1], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][0], 4.0);
EXPECT_FLOAT_EQ(result.Elements[1][1], 4.0);
}
b -= a;
EXPECT_FLOAT_EQ(b.Elements[0][0], 4.0);
EXPECT_FLOAT_EQ(b.Elements[0][1], 4.0);
EXPECT_FLOAT_EQ(b.Elements[1][0], 4.0);
EXPECT_FLOAT_EQ(b.Elements[1][1], 4.0);
#endif
}
TEST(Subtraction, Mat3)
{
HMM_Mat3 a = HMM_M3();
HMM_Mat3 b = HMM_M3();
int Counter = 1;
for (int Column = 0; Column < 3; ++Column)
{
for (int Row = 0; Row < 3; ++Row)
{
a.Elements[Column][Row] = Counter++;
}
}
for (int Column = 0; Column < 3; ++Column)
{
for (int Row = 0; Row < 3; ++Row)
{
b.Elements[Column][Row] = Counter++;
}
}
{
HMM_Mat3 result = HMM_SubM3(b,a);
EXPECT_FLOAT_EQ(result.Elements[0][0], 9.0);
EXPECT_FLOAT_EQ(result.Elements[0][1], 9.0);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0);
EXPECT_FLOAT_EQ(result.Elements[1][0], 9.0);
EXPECT_FLOAT_EQ(result.Elements[1][1], 9.0);
EXPECT_FLOAT_EQ(result.Elements[1][2], 9.0);
EXPECT_FLOAT_EQ(result.Elements[2][0], 9.0);
EXPECT_FLOAT_EQ(result.Elements[2][1], 9.0);
EXPECT_FLOAT_EQ(result.Elements[2][2], 9.0);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat3 result = HMM_Sub(b,a);
EXPECT_FLOAT_EQ(result.Elements[0][0], 9.0);
EXPECT_FLOAT_EQ(result.Elements[0][1], 9.0);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0);
EXPECT_FLOAT_EQ(result.Elements[1][0], 9.0);
EXPECT_FLOAT_EQ(result.Elements[1][1], 9.0);
EXPECT_FLOAT_EQ(result.Elements[1][2], 9.0);
EXPECT_FLOAT_EQ(result.Elements[2][0], 9.0);
EXPECT_FLOAT_EQ(result.Elements[2][1], 9.0);
EXPECT_FLOAT_EQ(result.Elements[2][2], 9.0);
}
#endif
#ifdef __cplusplus
b -= a;
EXPECT_FLOAT_EQ(b.Elements[0][0], 9.0);
EXPECT_FLOAT_EQ(b.Elements[0][1], 9.0);
EXPECT_FLOAT_EQ(b.Elements[0][2], 9.0);
EXPECT_FLOAT_EQ(b.Elements[1][0], 9.0);
EXPECT_FLOAT_EQ(b.Elements[1][1], 9.0);
EXPECT_FLOAT_EQ(b.Elements[1][2], 9.0);
EXPECT_FLOAT_EQ(b.Elements[2][0], 9.0);
EXPECT_FLOAT_EQ(b.Elements[2][1], 9.0);
EXPECT_FLOAT_EQ(b.Elements[2][2], 9.0);
#endif
}
TEST(Subtraction, Mat4) TEST(Subtraction, Mat4)
{ {
hmm_mat4 m4_1 = HMM_Mat4(); // will have 1 - 16 HMM_Mat4 m4_1 = HMM_M4(); // will have 1 - 16
hmm_mat4 m4_2 = HMM_Mat4(); // will have 17 - 32 HMM_Mat4 m4_2 = HMM_M4(); // will have 17 - 32
// Fill the matrices // Fill the matrices
int Counter = 1; int Counter = 1;
@@ -122,7 +245,7 @@ TEST(Subtraction, Mat4)
// Test the results // Test the results
{ {
hmm_mat4 result = HMM_SubtractMat4(m4_1, m4_2); HMM_Mat4 result = HMM_SubM4(m4_1, m4_2);
for (int Column = 0; Column < 4; ++Column) for (int Column = 0; Column < 4; ++Column)
{ {
for (int Row = 0; Row < 4; ++Row) for (int Row = 0; Row < 4; ++Row)
@@ -131,19 +254,21 @@ TEST(Subtraction, Mat4)
} }
} }
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Mat4 result = HMM_Sub(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);
}
}
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_mat4 result = HMM_Subtract(m4_1, m4_2); HMM_Mat4 result = 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);
}
}
}
{
hmm_mat4 result = m4_1 - m4_2;
for (int Column = 0; Column < 4; ++Column) for (int Column = 0; Column < 4; ++Column)
{ {
for (int Row = 0; Row < 4; ++Row) for (int Row = 0; Row < 4; ++Row)
@@ -166,26 +291,28 @@ TEST(Subtraction, Mat4)
TEST(Subtraction, Quaternion) TEST(Subtraction, Quaternion)
{ {
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f); HMM_Quat q1 = HMM_Q(1.0f, 2.0f, 3.0f, 4.0f);
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f); HMM_Quat q2 = HMM_Q(5.0f, 6.0f, 7.0f, 8.0f);
{ {
hmm_quaternion result = HMM_SubtractQuaternion(q1, q2); HMM_Quat result = HMM_SubQ(q1, q2);
EXPECT_FLOAT_EQ(result.X, -4.0f); EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f); EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f); EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f); EXPECT_FLOAT_EQ(result.W, -4.0f);
} }
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Quat result = HMM_Sub(q1, q2);
EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f);
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
{ {
hmm_quaternion result = HMM_Subtract(q1, q2); HMM_Quat result = q1 - q2;
EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f);
EXPECT_FLOAT_EQ(result.W, -4.0f);
}
{
hmm_quaternion result = q1 - q2;
EXPECT_FLOAT_EQ(result.X, -4.0f); EXPECT_FLOAT_EQ(result.X, -4.0f);
EXPECT_FLOAT_EQ(result.Y, -4.0f); EXPECT_FLOAT_EQ(result.Y, -4.0f);
EXPECT_FLOAT_EQ(result.Z, -4.0f); EXPECT_FLOAT_EQ(result.Z, -4.0f);
@@ -199,3 +326,32 @@ TEST(Subtraction, Quaternion)
EXPECT_FLOAT_EQ(q1.W, -4.0f); EXPECT_FLOAT_EQ(q1.W, -4.0f);
#endif #endif
} }
#ifdef __cplusplus
TEST(UnaryMinus, Vec2)
{
HMM_Vec2 VectorOne = {1.0f, 2.0f};
HMM_Vec2 Result = -VectorOne;
EXPECT_FLOAT_EQ(Result.X, -1.0f);
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
}
TEST(UnaryMinus, Vec3)
{
HMM_Vec3 VectorOne = {1.0f, 2.0f, 3.0f};
HMM_Vec3 Result = -VectorOne;
EXPECT_FLOAT_EQ(Result.X, -1.0f);
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
EXPECT_FLOAT_EQ(Result.Z, -3.0f);
}
TEST(UnaryMinus, Vec4)
{
HMM_Vec4 VectorOne = {1.0f, 2.0f, 3.0f, 4.0f};
HMM_Vec4 Result = -VectorOne;
EXPECT_FLOAT_EQ(Result.X, -1.0f);
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
EXPECT_FLOAT_EQ(Result.Z, -3.0f);
EXPECT_FLOAT_EQ(Result.W, -4.0f);
}
#endif

View File

@@ -2,76 +2,132 @@
TEST(Transformations, Translate) TEST(Transformations, Translate)
{ {
hmm_mat4 translate = HMM_Translate(HMM_Vec3(1.0f, -3.0f, 6.0f)); HMM_Mat4 translate = HMM_Translate(HMM_V3(1.0f, -3.0f, 6.0f));
hmm_vec3 original = HMM_Vec3(1.0f, 2.0f, 3.0f); HMM_Vec3 original = HMM_V3(1.0f, 2.0f, 3.0f);
hmm_vec4 translated = HMM_MultiplyMat4ByVec4(translate, HMM_Vec4v(original, 1)); HMM_Vec4 translated = HMM_MulM4V4(translate, HMM_V4V(original, 1));
EXPECT_FLOAT_EQ(translated.X, 2.0f); EXPECT_NEAR(translated.X, 2.0f, 0.001f);
EXPECT_FLOAT_EQ(translated.Y, -1.0f); EXPECT_NEAR(translated.Y, -1.0f, 0.001f);
EXPECT_FLOAT_EQ(translated.Z, 9.0f); EXPECT_NEAR(translated.Z, 9.0f, 0.001f);
EXPECT_FLOAT_EQ(translated.W, 1.0f); EXPECT_NEAR(translated.W, 1.0f, 0.001f);
} }
TEST(Transformations, Rotate) TEST(Transformations, Rotate)
{ {
hmm_vec3 original = HMM_Vec3(1.0f, 1.0f, 1.0f); HMM_Vec3 original = HMM_V3(1.0f, 1.0f, 1.0f);
hmm_mat4 rotateX = HMM_Rotate(90, HMM_Vec3(1, 0, 0)); HMM_Mat4 rotateX = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(1, 0, 0));
hmm_vec4 rotatedX = HMM_MultiplyMat4ByVec4(rotateX, HMM_Vec4v(original, 1)); HMM_Vec4 rotatedX = HMM_MulM4V4(rotateX, HMM_V4V(original, 1));
EXPECT_FLOAT_EQ(rotatedX.X, 1.0f); EXPECT_NEAR(rotatedX.X, 1.0f, 0.001f);
EXPECT_FLOAT_EQ(rotatedX.Y, -1.0f); EXPECT_NEAR(rotatedX.Y, -1.0f, 0.001f);
EXPECT_FLOAT_EQ(rotatedX.Z, 1.0f); EXPECT_NEAR(rotatedX.Z, 1.0f, 0.001f);
EXPECT_FLOAT_EQ(rotatedX.W, 1.0f); EXPECT_NEAR(rotatedX.W, 1.0f, 0.001f);
hmm_mat4 rotateY = HMM_Rotate(90, HMM_Vec3(0, 1, 0)); HMM_Mat4 rotateY = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(0, 1, 0));
hmm_vec4 rotatedY = HMM_MultiplyMat4ByVec4(rotateY, HMM_Vec4v(original, 1)); HMM_Vec4 rotatedY = HMM_MulM4V4(rotateY, HMM_V4V(original, 1));
EXPECT_FLOAT_EQ(rotatedY.X, 1.0f); EXPECT_NEAR(rotatedY.X, 1.0f, 0.001f);
EXPECT_FLOAT_EQ(rotatedY.Y, 1.0f); EXPECT_NEAR(rotatedY.Y, 1.0f, 0.001f);
EXPECT_FLOAT_EQ(rotatedY.Z, -1.0f); EXPECT_NEAR(rotatedY.Z, -1.0f, 0.001f);
EXPECT_FLOAT_EQ(rotatedY.W, 1.0f); EXPECT_NEAR(rotatedY.W, 1.0f, 0.001f);
hmm_mat4 rotateZ = HMM_Rotate(90, HMM_Vec3(0, 0, 1)); HMM_Mat4 rotateZ = HMM_Rotate_RH(HMM_AngleDeg(90.0f), HMM_V3(0, 0, 1));
hmm_vec4 rotatedZ = HMM_MultiplyMat4ByVec4(rotateZ, HMM_Vec4v(original, 1)); HMM_Vec4 rotatedZ = HMM_MulM4V4(rotateZ, HMM_V4V(original, 1));
EXPECT_FLOAT_EQ(rotatedZ.X, -1.0f); EXPECT_NEAR(rotatedZ.X, -1.0f, 0.001f);
EXPECT_FLOAT_EQ(rotatedZ.Y, 1.0f); EXPECT_NEAR(rotatedZ.Y, 1.0f, 0.001f);
EXPECT_FLOAT_EQ(rotatedZ.Z, 1.0f); EXPECT_NEAR(rotatedZ.Z, 1.0f, 0.001f);
EXPECT_FLOAT_EQ(rotatedZ.W, 1.0f); EXPECT_NEAR(rotatedZ.W, 1.0f, 0.001f);
HMM_Mat4 rotateZLH = HMM_Rotate_LH(HMM_AngleDeg(90.0f), HMM_V3(0, 0, 1));
HMM_Vec4 rotatedZLH = HMM_MulM4V4(rotateZLH, HMM_V4V(original, 1));
EXPECT_NEAR(rotatedZLH.X, 1.0f, 0.001f);
EXPECT_NEAR(rotatedZLH.Y, -1.0f, 0.001f);
EXPECT_NEAR(rotatedZLH.Z, 1.0f, 0.001f);
EXPECT_NEAR(rotatedZLH.W, 1.0f, 0.001f);
} }
TEST(Transformations, Scale) TEST(Transformations, Scale)
{ {
hmm_mat4 scale = HMM_Scale(HMM_Vec3(2.0f, -3.0f, 0.5f)); HMM_Mat4 scale = HMM_Scale(HMM_V3(2.0f, -3.0f, 0.5f));
hmm_vec3 original = HMM_Vec3(1.0f, 2.0f, 3.0f); HMM_Vec3 original = HMM_V3(1.0f, 2.0f, 3.0f);
hmm_vec4 scaled = HMM_MultiplyMat4ByVec4(scale, HMM_Vec4v(original, 1)); HMM_Vec4 scaled = HMM_MulM4V4(scale, HMM_V4V(original, 1));
EXPECT_FLOAT_EQ(scaled.X, 2.0f); EXPECT_NEAR(scaled.X, 2.0f, 0.001f);
EXPECT_FLOAT_EQ(scaled.Y, -6.0f); EXPECT_NEAR(scaled.Y, -6.0f, 0.001f);
EXPECT_FLOAT_EQ(scaled.Z, 1.5f); EXPECT_NEAR(scaled.Z, 1.5f, 0.001f);
EXPECT_FLOAT_EQ(scaled.W, 1.0f); EXPECT_NEAR(scaled.W, 1.0f, 0.001f);
} }
TEST(Transformations, LookAt) TEST(Transformations, LookAt)
{ {
const float abs_error = 0.0001f; const float abs_error = 0.001f;
hmm_mat4 result = HMM_LookAt(HMM_Vec3(1.0f, 0.0f, 0.0f), HMM_Vec3(0.0f, 2.0f, 1.0f), HMM_Vec3(2.0f, 1.0f, 1.0f)); {
HMM_Mat4 result = HMM_LookAt_RH(HMM_V3(1.0f, 0.0f, 0.0f), HMM_V3(0.0f, 2.0f, 1.0f), HMM_V3(2.0f, 1.0f, 1.0f));
EXPECT_NEAR(result.Elements[0][0], 0.169031f, abs_error); EXPECT_NEAR(result.Elements[0][0], 0.169031f, abs_error);
EXPECT_NEAR(result.Elements[0][1], 0.897085f, abs_error); EXPECT_NEAR(result.Elements[0][1], 0.897085f, abs_error);
EXPECT_NEAR(result.Elements[0][2], 0.408248f, abs_error); EXPECT_NEAR(result.Elements[0][2], 0.408248f, abs_error);
EXPECT_FLOAT_EQ(result.Elements[0][3], 0.0f); EXPECT_NEAR(result.Elements[0][3], 0.0f, abs_error);
EXPECT_NEAR(result.Elements[1][0], 0.507093f, abs_error); EXPECT_NEAR(result.Elements[1][0], 0.507093f, abs_error);
EXPECT_NEAR(result.Elements[1][1], 0.276026f, abs_error); EXPECT_NEAR(result.Elements[1][1], 0.276026f, abs_error);
EXPECT_NEAR(result.Elements[1][2], -0.816497f, abs_error); EXPECT_NEAR(result.Elements[1][2], -0.816497f, abs_error);
EXPECT_FLOAT_EQ(result.Elements[1][3], 0.0f); EXPECT_NEAR(result.Elements[1][3], 0.0f, abs_error);
EXPECT_NEAR(result.Elements[2][0], -0.845154f, abs_error); EXPECT_NEAR(result.Elements[2][0], -0.845154f, abs_error);
EXPECT_NEAR(result.Elements[2][1], 0.345033f, abs_error); EXPECT_NEAR(result.Elements[2][1], 0.345033f, abs_error);
EXPECT_NEAR(result.Elements[2][2], -0.408248f, abs_error); EXPECT_NEAR(result.Elements[2][2], -0.408248f, abs_error);
EXPECT_FLOAT_EQ(result.Elements[2][3], 0.0f); EXPECT_NEAR(result.Elements[2][3], 0.0f, abs_error);
EXPECT_NEAR(result.Elements[3][0], -0.169031f, abs_error); EXPECT_NEAR(result.Elements[3][0], -0.169031f, abs_error);
EXPECT_NEAR(result.Elements[3][1], -0.897085f, abs_error); EXPECT_NEAR(result.Elements[3][1], -0.897085f, abs_error);
EXPECT_NEAR(result.Elements[3][2], -0.408248f, abs_error); EXPECT_NEAR(result.Elements[3][2], -0.408248f, abs_error);
EXPECT_FLOAT_EQ(result.Elements[3][3], 1.0f); EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error);
}
{
HMM_Mat4 result = HMM_LookAt_LH(HMM_V3(1.0f, 0.0f, 0.0f), HMM_V3(0.0f, 2.0f, 1.0f), HMM_V3(2.0f, 1.0f, 1.0f));
EXPECT_NEAR(result.Elements[0][0], -0.169031f, abs_error);
EXPECT_NEAR(result.Elements[0][1], 0.897085f, abs_error);
EXPECT_NEAR(result.Elements[0][2], -0.408248f, abs_error);
EXPECT_NEAR(result.Elements[0][3], 0.0f, abs_error);
EXPECT_NEAR(result.Elements[1][0], -0.507093f, abs_error);
EXPECT_NEAR(result.Elements[1][1], 0.276026f, abs_error);
EXPECT_NEAR(result.Elements[1][2], 0.816497f, abs_error);
EXPECT_NEAR(result.Elements[1][3], 0.0f, abs_error);
EXPECT_NEAR(result.Elements[2][0], 0.845154f, abs_error);
EXPECT_NEAR(result.Elements[2][1], 0.345033f, abs_error);
EXPECT_NEAR(result.Elements[2][2], 0.408248f, abs_error);
EXPECT_NEAR(result.Elements[2][3], 0.0f, abs_error);
EXPECT_NEAR(result.Elements[3][0], 0.169031f, abs_error);
EXPECT_NEAR(result.Elements[3][1], -0.897085f, abs_error);
EXPECT_NEAR(result.Elements[3][2], 0.408248f, abs_error);
EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error);
}
}
TEST(Transformations, RotateV2)
{
HMM_Vec2 v2 = HMM_V2(1, 2);
float epsilon = 0.000001f;
{
HMM_Vec2 res = HMM_RotateV2(v2, HMM_AngleDeg(90));
EXPECT_NEAR(res.X, -2.0f, epsilon);
EXPECT_NEAR(res.Y, 1.0f, epsilon);
}
{
HMM_Vec2 res = HMM_RotateV2(v2, HMM_AngleDeg(180));
EXPECT_NEAR(res.X, -1.0f, epsilon);
EXPECT_NEAR(res.Y, -2.0f, epsilon);
}
{
HMM_Vec2 res = HMM_RotateV2(v2, HMM_AngleDeg(270));
EXPECT_NEAR(res.X, 2.0f, epsilon);
EXPECT_NEAR(res.Y, -1.0f, epsilon);
}
{
HMM_Vec2 res = HMM_RotateV2(v2, HMM_AngleDeg(360));
EXPECT_NEAR(res.X, 1.0f, epsilon);
EXPECT_NEAR(res.Y, 2.0f, epsilon);
}
} }

View File

@@ -2,83 +2,83 @@
TEST(VectorOps, LengthSquared) TEST(VectorOps, LengthSquared)
{ {
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f); HMM_Vec2 v2 = HMM_V2(1.0f, -2.0f);
hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f); HMM_Vec3 v3 = HMM_V3(1.0f, -2.0f, 3.0f);
hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, 1.0f); HMM_Vec4 v4 = HMM_V4(1.0f, -2.0f, 3.0f, 1.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec2(v2), 5.0f); EXPECT_FLOAT_EQ(HMM_LenSqrV2(v2), 5.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec3(v3), 14.0f); EXPECT_FLOAT_EQ(HMM_LenSqrV3(v3), 14.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec4(v4), 15.0f); EXPECT_FLOAT_EQ(HMM_LenSqrV4(v4), 15.0f);
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_LengthSquared(v2), 5.0f); EXPECT_FLOAT_EQ(HMM_LenSqr(v2), 5.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquared(v3), 14.0f); EXPECT_FLOAT_EQ(HMM_LenSqr(v3), 14.0f);
EXPECT_FLOAT_EQ(HMM_LengthSquared(v4), 15.0f); EXPECT_FLOAT_EQ(HMM_LenSqr(v4), 15.0f);
#endif #endif
} }
TEST(VectorOps, Length) TEST(VectorOps, Length)
{ {
hmm_vec2 v2 = HMM_Vec2(1.0f, -9.0f); HMM_Vec2 v2 = HMM_V2(1.0f, -9.0f);
hmm_vec3 v3 = HMM_Vec3(2.0f, -3.0f, 6.0f); HMM_Vec3 v3 = HMM_V3(2.0f, -3.0f, 6.0f);
hmm_vec4 v4 = HMM_Vec4(2.0f, -3.0f, 6.0f, 12.0f); HMM_Vec4 v4 = HMM_V4(2.0f, -3.0f, 6.0f, 12.0f);
EXPECT_FLOAT_EQ(HMM_LengthVec2(v2), 9.0553856f); EXPECT_FLOAT_EQ(HMM_LenV2(v2), 9.0553856f);
EXPECT_FLOAT_EQ(HMM_LengthVec3(v3), 7.0f); EXPECT_FLOAT_EQ(HMM_LenV3(v3), 7.0f);
EXPECT_FLOAT_EQ(HMM_LengthVec4(v4), 13.892444f); EXPECT_FLOAT_EQ(HMM_LenV4(v4), 13.892444f);
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_Length(v2), 9.0553856f); EXPECT_FLOAT_EQ(HMM_Len(v2), 9.0553856f);
EXPECT_FLOAT_EQ(HMM_Length(v3), 7.0f); EXPECT_FLOAT_EQ(HMM_Len(v3), 7.0f);
EXPECT_FLOAT_EQ(HMM_Length(v4), 13.892444f); EXPECT_FLOAT_EQ(HMM_Len(v4), 13.892444f);
#endif #endif
} }
TEST(VectorOps, Normalize) TEST(VectorOps, Normalize)
{ {
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f); HMM_Vec2 v2 = HMM_V2(1.0f, -2.0f);
hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f); HMM_Vec3 v3 = HMM_V3(1.0f, -2.0f, 3.0f);
hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, -1.0f); HMM_Vec4 v4 = HMM_V4(1.0f, -2.0f, 3.0f, -1.0f);
{ {
hmm_vec2 result = HMM_NormalizeVec2(v2); HMM_Vec2 result = HMM_NormV2(v2);
EXPECT_FLOAT_EQ(HMM_LengthVec2(result), 1.0f); EXPECT_NEAR(HMM_LenV2(result), 1.0f, 0.001f);
EXPECT_GT(result.X, 0.0f); EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f); EXPECT_LT(result.Y, 0.0f);
} }
{ {
hmm_vec3 result = HMM_NormalizeVec3(v3); HMM_Vec3 result = HMM_NormV3(v3);
EXPECT_FLOAT_EQ(HMM_LengthVec3(result), 1.0f); EXPECT_NEAR(HMM_LenV3(result), 1.0f, 0.001f);
EXPECT_GT(result.X, 0.0f); EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f); EXPECT_LT(result.Y, 0.0f);
EXPECT_GT(result.Z, 0.0f); EXPECT_GT(result.Z, 0.0f);
} }
{ {
hmm_vec4 result = HMM_NormalizeVec4(v4); HMM_Vec4 result = HMM_NormV4(v4);
EXPECT_FLOAT_EQ(HMM_LengthVec4(result), 1.0f); EXPECT_NEAR(HMM_LenV4(result), 1.0f, 0.001f);
EXPECT_GT(result.X, 0.0f); EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f); EXPECT_LT(result.Y, 0.0f);
EXPECT_GT(result.Z, 0.0f); EXPECT_GT(result.Z, 0.0f);
EXPECT_LT(result.W, 0.0f); EXPECT_LT(result.W, 0.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
hmm_vec2 result = HMM_Normalize(v2); HMM_Vec2 result = HMM_Norm(v2);
EXPECT_FLOAT_EQ(HMM_LengthVec2(result), 1.0f); EXPECT_NEAR(HMM_LenV2(result), 1.0f, 0.001f);
EXPECT_GT(result.X, 0.0f); EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f); EXPECT_LT(result.Y, 0.0f);
} }
{ {
hmm_vec3 result = HMM_Normalize(v3); HMM_Vec3 result = HMM_Norm(v3);
EXPECT_FLOAT_EQ(HMM_LengthVec3(result), 1.0f); EXPECT_NEAR(HMM_LenV3(result), 1.0f, 0.001f);
EXPECT_GT(result.X, 0.0f); EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f); EXPECT_LT(result.Y, 0.0f);
EXPECT_GT(result.Z, 0.0f); EXPECT_GT(result.Z, 0.0f);
} }
{ {
hmm_vec4 result = HMM_Normalize(v4); HMM_Vec4 result = HMM_Norm(v4);
EXPECT_FLOAT_EQ(HMM_LengthVec4(result), 1.0f); EXPECT_NEAR(HMM_LenV4(result), 1.0f, 0.001f);
EXPECT_GT(result.X, 0.0f); EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f); EXPECT_LT(result.Y, 0.0f);
EXPECT_GT(result.Z, 0.0f); EXPECT_GT(result.Z, 0.0f);
@@ -89,143 +89,43 @@ TEST(VectorOps, Normalize)
TEST(VectorOps, NormalizeZero) TEST(VectorOps, NormalizeZero)
{ {
hmm_vec2 v2 = HMM_Vec2(0.0f, 0.0f); HMM_Vec2 v2 = HMM_V2(0.0f, 0.0f);
hmm_vec3 v3 = HMM_Vec3(0.0f, 0.0f, 0.0f); HMM_Vec3 v3 = HMM_V3(0.0f, 0.0f, 0.0f);
hmm_vec4 v4 = HMM_Vec4(0.0f, 0.0f, 0.0f, 0.0f); HMM_Vec4 v4 = HMM_V4(0.0f, 0.0f, 0.0f, 0.0f);
{ {
hmm_vec2 result = HMM_NormalizeVec2(v2); HMM_Vec2 result = HMM_NormV2(v2);
EXPECT_FLOAT_EQ(result.X, 0.0f); EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f); EXPECT_FLOAT_EQ(result.Y, 0.0f);
} }
{ {
hmm_vec3 result = HMM_NormalizeVec3(v3); HMM_Vec3 result = HMM_NormV3(v3);
EXPECT_FLOAT_EQ(result.X, 0.0f); EXPECT_FLOAT_EQ(result.X, 0.0f);
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);
} }
{ {
hmm_vec4 result = HMM_NormalizeVec4(v4); HMM_Vec4 result = HMM_NormV4(v4);
EXPECT_FLOAT_EQ(result.X, 0.0f); EXPECT_FLOAT_EQ(result.X, 0.0f);
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_FLOAT_EQ(result.W, 0.0f); EXPECT_FLOAT_EQ(result.W, 0.0f);
} }
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{ {
hmm_vec2 result = HMM_Normalize(v2); HMM_Vec2 result = HMM_Norm(v2);
EXPECT_FLOAT_EQ(result.X, 0.0f); EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f); EXPECT_FLOAT_EQ(result.Y, 0.0f);
} }
{ {
hmm_vec3 result = HMM_Normalize(v3); HMM_Vec3 result = HMM_Norm(v3);
EXPECT_FLOAT_EQ(result.X, 0.0f); EXPECT_FLOAT_EQ(result.X, 0.0f);
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);
} }
{ {
hmm_vec4 result = HMM_Normalize(v4); HMM_Vec4 result = HMM_Norm(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(VectorOps, FastNormalize)
{
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.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_vec2 result = HMM_FastNormalizeVec2(v2);
EXPECT_NEAR(HMM_LengthVec2(result), 1.0f, 0.001f);
EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f);
}
{
hmm_vec3 result = HMM_FastNormalizeVec3(v3);
EXPECT_NEAR(HMM_LengthVec3(result), 1.0f, 0.001f);
EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f);
EXPECT_GT(result.Z, 0.0f);
}
{
hmm_vec4 result = HMM_FastNormalizeVec4(v4);
EXPECT_NEAR(HMM_LengthVec4(result), 1.0f, 0.001f);
EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f);
EXPECT_GT(result.Z, 0.0f);
EXPECT_LT(result.W, 0.0f);
}
#ifdef __cplusplus
{
hmm_vec2 result = HMM_FastNormalize(v2);
EXPECT_NEAR(HMM_LengthVec2(result), 1.0f, 0.001f);
EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f);
}
{
hmm_vec3 result = HMM_FastNormalize(v3);
EXPECT_NEAR(HMM_LengthVec3(result), 1.0f, 0.001f);
EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f);
EXPECT_GT(result.Z, 0.0f);
}
{
hmm_vec4 result = HMM_FastNormalize(v4);
EXPECT_NEAR(HMM_LengthVec4(result), 1.0f, 0.001f);
EXPECT_GT(result.X, 0.0f);
EXPECT_LT(result.Y, 0.0f);
EXPECT_GT(result.Z, 0.0f);
EXPECT_LT(result.W, 0.0f);
}
#endif
}
TEST(VectorOps, FastNormalizeZero)
{
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_FastNormalizeVec2(v2);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
}
{
hmm_vec3 result = HMM_FastNormalizeVec3(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_FastNormalizeVec4(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_FastNormalize(v2);
EXPECT_FLOAT_EQ(result.X, 0.0f);
EXPECT_FLOAT_EQ(result.Y, 0.0f);
}
{
hmm_vec3 result = HMM_FastNormalize(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_FastNormalize(v4);
EXPECT_FLOAT_EQ(result.X, 0.0f); EXPECT_FLOAT_EQ(result.X, 0.0f);
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);
@@ -236,10 +136,10 @@ TEST(VectorOps, FastNormalizeZero)
TEST(VectorOps, Cross) TEST(VectorOps, Cross)
{ {
hmm_vec3 v1 = HMM_Vec3(1.0f, 2.0f, 3.0f); HMM_Vec3 v1 = HMM_V3(1.0f, 2.0f, 3.0f);
hmm_vec3 v2 = HMM_Vec3(4.0f, 5.0f, 6.0f); HMM_Vec3 v2 = HMM_V3(4.0f, 5.0f, 6.0f);
hmm_vec3 result = HMM_Cross(v1, v2); HMM_Vec3 result = HMM_Cross(v1, v2);
EXPECT_FLOAT_EQ(result.X, -3.0f); EXPECT_FLOAT_EQ(result.X, -3.0f);
EXPECT_FLOAT_EQ(result.Y, 6.0f); EXPECT_FLOAT_EQ(result.Y, 6.0f);
@@ -248,45 +148,107 @@ TEST(VectorOps, Cross)
TEST(VectorOps, DotVec2) TEST(VectorOps, DotVec2)
{ {
hmm_vec2 v1 = HMM_Vec2(1.0f, 2.0f); HMM_Vec2 v1 = HMM_V2(1.0f, 2.0f);
hmm_vec2 v2 = HMM_Vec2(3.0f, 4.0f); HMM_Vec2 v2 = HMM_V2(3.0f, 4.0f);
EXPECT_FLOAT_EQ(HMM_DotVec2(v1, v2), 11.0f); EXPECT_FLOAT_EQ(HMM_DotV2(v1, v2), 11.0f);
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 11.0f); EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 11.0f);
#endif #endif
} }
TEST(VectorOps, DotVec3) TEST(VectorOps, DotVec3)
{ {
hmm_vec3 v1 = HMM_Vec3(1.0f, 2.0f, 3.0f); HMM_Vec3 v1 = HMM_V3(1.0f, 2.0f, 3.0f);
hmm_vec3 v2 = HMM_Vec3(4.0f, 5.0f, 6.0f); HMM_Vec3 v2 = HMM_V3(4.0f, 5.0f, 6.0f);
EXPECT_FLOAT_EQ(HMM_DotVec3(v1, v2), 32.0f); EXPECT_FLOAT_EQ(HMM_DotV3(v1, v2), 32.0f);
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 32.0f); EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 32.0f);
#endif #endif
} }
TEST(VectorOps, DotVec4) TEST(VectorOps, DotVec4)
{ {
hmm_vec4 v1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f); HMM_Vec4 v1 = HMM_V4(1.0f, 2.0f, 3.0f, 4.0f);
hmm_vec4 v2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f); HMM_Vec4 v2 = HMM_V4(5.0f, 6.0f, 7.0f, 8.0f);
EXPECT_FLOAT_EQ(HMM_DotVec4(v1, v2), 70.0f); EXPECT_FLOAT_EQ(HMM_DotV4(v1, v2), 70.0f);
#ifdef __cplusplus #if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 70.0f); EXPECT_FLOAT_EQ(HMM_Dot(v1, v2), 70.0f);
#endif #endif
} }
TEST(VectorOps, LerpV2)
{
HMM_Vec2 v1 = HMM_V2(1.0f, 0.0f);
HMM_Vec2 v2 = HMM_V2(0.0f, 1.0f);
{
HMM_Vec2 result = HMM_LerpV2(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.5f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec2 result = HMM_Lerp(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 0.5f);
}
#endif
}
TEST(VectorOps, LerpV3)
{
HMM_Vec3 v1 = HMM_V3(1.0f, 1.0f, 0.0f);
HMM_Vec3 v2 = HMM_V3(0.0f, 1.0f, 1.0f);
{
HMM_Vec3 result = HMM_LerpV3(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 0.5f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec3 result = HMM_Lerp(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 0.5f);
}
#endif
}
TEST(VectorOps, LerpV4)
{
HMM_Vec4 v1 = HMM_V4(1.0f, 1.0f, 0.0f, 1.0f);
HMM_Vec4 v2 = HMM_V4(0.0f, 1.0f, 1.0f, 1.0f);
{
HMM_Vec4 result = HMM_LerpV4(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 0.5f);
EXPECT_FLOAT_EQ(result.W, 1.0f);
}
#if HANDMADE_MATH__USE_C11_GENERICS || defined(__cplusplus)
{
HMM_Vec4 result = HMM_Lerp(v1, 0.5, v2);
EXPECT_FLOAT_EQ(result.X, 0.5f);
EXPECT_FLOAT_EQ(result.Y, 1.0f);
EXPECT_FLOAT_EQ(result.Z, 0.5f);
EXPECT_FLOAT_EQ(result.W, 1.0f);
}
#endif
}
/* /*
* MatrixOps tests * MatrixOps tests
*/ */
TEST(MatrixOps, Transpose) TEST(MatrixOps, TransposeM4)
{ {
hmm_mat4 m4 = HMM_Mat4(); // will have 1 - 16 HMM_Mat4 m4 = HMM_M4(); // will have 1 - 16
// Fill the matrix // Fill the matrix
int Counter = 1; int Counter = 1;
@@ -300,7 +262,7 @@ TEST(MatrixOps, Transpose)
} }
// Test the matrix // Test the matrix
hmm_mat4 result = HMM_Transpose(m4); HMM_Mat4 result = HMM_TransposeM4(m4);
EXPECT_FLOAT_EQ(result.Elements[0][0], 1.0f); EXPECT_FLOAT_EQ(result.Elements[0][0], 1.0f);
EXPECT_FLOAT_EQ(result.Elements[0][1], 5.0f); EXPECT_FLOAT_EQ(result.Elements[0][1], 5.0f);
EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f); EXPECT_FLOAT_EQ(result.Elements[0][2], 9.0f);

View File

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

View File

@@ -1,11 +1,15 @@
#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"
#include "categories/Initialization.h" #include "categories/Initialization.h"
#include "categories/VectorOps.h" #include "categories/VectorOps.h"
#include "categories/MatrixOps.h"
#include "categories/QuaternionOps.h" #include "categories/QuaternionOps.h"
#include "categories/Addition.h" #include "categories/Addition.h"
#include "categories/Subtraction.h" #include "categories/Subtraction.h"

27
test/run_test_clang.bat Normal file
View File

@@ -0,0 +1,27 @@
@echo off
if not exist "build" mkdir build
pushd build
clang-cl /std:c11 /Fehmm_test_c11.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c11 || exit /b 1
clang-cl /std:c11 /Fehmm_test_c11_no_simd.exe /DHANDMADE_MATH_NO_SIMD ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c11_no_simd || exit /b 1
clang-cl /std:c17 /Fehmm_test_c17.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c17 || exit /b 1
clang-cl /std:c++14 /Fehmm_test_cpp14.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp14 || exit /b 1
clang-cl /std:c++14 /Fehmm_test_cpp14_no_simd.exe /DHANDMADE_MATH_NO_SIMD ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp14_no_simd || exit /b 1
clang-cl /std:c++17 /Fehmm_test_cpp17.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp17 || exit /b 1
clang-cl /std:c++20 /Fehmm_test_cpp20.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp20 || exit /b 1
popd

32
test/run_test_msvc.bat Normal file
View File

@@ -0,0 +1,32 @@
@echo off
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 /std:c11 /Fehmm_test_c11.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c11 || exit /b 1
cl /std:c11 /Fehmm_test_c11_no_simd.exe /DHANDMADE_MATH_NO_SIMD ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c11_no_simd || exit /b 1
cl /std:c17 /Fehmm_test_c17.exe ..\HandmadeMath.c ..\hmm_test.c || exit /b 1
hmm_test_c17 || exit /b 1
cl /std:c++14 /Fehmm_test_cpp14.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp14 || exit /b 1
cl /std:c++14 /Fehmm_test_cpp14_no_simd.exe /DHANDMADE_MATH_NO_SIMD ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp14_no_simd || exit /b 1
cl /std:c++17 /Fehmm_test_cpp17.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp17 || exit /b 1
cl /std:c++20 /Fehmm_test_cpp20.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || exit /b 1
hmm_test_cpp20 || exit /b 1
popd

24
update/README.md Normal file
View File

@@ -0,0 +1,24 @@
# Handmade Math 2.0 Update Tool
Due to the large number of breaking naming changes in Handmade Math 2, we provide a small Python script to update your programs automatically. It can run on individual files or on all files in a directory (recursively).
**Warning!** This tool is not very smart! Please ensure that your work is committed and backed up, in case you have to revert this tool's changes.
```
# see usage info and options
> python3 update_hmm.py -h
usage: update_hmm [-h] [--exts .foo [.foo ...]] filename [filename ...]
...
# run on individual files
> python3 update_hmm.py MyPlatformLayer.c MyPlatformLayer.h
Updating: MyPlatformLayer.c
Updating: MyPlatformLayer.h
Updated 2 files with 0 warnings.
# run on a whole directory
> python3 update_hmm.py projects/MyCoolGame
Updating: projects/MyCoolGame/src/MyPlatformLayer.c
Updating: projects/MyCoolGame/include/MyPlatformLayer.h
...
```

166
update/update_hmm.py Executable file
View File

@@ -0,0 +1,166 @@
#!/usr/bin/env python3
import argparse
import os
import re
typeReplacements = [
('hmm_', 'HMM_'),
('vec', 'Vec'),
('mat', 'Mat'),
('quaternion', 'Quaternion'),
('bool', 'Bool'),
('.InternalElementsSSE', '.SSE'),
]
funcReplacements = [
('HMM_', 'HMM_'),
('Vec', 'V'),
('Mat', 'M'),
('Quaternion', 'Q'),
('Equals', 'Eq'),
('Subtract', 'Sub'),
('Multiply', 'Mul'),
('Divide', 'Div'),
('Inverse', 'Inv'),
('RSquareRoot', 'InvSqrt'),
('SquareRoot', 'Sqrt'),
('Squared', 'Sqr'),
('Length', 'Len'),
('Slerp', 'SLerp'),
('By', ''),
('LinearCombineSSE', 'LinearCombineV4M4'),
('Transpose', 'TransposeM4'),
('Fast', ''), # TODO(port): emit warning, lower precision
('Normalize', 'Norm'),
('ToRadians', 'ToRad')
]
handedFuncs = [
'Perspective',
'Rotate',
'Orthographic',
'LookAt',
'FromAxisAngle',
'ToQuaternion',
]
projectionFuncs = [
'Perspective',
'Orthographic',
]
numFiles = 0
numWarnings = 0
def printWarning(msg):
global numWarnings
numWarnings += 1
print('WARNING: {}'.format(msg))
def updateFile(filename):
global numFiles
print('Updating: {}'.format(filename))
numFiles += 1
result = ''
with open(filename, 'r', newline='') as f:
for lineNo, line in enumerate(f):
updatedLine = line
def printLineWarning(msg):
printWarning(' Line {}: {}'.format(lineNo + 1, msg))
def replaceName(m):
name = m.group()
if name.startswith('hmm_'):
# do type replacements
for before, after in typeReplacements:
if before not in name:
continue
name = name.replace(before, after)
else:
# do func replacements
for before, after in funcReplacements:
if before not in name:
continue
name = name.replace(before, after)
if after == 'LinearCombineV4M4':
printLineWarning('HMM_LinearCombineSSE is now HMM_LinearCombineV4M4, and will now use a fallback method when SSE is not available. You no longer need to check for the availability of SSE.')
if after == 'V' or after == 'M':
# uppercase the modifier, if any
name = re.sub(
r'[VM]\d[ivfd]?',
lambda m: m.group().upper(),
name
)
# and also nuke the integer constructors
vecIntMatch = re.search(r'(V\d)I', name)
if vecIntMatch:
name = name.replace(vecIntMatch.group(), vecIntMatch.group(1))
# add handedness / NDC modifiers
if not any(x in name for x in ['RH', 'LH', 'NO', 'ZO']):
for handedFunc in handedFuncs:
suffixed = handedFunc + '_RH'
if handedFunc in projectionFuncs:
suffixed += '_NO'
name = name.replace(handedFunc, suffixed)
return name
def wrapDegrees(m):
name = m.group('name')
arg = m.group('arg')
if '(' in arg:
# all bets are off, don't wrap the argument
printLineWarning('{} now takes radians, but we were unable to automatically wrap the first argument with HMM_AngleDeg().'.format(name))
return m.group()
return '{}(HMM_AngleDeg({}),'.format(name, arg)
updatedLine = re.sub(r'(hmm_|HMM_)\w+', replaceName, updatedLine)
updatedLine = re.sub(r'(?P<name>HMM_Perspective_RH_NO|HMM_Rotate_RH)\((?P<arg>.*?),', wrapDegrees, updatedLine)
result += updatedLine
with open(filename, 'w', newline='') as f:
f.write(result)
parser = argparse.ArgumentParser(
prog = 'update_hmm',
description = 'Updates C and C++ source code to use Handmade Math 2.0.',
)
parser.add_argument(
'filename', nargs='+',
help='A file or directory to update to HMM 2.0. If a directory, all files with extensions from --exts will be processed.',
)
parser.add_argument(
'--exts', nargs='+', default=['.c', '.cpp', '.h', '.hpp'],
help='File extensions to run the script on, when targeting a directory. Default: .c, .cpp, .h, .hpp.',
metavar='.foo',
)
args = parser.parse_args()
for path in args.filename:
filenames = []
if os.path.isfile(path):
filenames = [path]
else:
for root, dirs, files in os.walk(path):
for file in files:
if file == 'HandmadeMath.h':
printWarning('HandmadeMath.h will not be replaced by this script.')
elif file.endswith(tuple(args.exts)):
filenames.append(os.path.join(root, file))
for filename in filenames:
try:
updateFile(filename)
except UnicodeDecodeError:
pass
print('Updated {} files with {} warnings.'.format(numFiles, numWarnings))