79#if defined(DSPARK_SIMD_AVX)
80 const __m256 vGain = _mm256_set1_ps(gain);
82 for (; i + 7 < count; i += 8)
84 __m256 vDst = _mm256_loadu_ps(dst + i);
85 __m256 vSrc = _mm256_loadu_ps(src + i);
87 #if defined(DSPARK_SIMD_FMA)
88 _mm256_storeu_ps(dst + i, _mm256_fmadd_ps(vSrc, vGain, vDst));
90 _mm256_storeu_ps(dst + i, _mm256_add_ps(vDst, _mm256_mul_ps(vSrc, vGain)));
93 for (; i < count; ++i) dst[i] += src[i] * gain;
95#elif defined(DSPARK_SIMD_SSE2)
96 const __m128 vGain = _mm_set1_ps(gain);
98 for (; i + 3 < count; i += 4)
100 __m128 vDst = _mm_loadu_ps(dst + i);
101 __m128 vSrc = _mm_loadu_ps(src + i);
103 #if defined(DSPARK_SIMD_FMA)
104 _mm_storeu_ps(dst + i, _mm_fmadd_ps(vSrc, vGain, vDst));
106 _mm_storeu_ps(dst + i, _mm_add_ps(vDst, _mm_mul_ps(vSrc, vGain)));
109 for (; i < count; ++i) dst[i] += src[i] * gain;
111#elif defined(DSPARK_SIMD_NEON)
112 const float32x4_t vGain = vdupq_n_f32(gain);
114 for (; i + 3 < count; i += 4)
116 float32x4_t vDst = vld1q_f32(dst + i);
117 float32x4_t vSrc = vld1q_f32(src + i);
120 vst1q_f32(dst + i, vfmaq_f32(vDst, vSrc, vGain));
122 for (; i < count; ++i) dst[i] += src[i] * gain;
125 for (
int i = 0; i < count; ++i) dst[i] += src[i] * gain;
132#if defined(DSPARK_SIMD_AVX)
133 const __m256d vGain = _mm256_set1_pd(gain);
135 for (; i + 3 < count; i += 4)
137 __m256d vDst = _mm256_loadu_pd(dst + i);
138 __m256d vSrc = _mm256_loadu_pd(src + i);
140 #if defined(DSPARK_SIMD_FMA)
141 _mm256_storeu_pd(dst + i, _mm256_fmadd_pd(vSrc, vGain, vDst));
143 _mm256_storeu_pd(dst + i, _mm256_add_pd(vDst, _mm256_mul_pd(vSrc, vGain)));
146 for (; i < count; ++i) dst[i] += src[i] * gain;
148#elif defined(DSPARK_SIMD_SSE2)
149 const __m128d vGain = _mm_set1_pd(gain);
151 for (; i + 1 < count; i += 2)
153 __m128d vDst = _mm_loadu_pd(dst + i);
154 __m128d vSrc = _mm_loadu_pd(src + i);
156 #if defined(DSPARK_SIMD_FMA)
157 _mm_storeu_pd(dst + i, _mm_fmadd_pd(vSrc, vGain, vDst));
159 _mm_storeu_pd(dst + i, _mm_add_pd(vDst, _mm_mul_pd(vSrc, vGain)));
162 for (; i < count; ++i) dst[i] += src[i] * gain;
164#elif defined(DSPARK_SIMD_NEON)
165 const float64x2_t vGain = vdupq_n_f64(gain);
167 for (; i + 1 < count; i += 2)
169 float64x2_t vDst = vld1q_f64(dst + i);
170 float64x2_t vSrc = vld1q_f64(src + i);
171 vst1q_f64(dst + i, vfmaq_f64(vDst, vSrc, vGain));
173 for (; i < count; ++i) dst[i] += src[i] * gain;
175 for (
int i = 0; i < count; ++i) dst[i] += src[i] * gain;
188#if defined(DSPARK_SIMD_AVX)
189 const __m256 vGain = _mm256_set1_ps(gain);
191 for (; i + 7 < count; i += 8)
193 __m256 v = _mm256_loadu_ps(data + i);
194 _mm256_storeu_ps(data + i, _mm256_mul_ps(v, vGain));
196 for (; i < count; ++i) data[i] *= gain;
198#elif defined(DSPARK_SIMD_SSE2)
199 const __m128 vGain = _mm_set1_ps(gain);
201 for (; i + 3 < count; i += 4)
203 __m128 v = _mm_loadu_ps(data + i);
204 _mm_storeu_ps(data + i, _mm_mul_ps(v, vGain));
206 for (; i < count; ++i) data[i] *= gain;
208#elif defined(DSPARK_SIMD_NEON)
209 const float32x4_t vGain = vdupq_n_f32(gain);
211 for (; i + 3 < count; i += 4)
213 float32x4_t v = vld1q_f32(data + i);
214 vst1q_f32(data + i, vmulq_f32(v, vGain));
216 for (; i < count; ++i) data[i] *= gain;
219 for (
int i = 0; i < count; ++i) data[i] *= gain;
226#if defined(DSPARK_SIMD_AVX)
227 const __m256d vGain = _mm256_set1_pd(gain);
229 for (; i + 3 < count; i += 4)
230 _mm256_storeu_pd(data + i, _mm256_mul_pd(_mm256_loadu_pd(data + i), vGain));
231 for (; i < count; ++i) data[i] *= gain;
233#elif defined(DSPARK_SIMD_SSE2)
234 const __m128d vGain = _mm_set1_pd(gain);
236 for (; i + 1 < count; i += 2)
238 __m128d v = _mm_loadu_pd(data + i);
239 _mm_storeu_pd(data + i, _mm_mul_pd(v, vGain));
241 for (; i < count; ++i) data[i] *= gain;
243#elif defined(DSPARK_SIMD_NEON)
244 const float64x2_t vGain = vdupq_n_f64(gain);
246 for (; i + 1 < count; i += 2)
247 vst1q_f64(data + i, vmulq_f64(vld1q_f64(data + i), vGain));
248 for (; i < count; ++i) data[i] *= gain;
250 for (
int i = 0; i < count; ++i) data[i] *= gain;
266#if defined(DSPARK_SIMD_AVX)
267 const __m256 absMask = _mm256_castsi256_ps(_mm256_set1_epi32(0x7FFFFFFF));
268 __m256 vMax = _mm256_setzero_ps();
270 for (; i + 7 < count; i += 8)
272 __m256 v = _mm256_loadu_ps(data + i);
273 v = _mm256_and_ps(v, absMask);
277 vMax = _mm256_max_ps(v, vMax);
279 __m128 hi = _mm256_extractf128_ps(vMax, 1);
280 __m128 lo = _mm256_castps256_ps128(vMax);
281 __m128 m4 = _mm_max_ps(lo, hi);
282 __m128 m2 = _mm_max_ps(m4, _mm_movehl_ps(m4, m4));
283 __m128 m1 = _mm_max_ss(m2, _mm_shuffle_ps(m2, m2, 1));
284 float peak = _mm_cvtss_f32(m1);
286 for (; i < count; ++i)
288 float a = data[i] < 0.0f ? -data[i] : data[i];
289 if (a > peak) peak = a;
293#elif defined(DSPARK_SIMD_SSE2)
294 const __m128 absMask = _mm_castsi128_ps(_mm_set1_epi32(0x7FFFFFFF));
295 __m128 vMax = _mm_setzero_ps();
297 for (; i + 3 < count; i += 4)
299 __m128 v = _mm_loadu_ps(data + i);
300 v = _mm_and_ps(v, absMask);
301 vMax = _mm_max_ps(v, vMax);
303 __m128 shuf = _mm_movehl_ps(vMax, vMax);
304 __m128 maxPair = _mm_max_ps(vMax, shuf);
305 __m128 maxSingle = _mm_max_ss(maxPair, _mm_shuffle_ps(maxPair, maxPair, 1));
306 float peak = _mm_cvtss_f32(maxSingle);
308 for (; i < count; ++i)
310 float a = data[i] < 0.0f ? -data[i] : data[i];
311 if (a > peak) peak = a;
315#elif defined(DSPARK_SIMD_NEON)
316 float32x4_t vMax = vdupq_n_f32(0.0f);
318 for (; i + 3 < count; i += 4)
320 float32x4_t v = vld1q_f32(data + i);
322 vMax = vmaxnmq_f32(vMax, v);
324 float peak = vmaxvq_f32(vMax);
326 for (; i < count; ++i)
328 float a = data[i] < 0.0f ? -data[i] : data[i];
329 if (a > peak) peak = a;
335 for (
int i = 0; i < count; ++i)
337 float a = data[i] < 0.0f ? -data[i] : data[i];
338 if (a > peak) peak = a;
347#if defined(DSPARK_SIMD_AVX)
348 const __m256d absMask = _mm256_castsi256_pd(_mm256_set1_epi64x(0x7FFFFFFFFFFFFFFFll));
349 __m256d vMax = _mm256_setzero_pd();
351 for (; i + 3 < count; i += 4)
352 vMax = _mm256_max_pd(_mm256_and_pd(_mm256_loadu_pd(data + i), absMask), vMax);
353 __m128d lo = _mm256_castpd256_pd128(vMax);
354 __m128d hi = _mm256_extractf128_pd(vMax, 1);
355 __m128d m2 = _mm_max_pd(lo, hi);
356 double peak = _mm_cvtsd_f64(_mm_max_sd(m2, _mm_unpackhi_pd(m2, m2)));
358 for (; i < count; ++i)
360 double a = data[i] < 0.0 ? -data[i] : data[i];
361 if (a > peak) peak = a;
365#elif defined(DSPARK_SIMD_SSE2)
366 const __m128d absMask = _mm_castsi128_pd(_mm_set_epi64x(
367 static_cast<int64_t
>(0x7FFFFFFFFFFFFFFF),
368 static_cast<int64_t
>(0x7FFFFFFFFFFFFFFF)));
369 __m128d vMax = _mm_setzero_pd();
371 for (; i + 1 < count; i += 2)
373 __m128d v = _mm_loadu_pd(data + i);
374 v = _mm_and_pd(v, absMask);
375 vMax = _mm_max_pd(v, vMax);
377 __m128d hi = _mm_unpackhi_pd(vMax, vMax);
378 __m128d maxVal = _mm_max_sd(vMax, hi);
379 double peak = _mm_cvtsd_f64(maxVal);
381 for (; i < count; ++i)
383 double a = data[i] < 0.0 ? -data[i] : data[i];
384 if (a > peak) peak = a;
388#elif defined(DSPARK_SIMD_NEON)
389 float64x2_t vMax = vdupq_n_f64(0.0);
391 for (; i + 1 < count; i += 2)
392 vMax = vmaxnmq_f64(vMax, vabsq_f64(vld1q_f64(data + i)));
393 double peak = vmaxvq_f64(vMax);
395 for (; i < count; ++i)
397 double a = data[i] < 0.0 ? -data[i] : data[i];
398 if (a > peak) peak = a;
403 for (
int i = 0; i < count; ++i)
405 double a = data[i] < 0.0 ? -data[i] : data[i];
406 if (a > peak) peak = a;
421#if defined(DSPARK_SIMD_AVX)
424 __m256 vSum0 = _mm256_setzero_ps();
425 __m256 vSum1 = _mm256_setzero_ps();
426 __m256 vSum2 = _mm256_setzero_ps();
427 __m256 vSum3 = _mm256_setzero_ps();
429 for (; i + 31 < count; i += 32)
431 #if defined(DSPARK_SIMD_FMA)
432 vSum0 = _mm256_fmadd_ps(_mm256_loadu_ps(a + i), _mm256_loadu_ps(b + i), vSum0);
433 vSum1 = _mm256_fmadd_ps(_mm256_loadu_ps(a + i + 8), _mm256_loadu_ps(b + i + 8), vSum1);
434 vSum2 = _mm256_fmadd_ps(_mm256_loadu_ps(a + i + 16), _mm256_loadu_ps(b + i + 16), vSum2);
435 vSum3 = _mm256_fmadd_ps(_mm256_loadu_ps(a + i + 24), _mm256_loadu_ps(b + i + 24), vSum3);
437 vSum0 = _mm256_add_ps(vSum0, _mm256_mul_ps(_mm256_loadu_ps(a + i), _mm256_loadu_ps(b + i)));
438 vSum1 = _mm256_add_ps(vSum1, _mm256_mul_ps(_mm256_loadu_ps(a + i + 8), _mm256_loadu_ps(b + i + 8)));
439 vSum2 = _mm256_add_ps(vSum2, _mm256_mul_ps(_mm256_loadu_ps(a + i + 16), _mm256_loadu_ps(b + i + 16)));
440 vSum3 = _mm256_add_ps(vSum3, _mm256_mul_ps(_mm256_loadu_ps(a + i + 24), _mm256_loadu_ps(b + i + 24)));
443 for (; i + 7 < count; i += 8)
445 #if defined(DSPARK_SIMD_FMA)
446 vSum0 = _mm256_fmadd_ps(_mm256_loadu_ps(a + i), _mm256_loadu_ps(b + i), vSum0);
448 vSum0 = _mm256_add_ps(vSum0, _mm256_mul_ps(_mm256_loadu_ps(a + i), _mm256_loadu_ps(b + i)));
451 __m256 vSum = _mm256_add_ps(_mm256_add_ps(vSum0, vSum1), _mm256_add_ps(vSum2, vSum3));
452 __m128 hi = _mm256_extractf128_ps(vSum, 1);
453 __m128 lo = _mm256_castps256_ps128(vSum);
454 __m128 sum4 = _mm_add_ps(lo, hi);
455 __m128 shuf = _mm_movehl_ps(sum4, sum4);
456 __m128 sum2 = _mm_add_ps(sum4, shuf);
457 __m128 sum1 = _mm_add_ss(sum2, _mm_shuffle_ps(sum2, sum2, 1));
458 float sum = _mm_cvtss_f32(sum1);
460 for (; i < count; ++i) sum += a[i] * b[i];
463#elif defined(DSPARK_SIMD_SSE2)
465 __m128 vSum0 = _mm_setzero_ps();
466 __m128 vSum1 = _mm_setzero_ps();
468 for (; i + 7 < count; i += 8)
470 #if defined(DSPARK_SIMD_FMA)
471 vSum0 = _mm_fmadd_ps(_mm_loadu_ps(a + i), _mm_loadu_ps(b + i), vSum0);
472 vSum1 = _mm_fmadd_ps(_mm_loadu_ps(a + i + 4), _mm_loadu_ps(b + i + 4), vSum1);
474 vSum0 = _mm_add_ps(vSum0, _mm_mul_ps(_mm_loadu_ps(a + i), _mm_loadu_ps(b + i)));
475 vSum1 = _mm_add_ps(vSum1, _mm_mul_ps(_mm_loadu_ps(a + i + 4), _mm_loadu_ps(b + i + 4)));
478 for (; i + 3 < count; i += 4)
480 #if defined(DSPARK_SIMD_FMA)
481 vSum0 = _mm_fmadd_ps(_mm_loadu_ps(a + i), _mm_loadu_ps(b + i), vSum0);
483 vSum0 = _mm_add_ps(vSum0, _mm_mul_ps(_mm_loadu_ps(a + i), _mm_loadu_ps(b + i)));
486 alignas(16)
float tmp[4];
487 _mm_store_ps(tmp, _mm_add_ps(vSum0, vSum1));
488 float sum = tmp[0] + tmp[1] + tmp[2] + tmp[3];
490 for (; i < count; ++i) sum += a[i] * b[i];
493#elif defined(DSPARK_SIMD_NEON)
494 float32x4_t vSum0 = vdupq_n_f32(0.0f);
495 float32x4_t vSum1 = vdupq_n_f32(0.0f);
497 for (; i + 7 < count; i += 8)
499 vSum0 = vfmaq_f32(vSum0, vld1q_f32(a + i), vld1q_f32(b + i));
500 vSum1 = vfmaq_f32(vSum1, vld1q_f32(a + i + 4), vld1q_f32(b + i + 4));
502 for (; i + 3 < count; i += 4)
503 vSum0 = vfmaq_f32(vSum0, vld1q_f32(a + i), vld1q_f32(b + i));
504 float sum = vaddvq_f32(vaddq_f32(vSum0, vSum1));
506 for (; i < count; ++i) sum += a[i] * b[i];
511 for (
int i = 0; i < count; ++i) sum += a[i] * b[i];
519#if defined(DSPARK_SIMD_AVX)
520 __m256d vSum0 = _mm256_setzero_pd();
521 __m256d vSum1 = _mm256_setzero_pd();
523 for (; i + 7 < count; i += 8)
525 #if defined(DSPARK_SIMD_FMA)
526 vSum0 = _mm256_fmadd_pd(_mm256_loadu_pd(a + i), _mm256_loadu_pd(b + i), vSum0);
527 vSum1 = _mm256_fmadd_pd(_mm256_loadu_pd(a + i + 4), _mm256_loadu_pd(b + i + 4), vSum1);
529 vSum0 = _mm256_add_pd(vSum0, _mm256_mul_pd(_mm256_loadu_pd(a + i), _mm256_loadu_pd(b + i)));
530 vSum1 = _mm256_add_pd(vSum1, _mm256_mul_pd(_mm256_loadu_pd(a + i + 4), _mm256_loadu_pd(b + i + 4)));
533 for (; i + 3 < count; i += 4)
535 #if defined(DSPARK_SIMD_FMA)
536 vSum0 = _mm256_fmadd_pd(_mm256_loadu_pd(a + i), _mm256_loadu_pd(b + i), vSum0);
538 vSum0 = _mm256_add_pd(vSum0, _mm256_mul_pd(_mm256_loadu_pd(a + i), _mm256_loadu_pd(b + i)));
541 __m256d vSum = _mm256_add_pd(vSum0, vSum1);
542 __m128d lo = _mm256_castpd256_pd128(vSum);
543 __m128d hi = _mm256_extractf128_pd(vSum, 1);
544 __m128d s2 = _mm_add_pd(lo, hi);
545 double sum = _mm_cvtsd_f64(_mm_add_sd(s2, _mm_unpackhi_pd(s2, s2)));
547 for (; i < count; ++i) sum += a[i] * b[i];
550#elif defined(DSPARK_SIMD_SSE2)
551 __m128d vSum0 = _mm_setzero_pd();
552 __m128d vSum1 = _mm_setzero_pd();
554 for (; i + 3 < count; i += 4)
556 #if defined(DSPARK_SIMD_FMA)
557 vSum0 = _mm_fmadd_pd(_mm_loadu_pd(a + i), _mm_loadu_pd(b + i), vSum0);
558 vSum1 = _mm_fmadd_pd(_mm_loadu_pd(a + i + 2), _mm_loadu_pd(b + i + 2), vSum1);
560 vSum0 = _mm_add_pd(vSum0, _mm_mul_pd(_mm_loadu_pd(a + i), _mm_loadu_pd(b + i)));
561 vSum1 = _mm_add_pd(vSum1, _mm_mul_pd(_mm_loadu_pd(a + i + 2), _mm_loadu_pd(b + i + 2)));
564 for (; i + 1 < count; i += 2)
566 #if defined(DSPARK_SIMD_FMA)
567 vSum0 = _mm_fmadd_pd(_mm_loadu_pd(a + i), _mm_loadu_pd(b + i), vSum0);
569 vSum0 = _mm_add_pd(vSum0, _mm_mul_pd(_mm_loadu_pd(a + i), _mm_loadu_pd(b + i)));
572 __m128d vSum = _mm_add_pd(vSum0, vSum1);
573 __m128d hi = _mm_unpackhi_pd(vSum, vSum);
574 double sum = _mm_cvtsd_f64(_mm_add_sd(vSum, hi));
576 for (; i < count; ++i) sum += a[i] * b[i];
579#elif defined(DSPARK_SIMD_NEON)
580 float64x2_t vSum0 = vdupq_n_f64(0.0);
581 float64x2_t vSum1 = vdupq_n_f64(0.0);
583 for (; i + 3 < count; i += 4)
585 vSum0 = vfmaq_f64(vSum0, vld1q_f64(a + i), vld1q_f64(b + i));
586 vSum1 = vfmaq_f64(vSum1, vld1q_f64(a + i + 2), vld1q_f64(b + i + 2));
588 for (; i + 1 < count; i += 2)
589 vSum0 = vfmaq_f64(vSum0, vld1q_f64(a + i), vld1q_f64(b + i));
590 double sum = vaddvq_f64(vaddq_f64(vSum0, vSum1));
592 for (; i < count; ++i) sum += a[i] * b[i];
596 for (
int i = 0; i < count; ++i) sum += a[i] * b[i];
610#if defined(DSPARK_SIMD_AVX)
612 for (; i + 7 < count; i += 8)
614 __m256 vDst = _mm256_loadu_ps(dst + i);
615 __m256 vSrc = _mm256_loadu_ps(src + i);
616 _mm256_storeu_ps(dst + i, _mm256_add_ps(vDst, vSrc));
618 for (; i < count; ++i) dst[i] += src[i];
620#elif defined(DSPARK_SIMD_SSE2)
622 for (; i + 3 < count; i += 4)
624 __m128 vDst = _mm_loadu_ps(dst + i);
625 __m128 vSrc = _mm_loadu_ps(src + i);
626 _mm_storeu_ps(dst + i, _mm_add_ps(vDst, vSrc));
628 for (; i < count; ++i) dst[i] += src[i];
630#elif defined(DSPARK_SIMD_NEON)
632 for (; i + 3 < count; i += 4)
634 float32x4_t vDst = vld1q_f32(dst + i);
635 float32x4_t vSrc = vld1q_f32(src + i);
636 vst1q_f32(dst + i, vaddq_f32(vDst, vSrc));
638 for (; i < count; ++i) dst[i] += src[i];
641 for (
int i = 0; i < count; ++i) dst[i] += src[i];
648#if defined(DSPARK_SIMD_AVX)
650 for (; i + 3 < count; i += 4)
651 _mm256_storeu_pd(dst + i, _mm256_add_pd(_mm256_loadu_pd(dst + i), _mm256_loadu_pd(src + i)));
652 for (; i < count; ++i) dst[i] += src[i];
654#elif defined(DSPARK_SIMD_SSE2)
656 for (; i + 1 < count; i += 2)
658 __m128d vDst = _mm_loadu_pd(dst + i);
659 __m128d vSrc = _mm_loadu_pd(src + i);
660 _mm_storeu_pd(dst + i, _mm_add_pd(vDst, vSrc));
662 for (; i < count; ++i) dst[i] += src[i];
664#elif defined(DSPARK_SIMD_NEON)
666 for (; i + 1 < count; i += 2)
667 vst1q_f64(dst + i, vaddq_f64(vld1q_f64(dst + i), vld1q_f64(src + i)));
668 for (; i < count; ++i) dst[i] += src[i];
670 for (
int i = 0; i < count; ++i) dst[i] += src[i];
681#if defined(DSPARK_SIMD_AVX)
683 for (; i + 7 < count; i += 8)
684 _mm256_storeu_ps(dst + i, _mm256_mul_ps(_mm256_loadu_ps(a + i), _mm256_loadu_ps(b + i)));
685 for (; i < count; ++i) dst[i] = a[i] * b[i];
686#elif defined(DSPARK_SIMD_SSE2)
688 for (; i + 3 < count; i += 4)
689 _mm_storeu_ps(dst + i, _mm_mul_ps(_mm_loadu_ps(a + i), _mm_loadu_ps(b + i)));
690 for (; i < count; ++i) dst[i] = a[i] * b[i];
691#elif defined(DSPARK_SIMD_NEON)
693 for (; i + 3 < count; i += 4)
694 vst1q_f32(dst + i, vmulq_f32(vld1q_f32(a + i), vld1q_f32(b + i)));
695 for (; i < count; ++i) dst[i] = a[i] * b[i];
697 for (
int i = 0; i < count; ++i) dst[i] = a[i] * b[i];
704#if defined(DSPARK_SIMD_AVX)
706 for (; i + 3 < count; i += 4)
707 _mm256_storeu_pd(dst + i, _mm256_mul_pd(_mm256_loadu_pd(a + i), _mm256_loadu_pd(b + i)));
708 for (; i < count; ++i) dst[i] = a[i] * b[i];
709#elif defined(DSPARK_SIMD_SSE2)
711 for (; i + 1 < count; i += 2)
712 _mm_storeu_pd(dst + i, _mm_mul_pd(_mm_loadu_pd(a + i), _mm_loadu_pd(b + i)));
713 for (; i < count; ++i) dst[i] = a[i] * b[i];
715#elif defined(DSPARK_SIMD_NEON)
717 for (; i + 1 < count; i += 2)
718 vst1q_f64(dst + i, vmulq_f64(vld1q_f64(a + i), vld1q_f64(b + i)));
719 for (; i < count; ++i) dst[i] = a[i] * b[i];
721 for (
int i = 0; i < count; ++i) dst[i] = a[i] * b[i];
732#if defined(DSPARK_SIMD_AVX)
733 const __m256 vGain = _mm256_set1_ps(gain);
735 for (; i + 7 < count; i += 8)
736 _mm256_storeu_ps(dst + i, _mm256_mul_ps(_mm256_loadu_ps(src + i), vGain));
737 for (; i < count; ++i) dst[i] = src[i] * gain;
738#elif defined(DSPARK_SIMD_SSE2)
739 const __m128 vGain = _mm_set1_ps(gain);
741 for (; i + 3 < count; i += 4)
742 _mm_storeu_ps(dst + i, _mm_mul_ps(_mm_loadu_ps(src + i), vGain));
743 for (; i < count; ++i) dst[i] = src[i] * gain;
744#elif defined(DSPARK_SIMD_NEON)
745 const float32x4_t vGain = vdupq_n_f32(gain);
747 for (; i + 3 < count; i += 4)
748 vst1q_f32(dst + i, vmulq_f32(vld1q_f32(src + i), vGain));
749 for (; i < count; ++i) dst[i] = src[i] * gain;
751 for (
int i = 0; i < count; ++i) dst[i] = src[i] * gain;
758#if defined(DSPARK_SIMD_AVX)
759 const __m256d vGain = _mm256_set1_pd(gain);
761 for (; i + 3 < count; i += 4)
762 _mm256_storeu_pd(dst + i, _mm256_mul_pd(_mm256_loadu_pd(src + i), vGain));
763 for (; i < count; ++i) dst[i] = src[i] * gain;
764#elif defined(DSPARK_SIMD_SSE2)
765 const __m128d vGain = _mm_set1_pd(gain);
767 for (; i + 1 < count; i += 2)
768 _mm_storeu_pd(dst + i, _mm_mul_pd(_mm_loadu_pd(src + i), vGain));
769 for (; i < count; ++i) dst[i] = src[i] * gain;
771#elif defined(DSPARK_SIMD_NEON)
772 const float64x2_t vGain = vdupq_n_f64(gain);
774 for (; i + 1 < count; i += 2)
775 vst1q_f64(dst + i, vmulq_f64(vld1q_f64(src + i), vGain));
776 for (; i < count; ++i) dst[i] = src[i] * gain;
778 for (
int i = 0; i < count; ++i) dst[i] = src[i] * gain;
796 if (count <= 0)
return;
797 const float step = (gainEnd - gainStart) /
static_cast<float>(count);
798#if defined(DSPARK_SIMD_AVX)
799 const __m256 vStep = _mm256_set1_ps(step * 8.0f);
800 __m256 vGain = _mm256_setr_ps(gainStart, gainStart + step,
801 gainStart + 2 * step, gainStart + 3 * step,
802 gainStart + 4 * step, gainStart + 5 * step,
803 gainStart + 6 * step, gainStart + 7 * step);
805 for (; i + 7 < count; i += 8)
807 _mm256_storeu_ps(data + i, _mm256_mul_ps(_mm256_loadu_ps(data + i), vGain));
808 vGain = _mm256_add_ps(vGain, vStep);
810 for (; i < count; ++i) data[i] *= gainStart + step * static_cast<float>(i);
812#elif defined(DSPARK_SIMD_SSE2)
813 const __m128 vStep = _mm_set1_ps(step * 4.0f);
814 __m128 vGain = _mm_setr_ps(gainStart, gainStart + step, gainStart + 2 * step, gainStart + 3 * step);
816 for (; i + 3 < count; i += 4)
818 _mm_storeu_ps(data + i, _mm_mul_ps(_mm_loadu_ps(data + i), vGain));
819 vGain = _mm_add_ps(vGain, vStep);
821 for (; i < count; ++i) data[i] *= gainStart + step * static_cast<float>(i);
823#elif defined(DSPARK_SIMD_NEON)
824 const float32x4_t vStep = vdupq_n_f32(step * 4.0f);
825 const float init[4] = { gainStart, gainStart + step, gainStart + 2 * step, gainStart + 3 * step };
826 float32x4_t vGain = vld1q_f32(init);
828 for (; i + 3 < count; i += 4)
830 vst1q_f32(data + i, vmulq_f32(vld1q_f32(data + i), vGain));
831 vGain = vaddq_f32(vGain, vStep);
833 for (; i < count; ++i) data[i] *= gainStart + step * static_cast<float>(i);
836 for (
int i = 0; i < count; ++i) data[i] *= gainStart + step * static_cast<float>(i);
843 if (count <= 0)
return;
844 const double step = (gainEnd - gainStart) /
static_cast<double>(count);
845#if defined(DSPARK_SIMD_AVX)
846 const __m256d vStep = _mm256_set1_pd(step * 4.0);
847 __m256d vGain = _mm256_setr_pd(gainStart, gainStart + step,
848 gainStart + 2 * step, gainStart + 3 * step);
850 for (; i + 3 < count; i += 4)
852 _mm256_storeu_pd(data + i, _mm256_mul_pd(_mm256_loadu_pd(data + i), vGain));
853 vGain = _mm256_add_pd(vGain, vStep);
855 for (; i < count; ++i) data[i] *= gainStart + step * static_cast<double>(i);
857#elif defined(DSPARK_SIMD_SSE2)
858 const __m128d vStep = _mm_set1_pd(step * 2.0);
859 __m128d vGain = _mm_setr_pd(gainStart, gainStart + step);
861 for (; i + 1 < count; i += 2)
863 _mm_storeu_pd(data + i, _mm_mul_pd(_mm_loadu_pd(data + i), vGain));
864 vGain = _mm_add_pd(vGain, vStep);
866 for (; i < count; ++i) data[i] *= gainStart + step * static_cast<double>(i);
868#elif defined(DSPARK_SIMD_NEON)
869 const float64x2_t vStep = vdupq_n_f64(step * 2.0);
870 const double init[2] = { gainStart, gainStart + step };
871 float64x2_t vGain = vld1q_f64(init);
873 for (; i + 1 < count; i += 2)
875 vst1q_f64(data + i, vmulq_f64(vld1q_f64(data + i), vGain));
876 vGain = vaddq_f64(vGain, vStep);
878 for (; i < count; ++i) data[i] *= gainStart + step * static_cast<double>(i);
881 for (
int i = 0; i < count; ++i) data[i] *= gainStart + step * static_cast<double>(i);
897 float gainStart,
float gainEnd,
int count)
noexcept
899 if (count <= 0)
return;
900 const float step = (gainEnd - gainStart) /
static_cast<float>(count);
901#if defined(DSPARK_SIMD_AVX)
902 const __m256 vStep = _mm256_set1_ps(step * 8.0f);
903 __m256 vGain = _mm256_setr_ps(gainStart, gainStart + step,
904 gainStart + 2 * step, gainStart + 3 * step,
905 gainStart + 4 * step, gainStart + 5 * step,
906 gainStart + 6 * step, gainStart + 7 * step);
908 for (; i + 7 < count; i += 8)
910 const __m256 vDst = _mm256_loadu_ps(dst + i);
911 const __m256 vSrc = _mm256_loadu_ps(src + i);
912 #if defined(DSPARK_SIMD_FMA)
913 _mm256_storeu_ps(dst + i, _mm256_fmadd_ps(vSrc, vGain, vDst));
915 _mm256_storeu_ps(dst + i, _mm256_add_ps(vDst, _mm256_mul_ps(vSrc, vGain)));
917 vGain = _mm256_add_ps(vGain, vStep);
919 for (; i < count; ++i) dst[i] += src[i] * (gainStart + step * static_cast<float>(i));
921#elif defined(DSPARK_SIMD_SSE2)
922 const __m128 vStep = _mm_set1_ps(step * 4.0f);
923 __m128 vGain = _mm_setr_ps(gainStart, gainStart + step, gainStart + 2 * step, gainStart + 3 * step);
925 for (; i + 3 < count; i += 4)
927 const __m128 vDst = _mm_loadu_ps(dst + i);
928 const __m128 vSrc = _mm_loadu_ps(src + i);
929 #if defined(DSPARK_SIMD_FMA)
930 _mm_storeu_ps(dst + i, _mm_fmadd_ps(vSrc, vGain, vDst));
932 _mm_storeu_ps(dst + i, _mm_add_ps(vDst, _mm_mul_ps(vSrc, vGain)));
934 vGain = _mm_add_ps(vGain, vStep);
936 for (; i < count; ++i) dst[i] += src[i] * (gainStart + step * static_cast<float>(i));
938#elif defined(DSPARK_SIMD_NEON)
939 const float32x4_t vStep = vdupq_n_f32(step * 4.0f);
940 const float init[4] = { gainStart, gainStart + step, gainStart + 2 * step, gainStart + 3 * step };
941 float32x4_t vGain = vld1q_f32(init);
943 for (; i + 3 < count; i += 4)
945 vst1q_f32(dst + i, vfmaq_f32(vld1q_f32(dst + i), vld1q_f32(src + i), vGain));
946 vGain = vaddq_f32(vGain, vStep);
948 for (; i < count; ++i) dst[i] += src[i] * (gainStart + step * static_cast<float>(i));
951 for (
int i = 0; i < count; ++i) dst[i] += src[i] * (gainStart + step * static_cast<float>(i));
957 double gainStart,
double gainEnd,
int count)
noexcept
959 if (count <= 0)
return;
960 const double step = (gainEnd - gainStart) /
static_cast<double>(count);
961#if defined(DSPARK_SIMD_AVX)
962 const __m256d vStep = _mm256_set1_pd(step * 4.0);
963 __m256d vGain = _mm256_setr_pd(gainStart, gainStart + step,
964 gainStart + 2 * step, gainStart + 3 * step);
966 for (; i + 3 < count; i += 4)
968 const __m256d vDst = _mm256_loadu_pd(dst + i);
969 const __m256d vSrc = _mm256_loadu_pd(src + i);
970 #if defined(DSPARK_SIMD_FMA)
971 _mm256_storeu_pd(dst + i, _mm256_fmadd_pd(vSrc, vGain, vDst));
973 _mm256_storeu_pd(dst + i, _mm256_add_pd(vDst, _mm256_mul_pd(vSrc, vGain)));
975 vGain = _mm256_add_pd(vGain, vStep);
977 for (; i < count; ++i) dst[i] += src[i] * (gainStart + step * static_cast<double>(i));
979#elif defined(DSPARK_SIMD_SSE2)
980 const __m128d vStep = _mm_set1_pd(step * 2.0);
981 __m128d vGain = _mm_setr_pd(gainStart, gainStart + step);
983 for (; i + 1 < count; i += 2)
985 const __m128d vDst = _mm_loadu_pd(dst + i);
986 const __m128d vSrc = _mm_loadu_pd(src + i);
987 #if defined(DSPARK_SIMD_FMA)
988 _mm_storeu_pd(dst + i, _mm_fmadd_pd(vSrc, vGain, vDst));
990 _mm_storeu_pd(dst + i, _mm_add_pd(vDst, _mm_mul_pd(vSrc, vGain)));
992 vGain = _mm_add_pd(vGain, vStep);
994 for (; i < count; ++i) dst[i] += src[i] * (gainStart + step * static_cast<double>(i));
996#elif defined(DSPARK_SIMD_NEON)
997 const float64x2_t vStep = vdupq_n_f64(step * 2.0);
998 const double init[2] = { gainStart, gainStart + step };
999 float64x2_t vGain = vld1q_f64(init);
1001 for (; i + 1 < count; i += 2)
1003 vst1q_f64(dst + i, vfmaq_f64(vld1q_f64(dst + i), vld1q_f64(src + i), vGain));
1004 vGain = vaddq_f64(vGain, vStep);
1006 for (; i < count; ++i) dst[i] += src[i] * (gainStart + step * static_cast<double>(i));
1009 for (
int i = 0; i < count; ++i) dst[i] += src[i] * (gainStart + step * static_cast<double>(i));
1042#if defined(DSPARK_SIMD_AVX)
1048 for (; k + 3 < bins; k += 4)
1050 const __m256 va = _mm256_loadu_ps(a + 2 * k);
1051 const __m256 vb = _mm256_loadu_ps(b + 2 * k);
1052 const __m256 vacc = _mm256_loadu_ps(accum + 2 * k);
1054 const __m256 aRe = _mm256_permute_ps(va, _MM_SHUFFLE(2, 2, 0, 0));
1055 const __m256 aIm = _mm256_permute_ps(va, _MM_SHUFFLE(3, 3, 1, 1));
1056 const __m256 bSwap = _mm256_permute_ps(vb, _MM_SHUFFLE(2, 3, 0, 1));
1058 #if defined(DSPARK_SIMD_FMA)
1059 const __m256 prod = _mm256_fmaddsub_ps(aRe, vb, _mm256_mul_ps(aIm, bSwap));
1061 const __m256 prod = _mm256_addsub_ps(_mm256_mul_ps(aRe, vb), _mm256_mul_ps(aIm, bSwap));
1064 _mm256_storeu_ps(accum + 2 * k, _mm256_add_ps(vacc, prod));
1066 for (; k < bins; ++k)
1068 const float re1 = a[2 * k], im1 = a[2 * k + 1];
1069 const float re2 = b[2 * k], im2 = b[2 * k + 1];
1070 accum[2 * k] += re1 * re2 - im1 * im2;
1071 accum[2 * k + 1] += re1 * im2 + im1 * re2;
1073#elif defined(DSPARK_SIMD_SSE2)
1075 const __m128 negMask = _mm_castsi128_ps(_mm_setr_epi32(
1076 static_cast<int>(0x80000000u), 0,
1077 static_cast<int>(0x80000000u), 0));
1080 for (; k + 1 < bins; k += 2)
1082 const __m128 va = _mm_loadu_ps(a + 2 * k);
1083 const __m128 vb = _mm_loadu_ps(b + 2 * k);
1084 __m128 vacc = _mm_loadu_ps(accum + 2 * k);
1086 const __m128 aRe = _mm_shuffle_ps(va, va, _MM_SHUFFLE(2, 2, 0, 0));
1087 const __m128 aIm = _mm_shuffle_ps(va, va, _MM_SHUFFLE(3, 3, 1, 1));
1088 const __m128 bSwap = _mm_shuffle_ps(vb, vb, _MM_SHUFFLE(2, 3, 0, 1));
1090 const __m128 p1 = _mm_mul_ps(aRe, vb);
1091 const __m128 p2 = _mm_xor_ps(_mm_mul_ps(aIm, bSwap), negMask);
1093 vacc = _mm_add_ps(vacc, _mm_add_ps(p1, p2));
1094 _mm_storeu_ps(accum + 2 * k, vacc);
1096 for (; k < bins; ++k)
1098 const float re1 = a[2 * k], im1 = a[2 * k + 1];
1099 const float re2 = b[2 * k], im2 = b[2 * k + 1];
1100 accum[2 * k] += re1 * re2 - im1 * im2;
1101 accum[2 * k + 1] += re1 * im2 + im1 * re2;
1103#elif defined(DSPARK_SIMD_NEON)
1104 alignas(16)
static constexpr uint32_t kNegRe[4] = { 0x80000000u, 0u, 0x80000000u, 0u };
1105 const uint32x4_t negMask = vld1q_u32(kNegRe);
1108 for (; k + 1 < bins; k += 2)
1110 const float32x4_t va = vld1q_f32(a + 2 * k);
1111 const float32x4_t vb = vld1q_f32(b + 2 * k);
1112 float32x4_t vacc = vld1q_f32(accum + 2 * k);
1114 const float32x4_t aRe = vtrn1q_f32(va, va);
1115 const float32x4_t aIm = vtrn2q_f32(va, va);
1116 const float32x4_t bSwap = vrev64q_f32(vb);
1118 const float32x4_t p1 = vmulq_f32(aRe, vb);
1119 const float32x4_t p2 = vreinterpretq_f32_u32(
1120 veorq_u32(vreinterpretq_u32_f32(vmulq_f32(aIm, bSwap)), negMask));
1122 vacc = vaddq_f32(vacc, vaddq_f32(p1, p2));
1123 vst1q_f32(accum + 2 * k, vacc);
1125 for (; k < bins; ++k)
1127 const float re1 = a[2 * k], im1 = a[2 * k + 1];
1128 const float re2 = b[2 * k], im2 = b[2 * k + 1];
1129 accum[2 * k] += re1 * re2 - im1 * im2;
1130 accum[2 * k + 1] += re1 * im2 + im1 * re2;
1133 for (
int k = 0; k < bins; ++k)
1135 const float re1 = a[2 * k], im1 = a[2 * k + 1];
1136 const float re2 = b[2 * k], im2 = b[2 * k + 1];
1137 accum[2 * k] += re1 * re2 - im1 * im2;
1138 accum[2 * k + 1] += re1 * im2 + im1 * re2;