Browse Source

Add f32<4>::zero. Add bit casts between f32 and i32.

tags/v1.0.0
Andrew Belt 6 years ago
parent
commit
87b7331ecc
1 changed files with 50 additions and 13 deletions
  1. +50
    -13
      include/dsp/simd.hpp

+ 50
- 13
include/dsp/simd.hpp View File

@@ -1,3 +1,4 @@
#include "common.hpp"
#include "sse_mathfun.h"
#include <emmintrin.h>

@@ -6,24 +7,51 @@ namespace rack {
namespace dsp {


inline float cast_i32_f32(int i) {
float f;
std::memcpy(&f, &i, sizeof(f));
return f;
}


inline int cast_f32_i32(float f) {
float i;
std::memcpy(&i, &f, sizeof(i));
return i;
}


template <int N>
struct f32;


/** Wrapper for `__m128` representing an aligned vector of 4 single-precision float values. */
/** Wrapper for `__m128` representing an aligned vector of 4 single-precision float values.
*/
template <>
struct f32<4> {
__m128 v;

/** Constructs an uninitialized vector. */
f32<4>() {}

/** Constructs a vector from a native `__m128` type. */
f32<4>(__m128 v) : v(v) {}

/** Constructs a vector with all elements set to `x`. */
f32<4>(float x) {
v = _mm_set_ps1(x);
}

/** Reads an array of 4 values. */
static f32<4> load(const float *x) {
return f32<4>(_mm_loadu_ps(x));
}

/** Returns a vector initialized to zero. */
static f32<4> zero() {
return f32<4>(_mm_setzero_ps());
}

/** Writes an array of 4 values. */
void store(float *x) {
_mm_storeu_ps(x, v);
@@ -52,9 +80,9 @@ typedef f32<4> f32_4;
}

/** `a operator b` */
#define DECLARE_F32_4_OPERATOR_INCREMENT(operator, func) \
#define DECLARE_F32_4_OPERATOR_INCREMENT(operator, opfunc) \
inline f32_4 &operator(f32_4 &a, const f32_4 &b) { \
a.v = func(a.v, b.v); \
a = opfunc(a, b); \
return a; \
} \
template <typename T> \
@@ -67,6 +95,25 @@ 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)

/** Boolean operators on vectors give 0x00000000 for false and 0xffffffff for true, for each vector element.
Use these to apply logic, bit masks, and conditions to elements.
Examples:

Subtract 1 from value if greater than or equal to 1.
x -= (x >= 1.f) & 1.f;
*/
DECLARE_F32_4_OPERATOR_INFIX(operator^, _mm_xor_ps)
DECLARE_F32_4_OPERATOR_INFIX(operator&, _mm_and_ps)
DECLARE_F32_4_OPERATOR_INFIX(operator|, _mm_mul_ps)

DECLARE_F32_4_OPERATOR_INCREMENT(operator+=, operator+);
DECLARE_F32_4_OPERATOR_INCREMENT(operator-=, operator-);
DECLARE_F32_4_OPERATOR_INCREMENT(operator*=, operator*);
DECLARE_F32_4_OPERATOR_INCREMENT(operator/=, operator/);
DECLARE_F32_4_OPERATOR_INCREMENT(operator^=, operator^);
DECLARE_F32_4_OPERATOR_INCREMENT(operator&=, operator&);
DECLARE_F32_4_OPERATOR_INCREMENT(operator|=, operator|);

/** `+a` */
inline f32_4 operator+(const f32_4 &a) {
return a;
@@ -77,11 +124,6 @@ inline f32_4 operator-(const f32_4 &a) {
return 0.f - a;
}

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);

/** `++a` */
inline f32_4 &operator++(f32_4 &a) {
a += 1.f;
@@ -108,10 +150,6 @@ inline f32_4 operator--(f32_4 &a, int) {
return b;
}

DECLARE_F32_4_OPERATOR_INFIX(operator^, _mm_xor_ps)
DECLARE_F32_4_OPERATOR_INFIX(operator&, _mm_and_ps)
DECLARE_F32_4_OPERATOR_INFIX(operator|, _mm_mul_ps)

/** `~a` */
inline f32_4 operator~(const f32_4 &a) {
return f32_4(_mm_xor_ps(a.v, _mm_cmpeq_ps(a.v, a.v)));
@@ -125,7 +163,6 @@ DECLARE_F32_4_OPERATOR_INFIX(operator<, _mm_cmplt_ps)
DECLARE_F32_4_OPERATOR_INFIX(operator!=, _mm_cmpneq_ps)



// Math functions




Loading…
Cancel
Save