From 0eb37da8bbcefc722ad4098b47b742d615c85fb1 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 11:01:07 +0300 Subject: [PATCH 01/10] vec4: optimize vec4 normalize with SIMD --- include/cglm/vec4.h | 48 ++++++++++++++++++++++++------------------ test/src/test_common.c | 8 +++++++ test/src/test_common.h | 3 +++ test/src/test_vec4.c | 29 +++++++++++++++++++++++-- 4 files changed, 66 insertions(+), 22 deletions(-) diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index eaa4eaf..0ef6bff 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -312,26 +312,6 @@ glm_vec4_inv_to(vec4 v, vec4 dest) { glm_vec4_flipsign(dest); } -/*! - * @brief normalize vec4 and store result in same vec - * - * @param[in, out] v vector - */ -CGLM_INLINE -void -glm_vec4_normalize(vec4 v) { - float norm; - - norm = glm_vec4_norm(v); - - if (norm == 0.0f) { - v[0] = v[1] = v[2] = v[3] = 0.0f; - return; - } - - glm_vec4_scale(v, 1.0f / norm, v); -} - /*! * @brief normalize vec4 to dest * @@ -341,16 +321,44 @@ glm_vec4_normalize(vec4 v) { CGLM_INLINE void glm_vec4_normalize_to(vec4 vec, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + __m128 xdot, x0; + float dot; + + x0 = _mm_load_ps(vec); + xdot = glm_simd_dot(x0, x0); + dot = _mm_cvtss_f32(xdot); + + if (dot == 0.0f) { + _mm_store_ps(dest, _mm_setzero_ps()); + return; + } + + _mm_store_ps(dest, _mm_div_ps(x0, _mm_sqrt_ps(xdot))); +#else float norm; norm = glm_vec4_norm(vec); if (norm == 0.0f) { dest[0] = dest[1] = dest[2] = dest[3] = 0.0f; + glm_vec4_broadcast(0.0f, dest); return; } glm_vec4_scale(vec, 1.0f / norm, dest); +#endif +} + +/*! + * @brief normalize vec4 and store result in same vec + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec4_normalize(vec4 v) { + glm_vec4_normalize_to(v, v); } /** diff --git a/test/src/test_common.c b/test/src/test_common.c index 514c006..a559087 100644 --- a/test/src/test_common.c +++ b/test/src/test_common.c @@ -91,6 +91,14 @@ test_assert_vec3_eq(vec3 v1, vec3 v2) { assert_true(fabsf(v1[2] - v2[2]) <= 0.000009); } +void +test_assert_vec4_eq(vec4 v1, vec4 v2) { + assert_true(fabsf(v1[0] - v2[0]) <= 0.000009); /* rounding errors */ + assert_true(fabsf(v1[1] - v2[1]) <= 0.000009); + assert_true(fabsf(v1[2] - v2[2]) <= 0.000009); + assert_true(fabsf(v1[3] - v2[3]) <= 0.000009); +} + void test_assert_quat_eq_abs(versor v1, versor v2) { assert_true(fabsf(fabsf(v1[0]) - fabsf(v2[0])) <= 0.0009); /* rounding errors */ diff --git a/test/src/test_common.h b/test/src/test_common.h index c95405e..50e84d6 100644 --- a/test/src/test_common.h +++ b/test/src/test_common.h @@ -34,6 +34,9 @@ test_assert_mat4_eq2(mat4 m1, mat4 m2, float eps); void test_assert_vec3_eq(vec3 v1, vec3 v2); +void +test_assert_vec4_eq(vec4 v1, vec4 v2); + void test_assert_quat_eq(versor v1, versor v2); diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c index a45a700..994bab7 100644 --- a/test/src/test_vec4.c +++ b/test/src/test_vec4.c @@ -13,18 +13,43 @@ test_vec4_dot(vec4 a, vec4 b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; } +CGLM_INLINE +void +test_vec4_normalize_to(vec4 vec, vec4 dest) { + float norm; + + norm = glm_vec4_norm(vec); + + if (norm == 0.0f) { + dest[0] = dest[1] = dest[2] = dest[3] = 0.0f; + return; + } + + glm_vec4_scale(vec, 1.0f / norm, dest); +} + void test_vec4(void **state) { - vec4 v; + vec4 v, v1, v2; int i; float d1, d2; - /* test SSE/SIMD dot product */ + for (i = 0; i < 100; i++) { + /* 1. test SSE/SIMD dot product */ test_rand_vec4(v); d1 = glm_vec4_dot(v, v); d2 = test_vec4_dot(v, v); assert_true(fabsf(d1 - d2) <= 0.000009); + + /* 2. test SIMD normalize */ + test_vec4_normalize_to(v, v1); + glm_vec4_normalize_to(v, v2); + glm_vec4_normalize(v); + + /* all must be same */ + test_assert_vec4_eq(v1, v2); + test_assert_vec4_eq(v, v2); } } From 79f8b1ebf85040e19a0a2eeb4b750dc57e948db5 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 11:18:42 +0300 Subject: [PATCH 02/10] vec4: optimize vec4 norm and norm2 --- include/cglm/vec4.h | 16 +++++++++++++++- test/src/test_common.c | 5 +++++ test/src/test_common.h | 3 +++ test/src/test_vec4.c | 20 +++++++++++++++++++- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 0ef6bff..c50b4f9 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -146,7 +146,15 @@ glm_vec4_dot(vec4 a, vec4 b) { CGLM_INLINE float glm_vec4_norm2(vec4 v) { - return glm_vec4_dot(v, v); +#if defined( __SSE__ ) || defined( __SSE2__ ) + __m128 x0; + x0 = _mm_load_ps(v); + x0 = _mm_mul_ps(x0, x0); + x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 1, 0, 3, 2)); + return _mm_cvtss_f32(_mm_add_ss(x0, _mm_shuffle1_ps(x0, 0, 1, 0, 1))); +#else + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; +#endif } /*! @@ -159,7 +167,13 @@ glm_vec4_norm2(vec4 v) { CGLM_INLINE float glm_vec4_norm(vec4 vec) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + __m128 x0; + x0 = _mm_load_ps(vec); + return _mm_cvtss_f32(_mm_sqrt_ss(glm_simd_dot(x0, x0))); +#else return sqrtf(glm_vec4_norm2(vec)); +#endif } /*! diff --git a/test/src/test_common.c b/test/src/test_common.c index a559087..60baac3 100644 --- a/test/src/test_common.c +++ b/test/src/test_common.c @@ -84,6 +84,11 @@ test_assert_mat4_eq2(mat4 m1, mat4 m2, float eps) { } } +void +test_assert_eqf(float a, float b) { + assert_true(fabsf(a - b) <= 0.000009); /* rounding errors */ +} + void test_assert_vec3_eq(vec3 v1, vec3 v2) { assert_true(fabsf(v1[0] - v2[0]) <= 0.000009); /* rounding errors */ diff --git a/test/src/test_common.h b/test/src/test_common.h index 50e84d6..db113a4 100644 --- a/test/src/test_common.h +++ b/test/src/test_common.h @@ -25,6 +25,9 @@ void test_rand_mat4(mat4 dest); +void +test_assert_eqf(float a, float b); + void test_assert_mat4_eq(mat4 m1, mat4 m2); diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c index 994bab7..51986f1 100644 --- a/test/src/test_vec4.c +++ b/test/src/test_vec4.c @@ -28,6 +28,16 @@ test_vec4_normalize_to(vec4 vec, vec4 dest) { glm_vec4_scale(vec, 1.0f / norm, dest); } +float +test_vec4_norm2(vec4 vec) { + return test_vec4_dot(vec, vec); +} + +float +test_vec4_norm(vec4 vec) { + return sqrtf(test_vec4_dot(vec, vec)); +} + void test_vec4(void **state) { vec4 v, v1, v2; @@ -35,7 +45,7 @@ test_vec4(void **state) { float d1, d2; - for (i = 0; i < 100; i++) { + for (i = 0; i < 1000; i++) { /* 1. test SSE/SIMD dot product */ test_rand_vec4(v); d1 = glm_vec4_dot(v, v); @@ -51,5 +61,13 @@ test_vec4(void **state) { /* all must be same */ test_assert_vec4_eq(v1, v2); test_assert_vec4_eq(v, v2); + + /* 3. test SIMD norm */ + test_rand_vec4(v); + test_assert_eqf(test_vec4_norm(v), glm_vec4_norm(v)); + + /* 3. test SIMD norm2 */ + test_rand_vec4(v); + test_assert_eqf(test_vec4_norm2(v), glm_vec4_norm2(v)); } } From c489955b0079d4c8c9a599fb14d9a2ca15a9363e Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 11:39:14 +0300 Subject: [PATCH 03/10] add simd norm helper --- include/cglm/simd/intrin.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/cglm/simd/intrin.h b/include/cglm/simd/intrin.h index 4c27d90..c396686 100644 --- a/include/cglm/simd/intrin.h +++ b/include/cglm/simd/intrin.h @@ -40,6 +40,12 @@ glm_simd_dot(__m128 a, __m128 b) { return _mm_add_ps(x0, _mm_shuffle1_ps(x0, 0, 1, 0, 1)); } +CGLM_INLINE +__m128 +glm_simd_norm(__m128 a) { + return _mm_sqrt_ps(glm_simd_dot(a, a)); +} + #endif /* x86, x64 */ From 25fc3d028486c000f242588f735885cb9afad2bd Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 11:57:14 +0300 Subject: [PATCH 04/10] vec: add one and zero helpers for vectors --- docs/source/vec3.rst | 16 ++++++++++++++++ docs/source/vec4.rst | 9 +++++++++ include/cglm/call/vec3.h | 8 ++++++++ include/cglm/call/vec4.h | 8 ++++++++ include/cglm/vec3.h | 26 ++++++++++++++++++++++++++ include/cglm/vec4.h | 36 ++++++++++++++++++++++++++++++++++++ makefile.am | 3 ++- src/vec3.c | 12 ++++++++++++ src/vec4.c | 12 ++++++++++++ test/src/test_main.c | 5 ++++- test/src/test_tests.h | 3 +++ test/src/test_vec3.c | 21 +++++++++++++++++++++ test/src/test_vec4.c | 8 ++++++++ 13 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 test/src/test_vec3.c diff --git a/docs/source/vec3.rst b/docs/source/vec3.rst index 8529333..0c5d590 100644 --- a/docs/source/vec3.rst +++ b/docs/source/vec3.rst @@ -31,6 +31,8 @@ Functions: 1. :c:func:`glm_vec3` #. :c:func:`glm_vec_copy` +#. :c:func:`glm_vec_zero` +#. :c:func:`glm_vec_one` #. :c:func:`glm_vec_dot` #. :c:func:`glm_vec_cross` #. :c:func:`glm_vec_norm2` @@ -76,6 +78,20 @@ Functions documentation | *[in]* **a** source | *[out]* **dest** destination +.. c:function:: void glm_vec_zero(vec3 v) + + makes all members 0.0f (zero) + + Parameters: + | *[in, out]* **v** vector + +.. c:function:: void glm_vec_one(vec3 v) + + makes all members 1.0f (one) + + Parameters: + | *[in, out]* **v** vector + .. c:function:: float glm_vec_dot(vec3 a, vec3 b) dot product of vec3 diff --git a/docs/source/vec4.rst b/docs/source/vec4.rst index 6955246..8deed35 100644 --- a/docs/source/vec4.rst +++ b/docs/source/vec4.rst @@ -24,6 +24,8 @@ Functions: 1. :c:func:`glm_vec4` #. :c:func:`glm_vec4_copy3` #. :c:func:`glm_vec4_copy` +#. :c:func:`glm_vec4_zero` +#. :c:func:`glm_vec4_one` #. :c:func:`glm_vec4_dot` #. :c:func:`glm_vec4_norm2` #. :c:func:`glm_vec4_norm` @@ -78,6 +80,13 @@ Functions documentation | *[in]* **v** source | *[in]* **dest** destination +.. c:function:: void glm_vec4_zero(vec4 v) + + makes all members zero + + Parameters: + | *[in, out]* **v** vector + .. c:function:: float glm_vec4_dot(vec4 a, vec4 b) dot product of vec4 diff --git a/include/cglm/call/vec3.h b/include/cglm/call/vec3.h index e79ec8f..396972f 100644 --- a/include/cglm/call/vec3.h +++ b/include/cglm/call/vec3.h @@ -24,6 +24,14 @@ CGLM_EXPORT void glmc_vec_copy(vec3 a, vec3 dest); +CGLM_EXPORT +void +glmc_vec_zero(vec3 v); + +CGLM_EXPORT +void +glmc_vec_one(vec3 v); + CGLM_EXPORT float glmc_vec_dot(vec3 a, vec3 b); diff --git a/include/cglm/call/vec4.h b/include/cglm/call/vec4.h index ad915e6..95f91e2 100644 --- a/include/cglm/call/vec4.h +++ b/include/cglm/call/vec4.h @@ -21,6 +21,14 @@ CGLM_EXPORT void glmc_vec4(vec3 v3, float last, vec4 dest); +CGLM_EXPORT +void +glmc_vec4_zero(vec4 v); + +CGLM_EXPORT +void +glmc_vec4_one(vec4 v); + CGLM_EXPORT void glmc_vec4_copy3(vec4 a, vec3 dest); diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 714165b..6f42855 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -103,6 +103,32 @@ glm_vec_copy(vec3 a, vec3 dest) { dest[2] = a[2]; } +/*! + * @brief make vector zero + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec_zero(vec4 v) { + v[0] = 0.0f; + v[1] = 0.0f; + v[2] = 0.0f; +} + +/*! + * @brief make vector one + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec_one(vec4 v) { + v[0] = 1.0f; + v[1] = 1.0f; + v[2] = 1.0f; +} + /*! * @brief vec3 dot product * diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index c50b4f9..44c6a31 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -111,6 +111,42 @@ glm_vec4_copy(vec4 v, vec4 dest) { #endif } +/*! + * @brief make vector zero + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec4_zero(vec4 v) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(v, _mm_setzero_ps()); +#else + v[0] = 0.0f; + v[1] = 0.0f; + v[2] = 0.0f; + v[3] = 0.0f; +#endif +} + +/*! + * @brief make vector one + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec4_one(vec4 v) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(v, _mm_set1_ps(1.0f)); +#else + v[0] = 1.0f; + v[1] = 1.0f; + v[2] = 1.0f; + v[3] = 1.0f; +#endif +} + /*! * @brief vec4 dot product * diff --git a/makefile.am b/makefile.am index 2922373..00800c0 100644 --- a/makefile.am +++ b/makefile.am @@ -110,7 +110,8 @@ test_tests_SOURCES=\ test/src/test_clamp.c \ test/src/test_euler.c \ test/src/test_quat.c \ - test/src/test_vec4.c + test/src/test_vec4.c \ + test/src/test_vec3.c all-local: sh ./post-build.sh diff --git a/src/vec3.c b/src/vec3.c index f7e2692..f7c890e 100644 --- a/src/vec3.c +++ b/src/vec3.c @@ -20,6 +20,18 @@ glmc_vec_copy(vec3 a, vec3 dest) { glm_vec_copy(a, dest); } +CGLM_EXPORT +void +glmc_vec_zero(vec3 v) { + glm_vec_zero(v); +} + +CGLM_EXPORT +void +glmc_vec_one(vec3 v) { + glm_vec_one(v); +} + CGLM_EXPORT float glmc_vec_dot(vec3 a, vec3 b) { diff --git a/src/vec4.c b/src/vec4.c index 7228070..df93556 100644 --- a/src/vec4.c +++ b/src/vec4.c @@ -14,6 +14,18 @@ glmc_vec4(vec3 v3, float last, vec4 dest) { glm_vec4(v3, last, dest); } +CGLM_EXPORT +void +glmc_vec4_zero(vec4 v) { + glm_vec4_zero(v); +} + +CGLM_EXPORT +void +glmc_vec4_one(vec4 v) { + glm_vec4_one(v); +} + CGLM_EXPORT void glmc_vec4_copy3(vec4 a, vec3 dest) { diff --git a/test/src/test_main.c b/test/src/test_main.c index 7995a5a..b0649cd 100644 --- a/test/src/test_main.c +++ b/test/src/test_main.c @@ -29,7 +29,10 @@ main(int argc, const char * argv[]) { cmocka_unit_test(test_quat), /* vec4 */ - cmocka_unit_test(test_vec4) + cmocka_unit_test(test_vec4), + + /* vec3 */ + cmocka_unit_test(test_vec3) }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/test/src/test_tests.h b/test/src/test_tests.h index 1dfbb5f..224d943 100644 --- a/test/src/test_tests.h +++ b/test/src/test_tests.h @@ -31,4 +31,7 @@ test_quat(void **state); void test_vec4(void **state); +void +test_vec3(void **state); + #endif /* test_tests_h */ diff --git a/test/src/test_vec3.c b/test/src/test_vec3.c new file mode 100644 index 0000000..5a3a4c8 --- /dev/null +++ b/test/src/test_vec3.c @@ -0,0 +1,21 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#include "test_common.h" + +void +test_vec3(void **state) { + vec3 v; + + /* test zero */ + glm_vec_zero(v); + test_assert_vec3_eq(GLM_VEC3_ZERO, v); + + /* test one */ + glm_vec_one(v); + test_assert_vec3_eq(GLM_VEC3_ONE, v); +} diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c index 51986f1..a80d9c7 100644 --- a/test/src/test_vec4.c +++ b/test/src/test_vec4.c @@ -70,4 +70,12 @@ test_vec4(void **state) { test_rand_vec4(v); test_assert_eqf(test_vec4_norm2(v), glm_vec4_norm2(v)); } + + /* test zero */ + glm_vec4_zero(v); + test_assert_vec4_eq(GLM_VEC4_ZERO, v); + + /* test one */ + glm_vec4_one(v); + test_assert_vec4_eq(GLM_VEC4_ONE, v); } From af5a2627b4566eabd44058d219f31dd8debb1e58 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 11:57:34 +0300 Subject: [PATCH 05/10] fix scale_as for zero length vector * return zero if vector length is zero --- include/cglm/vec3.h | 4 ++-- include/cglm/vec4.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 6f42855..2be7173 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -247,8 +247,8 @@ glm_vec_scale_as(vec3 v, float s, vec3 dest) { float norm; norm = glm_vec_norm(v); - if (norm == 0) { - glm_vec_copy(v, dest); + if (norm == 0.0f) { + glm_vec_zero(dest); return; } diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 44c6a31..b28d9fd 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -291,8 +291,8 @@ glm_vec4_scale_as(vec4 v, float s, vec4 dest) { float norm; norm = glm_vec4_norm(v); - if (norm == 0) { - glm_vec4_copy(v, dest); + if (norm == 0.0f) { + glm_vec4_zero(dest); return; } From d841f8809d7da5f1e4afe6d06b67cb0ba4397b6b Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 15:12:56 +0300 Subject: [PATCH 06/10] vec: add some new functions for vector * _mul: multiply two vector (replacement for _mulv) * _div: div two vector * _divs: div vector with scalar * adds: add scalar to each components of vec * subs: sub scalar from each components of vec --- docs/source/vec3.rst | 64 +++++++++++++++-- docs/source/vec4.rst | 66 ++++++++++++++--- include/cglm/call/vec3.h | 22 +++++- include/cglm/call/vec4.h | 24 ++++++- include/cglm/vec3-ext.h | 2 +- include/cglm/vec3.h | 114 ++++++++++++++++++++++++----- include/cglm/vec4-ext.h | 2 +- include/cglm/vec4.h | 152 +++++++++++++++++++++++++++++++-------- src/vec3.c | 34 ++++++++- src/vec4.c | 38 ++++++++-- test/src/test_vec3.c | 33 ++++++++- test/src/test_vec4.c | 31 ++++++++ 12 files changed, 510 insertions(+), 72 deletions(-) diff --git a/docs/source/vec3.rst b/docs/source/vec3.rst index 0c5d590..86f17e4 100644 --- a/docs/source/vec3.rst +++ b/docs/source/vec3.rst @@ -38,9 +38,14 @@ Functions: #. :c:func:`glm_vec_norm2` #. :c:func:`glm_vec_norm` #. :c:func:`glm_vec_add` +#. :c:func:`glm_vec_adds` #. :c:func:`glm_vec_sub` +#. :c:func:`glm_vec_subs` +#. :c:func:`glm_vec_mul` #. :c:func:`glm_vec_scale` #. :c:func:`glm_vec_scale_as` +#. :c:func:`glm_vec_div` +#. :c:func:`glm_vec_divs` #. :c:func:`glm_vec_flipsign` #. :c:func:`glm_vec_flipsign_to` #. :c:func:`glm_vec_inv` @@ -133,24 +138,51 @@ Functions documentation Parameters: | *[in]* **vec** vector -.. c:function:: void glm_vec_add(vec3 v1, vec3 v2, vec3 dest) +.. c:function:: void glm_vec_add(vec3 a, vec3 b, vec3 dest) - add v2 vector to v1 vector store result in dest + add a vector to b vector store result in dest Parameters: - | *[in]* **v1** vector1 - | *[in]* **v2** vector2 + | *[in]* **a** vector1 + | *[in]* **b** vector2 + | *[out]* **dest** destination vector + +.. c:function:: void glm_vec_adds(vec3 a, float s, vec3 dest) + + add scalar to v vector store result in dest (d = v + vec(s)) + + Parameters: + | *[in]* **v** vector + | *[in]* **s** scalar | *[out]* **dest** destination vector .. c:function:: void glm_vec_sub(vec3 v1, vec3 v2, vec3 dest) - subtract v2 vector from v1 vector store result in dest + subtract b vector from a vector store result in dest (d = v1 - v2) Parameters: - | *[in]* **v1** vector1 - | *[in]* **v2** vector2 + | *[in]* **a** vector1 + | *[in]* **b** vector2 | *[out]* **dest** destination vector +.. c:function:: void glm_vec_subs(vec3 v, float s, vec3 dest) + + subtract scalar from v vector store result in dest (d = v - vec(s)) + + Parameters: + | *[in]* **v** vector + | *[in]* **s** scalar + | *[out]* **dest** destination vector + +.. c:function:: void glm_vec_mul(vec3 a, vec3 b, vec3 d) + + multiply two vector (component-wise multiplication) + + Parameters: + | *[in]* **a** vector + | *[in]* **b** scalar + | *[out]* **d** result = (a[0] * b[0], a[1] * b[1], a[2] * b[2]) + .. c:function:: void glm_vec_scale(vec3 v, float s, vec3 dest) multiply/scale vec3 vector with scalar: result = v * s @@ -170,6 +202,24 @@ Functions documentation | *[in]* **s** scalar | *[out]* **dest** destination vector +.. c:function:: void glm_vec_div(vec3 a, vec3 b, vec3 dest) + + div vector with another component-wise division: d = a / b + + Parameters: + | *[in]* **a** vector 1 + | *[in]* **b** vector 2 + | *[out]* **dest** result = (a[0] / b[0], a[1] / b[1], a[2] / b[2]) + +.. c:function:: void glm_vec_divs(vec3 v, float s, vec3 dest) + + div vector with scalar: d = v / s + + Parameters: + | *[in]* **v** vector + | *[in]* **s** scalar + | *[out]* **dest** result = (a[0] / s, a[1] / s, a[2] / s]) + .. c:function:: void glm_vec_flipsign(vec3 v) flip sign of all vec3 members diff --git a/docs/source/vec4.rst b/docs/source/vec4.rst index 8deed35..89ac5c2 100644 --- a/docs/source/vec4.rst +++ b/docs/source/vec4.rst @@ -30,9 +30,14 @@ Functions: #. :c:func:`glm_vec4_norm2` #. :c:func:`glm_vec4_norm` #. :c:func:`glm_vec4_add` +#. :c:func:`glm_vec4_adds` #. :c:func:`glm_vec4_sub` +#. :c:func:`glm_vec4_subs` +#. :c:func:`glm_vec4_mul` #. :c:func:`glm_vec4_scale` #. :c:func:`glm_vec4_scale_as` +#. :c:func:`glm_vec4_div` +#. :c:func:`glm_vec4_divs` #. :c:func:`glm_vec4_flipsign` #. :c:func:`glm_vec_flipsign_to` #. :c:func:`glm_vec4_inv` @@ -119,24 +124,51 @@ Functions documentation Parameters: | *[in]* **vec** vector -.. c:function:: void glm_vec4_add(vec4 v1, vec4 v2, vec4 dest) +.. c:function:: void glm_vec4_add(vec4 a, vec4 b, vec4 dest) - add v2 vector to v1 vector store result in dest + add a vector to b vector store result in dest Parameters: - | *[in]* **v1** vector1 - | *[in]* **v2** vector2 + | *[in]* **a** vector1 + | *[in]* **b** vector2 | *[out]* **dest** destination vector -.. c:function:: void glm_vec4_sub(vec4 v1, vec4 v2, vec4 dest) +.. c:function:: void glm_vec4_adds(vec4 v, float s, vec4 dest) - subtract v2 vector from v1 vector store result in dest + add scalar to v vector store result in dest (d = v + vec(s)) Parameters: - | *[in]* **v1** vector1 - | *[in]* **v2** vector2 + | *[in]* **v** vector + | *[in]* **s** scalar | *[out]* **dest** destination vector +.. c:function:: void glm_vec4_sub(vec4 a, vec4 b, vec4 dest) + + subtract b vector from a vector store result in dest (d = v1 - v2) + + Parameters: + | *[in]* **a** vector1 + | *[in]* **b** vector2 + | *[out]* **dest** destination vector + +.. c:function:: void glm_vec4_subs(vec4 v, float s, vec4 dest) + + subtract scalar from v vector store result in dest (d = v - vec(s)) + + Parameters: + | *[in]* **v** vector + | *[in]* **s** scalar + | *[out]* **dest** destination vector + +.. c:function:: void glm_vec4_mul(vec4 a, vec4 b, vec4 d) + + multiply two vector (component-wise multiplication) + + Parameters: + | *[in]* **a** vector1 + | *[in]* **b** vector2 + | *[out]* **dest** result = (a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3]) + .. c:function:: void glm_vec4_scale(vec4 v, float s, vec4 dest) multiply/scale vec4 vector with scalar: result = v * s @@ -155,6 +187,24 @@ Functions documentation | *[in]* **s** scalar | *[out]* **dest** destination vector +.. c:function:: void glm_vec4_div(vec4 a, vec4 b, vec4 dest) + + div vector with another component-wise division: d = v1 / v2 + + Parameters: + | *[in]* **a** vector1 + | *[in]* **b** vector2 + | *[out]* **dest** result = (a[0] / b[0], a[1] / b[1], a[2] / b[2], a[3] / b[3]) + +.. c:function:: void glm_vec4_divs(vec4 v, float s, vec4 dest) + + div vector with scalar: d = v / s + + Parameters: + | *[in]* **v** vector + | *[in]* **s** scalar + | *[out]* **dest** result = (a[0] / s, a[1] / s, a[2] / s, a[3] / s) + .. c:function:: void glm_vec4_flipsign(vec4 v) flip sign of all vec4 members diff --git a/include/cglm/call/vec3.h b/include/cglm/call/vec3.h index 396972f..b2374e6 100644 --- a/include/cglm/call/vec3.h +++ b/include/cglm/call/vec3.h @@ -62,7 +62,19 @@ glmc_vec_add(vec3 v1, vec3 v2, vec3 dest); CGLM_EXPORT void -glmc_vec_sub(vec3 v1, vec3 v2, vec3 dest); +glmc_vec_adds(vec3 v, float s, vec3 dest); + +CGLM_EXPORT +void +glmc_vec_sub(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec_subs(vec3 v, float s, vec3 dest); + +CGLM_EXPORT +void +glmc_vec_mul(vec3 a, vec3 b, vec3 d); CGLM_EXPORT void @@ -72,6 +84,14 @@ CGLM_EXPORT void glmc_vec_scale_as(vec3 v, float s, vec3 dest); +CGLM_EXPORT +void +glmc_vec_div(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec_divs(vec3 a, float s, vec3 dest); + CGLM_EXPORT void glmc_vec_flipsign(vec3 v); diff --git a/include/cglm/call/vec4.h b/include/cglm/call/vec4.h index 95f91e2..b460962 100644 --- a/include/cglm/call/vec4.h +++ b/include/cglm/call/vec4.h @@ -59,11 +59,23 @@ glmc_vec4_normalize(vec4 v); CGLM_EXPORT void -glmc_vec4_add(vec4 v1, vec4 v2, vec4 dest); +glmc_vec4_add(vec4 a, vec4 b, vec4 dest); CGLM_EXPORT void -glmc_vec4_sub(vec4 v1, vec4 v2, vec4 dest); +glmc_vec4_adds(vec4 v, float s, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_sub(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_subs(vec4 v, float s, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_mul(vec4 a, vec4 b, vec4 d); CGLM_EXPORT void @@ -73,6 +85,14 @@ CGLM_EXPORT void glmc_vec4_scale_as(vec3 v, float s, vec3 dest); +CGLM_EXPORT +void +glmc_vec4_div(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_divs(vec4 v, float s, vec4 dest); + CGLM_EXPORT void glmc_vec4_flipsign(vec4 v); diff --git a/include/cglm/vec3-ext.h b/include/cglm/vec3-ext.h index fb2a687..e12c133 100644 --- a/include/cglm/vec3-ext.h +++ b/include/cglm/vec3-ext.h @@ -32,7 +32,7 @@ #include /*! - * @brief multiplies individual items, just for convenient like SIMD + * @brief DEPRECATED! use glm_vec_mul * * @param[in] a vec1 * @param[in] b vec2 diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 2be7173..b3012b6 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -28,10 +28,15 @@ CGLM_INLINE void glm_vec_cross(vec3 a, vec3 b, vec3 d); CGLM_INLINE float glm_vec_norm2(vec3 v); CGLM_INLINE float glm_vec_norm(vec3 vec); - CGLM_INLINE void glm_vec_add(vec3 v1, vec3 v2, vec3 dest); - CGLM_INLINE void glm_vec_sub(vec3 v1, vec3 v2, vec3 dest); + CGLM_INLINE void glm_vec_add(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec_adds(vec3 a, float s, vec3 dest); + CGLM_INLINE void glm_vec_sub(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec_subs(vec3 a, float s, vec3 dest); + CGLM_INLINE void glm_vec_mul(vec3 a, vec3 b, vec3 dest); CGLM_INLINE void glm_vec_scale(vec3 v, float s, vec3 dest); CGLM_INLINE void glm_vec_scale_as(vec3 v, float s, vec3 dest); + CGLM_INLINE void glm_vec_div(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec_divs(vec3 a, float s, vec3 dest); CGLM_INLINE void glm_vec_flipsign(vec3 v); CGLM_INLINE void glm_vec_inv(vec3 v); CGLM_INLINE void glm_vec_inv_to(vec3 v, vec3 dest); @@ -110,7 +115,7 @@ glm_vec_copy(vec3 a, vec3 dest) { */ CGLM_INLINE void -glm_vec_zero(vec4 v) { +glm_vec_zero(vec3 v) { v[0] = 0.0f; v[1] = 0.0f; v[2] = 0.0f; @@ -123,7 +128,7 @@ glm_vec_zero(vec4 v) { */ CGLM_INLINE void -glm_vec_one(vec4 v) { +glm_vec_one(vec3 v) { v[0] = 1.0f; v[1] = 1.0f; v[2] = 1.0f; @@ -190,33 +195,78 @@ glm_vec_norm(vec3 vec) { } /*! - * @brief add v2 vector to v1 vector store result in dest + * @brief add a vector to b vector store result in dest * - * @param[in] v1 vector1 - * @param[in] v2 vector2 + * @param[in] a vector1 + * @param[in] b vector2 * @param[out] dest destination vector */ CGLM_INLINE void -glm_vec_add(vec3 v1, vec3 v2, vec3 dest) { - dest[0] = v1[0] + v2[0]; - dest[1] = v1[1] + v2[1]; - dest[2] = v1[2] + v2[2]; +glm_vec_add(vec3 a, vec3 b, vec3 dest) { + dest[0] = a[0] + b[0]; + dest[1] = a[1] + b[1]; + dest[2] = a[2] + b[2]; +} + +/*! + * @brief add scalar to v vector store result in dest (d = v + s) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec_adds(vec3 v, float s, vec3 dest) { + dest[0] = v[0] + s; + dest[1] = v[1] + s; + dest[2] = v[2] + s; } /*! * @brief subtract v2 vector from v1 vector store result in dest * - * @param[in] v1 vector1 - * @param[in] v2 vector2 + * @param[in] a vector1 + * @param[in] b vector2 * @param[out] dest destination vector */ CGLM_INLINE void -glm_vec_sub(vec3 v1, vec3 v2, vec3 dest) { - dest[0] = v1[0] - v2[0]; - dest[1] = v1[1] - v2[1]; - dest[2] = v1[2] - v2[2]; +glm_vec_sub(vec3 a, vec3 b, vec3 dest) { + dest[0] = a[0] - b[0]; + dest[1] = a[1] - b[1]; + dest[2] = a[2] - b[2]; +} + +/*! + * @brief subtract scalar from v vector store result in dest (d = v - s) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec_subs(vec3 v, float s, vec3 dest) { + dest[0] = v[0] - s; + dest[1] = v[1] - s; + dest[2] = v[2] - s; +} + +/*! + * @brief multiply two vector (component-wise multiplication) + * + * @param a v1 + * @param b v2 + * @param d v3 = (a[0] * b[0], a[1] * b[1], a[2] * b[2]) + */ +CGLM_INLINE +void +glm_vec_mul(vec3 a, vec3 b, vec3 d) { + d[0] = a[0] * b[0]; + d[1] = a[1] * b[1]; + d[2] = a[2] * b[2]; } /*! @@ -255,6 +305,36 @@ glm_vec_scale_as(vec3 v, float s, vec3 dest) { glm_vec_scale(v, s / norm, dest); } +/*! + * @brief div vector with another component-wise division: d = a / b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest result = (a[0]/b[0], a[1]/b[1], a[2]/b[2]) + */ +CGLM_INLINE +void +glm_vec_div(vec3 a, vec3 b, vec3 dest) { + dest[0] = a[0] / b[0]; + dest[1] = a[1] / b[1]; + dest[2] = a[2] / b[2]; +} + +/*! + * @brief div vector with scalar: d = v / s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest result = (a[0]/s, a[1]/s, a[2]/s) + */ +CGLM_INLINE +void +glm_vec_divs(vec3 v, float s, vec3 dest) { + dest[0] = v[0] / s; + dest[1] = v[1] / s; + dest[2] = v[2] / s; +} + /*! * @brief flip sign of all vec3 members * diff --git a/include/cglm/vec4-ext.h b/include/cglm/vec4-ext.h index 53b02a8..7a6cb3d 100644 --- a/include/cglm/vec4-ext.h +++ b/include/cglm/vec4-ext.h @@ -32,7 +32,7 @@ #include /*! - * @brief multiplies individual items, just for convenient like SIMD + * @brief DEPRECATED! use glm_vec4_mul * * @param a v1 * @param b v2 diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index b28d9fd..e1319b9 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -28,10 +28,15 @@ CGLM_INLINE float glm_vec4_dot(vec4 a, vec4 b); CGLM_INLINE float glm_vec4_norm2(vec4 v); CGLM_INLINE float glm_vec4_norm(vec4 vec); - CGLM_INLINE void glm_vec4_add(vec4 v1, vec4 v2, vec4 dest); - CGLM_INLINE void glm_vec4_sub(vec4 v1, vec4 v2, vec4 dest); + CGLM_INLINE void glm_vec4_add(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_adds(vec4 v, float s, vec4 dest); + CGLM_INLINE void glm_vec4_sub(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_subs(vec4 v, float s, vec4 dest); + CGLM_INLINE void glm_vec4_mul(vec4 a, vec4 b, vec4 dest); CGLM_INLINE void glm_vec4_scale(vec4 v, float s, vec4 dest); CGLM_INLINE void glm_vec4_scale_as(vec4 v, float s, vec4 dest); + CGLM_INLINE void glm_vec4_div(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_divs(vec4 v, float s, vec4 dest); CGLM_INLINE void glm_vec4_flipsign(vec4 v); CGLM_INLINE void glm_vec4_inv(vec4 v); CGLM_INLINE void glm_vec4_inv_to(vec4 v, vec4 dest); @@ -41,6 +46,7 @@ CGLM_INLINE void glm_vec4_maxv(vec4 v1, vec4 v2, vec4 dest); CGLM_INLINE void glm_vec4_minv(vec4 v1, vec4 v2, vec4 dest); CGLM_INLINE void glm_vec4_clamp(vec4 v, float minVal, float maxVal); + CGLM_INLINE void glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest) */ #ifndef cglm_vec4_h @@ -215,44 +221,100 @@ glm_vec4_norm(vec4 vec) { /*! * @brief add v2 vector to v1 vector store result in dest * - * @param[in] v1 vector1 - * @param[in] v2 vector2 + * @param[in] a vector1 + * @param[in] b vector2 * @param[out] dest destination vector */ CGLM_INLINE void -glm_vec4_add(vec4 v1, vec4 v2, vec4 dest) { +glm_vec4_add(vec4 a, vec4 b, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, - _mm_add_ps(_mm_load_ps(v1), - _mm_load_ps(v2))); + _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(a), _mm_load_ps(b))); #else - dest[0] = v1[0] + v2[0]; - dest[1] = v1[1] + v2[1]; - dest[2] = v1[2] + v2[2]; - dest[3] = v1[3] + v2[3]; + dest[0] = a[0] + b[0]; + dest[1] = a[1] + b[1]; + dest[2] = a[2] + b[2]; + dest[3] = a[3] + b[3]; #endif } /*! - * @brief subtract v2 vector from v1 vector store result in dest + * @brief add scalar to v vector store result in dest (d = v + vec(s)) * - * @param[in] v1 vector1 - * @param[in] v2 vector2 + * @param[in] v vector + * @param[in] s scalar * @param[out] dest destination vector */ CGLM_INLINE void -glm_vec4_sub(vec4 v1, vec4 v2, vec4 dest) { +glm_vec4_adds(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, - _mm_sub_ps(_mm_load_ps(v1), - _mm_load_ps(v2))); + _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(v), _mm_set1_ps(s))); #else - dest[0] = v1[0] - v2[0]; - dest[1] = v1[1] - v2[1]; - dest[2] = v1[2] - v2[2]; - dest[3] = v1[3] - v2[3]; + dest[0] = v1[0] + s; + dest[1] = v1[1] + s; + dest[2] = v1[2] + s; + dest[3] = v1[3] + s; +#endif +} + +/*! + * @brief subtract b vector from a vector store result in dest (d = v1 - v2) + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_sub(vec4 a, vec4 b, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_sub_ps(_mm_load_ps(a), _mm_load_ps(b))); +#else + dest[0] = a[0] - b[0]; + dest[1] = a[1] - b[1]; + dest[2] = a[2] - b[2]; + dest[3] = a[3] - b[3]; +#endif +} + +/*! + * @brief subtract scalar from v vector store result in dest (d = v - vec(s)) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_subs(vec4 v, float s, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_sub_ps(_mm_load_ps(v), _mm_set1_ps(s))); +#else + dest[0] = v1[0] - s; + dest[1] = v1[1] - s; + dest[2] = v1[2] - s; + dest[3] = v1[3] - s; +#endif +} + +/*! + * @brief multiply two vector (component-wise multiplication) + * + * @param a v1 + * @param b v2 + * @param d v3 = (a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3]) + */ +CGLM_INLINE +void +glm_vec4_mul(vec4 a, vec4 b, vec4 d) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(d, _mm_mul_ps(_mm_load_ps(a), _mm_load_ps(b))); +#else + d[0] = a[0] * b[0]; + d[1] = a[1] * b[1]; + d[2] = a[2] * b[2]; + d[3] = a[3] * b[3]; #endif } @@ -267,9 +329,7 @@ CGLM_INLINE void glm_vec4_scale(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(dest, - _mm_mul_ps(_mm_load_ps(v), - _mm_set1_ps(s))); + _mm_store_ps(dest, _mm_mul_ps(_mm_load_ps(v), _mm_set1_ps(s))); #else dest[0] = v[0] * s; dest[1] = v[1] * s; @@ -299,6 +359,43 @@ glm_vec4_scale_as(vec4 v, float s, vec4 dest) { glm_vec4_scale(v, s / norm, dest); } +/*! + * @brief div vector with another component-wise division: d = v1 / v2 + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest result = (a[0]/b[0], a[1]/b[1], a[2]/b[2], a[3]/b[3]) + */ +CGLM_INLINE +void +glm_vec4_div(vec4 a, vec4 b, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_div_ps(_mm_load_ps(a), _mm_load_ps(b))); +#else + dest[0] = a[0] / b[0]; + dest[1] = a[1] / b[1]; + dest[2] = a[2] / b[2]; + dest[3] = a[3] / b[3]; +#endif +} + +/*! + * @brief div vec4 vector with scalar: d = v / s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_divs(vec4 v, float s, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_div_ps(_mm_load_ps(v), _mm_set1_ps(s))); +#else + glm_vec4_scale(v, 1.0f / s, dest); +#endif +} + /*! * @brief flip sign of all vec4 members * @@ -308,8 +405,7 @@ CGLM_INLINE void glm_vec4_flipsign(vec4 v) { #if defined( __SSE__ ) || defined( __SSE2__ ) - _mm_store_ps(v, _mm_xor_ps(_mm_load_ps(v), - _mm_set1_ps(-0.0f))); + _mm_store_ps(v, _mm_xor_ps(_mm_load_ps(v), _mm_set1_ps(-0.0f))); #else v[0] = -v[0]; v[1] = -v[1]; diff --git a/src/vec3.c b/src/vec3.c index f7c890e..b8553ec 100644 --- a/src/vec3.c +++ b/src/vec3.c @@ -76,8 +76,26 @@ glmc_vec_add(vec3 v1, vec3 v2, vec3 dest) { CGLM_EXPORT void -glmc_vec_sub(vec3 v1, vec3 v2, vec3 dest) { - glm_vec_sub(v1, v2, dest); +glmc_vec_adds(vec3 v, float s, vec3 dest) { + glm_vec_adds(v, s, dest); +} + +CGLM_EXPORT +void +glmc_vec_sub(vec3 a, vec3 b, vec3 dest) { + glm_vec_sub(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec_subs(vec3 v, float s, vec3 dest) { + glm_vec_subs(v, s, dest); +} + +CGLM_EXPORT +void +glmc_vec_mul(vec3 a, vec3 b, vec3 d) { + glm_vec_mul(a, b, d); } CGLM_EXPORT @@ -92,6 +110,18 @@ glmc_vec_scale_as(vec3 v, float s, vec3 dest) { glm_vec_scale_as(v, s, dest); } +CGLM_EXPORT +void +glmc_vec_div(vec3 a, vec3 b, vec3 dest) { + glm_vec_div(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec_divs(vec3 a, float s, vec3 dest) { + glm_vec_divs(a, s, dest); +} + CGLM_EXPORT void glmc_vec_flipsign(vec3 v) { diff --git a/src/vec4.c b/src/vec4.c index df93556..282712c 100644 --- a/src/vec4.c +++ b/src/vec4.c @@ -70,14 +70,32 @@ glmc_vec4_norm2(vec4 vec) { CGLM_EXPORT void -glmc_vec4_add(vec4 v1, vec4 v2, vec4 dest) { - glm_vec4_add(v1, v2, dest); +glmc_vec4_add(vec4 a, vec4 b, vec4 dest) { + glm_vec4_add(a, b, dest); } CGLM_EXPORT void -glmc_vec4_sub(vec4 v1, vec4 v2, vec4 dest) { - glm_vec4_sub(v1, v2, dest); +glmc_vec4_adds(vec4 v, float s, vec4 dest) { + glm_vec4_adds(v, s, dest); +} + +CGLM_EXPORT +void +glmc_vec4_sub(vec4 a, vec4 b, vec4 dest) { + glm_vec4_sub(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec4_subs(vec4 v, float s, vec4 dest) { + glm_vec4_subs(v, s, dest); +} + +CGLM_EXPORT +void +glmc_vec4_mul(vec4 a, vec4 b, vec4 d) { + glm_vec4_mul(a, b, d); } CGLM_EXPORT @@ -92,6 +110,18 @@ glmc_vec4_scale_as(vec3 v, float s, vec3 dest) { glm_vec4_scale_as(v, s, dest); } +CGLM_EXPORT +void +glmc_vec4_div(vec4 a, vec4 b, vec4 dest) { + glm_vec4_div(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec4_divs(vec4 v, float s, vec4 dest) { + glm_vec4_divs(v, s, dest); +} + CGLM_EXPORT void glmc_vec4_flipsign(vec4 v) { diff --git a/test/src/test_vec3.c b/test/src/test_vec3.c index 5a3a4c8..c33e5ec 100644 --- a/test/src/test_vec3.c +++ b/test/src/test_vec3.c @@ -9,7 +9,7 @@ void test_vec3(void **state) { - vec3 v; + vec3 v, v1; /* test zero */ glm_vec_zero(v); @@ -18,4 +18,35 @@ test_vec3(void **state) { /* test one */ glm_vec_one(v); test_assert_vec3_eq(GLM_VEC3_ONE, v); + + /* adds, subs, div, divs, mul */ + glm_vec_add(v, GLM_VEC3_ONE, v); + assert_true(glmc_vec_eq_eps(v, 2)); + + glm_vec_adds(v, 10, v); + assert_true(glmc_vec_eq_eps(v, 12)); + + glm_vec_sub(v, GLM_VEC3_ONE, v); + assert_true(glmc_vec_eq_eps(v, 11)); + + glm_vec_subs(v, 1, v); + assert_true(glmc_vec_eq_eps(v, 10)); + + glm_vec_broadcast(2, v1); + glm_vec_div(v, v1, v); + assert_true(glmc_vec_eq_eps(v, 5)); + + glm_vec_divs(v, 0.5, v); + assert_true(glmc_vec_eq_eps(v, 10)); + + glm_vec_mul(v, v1, v); + assert_true(glmc_vec_eq_eps(v, 20)); + + glm_vec_scale(v, 0.5, v); + assert_true(glmc_vec_eq_eps(v, 10)); + + glm_vec_normalize_to(v, v1); + glm_vec_scale(v1, 0.8, v1); + glm_vec_scale_as(v, 0.8, v); + test_assert_vec3_eq(v1, v); } diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c index a80d9c7..60772a9 100644 --- a/test/src/test_vec4.c +++ b/test/src/test_vec4.c @@ -78,4 +78,35 @@ test_vec4(void **state) { /* test one */ glm_vec4_one(v); test_assert_vec4_eq(GLM_VEC4_ONE, v); + + /* adds, subs, div, divs, mul */ + glm_vec4_add(v, GLM_VEC4_ONE, v); + assert_true(glmc_vec4_eq_eps(v, 2)); + + glm_vec4_adds(v, 10, v); + assert_true(glmc_vec4_eq_eps(v, 12)); + + glm_vec4_sub(v, GLM_VEC4_ONE, v); + assert_true(glmc_vec4_eq_eps(v, 11)); + + glm_vec4_subs(v, 1, v); + assert_true(glmc_vec4_eq_eps(v, 10)); + + glm_vec4_broadcast(2, v1); + glm_vec4_div(v, v1, v); + assert_true(glmc_vec4_eq_eps(v, 5)); + + glm_vec4_divs(v, 0.5, v); + assert_true(glmc_vec4_eq_eps(v, 10)); + + glm_vec4_mul(v, v1, v); + assert_true(glmc_vec4_eq_eps(v, 20)); + + glm_vec4_scale(v, 0.5, v); + assert_true(glmc_vec4_eq_eps(v, 10)); + + glm_vec4_normalize_to(v, v1); + glm_vec4_scale(v1, 0.8, v1); + glm_vec4_scale_as(v, 0.8, v); + test_assert_vec4_eq(v1, v); } From c05f58a1699307c4ace5733dad8f6fa93f3801c2 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 15:46:43 +0300 Subject: [PATCH 07/10] vec: add addadd, subadd and muladd helpers --- docs/source/vec3.rst | 33 +++++++++++++++++ docs/source/vec4.rst | 33 +++++++++++++++++ include/cglm/call/vec3.h | 12 +++++++ include/cglm/call/vec4.h | 12 +++++++ include/cglm/vec3.h | 54 ++++++++++++++++++++++++++++ include/cglm/vec4.h | 76 ++++++++++++++++++++++++++++++++++++++++ src/vec3.c | 18 ++++++++++ src/vec4.c | 20 ++++++++++- test/src/test_vec3.c | 16 ++++++++- test/src/test_vec4.c | 14 ++++++++ 10 files changed, 286 insertions(+), 2 deletions(-) diff --git a/docs/source/vec3.rst b/docs/source/vec3.rst index 86f17e4..1397700 100644 --- a/docs/source/vec3.rst +++ b/docs/source/vec3.rst @@ -46,6 +46,9 @@ Functions: #. :c:func:`glm_vec_scale_as` #. :c:func:`glm_vec_div` #. :c:func:`glm_vec_divs` +#. :c:func:`glm_vec_addadd` +#. :c:func:`glm_vec_subadd` +#. :c:func:`glm_vec_muladd` #. :c:func:`glm_vec_flipsign` #. :c:func:`glm_vec_flipsign_to` #. :c:func:`glm_vec_inv` @@ -220,6 +223,36 @@ Functions documentation | *[in]* **s** scalar | *[out]* **dest** result = (a[0] / s, a[1] / s, a[2] / s]) +.. c:function:: void glm_vec_addadd(vec3 a, vec3 b, vec3 dest) + + | add two vectors and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector 1 + | *[in]* **b** vector 2 + | *[out]* **dest** dest += (a + b) + +.. c:function:: void glm_vec_subadd(vec3 a, vec3 b, vec3 dest) + + | sub two vectors and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector 1 + | *[in]* **b** vector 2 + | *[out]* **dest** dest += (a - b) + +.. c:function:: void glm_vec_muladd(vec3 a, vec3 b, vec3 dest) + + | mul two vectors and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector 1 + | *[in]* **b** vector 2 + | *[out]* **dest** dest += (a * b) + .. c:function:: void glm_vec_flipsign(vec3 v) flip sign of all vec3 members diff --git a/docs/source/vec4.rst b/docs/source/vec4.rst index 89ac5c2..bd27978 100644 --- a/docs/source/vec4.rst +++ b/docs/source/vec4.rst @@ -38,6 +38,9 @@ Functions: #. :c:func:`glm_vec4_scale_as` #. :c:func:`glm_vec4_div` #. :c:func:`glm_vec4_divs` +#. :c:func:`glm_vec4_addadd` +#. :c:func:`glm_vec4_subadd` +#. :c:func:`glm_vec4_muladd` #. :c:func:`glm_vec4_flipsign` #. :c:func:`glm_vec_flipsign_to` #. :c:func:`glm_vec4_inv` @@ -205,6 +208,36 @@ Functions documentation | *[in]* **s** scalar | *[out]* **dest** result = (a[0] / s, a[1] / s, a[2] / s, a[3] / s) +.. c:function:: void glm_vec4_addadd(vec4 a, vec4 b, vec4 dest) + + | add two vectors and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector 1 + | *[in]* **b** vector 2 + | *[out]* **dest** dest += (a + b) + +.. c:function:: void glm_vec4_subadd(vec4 a, vec4 b, vec4 dest) + + | sub two vectors and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector 1 + | *[in]* **b** vector 2 + | *[out]* **dest** dest += (a - b) + +.. c:function:: void glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) + + | mul two vectors and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector 1 + | *[in]* **b** vector 2 + | *[out]* **dest** dest += (a * b) + .. c:function:: void glm_vec4_flipsign(vec4 v) flip sign of all vec4 members diff --git a/include/cglm/call/vec3.h b/include/cglm/call/vec3.h index b2374e6..495ad0b 100644 --- a/include/cglm/call/vec3.h +++ b/include/cglm/call/vec3.h @@ -92,6 +92,18 @@ CGLM_EXPORT void glmc_vec_divs(vec3 a, float s, vec3 dest); +CGLM_EXPORT +void +glmc_vec_addadd(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec_subadd(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec_muladd(vec3 a, vec3 b, vec3 dest); + CGLM_EXPORT void glmc_vec_flipsign(vec3 v); diff --git a/include/cglm/call/vec4.h b/include/cglm/call/vec4.h index b460962..0fea5bf 100644 --- a/include/cglm/call/vec4.h +++ b/include/cglm/call/vec4.h @@ -93,6 +93,18 @@ CGLM_EXPORT void glmc_vec4_divs(vec4 v, float s, vec4 dest); +CGLM_EXPORT +void +glmc_vec4_addadd(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_subadd(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_muladd(vec4 a, vec4 b, vec4 dest); + CGLM_EXPORT void glmc_vec4_flipsign(vec4 v); diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index b3012b6..f803af6 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -37,6 +37,9 @@ CGLM_INLINE void glm_vec_scale_as(vec3 v, float s, vec3 dest); CGLM_INLINE void glm_vec_div(vec3 a, vec3 b, vec3 dest); CGLM_INLINE void glm_vec_divs(vec3 a, float s, vec3 dest); + CGLM_INLINE void glm_vec_addadd(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec_subadd(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec_muladd(vec3 a, vec3 b, vec3 dest); CGLM_INLINE void glm_vec_flipsign(vec3 v); CGLM_INLINE void glm_vec_inv(vec3 v); CGLM_INLINE void glm_vec_inv_to(vec3 v, vec3 dest); @@ -335,6 +338,57 @@ glm_vec_divs(vec3 v, float s, vec3 dest) { dest[2] = v[2] / s; } +/*! + * @brief add two vectors and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a + b) + */ +CGLM_INLINE +void +glm_vec_addadd(vec3 a, vec3 b, vec3 dest) { + dest[0] += a[0] + b[0]; + dest[1] += a[1] + b[1]; + dest[2] += a[2] + b[2]; +} + +/*! + * @brief sub two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a + b) + */ +CGLM_INLINE +void +glm_vec_subadd(vec3 a, vec3 b, vec3 dest) { + dest[0] += a[0] - b[0]; + dest[1] += a[1] - b[1]; + dest[2] += a[2] - b[2]; +} + +/*! + * @brief mul two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_vec_muladd(vec3 a, vec3 b, vec3 dest) { + dest[0] += a[0] * b[0]; + dest[1] += a[1] * b[1]; + dest[2] += a[2] * b[2]; +} + /*! * @brief flip sign of all vec3 members * diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index e1319b9..c07a45e 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -37,6 +37,9 @@ CGLM_INLINE void glm_vec4_scale_as(vec4 v, float s, vec4 dest); CGLM_INLINE void glm_vec4_div(vec4 a, vec4 b, vec4 dest); CGLM_INLINE void glm_vec4_divs(vec4 v, float s, vec4 dest); + CGLM_INLINE void glm_vec4_addadd(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_subadd(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_muladd(vec4 a, vec4 b, vec4 dest); CGLM_INLINE void glm_vec4_flipsign(vec4 v); CGLM_INLINE void glm_vec4_inv(vec4 v); CGLM_INLINE void glm_vec4_inv_to(vec4 v, vec4 dest); @@ -396,6 +399,79 @@ glm_vec4_divs(vec4 v, float s, vec4 dest) { #endif } + +/*! + * @brief add two vectors and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a + b) + */ +CGLM_INLINE +void +glm_vec4_addadd(vec4 a, vec4 b, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(dest), + _mm_add_ps(_mm_load_ps(a), + _mm_load_ps(b)))); +#else + dest[0] += a[0] + b[0]; + dest[1] += a[1] + b[1]; + dest[2] += a[2] + b[2]; + dest[3] += a[3] + b[3]; +#endif +} + +/*! + * @brief sub two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a - b) + */ +CGLM_INLINE +void +glm_vec4_subadd(vec4 a, vec4 b, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(dest), + _mm_sub_ps(_mm_load_ps(a), + _mm_load_ps(b)))); +#else + dest[0] += a[0] - b[0]; + dest[1] += a[1] - b[1]; + dest[2] += a[2] - b[2]; + dest[3] += a[3] - b[3]; +#endif +} + +/*! + * @brief mul two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(dest), + _mm_mul_ps(_mm_load_ps(a), + _mm_load_ps(b)))); +#else + dest[0] += a[0] * b[0]; + dest[1] += a[1] * b[1]; + dest[2] += a[2] * b[2]; + dest[3] += a[3] * b[3]; +#endif +} + /*! * @brief flip sign of all vec4 members * diff --git a/src/vec3.c b/src/vec3.c index b8553ec..d484446 100644 --- a/src/vec3.c +++ b/src/vec3.c @@ -122,6 +122,24 @@ glmc_vec_divs(vec3 a, float s, vec3 dest) { glm_vec_divs(a, s, dest); } +CGLM_EXPORT +void +glmc_vec_addadd(vec3 a, vec3 b, vec3 dest) { + glm_vec_addadd(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec_subadd(vec3 a, vec3 b, vec3 dest) { + glm_vec_subadd(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec_muladd(vec3 a, vec3 b, vec3 dest) { + glm_vec_muladd(a, b, dest); +} + CGLM_EXPORT void glmc_vec_flipsign(vec3 v) { diff --git a/src/vec4.c b/src/vec4.c index 282712c..c3df5d2 100644 --- a/src/vec4.c +++ b/src/vec4.c @@ -106,7 +106,7 @@ glmc_vec4_scale(vec4 v, float s, vec4 dest) { CGLM_EXPORT void -glmc_vec4_scale_as(vec3 v, float s, vec3 dest) { +glmc_vec4_scale_as(vec4 v, float s, vec4 dest) { glm_vec4_scale_as(v, s, dest); } @@ -122,6 +122,24 @@ glmc_vec4_divs(vec4 v, float s, vec4 dest) { glm_vec4_divs(v, s, dest); } +CGLM_EXPORT +void +glmc_vec4_addadd(vec4 a, vec4 b, vec4 dest) { + glm_vec4_addadd(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec4_subadd(vec4 a, vec4 b, vec4 dest) { + glm_vec4_subadd(a, b, dest); +} + +CGLM_EXPORT +void +glmc_vec4_muladd(vec4 a, vec4 b, vec4 dest) { + glm_vec4_muladd(a, b, dest); +} + CGLM_EXPORT void glmc_vec4_flipsign(vec4 v) { diff --git a/test/src/test_vec3.c b/test/src/test_vec3.c index c33e5ec..7c85d1f 100644 --- a/test/src/test_vec3.c +++ b/test/src/test_vec3.c @@ -9,7 +9,7 @@ void test_vec3(void **state) { - vec3 v, v1; + vec3 v, v1, v2; /* test zero */ glm_vec_zero(v); @@ -49,4 +49,18 @@ test_vec3(void **state) { glm_vec_scale(v1, 0.8, v1); glm_vec_scale_as(v, 0.8, v); test_assert_vec3_eq(v1, v); + + /* addadd, subadd, muladd */ + glm_vec_one(v); + + glm_vec_addadd(GLM_VEC3_ONE, GLM_VEC3_ONE, v); + assert_true(glmc_vec_eq_eps(v, 3)); + + glm_vec_subadd(GLM_VEC3_ONE, GLM_VEC3_ZERO, v); + assert_true(glmc_vec_eq_eps(v, 4)); + + glm_vec_broadcast(2, v1); + glm_vec_broadcast(3, v2); + glm_vec_muladd(v1, v2, v); + assert_true(glmc_vec_eq_eps(v, 10)); } diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c index 60772a9..93ce9f7 100644 --- a/test/src/test_vec4.c +++ b/test/src/test_vec4.c @@ -109,4 +109,18 @@ test_vec4(void **state) { glm_vec4_scale(v1, 0.8, v1); glm_vec4_scale_as(v, 0.8, v); test_assert_vec4_eq(v1, v); + + /* addadd, subadd, muladd */ + glm_vec4_one(v); + + glm_vec4_addadd(GLM_VEC4_ONE, GLM_VEC4_ONE, v); + assert_true(glmc_vec4_eq_eps(v, 3)); + + glm_vec4_subadd(GLM_VEC4_ONE, GLM_VEC4_ZERO, v); + assert_true(glmc_vec4_eq_eps(v, 4)); + + glm_vec4_broadcast(2, v1); + glm_vec4_broadcast(3, v2); + glm_vec4_muladd(v1, v2, v); + assert_true(glmc_vec4_eq_eps(v, 10)); } From 13345f06c131572d8bdc265a33b8993e916ca238 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 15:50:05 +0300 Subject: [PATCH 08/10] fix vec4 scalar ops --- include/cglm/vec4.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index c07a45e..26247c7 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -198,7 +198,7 @@ glm_vec4_norm2(vec4 v) { x0 = _mm_add_ps(x0, _mm_shuffle1_ps(x0, 1, 0, 3, 2)); return _mm_cvtss_f32(_mm_add_ss(x0, _mm_shuffle1_ps(x0, 0, 1, 0, 1))); #else - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; + return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]; #endif } @@ -254,10 +254,10 @@ glm_vec4_adds(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(v), _mm_set1_ps(s))); #else - dest[0] = v1[0] + s; - dest[1] = v1[1] + s; - dest[2] = v1[2] + s; - dest[3] = v1[3] + s; + dest[0] = v[0] + s; + dest[1] = v[1] + s; + dest[2] = v[2] + s; + dest[3] = v[3] + s; #endif } @@ -294,10 +294,10 @@ glm_vec4_subs(vec4 v, float s, vec4 dest) { #if defined( __SSE__ ) || defined( __SSE2__ ) _mm_store_ps(dest, _mm_sub_ps(_mm_load_ps(v), _mm_set1_ps(s))); #else - dest[0] = v1[0] - s; - dest[1] = v1[1] - s; - dest[2] = v1[2] - s; - dest[3] = v1[3] - s; + dest[0] = v[0] - s; + dest[1] = v[1] - s; + dest[2] = v[2] - s; + dest[3] = v[3] - s; #endif } From 7f7007574b11c9fc4d03f138d2fd16555c24e4bc Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 22:30:44 +0300 Subject: [PATCH 09/10] vec: implement muladd's scalar version --- docs/source/vec3.rst | 11 +++++++++++ docs/source/vec4.rst | 11 +++++++++++ include/cglm/call/vec3.h | 4 ++++ include/cglm/call/vec4.h | 4 ++++ include/cglm/vec3.h | 17 +++++++++++++++++ include/cglm/vec4.h | 24 ++++++++++++++++++++++++ src/vec3.c | 6 ++++++ src/vec4.c | 6 ++++++ 8 files changed, 83 insertions(+) diff --git a/docs/source/vec3.rst b/docs/source/vec3.rst index 1397700..77aebb6 100644 --- a/docs/source/vec3.rst +++ b/docs/source/vec3.rst @@ -49,6 +49,7 @@ Functions: #. :c:func:`glm_vec_addadd` #. :c:func:`glm_vec_subadd` #. :c:func:`glm_vec_muladd` +#. :c:func:`glm_vec_muladds` #. :c:func:`glm_vec_flipsign` #. :c:func:`glm_vec_flipsign_to` #. :c:func:`glm_vec_inv` @@ -253,6 +254,16 @@ Functions documentation | *[in]* **b** vector 2 | *[out]* **dest** dest += (a * b) +.. c:function:: void glm_vec_muladds(vec3 a, float s, vec3 dest) + + | mul vector with scalar and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector + | *[in]* **s** scalar + | *[out]* **dest** dest += (a * b) + .. c:function:: void glm_vec_flipsign(vec3 v) flip sign of all vec3 members diff --git a/docs/source/vec4.rst b/docs/source/vec4.rst index bd27978..a1b7250 100644 --- a/docs/source/vec4.rst +++ b/docs/source/vec4.rst @@ -41,6 +41,7 @@ Functions: #. :c:func:`glm_vec4_addadd` #. :c:func:`glm_vec4_subadd` #. :c:func:`glm_vec4_muladd` +#. :c:func:`glm_vec4_muladds` #. :c:func:`glm_vec4_flipsign` #. :c:func:`glm_vec_flipsign_to` #. :c:func:`glm_vec4_inv` @@ -238,6 +239,16 @@ Functions documentation | *[in]* **b** vector 2 | *[out]* **dest** dest += (a * b) +.. c:function:: void glm_vec4_muladds(vec4 a, float s, vec4 dest) + + | mul vector with scalar and add result to sum + | it applies += operator so dest must be initialized + + Parameters: + | *[in]* **a** vector + | *[in]* **s** scalar + | *[out]* **dest** dest += (a * b) + .. c:function:: void glm_vec4_flipsign(vec4 v) flip sign of all vec4 members diff --git a/include/cglm/call/vec3.h b/include/cglm/call/vec3.h index 495ad0b..8fcee4f 100644 --- a/include/cglm/call/vec3.h +++ b/include/cglm/call/vec3.h @@ -104,6 +104,10 @@ CGLM_EXPORT void glmc_vec_muladd(vec3 a, vec3 b, vec3 dest); +CGLM_EXPORT +void +glmc_vec_muladds(vec3 a, float s, vec3 dest); + CGLM_EXPORT void glmc_vec_flipsign(vec3 v); diff --git a/include/cglm/call/vec4.h b/include/cglm/call/vec4.h index 0fea5bf..adcfc94 100644 --- a/include/cglm/call/vec4.h +++ b/include/cglm/call/vec4.h @@ -105,6 +105,10 @@ CGLM_EXPORT void glmc_vec4_muladd(vec4 a, vec4 b, vec4 dest); +CGLM_EXPORT +void +glmc_vec4_muladds(vec4 a, float s, vec4 dest); + CGLM_EXPORT void glmc_vec4_flipsign(vec4 v); diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index f803af6..9add4c3 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -389,6 +389,23 @@ glm_vec_muladd(vec3 a, vec3 b, vec3 dest) { dest[2] += a[2] * b[2]; } +/*! + * @brief mul vector with scalar and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_vec_muladds(vec3 a, float s, vec3 dest) { + dest[0] += a[0] * s; + dest[1] += a[1] * s; + dest[2] += a[2] * s; +} + /*! * @brief flip sign of all vec3 members * diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 26247c7..1824357 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -472,6 +472,30 @@ glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) { #endif } +/*! + * @brief mul vector with scalar and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_vec4_muladds(vec4 a, float s, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + _mm_store_ps(dest, _mm_add_ps(_mm_load_ps(dest), + _mm_mul_ps(_mm_load_ps(a), + _mm_set1_ps(s)))); +#else + dest[0] += a[0] * s; + dest[1] += a[1] * s; + dest[2] += a[2] * s; + dest[3] += a[3] * s; +#endif +} + /*! * @brief flip sign of all vec4 members * diff --git a/src/vec3.c b/src/vec3.c index d484446..28fda51 100644 --- a/src/vec3.c +++ b/src/vec3.c @@ -140,6 +140,12 @@ glmc_vec_muladd(vec3 a, vec3 b, vec3 dest) { glm_vec_muladd(a, b, dest); } +CGLM_EXPORT +void +glmc_vec_muladds(vec3 a, float s, vec3 dest) { + glm_vec_muladds(a, s, dest); +} + CGLM_EXPORT void glmc_vec_flipsign(vec3 v) { diff --git a/src/vec4.c b/src/vec4.c index c3df5d2..fb22796 100644 --- a/src/vec4.c +++ b/src/vec4.c @@ -140,6 +140,12 @@ glmc_vec4_muladd(vec4 a, vec4 b, vec4 dest) { glm_vec4_muladd(a, b, dest); } +CGLM_EXPORT +void +glmc_vec4_muladds(vec4 a, float s, vec4 dest) { + glm_vec4_muladds(a, s, dest); +} + CGLM_EXPORT void glmc_vec4_flipsign(vec4 v) { From d6395d4fb8dbfb90864ab8a6fd3456165236a956 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 13 Apr 2018 22:33:32 +0300 Subject: [PATCH 10/10] vec: optimize rotate vector using matrix * add mat3 version --- docs/source/vec3.rst | 10 +++++++++ include/cglm/vec3.h | 50 +++++++++++++++++++++++++++++++++++++------- test/src/test_vec3.c | 12 +++++++++++ 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/docs/source/vec3.rst b/docs/source/vec3.rst index 77aebb6..fcbfbfb 100644 --- a/docs/source/vec3.rst +++ b/docs/source/vec3.rst @@ -60,6 +60,7 @@ Functions: #. :c:func:`glm_vec_angle` #. :c:func:`glm_vec_rotate` #. :c:func:`glm_vec_rotate_m4` +#. :c:func:`glm_vec_rotate_m3` #. :c:func:`glm_vec_proj` #. :c:func:`glm_vec_center` #. :c:func:`glm_vec_maxv` @@ -338,6 +339,15 @@ Functions documentation | *[in]* **v** vector | *[out]* **dest** rotated vector +.. c:function:: void glm_vec_rotate_m3(mat3 m, vec3 v, vec3 dest) + + apply rotation matrix to vector + + Parameters: + | *[in]* **m** affine matrix or rot matrix + | *[in]* **v** vector + | *[out]* **dest** rotated vector + .. c:function:: void glm_vec_proj(vec3 a, vec3 b, vec3 dest) project a vector onto b vector diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 9add4c3..9976ad9 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -67,6 +67,7 @@ #define cglm_vec3_h #include "common.h" +#include "vec4.h" #include "vec3-ext.h" #include "util.h" @@ -551,6 +552,12 @@ glm_vec_rotate(vec3 v, float angle, vec3 axis) { /*! * @brief apply rotation matrix to vector * + * matrix format should be (no perspective): + * a b c x + * e f g y + * i j k z + * 0 0 0 w + * * @param[in] m affine matrix or rot matrix * @param[in] v vector * @param[out] dest rotated vector @@ -558,17 +565,44 @@ glm_vec_rotate(vec3 v, float angle, vec3 axis) { CGLM_INLINE void glm_vec_rotate_m4(mat4 m, vec3 v, vec3 dest) { - vec3 res, x, y, z; + vec4 x, y, z, res; - glm_vec_normalize_to(m[0], x); - glm_vec_normalize_to(m[1], y); - glm_vec_normalize_to(m[2], z); + glm_vec4_normalize_to(m[0], x); + glm_vec4_normalize_to(m[1], y); + glm_vec4_normalize_to(m[2], z); - res[0] = x[0] * v[0] + y[0] * v[1] + z[0] * v[2]; - res[1] = x[1] * v[0] + y[1] * v[1] + z[1] * v[2]; - res[2] = x[2] * v[0] + y[2] * v[1] + z[2] * v[2]; + glm_vec4_scale(x, v[0], res); + glm_vec4_muladds(y, v[1], res); + glm_vec4_muladds(y, v[2], res); - glm_vec_copy(res, dest); + glm_vec3(res, dest); +} + +/*! + * @brief apply rotation matrix to vector + * + * @param[in] m affine matrix or rot matrix + * @param[in] v vector + * @param[out] dest rotated vector + */ +CGLM_INLINE +void +glm_vec_rotate_m3(mat3 m, vec3 v, vec3 dest) { + vec4 res, x, y, z; + + glm_vec4(m[0], 0.0f, x); + glm_vec4(m[1], 0.0f, y); + glm_vec4(m[2], 0.0f, z); + + glm_vec4_normalize(x); + glm_vec4_normalize(y); + glm_vec4_normalize(z); + + glm_vec4_scale(x, v[0], res); + glm_vec4_muladds(y, v[1], res); + glm_vec4_muladds(y, v[2], res); + + glm_vec3(res, dest); } /*! diff --git a/test/src/test_vec3.c b/test/src/test_vec3.c index 7c85d1f..dd0c55d 100644 --- a/test/src/test_vec3.c +++ b/test/src/test_vec3.c @@ -9,6 +9,8 @@ void test_vec3(void **state) { + mat3 rot1m3; + mat4 rot1; vec3 v, v1, v2; /* test zero */ @@ -63,4 +65,14 @@ test_vec3(void **state) { glm_vec_broadcast(3, v2); glm_vec_muladd(v1, v2, v); assert_true(glmc_vec_eq_eps(v, 10)); + + /* rotate */ + glm_vec_copy(GLM_YUP, v); + glm_rotate_make(rot1, glm_rad(90), GLM_XUP); + glm_vec_rotate_m4(rot1, v, v1); + glm_mat4_pick3(rot1, rot1m3); + glm_vec_rotate_m3(rot1m3, v, v2); + + test_assert_vec3_eq(v1, v2); + test_assert_vec3_eq(v1, GLM_ZUP); }