33 namespace SIMDInternal
35 template <
typename Primitive>
struct MaskTypeFor {
using type = Primitive; };
36 template <>
struct MaskTypeFor <float> {
using type = uint32_t; };
37 template <>
struct MaskTypeFor <double> {
using type = uint64_t; };
38 template <>
struct MaskTypeFor <char> {
using type = uint8_t; };
39 template <>
struct MaskTypeFor <int8_t> {
using type = uint8_t; };
40 template <>
struct MaskTypeFor <int16_t> {
using type = uint16_t; };
41 template <>
struct MaskTypeFor <int32_t> {
using type = uint32_t; };
42 template <>
struct MaskTypeFor <int64_t> {
using type = uint64_t; };
43 template <>
struct MaskTypeFor <std::complex<float>> {
using type = uint32_t; };
44 template <>
struct MaskTypeFor <std::complex<double>> {
using type = uint64_t; };
46 template <
typename Primitive>
struct PrimitiveType {
using type =
typename std::remove_cv<Primitive>::type; };
47 template <
typename Primitive>
struct PrimitiveType<std::complex<Primitive>> {
using type =
typename std::remove_cv<Primitive>::type; };
49 template <
int n>
struct Log2Helper {
enum { value = Log2Helper<n/2>::value + 1 }; };
50 template <>
struct Log2Helper<1> {
enum { value = 0 }; };
59 template <
typename ScalarType,
typename vSIMDType>
62 static constexpr
size_t n =
sizeof (vSIMDType) /
sizeof (ScalarType);
63 static constexpr
size_t mask = (
sizeof (vSIMDType) /
sizeof (ScalarType)) - 1;
64 static constexpr
size_t bits = SIMDInternal::Log2Helper<(int) n>::value;
67 using MaskType =
typename SIMDInternal::MaskTypeFor<ScalarType>::type;
68 union UnionType { vSIMDType v; ScalarType s[n]; };
69 union UnionMaskType { vSIMDType v; MaskType m[n]; };
73 static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept {
return apply<ScalarAdd> (a, b); }
74 static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept {
return apply<ScalarSub> (a, b); }
75 static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept {
return apply<ScalarMul> (a, b); }
76 static forcedinline vSIMDType bit_and (vSIMDType a, vSIMDType b) noexcept {
return bitapply<ScalarAnd> (a, b); }
77 static forcedinline vSIMDType bit_or (vSIMDType a, vSIMDType b) noexcept {
return bitapply<ScalarOr > (a, b); }
78 static forcedinline vSIMDType bit_xor (vSIMDType a, vSIMDType b) noexcept {
return bitapply<ScalarXor> (a, b); }
79 static forcedinline vSIMDType bit_notand (vSIMDType a, vSIMDType b) noexcept {
return bitapply<ScalarNot> (a, b); }
81 static forcedinline vSIMDType min (vSIMDType a, vSIMDType b) noexcept {
return apply<ScalarMin> (a, b); }
82 static forcedinline vSIMDType max (vSIMDType a, vSIMDType b) noexcept {
return apply<ScalarMax> (a, b); }
83 static forcedinline vSIMDType equal (vSIMDType a, vSIMDType b) noexcept {
return cmp<ScalarEq > (a, b); }
84 static forcedinline vSIMDType notEqual (vSIMDType a, vSIMDType b) noexcept {
return cmp<ScalarNeq> (a, b); }
85 static forcedinline vSIMDType greaterThan (vSIMDType a, vSIMDType b) noexcept {
return cmp<ScalarGt > (a, b); }
86 static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept {
return cmp<ScalarGeq> (a, b); }
88 static forcedinline ScalarType
get (vSIMDType v,
size_t i) noexcept
94 static forcedinline vSIMDType
set (vSIMDType v,
size_t i, ScalarType s) noexcept
102 static forcedinline vSIMDType bit_not (vSIMDType av) noexcept
104 UnionMaskType a {av};
106 for (
size_t i = 0; i < n; ++i)
112 static forcedinline ScalarType sum (vSIMDType av) noexcept
115 auto retval =
static_cast<ScalarType
> (0);
117 for (
size_t i = 0; i < n; ++i)
123 static forcedinline vSIMDType truncate (vSIMDType av) noexcept
127 for (
size_t i = 0; i < n; ++i)
129 jassert (a.s[i] >= ScalarType (0));
130 a.s[i] = static_cast <ScalarType> (
static_cast<int> (a.s[i]));
136 static forcedinline vSIMDType multiplyAdd (vSIMDType av, vSIMDType bv, vSIMDType cv) noexcept
138 UnionType a {av}, b {bv}, c {cv};
140 for (
size_t i = 0; i < n; ++i)
141 a.s[i] += b.s[i] * c.s[i];
147 static forcedinline
bool allEqual (vSIMDType av, vSIMDType bv) noexcept
149 UnionType a {av}, b {bv};
151 for (
size_t i = 0; i < n; ++i)
152 if (a.s[i] != b.s[i])
159 static forcedinline vSIMDType cmplxmul (vSIMDType av, vSIMDType bv) noexcept
161 UnionType a {av}, b {bv}, r;
163 const int m = n >> 1;
164 for (
int i = 0; i < m; ++i)
166 std::complex<ScalarType> result
167 = std::complex<ScalarType> (a.s[i<<1], a.s[(i<<1)|1])
168 * std::complex<ScalarType> (b.s[i<<1], b.s[(i<<1)|1]);
170 r.s[i<<1] = result.real();
171 r.s[(i<<1)|1] = result.imag();
177 struct ScalarAdd {
static forcedinline ScalarType op (ScalarType a, ScalarType b) noexcept {
return a + b; } };
178 struct ScalarSub {
static forcedinline ScalarType op (ScalarType a, ScalarType b) noexcept {
return a - b; } };
179 struct ScalarMul {
static forcedinline ScalarType op (ScalarType a, ScalarType b) noexcept {
return a * b; } };
180 struct ScalarMin {
static forcedinline ScalarType op (ScalarType a, ScalarType b) noexcept {
return jmin (a, b); } };
181 struct ScalarMax {
static forcedinline ScalarType op (ScalarType a, ScalarType b) noexcept {
return jmax (a, b); } };
182 struct ScalarAnd {
static forcedinline MaskType op (MaskType a, MaskType b) noexcept {
return a & b; } };
183 struct ScalarOr {
static forcedinline MaskType op (MaskType a, MaskType b) noexcept {
return a | b; } };
184 struct ScalarXor {
static forcedinline MaskType op (MaskType a, MaskType b) noexcept {
return a ^ b; } };
185 struct ScalarNot {
static forcedinline MaskType op (MaskType a, MaskType b) noexcept {
return (~a) & b; } };
186 struct ScalarEq {
static forcedinline
bool op (ScalarType a, ScalarType b) noexcept {
return (a == b); } };
187 struct ScalarNeq {
static forcedinline
bool op (ScalarType a, ScalarType b) noexcept {
return (a != b); } };
188 struct ScalarGt {
static forcedinline
bool op (ScalarType a, ScalarType b) noexcept {
return (a > b); } };
189 struct ScalarGeq {
static forcedinline
bool op (ScalarType a, ScalarType b) noexcept {
return (a >= b); } };
192 template <
typename Op>
193 static forcedinline vSIMDType apply (vSIMDType av, vSIMDType bv) noexcept
195 UnionType a {av}, b {bv};
197 for (
size_t i = 0; i < n; ++i)
198 a.s[i] = Op::op (a.s[i], b.s[i]);
203 template <
typename Op>
204 static forcedinline vSIMDType cmp (vSIMDType av, vSIMDType bv) noexcept
206 UnionType a {av}, b {bv};
209 for (
size_t i = 0; i < n; ++i)
210 r.m[i] = Op::op (a.s[i], b.s[i]) ?
static_cast<MaskType
> (-1) : static_cast<MaskType> (0);
215 template <
typename Op>
216 static forcedinline vSIMDType bitapply (vSIMDType av, vSIMDType bv) noexcept
218 UnionMaskType a {av}, b {bv};
220 for (
size_t i = 0; i < n; ++i)
221 a.m[i] = Op::op (a.m[i], b.m[i]);
226 static forcedinline vSIMDType expand (ScalarType s) noexcept
230 for (
size_t i = 0; i < n; ++i)
236 static forcedinline vSIMDType load (
const ScalarType* a) noexcept
240 for (
size_t i = 0; i < n; ++i)
246 static forcedinline
void store (vSIMDType av, ScalarType* dest) noexcept
250 for (
size_t i = 0; i < n; ++i)
254 template <
unsigned int shuffle_
idx>
255 static forcedinline vSIMDType shuffle (vSIMDType av) noexcept
261 for (
size_t i = 0; i < n; ++i)
262 r.s[i] = a.s[(shuffle_idx >> (bits * i)) & mask];