The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
5.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. namespace juce
  20. {
  21. namespace dsp
  22. {
  23. //==============================================================================
  24. template <typename Type>
  25. struct SIMDRegister<Type>::ElementAccess
  26. {
  27. operator Type() const { return simd.get (idx); }
  28. ElementAccess& operator= (Type scalar) noexcept { simd.set (idx, scalar); return *this; }
  29. ElementAccess& operator= (ElementAccess& o) noexcept { return operator= ((Type) o); }
  30. private:
  31. friend struct SIMDRegister;
  32. ElementAccess (SIMDRegister& owner, size_t index) noexcept : simd (owner), idx (index) {}
  33. SIMDRegister& simd;
  34. size_t idx;
  35. };
  36. //==============================================================================
  37. /* This class is used internally by SIMDRegister to abstract away differences
  38. in operations which are different for complex and pure floating point types. */
  39. // the pure floating-point version
  40. template <typename Scalar>
  41. struct CmplxSIMDOps
  42. {
  43. typedef typename SIMDNativeOps<Scalar>::vSIMDType vSIMDType;
  44. static inline vSIMDType JUCE_VECTOR_CALLTYPE load (const Scalar* a) noexcept
  45. {
  46. return SIMDNativeOps<Scalar>::load (a);
  47. }
  48. static inline void JUCE_VECTOR_CALLTYPE store (vSIMDType value, Scalar* dest) noexcept
  49. {
  50. SIMDNativeOps<Scalar>::store (value, dest);
  51. }
  52. static inline vSIMDType JUCE_VECTOR_CALLTYPE expand (Scalar s) noexcept
  53. {
  54. return SIMDNativeOps<Scalar>::expand (s);
  55. }
  56. static inline Scalar JUCE_VECTOR_CALLTYPE get (vSIMDType v, std::size_t i) noexcept
  57. {
  58. return SIMDNativeOps<Scalar>::get (v, i);
  59. }
  60. static inline vSIMDType JUCE_VECTOR_CALLTYPE set (vSIMDType v, std::size_t i, Scalar s) noexcept
  61. {
  62. return SIMDNativeOps<Scalar>::set (v, i, s);
  63. }
  64. static inline Scalar JUCE_VECTOR_CALLTYPE sum (vSIMDType a) noexcept
  65. {
  66. return SIMDNativeOps<Scalar>::sum (a);
  67. }
  68. static inline vSIMDType JUCE_VECTOR_CALLTYPE mul (vSIMDType a, vSIMDType b) noexcept
  69. {
  70. return SIMDNativeOps<Scalar>::mul (a, b);
  71. }
  72. static inline vSIMDType JUCE_VECTOR_CALLTYPE muladd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept
  73. {
  74. return SIMDNativeOps<Scalar>::multiplyAdd (a, b, c);
  75. }
  76. };
  77. // The pure complex version
  78. template <typename Scalar>
  79. struct CmplxSIMDOps<std::complex<Scalar>>
  80. {
  81. typedef typename SIMDNativeOps<Scalar>::vSIMDType vSIMDType;
  82. static inline vSIMDType JUCE_VECTOR_CALLTYPE load (const std::complex<Scalar>* a) noexcept
  83. {
  84. return SIMDNativeOps<Scalar>::load (reinterpret_cast<const Scalar*> (a));
  85. }
  86. static inline void JUCE_VECTOR_CALLTYPE store (vSIMDType value, std::complex<Scalar>* dest) noexcept
  87. {
  88. SIMDNativeOps<Scalar>::store (value, reinterpret_cast<Scalar*> (dest));
  89. }
  90. static inline vSIMDType JUCE_VECTOR_CALLTYPE expand (std::complex<Scalar> s) noexcept
  91. {
  92. const int n = sizeof (vSIMDType) / sizeof (Scalar);
  93. union
  94. {
  95. vSIMDType v;
  96. Scalar floats[n];
  97. } u;
  98. for (int i = 0; i < n; ++i)
  99. u.floats[i] = (i & 1) == 0 ? s.real() : s.imag();
  100. return u.v;
  101. }
  102. static inline std::complex<Scalar> JUCE_VECTOR_CALLTYPE get (vSIMDType v, std::size_t i) noexcept
  103. {
  104. auto j = i << 1;
  105. return std::complex<Scalar> (SIMDNativeOps<Scalar>::get (v, j), SIMDNativeOps<Scalar>::get (v, j + 1));
  106. }
  107. static inline vSIMDType JUCE_VECTOR_CALLTYPE set (vSIMDType v, std::size_t i, std::complex<Scalar> s) noexcept
  108. {
  109. auto j = i << 1;
  110. return SIMDNativeOps<Scalar>::set (SIMDNativeOps<Scalar>::set (v, j, s.real()), j + 1, s.imag());
  111. }
  112. static inline std::complex<Scalar> JUCE_VECTOR_CALLTYPE sum (vSIMDType a) noexcept
  113. {
  114. vSIMDType result = SIMDNativeOps<Scalar>::oddevensum (a);
  115. auto* ptr = reinterpret_cast<const Scalar*> (&result);
  116. return std::complex<Scalar> (ptr[0], ptr[1]);
  117. }
  118. static inline vSIMDType JUCE_VECTOR_CALLTYPE mul (vSIMDType a, vSIMDType b) noexcept
  119. {
  120. return SIMDNativeOps<Scalar>::cmplxmul (a, b);
  121. }
  122. static inline vSIMDType JUCE_VECTOR_CALLTYPE muladd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept
  123. {
  124. return SIMDNativeOps<Scalar>::add (a, SIMDNativeOps<Scalar>::cmplxmul (b, c));
  125. }
  126. };
  127. //==============================================================================
  128. namespace util
  129. {
  130. template <typename Type>
  131. inline void snapToZero (SIMDRegister<Type>&) noexcept {}
  132. }
  133. } // namespace dsp
  134. // Extend some common used global functions to SIMDRegister types
  135. template <typename Type>
  136. inline dsp::SIMDRegister<Type> JUCE_VECTOR_CALLTYPE jmin (dsp::SIMDRegister<Type> a, dsp::SIMDRegister<Type> b) { return dsp::SIMDRegister<Type>::min (a, b); }
  137. template <typename Type>
  138. inline dsp::SIMDRegister<Type> JUCE_VECTOR_CALLTYPE jmax (dsp::SIMDRegister<Type> a, dsp::SIMDRegister<Type> b) { return dsp::SIMDRegister<Type>::max (a, b); }
  139. } // namespace juce