OpenShot Audio Library | OpenShotAudio  0.6.0
juce_SIMDRegister.h
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2022 - Raw Material Software Limited
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11  Agreement and JUCE Privacy Policy.
12 
13  End User License Agreement: www.juce.com/juce-7-licence
14  Privacy Policy: www.juce.com/juce-privacy-policy
15 
16  Or: You may also use this code under the terms of the GPL v3 (see
17  www.gnu.org/licenses).
18 
19  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21  DISCLAIMED.
22 
23  ==============================================================================
24 */
25 
26 namespace juce::dsp
27 {
28 
29 #ifndef DOXYGEN
30  // This class is needed internally.
31  template <typename Scalar>
32  struct CmplxSIMDOps;
33 #endif
34 
35 //==============================================================================
59 template <typename Type>
61 {
62  //==============================================================================
64  using ElementType = Type;
65 
68 
71  using MaskType = SIMDInternal::MaskType<ElementType>;
72 
73  //==============================================================================
74  // Here are some types which are needed internally
75 
77  using PrimitiveType = typename SIMDInternal::PrimitiveType<ElementType>::type;
78 
80  using NativeOps = SIMDNativeOps<PrimitiveType>;
81 
83  using vSIMDType = typename NativeOps::vSIMDType;
84 
87 
90 
93  using CmplxOps = CmplxSIMDOps<ElementType>;
94 
97  struct ElementAccess;
98 
99  //==============================================================================
101  static constexpr size_t SIMDRegisterSize = sizeof (vSIMDType);
102 
104  static constexpr size_t SIMDNumElements = SIMDRegisterSize / sizeof (ElementType);
105 
106  vSIMDType value;
107 
109  inline SIMDRegister() noexcept = default;
110 
112  inline SIMDRegister (vSIMDType a) noexcept : value (a) {}
113 
115  inline SIMDRegister (Type s) noexcept { *this = s; }
116 
117  //==============================================================================
119  static constexpr size_t size() noexcept { return SIMDNumElements; }
120 
121  //==============================================================================
124  static SIMDRegister JUCE_VECTOR_CALLTYPE expand (ElementType s) noexcept { return {CmplxOps::expand (s)}; }
125 
128  static SIMDRegister JUCE_VECTOR_CALLTYPE fromNative (vSIMDType a) noexcept { return {a}; }
129 
131  static SIMDRegister JUCE_VECTOR_CALLTYPE fromRawArray (const ElementType* a) noexcept
132  {
133  jassert (isSIMDAligned (a));
134  return {CmplxOps::load (a)};
135  }
136 
138  inline void JUCE_VECTOR_CALLTYPE copyToRawArray (ElementType* a) const noexcept
139  {
140  jassert (isSIMDAligned (a));
141  CmplxOps::store (value, a);
142  }
143 
144  //==============================================================================
147  inline ElementType JUCE_VECTOR_CALLTYPE get (size_t idx) const noexcept
148  {
149  jassert (idx < SIMDNumElements);
150  return CmplxOps::get (value, idx);
151  }
152 
155  inline void JUCE_VECTOR_CALLTYPE set (size_t idx, ElementType v) noexcept
156  {
157  jassert (idx < SIMDNumElements);
158  value = CmplxOps::set (value, idx, v);
159  }
160 
161  //==============================================================================
164  inline ElementType JUCE_VECTOR_CALLTYPE operator[] (size_t idx) const noexcept
165  {
166  return get (idx);
167  }
168 
171  inline ElementAccess JUCE_VECTOR_CALLTYPE operator[] (size_t idx) noexcept
172  {
173  jassert (idx < SIMDNumElements);
174  return ElementAccess (*this, idx);
175  }
176 
177  //==============================================================================
179  inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator+= (SIMDRegister v) noexcept { value = NativeOps::add (value, v.value); return *this; }
180 
182  inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator-= (SIMDRegister v) noexcept { value = NativeOps::sub (value, v.value); return *this; }
183 
185  inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator*= (SIMDRegister v) noexcept { value = CmplxOps::mul (value, v.value); return *this; }
186 
187  //==============================================================================
189  inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator= (ElementType s) noexcept { value = CmplxOps::expand (s); return *this; }
190 
192  inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator+= (ElementType s) noexcept { value = NativeOps::add (value, CmplxOps::expand (s)); return *this; }
193 
195  inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator-= (ElementType s) noexcept { value = NativeOps::sub (value, CmplxOps::expand (s)); return *this; }
196 
198  inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator*= (ElementType s) noexcept { value = CmplxOps::mul (value, CmplxOps::expand (s)); return *this; }
199 
200  //==============================================================================
202  inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator&= (vMaskType v) noexcept { value = NativeOps::bit_and (value, toVecType (v.value)); return *this; }
203 
205  inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator|= (vMaskType v) noexcept { value = NativeOps::bit_or (value, toVecType (v.value)); return *this; }
206 
208  inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator^= (vMaskType v) noexcept { value = NativeOps::bit_xor (value, toVecType (v.value)); return *this; }
209 
210  //==============================================================================
212  inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator&= (MaskType s) noexcept { value = NativeOps::bit_and (value, toVecType (s)); return *this; }
213 
215  inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator|= (MaskType s) noexcept { value = NativeOps::bit_or (value, toVecType (s)); return *this; }
216 
218  inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator^= (MaskType s) noexcept { value = NativeOps::bit_xor (value, toVecType (s)); return *this; }
219 
220  //==============================================================================
222  inline SIMDRegister JUCE_VECTOR_CALLTYPE operator+ (SIMDRegister v) const noexcept { return { NativeOps::add (value, v.value) }; }
223 
225  inline SIMDRegister JUCE_VECTOR_CALLTYPE operator- (SIMDRegister v) const noexcept { return { NativeOps::sub (value, v.value) }; }
226 
228  inline SIMDRegister JUCE_VECTOR_CALLTYPE operator* (SIMDRegister v) const noexcept { return { CmplxOps::mul (value, v.value) }; }
229 
230  //==============================================================================
232  inline SIMDRegister JUCE_VECTOR_CALLTYPE operator+ (ElementType s) const noexcept { return { NativeOps::add (value, CmplxOps::expand (s)) }; }
233 
235  inline SIMDRegister JUCE_VECTOR_CALLTYPE operator- (ElementType s) const noexcept { return { NativeOps::sub (value, CmplxOps::expand (s)) }; }
236 
238  inline SIMDRegister JUCE_VECTOR_CALLTYPE operator* (ElementType s) const noexcept { return { CmplxOps::mul (value, CmplxOps::expand (s)) }; }
239 
240  //==============================================================================
242  inline SIMDRegister JUCE_VECTOR_CALLTYPE operator& (vMaskType v) const noexcept { return { NativeOps::bit_and (value, toVecType (v.value)) }; }
243 
245  inline SIMDRegister JUCE_VECTOR_CALLTYPE operator| (vMaskType v) const noexcept { return { NativeOps::bit_or (value, toVecType (v.value)) }; }
246 
248  inline SIMDRegister JUCE_VECTOR_CALLTYPE operator^ (vMaskType v) const noexcept { return { NativeOps::bit_xor (value, toVecType (v.value)) }; }
249 
251  inline SIMDRegister JUCE_VECTOR_CALLTYPE operator~() const noexcept { return { NativeOps::bit_not (value) }; }
252 
253  //==============================================================================
255  inline SIMDRegister JUCE_VECTOR_CALLTYPE operator& (MaskType s) const noexcept { return { NativeOps::bit_and (value, toVecType (s)) }; }
256 
258  inline SIMDRegister JUCE_VECTOR_CALLTYPE operator| (MaskType s) const noexcept { return { NativeOps::bit_or (value, toVecType (s)) }; }
259 
261  inline SIMDRegister JUCE_VECTOR_CALLTYPE operator^ (MaskType s) const noexcept { return { NativeOps::bit_xor (value, toVecType (s)) }; }
262 
263  //==============================================================================
265  inline bool JUCE_VECTOR_CALLTYPE operator== (SIMDRegister other) const noexcept { return NativeOps::allEqual (value, other.value); }
266 
268  inline bool JUCE_VECTOR_CALLTYPE operator!= (SIMDRegister other) const noexcept { return ! (*this == other); }
269 
271  inline bool JUCE_VECTOR_CALLTYPE operator== (Type s) const noexcept { return *this == SIMDRegister::expand (s); }
272 
274  inline bool JUCE_VECTOR_CALLTYPE operator!= (Type s) const noexcept { return ! (*this == s); }
275 
276  //==============================================================================
280  static vMaskType JUCE_VECTOR_CALLTYPE equal (SIMDRegister a, SIMDRegister b) noexcept { return toMaskType (NativeOps::equal (a.value, b.value)); }
281 
285  static vMaskType JUCE_VECTOR_CALLTYPE notEqual (SIMDRegister a, SIMDRegister b) noexcept { return toMaskType (NativeOps::notEqual (a.value, b.value)); }
286 
290  static vMaskType JUCE_VECTOR_CALLTYPE lessThan (SIMDRegister a, SIMDRegister b) noexcept { return toMaskType (NativeOps::greaterThan (b.value, a.value)); }
291 
295  static vMaskType JUCE_VECTOR_CALLTYPE lessThanOrEqual (SIMDRegister a, SIMDRegister b) noexcept { return toMaskType (NativeOps::greaterThanOrEqual (b.value, a.value)); }
296 
300  static vMaskType JUCE_VECTOR_CALLTYPE greaterThan (SIMDRegister a, SIMDRegister b) noexcept { return toMaskType (NativeOps::greaterThan (a.value, b.value)); }
301 
305  static vMaskType JUCE_VECTOR_CALLTYPE greaterThanOrEqual (SIMDRegister a, SIMDRegister b) noexcept { return toMaskType (NativeOps::greaterThanOrEqual (a.value, b.value)); }
306 
307  //==============================================================================
309  static SIMDRegister JUCE_VECTOR_CALLTYPE min (SIMDRegister a, SIMDRegister b) noexcept { return { NativeOps::min (a.value, b.value) }; }
310 
312  static SIMDRegister JUCE_VECTOR_CALLTYPE max (SIMDRegister a, SIMDRegister b) noexcept { return { NativeOps::max (a.value, b.value) }; }
313 
314  //==============================================================================
316  static SIMDRegister JUCE_VECTOR_CALLTYPE multiplyAdd (SIMDRegister a, const SIMDRegister b, SIMDRegister c) noexcept
317  {
318  return { CmplxOps::muladd (a.value, b.value, c.value) };
319  }
320 
321  //==============================================================================
323  inline ElementType sum() const noexcept { return CmplxOps::sum (value); }
324 
325  //==============================================================================
328  static SIMDRegister JUCE_VECTOR_CALLTYPE truncate (SIMDRegister a) noexcept { return { NativeOps::truncate (a.value) }; }
329 
330  //==============================================================================
332  static SIMDRegister JUCE_VECTOR_CALLTYPE abs (SIMDRegister a) noexcept
333  {
334  return a - (a * (expand (ElementType (2)) & lessThan (a, expand (ElementType (0)))));
335  }
336 
337  //==============================================================================
339  static bool isSIMDAligned (const ElementType* ptr) noexcept
340  {
341  uintptr_t bitmask = SIMDRegisterSize - 1;
342  return (reinterpret_cast<uintptr_t> (ptr) & bitmask) == 0;
343  }
344 
351  {
352  return snapPointerToAlignment (ptr, SIMDRegisterSize);
353  }
354 
355 private:
356  static vMaskType JUCE_VECTOR_CALLTYPE toMaskType (vSIMDType a) noexcept
357  {
358  union
359  {
360  vSIMDType in;
361  vMaskSIMDType out;
362  } u;
363 
364  u.in = a;
365  return vMaskType::fromNative (u.out);
366  }
367 
368  static vSIMDType JUCE_VECTOR_CALLTYPE toVecType (vMaskSIMDType a) noexcept
369  {
370  union
371  {
372  vMaskSIMDType in;
373  vSIMDType out;
374  } u;
375 
376  u.in = a;
377  return u.out;
378  }
379 
380  static vSIMDType JUCE_VECTOR_CALLTYPE toVecType (MaskType a) noexcept
381  {
382  union
383  {
384  vMaskSIMDType in;
385  vSIMDType out;
386  } u;
387 
388  u.in = CmplxSIMDOps<MaskType>::expand (a);
389  return u.out;
390  }
391 };
392 
393 } // namespace juce::dsp
static SIMDRegister JUCE_VECTOR_CALLTYPE truncate(SIMDRegister a) noexcept
static SIMDRegister JUCE_VECTOR_CALLTYPE expand(ElementType s) noexcept
typename NativeOps::vSIMDType vSIMDType
ElementType sum() const noexcept
void JUCE_VECTOR_CALLTYPE copyToRawArray(ElementType *a) const noexcept
SIMDRegister &JUCE_VECTOR_CALLTYPE operator|=(vMaskType v) noexcept
static SIMDRegister JUCE_VECTOR_CALLTYPE max(SIMDRegister a, SIMDRegister b) noexcept
static vMaskType JUCE_VECTOR_CALLTYPE greaterThanOrEqual(SIMDRegister a, SIMDRegister b) noexcept
SIMDRegister &JUCE_VECTOR_CALLTYPE operator&=(vMaskType v) noexcept
static vMaskType JUCE_VECTOR_CALLTYPE greaterThan(SIMDRegister a, SIMDRegister b) noexcept
bool JUCE_VECTOR_CALLTYPE operator!=(SIMDRegister other) const noexcept
static bool isSIMDAligned(const ElementType *ptr) noexcept
static SIMDRegister JUCE_VECTOR_CALLTYPE abs(SIMDRegister a) noexcept
SIMDRegister JUCE_VECTOR_CALLTYPE operator|(vMaskType v) const noexcept
SIMDRegister< MaskType > vMaskType
static constexpr size_t SIMDRegisterSize
static vMaskType JUCE_VECTOR_CALLTYPE equal(SIMDRegister a, SIMDRegister b) noexcept
ElementType JUCE_VECTOR_CALLTYPE get(size_t idx) const noexcept
SIMDRegister &JUCE_VECTOR_CALLTYPE operator=(ElementType s) noexcept
SIMDNativeOps< PrimitiveType > NativeOps
SIMDRegister &JUCE_VECTOR_CALLTYPE operator^=(vMaskType v) noexcept
static SIMDRegister JUCE_VECTOR_CALLTYPE multiplyAdd(SIMDRegister a, const SIMDRegister b, SIMDRegister c) noexcept
static constexpr size_t size() noexcept
static vMaskType JUCE_VECTOR_CALLTYPE lessThan(SIMDRegister a, SIMDRegister b) noexcept
SIMDRegister() noexcept=default
static SIMDRegister JUCE_VECTOR_CALLTYPE min(SIMDRegister a, SIMDRegister b) noexcept
static constexpr size_t SIMDNumElements
typename vMaskType::vSIMDType vMaskSIMDType
SIMDInternal::MaskType< ElementType > MaskType
void JUCE_VECTOR_CALLTYPE set(size_t idx, ElementType v) noexcept
static vMaskType JUCE_VECTOR_CALLTYPE lessThanOrEqual(SIMDRegister a, SIMDRegister b) noexcept
SIMDRegister JUCE_VECTOR_CALLTYPE operator~() const noexcept
SIMDRegister JUCE_VECTOR_CALLTYPE operator^(vMaskType v) const noexcept
SIMDRegister &JUCE_VECTOR_CALLTYPE operator-=(SIMDRegister v) noexcept
static ElementType * getNextSIMDAlignedPtr(ElementType *ptr) noexcept
SIMDRegister(Type s) noexcept
static SIMDRegister JUCE_VECTOR_CALLTYPE fromNative(vSIMDType a) noexcept
CmplxSIMDOps< ElementType > CmplxOps
typename SIMDInternal::PrimitiveType< ElementType >::type PrimitiveType
SIMDRegister JUCE_VECTOR_CALLTYPE operator&(vMaskType v) const noexcept
static SIMDRegister JUCE_VECTOR_CALLTYPE fromRawArray(const ElementType *a) noexcept
SIMDRegister &JUCE_VECTOR_CALLTYPE operator*=(SIMDRegister v) noexcept
SIMDRegister JUCE_VECTOR_CALLTYPE operator+(SIMDRegister v) const noexcept
ElementType JUCE_VECTOR_CALLTYPE operator[](size_t idx) const noexcept
static vMaskType JUCE_VECTOR_CALLTYPE notEqual(SIMDRegister a, SIMDRegister b) noexcept
SIMDRegister JUCE_VECTOR_CALLTYPE operator*(SIMDRegister v) const noexcept
SIMDRegister JUCE_VECTOR_CALLTYPE operator-(SIMDRegister v) const noexcept
SIMDRegister &JUCE_VECTOR_CALLTYPE operator+=(SIMDRegister v) noexcept
bool JUCE_VECTOR_CALLTYPE operator==(SIMDRegister other) const noexcept