From 14292f8e65c7ed2016fe1b0f04ade6da6afb3956 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Wed, 13 Feb 2019 17:57:09 -0500 Subject: [PATCH] Add simd.hpp --- include/simd.hpp | 105 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 include/simd.hpp diff --git a/include/simd.hpp b/include/simd.hpp new file mode 100644 index 00000000..f3e32665 --- /dev/null +++ b/include/simd.hpp @@ -0,0 +1,105 @@ +#include + + +#define ALIGN(n) __attribute__((aligned(n))) + + +namespace simd { + + +template +struct f32; + + +/** Wrapper for `__m128` representing a vector of 4 single-precision float values. */ +template <> +struct f32<4> { + __m128 v; + + f32<4>() {} + f32<4>(__m128 v) : v(v) {} + template + f32<4>(T x) { + v = _mm_set_ps1((float) x); + } + /** Reads an array of 4 values */ + f32<4>(const float *x) { + v = _mm_loadu_ps(x); + } + /** Writes an array of 4 values */ + void store(float *x) { + _mm_storeu_ps(x, v); + } +}; + + +// Operator overloads + +#define DECLARE_F32_4_OPERATOR_INFIX(operator, func) \ + inline f32<4> operator(f32<4> a, f32<4> b) { \ + return f32<4>(func(a.v, b.v)); \ + } \ + template \ + f32<4> operator(T a, f32<4> b) { \ + return operator(f32<4>(a), b); \ + } \ + template \ + f32<4> operator(f32<4> a, T b) { \ + return operator(a, f32<4>(b)); \ + } + +DECLARE_F32_4_OPERATOR_INFIX(operator+, _mm_add_ps) +DECLARE_F32_4_OPERATOR_INFIX(operator-, _mm_sub_ps) +DECLARE_F32_4_OPERATOR_INFIX(operator*, _mm_mul_ps) +DECLARE_F32_4_OPERATOR_INFIX(operator/, _mm_div_ps) +DECLARE_F32_4_OPERATOR_INFIX(operator==, _mm_cmpeq_ps) +DECLARE_F32_4_OPERATOR_INFIX(operator>=, _mm_cmpge_ps) +DECLARE_F32_4_OPERATOR_INFIX(operator>, _mm_cmpgt_ps) +DECLARE_F32_4_OPERATOR_INFIX(operator<=, _mm_cmple_ps) +DECLARE_F32_4_OPERATOR_INFIX(operator<, _mm_cmplt_ps) +DECLARE_F32_4_OPERATOR_INFIX(operator!=, _mm_cmpneq_ps) + +#define DECLARE_F32_4_OPERATOR_INCREMENT(operator, func) \ + inline f32<4> &operator(f32<4> &a, f32<4> b) { \ + a.v = func(a.v, b.v); \ + return a; \ + } \ + template \ + f32<4> &operator(f32<4> &a, T b) { \ + return operator(a, f32<4>(b)); \ + } + +DECLARE_F32_4_OPERATOR_INCREMENT(operator+=, _mm_add_ps); +DECLARE_F32_4_OPERATOR_INCREMENT(operator-=, _mm_sub_ps); +DECLARE_F32_4_OPERATOR_INCREMENT(operator*=, _mm_mul_ps); +DECLARE_F32_4_OPERATOR_INCREMENT(operator/=, _mm_div_ps); + + +inline f32<4> rsqrt(f32<4> a) { + return f32<4>(_mm_rsqrt_ps(a.v)); +} + +inline f32<4> rcp(f32<4> a) { + return f32<4>(_mm_rcp_ps(a.v)); +} + + +} // namespace simd + + +namespace std { + +inline simd::f32<4> max(simd::f32<4> a, simd::f32<4> b) { + return simd::f32<4>(_mm_max_ps(a.v, b.v)); +} + +inline simd::f32<4> min(simd::f32<4> a, simd::f32<4> b) { + return simd::f32<4>(_mm_min_ps(a.v, b.v)); +} + +inline simd::f32<4> sqrt(simd::f32<4> a) { + return simd::f32<4>(_mm_sqrt_ps(a.v)); +} + +} // namespace std +