VCV Rack API v2
Loading...
Searching...
No Matches
Vector.hpp
Go to the documentation of this file.
1#pragma once
2#include <cstring>
3#include "common.hpp"
4#include <common.hpp>
5
6
7namespace rack {
8
9
12namespace simd {
13
14
27template <typename TYPE, int SIZE>
28struct Vector;
29
30
33template <>
34struct Vector<float, 4> {
35 using type = float;
36 constexpr static int size = 4;
37
38 union {
39 __m128 v;
42 float s[4];
43 };
44
46 Vector() = default;
47
49 Vector(__m128 v) : v(v) {}
50
52 Vector(float x) {
53 v = _mm_set1_ps(x);
54 }
55
57 Vector(float x1, float x2, float x3, float x4) {
58 v = _mm_setr_ps(x1, x2, x3, x4);
59 }
60
62 static Vector zero() {
63 return Vector(_mm_setzero_ps());
64 }
65
67 static Vector mask() {
68 return Vector(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())));
69 }
70
74 static Vector load(const float* x) {
75 /*
76 My benchmarks show that _mm_loadu_ps() performs equally as fast as _mm_load_ps() when data is actually aligned.
77 This post seems to agree. https://stackoverflow.com/a/20265193/272642
78 I therefore use _mm_loadu_ps() for generality, so you can load unaligned arrays using the same function (although load aligned arrays if you can for best performance).
79 */
80 return Vector(_mm_loadu_ps(x));
81 }
82
86 void store(float* x) {
87 _mm_storeu_ps(x, v);
88 }
89
93 float& operator[](int i) {
94 return s[i];
95 }
96 const float& operator[](int i) const {
97 return s[i];
98 }
99
100 // Conversions
102 // Casts
103 static Vector cast(Vector<int32_t, 4> a);
104};
105
106
107template <>
108struct Vector<int32_t, 4> {
109 using type = int32_t;
110 constexpr static int size = 4;
111
112 union {
113 __m128i v;
114 int32_t s[4];
115 };
116
117 Vector() = default;
118 Vector(__m128i v) : v(v) {}
119 Vector(int32_t x) {
120 v = _mm_set1_epi32(x);
121 }
122 Vector(int32_t x1, int32_t x2, int32_t x3, int32_t x4) {
123 v = _mm_setr_epi32(x1, x2, x3, x4);
124 }
125 static Vector zero() {
126 return Vector(_mm_setzero_si128());
127 }
128 static Vector mask() {
129 return Vector(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()));
130 }
131 static Vector load(const int32_t* x) {
132 // HACK
133 // Use _mm_loadu_si128() because GCC doesn't support _mm_loadu_si32()
134 return Vector(_mm_loadu_si128((const __m128i*) x));
135 }
136 void store(int32_t* x) {
137 // HACK
138 // Use _mm_storeu_si128() because GCC doesn't support _mm_storeu_si32()
139 _mm_storeu_si128((__m128i*) x, v);
140 }
141 int32_t& operator[](int i) {
142 return s[i];
143 }
144 const int32_t& operator[](int i) const {
145 return s[i];
146 }
148 static Vector cast(Vector<float, 4> a);
149};
150
151
152// Conversions and casts
153
154
156 v = _mm_cvtepi32_ps(a.v);
157}
158
160 v = _mm_cvttps_epi32(a.v);
161}
162
164 return Vector(_mm_castsi128_ps(a.v));
165}
166
168 return Vector(_mm_castps_si128(a.v));
169}
170
171
172// Operator overloads
173
174
176#define DECLARE_VECTOR_OPERATOR_INFIX(t, s, operator, func) \
177 inline Vector<t, s> operator(const Vector<t, s>& a, const Vector<t, s>& b) { \
178 return Vector<t, s>(func(a.v, b.v)); \
179 }
180
182#define DECLARE_VECTOR_OPERATOR_INCREMENT(t, s, operator, opfunc) \
183 inline Vector<t, s>& operator(Vector<t, s>& a, const Vector<t, s>& b) { \
184 return a = opfunc(a, b); \
185 }
186
187DECLARE_VECTOR_OPERATOR_INFIX(float, 4, operator+, _mm_add_ps)
188DECLARE_VECTOR_OPERATOR_INFIX(int32_t, 4, operator+, _mm_add_epi32)
189
190DECLARE_VECTOR_OPERATOR_INFIX(float, 4, operator-, _mm_sub_ps)
191DECLARE_VECTOR_OPERATOR_INFIX(int32_t, 4, operator-, _mm_sub_epi32)
192
193DECLARE_VECTOR_OPERATOR_INFIX(float, 4, operator*, _mm_mul_ps)
194// DECLARE_VECTOR_OPERATOR_INFIX(int32_t, 4, operator*, NOT AVAILABLE IN SSE3)
195
196DECLARE_VECTOR_OPERATOR_INFIX(float, 4, operator/, _mm_div_ps)
197// DECLARE_VECTOR_OPERATOR_INFIX(int32_t, 4, operator/, NOT AVAILABLE IN SSE3)
198
199/* Use these to apply logic, bit masks, and conditions to elements.
200Boolean operators on vectors give 0x00000000 for false and 0xffffffff for true, for each vector element.
201
202Examples:
203
204Subtract 1 from value if greater than or equal to 1.
205
206 x -= (x >= 1.f) & 1.f;
207*/
208DECLARE_VECTOR_OPERATOR_INFIX(float, 4, operator^, _mm_xor_ps)
209DECLARE_VECTOR_OPERATOR_INFIX(int32_t, 4, operator^, _mm_xor_si128)
210
211DECLARE_VECTOR_OPERATOR_INFIX(float, 4, operator&, _mm_and_ps)
212DECLARE_VECTOR_OPERATOR_INFIX(int32_t, 4, operator&, _mm_and_si128)
213
214DECLARE_VECTOR_OPERATOR_INFIX(float, 4, operator|, _mm_or_ps)
215DECLARE_VECTOR_OPERATOR_INFIX(int32_t, 4, operator|, _mm_or_si128)
216
217DECLARE_VECTOR_OPERATOR_INCREMENT(float, 4, operator+=, operator+)
218DECLARE_VECTOR_OPERATOR_INCREMENT(int32_t, 4, operator+=, operator+)
219
220DECLARE_VECTOR_OPERATOR_INCREMENT(float, 4, operator-=, operator-)
221DECLARE_VECTOR_OPERATOR_INCREMENT(int32_t, 4, operator-=, operator-)
222
223DECLARE_VECTOR_OPERATOR_INCREMENT(float, 4, operator*=, operator*)
224// DECLARE_VECTOR_OPERATOR_INCREMENT(int32_t, 4, operator*=, NOT AVAILABLE IN SSE3)
225
226DECLARE_VECTOR_OPERATOR_INCREMENT(float, 4, operator/=, operator/)
227// DECLARE_VECTOR_OPERATOR_INCREMENT(int32_t, 4, operator/=, NOT AVAILABLE IN SSE3)
228
229DECLARE_VECTOR_OPERATOR_INCREMENT(float, 4, operator^=, operator^)
230DECLARE_VECTOR_OPERATOR_INCREMENT(int32_t, 4, operator^=, operator^)
231
232DECLARE_VECTOR_OPERATOR_INCREMENT(float, 4, operator&=, operator&)
233DECLARE_VECTOR_OPERATOR_INCREMENT(int32_t, 4, operator&=, operator&)
234
235DECLARE_VECTOR_OPERATOR_INCREMENT(float, 4, operator|=, operator|)
236DECLARE_VECTOR_OPERATOR_INCREMENT(int32_t, 4, operator|=, operator|)
237
238DECLARE_VECTOR_OPERATOR_INFIX(float, 4, operator==, _mm_cmpeq_ps)
239DECLARE_VECTOR_OPERATOR_INFIX(int32_t, 4, operator==, _mm_cmpeq_epi32)
240
241DECLARE_VECTOR_OPERATOR_INFIX(float, 4, operator>=, _mm_cmpge_ps)
242inline Vector<int32_t, 4> operator>=(const Vector<int32_t, 4>& a, const Vector<int32_t, 4>& b) {
243 return Vector<int32_t, 4>(_mm_cmpgt_epi32(a.v, b.v)) ^ Vector<int32_t, 4>::mask();
244}
245
246DECLARE_VECTOR_OPERATOR_INFIX(float, 4, operator>, _mm_cmpgt_ps)
247DECLARE_VECTOR_OPERATOR_INFIX(int32_t, 4, operator>, _mm_cmpgt_epi32)
248
249DECLARE_VECTOR_OPERATOR_INFIX(float, 4, operator<=, _mm_cmple_ps)
250inline Vector<int32_t, 4> operator<=(const Vector<int32_t, 4>& a, const Vector<int32_t, 4>& b) {
251 return Vector<int32_t, 4>(_mm_cmplt_epi32(a.v, b.v)) ^ Vector<int32_t, 4>::mask();
252}
253
254DECLARE_VECTOR_OPERATOR_INFIX(float, 4, operator<, _mm_cmplt_ps)
255DECLARE_VECTOR_OPERATOR_INFIX(int32_t, 4, operator<, _mm_cmplt_epi32)
256
257DECLARE_VECTOR_OPERATOR_INFIX(float, 4, operator!=, _mm_cmpneq_ps)
258inline Vector<int32_t, 4> operator!=(const Vector<int32_t, 4>& a, const Vector<int32_t, 4>& b) {
259 return Vector<int32_t, 4>(_mm_cmpeq_epi32(a.v, b.v)) ^ Vector<int32_t, 4>::mask();
260}
261
264 return a;
265}
267 return a;
268}
269
272 return 0.f - a;
273}
275 return 0 - a;
276}
277
280 return a += 1.f;
281}
283 return a += 1;
284}
285
288 return a -= 1.f;
289}
291 return a -= 1;
292}
293
296 Vector<float, 4> b = a;
297 ++a;
298 return b;
299}
301 Vector<int32_t, 4> b = a;
302 ++a;
303 return b;
304}
305
308 Vector<float, 4> b = a;
309 --a;
310 return b;
311}
313 Vector<int32_t, 4> b = a;
314 --a;
315 return b;
316}
317
320 return a ^ Vector<float, 4>::mask();
321}
323 return a ^ Vector<int32_t, 4>::mask();
324}
325
327inline Vector<int32_t, 4> operator<<(const Vector<int32_t, 4>& a, const int& b) {
328 return Vector<int32_t, 4>(_mm_sll_epi32(a.v, _mm_cvtsi32_si128(b)));
329}
330
332inline Vector<int32_t, 4> operator>>(const Vector<int32_t, 4>& a, const int& b) {
333 return Vector<int32_t, 4>(_mm_srl_epi32(a.v, _mm_cvtsi32_si128(b)));
334}
335
336
337// Typedefs
338
339
342
343
344} // namespace simd
345} // namespace rack
#define DECLARE_VECTOR_OPERATOR_INFIX(t, s, operator,func)
a @ b
Definition Vector.hpp:176
#define DECLARE_VECTOR_OPERATOR_INCREMENT(t, s, operator,opfunc)
a @= b
Definition Vector.hpp:182
Vector< int32_t, 4 > operator<=(const Vector< int32_t, 4 > &a, const Vector< int32_t, 4 > &b)
Definition Vector.hpp:250
Vector< int32_t, 4 > operator>>(const Vector< int32_t, 4 > &a, const int &b)
a >> b
Definition Vector.hpp:332
Vector< int32_t, 4 > operator<<(const Vector< int32_t, 4 > &a, const int &b)
a << b
Definition Vector.hpp:327
Vector< float, 4 > operator-(const Vector< float, 4 > &a)
-a
Definition Vector.hpp:271
Vector< float, 4 > & operator++(Vector< float, 4 > &a)
++a
Definition Vector.hpp:279
Vector< float, 4 > & operator--(Vector< float, 4 > &a)
--a
Definition Vector.hpp:287
Vector< float, 4 > operator~(const Vector< float, 4 > &a)
~a
Definition Vector.hpp:319
Vector< float, 4 > operator+(const Vector< float, 4 > &a)
+a
Definition Vector.hpp:263
Root namespace for the Rack API.
Definition AudioDisplay.hpp:9
Wrapper for __m128 representing an aligned vector of 4 single-precision float values.
Definition Vector.hpp:34
static Vector mask()
Returns a vector with all 1 bits.
Definition Vector.hpp:67
void store(float *x)
Writes an array of 4 values.
Definition Vector.hpp:86
Vector(float x1, float x2, float x3, float x4)
Constructs a vector from four scalars.
Definition Vector.hpp:57
float & operator[](int i)
Accessing vector elements individually is slow and defeats the purpose of vectorizing.
Definition Vector.hpp:93
Vector(__m128 v)
Constructs a vector from a native __m128 type.
Definition Vector.hpp:49
Vector(float x)
Constructs a vector with all elements set to x.
Definition Vector.hpp:52
Vector()=default
Constructs an uninitialized vector.
static Vector load(const float *x)
Reads an array of 4 values.
Definition Vector.hpp:74
const float & operator[](int i) const
Definition Vector.hpp:96
float type
Definition Vector.hpp:35
static Vector zero()
Returns a vector with all 0 bits.
Definition Vector.hpp:62
__m128 v
Definition Vector.hpp:39
Definition Vector.hpp:108
Vector(int32_t x1, int32_t x2, int32_t x3, int32_t x4)
Definition Vector.hpp:122
static Vector zero()
Definition Vector.hpp:125
Vector(__m128i v)
Definition Vector.hpp:118
__m128i v
Definition Vector.hpp:113
Vector(int32_t x)
Definition Vector.hpp:119
const int32_t & operator[](int i) const
Definition Vector.hpp:144
int32_t type
Definition Vector.hpp:109
static Vector mask()
Definition Vector.hpp:128
static Vector load(const int32_t *x)
Definition Vector.hpp:131
int32_t & operator[](int i)
Definition Vector.hpp:141
void store(int32_t *x)
Definition Vector.hpp:136
Generic class for vector types.
Definition Vector.hpp:28