summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorGeorge Lebl <jirka@5z.com>2004-01-10 01:38:55 +0000
committerTim Janik <timj@src.gnome.org>2004-01-10 01:38:55 +0000
commit80591652ff873e7f09c1ad8f8a505a03fc1dbc62 (patch)
treef068dce0a09f07aa5273eba8993db078e89a32bb /tests
parent43da83fdae67ad6dba35ef4607c3626505f62281 (diff)
Add the init_by_array functionality from the reference implementation of
Fri Dec 19 11:49:21 2003 George Lebl <jirka@5z.com> * glib/grand.c glib/grand.h (g_rand_new) (g_rand_new_with_seed) (g_rand_new_with_seed_array) (g_rand_set_seed_array): Add the init_by_array functionality from the reference implementation of the mersenne twister (mt19937ar.c) and change the naming to fit with the rest of the grand API. New functions are g_rand_new_with_seed_array, g_rand_set_seed_array. This is only reliable/tested for the 2.2 version of the seeding as that's what the reference implementation uses. Also modify g_rand_new to get 4 longs from /dev/urandom since that will always be available anyway and we get more entropy and if /dev/urandom is unavailable use also 4 longs for seeding using secs, usecs, getpid and getppid. For version 2.0 use only a simple seed again but be more careful about seeding with secs/usecs in this case. * glib/grand.c glib/grand.h (g_rand_copy): Add g_rand_copy function to copy the current state of the random number generator. * glib/grand.c (g_rand_new): Add testing for EINTR when reading from /dev/urandom * tests/rand-test.c: add testing of the array seeding stuff against the reference implementation, plus add statistical sanity check to see that the values outputted are truly kind of random. And check that g_rand_copy truly copies the state by checking a few terms.
Diffstat (limited to 'tests')
-rw-r--r--tests/rand-test.c60
1 files changed, 59 insertions, 1 deletions
diff --git a/tests/rand-test.c b/tests/rand-test.c
index c8efa21c5..141883eb8 100644
--- a/tests/rand-test.c
+++ b/tests/rand-test.c
@@ -3,7 +3,11 @@
#include <glib.h>
-const gint32 first_numbers[] =
+/* Outputs tested against the reference implementation mt19937ar.c from
+ http://www.math.keio.ac.jp/~matumoto/MT2002/emt19937ar.html */
+
+/* Tests for a simple seed, first number is the seed */
+const guint32 first_numbers[] =
{
0x7a7a7a7a,
0xfdcc2d54,
@@ -28,17 +32,56 @@ const gint32 first_numbers[] =
0x1696330c,
};
+/* array seed */
+const guint32 seed_array[] =
+{
+ 0x6553375f,
+ 0xd6b8d43b,
+ 0xa1e7667f,
+ 0x2b10117c
+};
+
+/* tests for the array seed */
+const guint32 array_outputs[] =
+{
+ 0xc22b7dc3,
+ 0xfdecb8ae,
+ 0xb4af0738,
+ 0x516bc6e1,
+ 0x7e372e91,
+ 0x2d38ff80,
+ 0x6096494a,
+ 0xd162d5a8,
+ 0x3c0aaa0d,
+ 0x10e736ae
+};
+
const gint length = sizeof (first_numbers) / sizeof (first_numbers[0]);
+const gint seed_length = sizeof (seed_array) / sizeof (seed_array[0]);
+const gint array_length = sizeof (array_outputs) / sizeof (array_outputs[0]);
int main()
{
guint n;
+ guint ones;
+ double proportion;
GRand* rand = g_rand_new_with_seed (first_numbers[0]);
+ GRand* copy;
for (n = 1; n < length; n++)
g_assert (first_numbers[n] == g_rand_int (rand));
+ g_rand_set_seed (rand, 2);
+ g_rand_set_seed_array (rand, seed_array, seed_length);
+
+ for (n = 0; n < array_length; n++)
+ g_assert (array_outputs[n] == g_rand_int (rand));
+
+ copy = g_rand_copy (rand);
+ for (n = 0; n < 100; n++)
+ g_assert (g_rand_int (copy) == g_rand_int (rand));
+
for (n = 1; n < 100000; n++)
{
gint32 i;
@@ -70,7 +113,22 @@ int main()
g_assert (b == TRUE || b == FALSE);
}
+ /* Statistical sanity check, count the number of ones
+ * when getting random numbers in range [0,3) and see
+ * that it must be semi-close to 0.25 with a VERY large
+ * probability */
+ ones = 0;
+ for (n = 1; n < 100000; n++)
+ {
+ if (g_random_int_range (0, 4) == 1)
+ ones ++;
+ }
+ proportion = (double)ones / (double)100000;
+ /* 0.025 is overkill, but should suffice to test for some unreasonability */
+ g_assert (ABS (proportion - 0.25) < 0.025);
+
g_rand_free (rand);
+ g_rand_free (copy);
return 0;
}