/* ============================================================================== This file is part of the JUCE library. Copyright (c) 2022 - Raw Material Software Limited JUCE is an open source library subject to commercial or open-source licensing. By using JUCE, you agree to the terms of both the JUCE 7 End-User License Agreement and JUCE Privacy Policy. End User License Agreement: www.juce.com/juce-7-licence Privacy Policy: www.juce.com/juce-privacy-policy Or: You may also use this code under the terms of the GPL v3 (see www.gnu.org/licenses). JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE DISCLAIMED. ============================================================================== */ namespace juce { namespace dsp { //============================================================================== template struct SIMDRegister::ElementAccess { ElementAccess (const ElementAccess&) = default; operator Type() const { return simd.get (idx); } ElementAccess& operator= (Type scalar) noexcept { simd.set (idx, scalar); return *this; } ElementAccess& operator= (const ElementAccess& o) noexcept { return operator= ((Type) o); } private: friend struct SIMDRegister; ElementAccess (SIMDRegister& owner, size_t index) noexcept : simd (owner), idx (index) {} SIMDRegister& simd; size_t idx; }; #ifndef DOXYGEN //============================================================================== /* This class is used internally by SIMDRegister to abstract away differences in operations which are different for complex and pure floating point types. */ // the pure floating-point version template struct CmplxSIMDOps { using vSIMDType = typename SIMDNativeOps::vSIMDType; static vSIMDType JUCE_VECTOR_CALLTYPE load (const Scalar* a) noexcept { return SIMDNativeOps::load (a); } static void JUCE_VECTOR_CALLTYPE store (vSIMDType value, Scalar* dest) noexcept { SIMDNativeOps::store (value, dest); } static vSIMDType JUCE_VECTOR_CALLTYPE expand (Scalar s) noexcept { return SIMDNativeOps::expand (s); } static Scalar JUCE_VECTOR_CALLTYPE get (vSIMDType v, std::size_t i) noexcept { return SIMDNativeOps::get (v, i); } static vSIMDType JUCE_VECTOR_CALLTYPE set (vSIMDType v, std::size_t i, Scalar s) noexcept { return SIMDNativeOps::set (v, i, s); } static Scalar JUCE_VECTOR_CALLTYPE sum (vSIMDType a) noexcept { return SIMDNativeOps::sum (a); } static vSIMDType JUCE_VECTOR_CALLTYPE mul (vSIMDType a, vSIMDType b) noexcept { return SIMDNativeOps::mul (a, b); } static vSIMDType JUCE_VECTOR_CALLTYPE muladd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return SIMDNativeOps::multiplyAdd (a, b, c); } }; // The pure complex version template struct CmplxSIMDOps> { using vSIMDType = typename SIMDNativeOps::vSIMDType; static vSIMDType JUCE_VECTOR_CALLTYPE load (const std::complex* a) noexcept { return SIMDNativeOps::load (reinterpret_cast (a)); } static void JUCE_VECTOR_CALLTYPE store (vSIMDType value, std::complex* dest) noexcept { SIMDNativeOps::store (value, reinterpret_cast (dest)); } static vSIMDType JUCE_VECTOR_CALLTYPE expand (std::complex s) noexcept { const int n = sizeof (vSIMDType) / sizeof (Scalar); union { vSIMDType v; Scalar floats[(size_t) n]; } u; for (int i = 0; i < n; ++i) u.floats[i] = (i & 1) == 0 ? s.real() : s.imag(); return u.v; } static std::complex JUCE_VECTOR_CALLTYPE get (vSIMDType v, std::size_t i) noexcept { auto j = i << 1; return std::complex (SIMDNativeOps::get (v, j), SIMDNativeOps::get (v, j + 1)); } static vSIMDType JUCE_VECTOR_CALLTYPE set (vSIMDType v, std::size_t i, std::complex s) noexcept { auto j = i << 1; return SIMDNativeOps::set (SIMDNativeOps::set (v, j, s.real()), j + 1, s.imag()); } static std::complex JUCE_VECTOR_CALLTYPE sum (vSIMDType a) noexcept { vSIMDType result = SIMDNativeOps::oddevensum (a); auto* ptr = reinterpret_cast (&result); return std::complex (ptr[0], ptr[1]); } static vSIMDType JUCE_VECTOR_CALLTYPE mul (vSIMDType a, vSIMDType b) noexcept { return SIMDNativeOps::cmplxmul (a, b); } static vSIMDType JUCE_VECTOR_CALLTYPE muladd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return SIMDNativeOps::add (a, SIMDNativeOps::cmplxmul (b, c)); } }; #endif //============================================================================== namespace util { template inline void snapToZero (SIMDRegister&) noexcept {} } } // namespace dsp // Extend some common used global functions to SIMDRegister types template inline dsp::SIMDRegister JUCE_VECTOR_CALLTYPE jmin (dsp::SIMDRegister a, dsp::SIMDRegister b) { return dsp::SIMDRegister::min (a, b); } template inline dsp::SIMDRegister JUCE_VECTOR_CALLTYPE jmax (dsp::SIMDRegister a, dsp::SIMDRegister b) { return dsp::SIMDRegister::max (a, b); } } // namespace juce