aboutsummaryrefslogtreecommitdiffstats
path: root/include/glm/simd/common.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/glm/simd/common.h')
-rw-r--r--include/glm/simd/common.h169
1 files changed, 169 insertions, 0 deletions
diff --git a/include/glm/simd/common.h b/include/glm/simd/common.h
new file mode 100644
index 0000000..14af85b
--- /dev/null
+++ b/include/glm/simd/common.h
@@ -0,0 +1,169 @@
+#if(GLM_COMPILER & GLM_COMPILER_VC)
+#pragma warning(push)
+#pragma warning(disable : 4510 4512 4610)
+#endif
+
+ union ieee754_QNAN
+ {
+ const float f;
+ struct i
+ {
+ const unsigned int mantissa:23, exp:8, sign:1;
+ };
+
+ ieee754_QNAN() : f(0.0)/*, mantissa(0x7FFFFF), exp(0xFF), sign(0x0)*/ {}
+ };
+
+#if(GLM_COMPILER & GLM_COMPILER_VC)
+#pragma warning(pop)
+#endif
+
+static const __m128 GLM_VAR_USED glm_zero = _mm_setzero_ps();
+static const __m128 GLM_VAR_USED glm_one = _mm_set_ps1(1.0f);
+static const __m128 GLM_VAR_USED glm_half = _mm_set_ps1(0.5f);
+static const __m128 GLM_VAR_USED glm_minus_one = _mm_set_ps1(-1.0f);
+static const __m128 GLM_VAR_USED glm_two = _mm_set_ps1(2.0f);
+static const __m128 GLM_VAR_USED glm_three = _mm_set_ps1(3.0f);
+
+static const ieee754_QNAN glm_abs_mask;
+static const __m128 GLM_VAR_USED glm_abs4_mask = _mm_set_ps1(glm_abs_mask.f);
+static const __m128 GLM_VAR_USED glm_epi32_sign_mask = _mm_castsi128_ps(_mm_set1_epi32(static_cast<int>(0x80000000)));
+static const __m128 GLM_VAR_USED glm_ps_2pow23 = _mm_set_ps1(8388608.0f);
+static const __m128 GLM_VAR_USED glm_ps_1 = _mm_set_ps1(1.0f);
+
+GLM_FUNC_QUALIFIER __m128 glm_abs_ps(__m128 x)
+{
+ return _mm_and_ps(glm_abs4_mask, x);
+}
+
+//sign
+GLM_FUNC_QUALIFIER __m128 glm_sgn_ps(__m128 x)
+{
+ __m128 const Cmp0 = _mm_cmplt_ps(x, glm_zero);
+ __m128 const Cmp1 = _mm_cmpgt_ps(x, glm_zero);
+ __m128 const And0 = _mm_and_ps(Cmp0, glm_minus_one);
+ __m128 const And1 = _mm_and_ps(Cmp1, glm_one);
+ return _mm_or_ps(And0, And1);
+}
+
+//round
+GLM_FUNC_QUALIFIER __m128 glm_rnd_ps(__m128 x)
+{
+ __m128 const and0 = _mm_and_ps(glm_epi32_sign_mask, x);
+ __m128 const or0 = _mm_or_ps(and0, glm_ps_2pow23);
+ __m128 const add0 = _mm_add_ps(x, or0);
+ __m128 const sub0 = _mm_sub_ps(add0, or0);
+ return sub0;
+}
+
+//floor
+GLM_FUNC_QUALIFIER __m128 glm_flr_ps(__m128 x)
+{
+ __m128 const rnd0 = glm_rnd_ps(x);
+ __m128 const cmp0 = _mm_cmplt_ps(x, rnd0);
+ __m128 const and0 = _mm_and_ps(cmp0, glm_ps_1);
+ __m128 const sub0 = _mm_sub_ps(rnd0, and0);
+ return sub0;
+}
+
+//trunc
+//GLM_FUNC_QUALIFIER __m128 _mm_trc_ps(__m128 v)
+//{
+// return __m128();
+//}
+
+//roundEven
+GLM_FUNC_QUALIFIER __m128 glm_rde_ps(__m128 x)
+{
+ __m128 const and0 = _mm_and_ps(glm_epi32_sign_mask, x);
+ __m128 const or0 = _mm_or_ps(and0, glm_ps_2pow23);
+ __m128 const add0 = _mm_add_ps(x, or0);
+ __m128 const sub0 = _mm_sub_ps(add0, or0);
+ return sub0;
+}
+
+GLM_FUNC_QUALIFIER __m128 glm_ceil_ps(__m128 x)
+{
+ __m128 const rnd0 = glm_rnd_ps(x);
+ __m128 const cmp0 = _mm_cmpgt_ps(x, rnd0);
+ __m128 const and0 = _mm_and_ps(cmp0, glm_ps_1);
+ __m128 const add0 = _mm_add_ps(rnd0, and0);
+ return add0;
+}
+
+GLM_FUNC_QUALIFIER __m128 glm_frc_ps(__m128 x)
+{
+ __m128 const flr0 = glm_flr_ps(x);
+ __m128 const sub0 = _mm_sub_ps(x, flr0);
+ return sub0;
+}
+
+GLM_FUNC_QUALIFIER __m128 glm_mod_ps(__m128 x, __m128 y)
+{
+ __m128 const div0 = _mm_div_ps(x, y);
+ __m128 const flr0 = glm_flr_ps(div0);
+ __m128 const mul0 = _mm_mul_ps(y, flr0);
+ __m128 const sub0 = _mm_sub_ps(x, mul0);
+ return sub0;
+}
+
+GLM_FUNC_QUALIFIER __m128 glm_clp_ps(__m128 v, __m128 minVal, __m128 maxVal)
+{
+ __m128 const min0 = _mm_min_ps(v, maxVal);
+ __m128 const max0 = _mm_max_ps(min0, minVal);
+ return max0;
+}
+
+GLM_FUNC_QUALIFIER __m128 glm_mix_ps(__m128 v1, __m128 v2, __m128 a)
+{
+ __m128 const sub0 = _mm_sub_ps(glm_one, a);
+ __m128 const mul0 = _mm_mul_ps(v1, sub0);
+ __m128 const mul1 = _mm_mul_ps(v2, a);
+ __m128 const add0 = _mm_add_ps(mul0, mul1);
+ return add0;
+}
+
+//step
+GLM_FUNC_QUALIFIER __m128 glm_stp_ps(__m128 edge, __m128 x)
+{
+ __m128 const cmp = _mm_cmple_ps(x, edge);
+ return _mm_movemask_ps(cmp) == 0 ? glm_one : glm_zero;
+}
+
+// smoothstep
+GLM_FUNC_QUALIFIER __m128 glm_ssp_ps(__m128 edge0, __m128 edge1, __m128 x)
+{
+ __m128 const sub0 = _mm_sub_ps(x, edge0);
+ __m128 const sub1 = _mm_sub_ps(edge1, edge0);
+ __m128 const div0 = _mm_sub_ps(sub0, sub1);
+ __m128 const clp0 = glm_clp_ps(div0, glm_zero, glm_one);
+ __m128 const mul0 = _mm_mul_ps(glm_two, clp0);
+ __m128 const sub2 = _mm_sub_ps(glm_three, mul0);
+ __m128 const mul1 = _mm_mul_ps(clp0, clp0);
+ __m128 const mul2 = _mm_mul_ps(mul1, sub2);
+ return mul2;
+}
+
+/// \todo
+//GLM_FUNC_QUALIFIER __m128 glm_nan_ps(__m128 x)
+//{
+// __m128 empty;
+// return empty;
+//}
+
+/// \todo
+//GLM_FUNC_QUALIFIER __m128 glm_inf_ps(__m128 x)
+//{
+// __m128 empty;
+// return empty;
+//}
+
+// SSE scalar reciprocal sqrt using rsqrt op, plus one Newton-Rhaphson iteration
+// By Elan Ruskin, http://assemblyrequired.crashworks.org/
+GLM_FUNC_QUALIFIER __m128 glm_sqrt_wip_ss(__m128 x)
+{
+ __m128 const recip = _mm_rsqrt_ss(x); // "estimate" opcode
+ __m128 const halfrecip = _mm_mul_ss(glm_half, recip);
+ __m128 const threeminus_xrr = _mm_sub_ss(glm_three, _mm_mul_ss(x, _mm_mul_ss(recip, recip)));
+ return _mm_mul_ss(halfrecip, threeminus_xrr);
+}