32 namespace SIMDRegister_test_internal
36 template <
typename type>
39 static type next (
Random& random)
41 return static_cast<type
> (std::is_signed<type>::value ? (random.
nextFloat() * 16.0) - 8.0
47 template <
typename type>
50 static type next (
Random& random)
52 return static_cast<type
> (random.
nextInt64());
58 template <
typename type>
61 static std::complex<type> next (
Random& random)
68 template <
typename type>
71 static void fill (type* dst,
const int size,
Random& random)
73 for (
int i = 0; i < size; ++i)
80 template <
typename type>
83 static void fill (std::complex<type>* dst,
const int size,
Random& random)
85 for (
int i = 0; i < size; ++i)
90 template <
typename type>
108 template <
typename type>
109 static type safeAbs (type a)
111 return static_cast<type
> (std::abs (static_cast<double> (a)));
114 template <
typename type>
115 static type safeAbs (std::complex<type> a)
120 template <
typename type>
121 static double difference (type a)
123 return static_cast<double> (safeAbs (a));
126 template <
typename type>
127 static double difference (type a, type b)
129 return difference (a - b);
140 :
UnitTest (
"SIMDRegister UnitTests", UnitTestCategories::dsp)
145 template <
typename type>
157 for (
size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i)
158 if (elements[i] != scalar)
return false;
163 template <
typename type>
170 for (
size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i)
172 double delta = SIMDRegister_test_internal::difference (ptr[i], array[i]);
175 DBG (
"a: " << SIMDRegister_test_internal::difference (ptr[i]) <<
" b: " << SIMDRegister_test_internal::difference (array[i]) <<
" difference: " << delta);
183 template <
typename type>
192 for (
size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i)
201 template <
typename typeOne,
typename typeTwo>
202 static void inplace (typeOne& a,
const typeTwo& b)
207 template <
typename typeOne,
typename typeTwo>
208 static typeOne outofplace (
const typeOne& a,
const typeTwo& b)
216 template <
typename typeOne,
typename typeTwo>
217 static void inplace (typeOne& a,
const typeTwo& b)
222 template <
typename typeOne,
typename typeTwo>
223 static typeOne outofplace (
const typeOne& a,
const typeTwo& b)
231 template <
typename typeOne,
typename typeTwo>
232 static void inplace (typeOne& a,
const typeTwo& b)
237 template <
typename typeOne,
typename typeTwo>
238 static typeOne outofplace (
const typeOne& a,
const typeTwo& b)
246 template <
typename typeOne,
typename typeTwo>
247 static void inplace (typeOne& a,
const typeTwo& b)
252 template <
typename typeOne,
typename typeTwo>
253 static typeOne outofplace (
const typeOne& a,
const typeTwo& b)
261 template <
typename typeOne,
typename typeTwo>
262 static void inplace (typeOne& a,
const typeTwo& b)
267 template <
typename typeOne,
typename typeTwo>
268 static typeOne outofplace (
const typeOne& a,
const typeTwo& b)
276 template <
typename typeOne,
typename typeTwo>
277 static void inplace (typeOne& a,
const typeTwo& b)
282 template <
typename typeOne,
typename typeTwo>
283 static typeOne outofplace (
const typeOne& a,
const typeTwo& b)
293 template <
typename type>
307 u.
expect (vecEqualToArray (a, elements));
310 a *=
static_cast<type
> (2);
312 u.
expect (vecEqualToArray (b, elements));
319 template <
typename type>
329 for (
size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i)
332 u.
expect (vecEqualToArray (a, array));
337 for (
size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i)
338 u.
expect (b[i] == array[i]);
342 template <
class Operation>
345 template <
typename type>
348 for (
int n = 0; n < 100; ++n)
363 copy (a, array_a); copy (b, array_b); copy (c, array_c);
366 for (
size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i)
367 Operation::template inplace<type, type> (array_a[i], array_b[i]);
371 u.
expect (vecEqualToArray (a, array_a));
372 u.
expect (vecEqualToArray (b, array_b));
378 copy (a, array_a); copy (b, array_b); copy (c, array_c);
381 for (
size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i)
382 Operation::template inplace<type, type> (array_b[i], static_cast<type> (2));
384 Operation::template inplace<SIMDRegister<type>, type> (b, 2);
386 u.
expect (vecEqualToArray (a, array_a));
387 u.
expect (vecEqualToArray (b, array_b));
393 copy (a, array_a); copy (b, array_b); copy (c, array_c);
396 for (
size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i)
397 array_c[i] = Operation::template outofplace<type, type> (array_a[i], array_b[i]);
401 u.
expect (vecEqualToArray (a, array_a));
402 u.
expect (vecEqualToArray (b, array_b));
403 u.
expect (vecEqualToArray (c, array_c));
406 for (
size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i)
407 array_c[i] = Operation::template outofplace<type, type> (array_b[i], static_cast<type> (2));
409 c = Operation::template outofplace<SIMDRegister<type>, type> (b, 2);
411 u.
expect (vecEqualToArray (a, array_a));
412 u.
expect (vecEqualToArray (b, array_b));
413 u.
expect (vecEqualToArray (c, array_c));
418 template <
class Operation>
421 template <
typename type>
427 for (
int n = 0; n < 100; ++n)
433 union ConversionUnion
435 inline ConversionUnion() : floatVersion (static_cast<type> (0)) {}
436 inline ~ConversionUnion() {}
438 vMaskType intVersion;
441 vMaskType bitmask = vMaskType::expand (static_cast<MaskType> (1) << (
sizeof (MaskType) - 1));
443 copy (a.floatVersion, array_a);
444 copy (b.floatVersion, array_a);
446 Operation::template inplace<SIMDRegister<type>, vMaskType> (a.floatVersion, bitmask);
447 Operation::template inplace<vMaskType, vMaskType> (b.intVersion, bitmask);
454 b.floatVersion.copyToRawArray (elements);
456 u.
expect (vecEqualToArray (a.floatVersion, elements));
475 memcpy (array_c, float_c,
sizeof (type) * SIMDRegister<type>::SIMDNumElements);
476 copy (a, float_a); copy (b, array_b); copy (c, float_c);
479 for (
size_t i = 0; i < SIMDRegister<MaskType>::SIMDNumElements; ++i)
480 Operation::template inplace<MaskType, MaskType> (array_a[i], array_b[i]);
481 memcpy (float_a, array_a,
sizeof (type) * SIMDRegister<type>::SIMDNumElements);
483 Operation::template inplace<SIMDRegister<type>, vMaskType> (a, b);
485 u.
expect (vecEqualToArray (a, float_a));
486 u.
expect (vecEqualToArray (b, array_b));
491 memcpy (array_a, float_a,
sizeof (type) * SIMDRegister<type>::SIMDNumElements);
492 memcpy (array_c, float_c,
sizeof (type) * SIMDRegister<type>::SIMDNumElements);
493 copy (a, float_a); copy (b, array_b); copy (c, float_c);
496 for (
size_t i = 0; i < SIMDRegister<MaskType>::SIMDNumElements; ++i)
497 Operation::template inplace<MaskType, MaskType> (array_a[i], static_cast<MaskType> (9));
498 memcpy (float_a, array_a,
sizeof (type) * SIMDRegister<type>::SIMDNumElements);
500 Operation::template inplace<SIMDRegister<type>, MaskType> (a,
static_cast<MaskType
> (9));
502 u.
expect (vecEqualToArray (a, float_a));
503 u.
expect (vecEqualToArray (b, array_b));
509 memcpy (array_a, float_a,
sizeof (type) * SIMDRegister<type>::SIMDNumElements);
510 memcpy (array_c, float_c,
sizeof (type) * SIMDRegister<type>::SIMDNumElements);
511 copy (a, float_a); copy (b, array_b); copy (c, float_c);
514 for (
size_t i = 0; i < SIMDRegister<MaskType>::SIMDNumElements; ++i)
517 Operation::template outofplace<MaskType, MaskType> (array_a[i], array_b[i]);
519 memcpy (float_a, array_a,
sizeof (type) * SIMDRegister<type>::SIMDNumElements);
520 memcpy (float_c, array_c,
sizeof (type) * SIMDRegister<type>::SIMDNumElements);
522 c = Operation::template outofplace<SIMDRegister<type>, vMaskType> (a, b);
524 u.
expect (vecEqualToArray (a, float_a));
525 u.
expect (vecEqualToArray (b, array_b));
526 u.
expect (vecEqualToArray (c, float_c));
529 for (
size_t i = 0; i < SIMDRegister<MaskType>::SIMDNumElements; ++i)
530 array_c[i] = Operation::template outofplace<MaskType, MaskType> (array_a[i], static_cast<MaskType> (9));
531 memcpy (float_a, array_a,
sizeof (type) * SIMDRegister<type>::SIMDNumElements);
532 memcpy (float_c, array_c,
sizeof (type) * SIMDRegister<type>::SIMDNumElements);
534 c = Operation::template outofplace<SIMDRegister<type>, MaskType> (a,
static_cast<MaskType
> (9));
536 u.
expect (vecEqualToArray (a, float_a));
537 u.
expect (vecEqualToArray (b, array_b));
538 u.
expect (vecEqualToArray (c, float_c));
545 template <
typename type>
551 for (
int i = 0; i < 100; ++i)
568 for (
size_t j = 0; j < SIMDRegister<type>::SIMDNumElements; ++j)
570 array_eq [j] = (array_a[j] == array_b[j]) ? static_cast<MaskType> (-1) : 0;
571 array_neq [j] = (array_a[j] != array_b[j]) ? static_cast<MaskType> (-1) : 0;
572 array_lt [j] = (array_a[j] < array_b[j]) ? static_cast<MaskType> (-1) : 0;
573 array_le [j] = (array_a[j] <= array_b[j]) ? static_cast<MaskType> (-1) : 0;
574 array_gt [j] = (array_a[j] > array_b[j]) ? static_cast<MaskType> (-1) : 0;
575 array_ge [j] = (array_a[j] >= array_b[j]) ? static_cast<MaskType> (-1) : 0;
581 vMaskType eq, neq, lt, le, gt, ge;
593 u.
expect (vecEqualToArray (eq, array_eq ));
594 u.
expect (vecEqualToArray (neq, array_neq));
595 u.
expect (vecEqualToArray (lt, array_lt ));
596 u.
expect (vecEqualToArray (le, array_le ));
597 u.
expect (vecEqualToArray (gt, array_gt ));
598 u.
expect (vecEqualToArray (ge, array_ge ));
626 u.
expect (! (a != scalar));
631 u.
expect (! (a == scalar));
638 template <
typename type>
653 for (
size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i)
654 array_d[i] = array_a[i] + (array_b[i] * array_c[i]);
664 u.
expect (vecEqualToArray (d, array_d));
670 template <
typename type>
673 for (
int i = 0; i < 100; ++i)
680 for (
size_t j = 0; j < SIMDRegister<type>::SIMDNumElements; ++j)
682 array_a[j] =
static_cast<type
> (random.
nextInt (127));
683 array_b[j] =
static_cast<type
> (random.
nextInt (127));
686 for (
size_t j = 0; j < SIMDRegister<type>::SIMDNumElements; ++j)
688 array_min[j] = (array_a[j] < array_b[j]) ? array_a[j] : array_b[j];
689 array_max[j] = (array_a[j] > array_b[j]) ? array_a[j] : array_b[j];
703 u.
expect (vecEqualToArray (vMin, array_min));
704 u.
expect (vecEqualToArray (vMax, array_max));
706 copy (vMin, array_a);
707 copy (vMax, array_a);
712 u.
expect (vecEqualToArray (vMin, array_min));
713 u.
expect (vecEqualToArray (vMax, array_max));
720 template <
typename type>
728 for (
size_t j = 0; j < SIMDRegister<type>::SIMDNumElements; ++j)
730 sumCheck += array[j];
736 u.
expect (SIMDRegister_test_internal::difference (sumCheck, a.
sum()) < 1e-4);
742 template <
typename type>
754 auto calcAbs = [] (type x) -> type {
return x >= type (0) ? x : -x; };
756 for (
size_t j = 0; j < SIMDRegister<type>::SIMDNumElements; ++j)
757 outArray[j] = calcAbs (inArray[j]);
759 u.
expect (vecEqualToArray (a, outArray));
765 template <
typename type>
777 for (
size_t j = 0; j < SIMDRegister<type>::SIMDNumElements; ++j)
778 outArray[j] = (type) (int) inArray[j];
780 u.
expect (vecEqualToArray (a, outArray));
786 template <
typename type>
789 bool is_signed = std::is_signed<type>::value;
792 auto value = is_signed ?
static_cast<type
> ((random.
nextFloat() * 16.0) - 8.0)
793 :
static_cast<type
> (random.
nextFloat() * 8.0);
800 u.
expect (! (a != value));
804 u.
expect (! (a == value));
822 template <
class TheTest>
823 void runTestFloatingPoint (
const char* unitTestName)
825 beginTest (unitTestName);
827 Random random = getRandom();
829 TheTest::template run<float> (*
this, random);
830 TheTest::template run<double> (*
this, random);
834 template <
class TheTest>
835 void runTestForAllTypes (
const char* unitTestName)
837 beginTest (unitTestName);
839 Random random = getRandom();
841 TheTest::template run<float> (*
this, random);
842 TheTest::template run<double> (*
this, random);
843 TheTest::template run<int8_t> (*
this, random);
844 TheTest::template run<uint8_t> (*
this, random);
845 TheTest::template run<int16_t> (*
this, random);
846 TheTest::template run<uint16_t>(*
this, random);
847 TheTest::template run<int32_t> (*
this, random);
848 TheTest::template run<uint32_t>(*
this, random);
849 TheTest::template run<int64_t> (*
this, random);
850 TheTest::template run<uint64_t>(*
this, random);
851 TheTest::template run<std::complex<float>> (*
this, random);
852 TheTest::template run<std::complex<double>> (*
this, random);
855 template <
class TheTest>
856 void runTestNonComplex (
const char* unitTestName)
858 beginTest (unitTestName);
860 Random random = getRandom();
862 TheTest::template run<float> (*
this, random);
863 TheTest::template run<double> (*
this, random);
864 TheTest::template run<int8_t> (*
this, random);
865 TheTest::template run<uint8_t> (*
this, random);
866 TheTest::template run<int16_t> (*
this, random);
867 TheTest::template run<uint16_t>(*
this, random);
868 TheTest::template run<int32_t> (*
this, random);
869 TheTest::template run<uint32_t>(*
this, random);
870 TheTest::template run<int64_t> (*
this, random);
871 TheTest::template run<uint64_t>(*
this, random);
874 template <
class TheTest>
875 void runTestSigned (
const char* unitTestName)
877 beginTest (unitTestName);
879 Random random = getRandom();
881 TheTest::template run<float> (*
this, random);
882 TheTest::template run<double> (*
this, random);
883 TheTest::template run<int8_t> (*
this, random);
884 TheTest::template run<int16_t> (*
this, random);
885 TheTest::template run<int32_t> (*
this, random);
886 TheTest::template run<int64_t> (*
this, random);
891 runTestForAllTypes<InitializationTest> (
"InitializationTest");
893 runTestForAllTypes<AccessTest> (
"AccessTest");
895 runTestForAllTypes<OperatorTests<Addition>> (
"AdditionOperators");
896 runTestForAllTypes<OperatorTests<Subtraction>> (
"SubtractionOperators");
897 runTestForAllTypes<OperatorTests<Multiplication>> (
"MultiplicationOperators");
899 runTestForAllTypes<BitOperatorTests<BitAND>> (
"BitANDOperators");
900 runTestForAllTypes<BitOperatorTests<BitOR>> (
"BitOROperators");
901 runTestForAllTypes<BitOperatorTests<BitXOR>> (
"BitXOROperators");
903 runTestNonComplex<CheckComparisonOps> (
"CheckComparisons");
904 runTestNonComplex<CheckBoolEquals> (
"CheckBoolEquals");
905 runTestNonComplex<CheckMinMax> (
"CheckMinMax");
907 runTestForAllTypes<CheckMultiplyAdd> (
"CheckMultiplyAdd");
908 runTestForAllTypes<CheckSum> (
"CheckSum");
910 runTestSigned<CheckAbs> (
"CheckAbs");
912 runTestFloatingPoint<CheckTruncate> (
"CheckTruncate");
static vMaskType JUCE_VECTOR_CALLTYPE greaterThanOrEqual(SIMDRegister a, SIMDRegister b) noexcept
Returns a SIMDRegister of the corresponding integral type where each element has each bit set if the ...
typename SIMDInternal::MaskTypeFor< ElementType >::type MaskType
The corresponding primitive integer type, for example, this will be int32_t if type is a float...
static SIMDRegister JUCE_VECTOR_CALLTYPE abs(SIMDRegister a) noexcept
Returns the absolute value of each element.
ElementType * getData() const noexcept
Returns a raw pointer to the allocated data.
static vMaskType JUCE_VECTOR_CALLTYPE lessThan(SIMDRegister a, SIMDRegister b) noexcept
Returns a SIMDRegister of the corresponding integral type where each element has each bit set if the ...
int nextInt() noexcept
Returns the next random 32 bit integer.
ElementType sum() const noexcept
Returns a scalar which is the sum of all elements of the receiver.
static SIMDRegister JUCE_VECTOR_CALLTYPE min(SIMDRegister a, SIMDRegister b) noexcept
Returns a new vector where each element is the minimum of the corresponding element of a and b...
Very simple container class to hold a pointer to some data on the heap.
static SIMDRegister JUCE_VECTOR_CALLTYPE truncate(SIMDRegister a) noexcept
Truncates each element to its integer part.
A wrapper around the platform's native SIMD register type.
static SIMDRegister JUCE_VECTOR_CALLTYPE multiplyAdd(SIMDRegister a, const SIMDRegister b, SIMDRegister c) noexcept
Multiplies b and c and adds the result to a.
static SIMDRegister JUCE_VECTOR_CALLTYPE expand(ElementType s) noexcept
Creates a new SIMDRegister from the corresponding scalar primitive.
int64 nextInt64() noexcept
Returns the next 64-bit random number.
This is a base class for classes that perform a unit test.
static vMaskType JUCE_VECTOR_CALLTYPE notEqual(SIMDRegister a, SIMDRegister b) noexcept
Returns a SIMDRegister of the corresponding integral type where each element has each bit set if the ...
static vMaskType JUCE_VECTOR_CALLTYPE greaterThan(SIMDRegister a, SIMDRegister b) noexcept
Returns a SIMDRegister of the corresponding integral type where each element has each bit set if the ...
void JUCE_VECTOR_CALLTYPE copyToRawArray(ElementType *a) const noexcept
Copies the elements of the SIMDRegister to a scalar array in memory.
static SIMDRegister JUCE_VECTOR_CALLTYPE fromRawArray(const ElementType *a) noexcept
Creates a new SIMDRegister from the first SIMDNumElements of a scalar array.
static vMaskType JUCE_VECTOR_CALLTYPE equal(SIMDRegister a, SIMDRegister b) noexcept
Returns a SIMDRegister of the corresponding integral type where each element has each bit set if the ...
void expect(bool testResult, const String &failureMessage=String())
Checks that the result of a test is true, and logs this result.
static ElementType * getNextSIMDAlignedPtr(ElementType *ptr) noexcept
Returns the next position in memory where isSIMDAligned returns true.
float nextFloat() noexcept
Returns the next random floating-point number.
A random number generator.
static vMaskType JUCE_VECTOR_CALLTYPE lessThanOrEqual(SIMDRegister a, SIMDRegister b) noexcept
Returns a SIMDRegister of the corresponding integral type where each element has each bit set if the ...
void runTest()
Implement this method in your subclass to actually run your tests.
static SIMDRegister JUCE_VECTOR_CALLTYPE max(SIMDRegister a, SIMDRegister b) noexcept
Returns a new vector where each element is the maximum of the corresponding element of a and b...