Audio plugin host https://kx.studio/carla
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.

1044 lines
45KB

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