1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

SIMDRegister Test: Tidy up template functions

This commit is contained in:
reuk 2022-03-22 16:02:40 +00:00
parent ebac835673
commit c6f703aa57
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C

View file

@ -39,7 +39,6 @@ namespace SIMDRegister_test_internal
{
return static_cast<type> (std::is_signed<type>::value ? (random.nextFloat() * 16.0) - 8.0
: (random.nextFloat() * 8.0));
}
};
@ -49,11 +48,15 @@ namespace SIMDRegister_test_internal
static type next (Random& random)
{
return static_cast<type> (random.nextInt64());
}
};
template <typename type> struct RandomValue { static type next (Random& random) { return RandomPrimitive<type>::next (random); } };
template <typename type>
struct RandomValue
{
static type next (Random& random) { return RandomPrimitive<type>::next (random); }
};
template <typename type>
struct RandomValue<std::complex<type>>
{
@ -63,45 +66,14 @@ namespace SIMDRegister_test_internal
}
};
template <typename type>
struct VecFiller
static void fillVec (type* dst, Random& random)
{
static void fill (type* dst, const int size, Random& random)
std::generate_n (dst, SIMDRegister<type>::SIMDNumElements, [&]
{
for (int i = 0; i < size; ++i)
dst[i] = RandomValue<type>::next (random);
}
};
// We need to specialise for complex types: otherwise GCC 6 gives
// us an ICE internal compiler error after which the compiler seg faults.
template <typename type>
struct VecFiller<std::complex<type>>
{
static void fill (std::complex<type>* dst, const int size, Random& random)
{
for (int i = 0; i < size; ++i)
dst[i] = std::complex<type> (RandomValue<type>::next (random), RandomValue<type>::next (random));
}
};
template <typename type>
struct VecFiller<SIMDRegister<type>>
{
static SIMDRegister<type> fill (Random& random)
{
constexpr int size = (int) SIMDRegister<type>::SIMDNumElements;
#ifdef _MSC_VER
__declspec(align(sizeof (SIMDRegister<type>))) type elements[size];
#else
type elements[(size_t) size] __attribute__((aligned(sizeof (SIMDRegister<type>))));
#endif
VecFiller<type>::fill (elements, size, random);
return SIMDRegister<type>::fromRawArray (elements);
}
};
return RandomValue<type>::next (random);
});
}
// Avoid visual studio warning
template <typename type>
@ -127,7 +99,7 @@ namespace SIMDRegister_test_internal
{
return difference (a - b);
}
}
} // namespace SIMDRegister_test_internal
// These tests need to be strictly run on all platforms supported by JUCE as the
// SIMD code is highly platform dependent.
@ -135,6 +107,8 @@ namespace SIMDRegister_test_internal
class SIMDRegisterUnitTests : public UnitTest
{
public:
template <typename> struct Tag {};
SIMDRegisterUnitTests()
: UnitTest ("SIMDRegister UnitTests", UnitTestCategories::dsp)
{}
@ -290,7 +264,7 @@ public:
struct InitializationTest
{
template <typename type>
static void run (UnitTest& u, Random& random)
static void run (UnitTest& u, Random& random, Tag<type>)
{
u.expect (allValuesEqualTo<type> (SIMDRegister<type>::expand (static_cast<type> (23)), 23));
@ -300,7 +274,7 @@ public:
#else
type elements[SIMDRegister<type>::SIMDNumElements] __attribute__((aligned(sizeof (SIMDRegister<type>))));
#endif
SIMDRegister_test_internal::VecFiller<type>::fill (elements, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (elements, random);
SIMDRegister<type> a (SIMDRegister<type>::fromRawArray (elements));
u.expect (vecEqualToArray (a, elements));
@ -316,13 +290,13 @@ public:
struct AccessTest
{
template <typename type>
static void run (UnitTest& u, Random& random)
static void run (UnitTest& u, Random& random, Tag<type>)
{
// set-up
SIMDRegister<type> a;
type array [SIMDRegister<type>::SIMDNumElements];
SIMDRegister_test_internal::VecFiller<type>::fill (array, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (array, random);
// Test non-const access operator
for (size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i)
@ -342,7 +316,7 @@ public:
struct OperatorTests
{
template <typename type>
static void run (UnitTest& u, Random& random)
static void run (UnitTest& u, Random& random, Tag<type>)
{
for (int n = 0; n < 100; ++n)
{
@ -355,9 +329,9 @@ public:
type array_b [SIMDRegister<type>::SIMDNumElements];
type array_c [SIMDRegister<type>::SIMDNumElements];
SIMDRegister_test_internal::VecFiller<type>::fill (array_a, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<type>::fill (array_b, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<type>::fill (array_c, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (array_a, random);
SIMDRegister_test_internal::fillVec (array_b, random);
SIMDRegister_test_internal::fillVec (array_c, random);
copy (a, array_a); copy (b, array_b); copy (c, array_c);
@ -370,9 +344,9 @@ public:
u.expect (vecEqualToArray (a, array_a));
u.expect (vecEqualToArray (b, array_b));
SIMDRegister_test_internal::VecFiller<type>::fill (array_a, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<type>::fill (array_b, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<type>::fill (array_c, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (array_a, random);
SIMDRegister_test_internal::fillVec (array_b, random);
SIMDRegister_test_internal::fillVec (array_c, random);
copy (a, array_a); copy (b, array_b); copy (c, array_c);
@ -386,9 +360,9 @@ public:
u.expect (vecEqualToArray (b, array_b));
// set-up again
SIMDRegister_test_internal::VecFiller<type>::fill (array_a, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<type>::fill (array_b, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<type>::fill (array_c, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (array_a, random);
SIMDRegister_test_internal::fillVec (array_b, random);
SIMDRegister_test_internal::fillVec (array_c, random);
copy (a, array_a); copy (b, array_b); copy (c, array_c);
// test out-of-place with both params being vectors
@ -418,7 +392,7 @@ public:
struct BitOperatorTests
{
template <typename type>
static void run (UnitTest& u, Random& random)
static void run (UnitTest& u, Random& random, Tag<type>)
{
typedef typename SIMDRegister<type>::vMaskType vMaskType;
typedef typename SIMDRegister<type>::MaskType MaskType;
@ -438,7 +412,7 @@ public:
} a, b;
vMaskType bitmask = vMaskType::expand (static_cast<MaskType> (1) << (sizeof (MaskType) - 1));
SIMDRegister_test_internal::VecFiller<type>::fill (array_a, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (array_a, random);
copy (a.floatVersion, array_a);
copy (b.floatVersion, array_a);
@ -466,9 +440,9 @@ public:
type float_a [SIMDRegister<type>::SIMDNumElements];
type float_c [SIMDRegister<type>::SIMDNumElements];
SIMDRegister_test_internal::VecFiller<type>::fill (float_a, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<MaskType>::fill (array_b, SIMDRegister<MaskType>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<type>::fill (float_c, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (float_a, random);
SIMDRegister_test_internal::fillVec (array_b, random);
SIMDRegister_test_internal::fillVec (float_c, random);
memcpy (array_a, float_a, sizeof (type) * SIMDRegister<type>::SIMDNumElements);
memcpy (array_c, float_c, sizeof (type) * SIMDRegister<type>::SIMDNumElements);
@ -484,9 +458,9 @@ public:
u.expect (vecEqualToArray (a, float_a));
u.expect (vecEqualToArray (b, array_b));
SIMDRegister_test_internal::VecFiller<type>::fill (float_a, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<MaskType>::fill (array_b, SIMDRegister<MaskType>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<type>::fill (float_c, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (float_a, random);
SIMDRegister_test_internal::fillVec (array_b, random);
SIMDRegister_test_internal::fillVec (float_c, random);
memcpy (array_a, float_a, sizeof (type) * SIMDRegister<type>::SIMDNumElements);
memcpy (array_c, float_c, sizeof (type) * SIMDRegister<type>::SIMDNumElements);
copy (a, float_a); copy (b, array_b); copy (c, float_c);
@ -502,9 +476,9 @@ public:
u.expect (vecEqualToArray (b, array_b));
// set-up again
SIMDRegister_test_internal::VecFiller<type>::fill (float_a, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<MaskType>::fill (array_b, SIMDRegister<MaskType>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<type>::fill (float_c, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (float_a, random);
SIMDRegister_test_internal::fillVec (array_b, random);
SIMDRegister_test_internal::fillVec (float_c, random);
memcpy (array_a, float_a, sizeof (type) * SIMDRegister<type>::SIMDNumElements);
memcpy (array_c, float_c, sizeof (type) * SIMDRegister<type>::SIMDNumElements);
copy (a, float_a); copy (b, array_b); copy (c, float_c);
@ -542,7 +516,7 @@ public:
struct CheckComparisonOps
{
template <typename type>
static void run (UnitTest& u, Random& random)
static void run (UnitTest& u, Random& random, Tag<type>)
{
typedef typename SIMDRegister<type>::vMaskType vMaskType;
typedef typename SIMDRegister<type>::MaskType MaskType;
@ -560,8 +534,8 @@ public:
MaskType array_ge [SIMDRegister<type>::SIMDNumElements];
SIMDRegister_test_internal::VecFiller<type>::fill (array_a, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<type>::fill (array_b, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (array_a, random);
SIMDRegister_test_internal::fillVec (array_b, random);
// do check
for (size_t j = 0; j < SIMDRegister<type>::SIMDNumElements; ++j)
@ -598,8 +572,8 @@ public:
do
{
SIMDRegister_test_internal::VecFiller<type>::fill (array_a, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<type>::fill (array_b, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (array_a, random);
SIMDRegister_test_internal::fillVec (array_b, random);
} while (std::equal (array_a, array_a + SIMDRegister<type>::SIMDNumElements, array_b));
copy (a, array_a);
@ -609,7 +583,7 @@ public:
u.expect (! (a == b));
u.expect (! (b == a));
SIMDRegister_test_internal::VecFiller<type>::fill (array_a, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (array_a, random);
copy (a, array_a);
copy (b, array_a);
@ -635,7 +609,7 @@ public:
struct CheckMultiplyAdd
{
template <typename type>
static void run (UnitTest& u, Random& random)
static void run (UnitTest& u, Random& random, Tag<type>)
{
// set-up
type array_a [SIMDRegister<type>::SIMDNumElements];
@ -643,10 +617,10 @@ public:
type array_c [SIMDRegister<type>::SIMDNumElements];
type array_d [SIMDRegister<type>::SIMDNumElements];
SIMDRegister_test_internal::VecFiller<type>::fill (array_a, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<type>::fill (array_b, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<type>::fill (array_c, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::VecFiller<type>::fill (array_d, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (array_a, random);
SIMDRegister_test_internal::fillVec (array_b, random);
SIMDRegister_test_internal::fillVec (array_c, random);
SIMDRegister_test_internal::fillVec (array_d, random);
// check
for (size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i)
@ -667,7 +641,7 @@ public:
struct CheckMinMax
{
template <typename type>
static void run (UnitTest& u, Random& random)
static void run (UnitTest& u, Random& random, Tag<type>)
{
for (int i = 0; i < 100; ++i)
{
@ -717,17 +691,14 @@ public:
struct CheckSum
{
template <typename type>
static void run (UnitTest& u, Random& random)
static void run (UnitTest& u, Random& random, Tag<type>)
{
type array [SIMDRegister<type>::SIMDNumElements];
type sumCheck = 0;
SIMDRegister_test_internal::VecFiller<type>::fill (array, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (array, random);
for (size_t j = 0; j < SIMDRegister<type>::SIMDNumElements; ++j)
{
sumCheck += array[j];
}
using AddedType = decltype (type{} + type{});
const auto sumCheck = (type) std::accumulate (std::begin (array), std::end (array), AddedType{});
SIMDRegister<type> a;
copy (a, array);
@ -739,12 +710,12 @@ public:
struct CheckAbs
{
template <typename type>
static void run (UnitTest& u, Random& random)
static void run (UnitTest& u, Random& random, Tag<type>)
{
type inArray[SIMDRegister<type>::SIMDNumElements];
type outArray[SIMDRegister<type>::SIMDNumElements];
SIMDRegister_test_internal::VecFiller<type>::fill (inArray, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (inArray, random);
SIMDRegister<type> a;
copy (a, inArray);
@ -762,12 +733,12 @@ public:
struct CheckTruncate
{
template <typename type>
static void run (UnitTest& u, Random& random)
static void run (UnitTest& u, Random& random, Tag<type>)
{
type inArray[SIMDRegister<type>::SIMDNumElements];
type outArray[SIMDRegister<type>::SIMDNumElements];
SIMDRegister_test_internal::VecFiller<type>::fill (inArray, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (inArray, random);
SIMDRegister<type> a;
copy (a, inArray);
@ -783,7 +754,7 @@ public:
struct CheckBoolEquals
{
template <typename type>
static void run (UnitTest& u, Random& random)
static void run (UnitTest& u, Random& random, Tag<type>)
{
bool is_signed = std::is_signed<type>::value;
type array [SIMDRegister<type>::SIMDNumElements];
@ -802,14 +773,14 @@ public:
u.expect (a != value);
u.expect (! (a == value));
SIMDRegister_test_internal::VecFiller<type>::fill (array, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (array, random);
copy (a, array);
copy (b, array);
u.expect (a == b);
u.expect (! (a != b));
SIMDRegister_test_internal::VecFiller<type>::fill (array, SIMDRegister<type>::SIMDNumElements, random);
SIMDRegister_test_internal::fillVec (array, random);
copy (b, array);
u.expect (a != b);
@ -819,96 +790,96 @@ public:
//==============================================================================
template <class TheTest>
void runTestFloatingPoint (const char* unitTestName)
void runTestFloatingPoint (const char* unitTestName, TheTest)
{
beginTest (unitTestName);
Random random = getRandom();
TheTest::template run<float> (*this, random);
TheTest::template run<double> (*this, random);
TheTest::run (*this, random, Tag<float> {});
TheTest::run (*this, random, Tag<double>{});
}
//==============================================================================
template <class TheTest>
void runTestForAllTypes (const char* unitTestName)
void runTestForAllTypes (const char* unitTestName, TheTest)
{
beginTest (unitTestName);
Random random = getRandom();
TheTest::template run<float> (*this, random);
TheTest::template run<double> (*this, random);
TheTest::template run<int8_t> (*this, random);
TheTest::template run<uint8_t> (*this, random);
TheTest::template run<int16_t> (*this, random);
TheTest::template run<uint16_t>(*this, random);
TheTest::template run<int32_t> (*this, random);
TheTest::template run<uint32_t>(*this, random);
TheTest::template run<int64_t> (*this, random);
TheTest::template run<uint64_t>(*this, random);
TheTest::template run<std::complex<float>> (*this, random);
TheTest::template run<std::complex<double>> (*this, random);
TheTest::run (*this, random, Tag<float> {});
TheTest::run (*this, random, Tag<double> {});
TheTest::run (*this, random, Tag<int8_t> {});
TheTest::run (*this, random, Tag<uint8_t> {});
TheTest::run (*this, random, Tag<int16_t> {});
TheTest::run (*this, random, Tag<uint16_t> {});
TheTest::run (*this, random, Tag<int32_t> {});
TheTest::run (*this, random, Tag<uint32_t> {});
TheTest::run (*this, random, Tag<int64_t> {});
TheTest::run (*this, random, Tag<uint64_t> {});
TheTest::run (*this, random, Tag<std::complex<float>> {});
TheTest::run (*this, random, Tag<std::complex<double>>{});
}
template <class TheTest>
void runTestNonComplex (const char* unitTestName)
void runTestNonComplex (const char* unitTestName, TheTest)
{
beginTest (unitTestName);
Random random = getRandom();
TheTest::template run<float> (*this, random);
TheTest::template run<double> (*this, random);
TheTest::template run<int8_t> (*this, random);
TheTest::template run<uint8_t> (*this, random);
TheTest::template run<int16_t> (*this, random);
TheTest::template run<uint16_t>(*this, random);
TheTest::template run<int32_t> (*this, random);
TheTest::template run<uint32_t>(*this, random);
TheTest::template run<int64_t> (*this, random);
TheTest::template run<uint64_t>(*this, random);
TheTest::run (*this, random, Tag<float> {});
TheTest::run (*this, random, Tag<double> {});
TheTest::run (*this, random, Tag<int8_t> {});
TheTest::run (*this, random, Tag<uint8_t> {});
TheTest::run (*this, random, Tag<int16_t> {});
TheTest::run (*this, random, Tag<uint16_t>{});
TheTest::run (*this, random, Tag<int32_t> {});
TheTest::run (*this, random, Tag<uint32_t>{});
TheTest::run (*this, random, Tag<int64_t> {});
TheTest::run (*this, random, Tag<uint64_t>{});
}
template <class TheTest>
void runTestSigned (const char* unitTestName)
void runTestSigned (const char* unitTestName, TheTest)
{
beginTest (unitTestName);
Random random = getRandom();
TheTest::template run<float> (*this, random);
TheTest::template run<double> (*this, random);
TheTest::template run<int8_t> (*this, random);
TheTest::template run<int16_t> (*this, random);
TheTest::template run<int32_t> (*this, random);
TheTest::template run<int64_t> (*this, random);
TheTest::run (*this, random, Tag<float> {});
TheTest::run (*this, random, Tag<double> {});
TheTest::run (*this, random, Tag<int8_t> {});
TheTest::run (*this, random, Tag<int16_t>{});
TheTest::run (*this, random, Tag<int32_t>{});
TheTest::run (*this, random, Tag<int64_t>{});
}
void runTest()
{
runTestForAllTypes<InitializationTest> ("InitializationTest");
runTestForAllTypes ("InitializationTest", InitializationTest{});
runTestForAllTypes<AccessTest> ("AccessTest");
runTestForAllTypes ("AccessTest", AccessTest{});
runTestForAllTypes<OperatorTests<Addition>> ("AdditionOperators");
runTestForAllTypes<OperatorTests<Subtraction>> ("SubtractionOperators");
runTestForAllTypes<OperatorTests<Multiplication>> ("MultiplicationOperators");
runTestForAllTypes ("AdditionOperators", OperatorTests<Addition>{});
runTestForAllTypes ("SubtractionOperators", OperatorTests<Subtraction>{});
runTestForAllTypes ("MultiplicationOperators", OperatorTests<Multiplication>{});
runTestForAllTypes<BitOperatorTests<BitAND>> ("BitANDOperators");
runTestForAllTypes<BitOperatorTests<BitOR>> ("BitOROperators");
runTestForAllTypes<BitOperatorTests<BitXOR>> ("BitXOROperators");
runTestForAllTypes ("BitANDOperators", BitOperatorTests<BitAND>{});
runTestForAllTypes ("BitOROperators", BitOperatorTests<BitOR>{});
runTestForAllTypes ("BitXOROperators", BitOperatorTests<BitXOR>{});
runTestNonComplex<CheckComparisonOps> ("CheckComparisons");
runTestNonComplex<CheckBoolEquals> ("CheckBoolEquals");
runTestNonComplex<CheckMinMax> ("CheckMinMax");
runTestNonComplex ("CheckComparisons", CheckComparisonOps{});
runTestNonComplex ("CheckBoolEquals", CheckBoolEquals{});
runTestNonComplex ("CheckMinMax", CheckMinMax{});
runTestForAllTypes<CheckMultiplyAdd> ("CheckMultiplyAdd");
runTestForAllTypes<CheckSum> ("CheckSum");
runTestForAllTypes ("CheckMultiplyAdd", CheckMultiplyAdd{});
runTestForAllTypes ("CheckSum", CheckSum{});
runTestSigned<CheckAbs> ("CheckAbs");
runTestSigned ("CheckAbs", CheckAbs{});
runTestFloatingPoint<CheckTruncate> ("CheckTruncate");
runTestFloatingPoint ("CheckTruncate", CheckTruncate{});
}
};