PageRenderTime 60ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/PitchTune/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp

https://github.com/bayesrule/VocalModifier
C++ | 616 lines | 478 code | 110 blank | 28 comment | 61 complexity | 9beb3c6c6dac739f2766b36d2bba4dd0 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0
  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 += 4; src += 4;
  20. #define JUCE_INCREMENT_DEST dest += 4;
  21. #if JUCE_USE_SSE_INTRINSICS
  22. static bool sse2Present = false;
  23. static bool isSSE2Available() noexcept
  24. {
  25. if (sse2Present)
  26. return true;
  27. sse2Present = SystemStats::hasSSE2();
  28. return sse2Present;
  29. }
  30. inline static bool isAligned (const void* p) noexcept
  31. {
  32. return (((pointer_sized_int) p) & 15) == 0;
  33. }
  34. static inline float findMinimumOrMaximum (const float* src, int num, const bool isMinimum) noexcept
  35. {
  36. const int numLongOps = num / 4;
  37. if (numLongOps > 1 && FloatVectorHelpers::isSSE2Available())
  38. {
  39. __m128 val;
  40. #define JUCE_MINIMUMMAXIMUM_SSE_LOOP(loadOp, minMaxOp) \
  41. val = loadOp (src); \
  42. src += 4; \
  43. for (int i = 1; i < numLongOps; ++i) \
  44. { \
  45. const __m128 s = loadOp (src); \
  46. val = minMaxOp (val, s); \
  47. src += 4; \
  48. }
  49. if (isMinimum)
  50. {
  51. if (FloatVectorHelpers::isAligned (src)) { JUCE_MINIMUMMAXIMUM_SSE_LOOP (_mm_load_ps, _mm_min_ps) }
  52. else { JUCE_MINIMUMMAXIMUM_SSE_LOOP (_mm_loadu_ps, _mm_min_ps) }
  53. }
  54. else
  55. {
  56. if (FloatVectorHelpers::isAligned (src)) { JUCE_MINIMUMMAXIMUM_SSE_LOOP (_mm_load_ps, _mm_max_ps) }
  57. else { JUCE_MINIMUMMAXIMUM_SSE_LOOP (_mm_loadu_ps,_mm_max_ps) }
  58. }
  59. float localVal;
  60. {
  61. float vals[4];
  62. _mm_storeu_ps (vals, val);
  63. localVal = isMinimum ? jmin (vals[0], vals[1], vals[2], vals[3])
  64. : jmax (vals[0], vals[1], vals[2], vals[3]);
  65. }
  66. num &= 3;
  67. for (int i = 0; i < num; ++i)
  68. localVal = isMinimum ? jmin (localVal, src[i])
  69. : jmax (localVal, src[i]);
  70. return localVal;
  71. }
  72. return isMinimum ? juce::findMinimum (src, num)
  73. : juce::findMaximum (src, num);
  74. }
  75. #define JUCE_BEGIN_SSE_OP \
  76. if (FloatVectorHelpers::isSSE2Available()) \
  77. { \
  78. const int numLongOps = num / 4;
  79. #define JUCE_FINISH_SSE_OP(normalOp) \
  80. num &= 3; \
  81. if (num == 0) return; \
  82. } \
  83. for (int i = 0; i < num; ++i) normalOp;
  84. #define JUCE_SSE_LOOP(sseOp, srcLoad, dstLoad, dstStore, locals, increment) \
  85. for (int i = 0; i < numLongOps; ++i) \
  86. { \
  87. locals (srcLoad, dstLoad); \
  88. dstStore (dest, sseOp); \
  89. increment; \
  90. }
  91. #define JUCE_LOAD_NONE(srcLoad, dstLoad)
  92. #define JUCE_LOAD_DEST(srcLoad, dstLoad) const __m128 d = dstLoad (dest);
  93. #define JUCE_LOAD_SRC(srcLoad, dstLoad) const __m128 s = srcLoad (src);
  94. #define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const __m128 d = dstLoad (dest); const __m128 s = srcLoad (src);
  95. #define JUCE_PERFORM_SSE_OP_DEST(normalOp, sseOp, locals) \
  96. JUCE_BEGIN_SSE_OP \
  97. if (FloatVectorHelpers::isAligned (dest)) JUCE_SSE_LOOP (sseOp, dummy, _mm_load_ps, _mm_store_ps, locals, JUCE_INCREMENT_DEST) \
  98. else JUCE_SSE_LOOP (sseOp, dummy, _mm_loadu_ps, _mm_storeu_ps, locals, JUCE_INCREMENT_DEST) \
  99. JUCE_FINISH_SSE_OP (normalOp)
  100. #define JUCE_PERFORM_SSE_OP_SRC_DEST(normalOp, sseOp, locals, increment) \
  101. JUCE_BEGIN_SSE_OP \
  102. if (FloatVectorHelpers::isAligned (dest)) \
  103. { \
  104. if (FloatVectorHelpers::isAligned (src)) JUCE_SSE_LOOP (sseOp, _mm_load_ps, _mm_load_ps, _mm_store_ps, locals, increment) \
  105. else JUCE_SSE_LOOP (sseOp, _mm_loadu_ps, _mm_load_ps, _mm_store_ps, locals, increment) \
  106. }\
  107. else \
  108. { \
  109. if (FloatVectorHelpers::isAligned (src)) JUCE_SSE_LOOP (sseOp, _mm_load_ps, _mm_loadu_ps, _mm_storeu_ps, locals, increment) \
  110. else JUCE_SSE_LOOP (sseOp, _mm_loadu_ps, _mm_loadu_ps, _mm_storeu_ps, locals, increment) \
  111. } \
  112. JUCE_FINISH_SSE_OP (normalOp)
  113. //==============================================================================
  114. #elif JUCE_USE_ARM_NEON
  115. static inline float findMinimumOrMaximum (const float* src, int num, const bool isMinimum) noexcept
  116. {
  117. const int numLongOps = num / 4;
  118. if (numLongOps > 1)
  119. {
  120. float32x4_t val;
  121. #define JUCE_MINIMUMMAXIMUM_NEON_LOOP(loadOp, minMaxOp) \
  122. val = loadOp (src); \
  123. src += 4; \
  124. for (int i = 1; i < numLongOps; ++i) \
  125. { \
  126. const float32x4_t s = loadOp (src); \
  127. val = minMaxOp (val, s); \
  128. src += 4; \
  129. }
  130. if (isMinimum)
  131. JUCE_MINIMUMMAXIMUM_NEON_LOOP (vld1q_f32, vminq_f32)
  132. else
  133. JUCE_MINIMUMMAXIMUM_NEON_LOOP (vld1q_f32, vmaxq_f32)
  134. float localVal;
  135. {
  136. float vals[4];
  137. vst1q_f32 (vals, val);
  138. localVal = isMinimum ? jmin (vals[0], vals[1], vals[2], vals[3])
  139. : jmax (vals[0], vals[1], vals[2], vals[3]);
  140. }
  141. num &= 3;
  142. for (int i = 0; i < num; ++i)
  143. localVal = isMinimum ? jmin (localVal, src[i])
  144. : jmax (localVal, src[i]);
  145. return localVal;
  146. }
  147. return isMinimum ? juce::findMinimum (src, num)
  148. : juce::findMaximum (src, num);
  149. }
  150. #define JUCE_BEGIN_NEON_OP \
  151. const int numLongOps = num / 4;
  152. #define JUCE_FINISH_NEON_OP(normalOp) \
  153. num &= 3; \
  154. if (num == 0) return; \
  155. for (int i = 0; i < num; ++i) normalOp;
  156. #define JUCE_NEON_LOOP(neonOp, srcLoad, dstLoad, dstStore, locals, increment) \
  157. for (int i = 0; i < numLongOps; ++i) \
  158. { \
  159. locals (srcLoad, dstLoad); \
  160. dstStore (dest, neonOp); \
  161. increment; \
  162. }
  163. #define JUCE_LOAD_NONE(srcLoad, dstLoad)
  164. #define JUCE_LOAD_DEST(srcLoad, dstLoad) const float32x4_t d = dstLoad (dest);
  165. #define JUCE_LOAD_SRC(srcLoad, dstLoad) const float32x4_t s = srcLoad (src);
  166. #define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const float32x4_t d = dstLoad (dest); const float32x4_t s = srcLoad (src);
  167. #define JUCE_PERFORM_NEON_OP_DEST(normalOp, neonOp, locals) \
  168. JUCE_BEGIN_NEON_OP \
  169. JUCE_NEON_LOOP (neonOp, dummy, vld1q_f32, vst1q_f32, locals, JUCE_INCREMENT_DEST) \
  170. JUCE_FINISH_NEON_OP (normalOp)
  171. #define JUCE_PERFORM_NEON_OP_SRC_DEST(normalOp, neonOp, locals) \
  172. JUCE_BEGIN_NEON_OP \
  173. JUCE_NEON_LOOP (neonOp, vld1q_f32, vld1q_f32, vst1q_f32, locals, JUCE_INCREMENT_SRC_DEST) \
  174. JUCE_FINISH_NEON_OP (normalOp)
  175. //==============================================================================
  176. #else
  177. #define JUCE_PERFORM_SSE_OP_DEST(normalOp, unused1, unused2) for (int i = 0; i < num; ++i) normalOp;
  178. #define JUCE_PERFORM_SSE_OP_SRC_DEST(normalOp, sseOp, locals, increment) for (int i = 0; i < num; ++i) normalOp;
  179. #endif
  180. }
  181. //==============================================================================
  182. void JUCE_CALLTYPE FloatVectorOperations::clear (float* dest, int num) noexcept
  183. {
  184. #if JUCE_USE_VDSP_FRAMEWORK
  185. vDSP_vclr (dest, 1, (size_t) num);
  186. #else
  187. zeromem (dest, num * sizeof (float));
  188. #endif
  189. }
  190. void JUCE_CALLTYPE FloatVectorOperations::fill (float* dest, float valueToFill, int num) noexcept
  191. {
  192. #if JUCE_USE_VDSP_FRAMEWORK
  193. vDSP_vfill (&valueToFill, dest, 1, (size_t) num);
  194. #elif JUCE_USE_ARM_NEON
  195. const float32x4_t val = vld1q_dup_f32 (&valueToFill);
  196. JUCE_PERFORM_NEON_OP_DEST (dest[i] = valueToFill, val, JUCE_LOAD_NONE)
  197. #else
  198. #if JUCE_USE_SSE_INTRINSICS
  199. const __m128 val = _mm_load1_ps (&valueToFill);
  200. #endif
  201. JUCE_PERFORM_SSE_OP_DEST (dest[i] = valueToFill, val, JUCE_LOAD_NONE)
  202. #endif
  203. }
  204. void JUCE_CALLTYPE FloatVectorOperations::copy (float* dest, const float* src, int num) noexcept
  205. {
  206. memcpy (dest, src, (size_t) num * sizeof (float));
  207. }
  208. void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (float* dest, const float* src, float multiplier, int num) noexcept
  209. {
  210. #if JUCE_USE_VDSP_FRAMEWORK
  211. vDSP_vsmul (src, 1, &multiplier, dest, 1, num);
  212. #elif JUCE_USE_ARM_NEON
  213. JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] += src[i], vmulq_n_f32(s, multiplier), JUCE_LOAD_SRC)
  214. #else
  215. #if JUCE_USE_SSE_INTRINSICS
  216. const __m128 mult = _mm_load1_ps (&multiplier);
  217. #endif
  218. JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] = src[i] * multiplier, _mm_mul_ps (mult, s),
  219. JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST)
  220. #endif
  221. }
  222. void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src, int num) noexcept
  223. {
  224. #if JUCE_USE_VDSP_FRAMEWORK
  225. vDSP_vadd (src, 1, dest, 1, dest, 1, num);
  226. #elif JUCE_USE_ARM_NEON
  227. JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] += src[i], vaddq_f32 (d, s), JUCE_LOAD_SRC_DEST)
  228. #else
  229. JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] += src[i], _mm_add_ps (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
  230. #endif
  231. }
  232. void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, float amount, int num) noexcept
  233. {
  234. #if JUCE_USE_ARM_NEON
  235. const float32x4_t amountToAdd = vld1q_dup_f32(&amount);
  236. JUCE_PERFORM_NEON_OP_DEST (dest[i] += amount, vaddq_f32 (d, amountToAdd), JUCE_LOAD_DEST)
  237. #else
  238. #if JUCE_USE_SSE_INTRINSICS
  239. const __m128 amountToAdd = _mm_load1_ps (&amount);
  240. #endif
  241. JUCE_PERFORM_SSE_OP_DEST (dest[i] += amount, _mm_add_ps (d, amountToAdd), JUCE_LOAD_DEST)
  242. #endif
  243. }
  244. void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (float* dest, const float* src, float multiplier, int num) noexcept
  245. {
  246. #if JUCE_USE_ARM_NEON
  247. JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] += src[i] * multiplier,
  248. vmlaq_n_f32 (d, s, multiplier),
  249. JUCE_LOAD_SRC_DEST)
  250. #else
  251. #if JUCE_USE_SSE_INTRINSICS
  252. const __m128 mult = _mm_load1_ps (&multiplier);
  253. #endif
  254. JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] += src[i] * multiplier,
  255. _mm_add_ps (d, _mm_mul_ps (mult, s)),
  256. JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
  257. #endif
  258. }
  259. void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src, int num) noexcept
  260. {
  261. #if JUCE_USE_VDSP_FRAMEWORK
  262. vDSP_vmul (src, 1, dest, 1, dest, 1, num);
  263. #elif JUCE_USE_ARM_NEON
  264. JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] *= src[i], vmulq_f32 (d, s), JUCE_LOAD_SRC_DEST)
  265. #else
  266. JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] *= src[i], _mm_mul_ps (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
  267. #endif
  268. }
  269. void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, float multiplier, int num) noexcept
  270. {
  271. #if JUCE_USE_VDSP_FRAMEWORK
  272. vDSP_vsmul (dest, 1, &multiplier, dest, 1, num);
  273. #elif JUCE_USE_ARM_NEON
  274. JUCE_PERFORM_NEON_OP_DEST (dest[i] *= multiplier, vmulq_n_f32 (d, multiplier), JUCE_LOAD_DEST)
  275. #else
  276. #if JUCE_USE_SSE_INTRINSICS
  277. const __m128 mult = _mm_load1_ps (&multiplier);
  278. #endif
  279. JUCE_PERFORM_SSE_OP_DEST (dest[i] *= multiplier, _mm_mul_ps (d, mult), JUCE_LOAD_DEST)
  280. #endif
  281. }
  282. void FloatVectorOperations::negate (float* dest, const float* src, int num) noexcept
  283. {
  284. #if JUCE_USE_VDSP_FRAMEWORK
  285. vDSP_vneg ((float*) src, 1, dest, 1, (vDSP_Length) num);
  286. #else
  287. copyWithMultiply (dest, src, -1.0f, num);
  288. #endif
  289. }
  290. void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, const int* src, float multiplier, int num) noexcept
  291. {
  292. #if JUCE_USE_ARM_NEON
  293. JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] = src[i] * multiplier,
  294. vmulq_n_f32 (vcvtq_f32_s32 (vld1q_s32 (src)), multiplier),
  295. JUCE_LOAD_NONE)
  296. #else
  297. #if JUCE_USE_SSE_INTRINSICS
  298. const __m128 mult = _mm_load1_ps (&multiplier);
  299. #endif
  300. JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] = src[i] * multiplier,
  301. _mm_mul_ps (mult, _mm_cvtepi32_ps (_mm_loadu_si128 ((const __m128i*) src))),
  302. JUCE_LOAD_NONE, JUCE_INCREMENT_SRC_DEST)
  303. #endif
  304. }
  305. void JUCE_CALLTYPE FloatVectorOperations::findMinAndMax (const float* src, int num, float& minResult, float& maxResult) noexcept
  306. {
  307. #if JUCE_USE_SSE_INTRINSICS
  308. const int numLongOps = num / 4;
  309. if (numLongOps > 1 && FloatVectorHelpers::isSSE2Available())
  310. {
  311. __m128 mn, mx;
  312. #define JUCE_MINMAX_SSE_LOOP(loadOp) \
  313. mn = loadOp (src); \
  314. mx = mn; \
  315. src += 4; \
  316. for (int i = 1; i < numLongOps; ++i) \
  317. { \
  318. const __m128 s = loadOp (src); \
  319. mn = _mm_min_ps (mn, s); \
  320. mx = _mm_max_ps (mx, s); \
  321. src += 4; \
  322. }
  323. if (FloatVectorHelpers::isAligned (src)) { JUCE_MINMAX_SSE_LOOP (_mm_load_ps) }
  324. else { JUCE_MINMAX_SSE_LOOP (_mm_loadu_ps) }
  325. float localMin, localMax;
  326. {
  327. float mns[4], mxs[4];
  328. _mm_storeu_ps (mns, mn);
  329. _mm_storeu_ps (mxs, mx);
  330. localMin = jmin (mns[0], mns[1], mns[2], mns[3]);
  331. localMax = jmax (mxs[0], mxs[1], mxs[2], mxs[3]);
  332. }
  333. num &= 3;
  334. for (int i = 0; i < num; ++i)
  335. {
  336. const float s = src[i];
  337. localMin = jmin (localMin, s);
  338. localMax = jmax (localMax, s);
  339. }
  340. minResult = localMin;
  341. maxResult = localMax;
  342. return;
  343. }
  344. #elif JUCE_USE_ARM_NEON
  345. const int numLongOps = num / 4;
  346. if (numLongOps > 1)
  347. {
  348. float32x4_t mn, mx;
  349. #define JUCE_MINMAX_NEON_LOOP(loadOp) \
  350. mn = loadOp (src); \
  351. mx = mn; \
  352. src += 4; \
  353. for (int i = 1; i < numLongOps; ++i) \
  354. { \
  355. const float32x4_t s = loadOp (src); \
  356. mn = vminq_f32 (mn, s); \
  357. mx = vmaxq_f32 (mx, s); \
  358. src += 4; \
  359. }
  360. JUCE_MINMAX_NEON_LOOP (vld1q_f32);
  361. float localMin, localMax;
  362. {
  363. float mns[4], mxs[4];
  364. vst1q_f32 (mns, mn);
  365. vst1q_f32 (mxs, mx);
  366. localMin = jmin (mns[0], mns[1], mns[2], mns[3]);
  367. localMax = jmax (mxs[0], mxs[1], mxs[2], mxs[3]);
  368. }
  369. num &= 3;
  370. for (int i = 0; i < num; ++i)
  371. {
  372. const float s = src[i];
  373. localMin = jmin (localMin, s);
  374. localMax = jmax (localMax, s);
  375. }
  376. minResult = localMin;
  377. maxResult = localMax;
  378. return;
  379. }
  380. #endif
  381. juce::findMinAndMax (src, num, minResult, maxResult);
  382. }
  383. float JUCE_CALLTYPE FloatVectorOperations::findMinimum (const float* src, int num) noexcept
  384. {
  385. #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
  386. return FloatVectorHelpers::findMinimumOrMaximum (src, num, true);
  387. #else
  388. return juce::findMinimum (src, num);
  389. #endif
  390. }
  391. float JUCE_CALLTYPE FloatVectorOperations::findMaximum (const float* src, int num) noexcept
  392. {
  393. #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
  394. return FloatVectorHelpers::findMinimumOrMaximum (src, num, false);
  395. #else
  396. return juce::findMaximum (src, num);
  397. #endif
  398. }
  399. void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnable) noexcept
  400. {
  401. #if JUCE_USE_SSE_INTRINSICS
  402. if (FloatVectorHelpers::isSSE2Available())
  403. _MM_SET_FLUSH_ZERO_MODE (shouldEnable ? _MM_FLUSH_ZERO_ON : _MM_FLUSH_ZERO_OFF);
  404. #endif
  405. (void) shouldEnable;
  406. }
  407. //==============================================================================
  408. //==============================================================================
  409. #if JUCE_UNIT_TESTS
  410. class FloatVectorOperationsTests : public UnitTest
  411. {
  412. public:
  413. FloatVectorOperationsTests() : UnitTest ("FloatVectorOperations") {}
  414. void runTest()
  415. {
  416. beginTest ("FloatVectorOperations");
  417. for (int i = 100; --i >= 0;)
  418. {
  419. const int num = getRandom().nextInt (500) + 1;
  420. HeapBlock<float> buffer1 (num + 16), buffer2 (num + 16);
  421. HeapBlock<int> buffer3 (num + 16);
  422. #if JUCE_ARM
  423. float* const data1 = buffer1;
  424. float* const data2 = buffer2;
  425. int* const int1 = buffer3;
  426. #else
  427. float* const data1 = addBytesToPointer (buffer1.getData(), getRandom().nextInt (16));
  428. float* const data2 = addBytesToPointer (buffer2.getData(), getRandom().nextInt (16));
  429. int* const int1 = addBytesToPointer (buffer3.getData(), getRandom().nextInt (16));
  430. #endif
  431. fillRandomly (data1, num);
  432. fillRandomly (data2, num);
  433. float mn1, mx1, mn2, mx2;
  434. FloatVectorOperations::findMinAndMax (data1, num, mn1, mx1);
  435. juce::findMinAndMax (data1, num, mn2, mx2);
  436. expect (mn1 == mn2);
  437. expect (mx1 == mx2);
  438. expect (FloatVectorOperations::findMinimum (data1, num) == juce::findMinimum (data1, num));
  439. expect (FloatVectorOperations::findMaximum (data1, num) == juce::findMaximum (data1, num));
  440. expect (FloatVectorOperations::findMinimum (data2, num) == juce::findMinimum (data2, num));
  441. expect (FloatVectorOperations::findMaximum (data2, num) == juce::findMaximum (data2, num));
  442. FloatVectorOperations::clear (data1, num);
  443. expect (areAllValuesEqual (data1, num, 0));
  444. FloatVectorOperations::fill (data1, 2.0f, num);
  445. expect (areAllValuesEqual (data1, num, 2.0f));
  446. FloatVectorOperations::add (data1, 2.0f, num);
  447. expect (areAllValuesEqual (data1, num, 4.0f));
  448. FloatVectorOperations::copy (data2, data1, num);
  449. expect (areAllValuesEqual (data2, num, 4.0f));
  450. FloatVectorOperations::add (data2, data1, num);
  451. expect (areAllValuesEqual (data2, num, 8.0f));
  452. FloatVectorOperations::copyWithMultiply (data2, data1, 4.0f, num);
  453. expect (areAllValuesEqual (data2, num, 16.0f));
  454. FloatVectorOperations::addWithMultiply (data2, data1, 4.0f, num);
  455. expect (areAllValuesEqual (data2, num, 32.0f));
  456. FloatVectorOperations::multiply (data1, 2.0f, num);
  457. expect (areAllValuesEqual (data1, num, 8.0f));
  458. FloatVectorOperations::multiply (data1, data2, num);
  459. expect (areAllValuesEqual (data1, num, 256.0f));
  460. FloatVectorOperations::negate (data2, data1, num);
  461. expect (areAllValuesEqual (data2, num, -256.0f));
  462. fillRandomly (int1, num);
  463. FloatVectorOperations::convertFixedToFloat (data1, int1, 2.0f, num);
  464. convertFixed (data2, int1, 2.0f, num);
  465. expect (buffersMatch (data1, data2, num));
  466. }
  467. }
  468. void fillRandomly (float* d, int num)
  469. {
  470. while (--num >= 0)
  471. *d++ = getRandom().nextFloat() * 1000.0f;
  472. }
  473. void fillRandomly (int* d, int num)
  474. {
  475. while (--num >= 0)
  476. *d++ = getRandom().nextInt();
  477. }
  478. static void convertFixed (float* d, const int* s, float multiplier, int num)
  479. {
  480. while (--num >= 0)
  481. *d++ = *s++ * multiplier;
  482. }
  483. static bool areAllValuesEqual (const float* d, int num, float target)
  484. {
  485. while (--num >= 0)
  486. if (*d++ != target)
  487. return false;
  488. return true;
  489. }
  490. static bool buffersMatch (const float* d1, const float* d2, int num)
  491. {
  492. while (--num >= 0)
  493. if (std::abs (*d1++ - *d2++) > std::numeric_limits<float>::epsilon())
  494. return false;
  495. return true;
  496. }
  497. };
  498. static FloatVectorOperationsTests vectorOpTests;
  499. #endif