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 
31 namespace juce
32 {
33 namespace 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 */
66 template <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 
365 private:
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 /** @}*/
static constexpr size_t size() noexcept
Returns the number of elements in this vector.
SIMDRegister JUCE_VECTOR_CALLTYPE operator &(vMaskType v) const noexcept
Returns the bit-and of the receiver and v.
static bool isSIMDAligned(const ElementType *ptr) noexcept
Checks if the given pointer is sufficiently aligned for using SIMD operations.
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 ...
typename SIMDInternal::MaskTypeFor< ElementType >::type MaskType
The corresponding primitive integer type, for example, this will be int32_t if type is a float...
static SIMDRegister JUCE_VECTOR_CALLTYPE abs(SIMDRegister a) noexcept
Returns the absolute value of each element.
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 &JUCE_VECTOR_CALLTYPE operator &=(vMaskType v) noexcept
Bit-and the receiver with SIMDRegister v and store the result in the receiver.
typename SIMDInternal::PrimitiveType< ElementType >::type PrimitiveType
The native primitive type (used internally).
bool JUCE_VECTOR_CALLTYPE operator!=(SIMDRegister other) const noexcept
Returns true if any element-wise comparisons return false.
ElementType sum() const noexcept
Returns a scalar which is the sum of all elements of the receiver.
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...
typename vMaskType::vSIMDType vMaskSIMDType
The internal native type for the corresponding mask type (used internally).
SIMDRegister &JUCE_VECTOR_CALLTYPE operator-=(SIMDRegister v) noexcept
Subtracts another SIMDRegister to the receiver.
static SIMDRegister JUCE_VECTOR_CALLTYPE truncate(SIMDRegister a) noexcept
Truncates each element to its integer part.
SIMDRegister JUCE_VECTOR_CALLTYPE operator|(vMaskType v) const noexcept
Returns the bit-or of the receiver and v.
A wrapper around the platform&#39;s native SIMD register type.
static SIMDRegister JUCE_VECTOR_CALLTYPE multiplyAdd(SIMDRegister a, const SIMDRegister b, SIMDRegister c) noexcept
Multiplies b and c and adds the result to a.
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.
~SIMDRegister() noexcept=default
Destructor.
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() noexcept=default
Default constructor.
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...
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 ...
ElementType value_type
STL compatible value_type definition (same as ElementType).
SIMDRegister JUCE_VECTOR_CALLTYPE operator*(SIMDRegister v) const noexcept
Returns the product of the receiver and v.
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^=(vMaskType v) noexcept
Bit-xor the receiver with SIMDRegister v and store the result in the receiver.
bool JUCE_VECTOR_CALLTYPE operator==(SIMDRegister other) const noexcept
Returns true if all element-wise comparisons return true.
static SIMDRegister JUCE_VECTOR_CALLTYPE fromRawArray(const ElementType *a) noexcept
Creates a new SIMDRegister from the first SIMDNumElements of a scalar array.
static constexpr size_t SIMDNumElements
The number of elements that this vector can hold.
Type ElementType
The type that represents the individual constituents of the SIMD Register.
SIMDRegister JUCE_VECTOR_CALLTYPE operator-(SIMDRegister v) const noexcept
Returns the difference of the receiver and v.
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 ...
static ElementType * getNextSIMDAlignedPtr(ElementType *ptr) noexcept
Returns the next position in memory where isSIMDAligned returns true.
static constexpr size_t SIMDRegisterSize
The size in bytes of this register.
SIMDRegister(Type s) noexcept
Constructs an object from a scalar type by broadcasting it to all elements.
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=(ElementType s) noexcept
Broadcasts the scalar to all elements of 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 ...
ElementType JUCE_VECTOR_CALLTYPE operator[](size_t idx) const noexcept
Returns the idx-th element of the receiver.
SIMDNativeOps< PrimitiveType > NativeOps
The native operations for this platform and type combination (used internally)
typename NativeOps::vSIMDType vSIMDType
The native type (used internally).
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...
CmplxSIMDOps< ElementType > CmplxOps
Wrapper for operations which need to be handled differently for complex and scalar types (used intern...
SIMDRegister JUCE_VECTOR_CALLTYPE operator+(SIMDRegister v) const noexcept
Returns the sum of the receiver and v.
SIMDRegister JUCE_VECTOR_CALLTYPE operator^(vMaskType v) const noexcept
Returns the bit-xor of the receiver and v.
SIMDRegister &JUCE_VECTOR_CALLTYPE operator+=(SIMDRegister v) noexcept
Adds another SIMDRegister to 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...