commit
f53074f223
10 changed files with 388 additions and 5 deletions
83
benchmarks/BM_multiplyMul.cpp
Normal file
83
benchmarks/BM_multiplyMul.cpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "SIMDHelpers.h"
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <random>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
class MultiplyMul : public benchmark::Fixture {
|
||||
public:
|
||||
void SetUp(const ::benchmark::State& state) {
|
||||
std::random_device rd { };
|
||||
std::mt19937 gen { rd() };
|
||||
std::uniform_real_distribution<float> dist { 0.1f, 1.0f };
|
||||
input = std::vector<float>(state.range(0));
|
||||
output = std::vector<float>(state.range(0));
|
||||
gain = std::vector<float>(state.range(0));
|
||||
std::fill(output.begin(), output.end(), 2.0f );
|
||||
std::generate(gain.begin(), gain.end(), [&]() { return dist(gen); });
|
||||
std::generate(input.begin(), input.end(), [&]() { return dist(gen); });
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& /* state */) {
|
||||
|
||||
}
|
||||
|
||||
std::vector<float> gain;
|
||||
std::vector<float> input;
|
||||
std::vector<float> output;
|
||||
};
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMul, Straight)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
for (int i = 0; i < state.range(0); ++i)
|
||||
output[i] *= gain[i] * input[i];
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMul, Scalar)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul, false);
|
||||
sfz::multiplyMul<float>(gain, input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMul, SIMD)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul, true);
|
||||
sfz::multiplyMul<float>(gain, input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMul, Scalar_Unaligned)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul, false);
|
||||
sfz::multiplyMul<float>(absl::MakeSpan(gain).subspan(1), absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMul, SIMD_Unaligned)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul, true);
|
||||
sfz::multiplyMul<float>(absl::MakeSpan(gain).subspan(1), absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(MultiplyMul, Straight)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMul, Scalar)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMul, SIMD)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMul, Scalar_Unaligned)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMul, SIMD_Unaligned)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_MAIN();
|
||||
88
benchmarks/BM_multiplyMulFixedGain.cpp
Normal file
88
benchmarks/BM_multiplyMulFixedGain.cpp
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "SIMDHelpers.h"
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <random>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
class MultiplyMulFixedGain : public benchmark::Fixture {
|
||||
public:
|
||||
void SetUp(const ::benchmark::State& state)
|
||||
{
|
||||
std::random_device rd {};
|
||||
std::mt19937 gen { rd() };
|
||||
std::uniform_real_distribution<float> dist { 0.1f, 1.0f };
|
||||
input = std::vector<float>(state.range(0));
|
||||
output = std::vector<float>(state.range(0));
|
||||
gain = dist(gen);
|
||||
std::fill(output.begin(), output.end(), 2.0f);
|
||||
std::generate(input.begin(), input.end(), [&]() { return dist(gen); });
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& /* state */)
|
||||
{
|
||||
}
|
||||
|
||||
float gain = {};
|
||||
std::vector<float> input;
|
||||
std::vector<float> output;
|
||||
};
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMulFixedGain, Straight)
|
||||
(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
for (int i = 0; i < state.range(0); ++i)
|
||||
output[i] *= gain * input[i];
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMulFixedGain, Scalar)
|
||||
(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul1, false);
|
||||
sfz::multiplyMul1<float>(gain, input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMulFixedGain, SIMD)
|
||||
(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul1, true);
|
||||
sfz::multiplyMul1<float>(gain, input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMulFixedGain, Scalar_Unaligned)
|
||||
(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul1, false);
|
||||
sfz::multiplyMul1<float>(gain, absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMulFixedGain, SIMD_Unaligned)
|
||||
(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul1, true);
|
||||
sfz::multiplyMul1<float>(gain, absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(MultiplyMulFixedGain, Straight)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMulFixedGain, Scalar)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMulFixedGain, SIMD)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMulFixedGain, Scalar_Unaligned)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMulFixedGain, SIMD_Unaligned)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_MAIN();
|
||||
|
|
@ -49,6 +49,8 @@ target_link_libraries(bm_ADSR PRIVATE sfizz::sfizz)
|
|||
sfizz_add_benchmark(bm_add BM_add.cpp)
|
||||
sfizz_add_benchmark(bm_multiplyAdd BM_multiplyAdd.cpp)
|
||||
sfizz_add_benchmark(bm_multiplyAddFixedGain BM_multiplyAddFixedGain.cpp)
|
||||
sfizz_add_benchmark(bm_multiplyMul BM_multiplyMul.cpp)
|
||||
sfizz_add_benchmark(bm_multiplyMulFixedGain BM_multiplyMulFixedGain.cpp)
|
||||
sfizz_add_benchmark(bm_subtract BM_subtract.cpp)
|
||||
sfizz_add_benchmark(bm_copy BM_copy.cpp)
|
||||
sfizz_add_benchmark(bm_mean BM_mean.cpp)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ struct SIMDDispatch {
|
|||
decltype(÷Scalar<T>) divide = ÷Scalar<T>;
|
||||
decltype(&multiplyAddScalar<T>) multiplyAdd = &multiplyAddScalar<T>;
|
||||
decltype(&multiplyAdd1Scalar<T>) multiplyAdd1 = &multiplyAdd1Scalar<T>;
|
||||
decltype(&multiplyMulScalar<T>) multiplyMul = &multiplyMulScalar<T>;
|
||||
decltype(&multiplyMul1Scalar<T>) multiplyMul1 = &multiplyMul1Scalar<T>;
|
||||
decltype(&linearRampScalar<T>) linearRamp = &linearRampScalar<T>;
|
||||
decltype(&multiplicativeRampScalar<T>) multiplicativeRamp = &multiplicativeRampScalar<T>;
|
||||
decltype(&addScalar<T>) add = &addScalar<T>;
|
||||
|
|
@ -81,6 +83,8 @@ void SIMDDispatch<float>::setStatus(SIMDOps op, bool enable)
|
|||
SIMD_OP(subtract1)
|
||||
SIMD_OP(multiplyAdd)
|
||||
SIMD_OP(multiplyAdd1)
|
||||
SIMD_OP(multiplyMul)
|
||||
SIMD_OP(multiplyMul1)
|
||||
SIMD_OP(copy)
|
||||
SIMD_OP(cumsum)
|
||||
SIMD_OP(diff)
|
||||
|
|
@ -118,6 +122,8 @@ void SIMDDispatch<float>::setStatus(SIMDOps op, bool enable)
|
|||
SIMD_OP(subtract1)
|
||||
SIMD_OP(multiplyAdd)
|
||||
SIMD_OP(multiplyAdd1)
|
||||
SIMD_OP(multiplyMul)
|
||||
SIMD_OP(multiplyMul1)
|
||||
SIMD_OP(copy)
|
||||
SIMD_OP(cumsum)
|
||||
SIMD_OP(diff)
|
||||
|
|
@ -158,6 +164,8 @@ void SIMDDispatch<float>::resetStatus()
|
|||
setStatus(SIMDOps::subtract1, false);
|
||||
setStatus(SIMDOps::multiplyAdd, false);
|
||||
setStatus(SIMDOps::multiplyAdd1, false);
|
||||
setStatus(SIMDOps::multiplyMul, false);
|
||||
setStatus(SIMDOps::multiplyMul1, false);
|
||||
setStatus(SIMDOps::copy, false);
|
||||
setStatus(SIMDOps::cumsum, true);
|
||||
setStatus(SIMDOps::diff, false);
|
||||
|
|
@ -243,6 +251,18 @@ void multiplyAdd1<float>(float gain, const float* input, float* output, unsigned
|
|||
return simdDispatch<float>().multiplyAdd1(gain, input, output, size);
|
||||
}
|
||||
|
||||
template <>
|
||||
void multiplyMul<float>(const float* gain, const float* input, float* output, unsigned size) noexcept
|
||||
{
|
||||
return simdDispatch<float>().multiplyMul(gain, input, output, size);
|
||||
}
|
||||
|
||||
template <>
|
||||
void multiplyMul1<float>(float gain, const float* input, float* output, unsigned size) noexcept
|
||||
{
|
||||
return simdDispatch<float>().multiplyMul1(gain, input, output, size);
|
||||
}
|
||||
|
||||
template <>
|
||||
float linearRamp<float>(float* output, float start, float step, unsigned size) noexcept
|
||||
{
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ enum class SIMDOps {
|
|||
subtract1,
|
||||
multiplyAdd,
|
||||
multiplyAdd1,
|
||||
multiplyMul,
|
||||
multiplyMul1,
|
||||
copy,
|
||||
cumsum,
|
||||
diff,
|
||||
|
|
@ -322,6 +324,56 @@ void multiplyAdd1(T gain, absl::Span<const T> input, absl::Span<T> output) noexc
|
|||
multiplyAdd1<T>(gain, input.data(), output.data(), minSpanSize(input, output));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Applies a gain to the input and multiply the output with it
|
||||
*
|
||||
* @tparam T the underlying type
|
||||
* @param gain
|
||||
* @param input
|
||||
* @param output
|
||||
* @param size
|
||||
*/
|
||||
template <class T>
|
||||
void multiplyMul(const T* gain, const T* input, T* output, unsigned size) noexcept
|
||||
{
|
||||
multiplyMulScalar(gain, input, output, size);
|
||||
}
|
||||
|
||||
template <>
|
||||
void multiplyMul<float>(const float* gain, const float* input, float* output, unsigned size) noexcept;
|
||||
|
||||
template <class T>
|
||||
void multiplyMul(absl::Span<const T> gain, absl::Span<const T> input, absl::Span<T> output) noexcept
|
||||
{
|
||||
CHECK_SPAN_SIZES(gain, input, output);
|
||||
multiplyMul<T>(gain.data(), input.data(), output.data(), minSpanSize(gain, input, output));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Applies a fixed gain to the input and multiply the output with it
|
||||
*
|
||||
* @tparam T the underlying type
|
||||
* @param gain
|
||||
* @param input
|
||||
* @param output
|
||||
* @param size
|
||||
*/
|
||||
template <class T>
|
||||
void multiplyMul1(T gain, const T* input, T* output, unsigned size) noexcept
|
||||
{
|
||||
multiplyMul1Scalar(gain, input, output, size);
|
||||
}
|
||||
|
||||
template <>
|
||||
void multiplyMul1<float>(float gain, const float* input, float* output, unsigned size) noexcept;
|
||||
|
||||
template <class T>
|
||||
void multiplyMul1(T gain, absl::Span<const T> input, absl::Span<T> output) noexcept
|
||||
{
|
||||
CHECK_SPAN_SIZES(input, output);
|
||||
multiplyMul1<T>(gain, input.data(), output.data(), minSpanSize(input, output));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute a linear ramp blockwise between 2 values
|
||||
*
|
||||
|
|
|
|||
|
|
@ -355,16 +355,14 @@ float* ModMatrix::getModulation(TargetId targetId)
|
|||
}
|
||||
else {
|
||||
if (targetFlags & kModIsMultiplicative) {
|
||||
for (uint32_t i = 0; i < numFrames; ++i)
|
||||
buffer[i] *= sourceDepth * sourceBuffer[i];
|
||||
multiplyMul1<float>(sourceDepth, sourceBuffer, buffer);
|
||||
}
|
||||
else if (targetFlags & kModIsPercentMultiplicative) {
|
||||
for (uint32_t i = 0; i < numFrames; ++i)
|
||||
buffer[i] *= (0.01f * sourceDepth) * sourceBuffer[i];
|
||||
multiplyMul1<float>(0.01f * sourceDepth, sourceBuffer, buffer);
|
||||
}
|
||||
else {
|
||||
ASSERT(targetFlags & kModIsAdditive);
|
||||
sfz::multiplyAdd1<float>(sourceDepth, sourceBuffer, buffer);
|
||||
multiplyAdd1<float>(sourceDepth, sourceBuffer, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,6 +183,49 @@ void multiplyAdd1SSE(float gain, const float* input, float* output, unsigned siz
|
|||
*output++ += gain * (*input++);
|
||||
}
|
||||
|
||||
void multiplyMulSSE(const float* gain, const float* input, float* output, unsigned size) noexcept
|
||||
{
|
||||
const auto sentinel = output + size;
|
||||
|
||||
#if SFIZZ_HAVE_SSE2
|
||||
const auto* lastAligned = prevAligned<ByteAlignment>(sentinel);
|
||||
while (unaligned<ByteAlignment>(input, output) && output < lastAligned)
|
||||
*output++ *= (*gain++) * (*input++);
|
||||
|
||||
while (output < lastAligned) {
|
||||
auto mmOut = _mm_load_ps(output);
|
||||
mmOut = _mm_mul_ps(_mm_mul_ps(_mm_load_ps(gain), _mm_load_ps(input)), mmOut);
|
||||
_mm_store_ps(output, mmOut);
|
||||
incrementAll<TypeAlignment>(gain, input, output);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (output < sentinel)
|
||||
*output++ *= (*gain++) * (*input++);
|
||||
}
|
||||
|
||||
void multiplyMul1SSE(float gain, const float* input, float* output, unsigned size) noexcept
|
||||
{
|
||||
const auto sentinel = output + size;
|
||||
|
||||
#if SFIZZ_HAVE_SSE2
|
||||
const auto* lastAligned = prevAligned<ByteAlignment>(sentinel);
|
||||
while (unaligned<ByteAlignment>(input, output) && output < lastAligned)
|
||||
*output++ *= gain * (*input++);
|
||||
|
||||
auto mmGain = _mm_set1_ps(gain);
|
||||
while (output < lastAligned) {
|
||||
auto mmOut = _mm_load_ps(output);
|
||||
mmOut = _mm_mul_ps(_mm_mul_ps(mmGain, _mm_load_ps(input)), mmOut);
|
||||
_mm_store_ps(output, mmOut);
|
||||
incrementAll<TypeAlignment>(input, output);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (output < sentinel)
|
||||
*output++ *= gain * (*input++);
|
||||
}
|
||||
|
||||
float linearRampSSE(float* output, float start, float step, unsigned size) noexcept
|
||||
{
|
||||
const auto sentinel = output + size;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ void gain1SSE(float gain, const float* input, float* output, unsigned size) noex
|
|||
void divideSSE(const float* input, const float* divisor, float* output, unsigned size) noexcept;
|
||||
void multiplyAddSSE(const float* gain, const float* input, float* output, unsigned size) noexcept;
|
||||
void multiplyAdd1SSE(float gain, const float* input, float* output, unsigned size) noexcept;
|
||||
void multiplyMulSSE(const float* gain, const float* input, float* output, unsigned size) noexcept;
|
||||
void multiplyMul1SSE(float gain, const float* input, float* output, unsigned size) noexcept;
|
||||
float linearRampSSE(float* output, float start, float step, unsigned size) noexcept;
|
||||
float multiplicativeRampSSE(float* output, float start, float step, unsigned size) noexcept;
|
||||
void addSSE(const float* input, float* output, unsigned size) noexcept;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,22 @@ inline void multiplyAdd1Scalar(T gain, const T* input, T* output, unsigned size)
|
|||
*output++ += gain * (*input++);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void multiplyMulScalar(const T* gain, const T* input, T* output, unsigned size) noexcept
|
||||
{
|
||||
const auto sentinel = output + size;
|
||||
while (output < sentinel)
|
||||
*output++ *= (*gain++) * (*input++);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void multiplyMul1Scalar(T gain, const T* input, T* output, unsigned size) noexcept
|
||||
{
|
||||
const auto sentinel = output + size;
|
||||
while (output < sentinel)
|
||||
*output++ *= gain * (*input++);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T linearRampScalar(T* output, T start, T step, unsigned size) noexcept
|
||||
{
|
||||
|
|
|
|||
|
|
@ -517,6 +517,7 @@ TEST_CASE("[Helpers] MultiplyAdd (SIMD)")
|
|||
REQUIRE(output == expected);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("[Helpers] MultiplyAdd (SIMD vs scalar)")
|
||||
{
|
||||
std::vector<float> gain(bigBufferSize);
|
||||
|
|
@ -574,6 +575,84 @@ TEST_CASE("[Helpers] MultiplyAdd fixed gain (SIMD vs scalar)")
|
|||
REQUIRE(approxEqual<float>(outputScalar, outputSIMD));
|
||||
}
|
||||
|
||||
TEST_CASE("[Helpers] MultiplyMul (Scalar)")
|
||||
{
|
||||
std::array<float, 5> gain { 0.0f, 0.1f, 0.2f, 0.3f, 0.4f };
|
||||
std::array<float, 5> input { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
|
||||
std::array<float, 5> output { 5.0f, 4.0f, 3.0f, 2.0f, 1.0f };
|
||||
std::array<float, 5> expected { 0.0f, 0.8f, 1.8f, 2.4f, 2.0f };
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul, true);
|
||||
sfz::multiplyMul<float>(gain, input, absl::MakeSpan(output));
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
}
|
||||
|
||||
TEST_CASE("[Helpers] MultiplyMul (SIMD)")
|
||||
{
|
||||
std::array<float, 5> gain { 0.0f, 0.1f, 0.2f, 0.3f, 0.4f };
|
||||
std::array<float, 5> input { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
|
||||
std::array<float, 5> output { 5.0f, 4.0f, 3.0f, 2.0f, 1.0f };
|
||||
std::array<float, 5> expected { 0.0f, 0.8f, 1.8f, 2.4f, 2.0f };
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul, true);
|
||||
sfz::multiplyMul<float>(gain, input, absl::MakeSpan(output));
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
}
|
||||
|
||||
TEST_CASE("[Helpers] MultiplyMul (SIMD vs Scalar)")
|
||||
{
|
||||
std::vector<float> gain(bigBufferSize);
|
||||
std::vector<float> input(bigBufferSize);
|
||||
std::vector<float> outputScalar(bigBufferSize);
|
||||
std::vector<float> outputSIMD(bigBufferSize);
|
||||
absl::c_iota(gain, 0.0f);
|
||||
absl::c_iota(input, 0.0f);
|
||||
absl::c_iota(outputScalar, 0.0f);
|
||||
absl::c_iota(outputSIMD, 0.0f);
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul, false);
|
||||
sfz::multiplyMul<float>(gain, input, absl::MakeSpan(outputScalar));
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul, true);
|
||||
sfz::multiplyMul<float>(gain, input, absl::MakeSpan(outputSIMD));
|
||||
REQUIRE(approxEqual<float>(outputScalar, outputSIMD));
|
||||
}
|
||||
|
||||
TEST_CASE("[Helpers] MultiplyMul fixed gain (Scalar)")
|
||||
{
|
||||
float gain = 0.3f;
|
||||
std::array<float, 5> input { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
|
||||
std::array<float, 5> output { 5.0f, 4.0f, 3.0f, 2.0f, 1.0f };
|
||||
std::array<float, 5> expected { 1.5f, 2.4f, 2.7f, 2.4f, 1.5f };
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul1, false);
|
||||
sfz::multiplyMul1<float>(gain, input, absl::MakeSpan(output));
|
||||
REQUIRE(output == expected);
|
||||
}
|
||||
|
||||
TEST_CASE("[Helpers] MultiplyMul fixed gain (SIMD)")
|
||||
{
|
||||
float gain = 0.3f;
|
||||
std::array<float, 5> input { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
|
||||
std::array<float, 5> output { 5.0f, 4.0f, 3.0f, 2.0f, 1.0f };
|
||||
std::array<float, 5> expected { 1.5f, 2.4f, 2.7f, 2.4f, 1.5f };
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul1, true);
|
||||
sfz::multiplyMul1<float>(gain, input, absl::MakeSpan(output));
|
||||
REQUIRE(output == expected);
|
||||
}
|
||||
|
||||
TEST_CASE("[Helpers] MultiplyMul fixed gain (SIMD vs scalar)")
|
||||
{
|
||||
float gain = 0.3f;
|
||||
std::vector<float> input(bigBufferSize);
|
||||
std::vector<float> outputScalar(bigBufferSize);
|
||||
std::vector<float> outputSIMD(bigBufferSize);
|
||||
absl::c_iota(input, 0.0f);
|
||||
absl::c_iota(outputScalar, 0.0f);
|
||||
absl::c_iota(outputSIMD, 0.0f);
|
||||
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul1, false);
|
||||
sfz::multiplyMul1<float>(gain, input, absl::MakeSpan(outputScalar));
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul1, true);
|
||||
sfz::multiplyMul1<float>(gain, input, absl::MakeSpan(outputSIMD));
|
||||
REQUIRE(approxEqual<float>(outputScalar, outputSIMD));
|
||||
}
|
||||
|
||||
TEST_CASE("[Helpers] Subtract")
|
||||
{
|
||||
std::array<float, 5> input { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue