move MT19937 random generator to ddsrt

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Erik Boasson 2019-04-03 17:03:17 +02:00 committed by eboasson
parent dd9aceb713
commit 6e87841ea5
13 changed files with 345 additions and 264 deletions

View file

@ -22,6 +22,7 @@ set(sources
"thread_cleanup.c"
"string.c"
"log.c"
"random.c"
"strlcpy.c"
"socket.c"
"select.c")

92
src/ddsrt/tests/random.c Normal file
View file

@ -0,0 +1,92 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "CUnit/Test.h"
#include "dds/ddsrt/random.h"
#define N_PRNG 4
#define N_DATA 10
CU_Test(ddsrt_random, mt19937)
{
static const uint32_t refdata[N_DATA] = {
3499211612u, 581869302u, 3890346734u, 3586334585u, 545404204u,
4161255391u, 3922919429u, 949333985u, 2715962298u, 1323567403u
};
ddsrt_prng_t prng;
ddsrt_prng_init_simple (&prng, 5489U);
for (size_t i = 0; i < N_DATA; i++)
{
uint32_t x = ddsrt_prng_random (&prng);
CU_ASSERT_EQUAL_FATAL(x, refdata[i]);
}
}
CU_Test(ddsrt_random, makeseed)
{
ddsrt_prng_seed_t seeds[N_PRNG];
/* Until proven otherwise, assume all platforms have a good way of getting multiple seeds */
memset (seeds, 0, sizeof (seeds));
for (size_t i = 0; i < N_PRNG; i++)
{
bool ok = ddsrt_prng_makeseed (&seeds[i]);
CU_ASSERT_FATAL(ok);
}
/* Any pair the same is possible, but the likelihood should be so small that it is worth accepting
an intermittently failing test */
for (size_t i = 0; i < N_PRNG; i++)
{
for (size_t j = i + 1; j < N_PRNG; j++)
CU_ASSERT_FATAL (memcmp (&seeds[i], &seeds[j], sizeof (seeds[i])) != 0);
}
/* A short random sequence generated from each of the different seeds should be unique -- again,
there is no guarantee but only an overwhelming likelihood */
ddsrt_prng_t prngs[N_PRNG];
uint32_t data[N_PRNG][N_DATA];
memset (data, 0, sizeof (data));
for (size_t i = 0; i < N_PRNG; i++)
{
ddsrt_prng_init (&prngs[i], &seeds[i]);
for (size_t j = 0; j < N_DATA; j++)
data[i][j] = ddsrt_prng_random (&prngs[i]);
}
for (size_t i = 0; i < N_PRNG; i++)
{
for (size_t j = i + 1; j < N_PRNG; j++)
CU_ASSERT_FATAL (memcmp (&data[i], &data[j], sizeof (data[i])) != 0);
}
}
CU_Test(ddsrt_random, default_random)
{
#define N_BINS 128
#define N_PER_BIN 100
uint32_t bins[N_BINS];
memset (bins, 0, sizeof (bins));
for (size_t i = 0; i < N_PER_BIN * N_BINS; i++)
{
uint32_t x = ddsrt_random ();
bins[x % N_BINS]++;
}
double chisq = 0.0;
for (size_t i = 0; i < N_BINS; i++)
chisq += ((bins[i] - N_PER_BIN) * (bins[i] - N_PER_BIN)) / (double) N_PER_BIN;
/* Solve[CDF[ChiSquareDistribution[127], x] == 999/1000] */
CU_ASSERT (chisq < 181.993);
}