OpenShot Library | OpenShotAudio 0.2.2
juce_SIMDRegister.h
1
2/** @weakgroup juce_dsp-containers
3 * @{
4 */
5/*
6 ==============================================================================
7
8 This file is part of the JUCE library.
9 Copyright (c) 2017 - ROLI Ltd.
10
11 JUCE is an open source library subject to commercial or open-source
12 licensing.
13
14 By using JUCE, you agree to the terms of both the JUCE 5 End-User License
15 Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
16 27th April 2017).
17
18 End User License Agreement: www.juce.com/juce-5-licence
19 Privacy Policy: www.juce.com/juce-5-privacy-policy
20
21 Or: You may also use this code under the terms of the GPL v3 (see
22 www.gnu.org/licenses).
23
24 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
25 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
26 DISCLAIMED.
27
28 ==============================================================================
29*/
30
31namespace juce
32{
33namespace dsp
34{
35
36#ifndef DOXYGEN
37 // This class is needed internally.
38 template <typename Scalar>
39 struct CmplxSIMDOps;
40#endif
41
42//==============================================================================
43/**
44 A wrapper around the platform's native SIMD register type.
45
46 This class is only available on SIMD machines. Use JUCE_USE_SIMD to query
47 if SIMD is available for your system.
48
49 SIMDRegister<Type> is a templated class representing the native
50 vectorized version of FloatingType. SIMDRegister supports all numerical
51 primitive types and std:complex<float> and std::complex<double> supports
52 and most operations of the corresponding primitive
53 type. Additionally, SIMDRegister can be accessed like an array to extract
54 the individual elements.
55
56 If you are using SIMDRegister as a pointer, then you must ensure that the
57 memory is sufficiently aligned for SIMD vector operations. Failing to do so
58 will result in crashes or very slow code. Use SIMDRegister::isSIMDAligned
59 to query if a pointer is sufficiently aligned for SIMD vector operations.
60
61 Note that using SIMDRegister without enabling optimizations will result
62 in code with very poor performance.
63
64 @tags{DSP}
65*/
66template <typename Type>
68{
69 //==============================================================================
70 /** The type that represents the individual constituents of the SIMD Register */
71 using ElementType = Type;
72
73 /** STL compatible value_type definition (same as ElementType). */
75
76 /** The corresponding primitive integer type, for example, this will be int32_t
77 if type is a float. */
78 using MaskType = typename SIMDInternal::MaskTypeFor<ElementType>::type;
79
80 //==============================================================================
81 // Here are some types which are needed internally
82
83 /** The native primitive type (used internally). */
84 using PrimitiveType = typename SIMDInternal::PrimitiveType<ElementType>::type;
85
86 /** The native operations for this platform and type combination (used internally) */
87 using NativeOps = SIMDNativeOps<PrimitiveType>;
88
89 /** The native type (used internally). */
90 using vSIMDType = typename NativeOps::vSIMDType;
91
92 /** The corresponding integer SIMDRegister type (used internally). */
94
95 /** The internal native type for the corresponding mask type (used internally). */
97
98 /** Wrapper for operations which need to be handled differently for complex
99 and scalar types (used internally). */
100 using CmplxOps = CmplxSIMDOps<ElementType>;
101
102 /** Type which is returned when using the subscript operator. The returned type
103 should be used just like the type ElementType. */
104 struct ElementAccess;
105
106 //==============================================================================
107 /** The size in bytes of this register. */
108 static constexpr size_t SIMDRegisterSize = sizeof (vSIMDType);
109
110 /** The number of elements that this vector can hold. */
111 static constexpr size_t SIMDNumElements = SIMDRegisterSize / sizeof (ElementType);
112
113 vSIMDType value;
114
115 /** Default constructor. */
116 inline SIMDRegister() noexcept = default;
117
118 /** Constructs an object from the native SIMD type. */
119 inline SIMDRegister (vSIMDType a) noexcept : value (a) {}
120
121 /** Constructs an object from a scalar type by broadcasting it to all elements. */
122 inline SIMDRegister (Type s) noexcept { *this = s; }
123
124 /** Destructor. */
125 inline ~SIMDRegister() noexcept = default;
126
127 //==============================================================================
128 /** Returns the number of elements in this vector. */
129 static constexpr size_t size() noexcept { return SIMDNumElements; }
130
131 //==============================================================================
132 /** Creates a new SIMDRegister from the corresponding scalar primitive.
133 The scalar is extended to all elements of the vector. */
134 inline static SIMDRegister JUCE_VECTOR_CALLTYPE expand (ElementType s) noexcept { return {CmplxOps::expand (s)}; }
135
136 /** Creates a new SIMDRegister from the internal SIMD type (for example
137 __mm128 for single-precision floating point on SSE architectures). */
138 inline static SIMDRegister JUCE_VECTOR_CALLTYPE fromNative (vSIMDType a) noexcept { return {a}; }
139
140 /** Creates a new SIMDRegister from the first SIMDNumElements of a scalar array. */
141 inline static SIMDRegister JUCE_VECTOR_CALLTYPE fromRawArray (const ElementType* a) noexcept
142 {
143 jassert (isSIMDAligned (a));
144 return {CmplxOps::load (a)};
145 }
146
147 /** Copies the elements of the SIMDRegister to a scalar array in memory. */
148 inline void JUCE_VECTOR_CALLTYPE copyToRawArray (ElementType* a) const noexcept
149 {
150 jassert (isSIMDAligned (a));
151 CmplxOps::store (value, a);
152 }
153
154 //==============================================================================
155 /** Returns the idx-th element of the receiver. Note that this does not check if idx
156 is larger than the native register size. */
157 inline ElementType JUCE_VECTOR_CALLTYPE get (size_t idx) const noexcept
158 {
159 jassert (idx < SIMDNumElements);
160 return CmplxOps::get (value, idx);
161 }
162
163 /** Sets the idx-th element of the receiver. Note that this does not check if idx
164 is larger than the native register size. */
165 inline void JUCE_VECTOR_CALLTYPE set (size_t idx, ElementType v) noexcept
166 {
167 jassert (idx < SIMDNumElements);
168 value = CmplxOps::set (value, idx, v);
169 }
170
171 //==============================================================================
172 /** Returns the idx-th element of the receiver. Note that this does not check if idx
173 is larger than the native register size. */
174 inline ElementType JUCE_VECTOR_CALLTYPE operator[] (size_t idx) const noexcept
175 {
176 return get (idx);
177 }
178
179 /** Returns the idx-th element of the receiver. Note that this does not check if idx
180 is larger than the native register size. */
181 inline ElementAccess JUCE_VECTOR_CALLTYPE operator[] (size_t idx) noexcept
182 {
183 jassert (idx < SIMDNumElements);
184 return ElementAccess (*this, idx);
185 }
186
187 //==============================================================================
188 /** Adds another SIMDRegister to the receiver. */
189 inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator+= (SIMDRegister v) noexcept { value = NativeOps::add (value, v.value); return *this; }
190
191 /** Subtracts another SIMDRegister to the receiver. */
192 inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator-= (SIMDRegister v) noexcept { value = NativeOps::sub (value, v.value); return *this; }
193
194 /** Multiplies another SIMDRegister to the receiver. */
195 inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator*= (SIMDRegister v) noexcept { value = CmplxOps::mul (value, v.value); return *this; }
196
197 //==============================================================================
198 /** Broadcasts the scalar to all elements of the receiver. */
199 inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator= (ElementType s) noexcept { value = CmplxOps::expand (s); return *this; }
200
201 /** Adds a scalar to the receiver. */
202 inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator+= (ElementType s) noexcept { value = NativeOps::add (value, CmplxOps::expand (s)); return *this; }
203
204 /** Subtracts a scalar to the receiver. */
205 inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator-= (ElementType s) noexcept { value = NativeOps::sub (value, CmplxOps::expand (s)); return *this; }
206
207 /** Multiplies a scalar to the receiver. */
208 inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator*= (ElementType s) noexcept { value = CmplxOps::mul (value, CmplxOps::expand (s)); return *this; }
209
210 //==============================================================================
211 /** Bit-and the receiver with SIMDRegister v and store the result in the receiver. */
212 inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator&= (vMaskType v) noexcept { value = NativeOps::bit_and (value, toVecType (v.value)); return *this; }
213
214 /** Bit-or the receiver with SIMDRegister v and store the result in the receiver. */
215 inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator|= (vMaskType v) noexcept { value = NativeOps::bit_or (value, toVecType (v.value)); return *this; }
216
217 /** Bit-xor the receiver with SIMDRegister v and store the result in the receiver. */
218 inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator^= (vMaskType v) noexcept { value = NativeOps::bit_xor (value, toVecType (v.value)); return *this; }
219
220 //==============================================================================
221 /** Bit-and each element of the receiver with the scalar s and store the result in the receiver.*/
222 inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator&= (MaskType s) noexcept { value = NativeOps::bit_and (value, toVecType (s)); return *this; }
223
224 /** Bit-or each element of the receiver with the scalar s and store the result in the receiver.*/
225 inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator|= (MaskType s) noexcept { value = NativeOps::bit_or (value, toVecType (s)); return *this; }
226
227 /** Bit-xor each element of the receiver with the scalar s and store the result in the receiver.*/
228 inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator^= (MaskType s) noexcept { value = NativeOps::bit_xor (value, toVecType (s)); return *this; }
229
230 //==============================================================================
231 /** Returns the sum of the receiver and v.*/
232 inline SIMDRegister JUCE_VECTOR_CALLTYPE operator+ (SIMDRegister v) const noexcept { return { NativeOps::add (value, v.value) }; }
233
234 /** Returns the difference of the receiver and v.*/
235 inline SIMDRegister JUCE_VECTOR_CALLTYPE operator- (SIMDRegister v) const noexcept { return { NativeOps::sub (value, v.value) }; }
236
237 /** Returns the product of the receiver and v.*/
238 inline SIMDRegister JUCE_VECTOR_CALLTYPE operator* (SIMDRegister v) const noexcept { return { CmplxOps::mul (value, v.value) }; }
239
240 //==============================================================================
241 /** Returns a vector where each element is the sum of the corresponding element in the receiver and the scalar s.*/
242 inline SIMDRegister JUCE_VECTOR_CALLTYPE operator+ (ElementType s) const noexcept { return { NativeOps::add (value, CmplxOps::expand (s)) }; }
243
244 /** Returns a vector where each element is the difference of the corresponding element in the receiver and the scalar s.*/
245 inline SIMDRegister JUCE_VECTOR_CALLTYPE operator- (ElementType s) const noexcept { return { NativeOps::sub (value, CmplxOps::expand (s)) }; }
246
247 /** Returns a vector where each element is the product of the corresponding element in the receiver and the scalar s.*/
248 inline SIMDRegister JUCE_VECTOR_CALLTYPE operator* (ElementType s) const noexcept { return { CmplxOps::mul (value, CmplxOps::expand (s)) }; }
249
250 //==============================================================================
251 /** Returns the bit-and of the receiver and v. */
252 inline SIMDRegister JUCE_VECTOR_CALLTYPE operator& (vMaskType v) const noexcept { return { NativeOps::bit_and (value, toVecType (v.value)) }; }
253
254 /** Returns the bit-or of the receiver and v. */
255 inline SIMDRegister JUCE_VECTOR_CALLTYPE operator| (vMaskType v) const noexcept { return { NativeOps::bit_or (value, toVecType (v.value)) }; }
256
257 /** Returns the bit-xor of the receiver and v. */
258 inline SIMDRegister JUCE_VECTOR_CALLTYPE operator^ (vMaskType v) const noexcept { return { NativeOps::bit_xor (value, toVecType (v.value)) }; }
259
260 /** Returns a vector where each element is the bit-inverted value of the corresponding element in the receiver.*/
261 inline SIMDRegister JUCE_VECTOR_CALLTYPE operator~() const noexcept { return { NativeOps::bit_not (value) }; }
262
263 //==============================================================================
264 /** Returns a vector where each element is the bit-and'd value of the corresponding element in the receiver and the scalar s.*/
265 inline SIMDRegister JUCE_VECTOR_CALLTYPE operator& (MaskType s) const noexcept { return { NativeOps::bit_and (value, toVecType (s)) }; }
266
267 /** Returns a vector where each element is the bit-or'd value of the corresponding element in the receiver and the scalar s.*/
268 inline SIMDRegister JUCE_VECTOR_CALLTYPE operator| (MaskType s) const noexcept { return { NativeOps::bit_or (value, toVecType (s)) }; }
269
270 /** Returns a vector where each element is the bit-xor'd value of the corresponding element in the receiver and the scalar s.*/
271 inline SIMDRegister JUCE_VECTOR_CALLTYPE operator^ (MaskType s) const noexcept { return { NativeOps::bit_xor (value, toVecType (s)) }; }
272
273 //==============================================================================
274 /** Returns true if all element-wise comparisons return true. */
275 inline bool JUCE_VECTOR_CALLTYPE operator== (SIMDRegister other) const noexcept { return NativeOps::allEqual (value, other.value); }
276
277 /** Returns true if any element-wise comparisons return false. */
278 inline bool JUCE_VECTOR_CALLTYPE operator!= (SIMDRegister other) const noexcept { return ! (*this == other); }
279
280 /** Returns true if all elements are equal to the scalar. */
281 inline bool JUCE_VECTOR_CALLTYPE operator== (Type s) const noexcept { return *this == SIMDRegister::expand (s); }
282
283 /** Returns true if any elements are not equal to the scalar. */
284 inline bool JUCE_VECTOR_CALLTYPE operator!= (Type s) const noexcept { return ! (*this == s); }
285
286 //==============================================================================
287 /** Returns a SIMDRegister of the corresponding integral type where each element has each bit set
288 if the corresponding element of a is equal to the corresponding element of b, or zero otherwise.
289 The result can then be used in bit operations defined above to avoid branches in vector SIMD code. */
290 static inline vMaskType JUCE_VECTOR_CALLTYPE equal (SIMDRegister a, SIMDRegister b) noexcept { return toMaskType (NativeOps::equal (a.value, b.value)); }
291
292 /** Returns a SIMDRegister of the corresponding integral type where each element has each bit set
293 if the corresponding element of a is not equal to the corresponding element of b, or zero otherwise.
294 The result can then be used in bit operations defined above to avoid branches in vector SIMD code. */
295 static inline vMaskType JUCE_VECTOR_CALLTYPE notEqual (SIMDRegister a, SIMDRegister b) noexcept { return toMaskType (NativeOps::notEqual (a.value, b.value)); }
296
297 /** Returns a SIMDRegister of the corresponding integral type where each element has each bit set
298 if the corresponding element of a is less than to the corresponding element of b, or zero otherwise.
299 The result can then be used in bit operations defined above to avoid branches in vector SIMD code. */
300 static inline vMaskType JUCE_VECTOR_CALLTYPE lessThan (SIMDRegister a, SIMDRegister b) noexcept { return toMaskType (NativeOps::greaterThan (b.value, a.value)); }
301
302 /** Returns a SIMDRegister of the corresponding integral type where each element has each bit set
303 if the corresponding element of a is than or equal to the corresponding element of b, or zero otherwise.
304 The result can then be used in bit operations defined above to avoid branches in vector SIMD code. */
305 static inline vMaskType JUCE_VECTOR_CALLTYPE lessThanOrEqual (SIMDRegister a, SIMDRegister b) noexcept { return toMaskType (NativeOps::greaterThanOrEqual (b.value, a.value)); }
306
307 /** Returns a SIMDRegister of the corresponding integral type where each element has each bit set
308 if the corresponding element of a is greater than to the corresponding element of b, or zero otherwise.
309 The result can then be used in bit operations defined above to avoid branches in vector SIMD code. */
310 static inline vMaskType JUCE_VECTOR_CALLTYPE greaterThan (SIMDRegister a, SIMDRegister b) noexcept { return toMaskType (NativeOps::greaterThan (a.value, b.value)); }
311
312 /** Returns a SIMDRegister of the corresponding integral type where each element has each bit set
313 if the corresponding element of a is greater than or equal to the corresponding element of b, or zero otherwise.
314 The result can then be used in bit operations defined above to avoid branches in vector SIMD code. */
315 static inline vMaskType JUCE_VECTOR_CALLTYPE greaterThanOrEqual (SIMDRegister a, SIMDRegister b) noexcept { return toMaskType (NativeOps::greaterThanOrEqual (a.value, b.value)); }
316
317 //==============================================================================
318 /** Returns a new vector where each element is the minimum of the corresponding element of a and b. */
319 static inline SIMDRegister JUCE_VECTOR_CALLTYPE min (SIMDRegister a, SIMDRegister b) noexcept { return { NativeOps::min (a.value, b.value) }; }
320
321 /** Returns a new vector where each element is the maximum of the corresponding element of a and b. */
322 static inline SIMDRegister JUCE_VECTOR_CALLTYPE max (SIMDRegister a, SIMDRegister b) noexcept { return { NativeOps::max (a.value, b.value) }; }
323
324 //==============================================================================
325 /** Multiplies b and c and adds the result to a. */
326 static inline SIMDRegister JUCE_VECTOR_CALLTYPE multiplyAdd (SIMDRegister a, const SIMDRegister b, SIMDRegister c) noexcept
327 {
328 return { CmplxOps::muladd (a.value, b.value, c.value) };
329 }
330
331 //==============================================================================
332 /** Returns a scalar which is the sum of all elements of the receiver. */
333 inline ElementType sum() const noexcept { return CmplxOps::sum (value); }
334
335 //==============================================================================
336 /** Truncates each element to its integer part.
337 Effectively discards the fractional part of each element. A.k.a. round to zero. */
338 static inline SIMDRegister JUCE_VECTOR_CALLTYPE truncate (SIMDRegister a) noexcept { return { NativeOps::truncate (a.value) }; }
339
340 //==============================================================================
341 /** Returns the absolute value of each element. */
342 static inline SIMDRegister JUCE_VECTOR_CALLTYPE abs (SIMDRegister a) noexcept
343 {
344 return a - (a * (expand (ElementType (2)) & lessThan (a, expand (ElementType (0)))));
345 }
346
347 //==============================================================================
348 /** Checks if the given pointer is sufficiently aligned for using SIMD operations. */
349 static inline bool isSIMDAligned (const ElementType* ptr) noexcept
350 {
351 uintptr_t bitmask = SIMDRegisterSize - 1;
352 return (reinterpret_cast<uintptr_t> (ptr) & bitmask) == 0;
353 }
354
355 /** Returns the next position in memory where isSIMDAligned returns true.
356
357 If the current position in memory is already aligned then this method
358 will simply return the pointer.
359 */
360 static inline ElementType* getNextSIMDAlignedPtr (ElementType* ptr) noexcept
361 {
362 return snapPointerToAlignment (ptr, SIMDRegisterSize);
363 }
364
365private:
366 static inline vMaskType JUCE_VECTOR_CALLTYPE toMaskType (vSIMDType a) noexcept
367 {
368 union
369 {
370 vSIMDType in;
371 vMaskSIMDType out;
372 } u;
373
374 u.in = a;
375 return vMaskType::fromNative (u.out);
376 }
377
378 static inline vSIMDType JUCE_VECTOR_CALLTYPE toVecType (vMaskSIMDType a) noexcept
379 {
380 union
381 {
382 vMaskSIMDType in;
383 vSIMDType out;
384 } u;
385
386 u.in = a;
387 return u.out;
388 }
389
390 static inline vSIMDType JUCE_VECTOR_CALLTYPE toVecType (MaskType a) noexcept
391 {
392 union
393 {
394 vMaskSIMDType in;
395 vSIMDType out;
396 } u;
397
398 u.in = CmplxSIMDOps<MaskType>::expand (a);
399 return u.out;
400 }
401};
402
403} // namespace dsp
404} // namespace juce
405
406#ifndef DOXYGEN
407 #include "juce_SIMDRegister_Impl.h"
408#endif
409
410/** @}*/
A wrapper around the platform's native SIMD register type.
static SIMDRegister JUCE_VECTOR_CALLTYPE truncate(SIMDRegister a) noexcept
Truncates each element to its integer part.
SIMDRegister &JUCE_VECTOR_CALLTYPE operator*=(SIMDRegister v) noexcept
Multiplies another SIMDRegister to the receiver.
static SIMDRegister JUCE_VECTOR_CALLTYPE expand(ElementType s) noexcept
Creates a new SIMDRegister from the corresponding scalar primitive.
typename NativeOps::vSIMDType vSIMDType
The native type (used internally).
ElementType sum() const noexcept
Returns a scalar which is the sum of all elements of the receiver.
void JUCE_VECTOR_CALLTYPE copyToRawArray(ElementType *a) const noexcept
Copies the elements of the SIMDRegister to a scalar array in memory.
SIMDRegister &JUCE_VECTOR_CALLTYPE operator=(ElementType s) noexcept
Broadcasts the scalar to all elements of the receiver.
static SIMDRegister JUCE_VECTOR_CALLTYPE max(SIMDRegister a, SIMDRegister b) noexcept
Returns a new vector where each element is the maximum of the corresponding element of a and b.
static ElementType * getNextSIMDAlignedPtr(ElementType *ptr) noexcept
Returns the next position in memory where isSIMDAligned returns true.
static vMaskType JUCE_VECTOR_CALLTYPE greaterThanOrEqual(SIMDRegister a, SIMDRegister b) noexcept
Returns a SIMDRegister of the corresponding integral type where each element has each bit set if the ...
static vMaskType JUCE_VECTOR_CALLTYPE greaterThan(SIMDRegister a, SIMDRegister b) noexcept
Returns a SIMDRegister of the corresponding integral type where each element has each bit set if the ...
bool JUCE_VECTOR_CALLTYPE operator!=(SIMDRegister other) const noexcept
Returns true if any element-wise comparisons return false.
static bool isSIMDAligned(const ElementType *ptr) noexcept
Checks if the given pointer is sufficiently aligned for using SIMD operations.
static SIMDRegister JUCE_VECTOR_CALLTYPE abs(SIMDRegister a) noexcept
Returns the absolute value of each element.
SIMDRegister JUCE_VECTOR_CALLTYPE operator|(vMaskType v) const noexcept
Returns the bit-or of the receiver and v.
SIMDRegister< MaskType > vMaskType
The corresponding integer SIMDRegister type (used internally).
static constexpr size_t SIMDRegisterSize
The size in bytes of this register.
SIMDRegister &JUCE_VECTOR_CALLTYPE operator^=(vMaskType v) noexcept
Bit-xor the receiver with SIMDRegister v and store the result in the receiver.
static vMaskType JUCE_VECTOR_CALLTYPE equal(SIMDRegister a, SIMDRegister b) noexcept
Returns a SIMDRegister of the corresponding integral type where each element has each bit set if the ...
ElementType JUCE_VECTOR_CALLTYPE get(size_t idx) const noexcept
Returns the idx-th element of the receiver.
SIMDRegister &JUCE_VECTOR_CALLTYPE operator-=(SIMDRegister v) noexcept
Subtracts another SIMDRegister to the receiver.
SIMDRegister &JUCE_VECTOR_CALLTYPE operator&=(vMaskType v) noexcept
Bit-and the receiver with SIMDRegister v and store the result in the receiver.
SIMDNativeOps< PrimitiveType > NativeOps
The native operations for this platform and type combination (used internally)
static SIMDRegister JUCE_VECTOR_CALLTYPE multiplyAdd(SIMDRegister a, const SIMDRegister b, SIMDRegister c) noexcept
Multiplies b and c and adds the result to a.
static constexpr size_t size() noexcept
Returns the number of elements in this vector.
static vMaskType JUCE_VECTOR_CALLTYPE lessThan(SIMDRegister a, SIMDRegister b) noexcept
Returns a SIMDRegister of the corresponding integral type where each element has each bit set if the ...
SIMDRegister() noexcept=default
Default constructor.
Type ElementType
The type that represents the individual constituents of the SIMD Register.
static SIMDRegister JUCE_VECTOR_CALLTYPE min(SIMDRegister a, SIMDRegister b) noexcept
Returns a new vector where each element is the minimum of the corresponding element of a and b.
static constexpr size_t SIMDNumElements
The number of elements that this vector can hold.
typename vMaskType::vSIMDType vMaskSIMDType
The internal native type for the corresponding mask type (used internally).
~SIMDRegister() noexcept=default
Destructor.
void JUCE_VECTOR_CALLTYPE set(size_t idx, ElementType v) noexcept
Sets the idx-th element of the receiver.
SIMDRegister &JUCE_VECTOR_CALLTYPE operator+=(SIMDRegister v) noexcept
Adds another SIMDRegister to the receiver.
static vMaskType JUCE_VECTOR_CALLTYPE lessThanOrEqual(SIMDRegister a, SIMDRegister b) noexcept
Returns a SIMDRegister of the corresponding integral type where each element has each bit set if the ...
SIMDRegister JUCE_VECTOR_CALLTYPE operator~() const noexcept
Returns a vector where each element is the bit-inverted value of the corresponding element in the rec...
SIMDRegister JUCE_VECTOR_CALLTYPE operator^(vMaskType v) const noexcept
Returns the bit-xor of the receiver and v.
SIMDRegister(Type s) noexcept
Constructs an object from a scalar type by broadcasting it to all elements.
static SIMDRegister JUCE_VECTOR_CALLTYPE fromNative(vSIMDType a) noexcept
Creates a new SIMDRegister from the internal SIMD type (for example __mm128 for single-precision floa...
typename SIMDInternal::MaskTypeFor< ElementType >::type MaskType
The corresponding primitive integer type, for example, this will be int32_t if type is a float.
CmplxSIMDOps< ElementType > CmplxOps
Wrapper for operations which need to be handled differently for complex and scalar types (used intern...
typename SIMDInternal::PrimitiveType< ElementType >::type PrimitiveType
The native primitive type (used internally).
SIMDRegister &JUCE_VECTOR_CALLTYPE operator|=(vMaskType v) noexcept
Bit-or the receiver with SIMDRegister v and store the result in the receiver.
SIMDRegister JUCE_VECTOR_CALLTYPE operator&(vMaskType v) const noexcept
Returns the bit-and of the receiver and v.
static SIMDRegister JUCE_VECTOR_CALLTYPE fromRawArray(const ElementType *a) noexcept
Creates a new SIMDRegister from the first SIMDNumElements of a scalar array.
SIMDRegister JUCE_VECTOR_CALLTYPE operator+(SIMDRegister v) const noexcept
Returns the sum of the receiver and v.
ElementType JUCE_VECTOR_CALLTYPE operator[](size_t idx) const noexcept
Returns the idx-th element of the receiver.
static vMaskType JUCE_VECTOR_CALLTYPE notEqual(SIMDRegister a, SIMDRegister b) noexcept
Returns a SIMDRegister of the corresponding integral type where each element has each bit set if the ...
SIMDRegister JUCE_VECTOR_CALLTYPE operator*(SIMDRegister v) const noexcept
Returns the product of the receiver and v.
SIMDRegister JUCE_VECTOR_CALLTYPE operator-(SIMDRegister v) const noexcept
Returns the difference of the receiver and v.
ElementType value_type
STL compatible value_type definition (same as ElementType).
bool JUCE_VECTOR_CALLTYPE operator==(SIMDRegister other) const noexcept
Returns true if all element-wise comparisons return true.