summaryrefslogtreecommitdiff
path: root/xdelta3/testing/random.h
diff options
context:
space:
mode:
authorjosh.macdonald <jmacd@users.noreply.github.com>2008-06-30 05:15:05 +0000
committerjosh.macdonald <jmacd@users.noreply.github.com>2008-06-30 05:15:05 +0000
commit9e896b470f5a4550a7fbbdc515db08b0249f5950 (patch)
tree8f2ea4d701f554a578a7d7e441f98e1f77425e9a /xdelta3/testing/random.h
parente127914b71638072798f7c02e93caf9377ba7385 (diff)
A test is taking shape...
Diffstat (limited to 'xdelta3/testing/random.h')
-rw-r--r--xdelta3/testing/random.h125
1 files changed, 125 insertions, 0 deletions
diff --git a/xdelta3/testing/random.h b/xdelta3/testing/random.h
new file mode 100644
index 0000000..6648edb
--- /dev/null
+++ b/xdelta3/testing/random.h
@@ -0,0 +1,125 @@
1/* -*- Mode: C++ -*- */
2/* This is public-domain Mersenne Twister code,
3 * attributed to Michael Brundage. Thanks!
4 * http://www.qbrundage.com/michaelb/pubs/essays/random_number_generation.html
5 */
6#include <math.h>
7
8namespace regtest {
9
10class MTRandom {
11 public:
12 static const uint32_t TEST_SEED1 = 0x1975;
13
14 static const int MT_LEN = 624;
15 static const int MT_IA = 397;
16 static const int MT_IB = (MT_LEN - MT_IA);
17 static const uint32_t UPPER_MASK = 0x80000000;
18 static const uint32_t LOWER_MASK = 0x7FFFFFFF;
19 static const uint32_t MATRIX_A = 0x9908B0DF;
20
21 MTRandom() {
22 Init(TEST_SEED1);
23 }
24
25 MTRandom(uint32_t seed) {
26 Init(seed);
27 }
28
29 uint32_t TWIST(int i, int j) {
30 return (mt_buffer_[i] & UPPER_MASK) | (mt_buffer_[j] & LOWER_MASK);
31 }
32
33 uint32_t MAGIC(uint32_t s) {
34 return (s & 1) * MATRIX_A;
35 }
36
37 uint32_t Rand32 () {
38 int idx = mt_index_;
39 uint32_t s;
40 int i;
41
42 if (idx == MT_LEN * sizeof(uint32_t)) {
43 idx = 0;
44 i = 0;
45 for (; i < MT_IB; i++) {
46 s = TWIST(i, i+1);
47 mt_buffer_[i] = mt_buffer_[i + MT_IA] ^ (s >> 1) ^ MAGIC(s);
48 }
49 for (; i < MT_LEN-1; i++) {
50 s = TWIST(i, i+1);
51 mt_buffer_[i] = mt_buffer_[i - MT_IB] ^ (s >> 1) ^ MAGIC(s);
52 }
53
54 s = TWIST(MT_LEN-1, 0);
55 mt_buffer_[MT_LEN-1] = mt_buffer_[MT_IA-1] ^ (s >> 1) ^ MAGIC(s);
56 }
57 mt_index_ = idx + sizeof(uint32_t);
58
59 // Original code had an unaligned access, make it portable.
60 // return *(uint32_t *)((unsigned char *)b + idx);
61 uint32_t r;
62 memcpy(&r, ((unsigned char *)mt_buffer_ + idx), sizeof(uint32_t));
63 return r;
64 }
65
66 uint32_t ExpRand32(uint32_t mean) {
67 double mean_d = mean;
68 double erand = log (1.0 / (Rand32() / (double)UINT32_MAX));
69 uint32_t x = (uint32_t) (mean_d * erand + 0.5);
70 return x;
71 }
72
73 uint64_t Rand64() {
74 return ((uint64_t)Rand32() << 32) | Rand32();
75 }
76
77 uint64_t ExpRand64(uint64_t mean) {
78 double mean_d = mean;
79 double erand = log (1.0 / (Rand64() / (double)UINT32_MAX));
80 uint64_t x = (uint64_t) (mean_d * erand + 0.5);
81 return x;
82 }
83
84 template <typename T>
85 T Rand() {
86 switch (sizeof(T)) {
87 case sizeof(uint32_t):
88 return Rand32();
89 case sizeof(uint64_t):
90 return Rand64();
91 default:
92 cerr << "Invalid sizeof T" << endl;
93 abort();
94 }
95 }
96
97 template <typename T>
98 T ExpRand(T mean) {
99 switch (sizeof(T)) {
100 case sizeof(uint32_t):
101 return ExpRand32(mean);
102 case sizeof(uint64_t):
103 return ExpRand64(mean);
104 default:
105 cerr << "Invalid sizeof T" << endl;
106 abort();
107 }
108 }
109
110 private:
111 void Init(uint32_t seed) {
112 int i;
113 srand (seed);
114 for (i = 0; i < MT_LEN; i++)
115 {
116 mt_buffer_[i] = rand ();
117 }
118 mt_index_ = 0;
119 }
120
121 int mt_index_;
122 uint32_t mt_buffer_[MT_LEN];
123};
124
125} // namespace regtest