1 /////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) Electronic Arts Inc. All rights reserved.
3 /////////////////////////////////////////////////////////////////////////////
4
5
6 #if defined(_MSC_VER)
7 //#pragma warning(disable: 4267) // 'argument' : conversion from 'size_t' to 'uint32_t', possible loss of data.
8 #endif
9
10
11 #include "EASTLTest.h"
12 #include <EASTL/numeric_limits.h>
13 #include <EASTL/set.h>
14 #include <EASTL/random.h>
15
16
17 struct GeneratorUint8
18 {
19 uint8_t mValue;
GeneratorUint8GeneratorUint820 GeneratorUint8() : mValue(0) {}
operator ()GeneratorUint821 uint8_t operator()(){ return mValue++; } // This is a pretty bad random number generator, but works for our tests.
22 };
23
24 struct GeneratorUint16
25 {
26 uint16_t mValue;
GeneratorUint16GeneratorUint1627 GeneratorUint16() : mValue(0) {}
operator ()GeneratorUint1628 uint16_t operator()(){ return mValue++; }
29 };
30
31 struct GeneratorUint32
32 {
33 uint32_t mValue;
GeneratorUint32GeneratorUint3234 GeneratorUint32() : mValue(0) {}
operator ()GeneratorUint3235 uint32_t operator()(){ return mValue++; }
36 };
37
38
39
40
41 ///////////////////////////////////////////////////////////////////////////////
42 // TestRandom
43 //
TestRandom()44 int TestRandom()
45 {
46 int nErrorCount = 0;
47
48 {
49 // template<class IntType = int>
50 // class uniform_int_distribution
51
52 // The C++11 Standard defines a number of formal Generators, such as std::mersenne_twister_engine,
53 // linear_congruential_engine, discard_block_engine, etc.
54
55 using namespace eastl;
56
57 {
58 eastl::uniform_int_distribution<uint8_t> uid(1, 6);
59 GeneratorUint8 g;
60
61 for(uint32_t i = 0; i < UINT8_MAX; i += 1)
62 {
63 uint8_t value = uid(g);
64 EATEST_VERIFY((value >= 1) && (value <= 6));
65 // To do: Validate the randomness of the value.
66 }
67
68 eastl::uniform_int_distribution<uint8_t> uid2(1, 6);
69 EATEST_VERIFY(uid == uid2);
70 }
71
72 {
73 eastl::uniform_int_distribution<uint16_t> uid(1, 6);
74 GeneratorUint16 g;
75
76 for(uint32_t i = 0; i < (UINT16_MAX - (UINT16_MAX / 50)); i += (UINT16_MAX / 50))
77 {
78 uint16_t value = uid(g);
79 EATEST_VERIFY((value >= 1) && (value <= 6));
80 // To do: Validate the randomness of the value.
81 }
82
83 eastl::uniform_int_distribution<uint16_t> uid2(1, 6);
84 EATEST_VERIFY(uid == uid2);
85 }
86
87 {
88 eastl::uniform_int_distribution<uint32_t> uid(1, 6);
89 GeneratorUint32 g;
90
91 for(uint32_t i = 0; i < (UINT32_MAX - (UINT32_MAX / 500)); i += (UINT32_MAX / 500))
92 {
93 uint32_t value = uid(g);
94 EATEST_VERIFY((value >= 1) && (value <= 6));
95 // To do: Validate the randomness of the value.
96 }
97
98 eastl::uniform_int_distribution<uint32_t> uid2(1, 6);
99 EATEST_VERIFY(uid == uid2);
100 }
101 }
102
103
104
105 /// Example usage:
106 /// eastl_size_t Rand(eastl_size_t n) { return (eastl_size_t)(rand() % n); } // Note: The C rand function is poor and slow.
107 /// pointer_to_unary_function<eastl_size_t, eastl_size_t> randInstance(Rand);
108 /// random_shuffle(pArrayBegin, pArrayEnd, randInstance);
109 ///
110 /// Example usage:
111 /// struct Rand{ eastl_size_t operator()(eastl_size_t n) { return (eastl_size_t)(rand() % n); } }; // Note: The C rand function is poor and slow.
112 /// Rand randInstance;
113 /// random_shuffle(pArrayBegin, pArrayEnd, randInstance);
114
115
116 {
117 // void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator& rng)
118 using namespace eastl;
119
120 EASTLTest_Rand rng(EA::UnitTest::GetRandSeed());
121 int intArray[] = { 3, 2, 6, 5, 4, 1 };
122
123 random_shuffle(intArray, intArray + 0, rng);
124 EATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), "random_shuffle", 3, 2, 6, 5, 4, 1, -1));
125
126 random_shuffle(intArray, intArray + (sizeof(intArray) / sizeof(intArray[0])), rng);
127 bool changed = false;
128 for(int i = 0; (i < 5) && !changed; i++)
129 {
130 changed = (intArray[0] != 3) || (intArray[1] != 2) || (intArray[2] != 6) ||
131 (intArray[3] != 5) || (intArray[4] != 4) || (intArray[5] != 1);
132 }
133 EATEST_VERIFY(changed);
134
135 // Test of possible bug report by user John Chin.
136 // The report is that shuffling an ordered array 0, 1, 2, 3, 4 ... results in duplicates, such as 5, 2, 2, 4 ...
137 eastl::vector<eastl_size_t> rngArray;
138
139 for(eastl_size_t i = 0; i < 200; ++i)
140 rngArray.push_back(i);
141
142 random_shuffle(rngArray.begin(), rngArray.end(), rng);
143 EATEST_VERIFY(rngArray.validate());
144
145 eastl::set<eastl_size_t> intSet;
146
147 for(eastl_size_t s = 0, sEnd = rngArray.size(); s < sEnd; ++s)
148 intSet.insert(rngArray[s]);
149
150 // If the shuffled array is unique, then a set of its values should be the same size as the array.
151 EATEST_VERIFY(intSet.size() == rngArray.size());
152 }
153
154
155 return nErrorCount;
156 }
157
158
159
160
161
162
163
164
165
166
167
168
169