facility to inject a non-random random generator

This should be handy for writing tests that make use of randomization.
This commit is contained in:
Steffen Mecke 2015-12-08 17:48:53 +01:00
parent 1a9e3db423
commit 703edb676c
4 changed files with 78 additions and 2 deletions

View file

@ -23,6 +23,7 @@
#include <util/language.h>
#include <util/message.h>
#include <util/log.h>
#include <util/rand.h>
#include <CuTest.h>
@ -103,6 +104,8 @@ void test_cleanup(void)
errno = 0;
log_error("errno: %d", error);
}
random_source_reset();
}
terrain_type *

View file

@ -21,6 +21,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "rng.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <float.h>
@ -65,3 +66,66 @@ bool chance(double x)
return true;
return rng_double() < x;
}
extern double genrand_real2(void);
typedef struct random_source {
double (*double_source) (void);
} random_source;
random_source *r_source = 0;
double rng_injectable_double(void) {
if (r_source)
return r_source->double_source();
return genrand_real2();
}
static double constant_value;
static double constant_source (void) {
return constant_value;
}
struct random_source constant_provider = {
constant_source
};
void random_source_inject_constant(double value) {
constant_value = value;
r_source = &constant_provider;
}
static int i = 0;
static double *values;
static int value_size = 0;
static double array_source (void) {
assert(i<value_size);
return values[i++];
}
struct random_source array_provider = {
array_source
};
void random_source_inject_array(double inject[], int size) {
assert(size > 0);
value_size = size;
if (values)
free(values);
values = malloc(sizeof(double) * size);
for (i=0; i < size; ++i) {
values[i] = inject[i];
}
i = 0;
r_source = &array_provider;
}
void random_source_reset(void) {
if (values)
free(values);
values = NULL;
r_source = NULL;
}

View file

@ -31,6 +31,15 @@ extern "C" {
extern int ntimespprob(int n, double p, double mod);
extern bool chance(double x);
/* a random source that generates numbers in [0, 1).
By calling the random_source_inject... functions you can set a special random source,
which is handy for testing */
double rng_injectable_double(void);
void random_source_inject_constant(double value);
void random_source_inject_array(double inject[], int size);
void random_source_reset(void);
#ifdef __cplusplus
}
#endif

View file

@ -23,7 +23,7 @@ extern "C" {
extern unsigned long genrand_int32(void);
/* generates a random number on [0,1)-real-interval */
extern double genrand_real2(void);
extern double rng_injectable_double(void);
/* generates a random number on [0,0x7fffffff]-interval */
long genrand_int31(void);
@ -31,7 +31,7 @@ extern "C" {
# define rng_init(seed) init_genrand(seed)
# define rng_int (int)genrand_int31
# define rng_uint (unsigned int)genrand_int32
# define rng_double genrand_real2
# define rng_double rng_injectable_double
# define RNG_RAND_MAX 0x7fffffff
#else
# include <stdlib.h>