OpenShot Library | OpenShotAudio 0.2.2
juce_SIMDRegister_Impl.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
37//==============================================================================
38template <typename Type>
40{
41 operator Type() const { return simd.get (idx); }
42 ElementAccess& operator= (Type scalar) noexcept { simd.set (idx, scalar); return *this; }
43 ElementAccess& operator= (ElementAccess& o) noexcept { return operator= ((Type) o); }
44
45private:
46 friend struct SIMDRegister;
47 ElementAccess (SIMDRegister& owner, size_t index) noexcept : simd (owner), idx (index) {}
48 SIMDRegister& simd;
49 size_t idx;
50};
51
52#ifndef DOXYGEN
53//==============================================================================
54/* This class is used internally by SIMDRegister to abstract away differences
55 in operations which are different for complex and pure floating point types. */
56
57// the pure floating-point version
58template <typename Scalar>
59struct CmplxSIMDOps
60{
61 using vSIMDType = typename SIMDNativeOps<Scalar>::vSIMDType;
62
63 static inline vSIMDType JUCE_VECTOR_CALLTYPE load (const Scalar* a) noexcept
64 {
65 return SIMDNativeOps<Scalar>::load (a);
66 }
67
68 static inline void JUCE_VECTOR_CALLTYPE store (vSIMDType value, Scalar* dest) noexcept
69 {
70 SIMDNativeOps<Scalar>::store (value, dest);
71 }
72
73 static inline vSIMDType JUCE_VECTOR_CALLTYPE expand (Scalar s) noexcept
74 {
75 return SIMDNativeOps<Scalar>::expand (s);
76 }
77
78 static inline Scalar JUCE_VECTOR_CALLTYPE get (vSIMDType v, std::size_t i) noexcept
79 {
80 return SIMDNativeOps<Scalar>::get (v, i);
81 }
82
83 static inline vSIMDType JUCE_VECTOR_CALLTYPE set (vSIMDType v, std::size_t i, Scalar s) noexcept
84 {
85 return SIMDNativeOps<Scalar>::set (v, i, s);
86 }
87
88 static inline Scalar JUCE_VECTOR_CALLTYPE sum (vSIMDType a) noexcept
89 {
90 return SIMDNativeOps<Scalar>::sum (a);
91 }
92
93 static inline vSIMDType JUCE_VECTOR_CALLTYPE mul (vSIMDType a, vSIMDType b) noexcept
94 {
95 return SIMDNativeOps<Scalar>::mul (a, b);
96 }
97
98 static inline vSIMDType JUCE_VECTOR_CALLTYPE muladd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept
99 {
100 return SIMDNativeOps<Scalar>::multiplyAdd (a, b, c);
101 }
102};
103
104// The pure complex version
105template <typename Scalar>
106struct CmplxSIMDOps<std::complex<Scalar>>
107{
108 using vSIMDType = typename SIMDNativeOps<Scalar>::vSIMDType;
109
110 static inline vSIMDType JUCE_VECTOR_CALLTYPE load (const std::complex<Scalar>* a) noexcept
111 {
112 return SIMDNativeOps<Scalar>::load (reinterpret_cast<const Scalar*> (a));
113 }
114
115 static inline void JUCE_VECTOR_CALLTYPE store (vSIMDType value, std::complex<Scalar>* dest) noexcept
116 {
117 SIMDNativeOps<Scalar>::store (value, reinterpret_cast<Scalar*> (dest));
118 }
119
120 static inline vSIMDType JUCE_VECTOR_CALLTYPE expand (std::complex<Scalar> s) noexcept
121 {
122 const int n = sizeof (vSIMDType) / sizeof (Scalar);
123
124 union
125 {
126 vSIMDType v;
127 Scalar floats[(size_t) n];
128 } u;
129
130 for (int i = 0; i < n; ++i)
131 u.floats[i] = (i & 1) == 0 ? s.real() : s.imag();
132
133 return u.v;
134 }
135
136 static inline std::complex<Scalar> JUCE_VECTOR_CALLTYPE get (vSIMDType v, std::size_t i) noexcept
137 {
138 auto j = i << 1;
139 return std::complex<Scalar> (SIMDNativeOps<Scalar>::get (v, j), SIMDNativeOps<Scalar>::get (v, j + 1));
140 }
141
142 static inline vSIMDType JUCE_VECTOR_CALLTYPE set (vSIMDType v, std::size_t i, std::complex<Scalar> s) noexcept
143 {
144 auto j = i << 1;
145 return SIMDNativeOps<Scalar>::set (SIMDNativeOps<Scalar>::set (v, j, s.real()), j + 1, s.imag());
146 }
147
148 static inline std::complex<Scalar> JUCE_VECTOR_CALLTYPE sum (vSIMDType a) noexcept
149 {
150 vSIMDType result = SIMDNativeOps<Scalar>::oddevensum (a);
151 auto* ptr = reinterpret_cast<const Scalar*> (&result);
152 return std::complex<Scalar> (ptr[0], ptr[1]);
153 }
154
155 static inline vSIMDType JUCE_VECTOR_CALLTYPE mul (vSIMDType a, vSIMDType b) noexcept
156 {
157 return SIMDNativeOps<Scalar>::cmplxmul (a, b);
158 }
159
160 static inline vSIMDType JUCE_VECTOR_CALLTYPE muladd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept
161 {
162 return SIMDNativeOps<Scalar>::add (a, SIMDNativeOps<Scalar>::cmplxmul (b, c));
163 }
164};
165#endif
166
167//==============================================================================
168 namespace util
169 {
170 template <typename Type>
171 inline void snapToZero (SIMDRegister<Type>&) noexcept {}
172 }
173
174} // namespace dsp
175
176// Extend some common used global functions to SIMDRegister types
177template <typename Type>
178inline dsp::SIMDRegister<Type> JUCE_VECTOR_CALLTYPE jmin (dsp::SIMDRegister<Type> a, dsp::SIMDRegister<Type> b) { return dsp::SIMDRegister<Type>::min (a, b); }
179template <typename Type>
180inline dsp::SIMDRegister<Type> JUCE_VECTOR_CALLTYPE jmax (dsp::SIMDRegister<Type> a, dsp::SIMDRegister<Type> b) { return dsp::SIMDRegister<Type>::max (a, b); }
181
182} // namespace juce
183
184/** @}*/
A wrapper around the platform's native SIMD register type.
typename NativeOps::vSIMDType vSIMDType
The native type (used internally).
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 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.
void JUCE_VECTOR_CALLTYPE set(size_t idx, ElementType v) noexcept
Sets the idx-th element of the receiver.