diff --git a/docs/source/vec3.rst b/docs/source/vec3.rst index 8529333..fcbfbfb 100644 --- a/docs/source/vec3.rst +++ b/docs/source/vec3.rst @@ -31,14 +31,25 @@ 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` #. :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_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` @@ -49,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` @@ -76,6 +88,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 @@ -117,24 +143,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 @@ -154,6 +207,64 @@ 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_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_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 @@ -228,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/docs/source/vec4.rst b/docs/source/vec4.rst index 6955246..a1b7250 100644 --- a/docs/source/vec4.rst +++ b/docs/source/vec4.rst @@ -24,13 +24,24 @@ 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` #. :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_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` @@ -78,6 +89,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 @@ -110,24 +128,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 @@ -146,6 +191,64 @@ 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_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_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 e79ec8f..8fcee4f 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); @@ -54,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 @@ -64,6 +84,30 @@ 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_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_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 ad915e6..adcfc94 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); @@ -51,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 @@ -65,6 +85,30 @@ 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_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_muladds(vec4 a, float s, vec4 dest); + CGLM_EXPORT void glmc_vec4_flipsign(vec4 v); 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 */ 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 714165b..9976ad9 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -28,10 +28,18 @@ 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_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); @@ -59,6 +67,7 @@ #define cglm_vec3_h #include "common.h" +#include "vec4.h" #include "vec3-ext.h" #include "util.h" @@ -103,6 +112,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(vec3 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(vec3 v) { + v[0] = 1.0f; + v[1] = 1.0f; + v[2] = 1.0f; +} + /*! * @brief vec3 dot product * @@ -164,33 +199,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]; } /*! @@ -221,14 +301,112 @@ 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; } 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 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 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 * @@ -374,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 @@ -381,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/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 eaa4eaf..1824357 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -28,10 +28,18 @@ 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_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); @@ -41,6 +49,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 @@ -111,6 +120,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 * @@ -146,7 +191,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 v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]; +#endif } /*! @@ -159,50 +212,112 @@ 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 } /*! * @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] = v[0] + s; + dest[1] = v[1] + s; + dest[2] = v[2] + s; + dest[3] = v[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] = v[0] - s; + dest[1] = v[1] - s; + dest[2] = v[2] - s; + dest[3] = v[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 } @@ -217,9 +332,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; @@ -241,14 +354,148 @@ 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; } 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 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 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 * @@ -258,8 +505,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]; @@ -312,26 +558,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 +567,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/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..28fda51 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) { @@ -64,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 @@ -80,6 +110,42 @@ 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_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_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 7228070..fb22796 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) { @@ -58,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 @@ -76,10 +106,46 @@ 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); } +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_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_muladds(vec4 a, float s, vec4 dest) { + glm_vec4_muladds(a, s, dest); +} + CGLM_EXPORT void glmc_vec4_flipsign(vec4 v) { diff --git a/test/src/test_common.c b/test/src/test_common.c index 514c006..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 */ @@ -91,6 +96,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..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); @@ -34,6 +37,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_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..dd0c55d --- /dev/null +++ b/test/src/test_vec3.c @@ -0,0 +1,78 @@ +/* + * 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) { + mat3 rot1m3; + mat4 rot1; + vec3 v, v1, v2; + + /* 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); + + /* 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); + + /* 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)); + + /* 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); +} diff --git a/test/src/test_vec4.c b/test/src/test_vec4.c index a45a700..93ce9f7 100644 --- a/test/src/test_vec4.c +++ b/test/src/test_vec4.c @@ -13,18 +13,114 @@ 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); +} + +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; + vec4 v, v1, v2; int i; float d1, d2; - /* test SSE/SIMD dot product */ - 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); 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); + + /* 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)); } + + /* 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); + + /* 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); + + /* 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)); }