/* Test-ZRandomGenerator.cpp Author: James Russell Purpose: Unit Test the ZRandomGenerator class. Changelog: 2011/12/18 - Removed dependency on ZString (crertel) 2011/11/27 - creation (jcrussell) */ #include "ZUnitTest.hpp" #include #include //#include static const char* testMersenne(); static const char* testCMWC(); static const char* testSmallPRNG(); #define FPEQUALS(a,b) (a == b) #define ZRG_TEST_SEED_1 (1000) #define ZRG_TEST_SEED_2 (1024) #define ZRG_TEST_FLOAT_RANGE_MIN (-64000.0f) #define ZRG_TEST_FLOAT_RANGE_MAX (64000.0f) #define ZRG_TEST_INT_RANGE_MIN (-10000) #define ZRG_TEST_INT_RANGE_MAX (10000) //List of unit tests ZUnitTest ZRandomGeneratorUnitTests[] = { { "Test SST_Mersenne Generator", testMersenne }, { "Test SST_CMWC Generator", testCMWC }, { "Test SST_SmallPRNG Generator", testSmallPRNG } }; //Now declare the ZUnitTestBlock associated with this. DECLARE_ZTESTBLOCK(ZRandomGenerator); /*************************************************************************/ static const char* testGenerator(ZRandomGenerator *generator) { uint32_t seed; uint64_t sequence, correctSequence; seed = generator->GetSeed(); //First, we test grabbing floats float f1, f2, f3, f4; f1 = generator->GetFloat(); f2 = generator->GetFloat(); f3 = generator->GetFloat(); f4 = generator->GetFloat(); correctSequence = 4; sequence = generator->GetSequence(); TASSERT(sequence == correctSequence, "Generator has incorrect sequence number after GetFloat!"); TASSERT(f1 >= 0.0f && f1 < 1.0f, "f1 is out of range [0, 1.0)!"); TASSERT(f2 >= 0.0f && f2 < 1.0f, "f2 is out of range [0, 1.0)!"); TASSERT(f3 >= 0.0f && f3 < 1.0f, "f3 is out of range [0, 1.0)!"); TASSERT(f4 >= 0.0f && f4 < 1.0f, "f4 is out of range [0, 1.0)!"); //Swap seed, make sure we don't get the same four floats float f5, f6, f7, f8; generator->SetSeed(ZRG_TEST_SEED_2); seed = generator->GetSeed(); TASSERT(seed == ZRG_TEST_SEED_2, "After reseeding, generator returns incorrect seed!"); sequence = generator->GetSequence(); TASSERT(sequence == 0, "After reseeding, generator does not have sequence zero!"); f5 = generator->GetFloat(); f6 = generator->GetFloat(); f7 = generator->GetFloat(); f8 = generator->GetFloat(); sequence = generator->GetSequence(); TASSERT(sequence == correctSequence, "Generator has incorrect sequence number after SetSeed and four gets!"); bool equal; equal = FPEQUALS(f1, f5) && FPEQUALS(f2, f6) && FPEQUALS(f3, f7) && FPEQUALS(f4, f8); TASSERT(!equal, "After reseeding, generator generates same four numbers!"); //Now we test grabbing an array of floats float f1a[10], f2a[1000], f3a[100000]; generator->GetFloatArray(f1a, sizeof(f1a) / sizeof(float)); generator->GetFloatArray(f2a, sizeof(f2a) / sizeof(float)); generator->GetFloatArray(f3a, sizeof(f3a) / sizeof(float)); correctSequence = correctSequence + (sizeof(f1a) / sizeof(float)) + (sizeof(f2a) / sizeof(float)) + (sizeof(f3a) / sizeof(float)); sequence = generator->GetSequence(); TASSERT(sequence == correctSequence, "Generator has incorrect sequence number after GetFloatArray!"); for (size_t i = 0; i < sizeof(f1a) / sizeof(float); i++) { TASSERT(f1a[i] >= 0.0f && f1a[i] < 1.0f, "f1a has members out of range!"); } for (size_t i = 0; i < sizeof(f2a) / sizeof(float); i++) { TASSERT(f2a[i] >= 0.0f && f2a[i] < 1.0f, "f2a has members out of range!"); } for (size_t i = 0; i < sizeof(f3a) / sizeof(float); i++) { TASSERT(f3a[i] >= 0.0f && f3a[i] < 1.0f, "f3a has members out of range!"); } //Now we test grabbing floats in a range f1 = generator->GetFloatInRange(ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX); f2 = generator->GetFloatInRange(ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX); f3 = generator->GetFloatInRange(ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX); f4 = generator->GetFloatInRange(ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX); correctSequence += 4; sequence = generator->GetSequence(); TASSERT(sequence == correctSequence, "Generator has incorrect sequence number after GetFloatInRange!"); TASSERT(f1 >= ZRG_TEST_FLOAT_RANGE_MIN && f1 < ZRG_TEST_FLOAT_RANGE_MAX, "f1 is out of range [ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX)!"); TASSERT(f2 >= ZRG_TEST_FLOAT_RANGE_MIN && f2 < ZRG_TEST_FLOAT_RANGE_MAX, "f2 is out of range [ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX)!"); TASSERT(f3 >= ZRG_TEST_FLOAT_RANGE_MIN && f3 < ZRG_TEST_FLOAT_RANGE_MAX, "f3 is out of range [ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX)!"); TASSERT(f4 >= ZRG_TEST_FLOAT_RANGE_MIN && f4 < ZRG_TEST_FLOAT_RANGE_MAX, "f4 is out of range [ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX)!"); //Now we test grabbing arrays of floats in a range generator->GetFloatArrayInRange(f1a, sizeof(f1a) / sizeof(float), ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX); generator->GetFloatArrayInRange(f2a, sizeof(f2a) / sizeof(float), ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX); generator->GetFloatArrayInRange(f3a, sizeof(f3a) / sizeof(float), ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX); correctSequence = correctSequence + (sizeof(f1a) / sizeof(float)) + (sizeof(f2a) / sizeof(float)) + (sizeof(f3a) / sizeof(float)); sequence = generator->GetSequence(); TASSERT(sequence == correctSequence, "Generator has incorrect sequence number after GetFloatArrayInRange!"); for (size_t i = 0; i < sizeof(f1a) / sizeof(float); i++) { TASSERT(f1a[i] >= ZRG_TEST_FLOAT_RANGE_MIN && f1a[i] < ZRG_TEST_FLOAT_RANGE_MAX, "f1a has members out of range!"); } for (size_t i = 0; i < sizeof(f2a) / sizeof(float); i++) { TASSERT(f2a[i] >= ZRG_TEST_FLOAT_RANGE_MIN && f2a[i] < ZRG_TEST_FLOAT_RANGE_MAX, "f2a has members out of range!"); } for (size_t i = 0; i < sizeof(f3a) / sizeof(float); i++) { TASSERT(f3a[i] >= ZRG_TEST_FLOAT_RANGE_MIN && f3a[i] < ZRG_TEST_FLOAT_RANGE_MAX, "f3a has members out of range!"); } //Now we grab an int in a range int i1, i2, i3, i4; i1 = generator->GetIntInRange(ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX); i2 = generator->GetIntInRange(ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX); i3 = generator->GetIntInRange(ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX); i4 = generator->GetIntInRange(ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX); correctSequence += 4; sequence = generator->GetSequence(); TASSERT(sequence == correctSequence, "Generator has incorrect sequence number after GetIntInRange!"); TASSERT(i1 >= ZRG_TEST_INT_RANGE_MIN && i1 < ZRG_TEST_INT_RANGE_MAX, "i1 is out of range [ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX)!"); TASSERT(i2 >= ZRG_TEST_INT_RANGE_MIN && i2 < ZRG_TEST_INT_RANGE_MAX, "i2 is out of range [ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX)!"); TASSERT(i3 >= ZRG_TEST_INT_RANGE_MIN && i3 < ZRG_TEST_INT_RANGE_MAX, "i3 is out of range [ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX)!"); TASSERT(i4 >= ZRG_TEST_INT_RANGE_MIN && i4 < ZRG_TEST_INT_RANGE_MAX, "i4 is out of range [ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX)!"); //Now we grab an int array in range int i1a[10], i2a[1000], i3a[100000]; generator->GetIntArrayInRange(i1a, sizeof(i1a) / sizeof(int), ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX); generator->GetIntArrayInRange(i2a, sizeof(i2a) / sizeof(int), ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX); generator->GetIntArrayInRange(i3a, sizeof(i3a) / sizeof(int), ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX); correctSequence = correctSequence + (sizeof(i1a) / sizeof(int)) + (sizeof(i2a) / sizeof(int)) + (sizeof(i3a) / sizeof(int)); sequence = generator->GetSequence(); TASSERT(sequence == correctSequence, "Generator has incorrect sequence number after GetIntArrayInRange!"); for (size_t i = 0; i < sizeof(i1a) / sizeof(int); i++) { TASSERT(i1a[i] >= ZRG_TEST_INT_RANGE_MIN && i1a[i] < ZRG_TEST_INT_RANGE_MAX, "i1a has members out of range!"); } for (size_t i = 0; i < sizeof(i2a) / sizeof(int); i++) { TASSERT(i2a[i] >= ZRG_TEST_INT_RANGE_MIN && i2a[i] < ZRG_TEST_INT_RANGE_MAX, "i2a has members out of range!"); } for (size_t i = 0; i < sizeof(i3a) / sizeof(int); i++) { TASSERT(i3a[i] >= ZRG_TEST_INT_RANGE_MIN && i3a[i] < ZRG_TEST_INT_RANGE_MAX, "i3a has member out of range!"); } //Now we grab some gaussian distributed floats f1 = generator->GetGaussianFloat(ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX); f2 = generator->GetGaussianFloat(ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX); f3 = generator->GetGaussianFloat(ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX); f4 = generator->GetGaussianFloat(ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX); correctSequence += 8; //Two per call sequence = generator->GetSequence(); TASSERT(sequence == correctSequence, "Generator has incorrect sequence number after GetGaussianFloat!"); TASSERT(f1 >= ZRG_TEST_FLOAT_RANGE_MIN && f1 < ZRG_TEST_FLOAT_RANGE_MAX, "f1 is out of range [ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX) for gaussian test!"); TASSERT(f2 >= ZRG_TEST_FLOAT_RANGE_MIN && f2 < ZRG_TEST_FLOAT_RANGE_MAX, "f2 is out of range [ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX) for gaussian test!"); TASSERT(f3 >= ZRG_TEST_FLOAT_RANGE_MIN && f3 < ZRG_TEST_FLOAT_RANGE_MAX, "f3 is out of range [ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX) for gaussian test!"); TASSERT(f4 >= ZRG_TEST_FLOAT_RANGE_MIN && f4 < ZRG_TEST_FLOAT_RANGE_MAX, "f4 is out of range [ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX) for gaussian test!"); //Now we grab some gaussian distributed floats in an array generator->GetGaussianFloatArray(f1a, sizeof(f1a) / sizeof(float), ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX); generator->GetGaussianFloatArray(f2a, sizeof(f2a) / sizeof(float), ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX); generator->GetGaussianFloatArray(f3a, sizeof(f3a) / sizeof(float), ZRG_TEST_FLOAT_RANGE_MIN, ZRG_TEST_FLOAT_RANGE_MAX); correctSequence = correctSequence + 2*(sizeof(f1a) / sizeof(float)) + 2*(sizeof(f2a) / sizeof(float)) + 2*(sizeof(f3a) / sizeof(float)); //Two per call sequence = generator->GetSequence(); TASSERT(sequence == correctSequence, "Generator has incorrect sequence number after GetGaussianFloatArray!"); for (size_t i = 0; i < sizeof(f1a) / sizeof(float); i++) { TASSERT(f1a[i] >= ZRG_TEST_FLOAT_RANGE_MIN && f1a[i] < ZRG_TEST_FLOAT_RANGE_MAX, "f1a has members out of range for gaussian test!"); } for (size_t i = 0; i < sizeof(f2a) / sizeof(float); i++) { TASSERT(f2a[i] >= ZRG_TEST_FLOAT_RANGE_MIN && f2a[i] < ZRG_TEST_FLOAT_RANGE_MAX, "f2a has members out of range for gaussian test!"); } for (size_t i = 0; i < sizeof(f3a) / sizeof(float); i++) { TASSERT(f3a[i] >= ZRG_TEST_FLOAT_RANGE_MIN && f3a[i] < ZRG_TEST_FLOAT_RANGE_MAX, "f3a has member out of range for gaussian test!\n"); } //Now we grab some gaussian distributed ints i1 = generator->GetGaussianInt(ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX); i2 = generator->GetGaussianInt(ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX); i3 = generator->GetGaussianInt(ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX); i4 = generator->GetGaussianInt(ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX); correctSequence += 8; //Two per call sequence = generator->GetSequence(); TASSERT(sequence == correctSequence, "Generator has incorrect sequence number after GetGaussianInt!"); TASSERT(i1 >= ZRG_TEST_INT_RANGE_MIN && i1 < ZRG_TEST_INT_RANGE_MAX, "i1 is out of range [ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX) for gaussian test!"); TASSERT(i2 >= ZRG_TEST_INT_RANGE_MIN && i2 < ZRG_TEST_INT_RANGE_MAX, "i2 is out of range [ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX) for gaussian test!"); TASSERT(i3 >= ZRG_TEST_INT_RANGE_MIN && i3 < ZRG_TEST_INT_RANGE_MAX, "i3 is out of range [ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX) for gaussian test!"); TASSERT(i4 >= ZRG_TEST_INT_RANGE_MIN && i4 < ZRG_TEST_INT_RANGE_MAX, "i4 is out of range [ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX) for gaussian test!"); //Now we grab some gaussian distributed ints in an array generator->GetGaussianIntArray(i1a, sizeof(i1a) / sizeof(int), ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX); generator->GetGaussianIntArray(i2a, sizeof(i2a) / sizeof(int), ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX); generator->GetGaussianIntArray(i3a, sizeof(i3a) / sizeof(int), ZRG_TEST_INT_RANGE_MIN, ZRG_TEST_INT_RANGE_MAX); correctSequence = correctSequence + 2*(sizeof(i1a) / sizeof(int)) + 2*(sizeof(i2a) / sizeof(int)) + 2*(sizeof(i3a) / sizeof(int)); sequence = generator->GetSequence(); TASSERT(sequence == correctSequence, "Generator has incorrect sequence number after GetGaussianIntArray!"); for (size_t i = 0; i < sizeof(i1a) / sizeof(int); i++) { TASSERT(i1a[i] >= ZRG_TEST_INT_RANGE_MIN && i1a[i] < ZRG_TEST_INT_RANGE_MAX, "i1a has members out of range for guassian test!"); } for (size_t i = 0; i < sizeof(i2a) / sizeof(int); i++) { TASSERT(i2a[i] >= ZRG_TEST_INT_RANGE_MIN && i2a[i] < ZRG_TEST_INT_RANGE_MAX, "i2a has members out of range for guassian test!"); } for (size_t i = 0; i < sizeof(i3a) / sizeof(int); i++) { TASSERT(i3a[i] >= ZRG_TEST_INT_RANGE_MIN && i3a[i] < ZRG_TEST_INT_RANGE_MAX, "i3a has member %i (%i) out of range for gaussian test!\n"); } return ZTEST_SUCCESS; } static const char* testMersenne() { ZRandomGenerator *generator; generator = znew ZRandomGenerator(SST_PRNG_MERSENNE, ZRG_TEST_SEED_1); TASSERT(generator->GetSeed() == ZRG_TEST_SEED_1, "Mersenne Generator has incorrect seed !"); const char* result = testGenerator(generator); zdelete generator; return result; } static const char* testCMWC() { ZRandomGenerator *generator; generator = znew ZRandomGenerator(SST_PRNG_CMWC, ZRG_TEST_SEED_1); TASSERT(generator->GetSeed() == ZRG_TEST_SEED_1, "CMWC Generator has incorrect seed!"); const char* result = testGenerator(generator); zdelete generator; return result; } static const char* testSmallPRNG() { ZRandomGenerator *generator; generator = znew ZRandomGenerator(SST_PRNG_SMALLPRNG, ZRG_TEST_SEED_1); TASSERT(generator->GetSeed() == ZRG_TEST_SEED_1, "Small PRNG Generator has incorrect seed!"); const char* result = testGenerator(generator); zdelete generator; return result; }