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.

1099 lines
47KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. namespace FloatVectorHelpers
  18. {
  19. #define JUCE_INCREMENT_SRC_DEST dest += (16 / sizeof (*dest)); src += (16 / sizeof (*dest));
  20. #define JUCE_INCREMENT_SRC1_SRC2_DEST dest += (16 / sizeof (*dest)); src1 += (16 / sizeof (*dest)); src2 += (16 / sizeof (*dest));
  21. #define JUCE_INCREMENT_DEST dest += (16 / sizeof (*dest));
  22. #if JUCE_USE_SSE_INTRINSICS
  23. static bool sse2Present = false;
  24. static bool isSSE2Available() noexcept
  25. {
  26. if (sse2Present)
  27. return true;
  28. sse2Present = SystemStats::hasSSE2();
  29. return sse2Present;
  30. }
  31. inline static bool isAligned (const void* p) noexcept
  32. {
  33. return (((pointer_sized_int) p) & 15) == 0;
  34. }
  35. struct BasicOps32
  36. {
  37. typedef float Type;
  38. typedef __m128 ParallelType;
  39. enum { numParallel = 4 };
  40. static forcedinline ParallelType load1 (Type v) noexcept { return _mm_load1_ps (&v); }
  41. static forcedinline ParallelType loadA (const Type* v) noexcept { return _mm_load_ps (v); }
  42. static forcedinline ParallelType loadU (const Type* v) noexcept { return _mm_loadu_ps (v); }
  43. static forcedinline void storeA (Type* dest, ParallelType a) noexcept { _mm_store_ps (dest, a); }
  44. static forcedinline void storeU (Type* dest, ParallelType a) noexcept { _mm_storeu_ps (dest, a); }
  45. static forcedinline ParallelType add (ParallelType a, ParallelType b) noexcept { return _mm_add_ps (a, b); }
  46. static forcedinline ParallelType sub (ParallelType a, ParallelType b) noexcept { return _mm_sub_ps (a, b); }
  47. static forcedinline ParallelType mul (ParallelType a, ParallelType b) noexcept { return _mm_mul_ps (a, b); }
  48. static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return _mm_max_ps (a, b); }
  49. static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return _mm_min_ps (a, b); }
  50. static forcedinline ParallelType bit_and (ParallelType a, ParallelType b) noexcept { return _mm_and_ps (a, b); }
  51. static forcedinline ParallelType bit_not (ParallelType a, ParallelType b) noexcept { return _mm_andnot_ps (a, b); }
  52. static forcedinline ParallelType bit_or (ParallelType a, ParallelType b) noexcept { return _mm_or_ps (a, b); }
  53. static forcedinline ParallelType bit_xor (ParallelType a, ParallelType b) noexcept { return _mm_xor_ps (a, b); }
  54. static forcedinline Type max (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmax (v[0], v[1], v[2], v[3]); }
  55. static forcedinline Type min (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmin (v[0], v[1], v[2], v[3]); }
  56. };
  57. struct BasicOps64
  58. {
  59. typedef double Type;
  60. typedef __m128d ParallelType;
  61. enum { numParallel = 2 };
  62. static forcedinline ParallelType load1 (Type v) noexcept { return _mm_load1_pd (&v); }
  63. static forcedinline ParallelType loadA (const Type* v) noexcept { return _mm_load_pd (v); }
  64. static forcedinline ParallelType loadU (const Type* v) noexcept { return _mm_loadu_pd (v); }
  65. static forcedinline void storeA (Type* dest, ParallelType a) noexcept { _mm_store_pd (dest, a); }
  66. static forcedinline void storeU (Type* dest, ParallelType a) noexcept { _mm_storeu_pd (dest, a); }
  67. static forcedinline ParallelType add (ParallelType a, ParallelType b) noexcept { return _mm_add_pd (a, b); }
  68. static forcedinline ParallelType sub (ParallelType a, ParallelType b) noexcept { return _mm_sub_pd (a, b); }
  69. static forcedinline ParallelType mul (ParallelType a, ParallelType b) noexcept { return _mm_mul_pd (a, b); }
  70. static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return _mm_max_pd (a, b); }
  71. static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return _mm_min_pd (a, b); }
  72. static forcedinline ParallelType bit_and (ParallelType a, ParallelType b) noexcept { return _mm_and_pd (a, b); }
  73. static forcedinline ParallelType bit_not (ParallelType a, ParallelType b) noexcept { return _mm_andnot_pd (a, b); }
  74. static forcedinline ParallelType bit_or (ParallelType a, ParallelType b) noexcept { return _mm_or_pd (a, b); }
  75. static forcedinline ParallelType bit_xor (ParallelType a, ParallelType b) noexcept { return _mm_xor_pd (a, b); }
  76. static forcedinline Type max (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmax (v[0], v[1]); }
  77. static forcedinline Type min (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmin (v[0], v[1]); }
  78. };
  79. #define JUCE_BEGIN_VEC_OP \
  80. typedef FloatVectorHelpers::ModeType<sizeof(*dest)>::Mode Mode; \
  81. if (FloatVectorHelpers::isSSE2Available()) \
  82. { \
  83. const int numLongOps = num / Mode::numParallel;
  84. #define JUCE_FINISH_VEC_OP(normalOp) \
  85. num &= (Mode::numParallel - 1); \
  86. if (num == 0) return; \
  87. } \
  88. for (int i = 0; i < num; ++i) normalOp;
  89. #define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp) \
  90. JUCE_BEGIN_VEC_OP \
  91. setupOp \
  92. if (FloatVectorHelpers::isAligned (dest)) JUCE_VEC_LOOP (vecOp, dummy, Mode::loadA, Mode::storeA, locals, JUCE_INCREMENT_DEST) \
  93. else JUCE_VEC_LOOP (vecOp, dummy, Mode::loadU, Mode::storeU, locals, JUCE_INCREMENT_DEST) \
  94. JUCE_FINISH_VEC_OP (normalOp)
  95. #define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp) \
  96. JUCE_BEGIN_VEC_OP \
  97. setupOp \
  98. if (FloatVectorHelpers::isAligned (dest)) \
  99. { \
  100. if (FloatVectorHelpers::isAligned (src)) JUCE_VEC_LOOP (vecOp, Mode::loadA, Mode::loadA, Mode::storeA, locals, increment) \
  101. else JUCE_VEC_LOOP (vecOp, Mode::loadU, Mode::loadA, Mode::storeA, locals, increment) \
  102. }\
  103. else \
  104. { \
  105. if (FloatVectorHelpers::isAligned (src)) JUCE_VEC_LOOP (vecOp, Mode::loadA, Mode::loadU, Mode::storeU, locals, increment) \
  106. else JUCE_VEC_LOOP (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
  107. } \
  108. JUCE_FINISH_VEC_OP (normalOp)
  109. #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
  110. JUCE_BEGIN_VEC_OP \
  111. setupOp \
  112. { \
  113. Mode::ParallelType (&loadSrc1) (const Mode::Type* v) = FloatVectorHelpers::isAligned (src1) ? Mode::loadA : Mode::loadU; \
  114. Mode::ParallelType (&loadSrc2) (const Mode::Type* v) = FloatVectorHelpers::isAligned (src2) ? Mode::loadA : Mode::loadU; \
  115. void (&storeDst) (Mode::Type* dest, Mode::ParallelType a) = FloatVectorHelpers::isAligned (dest) ? Mode::storeA : Mode::storeU; \
  116. JUCE_VEC_LOOP_TWO_SOURCES (vecOp, loadSrc1, loadSrc2, storeDst, locals, increment); \
  117. } \
  118. JUCE_FINISH_VEC_OP (normalOp)
  119. #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp) \
  120. JUCE_BEGIN_VEC_OP \
  121. setupOp \
  122. { \
  123. Mode::ParallelType (&loadSrc1) (const Mode::Type* v) = FloatVectorHelpers::isAligned (src1) ? Mode::loadA : Mode::loadU; \
  124. Mode::ParallelType (&loadSrc2) (const Mode::Type* v) = FloatVectorHelpers::isAligned (src2) ? Mode::loadA : Mode::loadU; \
  125. Mode::ParallelType (&loadDst) (const Mode::Type* v) = FloatVectorHelpers::isAligned (dest) ? Mode::loadA : Mode::loadU; \
  126. void (&storeDst) (Mode::Type* dest, Mode::ParallelType a) = FloatVectorHelpers::isAligned (dest) ? Mode::storeA : Mode::storeU; \
  127. JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, loadSrc1, loadSrc2, loadDst, storeDst, locals, increment); \
  128. } \
  129. JUCE_FINISH_VEC_OP (normalOp)
  130. //==============================================================================
  131. #elif JUCE_USE_ARM_NEON
  132. struct BasicOps32
  133. {
  134. typedef float Type;
  135. typedef float32x4_t ParallelType;
  136. enum { numParallel = 4 };
  137. static forcedinline ParallelType load1 (Type v) noexcept { return vld1q_dup_f32 (&v); }
  138. static forcedinline ParallelType loadA (const Type* v) noexcept { return vld1q_f32 (v); }
  139. static forcedinline ParallelType loadU (const Type* v) noexcept { return vld1q_f32 (v); }
  140. static forcedinline void storeA (Type* dest, ParallelType a) noexcept { vst1q_f32 (dest, a); }
  141. static forcedinline void storeU (Type* dest, ParallelType a) noexcept { vst1q_f32 (dest, a); }
  142. static forcedinline ParallelType add (ParallelType a, ParallelType b) noexcept { return vaddq_f32 (a, b); }
  143. static forcedinline ParallelType sub (ParallelType a, ParallelType b) noexcept { return vsubq_f32 (a, b); }
  144. static forcedinline ParallelType mul (ParallelType a, ParallelType b) noexcept { return vmulq_f32 (a, b); }
  145. static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return vmaxq_f32 (a, b); }
  146. static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return vminq_f32 (a, b); }
  147. static forcedinline Type max (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmax (v[0], v[1], v[2], v[3]); }
  148. static forcedinline Type min (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmin (v[0], v[1], v[2], v[3]); }
  149. };
  150. struct BasicOps64
  151. {
  152. typedef double Type;
  153. typedef double ParallelType;
  154. enum { numParallel = 1 };
  155. static forcedinline ParallelType load1 (Type v) noexcept { return v; }
  156. static forcedinline ParallelType loadA (const Type* v) noexcept { return *v; }
  157. static forcedinline ParallelType loadU (const Type* v) noexcept { return *v; }
  158. static forcedinline void storeA (Type* dest, ParallelType a) noexcept { *dest = a; }
  159. static forcedinline void storeU (Type* dest, ParallelType a) noexcept { *dest = a; }
  160. static forcedinline ParallelType add (ParallelType a, ParallelType b) noexcept { return a + b; }
  161. static forcedinline ParallelType sub (ParallelType a, ParallelType b) noexcept { return a - b; }
  162. static forcedinline ParallelType mul (ParallelType a, ParallelType b) noexcept { return a * b; }
  163. static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return jmax (a, b); }
  164. static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return jmin (a, b); }
  165. static forcedinline Type max (ParallelType a) noexcept { return a; }
  166. static forcedinline Type min (ParallelType a) noexcept { return a; }
  167. };
  168. #define JUCE_BEGIN_VEC_OP \
  169. typedef FloatVectorHelpers::ModeType<sizeof(*dest)>::Mode Mode; \
  170. if (Mode::numParallel > 1) \
  171. { \
  172. const int numLongOps = num / Mode::numParallel;
  173. #define JUCE_FINISH_VEC_OP(normalOp) \
  174. num &= (Mode::numParallel - 1); \
  175. if (num == 0) return; \
  176. } \
  177. for (int i = 0; i < num; ++i) normalOp;
  178. #define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp) \
  179. JUCE_BEGIN_VEC_OP \
  180. setupOp \
  181. JUCE_VEC_LOOP (vecOp, dummy, Mode::loadU, Mode::storeU, locals, JUCE_INCREMENT_DEST) \
  182. JUCE_FINISH_VEC_OP (normalOp)
  183. #define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp) \
  184. JUCE_BEGIN_VEC_OP \
  185. setupOp \
  186. JUCE_VEC_LOOP (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
  187. JUCE_FINISH_VEC_OP (normalOp)
  188. #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
  189. JUCE_BEGIN_VEC_OP \
  190. setupOp \
  191. JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
  192. JUCE_FINISH_VEC_OP (normalOp)
  193. #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp) \
  194. JUCE_BEGIN_VEC_OP \
  195. setupOp \
  196. JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
  197. JUCE_FINISH_VEC_OP (normalOp)
  198. //==============================================================================
  199. #else
  200. #define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp) \
  201. for (int i = 0; i < num; ++i) normalOp;
  202. #define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp) \
  203. for (int i = 0; i < num; ++i) normalOp;
  204. #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
  205. for (int i = 0; i < num; ++i) normalOp;
  206. #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp) \
  207. for (int i = 0; i < num; ++i) normalOp;
  208. #endif
  209. //==============================================================================
  210. #define JUCE_VEC_LOOP(vecOp, srcLoad, dstLoad, dstStore, locals, increment) \
  211. for (int i = 0; i < numLongOps; ++i) \
  212. { \
  213. locals (srcLoad, dstLoad); \
  214. dstStore (dest, vecOp); \
  215. increment; \
  216. }
  217. #define JUCE_VEC_LOOP_TWO_SOURCES(vecOp, src1Load, src2Load, dstStore, locals, increment) \
  218. for (int i = 0; i < numLongOps; ++i) \
  219. { \
  220. locals (src1Load, src2Load); \
  221. dstStore (dest, vecOp); \
  222. increment; \
  223. }
  224. #define JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD(vecOp, src1Load, src2Load, dstLoad, dstStore, locals, increment) \
  225. for (int i = 0; i < numLongOps; ++i) \
  226. { \
  227. locals (src1Load, src2Load, dstLoad); \
  228. dstStore (dest, vecOp); \
  229. increment; \
  230. }
  231. #define JUCE_LOAD_NONE(srcLoad, dstLoad)
  232. #define JUCE_LOAD_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest);
  233. #define JUCE_LOAD_SRC(srcLoad, dstLoad) const Mode::ParallelType s = srcLoad (src);
  234. #define JUCE_LOAD_SRC1_SRC2(src1Load, src2Load) const Mode::ParallelType s1 = src1Load (src1), s2 = src2Load (src2);
  235. #define JUCE_LOAD_SRC1_SRC2_DEST(src1Load, src2Load, dstLoad) const Mode::ParallelType d = dstLoad (dest), s1 = src1Load (src1), s2 = src2Load (src2);
  236. #define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest), s = srcLoad (src);
  237. #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
  238. template<int typeSize> struct ModeType { typedef BasicOps32 Mode; };
  239. template<> struct ModeType<8> { typedef BasicOps64 Mode; };
  240. template <typename Mode>
  241. struct MinMax
  242. {
  243. typedef typename Mode::Type Type;
  244. typedef typename Mode::ParallelType ParallelType;
  245. static Type findMinOrMax (const Type* src, int num, const bool isMinimum) noexcept
  246. {
  247. int numLongOps = num / Mode::numParallel;
  248. #if JUCE_USE_SSE_INTRINSICS
  249. if (numLongOps > 1 && isSSE2Available())
  250. #else
  251. if (numLongOps > 1)
  252. #endif
  253. {
  254. ParallelType val;
  255. #if ! JUCE_USE_ARM_NEON
  256. if (isAligned (src))
  257. {
  258. val = Mode::loadA (src);
  259. if (isMinimum)
  260. {
  261. while (--numLongOps > 0)
  262. {
  263. src += Mode::numParallel;
  264. val = Mode::min (val, Mode::loadA (src));
  265. }
  266. }
  267. else
  268. {
  269. while (--numLongOps > 0)
  270. {
  271. src += Mode::numParallel;
  272. val = Mode::max (val, Mode::loadA (src));
  273. }
  274. }
  275. }
  276. else
  277. #endif
  278. {
  279. val = Mode::loadU (src);
  280. if (isMinimum)
  281. {
  282. while (--numLongOps > 0)
  283. {
  284. src += Mode::numParallel;
  285. val = Mode::min (val, Mode::loadU (src));
  286. }
  287. }
  288. else
  289. {
  290. while (--numLongOps > 0)
  291. {
  292. src += Mode::numParallel;
  293. val = Mode::max (val, Mode::loadU (src));
  294. }
  295. }
  296. }
  297. Type result = isMinimum ? Mode::min (val)
  298. : Mode::max (val);
  299. num &= (Mode::numParallel - 1);
  300. src += Mode::numParallel;
  301. for (int i = 0; i < num; ++i)
  302. result = isMinimum ? jmin (result, src[i])
  303. : jmax (result, src[i]);
  304. return result;
  305. }
  306. return isMinimum ? juce::findMinimum (src, num)
  307. : juce::findMaximum (src, num);
  308. }
  309. static Range<Type> findMinAndMax (const Type* src, int num) noexcept
  310. {
  311. int numLongOps = num / Mode::numParallel;
  312. #if JUCE_USE_SSE_INTRINSICS
  313. if (numLongOps > 1 && isSSE2Available())
  314. #else
  315. if (numLongOps > 1)
  316. #endif
  317. {
  318. ParallelType mn, mx;
  319. #if ! JUCE_USE_ARM_NEON
  320. if (isAligned (src))
  321. {
  322. mn = Mode::loadA (src);
  323. mx = mn;
  324. while (--numLongOps > 0)
  325. {
  326. src += Mode::numParallel;
  327. const ParallelType v = Mode::loadA (src);
  328. mn = Mode::min (mn, v);
  329. mx = Mode::max (mx, v);
  330. }
  331. }
  332. else
  333. #endif
  334. {
  335. mn = Mode::loadU (src);
  336. mx = mn;
  337. while (--numLongOps > 0)
  338. {
  339. src += Mode::numParallel;
  340. const ParallelType v = Mode::loadU (src);
  341. mn = Mode::min (mn, v);
  342. mx = Mode::max (mx, v);
  343. }
  344. }
  345. Range<Type> result (Mode::min (mn),
  346. Mode::max (mx));
  347. num &= (Mode::numParallel - 1);
  348. src += Mode::numParallel;
  349. for (int i = 0; i < num; ++i)
  350. result = result.getUnionWith (src[i]);
  351. return result;
  352. }
  353. return Range<Type>::findMinAndMax (src, num);
  354. }
  355. };
  356. #endif
  357. }
  358. //==============================================================================
  359. void JUCE_CALLTYPE FloatVectorOperations::clear (float* dest, int num) noexcept
  360. {
  361. #if JUCE_USE_VDSP_FRAMEWORK
  362. vDSP_vclr (dest, 1, (size_t) num);
  363. #else
  364. zeromem (dest, num * sizeof (float));
  365. #endif
  366. }
  367. void JUCE_CALLTYPE FloatVectorOperations::clear (double* dest, int num) noexcept
  368. {
  369. #if JUCE_USE_VDSP_FRAMEWORK
  370. vDSP_vclrD (dest, 1, (size_t) num);
  371. #else
  372. zeromem (dest, num * sizeof (double));
  373. #endif
  374. }
  375. void JUCE_CALLTYPE FloatVectorOperations::fill (float* dest, float valueToFill, int num) noexcept
  376. {
  377. #if JUCE_USE_VDSP_FRAMEWORK
  378. vDSP_vfill (&valueToFill, dest, 1, (size_t) num);
  379. #else
  380. JUCE_PERFORM_VEC_OP_DEST (dest[i] = valueToFill, val, JUCE_LOAD_NONE,
  381. const Mode::ParallelType val = Mode::load1 (valueToFill);)
  382. #endif
  383. }
  384. void JUCE_CALLTYPE FloatVectorOperations::fill (double* dest, double valueToFill, int num) noexcept
  385. {
  386. #if JUCE_USE_VDSP_FRAMEWORK
  387. vDSP_vfillD (&valueToFill, dest, 1, (size_t) num);
  388. #else
  389. JUCE_PERFORM_VEC_OP_DEST (dest[i] = valueToFill, val, JUCE_LOAD_NONE,
  390. const Mode::ParallelType val = Mode::load1 (valueToFill);)
  391. #endif
  392. }
  393. void JUCE_CALLTYPE FloatVectorOperations::copy (float* dest, const float* src, int num) noexcept
  394. {
  395. memcpy (dest, src, (size_t) num * sizeof (float));
  396. }
  397. void JUCE_CALLTYPE FloatVectorOperations::copy (double* dest, const double* src, int num) noexcept
  398. {
  399. memcpy (dest, src, (size_t) num * sizeof (double));
  400. }
  401. void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (float* dest, const float* src, float multiplier, int num) noexcept
  402. {
  403. #if JUCE_USE_VDSP_FRAMEWORK
  404. vDSP_vsmul (src, 1, &multiplier, dest, 1, (vDSP_Length) num);
  405. #else
  406. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s),
  407. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
  408. const Mode::ParallelType mult = Mode::load1 (multiplier);)
  409. #endif
  410. }
  411. void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (double* dest, const double* src, double multiplier, int num) noexcept
  412. {
  413. #if JUCE_USE_VDSP_FRAMEWORK
  414. vDSP_vsmulD (src, 1, &multiplier, dest, 1, (vDSP_Length) num);
  415. #else
  416. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s),
  417. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
  418. const Mode::ParallelType mult = Mode::load1 (multiplier);)
  419. #endif
  420. }
  421. void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, float amount, int num) noexcept
  422. {
  423. #if JUCE_USE_VDSP_FRAMEWORK
  424. vDSP_vsadd (dest, 1, &amount, dest, 1, (vDSP_Length) num);
  425. #else
  426. JUCE_PERFORM_VEC_OP_DEST (dest[i] += amount, Mode::add (d, amountToAdd), JUCE_LOAD_DEST,
  427. const Mode::ParallelType amountToAdd = Mode::load1 (amount);)
  428. #endif
  429. }
  430. void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, double amount, int num) noexcept
  431. {
  432. JUCE_PERFORM_VEC_OP_DEST (dest[i] += amount, Mode::add (d, amountToAdd), JUCE_LOAD_DEST,
  433. const Mode::ParallelType amountToAdd = Mode::load1 (amount);)
  434. }
  435. void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, float* src, float amount, int num) noexcept
  436. {
  437. #if JUCE_USE_VDSP_FRAMEWORK
  438. vDSP_vsadd (src, 1, &amount, dest, 1, (vDSP_Length) num);
  439. #else
  440. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] + amount, Mode::add (am, s),
  441. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
  442. const Mode::ParallelType am = Mode::load1 (amount);)
  443. #endif
  444. }
  445. void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, double* src, double amount, int num) noexcept
  446. {
  447. #if JUCE_USE_VDSP_FRAMEWORK
  448. vDSP_vsaddD (src, 1, &amount, dest, 1, (vDSP_Length) num);
  449. #else
  450. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] + amount, Mode::add (am, s),
  451. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
  452. const Mode::ParallelType am = Mode::load1 (amount);)
  453. #endif
  454. }
  455. void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src, int num) noexcept
  456. {
  457. #if JUCE_USE_VDSP_FRAMEWORK
  458. vDSP_vadd (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
  459. #else
  460. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i], Mode::add (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, )
  461. #endif
  462. }
  463. void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, const double* src, int num) noexcept
  464. {
  465. #if JUCE_USE_VDSP_FRAMEWORK
  466. vDSP_vaddD (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
  467. #else
  468. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i], Mode::add (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, )
  469. #endif
  470. }
  471. void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src1, const float* src2, int num) noexcept
  472. {
  473. #if JUCE_USE_VDSP_FRAMEWORK
  474. vDSP_vadd (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
  475. #else
  476. JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] + src2[i], Mode::add (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
  477. #endif
  478. }
  479. void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, const double* src1, const double* src2, int num) noexcept
  480. {
  481. #if JUCE_USE_VDSP_FRAMEWORK
  482. vDSP_vaddD (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
  483. #else
  484. JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] + src2[i], Mode::add (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
  485. #endif
  486. }
  487. void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* src, int num) noexcept
  488. {
  489. #if JUCE_USE_VDSP_FRAMEWORK
  490. vDSP_vsub (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
  491. #else
  492. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i], Mode::sub (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, )
  493. #endif
  494. }
  495. void JUCE_CALLTYPE FloatVectorOperations::subtract (double* dest, const double* src, int num) noexcept
  496. {
  497. #if JUCE_USE_VDSP_FRAMEWORK
  498. vDSP_vsubD (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
  499. #else
  500. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i], Mode::sub (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, )
  501. #endif
  502. }
  503. void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* src1, const float* src2, int num) noexcept
  504. {
  505. #if JUCE_USE_VDSP_FRAMEWORK
  506. vDSP_vsub (src2, 1, src1, 1, dest, 1, (vDSP_Length) num);
  507. #else
  508. JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] - src2[i], Mode::sub (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
  509. #endif
  510. }
  511. void JUCE_CALLTYPE FloatVectorOperations::subtract (double* dest, const double* src1, const double* src2, int num) noexcept
  512. {
  513. #if JUCE_USE_VDSP_FRAMEWORK
  514. vDSP_vsubD (src2, 1, src1, 1, dest, 1, (vDSP_Length) num);
  515. #else
  516. JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] - src2[i], Mode::sub (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
  517. #endif
  518. }
  519. void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (float* dest, const float* src, float multiplier, int num) noexcept
  520. {
  521. #if JUCE_USE_VDSP_FRAMEWORK
  522. vDSP_vsma (src, 1, &multiplier, dest, 1, dest, 1, (vDSP_Length) num);
  523. #else
  524. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i] * multiplier, Mode::add (d, Mode::mul (mult, s)),
  525. JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST,
  526. const Mode::ParallelType mult = Mode::load1 (multiplier);)
  527. #endif
  528. }
  529. void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (double* dest, const double* src, double multiplier, int num) noexcept
  530. {
  531. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i] * multiplier, Mode::add (d, Mode::mul (mult, s)),
  532. JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST,
  533. const Mode::ParallelType mult = Mode::load1 (multiplier);)
  534. }
  535. void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (float* dest, const float* src1, const float* src2, int num) noexcept
  536. {
  537. #if JUCE_USE_VDSP_FRAMEWORK
  538. vDSP_vma ((float*) src1, 1, (float*) src2, 1, dest, 1, dest, 1, (vDSP_Length) num);
  539. #else
  540. JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST (dest[i] += src1[i] * src2[i], Mode::add (d, Mode::mul (s1, s2)),
  541. JUCE_LOAD_SRC1_SRC2_DEST,
  542. JUCE_INCREMENT_SRC1_SRC2_DEST, )
  543. #endif
  544. }
  545. void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (double* dest, const double* src1, const double* src2, int num) noexcept
  546. {
  547. #if JUCE_USE_VDSP_FRAMEWORK
  548. vDSP_vmaD ((double*) src1, 1, (double*) src2, 1, dest, 1, dest, 1, (vDSP_Length) num);
  549. #else
  550. JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST (dest[i] += src1[i] * src2[i], Mode::add (d, Mode::mul (s1, s2)),
  551. JUCE_LOAD_SRC1_SRC2_DEST,
  552. JUCE_INCREMENT_SRC1_SRC2_DEST, )
  553. #endif
  554. }
  555. void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src, int num) noexcept
  556. {
  557. #if JUCE_USE_VDSP_FRAMEWORK
  558. vDSP_vmul (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
  559. #else
  560. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] *= src[i], Mode::mul (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, )
  561. #endif
  562. }
  563. void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, const double* src, int num) noexcept
  564. {
  565. #if JUCE_USE_VDSP_FRAMEWORK
  566. vDSP_vmulD (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
  567. #else
  568. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] *= src[i], Mode::mul (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, )
  569. #endif
  570. }
  571. void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src1, const float* src2, int num) noexcept
  572. {
  573. #if JUCE_USE_VDSP_FRAMEWORK
  574. vDSP_vmul (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
  575. #else
  576. JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] * src2[i], Mode::mul (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
  577. #endif
  578. }
  579. void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, const double* src1, const double* src2, int num) noexcept
  580. {
  581. #if JUCE_USE_VDSP_FRAMEWORK
  582. vDSP_vmulD (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
  583. #else
  584. JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] * src2[i], Mode::mul (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
  585. #endif
  586. }
  587. void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, float multiplier, int num) noexcept
  588. {
  589. #if JUCE_USE_VDSP_FRAMEWORK
  590. vDSP_vsmul (dest, 1, &multiplier, dest, 1, (vDSP_Length) num);
  591. #else
  592. JUCE_PERFORM_VEC_OP_DEST (dest[i] *= multiplier, Mode::mul (d, mult), JUCE_LOAD_DEST,
  593. const Mode::ParallelType mult = Mode::load1 (multiplier);)
  594. #endif
  595. }
  596. void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, double multiplier, int num) noexcept
  597. {
  598. #if JUCE_USE_VDSP_FRAMEWORK
  599. vDSP_vsmulD (dest, 1, &multiplier, dest, 1, (vDSP_Length) num);
  600. #else
  601. JUCE_PERFORM_VEC_OP_DEST (dest[i] *= multiplier, Mode::mul (d, mult), JUCE_LOAD_DEST,
  602. const Mode::ParallelType mult = Mode::load1 (multiplier);)
  603. #endif
  604. }
  605. void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src, float multiplier, int num) noexcept
  606. {
  607. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s),
  608. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
  609. const Mode::ParallelType mult = Mode::load1 (multiplier);)
  610. }
  611. void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, const double* src, double multiplier, int num) noexcept
  612. {
  613. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s),
  614. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
  615. const Mode::ParallelType mult = Mode::load1 (multiplier);)
  616. }
  617. void FloatVectorOperations::negate (float* dest, const float* src, int num) noexcept
  618. {
  619. #if JUCE_USE_VDSP_FRAMEWORK
  620. vDSP_vneg ((float*) src, 1, dest, 1, (vDSP_Length) num);
  621. #else
  622. copyWithMultiply (dest, src, -1.0f, num);
  623. #endif
  624. }
  625. void FloatVectorOperations::negate (double* dest, const double* src, int num) noexcept
  626. {
  627. #if JUCE_USE_VDSP_FRAMEWORK
  628. vDSP_vnegD ((double*) src, 1, dest, 1, (vDSP_Length) num);
  629. #else
  630. copyWithMultiply (dest, src, -1.0f, num);
  631. #endif
  632. }
  633. void FloatVectorOperations::abs (float* dest, const float* src, int num) noexcept
  634. {
  635. #if JUCE_USE_VDSP_FRAMEWORK
  636. vDSP_vabs ((float*) src, 1, dest, 1, (vDSP_Length) num);
  637. #else
  638. union {float f; uint32 i;} signMask;
  639. signMask.i = 0x80000000UL;
  640. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = fabsf(src[i]),
  641. Mode::bit_xor (s, Mode::bit_and (s, mask)),
  642. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
  643. const Mode::ParallelType mask = Mode::load1 (signMask.f);)
  644. #endif
  645. }
  646. void FloatVectorOperations::abs (double* dest, const double* src, int num) noexcept
  647. {
  648. #if JUCE_USE_VDSP_FRAMEWORK
  649. vDSP_vabsD ((double*) src, 1, dest, 1, (vDSP_Length) num);
  650. #else
  651. union {double d; uint64 i;} signMask;
  652. signMask.i = 0x8000000000000000ULL;
  653. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = fabs (src[i]),
  654. Mode::bit_xor (s, Mode::bit_and (s, mask)),
  655. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
  656. const Mode::ParallelType mask = Mode::load1 (signMask.d);)
  657. #endif
  658. }
  659. void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, const int* src, float multiplier, int num) noexcept
  660. {
  661. #if JUCE_USE_ARM_NEON
  662. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier,
  663. vmulq_n_f32 (vcvtq_f32_s32 (vld1q_s32 (src)), multiplier),
  664. JUCE_LOAD_NONE, JUCE_INCREMENT_SRC_DEST, )
  665. #else
  666. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier,
  667. Mode::mul (mult, _mm_cvtepi32_ps (_mm_loadu_si128 ((const __m128i*) src))),
  668. JUCE_LOAD_NONE, JUCE_INCREMENT_SRC_DEST,
  669. const Mode::ParallelType mult = Mode::load1 (multiplier);)
  670. #endif
  671. }
  672. void JUCE_CALLTYPE FloatVectorOperations::min (float* dest, const float* src, float comp, int num) noexcept
  673. {
  674. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmin (src[i], comp), Mode::min (s, cmp),
  675. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
  676. const Mode::ParallelType cmp = Mode::load1 (comp);)
  677. }
  678. void JUCE_CALLTYPE FloatVectorOperations::min (double* dest, const double* src, double comp, int num) noexcept
  679. {
  680. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmin (src[i], comp), Mode::min (s, cmp),
  681. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
  682. const Mode::ParallelType cmp = Mode::load1 (comp);)
  683. }
  684. void JUCE_CALLTYPE FloatVectorOperations::min (float* dest, const float* src1, const float* src2, int num) noexcept
  685. {
  686. #if JUCE_USE_VDSP_FRAMEWORK
  687. vDSP_vmin ((float*) src1, 1, (float*) src2, 1, dest, 1, (vDSP_Length) num);
  688. #else
  689. JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmin (src1[i], src2[i]), Mode::min (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
  690. #endif
  691. }
  692. void JUCE_CALLTYPE FloatVectorOperations::min (double* dest, const double* src1, const double* src2, int num) noexcept
  693. {
  694. #if JUCE_USE_VDSP_FRAMEWORK
  695. vDSP_vminD ((double*) src1, 1, (double*) src2, 1, dest, 1, (vDSP_Length) num);
  696. #else
  697. JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmin (src1[i], src2[i]), Mode::min (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
  698. #endif
  699. }
  700. void JUCE_CALLTYPE FloatVectorOperations::max (float* dest, const float* src, float comp, int num) noexcept
  701. {
  702. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (src[i], comp), Mode::max (s, cmp),
  703. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
  704. const Mode::ParallelType cmp = Mode::load1 (comp);)
  705. }
  706. void JUCE_CALLTYPE FloatVectorOperations::max (double* dest, const double* src, double comp, int num) noexcept
  707. {
  708. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (src[i], comp), Mode::max (s, cmp),
  709. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
  710. const Mode::ParallelType cmp = Mode::load1 (comp);)
  711. }
  712. void JUCE_CALLTYPE FloatVectorOperations::max (float* dest, const float* src1, const float* src2, int num) noexcept
  713. {
  714. #if JUCE_USE_VDSP_FRAMEWORK
  715. vDSP_vmax ((float*) src1, 1, (float*) src2, 1, dest, 1, (vDSP_Length) num);
  716. #else
  717. JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmax (src1[i], src2[i]), Mode::max (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
  718. #endif
  719. }
  720. void JUCE_CALLTYPE FloatVectorOperations::max (double* dest, const double* src1, const double* src2, int num) noexcept
  721. {
  722. #if JUCE_USE_VDSP_FRAMEWORK
  723. vDSP_vmaxD ((double*) src1, 1, (double*) src2, 1, dest, 1, (vDSP_Length) num);
  724. #else
  725. JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmax (src1[i], src2[i]), Mode::max (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
  726. #endif
  727. }
  728. void JUCE_CALLTYPE FloatVectorOperations::clip (float* dest, const float* src, float low, float high, int num) noexcept
  729. {
  730. jassert(high >= low);
  731. #if JUCE_USE_VDSP_FRAMEWORK
  732. vDSP_vclip ((float*) src, 1, &low, &high, dest, 1, (vDSP_Length) num);
  733. #else
  734. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (jmin (src[i], high), low), Mode::max (Mode::min (s, hi), lo),
  735. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
  736. const Mode::ParallelType lo = Mode::load1 (low); const Mode::ParallelType hi = Mode::load1 (high);)
  737. #endif
  738. }
  739. void JUCE_CALLTYPE FloatVectorOperations::clip (double* dest, const double* src, double low, double high, int num) noexcept
  740. {
  741. jassert(high >= low);
  742. #if JUCE_USE_VDSP_FRAMEWORK
  743. vDSP_vclipD ((double*) src, 1, &low, &high, dest, 1, (vDSP_Length) num);
  744. #else
  745. JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (jmin (src[i], high), low), Mode::max (Mode::min (s, hi), lo),
  746. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
  747. const Mode::ParallelType lo = Mode::load1 (low); const Mode::ParallelType hi = Mode::load1 (high);)
  748. #endif
  749. }
  750. Range<float> JUCE_CALLTYPE FloatVectorOperations::findMinAndMax (const float* src, int num) noexcept
  751. {
  752. #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
  753. return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps32>::findMinAndMax (src, num);
  754. #else
  755. return Range<float>::findMinAndMax (src, num);
  756. #endif
  757. }
  758. Range<double> JUCE_CALLTYPE FloatVectorOperations::findMinAndMax (const double* src, int num) noexcept
  759. {
  760. #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
  761. return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps64>::findMinAndMax (src, num);
  762. #else
  763. return Range<double>::findMinAndMax (src, num);
  764. #endif
  765. }
  766. float JUCE_CALLTYPE FloatVectorOperations::findMinimum (const float* src, int num) noexcept
  767. {
  768. #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
  769. return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps32>::findMinOrMax (src, num, true);
  770. #else
  771. return juce::findMinimum (src, num);
  772. #endif
  773. }
  774. double JUCE_CALLTYPE FloatVectorOperations::findMinimum (const double* src, int num) noexcept
  775. {
  776. #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
  777. return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps64>::findMinOrMax (src, num, true);
  778. #else
  779. return juce::findMinimum (src, num);
  780. #endif
  781. }
  782. float JUCE_CALLTYPE FloatVectorOperations::findMaximum (const float* src, int num) noexcept
  783. {
  784. #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
  785. return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps32>::findMinOrMax (src, num, false);
  786. #else
  787. return juce::findMaximum (src, num);
  788. #endif
  789. }
  790. double JUCE_CALLTYPE FloatVectorOperations::findMaximum (const double* src, int num) noexcept
  791. {
  792. #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
  793. return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps64>::findMinOrMax (src, num, false);
  794. #else
  795. return juce::findMaximum (src, num);
  796. #endif
  797. }
  798. void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnable) noexcept
  799. {
  800. #if JUCE_USE_SSE_INTRINSICS
  801. if (FloatVectorHelpers::isSSE2Available())
  802. _MM_SET_FLUSH_ZERO_MODE (shouldEnable ? _MM_FLUSH_ZERO_ON : _MM_FLUSH_ZERO_OFF);
  803. #endif
  804. (void) shouldEnable;
  805. }
  806. //==============================================================================
  807. //==============================================================================
  808. #if JUCE_UNIT_TESTS
  809. class FloatVectorOperationsTests : public UnitTest
  810. {
  811. public:
  812. FloatVectorOperationsTests() : UnitTest ("FloatVectorOperations") {}
  813. template <typename ValueType>
  814. struct TestRunner
  815. {
  816. static void runTest (UnitTest& u, Random random)
  817. {
  818. const int range = random.nextBool() ? 500 : 10;
  819. const int num = random.nextInt (range) + 1;
  820. HeapBlock<ValueType> buffer1 ((size_t) num + 16), buffer2 ((size_t) num + 16);
  821. HeapBlock<int> buffer3 ((size_t) num + 16);
  822. #if JUCE_ARM
  823. ValueType* const data1 = buffer1;
  824. ValueType* const data2 = buffer2;
  825. int* const int1 = buffer3;
  826. #else
  827. ValueType* const data1 = addBytesToPointer (buffer1.getData(), random.nextInt (16));
  828. ValueType* const data2 = addBytesToPointer (buffer2.getData(), random.nextInt (16));
  829. int* const int1 = addBytesToPointer (buffer3.getData(), random.nextInt (16));
  830. #endif
  831. fillRandomly (random, data1, num);
  832. fillRandomly (random, data2, num);
  833. Range<ValueType> minMax1 (FloatVectorOperations::findMinAndMax (data1, num));
  834. Range<ValueType> minMax2 (Range<ValueType>::findMinAndMax (data1, num));
  835. u.expect (minMax1 == minMax2);
  836. u.expect (valuesMatch (FloatVectorOperations::findMinimum (data1, num), juce::findMinimum (data1, num)));
  837. u.expect (valuesMatch (FloatVectorOperations::findMaximum (data1, num), juce::findMaximum (data1, num)));
  838. u.expect (valuesMatch (FloatVectorOperations::findMinimum (data2, num), juce::findMinimum (data2, num)));
  839. u.expect (valuesMatch (FloatVectorOperations::findMaximum (data2, num), juce::findMaximum (data2, num)));
  840. FloatVectorOperations::clear (data1, num);
  841. u.expect (areAllValuesEqual (data1, num, 0));
  842. FloatVectorOperations::fill (data1, (ValueType) 2, num);
  843. u.expect (areAllValuesEqual (data1, num, (ValueType) 2));
  844. FloatVectorOperations::add (data1, (ValueType) 2, num);
  845. u.expect (areAllValuesEqual (data1, num, (ValueType) 4));
  846. FloatVectorOperations::copy (data2, data1, num);
  847. u.expect (areAllValuesEqual (data2, num, (ValueType) 4));
  848. FloatVectorOperations::add (data2, data1, num);
  849. u.expect (areAllValuesEqual (data2, num, (ValueType) 8));
  850. FloatVectorOperations::copyWithMultiply (data2, data1, (ValueType) 4, num);
  851. u.expect (areAllValuesEqual (data2, num, (ValueType) 16));
  852. FloatVectorOperations::addWithMultiply (data2, data1, (ValueType) 4, num);
  853. u.expect (areAllValuesEqual (data2, num, (ValueType) 32));
  854. FloatVectorOperations::multiply (data1, (ValueType) 2, num);
  855. u.expect (areAllValuesEqual (data1, num, (ValueType) 8));
  856. FloatVectorOperations::multiply (data1, data2, num);
  857. u.expect (areAllValuesEqual (data1, num, (ValueType) 256));
  858. FloatVectorOperations::negate (data2, data1, num);
  859. u.expect (areAllValuesEqual (data2, num, (ValueType) -256));
  860. FloatVectorOperations::subtract (data1, data2, num);
  861. u.expect (areAllValuesEqual (data1, num, (ValueType) 512));
  862. FloatVectorOperations::abs (data1, data2, num);
  863. u.expect (areAllValuesEqual (data1, num, (ValueType) 256));
  864. FloatVectorOperations::abs (data2, data1, num);
  865. u.expect (areAllValuesEqual (data2, num, (ValueType) 256));
  866. fillRandomly (random, int1, num);
  867. doConversionTest (u, data1, data2, int1, num);
  868. FloatVectorOperations::fill (data1, (ValueType) 2, num);
  869. FloatVectorOperations::fill (data2, (ValueType) 3, num);
  870. FloatVectorOperations::addWithMultiply (data1, data1, data2, num);
  871. u.expect (areAllValuesEqual (data1, num, (ValueType) 8));
  872. }
  873. static void doConversionTest (UnitTest& u, float* data1, float* data2, int* const int1, int num)
  874. {
  875. FloatVectorOperations::convertFixedToFloat (data1, int1, 2.0f, num);
  876. convertFixed (data2, int1, 2.0f, num);
  877. u.expect (buffersMatch (data1, data2, num));
  878. }
  879. static void doConversionTest (UnitTest&, double*, double*, int*, int) {}
  880. static void fillRandomly (Random& random, ValueType* d, int num)
  881. {
  882. while (--num >= 0)
  883. *d++ = (ValueType) (random.nextDouble() * 1000.0);
  884. }
  885. static void fillRandomly (Random& random, int* d, int num)
  886. {
  887. while (--num >= 0)
  888. *d++ = random.nextInt();
  889. }
  890. static void convertFixed (float* d, const int* s, ValueType multiplier, int num)
  891. {
  892. while (--num >= 0)
  893. *d++ = *s++ * multiplier;
  894. }
  895. static bool areAllValuesEqual (const ValueType* d, int num, ValueType target)
  896. {
  897. while (--num >= 0)
  898. if (*d++ != target)
  899. return false;
  900. return true;
  901. }
  902. static bool buffersMatch (const ValueType* d1, const ValueType* d2, int num)
  903. {
  904. while (--num >= 0)
  905. if (! valuesMatch (*d1++, *d2++))
  906. return false;
  907. return true;
  908. }
  909. static bool valuesMatch (ValueType v1, ValueType v2)
  910. {
  911. return std::abs (v1 - v2) < std::numeric_limits<ValueType>::epsilon();
  912. }
  913. };
  914. void runTest()
  915. {
  916. beginTest ("FloatVectorOperations");
  917. for (int i = 1000; --i >= 0;)
  918. {
  919. TestRunner<float>::runTest (*this, getRandom());
  920. TestRunner<double>::runTest (*this, getRandom());
  921. }
  922. }
  923. };
  924. static FloatVectorOperationsTests vectorOpTests;
  925. #endif