LMMS
Loading...
Searching...
No Matches
juce_FloatVectorOperations.cpp
Go to the documentation of this file.
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 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
27{
28 #define JUCE_INCREMENT_SRC_DEST dest += (16 / sizeof (*dest)); src += (16 / sizeof (*dest));
29 #define JUCE_INCREMENT_SRC1_SRC2_DEST dest += (16 / sizeof (*dest)); src1 += (16 / sizeof (*dest)); src2 += (16 / sizeof (*dest));
30 #define JUCE_INCREMENT_DEST dest += (16 / sizeof (*dest));
31
32 #if JUCE_USE_SSE_INTRINSICS
33 static bool isAligned (const void* p) noexcept
34 {
35 return (((pointer_sized_int) p) & 15) == 0;
36 }
37
38 struct BasicOps32
39 {
40 using Type = float;
41 using ParallelType = __m128;
42 using IntegerType = __m128;
43 enum { numParallel = 4 };
44
45 // Integer and parallel types are the same for SSE. On neon they have different types
46 static forcedinline IntegerType toint (ParallelType v) noexcept { return v; }
47 static forcedinline ParallelType toflt (IntegerType v) noexcept { return v; }
48
49 static forcedinline ParallelType load1 (Type v) noexcept { return _mm_load1_ps (&v); }
50 static forcedinline ParallelType loadA (const Type* v) noexcept { return _mm_load_ps (v); }
51 static forcedinline ParallelType loadU (const Type* v) noexcept { return _mm_loadu_ps (v); }
52 static forcedinline void storeA (Type* dest, ParallelType a) noexcept { _mm_store_ps (dest, a); }
53 static forcedinline void storeU (Type* dest, ParallelType a) noexcept { _mm_storeu_ps (dest, a); }
54
55 static forcedinline ParallelType add (ParallelType a, ParallelType b) noexcept { return _mm_add_ps (a, b); }
56 static forcedinline ParallelType sub (ParallelType a, ParallelType b) noexcept { return _mm_sub_ps (a, b); }
57 static forcedinline ParallelType mul (ParallelType a, ParallelType b) noexcept { return _mm_mul_ps (a, b); }
58 static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return _mm_max_ps (a, b); }
59 static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return _mm_min_ps (a, b); }
60
61 static forcedinline ParallelType bit_and (ParallelType a, ParallelType b) noexcept { return _mm_and_ps (a, b); }
62 static forcedinline ParallelType bit_not (ParallelType a, ParallelType b) noexcept { return _mm_andnot_ps (a, b); }
63 static forcedinline ParallelType bit_or (ParallelType a, ParallelType b) noexcept { return _mm_or_ps (a, b); }
64 static forcedinline ParallelType bit_xor (ParallelType a, ParallelType b) noexcept { return _mm_xor_ps (a, b); }
65
66 static forcedinline Type max (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmax (v[0], v[1], v[2], v[3]); }
67 static forcedinline Type min (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmin (v[0], v[1], v[2], v[3]); }
68 };
69
70 struct BasicOps64
71 {
72 using Type = double;
73 using ParallelType = __m128d;
74 using IntegerType = __m128d;
75 enum { numParallel = 2 };
76
77 // Integer and parallel types are the same for SSE. On neon they have different types
78 static forcedinline IntegerType toint (ParallelType v) noexcept { return v; }
79 static forcedinline ParallelType toflt (IntegerType v) noexcept { return v; }
80
81 static forcedinline ParallelType load1 (Type v) noexcept { return _mm_load1_pd (&v); }
82 static forcedinline ParallelType loadA (const Type* v) noexcept { return _mm_load_pd (v); }
83 static forcedinline ParallelType loadU (const Type* v) noexcept { return _mm_loadu_pd (v); }
84 static forcedinline void storeA (Type* dest, ParallelType a) noexcept { _mm_store_pd (dest, a); }
85 static forcedinline void storeU (Type* dest, ParallelType a) noexcept { _mm_storeu_pd (dest, a); }
86
87 static forcedinline ParallelType add (ParallelType a, ParallelType b) noexcept { return _mm_add_pd (a, b); }
88 static forcedinline ParallelType sub (ParallelType a, ParallelType b) noexcept { return _mm_sub_pd (a, b); }
89 static forcedinline ParallelType mul (ParallelType a, ParallelType b) noexcept { return _mm_mul_pd (a, b); }
90 static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return _mm_max_pd (a, b); }
91 static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return _mm_min_pd (a, b); }
92
93 static forcedinline ParallelType bit_and (ParallelType a, ParallelType b) noexcept { return _mm_and_pd (a, b); }
94 static forcedinline ParallelType bit_not (ParallelType a, ParallelType b) noexcept { return _mm_andnot_pd (a, b); }
95 static forcedinline ParallelType bit_or (ParallelType a, ParallelType b) noexcept { return _mm_or_pd (a, b); }
96 static forcedinline ParallelType bit_xor (ParallelType a, ParallelType b) noexcept { return _mm_xor_pd (a, b); }
97
98 static forcedinline Type max (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmax (v[0], v[1]); }
99 static forcedinline Type min (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmin (v[0], v[1]); }
100 };
101
102
103
104 #define JUCE_BEGIN_VEC_OP \
105 using Mode = FloatVectorHelpers::ModeType<sizeof(*dest)>::Mode; \
106 { \
107 const auto numLongOps = num / Mode::numParallel;
108
109 #define JUCE_FINISH_VEC_OP(normalOp) \
110 num &= (Mode::numParallel - 1); \
111 if (num == 0) return; \
112 } \
113 for (auto i = (decltype (num)) 0; i < num; ++i) normalOp;
114
115 #define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp) \
116 JUCE_BEGIN_VEC_OP \
117 setupOp \
118 if (FloatVectorHelpers::isAligned (dest)) JUCE_VEC_LOOP (vecOp, dummy, Mode::loadA, Mode::storeA, locals, JUCE_INCREMENT_DEST) \
119 else JUCE_VEC_LOOP (vecOp, dummy, Mode::loadU, Mode::storeU, locals, JUCE_INCREMENT_DEST) \
120 JUCE_FINISH_VEC_OP (normalOp)
121
122 #define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp) \
123 JUCE_BEGIN_VEC_OP \
124 setupOp \
125 if (FloatVectorHelpers::isAligned (dest)) \
126 { \
127 if (FloatVectorHelpers::isAligned (src)) JUCE_VEC_LOOP (vecOp, Mode::loadA, Mode::loadA, Mode::storeA, locals, increment) \
128 else JUCE_VEC_LOOP (vecOp, Mode::loadU, Mode::loadA, Mode::storeA, locals, increment) \
129 }\
130 else \
131 { \
132 if (FloatVectorHelpers::isAligned (src)) JUCE_VEC_LOOP (vecOp, Mode::loadA, Mode::loadU, Mode::storeU, locals, increment) \
133 else JUCE_VEC_LOOP (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
134 } \
135 JUCE_FINISH_VEC_OP (normalOp)
136
137 #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
138 JUCE_BEGIN_VEC_OP \
139 setupOp \
140 if (FloatVectorHelpers::isAligned (dest)) \
141 { \
142 if (FloatVectorHelpers::isAligned (src1)) \
143 { \
144 if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadA, Mode::loadA, Mode::storeA, locals, increment) \
145 else JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadA, Mode::loadU, Mode::storeA, locals, increment) \
146 } \
147 else \
148 { \
149 if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadA, Mode::storeA, locals, increment) \
150 else JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadU, Mode::storeA, locals, increment) \
151 } \
152 } \
153 else \
154 { \
155 if (FloatVectorHelpers::isAligned (src1)) \
156 { \
157 if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadA, Mode::loadA, Mode::storeU, locals, increment) \
158 else JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadA, Mode::loadU, Mode::storeU, locals, increment) \
159 } \
160 else \
161 { \
162 if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadA, Mode::storeU, locals, increment) \
163 else JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
164 } \
165 } \
166 JUCE_FINISH_VEC_OP (normalOp)
167
168 #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp) \
169 JUCE_BEGIN_VEC_OP \
170 setupOp \
171 if (FloatVectorHelpers::isAligned (dest)) \
172 { \
173 if (FloatVectorHelpers::isAligned (src1)) \
174 { \
175 if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadA, Mode::loadA, Mode::loadA, Mode::storeA, locals, increment) \
176 else JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadA, Mode::loadU, Mode::loadA, Mode::storeA, locals, increment) \
177 } \
178 else \
179 { \
180 if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadA, Mode::loadA, Mode::storeA, locals, increment) \
181 else JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadU, Mode::loadA, Mode::storeA, locals, increment) \
182 } \
183 } \
184 else \
185 { \
186 if (FloatVectorHelpers::isAligned (src1)) \
187 { \
188 if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadA, Mode::loadA, Mode::loadU, Mode::storeU, locals, increment) \
189 else JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadA, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
190 } \
191 else \
192 { \
193 if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadA, Mode::loadU, Mode::storeU, locals, increment) \
194 else JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
195 } \
196 } \
197 JUCE_FINISH_VEC_OP (normalOp)
198
199
200 //==============================================================================
201 #elif JUCE_USE_ARM_NEON
202
203 struct BasicOps32
204 {
205 using Type = float;
206 using ParallelType = float32x4_t;
207 using IntegerType = uint32x4_t;
208 union signMaskUnion { ParallelType f; IntegerType i; };
209 enum { numParallel = 4 };
210
211 static forcedinline IntegerType toint (ParallelType v) noexcept { signMaskUnion u; u.f = v; return u.i; }
212 static forcedinline ParallelType toflt (IntegerType v) noexcept { signMaskUnion u; u.i = v; return u.f; }
213
214 static forcedinline ParallelType load1 (Type v) noexcept { return vld1q_dup_f32 (&v); }
215 static forcedinline ParallelType loadA (const Type* v) noexcept { return vld1q_f32 (v); }
216 static forcedinline ParallelType loadU (const Type* v) noexcept { return vld1q_f32 (v); }
217 static forcedinline void storeA (Type* dest, ParallelType a) noexcept { vst1q_f32 (dest, a); }
218 static forcedinline void storeU (Type* dest, ParallelType a) noexcept { vst1q_f32 (dest, a); }
219
220 static forcedinline ParallelType add (ParallelType a, ParallelType b) noexcept { return vaddq_f32 (a, b); }
221 static forcedinline ParallelType sub (ParallelType a, ParallelType b) noexcept { return vsubq_f32 (a, b); }
222 static forcedinline ParallelType mul (ParallelType a, ParallelType b) noexcept { return vmulq_f32 (a, b); }
223 static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return vmaxq_f32 (a, b); }
224 static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return vminq_f32 (a, b); }
225
226 static forcedinline ParallelType bit_and (ParallelType a, ParallelType b) noexcept { return toflt (vandq_u32 (toint (a), toint (b))); }
227 static forcedinline ParallelType bit_not (ParallelType a, ParallelType b) noexcept { return toflt (vbicq_u32 (toint (a), toint (b))); }
228 static forcedinline ParallelType bit_or (ParallelType a, ParallelType b) noexcept { return toflt (vorrq_u32 (toint (a), toint (b))); }
229 static forcedinline ParallelType bit_xor (ParallelType a, ParallelType b) noexcept { return toflt (veorq_u32 (toint (a), toint (b))); }
230
231 static forcedinline Type max (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmax (v[0], v[1], v[2], v[3]); }
232 static forcedinline Type min (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmin (v[0], v[1], v[2], v[3]); }
233 };
234
235 struct BasicOps64
236 {
237 using Type = double;
238 using ParallelType = double;
239 using IntegerType = uint64;
240 union signMaskUnion { ParallelType f; IntegerType i; };
241 enum { numParallel = 1 };
242
243 static forcedinline IntegerType toint (ParallelType v) noexcept { signMaskUnion u; u.f = v; return u.i; }
244 static forcedinline ParallelType toflt (IntegerType v) noexcept { signMaskUnion u; u.i = v; return u.f; }
245
246 static forcedinline ParallelType load1 (Type v) noexcept { return v; }
247 static forcedinline ParallelType loadA (const Type* v) noexcept { return *v; }
248 static forcedinline ParallelType loadU (const Type* v) noexcept { return *v; }
249 static forcedinline void storeA (Type* dest, ParallelType a) noexcept { *dest = a; }
250 static forcedinline void storeU (Type* dest, ParallelType a) noexcept { *dest = a; }
251
252 static forcedinline ParallelType add (ParallelType a, ParallelType b) noexcept { return a + b; }
253 static forcedinline ParallelType sub (ParallelType a, ParallelType b) noexcept { return a - b; }
254 static forcedinline ParallelType mul (ParallelType a, ParallelType b) noexcept { return a * b; }
255 static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return jmax (a, b); }
256 static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return jmin (a, b); }
257
258 static forcedinline ParallelType bit_and (ParallelType a, ParallelType b) noexcept { return toflt (toint (a) & toint (b)); }
259 static forcedinline ParallelType bit_not (ParallelType a, ParallelType b) noexcept { return toflt ((~toint (a)) & toint (b)); }
260 static forcedinline ParallelType bit_or (ParallelType a, ParallelType b) noexcept { return toflt (toint (a) | toint (b)); }
261 static forcedinline ParallelType bit_xor (ParallelType a, ParallelType b) noexcept { return toflt (toint (a) ^ toint (b)); }
262
263 static forcedinline Type max (ParallelType a) noexcept { return a; }
264 static forcedinline Type min (ParallelType a) noexcept { return a; }
265 };
266
267 #define JUCE_BEGIN_VEC_OP \
268 using Mode = FloatVectorHelpers::ModeType<sizeof(*dest)>::Mode; \
269 if (Mode::numParallel > 1) \
270 { \
271 const auto numLongOps = num / Mode::numParallel;
272
273 #define JUCE_FINISH_VEC_OP(normalOp) \
274 num &= (Mode::numParallel - 1); \
275 if (num == 0) return; \
276 } \
277 for (auto i = (decltype (num)) 0; i < num; ++i) normalOp;
278
279 #define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp) \
280 JUCE_BEGIN_VEC_OP \
281 setupOp \
282 JUCE_VEC_LOOP (vecOp, dummy, Mode::loadU, Mode::storeU, locals, JUCE_INCREMENT_DEST) \
283 JUCE_FINISH_VEC_OP (normalOp)
284
285 #define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp) \
286 JUCE_BEGIN_VEC_OP \
287 setupOp \
288 JUCE_VEC_LOOP (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
289 JUCE_FINISH_VEC_OP (normalOp)
290
291 #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
292 JUCE_BEGIN_VEC_OP \
293 setupOp \
294 JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
295 JUCE_FINISH_VEC_OP (normalOp)
296
297 #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp) \
298 JUCE_BEGIN_VEC_OP \
299 setupOp \
300 JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
301 JUCE_FINISH_VEC_OP (normalOp)
302
303
304 //==============================================================================
305 #else
306 #define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp) \
307 for (auto i = (decltype (num)) 0; i < num; ++i) normalOp;
308
309 #define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp) \
310 for (auto i = (decltype (num)) 0; i < num; ++i) normalOp;
311
312 #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
313 for (auto i = (decltype (num)) 0; i < num; ++i) normalOp;
314
315 #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp) \
316 for (auto i = (decltype (num)) 0; i < num; ++i) normalOp;
317
318 #endif
319
320 //==============================================================================
321 #define JUCE_VEC_LOOP(vecOp, srcLoad, dstLoad, dstStore, locals, increment) \
322 for (auto i = (decltype (numLongOps)) 0; i < numLongOps; ++i) \
323 { \
324 locals (srcLoad, dstLoad); \
325 dstStore (dest, vecOp); \
326 increment; \
327 }
328
329 #define JUCE_VEC_LOOP_TWO_SOURCES(vecOp, src1Load, src2Load, dstStore, locals, increment) \
330 for (auto i = (decltype (numLongOps)) 0; i < numLongOps; ++i) \
331 { \
332 locals (src1Load, src2Load); \
333 dstStore (dest, vecOp); \
334 increment; \
335 }
336
337 #define JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD(vecOp, src1Load, src2Load, dstLoad, dstStore, locals, increment) \
338 for (auto i = (decltype (numLongOps)) 0; i < numLongOps; ++i) \
339 { \
340 locals (src1Load, src2Load, dstLoad); \
341 dstStore (dest, vecOp); \
342 increment; \
343 }
344
345 #define JUCE_LOAD_NONE(srcLoad, dstLoad)
346 #define JUCE_LOAD_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest);
347 #define JUCE_LOAD_SRC(srcLoad, dstLoad) const Mode::ParallelType s = srcLoad (src);
348 #define JUCE_LOAD_SRC1_SRC2(src1Load, src2Load) const Mode::ParallelType s1 = src1Load (src1), s2 = src2Load (src2);
349 #define JUCE_LOAD_SRC1_SRC2_DEST(src1Load, src2Load, dstLoad) const Mode::ParallelType d = dstLoad (dest), s1 = src1Load (src1), s2 = src2Load (src2);
350 #define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest), s = srcLoad (src);
351
352 union signMask32 { float f; uint32 i; };
353 union signMask64 { double d; uint64 i; };
354
355 #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
356 template <int typeSize> struct ModeType { using Mode = BasicOps32; };
357 template <> struct ModeType<8> { using Mode = BasicOps64; };
358
359 template <typename Mode>
360 struct MinMax
361 {
362 using Type = typename Mode::Type;
363 using ParallelType = typename Mode::ParallelType;
364
365 template <typename Size>
366 static Type findMinOrMax (const Type* src, Size num, const bool isMinimum) noexcept
367 {
368 auto numLongOps = num / Mode::numParallel;
369
370 if (numLongOps > 1)
371 {
372 ParallelType val;
373
374 #if ! JUCE_USE_ARM_NEON
375 if (isAligned (src))
376 {
377 val = Mode::loadA (src);
378
379 if (isMinimum)
380 {
381 while (--numLongOps > 0)
382 {
383 src += Mode::numParallel;
384 val = Mode::min (val, Mode::loadA (src));
385 }
386 }
387 else
388 {
389 while (--numLongOps > 0)
390 {
391 src += Mode::numParallel;
392 val = Mode::max (val, Mode::loadA (src));
393 }
394 }
395 }
396 else
397 #endif
398 {
399 val = Mode::loadU (src);
400
401 if (isMinimum)
402 {
403 while (--numLongOps > 0)
404 {
405 src += Mode::numParallel;
406 val = Mode::min (val, Mode::loadU (src));
407 }
408 }
409 else
410 {
411 while (--numLongOps > 0)
412 {
413 src += Mode::numParallel;
414 val = Mode::max (val, Mode::loadU (src));
415 }
416 }
417 }
418
419 Type result = isMinimum ? Mode::min (val)
420 : Mode::max (val);
421
422 num &= (Mode::numParallel - 1);
423 src += Mode::numParallel;
424
425 for (auto i = (decltype (num)) 0; i < num; ++i)
426 result = isMinimum ? jmin (result, src[i])
427 : jmax (result, src[i]);
428
429 return result;
430 }
431
432 if (num <= 0)
433 return 0;
434
435 return isMinimum ? *std::min_element (src, src + num)
436 : *std::max_element (src, src + num);
437 }
438
439 template <typename Size>
440 static Range<Type> findMinAndMax (const Type* src, Size num) noexcept
441 {
442 auto numLongOps = num / Mode::numParallel;
443
444 if (numLongOps > 1)
445 {
446 ParallelType mn, mx;
447
448 #if ! JUCE_USE_ARM_NEON
449 if (isAligned (src))
450 {
451 mn = Mode::loadA (src);
452 mx = mn;
453
454 while (--numLongOps > 0)
455 {
456 src += Mode::numParallel;
457 const ParallelType v = Mode::loadA (src);
458 mn = Mode::min (mn, v);
459 mx = Mode::max (mx, v);
460 }
461 }
462 else
463 #endif
464 {
465 mn = Mode::loadU (src);
466 mx = mn;
467
468 while (--numLongOps > 0)
469 {
470 src += Mode::numParallel;
471 const ParallelType v = Mode::loadU (src);
472 mn = Mode::min (mn, v);
473 mx = Mode::max (mx, v);
474 }
475 }
476
477 Range<Type> result (Mode::min (mn),
478 Mode::max (mx));
479
480 num &= (Mode::numParallel - 1);
481 src += Mode::numParallel;
482
483 for (auto i = (decltype (num)) 0; i < num; ++i)
484 result = result.getUnionWith (src[i]);
485
486 return result;
487 }
488
489 return Range<Type>::findMinAndMax (src, num);
490 }
491 };
492 #endif
493
494//==============================================================================
495namespace
496{
497 template <typename Size>
498 void clear (float* dest, Size num) noexcept
499 {
500 #if JUCE_USE_VDSP_FRAMEWORK
501 vDSP_vclr (dest, 1, (vDSP_Length) num);
502 #else
503 zeromem (dest, (size_t) num * sizeof (float));
504 #endif
505 }
506
507 template <typename Size>
508 void clear (double* dest, Size num) noexcept
509 {
510 #if JUCE_USE_VDSP_FRAMEWORK
511 vDSP_vclrD (dest, 1, (vDSP_Length) num);
512 #else
513 zeromem (dest, (size_t) num * sizeof (double));
514 #endif
515 }
516
517 template <typename Size>
518 void fill (float* dest, float valueToFill, Size num) noexcept
519 {
520 #if JUCE_USE_VDSP_FRAMEWORK
521 vDSP_vfill (&valueToFill, dest, 1, (vDSP_Length) num);
522 #else
523 JUCE_PERFORM_VEC_OP_DEST (dest[i] = valueToFill,
524 val,
526 const Mode::ParallelType val = Mode::load1 (valueToFill);)
527 #endif
528 }
529
530 template <typename Size>
531 void fill (double* dest, double valueToFill, Size num) noexcept
532 {
533 #if JUCE_USE_VDSP_FRAMEWORK
534 vDSP_vfillD (&valueToFill, dest, 1, (vDSP_Length) num);
535 #else
536 JUCE_PERFORM_VEC_OP_DEST (dest[i] = valueToFill,
537 val,
539 const Mode::ParallelType val = Mode::load1 (valueToFill);)
540 #endif
541 }
542
543 template <typename Size>
544 void copyWithMultiply (float* dest, const float* src, float multiplier, Size num) noexcept
545 {
546 #if JUCE_USE_VDSP_FRAMEWORK
547 vDSP_vsmul (src, 1, &multiplier, dest, 1, (vDSP_Length) num);
548 #else
549 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier,
550 Mode::mul (mult, s),
553 const Mode::ParallelType mult = Mode::load1 (multiplier);)
554 #endif
555 }
556
557 template <typename Size>
558 void copyWithMultiply (double* dest, const double* src, double multiplier, Size num) noexcept
559 {
560 #if JUCE_USE_VDSP_FRAMEWORK
561 vDSP_vsmulD (src, 1, &multiplier, dest, 1, (vDSP_Length) num);
562 #else
563 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier,
564 Mode::mul (mult, s),
567 const Mode::ParallelType mult = Mode::load1 (multiplier);)
568 #endif
569 }
570
571 template <typename Size>
572 void add (float* dest, float amount, Size num) noexcept
573 {
574 #if JUCE_USE_VDSP_FRAMEWORK
575 vDSP_vsadd (dest, 1, &amount, dest, 1, (vDSP_Length) num);
576 #else
577 JUCE_PERFORM_VEC_OP_DEST (dest[i] += amount,
578 Mode::add (d, amountToAdd),
580 const Mode::ParallelType amountToAdd = Mode::load1 (amount);)
581 #endif
582 }
583
584 template <typename Size>
585 void add (double* dest, double amount, Size num) noexcept
586 {
587 JUCE_PERFORM_VEC_OP_DEST (dest[i] += amount,
588 Mode::add (d, amountToAdd),
590 const Mode::ParallelType amountToAdd = Mode::load1 (amount);)
591 }
592
593 template <typename Size>
594 void add (float* dest, const float* src, float amount, Size num) noexcept
595 {
596 #if JUCE_USE_VDSP_FRAMEWORK
597 vDSP_vsadd (src, 1, &amount, dest, 1, (vDSP_Length) num);
598 #else
599 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] + amount,
600 Mode::add (am, s),
603 const Mode::ParallelType am = Mode::load1 (amount);)
604 #endif
605 }
606
607 template <typename Size>
608 void add (double* dest, const double* src, double amount, Size num) noexcept
609 {
610 #if JUCE_USE_VDSP_FRAMEWORK
611 vDSP_vsaddD (src, 1, &amount, dest, 1, (vDSP_Length) num);
612 #else
613 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] + amount,
614 Mode::add (am, s),
617 const Mode::ParallelType am = Mode::load1 (amount);)
618 #endif
619 }
620
621 template <typename Size>
622 void add (float* dest, const float* src, Size num) noexcept
623 {
624 #if JUCE_USE_VDSP_FRAMEWORK
625 vDSP_vadd (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
626 #else
627 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i],
628 Mode::add (d, s),
631 #endif
632 }
633
634 template <typename Size>
635 void add (double* dest, const double* src, Size num) noexcept
636 {
637 #if JUCE_USE_VDSP_FRAMEWORK
638 vDSP_vaddD (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
639 #else
640 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i],
641 Mode::add (d, s),
644 #endif
645 }
646
647 template <typename Size>
648 void add (float* dest, const float* src1, const float* src2, Size num) noexcept
649 {
650 #if JUCE_USE_VDSP_FRAMEWORK
651 vDSP_vadd (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
652 #else
653 JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] + src2[i],
654 Mode::add (s1, s2),
657 #endif
658 }
659
660 template <typename Size>
661 void add (double* dest, const double* src1, const double* src2, Size num) noexcept
662 {
663 #if JUCE_USE_VDSP_FRAMEWORK
664 vDSP_vaddD (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
665 #else
666 JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] + src2[i],
667 Mode::add (s1, s2),
670 #endif
671 }
672
673 template <typename Size>
674 void subtract (float* dest, const float* src, Size num) noexcept
675 {
676 #if JUCE_USE_VDSP_FRAMEWORK
677 vDSP_vsub (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
678 #else
679 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i],
680 Mode::sub (d, s),
683 #endif
684 }
685
686 template <typename Size>
687 void subtract (double* dest, const double* src, Size num) noexcept
688 {
689 #if JUCE_USE_VDSP_FRAMEWORK
690 vDSP_vsubD (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
691 #else
692 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i],
693 Mode::sub (d, s),
696 #endif
697 }
698
699 template <typename Size>
700 void subtract (float* dest, const float* src1, const float* src2, Size num) noexcept
701 {
702 #if JUCE_USE_VDSP_FRAMEWORK
703 vDSP_vsub (src2, 1, src1, 1, dest, 1, (vDSP_Length) num);
704 #else
705 JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] - src2[i],
706 Mode::sub (s1, s2),
709 #endif
710 }
711
712 template <typename Size>
713 void subtract (double* dest, const double* src1, const double* src2, Size num) noexcept
714 {
715 #if JUCE_USE_VDSP_FRAMEWORK
716 vDSP_vsubD (src2, 1, src1, 1, dest, 1, (vDSP_Length) num);
717 #else
718 JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] - src2[i],
719 Mode::sub (s1, s2),
722 #endif
723 }
724
725 template <typename Size>
726 void addWithMultiply (float* dest, const float* src, float multiplier, Size num) noexcept
727 {
728 #if JUCE_USE_VDSP_FRAMEWORK
729 vDSP_vsma (src, 1, &multiplier, dest, 1, dest, 1, (vDSP_Length) num);
730 #else
731 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i] * multiplier,
732 Mode::add (d, Mode::mul (mult, s)),
735 const Mode::ParallelType mult = Mode::load1 (multiplier);)
736 #endif
737 }
738
739 template <typename Size>
740 void addWithMultiply (double* dest, const double* src, double multiplier, Size num) noexcept
741 {
742 #if JUCE_USE_VDSP_FRAMEWORK
743 vDSP_vsmaD (src, 1, &multiplier, dest, 1, dest, 1, (vDSP_Length) num);
744 #else
745 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i] * multiplier,
746 Mode::add (d, Mode::mul (mult, s)),
749 const Mode::ParallelType mult = Mode::load1 (multiplier);)
750 #endif
751 }
752
753 template <typename Size>
754 void addWithMultiply (float* dest, const float* src1, const float* src2, Size num) noexcept
755 {
756 #if JUCE_USE_VDSP_FRAMEWORK
757 vDSP_vma ((float*) src1, 1, (float*) src2, 1, dest, 1, dest, 1, (vDSP_Length) num);
758 #else
759 JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST (dest[i] += src1[i] * src2[i],
760 Mode::add (d, Mode::mul (s1, s2)),
763 #endif
764 }
765
766 template <typename Size>
767 void addWithMultiply (double* dest, const double* src1, const double* src2, Size num) noexcept
768 {
769 #if JUCE_USE_VDSP_FRAMEWORK
770 vDSP_vmaD ((double*) src1, 1, (double*) src2, 1, dest, 1, dest, 1, (vDSP_Length) num);
771 #else
772 JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST (dest[i] += src1[i] * src2[i],
773 Mode::add (d, Mode::mul (s1, s2)),
776 #endif
777 }
778
779 template <typename Size>
780 void subtractWithMultiply (float* dest, const float* src, float multiplier, Size num) noexcept
781 {
782 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i] * multiplier,
783 Mode::sub (d, Mode::mul (mult, s)),
786 const Mode::ParallelType mult = Mode::load1 (multiplier);)
787 }
788
789 template <typename Size>
790 void subtractWithMultiply (double* dest, const double* src, double multiplier, Size num) noexcept
791 {
792 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i] * multiplier,
793 Mode::sub (d, Mode::mul (mult, s)),
796 const Mode::ParallelType mult = Mode::load1 (multiplier);)
797 }
798
799 template <typename Size>
800 void subtractWithMultiply (float* dest, const float* src1, const float* src2, Size num) noexcept
801 {
802 JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST (dest[i] -= src1[i] * src2[i],
803 Mode::sub (d, Mode::mul (s1, s2)),
806 }
807
808 template <typename Size>
809 void subtractWithMultiply (double* dest, const double* src1, const double* src2, Size num) noexcept
810 {
811 JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST (dest[i] -= src1[i] * src2[i],
812 Mode::sub (d, Mode::mul (s1, s2)),
815 }
816
817 template <typename Size>
818 void multiply (float* dest, const float* src, Size num) noexcept
819 {
820 #if JUCE_USE_VDSP_FRAMEWORK
821 vDSP_vmul (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
822 #else
823 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] *= src[i],
824 Mode::mul (d, s),
827 #endif
828 }
829
830 template <typename Size>
831 void multiply (double* dest, const double* src, Size num) noexcept
832 {
833 #if JUCE_USE_VDSP_FRAMEWORK
834 vDSP_vmulD (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
835 #else
836 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] *= src[i],
837 Mode::mul (d, s),
840 #endif
841 }
842
843 template <typename Size>
844 void multiply (float* dest, const float* src1, const float* src2, Size num) noexcept
845 {
846 #if JUCE_USE_VDSP_FRAMEWORK
847 vDSP_vmul (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
848 #else
849 JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] * src2[i],
850 Mode::mul (s1, s2),
853 #endif
854 }
855
856 template <typename Size>
857 void multiply (double* dest, const double* src1, const double* src2, Size num) noexcept
858 {
859 #if JUCE_USE_VDSP_FRAMEWORK
860 vDSP_vmulD (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
861 #else
862 JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] * src2[i],
863 Mode::mul (s1, s2),
866 #endif
867 }
868
869 template <typename Size>
870 void multiply (float* dest, float multiplier, Size num) noexcept
871 {
872 #if JUCE_USE_VDSP_FRAMEWORK
873 vDSP_vsmul (dest, 1, &multiplier, dest, 1, (vDSP_Length) num);
874 #else
875 JUCE_PERFORM_VEC_OP_DEST (dest[i] *= multiplier,
876 Mode::mul (d, mult),
878 const Mode::ParallelType mult = Mode::load1 (multiplier);)
879 #endif
880 }
881
882 template <typename Size>
883 void multiply (double* dest, double multiplier, Size num) noexcept
884 {
885 #if JUCE_USE_VDSP_FRAMEWORK
886 vDSP_vsmulD (dest, 1, &multiplier, dest, 1, (vDSP_Length) num);
887 #else
888 JUCE_PERFORM_VEC_OP_DEST (dest[i] *= multiplier,
889 Mode::mul (d, mult),
891 const Mode::ParallelType mult = Mode::load1 (multiplier);)
892 #endif
893 }
894
895 template <typename Size>
896 void multiply (float* dest, const float* src, float multiplier, Size num) noexcept
897 {
898 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier,
899 Mode::mul (mult, s),
902 const Mode::ParallelType mult = Mode::load1 (multiplier);)
903 }
904
905 template <typename Size>
906 void multiply (double* dest, const double* src, double multiplier, Size num) noexcept
907 {
908 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier,
909 Mode::mul (mult, s),
912 const Mode::ParallelType mult = Mode::load1 (multiplier);)
913 }
914
915 template <typename Size>
916 void negate (float* dest, const float* src, Size num) noexcept
917 {
918 #if JUCE_USE_VDSP_FRAMEWORK
919 vDSP_vneg ((float*) src, 1, dest, 1, (vDSP_Length) num);
920 #else
921 copyWithMultiply (dest, src, -1.0f, num);
922 #endif
923 }
924
925 template <typename Size>
926 void negate (double* dest, const double* src, Size num) noexcept
927 {
928 #if JUCE_USE_VDSP_FRAMEWORK
929 vDSP_vnegD ((double*) src, 1, dest, 1, (vDSP_Length) num);
930 #else
931 copyWithMultiply (dest, src, -1.0f, num);
932 #endif
933 }
934
935 template <typename Size>
936 void abs (float* dest, const float* src, Size num) noexcept
937 {
938 #if JUCE_USE_VDSP_FRAMEWORK
939 vDSP_vabs ((float*) src, 1, dest, 1, (vDSP_Length) num);
940 #else
941 FloatVectorHelpers::signMask32 signMask;
942 signMask.i = 0x7fffffffUL;
943 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = std::abs (src[i]),
944 Mode::bit_and (s, mask),
947 const Mode::ParallelType mask = Mode::load1 (signMask.f);)
948
949 ignoreUnused (signMask);
950 #endif
951 }
952
953 template <typename Size>
954 void abs (double* dest, const double* src, Size num) noexcept
955 {
956 #if JUCE_USE_VDSP_FRAMEWORK
957 vDSP_vabsD ((double*) src, 1, dest, 1, (vDSP_Length) num);
958 #else
959 FloatVectorHelpers::signMask64 signMask;
960 signMask.i = 0x7fffffffffffffffULL;
961
962 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = std::abs (src[i]),
963 Mode::bit_and (s, mask),
966 const Mode::ParallelType mask = Mode::load1 (signMask.d);)
967
968 ignoreUnused (signMask);
969 #endif
970 }
971
972 template <typename Size>
973 void min (float* dest, const float* src, float comp, Size num) noexcept
974 {
975 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmin (src[i], comp),
976 Mode::min (s, cmp),
979 const Mode::ParallelType cmp = Mode::load1 (comp);)
980 }
981
982 template <typename Size>
983 void min (double* dest, const double* src, double comp, Size num) noexcept
984 {
985 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmin (src[i], comp),
986 Mode::min (s, cmp),
989 const Mode::ParallelType cmp = Mode::load1 (comp);)
990 }
991
992 template <typename Size>
993 void min (float* dest, const float* src1, const float* src2, Size num) noexcept
994 {
995 #if JUCE_USE_VDSP_FRAMEWORK
996 vDSP_vmin ((float*) src1, 1, (float*) src2, 1, dest, 1, (vDSP_Length) num);
997 #else
998 JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmin (src1[i], src2[i]),
999 Mode::min (s1, s2),
1002 #endif
1003 }
1004
1005 template <typename Size>
1006 void min (double* dest, const double* src1, const double* src2, Size num) noexcept
1007 {
1008 #if JUCE_USE_VDSP_FRAMEWORK
1009 vDSP_vminD ((double*) src1, 1, (double*) src2, 1, dest, 1, (vDSP_Length) num);
1010 #else
1011 JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmin (src1[i], src2[i]),
1012 Mode::min (s1, s2),
1015 #endif
1016 }
1017
1018 template <typename Size>
1019 void max (float* dest, const float* src, float comp, Size num) noexcept
1020 {
1021 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (src[i], comp),
1022 Mode::max (s, cmp),
1025 const Mode::ParallelType cmp = Mode::load1 (comp);)
1026 }
1027
1028 template <typename Size>
1029 void max (double* dest, const double* src, double comp, Size num) noexcept
1030 {
1031 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (src[i], comp),
1032 Mode::max (s, cmp),
1035 const Mode::ParallelType cmp = Mode::load1 (comp);)
1036 }
1037
1038 template <typename Size>
1039 void max (float* dest, const float* src1, const float* src2, Size num) noexcept
1040 {
1041 #if JUCE_USE_VDSP_FRAMEWORK
1042 vDSP_vmax ((float*) src1, 1, (float*) src2, 1, dest, 1, (vDSP_Length) num);
1043 #else
1044 JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmax (src1[i], src2[i]),
1045 Mode::max (s1, s2),
1048 #endif
1049 }
1050
1051 template <typename Size>
1052 void max (double* dest, const double* src1, const double* src2, Size num) noexcept
1053 {
1054 #if JUCE_USE_VDSP_FRAMEWORK
1055 vDSP_vmaxD ((double*) src1, 1, (double*) src2, 1, dest, 1, (vDSP_Length) num);
1056 #else
1057 JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmax (src1[i], src2[i]),
1058 Mode::max (s1, s2),
1061 #endif
1062 }
1063
1064 template <typename Size>
1065 void clip (float* dest, const float* src, float low, float high, Size num) noexcept
1066 {
1067 jassert (high >= low);
1068
1069 #if JUCE_USE_VDSP_FRAMEWORK
1070 vDSP_vclip ((float*) src, 1, &low, &high, dest, 1, (vDSP_Length) num);
1071 #else
1072 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (jmin (src[i], high), low),
1073 Mode::max (Mode::min (s, hi), lo),
1076 const Mode::ParallelType lo = Mode::load1 (low);
1077 const Mode::ParallelType hi = Mode::load1 (high);)
1078 #endif
1079 }
1080
1081 template <typename Size>
1082 void clip (double* dest, const double* src, double low, double high, Size num) noexcept
1083 {
1084 jassert (high >= low);
1085
1086 #if JUCE_USE_VDSP_FRAMEWORK
1087 vDSP_vclipD ((double*) src, 1, &low, &high, dest, 1, (vDSP_Length) num);
1088 #else
1089 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (jmin (src[i], high), low),
1090 Mode::max (Mode::min (s, hi), lo),
1093 const Mode::ParallelType lo = Mode::load1 (low);
1094 const Mode::ParallelType hi = Mode::load1 (high);)
1095 #endif
1096 }
1097
1098 template <typename Size>
1099 Range<float> findMinAndMax (const float* src, Size num) noexcept
1100 {
1101 #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
1102 return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps32>::findMinAndMax (src, num);
1103 #else
1104 return Range<float>::findMinAndMax (src, num);
1105 #endif
1106 }
1107
1108 template <typename Size>
1109 Range<double> findMinAndMax (const double* src, Size num) noexcept
1110 {
1111 #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
1112 return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps64>::findMinAndMax (src, num);
1113 #else
1114 return Range<double>::findMinAndMax (src, num);
1115 #endif
1116 }
1117
1118 template <typename Size>
1119 float findMinimum (const float* src, Size num) noexcept
1120 {
1121 #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
1122 return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps32>::findMinOrMax (src, num, true);
1123 #else
1124 return juce::findMinimum (src, num);
1125 #endif
1126 }
1127
1128 template <typename Size>
1129 double findMinimum (const double* src, Size num) noexcept
1130 {
1131 #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
1132 return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps64>::findMinOrMax (src, num, true);
1133 #else
1134 return juce::findMinimum (src, num);
1135 #endif
1136 }
1137
1138 template <typename Size>
1139 float findMaximum (const float* src, Size num) noexcept
1140 {
1141 #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
1142 return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps32>::findMinOrMax (src, num, false);
1143 #else
1144 return juce::findMaximum (src, num);
1145 #endif
1146 }
1147
1148 template <typename Size>
1149 double findMaximum (const double* src, Size num) noexcept
1150 {
1151 #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
1152 return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps64>::findMinOrMax (src, num, false);
1153 #else
1154 return juce::findMaximum (src, num);
1155 #endif
1156 }
1157
1158 template <typename Size>
1159 void convertFixedToFloat (float* dest, const int* src, float multiplier, Size num) noexcept
1160 {
1161 #if JUCE_USE_ARM_NEON
1162 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = (float) src[i] * multiplier,
1163 vmulq_n_f32 (vcvtq_f32_s32 (vld1q_s32 (src)), multiplier),
1166 #else
1167 JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = (float) src[i] * multiplier,
1168 Mode::mul (mult, _mm_cvtepi32_ps (_mm_loadu_si128 (reinterpret_cast<const __m128i*> (src)))),
1171 const Mode::ParallelType mult = Mode::load1 (multiplier);)
1172 #endif
1173 }
1174
1175} // namespace
1176} // namespace FloatVectorHelpers
1177
1178//==============================================================================
1179template <typename FloatType, typename CountType>
1181 CountType numValues) noexcept
1182{
1183 FloatVectorHelpers::clear (dest, numValues);
1184}
1185
1186template <typename FloatType, typename CountType>
1188 FloatType valueToFill,
1189 CountType numValues) noexcept
1190{
1191 FloatVectorHelpers::fill (dest, valueToFill, numValues);
1192}
1193
1194template <typename FloatType, typename CountType>
1196 const FloatType* src,
1197 CountType numValues) noexcept
1198{
1199 memcpy (dest, src, (size_t) numValues * sizeof (FloatType));
1200}
1201
1202template <typename FloatType, typename CountType>
1204 const FloatType* src,
1205 FloatType multiplier,
1206 CountType numValues) noexcept
1207{
1208 FloatVectorHelpers::copyWithMultiply (dest, src, multiplier, numValues);
1209}
1210
1211template <typename FloatType, typename CountType>
1213 FloatType amountToAdd,
1214 CountType numValues) noexcept
1215{
1216 FloatVectorHelpers::add (dest, amountToAdd, numValues);
1217}
1218
1219template <typename FloatType, typename CountType>
1221 const FloatType* src,
1222 FloatType amount,
1223 CountType numValues) noexcept
1224{
1225 FloatVectorHelpers::add (dest, src, amount, numValues);
1226}
1227
1228template <typename FloatType, typename CountType>
1230 const FloatType* src,
1231 CountType numValues) noexcept
1232{
1233 FloatVectorHelpers::add (dest, src, numValues);
1234}
1235
1236template <typename FloatType, typename CountType>
1238 const FloatType* src1,
1239 const FloatType* src2,
1240 CountType num) noexcept
1241{
1242 FloatVectorHelpers::add (dest, src1, src2, num);
1243}
1244
1245template <typename FloatType, typename CountType>
1247 const FloatType* src,
1248 CountType numValues) noexcept
1249{
1250 FloatVectorHelpers::subtract (dest, src, numValues);
1251}
1252
1253template <typename FloatType, typename CountType>
1255 const FloatType* src1,
1256 const FloatType* src2,
1257 CountType num) noexcept
1258{
1259 FloatVectorHelpers::subtract (dest, src1, src2, num);
1260}
1261
1262template <typename FloatType, typename CountType>
1264 const FloatType* src,
1265 FloatType multiplier,
1266 CountType numValues) noexcept
1267{
1268 FloatVectorHelpers::addWithMultiply (dest, src, multiplier, numValues);
1269}
1270
1271template <typename FloatType, typename CountType>
1273 const FloatType* src1,
1274 const FloatType* src2,
1275 CountType num) noexcept
1276{
1277 FloatVectorHelpers::addWithMultiply (dest, src1, src2, num);
1278}
1279
1280template <typename FloatType, typename CountType>
1282 const FloatType* src,
1283 FloatType multiplier,
1284 CountType numValues) noexcept
1285{
1286 FloatVectorHelpers::subtractWithMultiply (dest, src, multiplier, numValues);
1287}
1288
1289template <typename FloatType, typename CountType>
1291 const FloatType* src1,
1292 const FloatType* src2,
1293 CountType num) noexcept
1294{
1295 FloatVectorHelpers::subtractWithMultiply (dest, src1, src2, num);
1296}
1297
1298template <typename FloatType, typename CountType>
1300 const FloatType* src,
1301 CountType numValues) noexcept
1302{
1303 FloatVectorHelpers::multiply (dest, src, numValues);
1304}
1305
1306template <typename FloatType, typename CountType>
1308 const FloatType* src1,
1309 const FloatType* src2,
1310 CountType numValues) noexcept
1311{
1312 FloatVectorHelpers::multiply (dest, src1, src2, numValues);
1313}
1314
1315template <typename FloatType, typename CountType>
1317 FloatType multiplier,
1318 CountType numValues) noexcept
1319{
1320 FloatVectorHelpers::multiply (dest, multiplier, numValues);
1321}
1322
1323template <typename FloatType, typename CountType>
1325 const FloatType* src,
1326 FloatType multiplier,
1327 CountType num) noexcept
1328{
1329 FloatVectorHelpers::multiply (dest, src, multiplier, num);
1330}
1331
1332template <typename FloatType, typename CountType>
1334 const FloatType* src,
1335 CountType numValues) noexcept
1336{
1337 FloatVectorHelpers::negate (dest, src, numValues);
1338}
1339
1340template <typename FloatType, typename CountType>
1342 const FloatType* src,
1343 CountType numValues) noexcept
1344{
1345 FloatVectorHelpers::abs (dest, src, numValues);
1346}
1347
1348template <typename FloatType, typename CountType>
1350 const FloatType* src,
1351 FloatType comp,
1352 CountType num) noexcept
1353{
1354 FloatVectorHelpers::min (dest, src, comp, num);
1355}
1356
1357template <typename FloatType, typename CountType>
1359 const FloatType* src1,
1360 const FloatType* src2,
1361 CountType num) noexcept
1362{
1363 FloatVectorHelpers::min (dest, src1, src2, num);
1364}
1365
1366template <typename FloatType, typename CountType>
1368 const FloatType* src,
1369 FloatType comp,
1370 CountType num) noexcept
1371{
1372 FloatVectorHelpers::max (dest, src, comp, num);
1373}
1374
1375template <typename FloatType, typename CountType>
1377 const FloatType* src1,
1378 const FloatType* src2,
1379 CountType num) noexcept
1380{
1381 FloatVectorHelpers::max (dest, src1, src2, num);
1382}
1383
1384template <typename FloatType, typename CountType>
1386 const FloatType* src,
1387 FloatType low,
1388 FloatType high,
1389 CountType num) noexcept
1390{
1391 FloatVectorHelpers::clip (dest, src, low, high, num);
1392}
1393
1394template <typename FloatType, typename CountType>
1396 CountType numValues) noexcept
1397{
1398 return FloatVectorHelpers::findMinAndMax (src, numValues);
1399}
1400
1401template <typename FloatType, typename CountType>
1403 CountType numValues) noexcept
1404{
1405 return FloatVectorHelpers::findMinimum (src, numValues);
1406}
1407
1408template <typename FloatType, typename CountType>
1410 CountType numValues) noexcept
1411{
1412 return FloatVectorHelpers::findMaximum (src, numValues);
1413}
1414
1419
1420void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, const int* src, float multiplier, size_t num) noexcept
1421{
1422 FloatVectorHelpers::convertFixedToFloat (dest, src, multiplier, num);
1423}
1424
1425void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, const int* src, float multiplier, int num) noexcept
1426{
1427 FloatVectorHelpers::convertFixedToFloat (dest, src, multiplier, num);
1428}
1429
1431{
1432 intptr_t fpsr = 0;
1433 #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS
1434 fpsr = static_cast<intptr_t> (_mm_getcsr());
1435 #elif defined(__arm64__) || defined(__aarch64__) || JUCE_USE_ARM_NEON
1436 #if defined(__arm64__) || defined(__aarch64__)
1437 asm volatile("mrs %0, fpcr"
1438 : "=r"(fpsr));
1439 #elif JUCE_USE_ARM_NEON
1440 asm volatile("vmrs %0, fpscr"
1441 : "=r"(fpsr));
1442 #endif
1443 #else
1444 #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))
1445 jassertfalse; // No support for getting the floating point status register for your platform
1446 #endif
1447 #endif
1448
1449 return fpsr;
1450}
1451
1453{
1454 #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS
1455 // the volatile keyword here is needed to workaround a bug in AppleClang 13.0
1456 // which aggressively optimises away the variable otherwise
1457 volatile auto fpsr_w = static_cast<uint32_t> (fpsr);
1458 _mm_setcsr (fpsr_w);
1459 #elif defined(__arm64__) || defined(__aarch64__) || JUCE_USE_ARM_NEON
1460 #if defined(__arm64__) || defined(__aarch64__)
1461 asm volatile("msr fpcr, %0"
1462 :
1463 : "ri"(fpsr));
1464 #elif JUCE_USE_ARM_NEON
1465 asm volatile("vmsr fpscr, %0"
1466 :
1467 : "ri"(fpsr));
1468 #endif
1469 #else
1470 #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))
1471 jassertfalse; // No support for getting the floating point status register for your platform
1472 #endif
1473 ignoreUnused (fpsr);
1474 #endif
1475}
1476
1478{
1479 #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))
1480 #if JUCE_USE_SSE_INTRINSICS
1481 intptr_t mask = _MM_FLUSH_ZERO_MASK;
1482 #else /*JUCE_USE_ARM_NEON*/
1483 intptr_t mask = (1 << 24 /* FZ */);
1484 #endif
1485 setFpStatusRegister ((getFpStatusRegister() & (~mask)) | (shouldEnable ? mask : 0));
1486 #else
1487 #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))
1488 jassertfalse; // No support for flush to zero mode on your platform
1489 #endif
1490 ignoreUnused (shouldEnable);
1491 #endif
1492}
1493
1495{
1496 #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))
1497 #if JUCE_USE_SSE_INTRINSICS
1498 intptr_t mask = 0x8040;
1499 #else /*JUCE_USE_ARM_NEON*/
1500 intptr_t mask = (1 << 24 /* FZ */);
1501 #endif
1502
1503 setFpStatusRegister ((getFpStatusRegister() & (~mask)) | (shouldDisable ? mask : 0));
1504 #else
1505 ignoreUnused (shouldDisable);
1506
1507 #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))
1508 jassertfalse; // No support for disable denormals mode on your platform
1509 #endif
1510 #endif
1511}
1512
1514{
1515 #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))
1516 #if JUCE_USE_SSE_INTRINSICS
1517 intptr_t mask = 0x8040;
1518 #else /*JUCE_USE_ARM_NEON*/
1519 intptr_t mask = (1 << 24 /* FZ */);
1520 #endif
1521
1522 return ((getFpStatusRegister() & mask) == mask);
1523 #else
1524 return false;
1525 #endif
1526}
1527
1529{
1530 #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))
1531 #if JUCE_USE_SSE_INTRINSICS
1532 intptr_t mask = 0x8040;
1533 #else /*JUCE_USE_ARM_NEON*/
1534 intptr_t mask = (1 << 24 /* FZ */);
1535 #endif
1536
1539 #endif
1540}
1541
1543{
1544 #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))
1546 #endif
1547}
1548
1549
1550//==============================================================================
1551//==============================================================================
1552#if JUCE_UNIT_TESTS
1553
1554class FloatVectorOperationsTests : public UnitTest
1555{
1556public:
1557 FloatVectorOperationsTests()
1558 : UnitTest ("FloatVectorOperations", UnitTestCategories::audio)
1559 {}
1560
1561 template <typename ValueType>
1562 struct TestRunner
1563 {
1564 static void runTest (UnitTest& u, Random random)
1565 {
1566 const int range = random.nextBool() ? 500 : 10;
1567 const int num = random.nextInt (range) + 1;
1568
1569 HeapBlock<ValueType> buffer1 (num + 16), buffer2 (num + 16);
1570 HeapBlock<int> buffer3 (num + 16, true);
1571
1572 #if JUCE_ARM
1573 ValueType* const data1 = buffer1;
1574 ValueType* const data2 = buffer2;
1575 int* const int1 = buffer3;
1576 #else
1577 // These tests deliberately operate on misaligned memory and will be flagged up by
1578 // checks for undefined behavior!
1579 ValueType* const data1 = addBytesToPointer (buffer1.get(), random.nextInt (16));
1580 ValueType* const data2 = addBytesToPointer (buffer2.get(), random.nextInt (16));
1581 int* const int1 = addBytesToPointer (buffer3.get(), random.nextInt (16));
1582 #endif
1583
1584 fillRandomly (random, data1, num);
1585 fillRandomly (random, data2, num);
1586
1587 Range<ValueType> minMax1 (FloatVectorOperations::findMinAndMax (data1, num));
1588 Range<ValueType> minMax2 (Range<ValueType>::findMinAndMax (data1, num));
1589 u.expect (minMax1 == minMax2);
1590
1591 u.expect (valuesMatch (FloatVectorOperations::findMinimum (data1, num), juce::findMinimum (data1, num)));
1592 u.expect (valuesMatch (FloatVectorOperations::findMaximum (data1, num), juce::findMaximum (data1, num)));
1593
1594 u.expect (valuesMatch (FloatVectorOperations::findMinimum (data2, num), juce::findMinimum (data2, num)));
1595 u.expect (valuesMatch (FloatVectorOperations::findMaximum (data2, num), juce::findMaximum (data2, num)));
1596
1597 FloatVectorOperations::clear (data1, num);
1598 u.expect (areAllValuesEqual (data1, num, 0));
1599
1600 FloatVectorOperations::fill (data1, (ValueType) 2, num);
1601 u.expect (areAllValuesEqual (data1, num, (ValueType) 2));
1602
1603 FloatVectorOperations::add (data1, (ValueType) 2, num);
1604 u.expect (areAllValuesEqual (data1, num, (ValueType) 4));
1605
1606 FloatVectorOperations::copy (data2, data1, num);
1607 u.expect (areAllValuesEqual (data2, num, (ValueType) 4));
1608
1609 FloatVectorOperations::add (data2, data1, num);
1610 u.expect (areAllValuesEqual (data2, num, (ValueType) 8));
1611
1612 FloatVectorOperations::copyWithMultiply (data2, data1, (ValueType) 4, num);
1613 u.expect (areAllValuesEqual (data2, num, (ValueType) 16));
1614
1615 FloatVectorOperations::addWithMultiply (data2, data1, (ValueType) 4, num);
1616 u.expect (areAllValuesEqual (data2, num, (ValueType) 32));
1617
1618 FloatVectorOperations::multiply (data1, (ValueType) 2, num);
1619 u.expect (areAllValuesEqual (data1, num, (ValueType) 8));
1620
1621 FloatVectorOperations::multiply (data1, data2, num);
1622 u.expect (areAllValuesEqual (data1, num, (ValueType) 256));
1623
1624 FloatVectorOperations::negate (data2, data1, num);
1625 u.expect (areAllValuesEqual (data2, num, (ValueType) -256));
1626
1627 FloatVectorOperations::subtract (data1, data2, num);
1628 u.expect (areAllValuesEqual (data1, num, (ValueType) 512));
1629
1630 FloatVectorOperations::abs (data1, data2, num);
1631 u.expect (areAllValuesEqual (data1, num, (ValueType) 256));
1632
1633 FloatVectorOperations::abs (data2, data1, num);
1634 u.expect (areAllValuesEqual (data2, num, (ValueType) 256));
1635
1636 fillRandomly (random, int1, num);
1637 doConversionTest (u, data1, data2, int1, num);
1638
1639 FloatVectorOperations::fill (data1, (ValueType) 2, num);
1640 FloatVectorOperations::fill (data2, (ValueType) 3, num);
1641 FloatVectorOperations::addWithMultiply (data1, data1, data2, num);
1642 u.expect (areAllValuesEqual (data1, num, (ValueType) 8));
1643 }
1644
1645 static void doConversionTest (UnitTest& u, float* data1, float* data2, int* const int1, int num)
1646 {
1647 FloatVectorOperations::convertFixedToFloat (data1, int1, 2.0f, num);
1648 convertFixed (data2, int1, 2.0f, num);
1649 u.expect (buffersMatch (data1, data2, num));
1650 }
1651
1652 static void doConversionTest (UnitTest&, double*, double*, int*, int) {}
1653
1654 static void fillRandomly (Random& random, ValueType* d, int num)
1655 {
1656 while (--num >= 0)
1657 *d++ = (ValueType) (random.nextDouble() * 1000.0);
1658 }
1659
1660 static void fillRandomly (Random& random, int* d, int num)
1661 {
1662 while (--num >= 0)
1663 *d++ = random.nextInt();
1664 }
1665
1666 static void convertFixed (float* d, const int* s, ValueType multiplier, int num)
1667 {
1668 while (--num >= 0)
1669 *d++ = (float) *s++ * multiplier;
1670 }
1671
1672 static bool areAllValuesEqual (const ValueType* d, int num, ValueType target)
1673 {
1674 while (--num >= 0)
1675 if (*d++ != target)
1676 return false;
1677
1678 return true;
1679 }
1680
1681 static bool buffersMatch (const ValueType* d1, const ValueType* d2, int num)
1682 {
1683 while (--num >= 0)
1684 if (! valuesMatch (*d1++, *d2++))
1685 return false;
1686
1687 return true;
1688 }
1689
1690 static bool valuesMatch (ValueType v1, ValueType v2)
1691 {
1692 return std::abs (v1 - v2) < std::numeric_limits<ValueType>::epsilon();
1693 }
1694 };
1695
1696 void runTest() override
1697 {
1698 beginTest ("FloatVectorOperations");
1699
1700 for (int i = 1000; --i >= 0;)
1701 {
1702 TestRunner<float>::runTest (*this, getRandom());
1703 TestRunner<double>::runTest (*this, getRandom());
1704 }
1705 }
1706};
1707
1708static FloatVectorOperationsTests vectorOpTests;
1709
1710#endif
1711
1712} // namespace juce
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
#define noexcept
Definition DistrhoDefines.h:72
uint8_t a
Definition Spc_Cpu.h:141
float abs(const fft_t *freqs, off_t x)
Definition OscilGen.cpp:52
uint64_t uint64
Definition basics.h:92
static const unsigned long mask[]
Definition bitwise.c:31
static void JUCE_CALLTYPE disableDenormalisedNumberSupport(bool shouldDisable=true) noexcept
Definition juce_FloatVectorOperations.cpp:1494
static void JUCE_CALLTYPE enableFlushToZeroMode(bool shouldEnable) noexcept
Definition juce_FloatVectorOperations.cpp:1477
static void JUCE_CALLTYPE setFpStatusRegister(intptr_t) noexcept
Definition juce_FloatVectorOperations.cpp:1452
static intptr_t JUCE_CALLTYPE getFpStatusRegister() noexcept
Definition juce_FloatVectorOperations.cpp:1430
static bool JUCE_CALLTYPE areDenormalsDisabled() noexcept
Definition juce_FloatVectorOperations.cpp:1513
static void JUCE_CALLTYPE convertFixedToFloat(float *dest, const int *src, float multiplier, int num) noexcept
Definition juce_FloatVectorOperations.cpp:1425
Definition juce_Range.h:40
~ScopedNoDenormals() noexcept
Definition juce_FloatVectorOperations.cpp:1542
ScopedNoDenormals() noexcept
Definition juce_FloatVectorOperations.cpp:1528
Definition juce_UnitTest.h:70
unsigned v[N_MAX]
Definition inflate.c:1584
unsigned d
Definition inflate.c:940
struct huft * u[BMAX]
Definition inflate.c:1583
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
unsigned f
Definition inflate.c:1572
static void v2(register WDL_FFT_REAL *a)
Definition fft.c:1099
int val
Definition jpeglib.h:956
#define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp)
Definition juce_FloatVectorOperations.cpp:309
#define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad)
Definition juce_FloatVectorOperations.cpp:350
#define JUCE_INCREMENT_SRC1_SRC2_DEST
Definition juce_FloatVectorOperations.cpp:29
#define JUCE_LOAD_NONE(srcLoad, dstLoad)
Definition juce_FloatVectorOperations.cpp:345
#define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp)
Definition juce_FloatVectorOperations.cpp:306
#define JUCE_LOAD_SRC1_SRC2(src1Load, src2Load)
Definition juce_FloatVectorOperations.cpp:348
#define JUCE_LOAD_DEST(srcLoad, dstLoad)
Definition juce_FloatVectorOperations.cpp:346
#define JUCE_INCREMENT_SRC_DEST
Definition juce_FloatVectorOperations.cpp:28
#define JUCE_LOAD_SRC(srcLoad, dstLoad)
Definition juce_FloatVectorOperations.cpp:347
#define JUCE_LOAD_SRC1_SRC2_DEST(src1Load, src2Load, dstLoad)
Definition juce_FloatVectorOperations.cpp:349
#define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp)
Definition juce_FloatVectorOperations.cpp:312
#define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp)
Definition juce_FloatVectorOperations.cpp:315
#define jassert(expression)
#define forcedinline
#define jassertfalse
#define JUCE_CALLTYPE
static int JUCE_CDECL comp(const void *a, const void *b)
Definition lsp.c:298
unsigned int uint32_t
Definition mid.cpp:100
T clip(T value, T min, T max)
Clip a value to [min, max].
Definition primitives.h:231
void fill(Buf &buf, T value)
Definition buffer.h:50
Definition juce_FloatVectorOperations.cpp:27
Definition juce_UnitTestCategories.h:27
void clear(void *s)
Definition juce_FixedSizeFunction.h:71
Definition carla_juce.cpp:31
unsigned long long uint64
Definition juce_MathsFunctions.h:56
void findMinAndMax(const Type *values, int numValues, Type &lowest, Type &highest)
Definition juce_MathsFunctions.h:219
unsigned int uint32
Definition juce_MathsFunctions.h:45
void ignoreUnused(Types &&...) noexcept
Definition juce_MathsFunctions.h:333
Type findMaximum(const Type *values, Size numValues)
Definition juce_MathsFunctions.h:199
Type findMinimum(const Type *data, Size numValues)
Definition juce_MathsFunctions.h:179
void zeromem(void *memory, size_t numBytes) noexcept
Definition juce_Memory.h:28
Type
Definition Lv2Ports.h:60
void add(SampleFrame *dst, const SampleFrame *src, int frames)
Add samples from src to dst.
Definition MixHelpers.cpp:135
void multiply(SampleFrame *dst, float coeff, int frames)
Multiply samples from dst by coeff.
Definition MixHelpers.cpp:192
#define min(x, y)
Definition os.h:74
#define max(x, y)
Definition os.h:78
Definition juce_FloatVectorOperations.h:55
static void JUCE_CALLTYPE add(FloatType *dest, FloatType amountToAdd, CountType numValues) noexcept
Definition juce_FloatVectorOperations.cpp:1212
static void JUCE_CALLTYPE max(FloatType *dest, const FloatType *src, FloatType comp, CountType num) noexcept
Definition juce_FloatVectorOperations.cpp:1367
static FloatType JUCE_CALLTYPE findMinimum(const FloatType *src, CountType numValues) noexcept
Definition juce_FloatVectorOperations.cpp:1402
static void JUCE_CALLTYPE multiply(FloatType *dest, const FloatType *src, CountType numValues) noexcept
Definition juce_FloatVectorOperations.cpp:1299
static void JUCE_CALLTYPE clear(FloatType *dest, CountType numValues) noexcept
Definition juce_FloatVectorOperations.cpp:1180
static void JUCE_CALLTYPE addWithMultiply(FloatType *dest, const FloatType *src, FloatType multiplier, CountType numValues) noexcept
Definition juce_FloatVectorOperations.cpp:1263
static Range< FloatType > JUCE_CALLTYPE findMinAndMax(const FloatType *src, CountType numValues) noexcept
Definition juce_FloatVectorOperations.cpp:1395
static void JUCE_CALLTYPE copy(FloatType *dest, const FloatType *src, CountType numValues) noexcept
Definition juce_FloatVectorOperations.cpp:1195
static void JUCE_CALLTYPE clip(FloatType *dest, const FloatType *src, FloatType low, FloatType high, CountType num) noexcept
Definition juce_FloatVectorOperations.cpp:1385
static FloatType JUCE_CALLTYPE findMaximum(const FloatType *src, CountType numValues) noexcept
Definition juce_FloatVectorOperations.cpp:1409
static void JUCE_CALLTYPE subtractWithMultiply(FloatType *dest, const FloatType *src, FloatType multiplier, CountType numValues) noexcept
Definition juce_FloatVectorOperations.cpp:1281
static void JUCE_CALLTYPE copyWithMultiply(FloatType *dest, const FloatType *src, FloatType multiplier, CountType numValues) noexcept
Definition juce_FloatVectorOperations.cpp:1203
static void JUCE_CALLTYPE fill(FloatType *dest, FloatType valueToFill, CountType numValues) noexcept
Definition juce_FloatVectorOperations.cpp:1187
static void JUCE_CALLTYPE subtract(FloatType *dest, const FloatType *src, CountType numValues) noexcept
Definition juce_FloatVectorOperations.cpp:1246
static void JUCE_CALLTYPE abs(FloatType *dest, const FloatType *src, CountType numValues) noexcept
Definition juce_FloatVectorOperations.cpp:1341
static void JUCE_CALLTYPE negate(FloatType *dest, const FloatType *src, CountType numValues) noexcept
Definition juce_FloatVectorOperations.cpp:1333
static void JUCE_CALLTYPE min(FloatType *dest, const FloatType *src, FloatType comp, CountType num) noexcept
Definition juce_FloatVectorOperations.cpp:1349
Definition juce_FloatVectorOperations.cpp:352
uint32 i
Definition juce_FloatVectorOperations.cpp:352
float f
Definition juce_FloatVectorOperations.cpp:352
Definition juce_FloatVectorOperations.cpp:353
uint64 i
Definition juce_FloatVectorOperations.cpp:353
double d
Definition juce_FloatVectorOperations.cpp:353
uch * p
Definition crypt.c:594
memcpy(hh, h, RAND_HEAD_LEN)
b
Definition crypt.c:628
int result
Definition process.c:1455