-
Notifications
You must be signed in to change notification settings - Fork 0
/
randq_utest.c
203 lines (167 loc) · 5.37 KB
/
randq_utest.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <string.h>
// CMOCKA INCLUDE
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
// RANDQD LIB
#include "src/randq.h"
#define MAX_ITER 42000
static void
hello_message()
{
fputs(" -------------------------------------------------\n", stdout);
fputs("| Pseudo-Random Number Generators UTEST |\n",stdout);
fputs(" -------------------------------------------------\n", stdout);
fputs("| Propriety of a RN with interval [0,1]: |\n",stdout);
fputs("| - mean: 1/2 |\n",stdout);
fputs("| - variance: 1/12 |\n",stdout);
fputs(" -------------------------------------------------\n", stdout);
}
/*
* To check whether your compiler and machine have the desired overflow
* properties, see if you can generate the following sequence of 32-bit
* values for the given starting state 0x0000000000
* SEE "Numerical Recipes in C" Second Edition at page 284 for more details
*/
static void
randq_uinteger_test(void **state)
{
(void) state;
static const uint32_t sequence[] = {
0x0000000000,0x3C6EF35FUL, 0x47502932UL, 0xD1CCF6E9UL, 0xAAF95334UL, 0x6252E503UL,
0x9F2EC686UL, 0x57FE6C2DUL, 0xA3D95FA8UL, 0x81FDBEE7UL, 0x94F0AF1AUL,0xCBF633B1UL,
};
srandqd(sequence[0]);
for (size_t i = 0; i < (sizeof(sequence) / sizeof(uint32_t)) - 1; ++i) {
assert_true(sequence[i+1] == randqd_uint32());
}
}
/*
* Check if the function double randqd_double() can generate
* double random double values within the range [0, 1)
*/
static void
randq_double_0_to_1(void **state)
{
(void) state;
uint32_t start_seed = 589765974UL;
uint32_t greater_then = 0, less_then = 0, other = 0;
srandqd(start_seed);
for (size_t i = 0; i < MAX_ITER; ++i) {
randqd_uint32();
double rand_num = randqd_double();
assert_true(rand_num >= 0 && rand_num < 1);
if (rand_num < 0.5){
++less_then;
} else if (rand_num > 0.5) {
++greater_then;
} else {
++other;
}
}
assert_true(greater_then && less_then);
fprintf(stdout,"[ --> greater than 0.5: %d (%f%%) - less than 0.5: %d (%f%%) - other: %d (%f%%)\n",
greater_then, (double) greater_then / MAX_ITER,
less_then, (double) less_then / MAX_ITER,
other, (double) other / MAX_ITER);
}
/*
* Check if the function double randq64_double() can generate
* double random double values within the range [0, 1)
*/
static void
randq64_double_0_to_1(void **state)
{
(void) state;
uint64_t start_seed = 589765974ULL;
uint32_t greater_then = 0, less_then = 0, other = 0;
srandq64(start_seed);
for (size_t i = 0; i < MAX_ITER; ++i) {
randq64_uint64();
double rand_num = randq64_double();
assert_true(rand_num >= 0 && rand_num < 1);
if (rand_num < 0.5){
++less_then;
} else if (rand_num > 0.5) {
++greater_then;
} else {
++other;
}
}
assert_true(greater_then && less_then);
printf("[ --> greater than 0.5: %d (%f%%) - less than 0.5: %d (%f%%) - other: %d (%f%%)\n",
greater_then, (double) greater_then / MAX_ITER,
less_then, (double) less_then / MAX_ITER,
other, (double) other / MAX_ITER);
}
/*
* Calculate mean and variance for both method
*/
void mean_and_variance(char* method){
double sum = 0;
double mean, variance;
uint32_t start_seed = 4345UL;
fprintf(stdout,"Calculate mean and variance for method: %s \n",method);
if( strcmp(method,"64bit"))
srandq64((uint64_t) start_seed);
else if (strcmp(method,"QS"))
srandqd(start_seed);
// Determinate Mean
for (size_t i = 0; i < 1000; ++i)
{
double rand_num = 0.0;
if( strcmp(method,"64bit")){
randq64_uint64();
rand_num = randq64_double();
}
else if (strcmp(method,"QS"))
{
randqd_uint32();
rand_num = randqd_double();
}
sum = sum + rand_num;
}
mean = sum / 1000;
fprintf(stdout," - sum: %f\n",sum);
// Determinate Variance
if( strcmp(method,"64bit"))
srandq64((uint64_t) start_seed);
else if (strcmp(method,"QS"))
srandqd(start_seed);
sum = 0;
for (size_t i = 0; i < 1000; ++i)
{
double rand_num = 0.0;
if( strcmp(method,"64bit")){
randq64_uint64();
rand_num = randq64_double();
}
else if (strcmp(method,"QS"))
{
randqd_uint32();
rand_num = randqd_double();
}
sum = sum + ((rand_num - mean)*(rand_num - mean));
}
variance = sum/1000;
printf(" - Mean:%f \n - Variance:%f \n",mean,variance);
}
int
main(void)
{
hello_message();
fputs("\nMean and variance for both method between in [0,1]\n",stdout);
mean_and_variance("64bit");
mean_and_variance("QS");
fputs("\nStarting Cmocka test:\n",stdout);
const struct CMUnitTest randqd_group[] = {
cmocka_unit_test(randq_uinteger_test),
cmocka_unit_test(randq_double_0_to_1),
cmocka_unit_test(randq64_double_0_to_1)
};
return cmocka_run_group_tests(randqd_group, NULL, NULL);
}