Added a divide SIMD helper

This commit is contained in:
Paul Ferrand 2019-12-09 19:22:50 +01:00
parent 19c3eabb6c
commit 3a320914a5
4 changed files with 84 additions and 2 deletions

View file

@ -58,6 +58,7 @@ namespace SIMDConfig {
constexpr bool readInterleaved { true };
constexpr bool fill { true };
constexpr bool gain { false };
constexpr bool divide { false };
constexpr bool mathfuns { false };
constexpr bool loopingSFZIndex { true };
constexpr bool saturatingSFZIndex { true };

View file

@ -77,6 +77,12 @@ void sfz::applyGain<float, true>(absl::Span<const float> gain, absl::Span<const
applyGain<float, false>(gain, input, output);
}
template <>
void sfz::divide<float, true>(absl::Span<const float> input, absl::Span<const float> divisor, absl::Span<float> output) noexcept
{
divide<float, false>(input, divisor, output);
}
template <>
void sfz::multiplyAdd<float, true>(absl::Span<const float> gain, absl::Span<const float> input, absl::Span<float> output) noexcept
{
@ -173,4 +179,4 @@ template <>
void sfz::diff<float, true>(absl::Span<const float> input, absl::Span<float> output) noexcept
{
diff<float, false>(input, output);
}
}

View file

@ -457,6 +457,56 @@ void applyGain<float, true>(float gain, absl::Span<const float> input, absl::Spa
template <>
void applyGain<float, true>(absl::Span<const float> gain, absl::Span<const float> input, absl::Span<float> output) noexcept;
namespace _internals {
template <class T>
inline void snippetDivSpan(const T*& input, const T*& divisor,T*& output)
{
*output++ = (*input++) / (*divisor++);
}
}
/**
* @brief Divide a vector by another vector
*
* The output size will be the minimum of the divisor, input span and output span size.
*
* @tparam T the underlying type
* @tparam SIMD use the SIMD version or the scalar version
* @param input
* @param divisor
* @param output
*/
template <class T, bool SIMD = SIMDConfig::divide>
void divide(absl::Span<const T> input, absl::Span<const T> divisor, absl::Span<T> output) noexcept
{
ASSERT(divisor.size() == input.size());
ASSERT(input.size() <= output.size());
auto* in = input.begin();
auto* d = divisor.begin();
auto* out = output.begin();
auto* sentinel = out + std::min(divisor.size(), std::min(output.size(), input.size()));
while (out < sentinel)
_internals::snippetDivSpan<T>(in, d, out);
}
/**
* @brief Divide a vector by another in place
*
* @tparam T the underlying type
* @tparam SIMD use the SIMD version or the scalar version
* @param output
* @param divisor
*/
template <class T, bool SIMD = SIMDConfig::divide>
void divide(absl::Span<T> output, absl::Span<const T> divisor) noexcept
{
divide<T, SIMD>(output, divisor, output);
}
template <>
void divide<float, true>(absl::Span<const float> input, absl::Span<const float> divisor, absl::Span<float> output) noexcept;
namespace _internals {
template <class T>
inline void snippetMultiplyAdd(const T*& gain, const T*& input, T*& output)

View file

@ -305,6 +305,31 @@ void sfz::applyGain<float, true>(absl::Span<const float> gain, absl::Span<const
_internals::snippetGainSpan<float>(g, in, out);
}
template <>
void sfz::divide<float, true>(absl::Span<const float> input, absl::Span<const float> divisor, absl::Span<float> output) noexcept
{
auto* in = input.begin();
auto* out = output.begin();
auto* div = divisor.begin();
const auto size = std::min(output.size(), std::min(input.size(), divisor.size()));
const auto* lastAligned = prevAligned(output.begin() + size);
while (unaligned(out, in, div) && out < lastAligned)
_internals::snippetDivSpan<float>(in, div, out);
while (out < lastAligned) {
_mm_store_ps(out, _mm_div_ps(_mm_load_ps(in), _mm_load_ps(div)));
div += TypeAlignment;
in += TypeAlignment;
out += TypeAlignment;
}
while (out < output.end())
_internals::snippetDivSpan<float>(in, div, out);
}
template <>
void sfz::multiplyAdd<float, true>(absl::Span<const float> gain, absl::Span<const float> input, absl::Span<float> output) noexcept
{
@ -809,4 +834,4 @@ void sfz::diff<float, true>(absl::Span<const float> input, absl::Span<float> out
while (in < sentinel)
_internals::snippetDiff(in, out);
}
}