Sitelet https://github.com/HandmadeMath/HandmadeMath/commit/f7c8e1f7d18f936deb86729606d87cb3f19fb707
Skip to content

Commit f7c8e1f

Browse files
bvisnessZak Strange
authored andcommitted
Add fast vector normalization (#94)
* Add fast normalization routines * Update readme and remove version history from main file * Update version at top of file
1 parent 5ca1d58 commit f7c8e1f

3 files changed

Lines changed: 138 additions & 114 deletions

File tree

‎HandmadeMath.h‎

Lines changed: 37 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
HandmadeMath.h v1.7.1
2+
HandmadeMath.h v1.8.0
33
44
This is a single header file with a bunch of useful functions for game and
55
graphics math operations.
@@ -65,119 +65,6 @@
6565
versions of these functions that are provided by the CRT.
6666
6767
=============================================================================
68-
69-
Version History:
70-
0.2 (*) Updated documentation
71-
(*) Better C compliance
72-
(*) Prefix all handmade math functions
73-
(*) Better operator overloading
74-
0.2a
75-
(*) Prefixed Macros
76-
0.2b
77-
(*) Disabled warning 4201 on MSVC as it is legal is C11
78-
(*) Removed the f at the end of HMM_PI to get 64bit precision
79-
0.3
80-
(*) Added +=, -=, *=, /= for hmm_vec2, hmm_vec3, hmm_vec4
81-
0.4
82-
(*) SSE Optimized HMM_SqrtF
83-
(*) SSE Optimized HMM_RSqrtF
84-
(*) Removed CRT
85-
0.5
86-
(*) Added scalar multiplication and division for vectors
87-
and matrices
88-
(*) Added matrix subtraction and += for hmm_mat4
89-
(*) Reconciled all headers and implementations
90-
(*) Tidied up, and filled in a few missing operators
91-
0.5.1
92-
(*) Ensured column-major order for matrices throughout
93-
(*) Fixed HMM_Translate producing row-major matrices
94-
0.5.2
95-
(*) Fixed SSE code in HMM_SqrtF
96-
(*) Fixed SSE code in HMM_RSqrtF
97-
0.6
98-
(*) Added Unit testing
99-
(*) Made HMM_Power faster
100-
(*) Fixed possible efficiency problem with HMM_Normalize
101-
(*) RENAMED HMM_LengthSquareRoot to HMM_LengthSquared
102-
(*) RENAMED HMM_RSqrtF to HMM_RSquareRootF
103-
(*) RENAMED HMM_SqrtF to HMM_SquareRootF
104-
(*) REMOVED Inner function (user should use Dot now)
105-
(*) REMOVED HMM_FastInverseSquareRoot function declaration
106-
0.7
107-
(*) REMOVED HMM_LengthSquared in HANDMADE_MATH_IMPLEMENTATION (should
108-
use HMM_LengthSquaredVec3, or HANDMADE_MATH_CPP_MODE for function
109-
overloaded version)
110-
(*) REMOVED HMM_Length in HANDMADE_MATH_IMPLEMENTATION (should use
111-
HMM_LengthVec3, HANDMADE_MATH_CPP_MODE for function
112-
overloaded version)
113-
(*) REMOVED HMM_Normalize in HANDMADE_MATH_IMPLEMENTATION (should use
114-
HMM_NormalizeVec3, or HANDMADE_MATH_CPP_MODE for function
115-
overloaded version)
116-
(*) Added HMM_LengthSquaredVec2
117-
(*) Added HMM_LengthSquaredVec4
118-
(*) Addd HMM_LengthVec2
119-
(*) Added HMM_LengthVec4
120-
(*) Added HMM_NormalizeVec2
121-
(*) Added HMM_NormalizeVec4
122-
1.0
123-
(*) Lots of testing!
124-
1.1
125-
(*) Quaternion support
126-
(*) Added type hmm_quaternion
127-
(*) Added HMM_Quaternion
128-
(*) Added HMM_QuaternionV4
129-
(*) Added HMM_AddQuaternion
130-
(*) Added HMM_SubtractQuaternion
131-
(*) Added HMM_MultiplyQuaternion
132-
(*) Added HMM_MultiplyQuaternionF
133-
(*) Added HMM_DivideQuaternionF
134-
(*) Added HMM_InverseQuaternion
135-
(*) Added HMM_DotQuaternion
136-
(*) Added HMM_NormalizeQuaternion
137-
(*) Added HMM_Slerp
138-
(*) Added HMM_QuaternionToMat4
139-
(*) Added HMM_QuaternionFromAxisAngle
140-
1.1.1
141-
(*) Resolved compiler warnings on gcc and g++
142-
1.1.2
143-
(*) Fixed invalid HMMDEF's in the function definitions
144-
1.1.3
145-
(*) Fixed compile error in C mode
146-
1.1.4
147-
(*) Fixed SSE being included on platforms that don't support it
148-
(*) Fixed divide-by-zero errors when normalizing zero vectors.
149-
1.1.5
150-
(*) Add Width and Height to HMM_Vec2
151-
(*) Made it so you can supply your own SqrtF
152-
1.2.0
153-
(*) Added equality functions for HMM_Vec2, HMM_Vec3, and HMM_Vec4.
154-
(*) Added HMM_EqualsVec2, HMM_EqualsVec3, and HMM_EqualsVec4
155-
(*) Added C++ overloaded HMM_Equals for all three
156-
(*) Added C++ == and != operators for all three
157-
(*) SSE'd HMM_MultiplyMat4 (this is _WAY_ faster)
158-
(*) SSE'd HMM_Transpose
159-
1.3.0
160-
(*) Remove need to #define HANDMADE_MATH_CPP_MODE
161-
1.4.0
162-
(*) Fixed bug when using HandmadeMath in C mode
163-
(*) SSEd all vec4 operations
164-
(*) Removed all zero-ing
165-
1.5.0
166-
(*) Changed internal structure for better performance and inlining.
167-
(*) As a result, HANDMADE_MATH_NO_INLINE has been removed and no
168-
longer has any effect.
169-
1.5.1
170-
(*) Fixed a bug with uninitialized elements in HMM_LookAt.
171-
1.6.0
172-
(*) Added array subscript operators for vector and matrix types in
173-
C++. This is provided as a convenience, but be aware that it may
174-
incur an extra function call in unoptimized builds.
175-
1.7.0
176-
(*) Renamed the 'Rows' member of hmm_mat4 to 'Columns'. Since our
177-
matrices are column-major, this should have been named 'Columns'
178-
from the start. 'Rows' is still present, but has been deprecated.
179-
1.7.1
180-
(*) Changed operator[] to take a const ref int instead of an int.
18168
18269
LICENSE
18370
@@ -1129,6 +1016,21 @@ HMM_INLINE hmm_vec4 HMM_NormalizeVec4(hmm_vec4 A)
11291016
return (Result);
11301017
}
11311018

1019+
HMM_INLINE hmm_vec2 HMM_FastNormalizeVec2(hmm_vec2 A)
1020+
{
1021+
return HMM_MultiplyVec2f(A, HMM_RSquareRootF(HMM_DotVec2(A, A)));
1022+
}
1023+
1024+
HMM_INLINE hmm_vec3 HMM_FastNormalizeVec3(hmm_vec3 A)
1025+
{
1026+
return HMM_MultiplyVec3f(A, HMM_RSquareRootF(HMM_DotVec3(A, A)));
1027+
}
1028+
1029+
HMM_INLINE hmm_vec4 HMM_FastNormalizeVec4(hmm_vec4 A)
1030+
{
1031+
return HMM_MultiplyVec4f(A, HMM_RSquareRootF(HMM_DotVec4(A, A)));
1032+
}
1033+
11321034

11331035
/*
11341036
* SSE stuff
@@ -1512,6 +1414,27 @@ HMM_INLINE hmm_vec4 HMM_Normalize(hmm_vec4 A)
15121414
return (Result);
15131415
}
15141416

1417+
HMM_INLINE hmm_vec2 HMM_FastNormalize(hmm_vec2 A)
1418+
{
1419+
hmm_vec2 Result = HMM_FastNormalizeVec2(A);
1420+
1421+
return (Result);
1422+
}
1423+
1424+
HMM_INLINE hmm_vec3 HMM_FastNormalize(hmm_vec3 A)
1425+
{
1426+
hmm_vec3 Result = HMM_FastNormalizeVec3(A);
1427+
1428+
return (Result);
1429+
}
1430+
1431+
HMM_INLINE hmm_vec4 HMM_FastNormalize(hmm_vec4 A)
1432+
{
1433+
hmm_vec4 Result = HMM_FastNormalizeVec4(A);
1434+
1435+
return (Result);
1436+
}
1437+
15151438
HMM_INLINE hmm_quaternion HMM_Normalize(hmm_quaternion A)
15161439
{
15171440
hmm_quaternion Result = HMM_NormalizeQuaternion(A);

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ To get started, go download [the latest release](https://github.com/HandmadeMath
1010

1111
Version | Changes |
1212
----------------|----------------|
13+
**1.8.0** | Added fast vector normalization routines that use fast inverse square roots.
1314
**1.7.1** | Changed operator[] to take a const ref int instead of an int.
1415
**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.
1516
**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.

‎test/categories/VectorOps.h‎

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,106 @@ TEST(VectorOps, NormalizeZero)
134134
#endif
135135
}
136136

137+
TEST(VectorOps, FastNormalize)
138+
{
139+
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f);
140+
hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f);
141+
hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, -1.0f);
142+
143+
{
144+
hmm_vec2 result = HMM_FastNormalizeVec2(v2);
145+
EXPECT_NEAR(HMM_LengthVec2(result), 1.0f, 0.001f);
146+
EXPECT_GT(result.X, 0.0f);
147+
EXPECT_LT(result.Y, 0.0f);
148+
}
149+
{
150+
hmm_vec3 result = HMM_FastNormalizeVec3(v3);
151+
EXPECT_NEAR(HMM_LengthVec3(result), 1.0f, 0.001f);
152+
EXPECT_GT(result.X, 0.0f);
153+
EXPECT_LT(result.Y, 0.0f);
154+
EXPECT_GT(result.Z, 0.0f);
155+
}
156+
{
157+
hmm_vec4 result = HMM_FastNormalizeVec4(v4);
158+
EXPECT_NEAR(HMM_LengthVec4(result), 1.0f, 0.001f);
159+
EXPECT_GT(result.X, 0.0f);
160+
EXPECT_LT(result.Y, 0.0f);
161+
EXPECT_GT(result.Z, 0.0f);
162+
EXPECT_LT(result.W, 0.0f);
163+
}
164+
165+
#ifdef __cplusplus
166+
{
167+
hmm_vec2 result = HMM_FastNormalize(v2);
168+
EXPECT_NEAR(HMM_LengthVec2(result), 1.0f, 0.001f);
169+
EXPECT_GT(result.X, 0.0f);
170+
EXPECT_LT(result.Y, 0.0f);
171+
}
172+
{
173+
hmm_vec3 result = HMM_FastNormalize(v3);
174+
EXPECT_NEAR(HMM_LengthVec3(result), 1.0f, 0.001f);
175+
EXPECT_GT(result.X, 0.0f);
176+
EXPECT_LT(result.Y, 0.0f);
177+
EXPECT_GT(result.Z, 0.0f);
178+
}
179+
{
180+
hmm_vec4 result = HMM_FastNormalize(v4);
181+
EXPECT_NEAR(HMM_LengthVec4(result), 1.0f, 0.001f);
182+
EXPECT_GT(result.X, 0.0f);
183+
EXPECT_LT(result.Y, 0.0f);
184+
EXPECT_GT(result.Z, 0.0f);
185+
EXPECT_LT(result.W, 0.0f);
186+
}
187+
#endif
188+
}
189+
190+
TEST(VectorOps, FastNormalizeZero)
191+
{
192+
hmm_vec2 v2 = HMM_Vec2(0.0f, 0.0f);
193+
hmm_vec3 v3 = HMM_Vec3(0.0f, 0.0f, 0.0f);
194+
hmm_vec4 v4 = HMM_Vec4(0.0f, 0.0f, 0.0f, 0.0f);
195+
196+
{
197+
hmm_vec2 result = HMM_FastNormalizeVec2(v2);
198+
EXPECT_FLOAT_EQ(result.X, 0.0f);
199+
EXPECT_FLOAT_EQ(result.Y, 0.0f);
200+
}
201+
{
202+
hmm_vec3 result = HMM_FastNormalizeVec3(v3);
203+
EXPECT_FLOAT_EQ(result.X, 0.0f);
204+
EXPECT_FLOAT_EQ(result.Y, 0.0f);
205+
EXPECT_FLOAT_EQ(result.Z, 0.0f);
206+
}
207+
{
208+
hmm_vec4 result = HMM_FastNormalizeVec4(v4);
209+
EXPECT_FLOAT_EQ(result.X, 0.0f);
210+
EXPECT_FLOAT_EQ(result.Y, 0.0f);
211+
EXPECT_FLOAT_EQ(result.Z, 0.0f);
212+
EXPECT_FLOAT_EQ(result.W, 0.0f);
213+
}
214+
215+
#ifdef __cplusplus
216+
{
217+
hmm_vec2 result = HMM_FastNormalize(v2);
218+
EXPECT_FLOAT_EQ(result.X, 0.0f);
219+
EXPECT_FLOAT_EQ(result.Y, 0.0f);
220+
}
221+
{
222+
hmm_vec3 result = HMM_FastNormalize(v3);
223+
EXPECT_FLOAT_EQ(result.X, 0.0f);
224+
EXPECT_FLOAT_EQ(result.Y, 0.0f);
225+
EXPECT_FLOAT_EQ(result.Z, 0.0f);
226+
}
227+
{
228+
hmm_vec4 result = HMM_FastNormalize(v4);
229+
EXPECT_FLOAT_EQ(result.X, 0.0f);
230+
EXPECT_FLOAT_EQ(result.Y, 0.0f);
231+
EXPECT_FLOAT_EQ(result.Z, 0.0f);
232+
EXPECT_FLOAT_EQ(result.W, 0.0f);
233+
}
234+
#endif
235+
}
236+
137237
TEST(VectorOps, Cross)
138238
{
139239
hmm_vec3 v1 = HMM_Vec3(1.0f, 2.0f, 3.0f);

0 commit comments

Comments
 (0)