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.

juce_FloatVectorOperations.cpp 45KB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  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